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" 288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "exec-all.h" 298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "disas.h" 308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "tcg-op.h" 318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#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; 695389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine#ifdef CONFIG_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 765285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic uint32_t gen_opc_condexec_bits[OPC_BUF_SIZE]; 775285864985be9077e58e42235af6582dee72e841David 'Digit' Turner 788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if defined(CONFIG_USER_ONLY) 798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define IS_USER(s) 1 808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else 818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define IS_USER(s) (s->user) 828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif 838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* These instructions trap after executing, so defer them until after the 858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project conditional executions state has been updated. */ 868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define DISAS_WFI 4 878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define DISAS_SWI 5 885285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define DISAS_SMC 6 898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic TCGv_ptr cpu_env; 918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* We reuse the same 64-bit temporaries for efficiency. */ 925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic TCGv_i64 cpu_V0, cpu_V1, cpu_M0; 935285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic TCGv_i32 cpu_R[16]; 945285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic TCGv_i32 cpu_exclusive_addr; 955285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic TCGv_i32 cpu_exclusive_val; 965285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic TCGv_i32 cpu_exclusive_high; 975285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#ifdef CONFIG_USER_ONLY 985285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic TCGv_i32 cpu_exclusive_test; 995285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic TCGv_i32 cpu_exclusive_info; 1005285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#endif 1018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* FIXME: These should be removed. */ 1035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic TCGv cpu_F0s, cpu_F1s; 1045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic TCGv_i64 cpu_F0d, cpu_F1d; 1058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "gen-icount.h" 1078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1085285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic const char *regnames[] = 1095285864985be9077e58e42235af6582dee72e841David 'Digit' Turner { "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", 1105285864985be9077e58e42235af6582dee72e841David 'Digit' Turner "r8", "r9", "r10", "r11", "r12", "r13", "r14", "pc" }; 1115285864985be9077e58e42235af6582dee72e841David 'Digit' Turner 1128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* initialize TCG globals. */ 1138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid arm_translate_init(void) 1148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 1155285864985be9077e58e42235af6582dee72e841David 'Digit' Turner int i; 1165285864985be9077e58e42235af6582dee72e841David 'Digit' Turner 1175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env"); 1185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 1195285864985be9077e58e42235af6582dee72e841David 'Digit' Turner for (i = 0; i < 16; i++) { 1205285864985be9077e58e42235af6582dee72e841David 'Digit' Turner cpu_R[i] = tcg_global_mem_new_i32(TCG_AREG0, 1215285864985be9077e58e42235af6582dee72e841David 'Digit' Turner offsetof(CPUState, regs[i]), 1225285864985be9077e58e42235af6582dee72e841David 'Digit' Turner regnames[i]); 1235285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 1245285864985be9077e58e42235af6582dee72e841David 'Digit' Turner cpu_exclusive_addr = tcg_global_mem_new_i32(TCG_AREG0, 1255285864985be9077e58e42235af6582dee72e841David 'Digit' Turner offsetof(CPUState, exclusive_addr), "exclusive_addr"); 1265285864985be9077e58e42235af6582dee72e841David 'Digit' Turner cpu_exclusive_val = tcg_global_mem_new_i32(TCG_AREG0, 1275285864985be9077e58e42235af6582dee72e841David 'Digit' Turner offsetof(CPUState, exclusive_val), "exclusive_val"); 1285285864985be9077e58e42235af6582dee72e841David 'Digit' Turner cpu_exclusive_high = tcg_global_mem_new_i32(TCG_AREG0, 1295285864985be9077e58e42235af6582dee72e841David 'Digit' Turner offsetof(CPUState, exclusive_high), "exclusive_high"); 1305285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#ifdef CONFIG_USER_ONLY 1315285864985be9077e58e42235af6582dee72e841David 'Digit' Turner cpu_exclusive_test = tcg_global_mem_new_i32(TCG_AREG0, 1325285864985be9077e58e42235af6582dee72e841David 'Digit' Turner offsetof(CPUState, exclusive_test), "exclusive_test"); 1335285864985be9077e58e42235af6582dee72e841David 'Digit' Turner cpu_exclusive_info = tcg_global_mem_new_i32(TCG_AREG0, 1345285864985be9077e58e42235af6582dee72e841David 'Digit' Turner offsetof(CPUState, exclusive_info), "exclusive_info"); 1355285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#endif 1368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#define GEN_HELPER 2 1385285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#include "helper.h" 1398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 1408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline TCGv load_cpu_offset(int offset) 1428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 1435285864985be9077e58e42235af6582dee72e841David 'Digit' Turner TCGv tmp = tcg_temp_new_i32(); 1448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_ld_i32(tmp, cpu_env, offset); 1458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return tmp; 1468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 1478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define load_cpu_field(name) load_cpu_offset(offsetof(CPUState, name)) 1498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline void store_cpu_offset(TCGv var, int offset) 1518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 1528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_st_i32(var, cpu_env, offset); 1535285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(var); 1548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 1558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define store_cpu_field(var, name) \ 1578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project store_cpu_offset(var, offsetof(CPUState, name)) 1588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Set a variable to the value of a CPU register. */ 1608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void load_reg_var(DisasContext *s, TCGv var, int reg) 1618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 1628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (reg == 15) { 1638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project uint32_t addr; 1648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* normaly, since we updated PC, we need only to add one insn */ 1658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (s->thumb) 1668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project addr = (long)s->pc + 2; 1678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 1688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project addr = (long)s->pc + 4; 1698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_movi_i32(var, addr); 1708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 1715285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_mov_i32(var, cpu_R[reg]); 1728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 1738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 1748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Create a new temporary and set it to the value of a CPU register. */ 1768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline TCGv load_reg(DisasContext *s, int reg) 1778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 1785285864985be9077e58e42235af6582dee72e841David 'Digit' Turner TCGv tmp = tcg_temp_new_i32(); 1798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project load_reg_var(s, tmp, reg); 1808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return tmp; 1818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 1828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Set a CPU register. The source must be a temporary and will be 1848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project marked as dead. */ 1858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void store_reg(DisasContext *s, int reg, TCGv var) 1868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 1878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (reg == 15) { 1888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_andi_i32(var, var, ~1); 1898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project s->is_jmp = DISAS_JUMP; 1908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 1915285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_mov_i32(cpu_R[reg], var); 1925285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(var); 1938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 1948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Value extensions. */ 1968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define gen_uxtb(var) tcg_gen_ext8u_i32(var, var) 1978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define gen_uxth(var) tcg_gen_ext16u_i32(var, var) 1988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define gen_sxtb(var) tcg_gen_ext8s_i32(var, var) 1998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define gen_sxth(var) tcg_gen_ext16s_i32(var, var) 2008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 2018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define gen_sxtb16(var) gen_helper_sxtb16(var, var) 2028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define gen_uxtb16(var) gen_helper_uxtb16(var, var) 2038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 2048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 2055285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic inline void gen_set_cpsr(TCGv var, uint32_t mask) 2065285864985be9077e58e42235af6582dee72e841David 'Digit' Turner{ 2075285864985be9077e58e42235af6582dee72e841David 'Digit' Turner TCGv tmp_mask = tcg_const_i32(mask); 2085285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_cpsr_write(var, tmp_mask); 2095285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp_mask); 2105285864985be9077e58e42235af6582dee72e841David 'Digit' Turner} 2118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Set NZCV flags from the high 4 bits of var. */ 2128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define gen_set_nzcv(var) gen_set_cpsr(var, CPSR_NZCV) 2138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 2148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void gen_exception(int excp) 2158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 2165285864985be9077e58e42235af6582dee72e841David 'Digit' Turner TCGv tmp = tcg_temp_new_i32(); 2178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_movi_i32(tmp, excp); 2188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_helper_exception(tmp); 2195285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 2208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 2218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 2228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void gen_smul_dual(TCGv a, TCGv b) 2238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 2245285864985be9077e58e42235af6582dee72e841David 'Digit' Turner TCGv tmp1 = tcg_temp_new_i32(); 2255285864985be9077e58e42235af6582dee72e841David 'Digit' Turner TCGv tmp2 = tcg_temp_new_i32(); 2268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_ext16s_i32(tmp1, a); 2278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_ext16s_i32(tmp2, b); 2288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_mul_i32(tmp1, tmp1, tmp2); 2295285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 2308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_sari_i32(a, a, 16); 2318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_sari_i32(b, b, 16); 2328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_mul_i32(b, b, a); 2338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_mov_i32(a, tmp1); 2345285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp1); 2358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 2368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 2378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Byteswap each halfword. */ 2388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void gen_rev16(TCGv var) 2398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 2405285864985be9077e58e42235af6582dee72e841David 'Digit' Turner TCGv tmp = tcg_temp_new_i32(); 2418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_shri_i32(tmp, var, 8); 2428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_andi_i32(tmp, tmp, 0x00ff00ff); 2438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_shli_i32(var, var, 8); 2448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_andi_i32(var, var, 0xff00ff00); 2458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_or_i32(var, var, tmp); 2465285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 2478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 2488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 2498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Byteswap low halfword and sign extend. */ 2508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void gen_revsh(TCGv var) 2518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 2525285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_ext16u_i32(var, var); 2535285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_bswap16_i32(var, var); 2545285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_ext16s_i32(var, var); 2558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 2568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 2578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Unsigned bitfield extract. */ 2588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void gen_ubfx(TCGv var, int shift, uint32_t mask) 2598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 2608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (shift) 2618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_shri_i32(var, var, shift); 2628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_andi_i32(var, var, mask); 2638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 2648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 2658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Signed bitfield extract. */ 2668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void gen_sbfx(TCGv var, int shift, int width) 2678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 2688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project uint32_t signbit; 2698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 2708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (shift) 2718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_sari_i32(var, var, shift); 2728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (shift + width < 32) { 2738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project signbit = 1u << (width - 1); 2748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_andi_i32(var, var, (1u << width) - 1); 2758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_xori_i32(var, var, signbit); 2768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_subi_i32(var, var, signbit); 2778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 2788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 2798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 2808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Bitfield insertion. Insert val into base. Clobbers base and val. */ 2818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void gen_bfi(TCGv dest, TCGv base, TCGv val, int shift, uint32_t mask) 2828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 2838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_andi_i32(val, val, mask); 2848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_shli_i32(val, val, shift); 2858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_andi_i32(base, base, ~(mask << shift)); 2868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_or_i32(dest, base, val); 2878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 2888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 2895285864985be9077e58e42235af6582dee72e841David 'Digit' Turner/* Return (b << 32) + a. Mark inputs as dead */ 2905285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic TCGv_i64 gen_addq_msw(TCGv_i64 a, TCGv b) 2915285864985be9077e58e42235af6582dee72e841David 'Digit' Turner{ 2925285864985be9077e58e42235af6582dee72e841David 'Digit' Turner TCGv_i64 tmp64 = tcg_temp_new_i64(); 2935285864985be9077e58e42235af6582dee72e841David 'Digit' Turner 2945285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_extu_i32_i64(tmp64, b); 2955285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(b); 2965285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_shli_i64(tmp64, tmp64, 32); 2975285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_add_i64(a, tmp64, a); 2985285864985be9077e58e42235af6582dee72e841David 'Digit' Turner 2995285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i64(tmp64); 3005285864985be9077e58e42235af6582dee72e841David 'Digit' Turner return a; 3015285864985be9077e58e42235af6582dee72e841David 'Digit' Turner} 3025285864985be9077e58e42235af6582dee72e841David 'Digit' Turner 3035285864985be9077e58e42235af6582dee72e841David 'Digit' Turner/* Return (b << 32) - a. Mark inputs as dead. */ 3045285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic TCGv_i64 gen_subq_msw(TCGv_i64 a, TCGv b) 3058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 3065285864985be9077e58e42235af6582dee72e841David 'Digit' Turner TCGv_i64 tmp64 = tcg_temp_new_i64(); 3075285864985be9077e58e42235af6582dee72e841David 'Digit' Turner 3085285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_extu_i32_i64(tmp64, b); 3095285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(b); 3105285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_shli_i64(tmp64, tmp64, 32); 3115285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_sub_i64(a, tmp64, a); 3125285864985be9077e58e42235af6582dee72e841David 'Digit' Turner 3135285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i64(tmp64); 3145285864985be9077e58e42235af6582dee72e841David 'Digit' Turner return a; 3158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 3168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 3178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* FIXME: Most targets have native widening multiplication. 3188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project It would be good to use that instead of a full wide multiply. */ 3198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* 32x32->64 multiply. Marks inputs as dead. */ 3205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic TCGv_i64 gen_mulu_i64_i32(TCGv a, TCGv b) 3218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 3225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner TCGv_i64 tmp1 = tcg_temp_new_i64(); 3235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner TCGv_i64 tmp2 = tcg_temp_new_i64(); 3248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 3258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_extu_i32_i64(tmp1, a); 3265285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(a); 3278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_extu_i32_i64(tmp2, b); 3285285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(b); 3298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_mul_i64(tmp1, tmp1, tmp2); 3305285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i64(tmp2); 3318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return tmp1; 3328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 3338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 3345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic TCGv_i64 gen_muls_i64_i32(TCGv a, TCGv b) 3358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 3365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner TCGv_i64 tmp1 = tcg_temp_new_i64(); 3375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner TCGv_i64 tmp2 = tcg_temp_new_i64(); 3388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 3398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_ext_i32_i64(tmp1, a); 3405285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(a); 3418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_ext_i32_i64(tmp2, b); 3425285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(b); 3438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_mul_i64(tmp1, tmp1, tmp2); 3445285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i64(tmp2); 3458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return tmp1; 3468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 3478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 3488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Swap low and high halfwords. */ 3498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void gen_swap_half(TCGv var) 3508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 3515285864985be9077e58e42235af6582dee72e841David 'Digit' Turner TCGv tmp = tcg_temp_new_i32(); 3528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_shri_i32(tmp, var, 16); 3538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_shli_i32(var, var, 16); 3548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_or_i32(var, var, tmp); 3555285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 3568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 3578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 3588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Dual 16-bit add. Result placed in t0 and t1 is marked as dead. 3598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = (t0 ^ t1) & 0x8000; 3608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project t0 &= ~0x8000; 3618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project t1 &= ~0x8000; 3628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project t0 = (t0 + t1) ^ tmp; 3638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 3648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 3658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void gen_add16(TCGv t0, TCGv t1) 3668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 3675285864985be9077e58e42235af6582dee72e841David 'Digit' Turner TCGv tmp = tcg_temp_new_i32(); 3688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_xor_i32(tmp, t0, t1); 3698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_andi_i32(tmp, tmp, 0x8000); 3708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_andi_i32(t0, t0, ~0x8000); 3718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_andi_i32(t1, t1, ~0x8000); 3728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_add_i32(t0, t0, t1); 3738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_xor_i32(t0, t0, tmp); 3745285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 3755285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(t1); 3768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 3778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 3788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define gen_set_CF(var) tcg_gen_st_i32(var, cpu_env, offsetof(CPUState, CF)) 3798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 3808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Set CF to the top bit of var. */ 3818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void gen_set_CF_bit31(TCGv var) 3828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 3835285864985be9077e58e42235af6582dee72e841David 'Digit' Turner TCGv tmp = tcg_temp_new_i32(); 3848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_shri_i32(tmp, var, 31); 3855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner gen_set_CF(tmp); 3865285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 3878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 3888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 3898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Set N and Z flags from var. */ 3908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline void gen_logic_CC(TCGv var) 3918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 3928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_st_i32(var, cpu_env, offsetof(CPUState, NF)); 3938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_st_i32(var, cpu_env, offsetof(CPUState, ZF)); 3948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 3958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 3968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* T0 += T1 + CF. */ 3975285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic void gen_adc(TCGv t0, TCGv t1) 3988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 3998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project TCGv tmp; 4005285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_add_i32(t0, t0, t1); 4018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_cpu_field(CF); 4025285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_add_i32(t0, t0, tmp); 4035285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 4048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 4058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 4065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner/* dest = T0 + T1 + CF. */ 4075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void gen_add_carry(TCGv dest, TCGv t0, TCGv t1) 4085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 4095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner TCGv tmp; 4105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tcg_gen_add_i32(dest, t0, t1); 4115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tmp = load_cpu_field(CF); 4125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tcg_gen_add_i32(dest, dest, tmp); 4135285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 4145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 4155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 4168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* dest = T0 - T1 + CF - 1. */ 4178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void gen_sub_carry(TCGv dest, TCGv t0, TCGv t1) 4188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 4198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project TCGv tmp; 4208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_sub_i32(dest, t0, t1); 4218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_cpu_field(CF); 4228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_add_i32(dest, dest, tmp); 4238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_subi_i32(dest, dest, 1); 4245285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 4258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 4268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 4278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* FIXME: Implement this natively. */ 4288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define tcg_gen_abs_i32(t0, t1) gen_helper_abs(t0, t1) 4298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 4308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void shifter_out_im(TCGv var, int shift) 4318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 4325285864985be9077e58e42235af6582dee72e841David 'Digit' Turner TCGv tmp = tcg_temp_new_i32(); 4338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (shift == 0) { 4348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_andi_i32(tmp, var, 1); 4358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 4368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_shri_i32(tmp, var, shift); 4375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (shift != 31) 4388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_andi_i32(tmp, tmp, 1); 4398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 4408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_set_CF(tmp); 4415285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 4428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 4438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 4448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Shift by immediate. Includes special handling for shift == 0. */ 4458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline void gen_arm_shift_im(TCGv var, int shiftop, int shift, int flags) 4468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 4478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (shiftop) { 4488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0: /* LSL */ 4498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (shift != 0) { 4508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (flags) 4518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project shifter_out_im(var, 32 - shift); 4528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_shli_i32(var, var, shift); 4538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 4548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 4558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 1: /* LSR */ 4568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (shift == 0) { 4578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (flags) { 4588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_shri_i32(var, var, 31); 4598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_set_CF(var); 4608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 4618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_movi_i32(var, 0); 4628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 4638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (flags) 4648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project shifter_out_im(var, shift - 1); 4658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_shri_i32(var, var, shift); 4668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 4678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 4688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 2: /* ASR */ 4698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (shift == 0) 4708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project shift = 32; 4718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (flags) 4728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project shifter_out_im(var, shift - 1); 4738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (shift == 32) 4748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project shift = 31; 4758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_sari_i32(var, var, shift); 4768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 4778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 3: /* ROR/RRX */ 4788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (shift != 0) { 4798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (flags) 4808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project shifter_out_im(var, shift - 1); 4815285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_rotri_i32(var, var, shift); break; 4828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 4838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project TCGv tmp = load_cpu_field(CF); 4848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (flags) 4858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project shifter_out_im(var, 0); 4868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_shri_i32(var, var, 1); 4878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_shli_i32(tmp, tmp, 31); 4888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_or_i32(var, var, tmp); 4895285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 4908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 4918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 4928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}; 4938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 4948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline void gen_arm_shift_reg(TCGv var, int shiftop, 4958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project TCGv shift, int flags) 4968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 4978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (flags) { 4988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (shiftop) { 4998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0: gen_helper_shl_cc(var, var, shift); break; 5008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 1: gen_helper_shr_cc(var, var, shift); break; 5018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 2: gen_helper_sar_cc(var, var, shift); break; 5028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 3: gen_helper_ror_cc(var, var, shift); break; 5038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 5048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 5058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (shiftop) { 5068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0: gen_helper_shl(var, var, shift); break; 5078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 1: gen_helper_shr(var, var, shift); break; 5088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 2: gen_helper_sar(var, var, shift); break; 5095285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 3: tcg_gen_andi_i32(shift, shift, 0x1f); 5105285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_rotr_i32(var, var, shift); break; 5118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 5128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 5135285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(shift); 5148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 5158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 5168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define PAS_OP(pfx) \ 5178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (op2) { \ 5188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0: gen_pas_helper(glue(pfx,add16)); break; \ 5198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 1: gen_pas_helper(glue(pfx,addsubx)); break; \ 5208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 2: gen_pas_helper(glue(pfx,subaddx)); break; \ 5218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 3: gen_pas_helper(glue(pfx,sub16)); break; \ 5228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 4: gen_pas_helper(glue(pfx,add8)); break; \ 5238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 7: gen_pas_helper(glue(pfx,sub8)); break; \ 5248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 5258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void gen_arm_parallel_addsub(int op1, int op2, TCGv a, TCGv b) 5268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 5275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner TCGv_ptr tmp; 5288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 5298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (op1) { 5308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b, tmp) 5318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 1: 5325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tmp = tcg_temp_new_ptr(); 5338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUState, GE)); 5348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project PAS_OP(s) 5355285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_ptr(tmp); 5368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 5378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 5: 5385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tmp = tcg_temp_new_ptr(); 5398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUState, GE)); 5408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project PAS_OP(u) 5415285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_ptr(tmp); 5428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 5438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#undef gen_pas_helper 5448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b) 5458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 2: 5468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project PAS_OP(q); 5478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 5488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 3: 5498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project PAS_OP(sh); 5508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 5518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 6: 5528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project PAS_OP(uq); 5538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 5548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 7: 5558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project PAS_OP(uh); 5568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 5578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#undef gen_pas_helper 5588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 5598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 5608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#undef PAS_OP 5618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 5628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* For unknown reasons Arm and Thumb-2 use arbitrarily different encodings. */ 5638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define PAS_OP(pfx) \ 5645285864985be9077e58e42235af6582dee72e841David 'Digit' Turner switch (op1) { \ 5658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0: gen_pas_helper(glue(pfx,add8)); break; \ 5668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 1: gen_pas_helper(glue(pfx,add16)); break; \ 5678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 2: gen_pas_helper(glue(pfx,addsubx)); break; \ 5688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 4: gen_pas_helper(glue(pfx,sub8)); break; \ 5698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 5: gen_pas_helper(glue(pfx,sub16)); break; \ 5708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 6: gen_pas_helper(glue(pfx,subaddx)); break; \ 5718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 5728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void gen_thumb2_parallel_addsub(int op1, int op2, TCGv a, TCGv b) 5738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 5745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner TCGv_ptr tmp; 5758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 5765285864985be9077e58e42235af6582dee72e841David 'Digit' Turner switch (op2) { 5778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b, tmp) 5788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0: 5795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tmp = tcg_temp_new_ptr(); 5808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUState, GE)); 5818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project PAS_OP(s) 5825285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_ptr(tmp); 5838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 5848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 4: 5855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tmp = tcg_temp_new_ptr(); 5868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUState, GE)); 5878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project PAS_OP(u) 5885285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_ptr(tmp); 5898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 5908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#undef gen_pas_helper 5918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b) 5928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 1: 5938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project PAS_OP(q); 5948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 5958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 2: 5968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project PAS_OP(sh); 5978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 5988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 5: 5998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project PAS_OP(uq); 6008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 6018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 6: 6028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project PAS_OP(uh); 6038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 6048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#undef gen_pas_helper 6058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 6068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 6078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#undef PAS_OP 6088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 6098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void gen_test_cc(int cc, int label) 6108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 6118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project TCGv tmp; 6128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project TCGv tmp2; 6138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int inv; 6148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 6158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (cc) { 6168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0: /* eq: Z */ 6178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_cpu_field(ZF); 6188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, label); 6198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 6208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 1: /* ne: !Z */ 6218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_cpu_field(ZF); 6228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, label); 6238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 6248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 2: /* cs: C */ 6258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_cpu_field(CF); 6268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, label); 6278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 6288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 3: /* cc: !C */ 6298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_cpu_field(CF); 6308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, label); 6318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 6328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 4: /* mi: N */ 6338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_cpu_field(NF); 6348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_brcondi_i32(TCG_COND_LT, tmp, 0, label); 6358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 6368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 5: /* pl: !N */ 6378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_cpu_field(NF); 6388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_brcondi_i32(TCG_COND_GE, tmp, 0, label); 6398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 6408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 6: /* vs: V */ 6418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_cpu_field(VF); 6428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_brcondi_i32(TCG_COND_LT, tmp, 0, label); 6438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 6448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 7: /* vc: !V */ 6458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_cpu_field(VF); 6468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_brcondi_i32(TCG_COND_GE, tmp, 0, label); 6478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 6488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 8: /* hi: C && !Z */ 6498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project inv = gen_new_label(); 6508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_cpu_field(CF); 6518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, inv); 6525285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 6538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_cpu_field(ZF); 6548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, label); 6558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_set_label(inv); 6568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 6578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 9: /* ls: !C || Z */ 6588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_cpu_field(CF); 6598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, label); 6605285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 6618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_cpu_field(ZF); 6628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, label); 6638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 6648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 10: /* ge: N == V -> N ^ V == 0 */ 6658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_cpu_field(VF); 6668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp2 = load_cpu_field(NF); 6678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_xor_i32(tmp, tmp, tmp2); 6685285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 6698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_brcondi_i32(TCG_COND_GE, tmp, 0, label); 6708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 6718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 11: /* lt: N != V -> N ^ V != 0 */ 6728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_cpu_field(VF); 6738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp2 = load_cpu_field(NF); 6748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_xor_i32(tmp, tmp, tmp2); 6755285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 6768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_brcondi_i32(TCG_COND_LT, tmp, 0, label); 6778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 6788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 12: /* gt: !Z && N == V */ 6798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project inv = gen_new_label(); 6808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_cpu_field(ZF); 6818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, inv); 6825285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 6838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_cpu_field(VF); 6848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp2 = load_cpu_field(NF); 6858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_xor_i32(tmp, tmp, tmp2); 6865285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 6878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_brcondi_i32(TCG_COND_GE, tmp, 0, label); 6888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_set_label(inv); 6898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 6908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 13: /* le: Z || N != V */ 6918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_cpu_field(ZF); 6928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, label); 6935285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 6948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_cpu_field(VF); 6958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp2 = load_cpu_field(NF); 6968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_xor_i32(tmp, tmp, tmp2); 6975285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 6988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_brcondi_i32(TCG_COND_LT, tmp, 0, label); 6998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 7008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project default: 7018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project fprintf(stderr, "Bad condition code 0x%x\n", cc); 7028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project abort(); 7038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 7045285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 7058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 7068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 7075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic const uint8_t table_logic_cc[16] = { 7088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1, /* and */ 7098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1, /* xor */ 7108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 0, /* sub */ 7118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 0, /* rsb */ 7128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 0, /* add */ 7138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 0, /* adc */ 7148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 0, /* sbc */ 7158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 0, /* rsc */ 7168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1, /* andl */ 7178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1, /* xorl */ 7188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 0, /* cmp */ 7198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 0, /* cmn */ 7208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1, /* orr */ 7218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1, /* mov */ 7228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1, /* bic */ 7238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1, /* mvn */ 7248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}; 7258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 7268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Set PC and Thumb state from an immediate address. */ 7278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline void gen_bx_im(DisasContext *s, uint32_t addr) 7288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 7298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project TCGv tmp; 7308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 7318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project s->is_jmp = DISAS_UPDATE; 7328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (s->thumb != (addr & 1)) { 7335285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = tcg_temp_new_i32(); 7348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_movi_i32(tmp, addr & 1); 7358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_st_i32(tmp, cpu_env, offsetof(CPUState, thumb)); 7365285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 7378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 7385285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_movi_i32(cpu_R[15], addr & ~1); 7398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 7408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 7418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Set PC and Thumb state from var. var is marked as dead. */ 7428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline void gen_bx(DisasContext *s, TCGv var) 7438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 7448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project s->is_jmp = DISAS_UPDATE; 7455285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_andi_i32(cpu_R[15], var, ~1); 7465285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_andi_i32(var, var, 1); 7475285864985be9077e58e42235af6582dee72e841David 'Digit' Turner store_cpu_field(var, thumb); 7488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 7498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 7505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner/* Variant of store_reg which uses branch&exchange logic when storing 7515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner to r15 in ARM architecture v7 and above. The source must be a temporary 7525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner and will be marked as dead. */ 7535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic inline void store_reg_bx(CPUState *env, DisasContext *s, 7545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int reg, TCGv var) 7555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 7565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (reg == 15 && ENABLE_ARCH_7) { 7575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner gen_bx(s, var); 7585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } else { 7595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner store_reg(s, reg, var); 7605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 7615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 7625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 7635285864985be9077e58e42235af6582dee72e841David 'Digit' Turner/* Variant of store_reg which uses branch&exchange logic when storing 7645285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * to r15 in ARM architecture v5T and above. This is used for storing 7655285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * the results of a LDR/LDM/POP into r15, and corresponds to the cases 7665285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * in the ARM ARM which use the LoadWritePC() pseudocode function. */ 7675285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic inline void store_reg_from_load(CPUState *env, DisasContext *s, 7685285864985be9077e58e42235af6582dee72e841David 'Digit' Turner int reg, TCGv var) 7695285864985be9077e58e42235af6582dee72e841David 'Digit' Turner{ 7705285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (reg == 15 && ENABLE_ARCH_5) { 7715285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_bx(s, var); 7725285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } else { 7735285864985be9077e58e42235af6582dee72e841David 'Digit' Turner store_reg(s, reg, var); 7745285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 7755285864985be9077e58e42235af6582dee72e841David 'Digit' Turner} 7765285864985be9077e58e42235af6582dee72e841David 'Digit' Turner 7775285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic inline void gen_smc(CPUState *env, DisasContext *s) 7785285864985be9077e58e42235af6582dee72e841David 'Digit' Turner{ 7795285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_movi_i32(cpu_R[15], s->pc); 7805285864985be9077e58e42235af6582dee72e841David 'Digit' Turner s->is_jmp = DISAS_SMC; 7815285864985be9077e58e42235af6582dee72e841David 'Digit' Turner} 7825285864985be9077e58e42235af6582dee72e841David 'Digit' Turner 7838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline TCGv gen_ld8s(TCGv addr, int index) 7848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 7855285864985be9077e58e42235af6582dee72e841David 'Digit' Turner TCGv tmp = tcg_temp_new_i32(); 7868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_qemu_ld8s(tmp, addr, index); 7878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return tmp; 7888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 7898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline TCGv gen_ld8u(TCGv addr, int index) 7908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 7915285864985be9077e58e42235af6582dee72e841David 'Digit' Turner TCGv tmp = tcg_temp_new_i32(); 7928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_qemu_ld8u(tmp, addr, index); 7938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return tmp; 7948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 7958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline TCGv gen_ld16s(TCGv addr, int index) 7968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 7975285864985be9077e58e42235af6582dee72e841David 'Digit' Turner TCGv tmp = tcg_temp_new_i32(); 7988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_qemu_ld16s(tmp, addr, index); 7998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return tmp; 8008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 8018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline TCGv gen_ld16u(TCGv addr, int index) 8028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 8035285864985be9077e58e42235af6582dee72e841David 'Digit' Turner TCGv tmp = tcg_temp_new_i32(); 8048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_qemu_ld16u(tmp, addr, index); 8058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return tmp; 8068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 8078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline TCGv gen_ld32(TCGv addr, int index) 8088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 8095285864985be9077e58e42235af6582dee72e841David 'Digit' Turner TCGv tmp = tcg_temp_new_i32(); 8108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_qemu_ld32u(tmp, addr, index); 8118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return tmp; 8128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 8135285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic inline TCGv_i64 gen_ld64(TCGv addr, int index) 8145285864985be9077e58e42235af6582dee72e841David 'Digit' Turner{ 8155285864985be9077e58e42235af6582dee72e841David 'Digit' Turner TCGv_i64 tmp = tcg_temp_new_i64(); 8165285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_qemu_ld64(tmp, addr, index); 8175285864985be9077e58e42235af6582dee72e841David 'Digit' Turner return tmp; 8185285864985be9077e58e42235af6582dee72e841David 'Digit' Turner} 8198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline void gen_st8(TCGv val, TCGv addr, int index) 8208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 8218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_qemu_st8(val, addr, index); 8225285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(val); 8238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 8248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline void gen_st16(TCGv val, TCGv addr, int index) 8258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 8268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_qemu_st16(val, addr, index); 8275285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(val); 8288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 8298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline void gen_st32(TCGv val, TCGv addr, int index) 8308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 8318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_qemu_st32(val, addr, index); 8325285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(val); 8338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 8345285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic inline void gen_st64(TCGv_i64 val, TCGv addr, int index) 8358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 8365285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_qemu_st64(val, addr, index); 8375285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i64(val); 8388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 8398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 8408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline void gen_set_pc_im(uint32_t val) 8418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 8425285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_movi_i32(cpu_R[15], val); 8438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 8448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 8458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Force a TB lookup after an instruction that changes the CPU state. */ 8468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline void gen_lookup_tb(DisasContext *s) 8478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 8485285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_movi_i32(cpu_R[15], s->pc & ~1); 8498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project s->is_jmp = DISAS_UPDATE; 8508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 8518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 8528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline void gen_add_data_offset(DisasContext *s, unsigned int insn, 8538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project TCGv var) 8548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 8558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int val, rm, shift, shiftop; 8568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project TCGv offset; 8578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 8588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (!(insn & (1 << 25))) { 8598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* immediate */ 8608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project val = insn & 0xfff; 8618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (!(insn & (1 << 23))) 8628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project val = -val; 8638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (val != 0) 8648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_addi_i32(var, var, val); 8658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 8668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* shift/register */ 8678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rm = (insn) & 0xf; 8688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project shift = (insn >> 7) & 0x1f; 8698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project shiftop = (insn >> 5) & 3; 8708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project offset = load_reg(s, rm); 8718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_arm_shift_im(offset, shiftop, shift, 0); 8728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (!(insn & (1 << 23))) 8738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_sub_i32(var, var, offset); 8748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 8758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_add_i32(var, var, offset); 8765285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(offset); 8778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 8788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 8798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 8808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline void gen_add_datah_offset(DisasContext *s, unsigned int insn, 8818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int extra, TCGv var) 8828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 8838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int val, rm; 8848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project TCGv offset; 8858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 8868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 22)) { 8878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* immediate */ 8888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project val = (insn & 0xf) | ((insn >> 4) & 0xf0); 8898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (!(insn & (1 << 23))) 8908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project val = -val; 8918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project val += extra; 8928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (val != 0) 8938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_addi_i32(var, var, val); 8948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 8958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* register */ 8968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (extra) 8978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_addi_i32(var, var, extra); 8988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rm = (insn) & 0xf; 8998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project offset = load_reg(s, rm); 9008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (!(insn & (1 << 23))) 9018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_sub_i32(var, var, offset); 9028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 9038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_add_i32(var, var, offset); 9045285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(offset); 9058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 9068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 9078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 9088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define VFP_OP2(name) \ 9098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline void gen_vfp_##name(int dp) \ 9108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ \ 9118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (dp) \ 9128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_helper_vfp_##name##d(cpu_F0d, cpu_F0d, cpu_F1d, cpu_env); \ 9138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else \ 9148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, cpu_F1s, cpu_env); \ 9158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 9168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 9178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectVFP_OP2(add) 9188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectVFP_OP2(sub) 9198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectVFP_OP2(mul) 9208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectVFP_OP2(div) 9218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 9228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#undef VFP_OP2 9238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 9245285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic inline void gen_vfp_F1_mul(int dp) 9255285864985be9077e58e42235af6582dee72e841David 'Digit' Turner{ 9265285864985be9077e58e42235af6582dee72e841David 'Digit' Turner /* Like gen_vfp_mul() but put result in F1 */ 9275285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (dp) { 9285285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_vfp_muld(cpu_F1d, cpu_F0d, cpu_F1d, cpu_env); 9295285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } else { 9305285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_vfp_muls(cpu_F1s, cpu_F0s, cpu_F1s, cpu_env); 9315285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 9325285864985be9077e58e42235af6582dee72e841David 'Digit' Turner} 9335285864985be9077e58e42235af6582dee72e841David 'Digit' Turner 9345285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic inline void gen_vfp_F1_neg(int dp) 9355285864985be9077e58e42235af6582dee72e841David 'Digit' Turner{ 9365285864985be9077e58e42235af6582dee72e841David 'Digit' Turner /* Like gen_vfp_neg() but put result in F1 */ 9375285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (dp) { 9385285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_vfp_negd(cpu_F1d, cpu_F0d); 9395285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } else { 9405285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_vfp_negs(cpu_F1s, cpu_F0s); 9415285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 9425285864985be9077e58e42235af6582dee72e841David 'Digit' Turner} 9435285864985be9077e58e42235af6582dee72e841David 'Digit' Turner 9448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline void gen_vfp_abs(int dp) 9458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 9468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (dp) 9478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_helper_vfp_absd(cpu_F0d, cpu_F0d); 9488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 9498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_helper_vfp_abss(cpu_F0s, cpu_F0s); 9508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 9518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 9528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline void gen_vfp_neg(int dp) 9538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 9548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (dp) 9558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_helper_vfp_negd(cpu_F0d, cpu_F0d); 9568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 9578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_helper_vfp_negs(cpu_F0s, cpu_F0s); 9588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 9598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 9608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline void gen_vfp_sqrt(int dp) 9618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 9628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (dp) 9638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_helper_vfp_sqrtd(cpu_F0d, cpu_F0d, cpu_env); 9648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 9658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_helper_vfp_sqrts(cpu_F0s, cpu_F0s, cpu_env); 9668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 9678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 9688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline void gen_vfp_cmp(int dp) 9698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 9708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (dp) 9718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_helper_vfp_cmpd(cpu_F0d, cpu_F1d, cpu_env); 9728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 9738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_helper_vfp_cmps(cpu_F0s, cpu_F1s, cpu_env); 9748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 9758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 9768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline void gen_vfp_cmpe(int dp) 9778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 9788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (dp) 9798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_helper_vfp_cmped(cpu_F0d, cpu_F1d, cpu_env); 9808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 9818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_helper_vfp_cmpes(cpu_F0s, cpu_F1s, cpu_env); 9828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 9838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 9848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline void gen_vfp_F1_ld0(int dp) 9858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 9868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (dp) 9878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_movi_i64(cpu_F1d, 0); 9888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 9898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_movi_i32(cpu_F1s, 0); 9908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 9918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 9925285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define VFP_GEN_ITOF(name) \ 9935285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic inline void gen_vfp_##name(int dp, int neon) \ 9945285864985be9077e58e42235af6582dee72e841David 'Digit' Turner{ \ 9955285864985be9077e58e42235af6582dee72e841David 'Digit' Turner TCGv_ptr statusptr = tcg_temp_new_ptr(); \ 9965285864985be9077e58e42235af6582dee72e841David 'Digit' Turner int offset; \ 9975285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (neon) { \ 9985285864985be9077e58e42235af6582dee72e841David 'Digit' Turner offset = offsetof(CPUState, vfp.standard_fp_status); \ 9995285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } else { \ 10005285864985be9077e58e42235af6582dee72e841David 'Digit' Turner offset = offsetof(CPUState, vfp.fp_status); \ 10015285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } \ 10025285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_addi_ptr(statusptr, cpu_env, offset); \ 10035285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (dp) { \ 10045285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_vfp_##name##d(cpu_F0d, cpu_F0s, statusptr); \ 10055285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } else { \ 10065285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, statusptr); \ 10075285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } \ 10085285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_ptr(statusptr); \ 10098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 10108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 10115285864985be9077e58e42235af6582dee72e841David 'Digit' TurnerVFP_GEN_ITOF(uito) 10125285864985be9077e58e42235af6582dee72e841David 'Digit' TurnerVFP_GEN_ITOF(sito) 10135285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#undef VFP_GEN_ITOF 10148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 10155285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define VFP_GEN_FTOI(name) \ 10165285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic inline void gen_vfp_##name(int dp, int neon) \ 10175285864985be9077e58e42235af6582dee72e841David 'Digit' Turner{ \ 10185285864985be9077e58e42235af6582dee72e841David 'Digit' Turner TCGv_ptr statusptr = tcg_temp_new_ptr(); \ 10195285864985be9077e58e42235af6582dee72e841David 'Digit' Turner int offset; \ 10205285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (neon) { \ 10215285864985be9077e58e42235af6582dee72e841David 'Digit' Turner offset = offsetof(CPUState, vfp.standard_fp_status); \ 10225285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } else { \ 10235285864985be9077e58e42235af6582dee72e841David 'Digit' Turner offset = offsetof(CPUState, vfp.fp_status); \ 10245285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } \ 10255285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_addi_ptr(statusptr, cpu_env, offset); \ 10265285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (dp) { \ 10275285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_vfp_##name##d(cpu_F0s, cpu_F0d, statusptr); \ 10285285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } else { \ 10295285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, statusptr); \ 10305285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } \ 10315285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_ptr(statusptr); \ 10328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 10338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 10345285864985be9077e58e42235af6582dee72e841David 'Digit' TurnerVFP_GEN_FTOI(toui) 10355285864985be9077e58e42235af6582dee72e841David 'Digit' TurnerVFP_GEN_FTOI(touiz) 10365285864985be9077e58e42235af6582dee72e841David 'Digit' TurnerVFP_GEN_FTOI(tosi) 10375285864985be9077e58e42235af6582dee72e841David 'Digit' TurnerVFP_GEN_FTOI(tosiz) 10385285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#undef VFP_GEN_FTOI 10398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 10408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define VFP_GEN_FIX(name) \ 10415285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic inline void gen_vfp_##name(int dp, int shift, int neon) \ 10428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ \ 10435285864985be9077e58e42235af6582dee72e841David 'Digit' Turner TCGv tmp_shift = tcg_const_i32(shift); \ 10445285864985be9077e58e42235af6582dee72e841David 'Digit' Turner TCGv_ptr statusptr = tcg_temp_new_ptr(); \ 10455285864985be9077e58e42235af6582dee72e841David 'Digit' Turner int offset; \ 10465285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (neon) { \ 10475285864985be9077e58e42235af6582dee72e841David 'Digit' Turner offset = offsetof(CPUState, vfp.standard_fp_status); \ 10485285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } else { \ 10495285864985be9077e58e42235af6582dee72e841David 'Digit' Turner offset = offsetof(CPUState, vfp.fp_status); \ 10505285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } \ 10515285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_addi_ptr(statusptr, cpu_env, offset); \ 10525285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (dp) { \ 10535285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_vfp_##name##d(cpu_F0d, cpu_F0d, tmp_shift, statusptr); \ 10545285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } else { \ 10555285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, tmp_shift, statusptr); \ 10565285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } \ 10575285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp_shift); \ 10585285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_ptr(statusptr); \ 10598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 10608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectVFP_GEN_FIX(tosh) 10618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectVFP_GEN_FIX(tosl) 10628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectVFP_GEN_FIX(touh) 10638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectVFP_GEN_FIX(toul) 10648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectVFP_GEN_FIX(shto) 10658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectVFP_GEN_FIX(slto) 10668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectVFP_GEN_FIX(uhto) 10678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectVFP_GEN_FIX(ulto) 10688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#undef VFP_GEN_FIX 10698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 10705285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic inline void gen_vfp_ld(DisasContext *s, int dp, TCGv addr) 10718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 10728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (dp) 10735285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_qemu_ld64(cpu_F0d, addr, IS_USER(s)); 10748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 10755285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_qemu_ld32u(cpu_F0s, addr, IS_USER(s)); 10768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 10778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 10785285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic inline void gen_vfp_st(DisasContext *s, int dp, TCGv addr) 10798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 10808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (dp) 10815285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_qemu_st64(cpu_F0d, addr, IS_USER(s)); 10828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 10835285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_qemu_st32(cpu_F0s, addr, IS_USER(s)); 10848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 10858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 10868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline long 10878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvfp_reg_offset (int dp, int reg) 10888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 10898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (dp) 10908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return offsetof(CPUARMState, vfp.regs[reg]); 10918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else if (reg & 1) { 10928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return offsetof(CPUARMState, vfp.regs[reg >> 1]) 10938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project + offsetof(CPU_DoubleU, l.upper); 10948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 10958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return offsetof(CPUARMState, vfp.regs[reg >> 1]) 10968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project + offsetof(CPU_DoubleU, l.lower); 10978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 10988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 10998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 11008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Return the offset of a 32-bit piece of a NEON register. 11018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project zero is the least significant end of the register. */ 11028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline long 11038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectneon_reg_offset (int reg, int n) 11048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 11058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int sreg; 11068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project sreg = reg * 2 + n; 11078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return vfp_reg_offset(0, sreg); 11088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 11098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 11108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic TCGv neon_load_reg(int reg, int pass) 11118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 11125285864985be9077e58e42235af6582dee72e841David 'Digit' Turner TCGv tmp = tcg_temp_new_i32(); 11138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_ld_i32(tmp, cpu_env, neon_reg_offset(reg, pass)); 11148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return tmp; 11158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 11168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 11178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void neon_store_reg(int reg, int pass, TCGv var) 11188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 11198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_st_i32(var, cpu_env, neon_reg_offset(reg, pass)); 11205285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(var); 11218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 11228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 11235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic inline void neon_load_reg64(TCGv_i64 var, int reg) 11248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 11258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_ld_i64(var, cpu_env, vfp_reg_offset(1, reg)); 11268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 11278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 11285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic inline void neon_store_reg64(TCGv_i64 var, int reg) 11298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 11308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_st_i64(var, cpu_env, vfp_reg_offset(1, reg)); 11318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 11328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 11338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define tcg_gen_ld_f32 tcg_gen_ld_i32 11348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define tcg_gen_ld_f64 tcg_gen_ld_i64 11358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define tcg_gen_st_f32 tcg_gen_st_i32 11368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define tcg_gen_st_f64 tcg_gen_st_i64 11378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 11388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline void gen_mov_F0_vreg(int dp, int reg) 11398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 11408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (dp) 11418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_ld_f64(cpu_F0d, cpu_env, vfp_reg_offset(dp, reg)); 11428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 11438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_ld_f32(cpu_F0s, cpu_env, vfp_reg_offset(dp, reg)); 11448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 11458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 11468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline void gen_mov_F1_vreg(int dp, int reg) 11478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 11488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (dp) 11498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_ld_f64(cpu_F1d, cpu_env, vfp_reg_offset(dp, reg)); 11508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 11518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_ld_f32(cpu_F1s, cpu_env, vfp_reg_offset(dp, reg)); 11528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 11538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 11548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline void gen_mov_vreg_F0(int dp, int reg) 11558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 11568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (dp) 11578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_st_f64(cpu_F0d, cpu_env, vfp_reg_offset(dp, reg)); 11588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 11598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_st_f32(cpu_F0s, cpu_env, vfp_reg_offset(dp, reg)); 11608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 11618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 11628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define ARM_CP_RW_BIT (1 << 20) 11638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 11645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic inline void iwmmxt_load_reg(TCGv_i64 var, int reg) 11658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 11668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_ld_i64(var, cpu_env, offsetof(CPUState, iwmmxt.regs[reg])); 11678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 11688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 11695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic inline void iwmmxt_store_reg(TCGv_i64 var, int reg) 11708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 11718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_st_i64(var, cpu_env, offsetof(CPUState, iwmmxt.regs[reg])); 11728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 11738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 11745285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic inline TCGv iwmmxt_load_creg(int reg) 11758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 11765285864985be9077e58e42235af6582dee72e841David 'Digit' Turner TCGv var = tcg_temp_new_i32(); 11775285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_ld_i32(var, cpu_env, offsetof(CPUState, iwmmxt.cregs[reg])); 11785285864985be9077e58e42235af6582dee72e841David 'Digit' Turner return var; 11798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 11808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 11815285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic inline void iwmmxt_store_creg(int reg, TCGv var) 11828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 11835285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_st_i32(var, cpu_env, offsetof(CPUState, iwmmxt.cregs[reg])); 11845285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(var); 11858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 11868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 11878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline void gen_op_iwmmxt_movq_wRn_M0(int rn) 11888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 11898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project iwmmxt_store_reg(cpu_M0, rn); 11908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 11918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 11928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline void gen_op_iwmmxt_movq_M0_wRn(int rn) 11938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 11948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project iwmmxt_load_reg(cpu_M0, rn); 11958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 11968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 11978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline void gen_op_iwmmxt_orq_M0_wRn(int rn) 11988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 11998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project iwmmxt_load_reg(cpu_V1, rn); 12008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_or_i64(cpu_M0, cpu_M0, cpu_V1); 12018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 12028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 12038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline void gen_op_iwmmxt_andq_M0_wRn(int rn) 12048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 12058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project iwmmxt_load_reg(cpu_V1, rn); 12068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_and_i64(cpu_M0, cpu_M0, cpu_V1); 12078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 12088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 12098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline void gen_op_iwmmxt_xorq_M0_wRn(int rn) 12108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 12118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project iwmmxt_load_reg(cpu_V1, rn); 12128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_xor_i64(cpu_M0, cpu_M0, cpu_V1); 12138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 12148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 12158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define IWMMXT_OP(name) \ 12168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline void gen_op_iwmmxt_##name##_M0_wRn(int rn) \ 12178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ \ 12188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project iwmmxt_load_reg(cpu_V1, rn); \ 12198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_helper_iwmmxt_##name(cpu_M0, cpu_M0, cpu_V1); \ 12208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 12218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 12225285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define IWMMXT_OP_SIZE(name) \ 12235285864985be9077e58e42235af6582dee72e841David 'Digit' TurnerIWMMXT_OP(name##b) \ 12245285864985be9077e58e42235af6582dee72e841David 'Digit' TurnerIWMMXT_OP(name##w) \ 12255285864985be9077e58e42235af6582dee72e841David 'Digit' TurnerIWMMXT_OP(name##l) 12268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 12275285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define IWMMXT_OP_1(name) \ 12288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline void gen_op_iwmmxt_##name##_M0(void) \ 12298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ \ 12305285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_iwmmxt_##name(cpu_M0, cpu_M0); \ 12318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 12328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 12338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectIWMMXT_OP(maddsq) 12348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectIWMMXT_OP(madduq) 12358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectIWMMXT_OP(sadb) 12368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectIWMMXT_OP(sadw) 12378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectIWMMXT_OP(mulslw) 12388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectIWMMXT_OP(mulshw) 12398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectIWMMXT_OP(mululw) 12408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectIWMMXT_OP(muluhw) 12418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectIWMMXT_OP(macsw) 12428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectIWMMXT_OP(macuw) 12438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 12445285864985be9077e58e42235af6582dee72e841David 'Digit' TurnerIWMMXT_OP_SIZE(unpackl) 12455285864985be9077e58e42235af6582dee72e841David 'Digit' TurnerIWMMXT_OP_SIZE(unpackh) 12465285864985be9077e58e42235af6582dee72e841David 'Digit' Turner 12475285864985be9077e58e42235af6582dee72e841David 'Digit' TurnerIWMMXT_OP_1(unpacklub) 12485285864985be9077e58e42235af6582dee72e841David 'Digit' TurnerIWMMXT_OP_1(unpackluw) 12495285864985be9077e58e42235af6582dee72e841David 'Digit' TurnerIWMMXT_OP_1(unpacklul) 12505285864985be9077e58e42235af6582dee72e841David 'Digit' TurnerIWMMXT_OP_1(unpackhub) 12515285864985be9077e58e42235af6582dee72e841David 'Digit' TurnerIWMMXT_OP_1(unpackhuw) 12525285864985be9077e58e42235af6582dee72e841David 'Digit' TurnerIWMMXT_OP_1(unpackhul) 12535285864985be9077e58e42235af6582dee72e841David 'Digit' TurnerIWMMXT_OP_1(unpacklsb) 12545285864985be9077e58e42235af6582dee72e841David 'Digit' TurnerIWMMXT_OP_1(unpacklsw) 12555285864985be9077e58e42235af6582dee72e841David 'Digit' TurnerIWMMXT_OP_1(unpacklsl) 12565285864985be9077e58e42235af6582dee72e841David 'Digit' TurnerIWMMXT_OP_1(unpackhsb) 12575285864985be9077e58e42235af6582dee72e841David 'Digit' TurnerIWMMXT_OP_1(unpackhsw) 12585285864985be9077e58e42235af6582dee72e841David 'Digit' TurnerIWMMXT_OP_1(unpackhsl) 12595285864985be9077e58e42235af6582dee72e841David 'Digit' Turner 12605285864985be9077e58e42235af6582dee72e841David 'Digit' TurnerIWMMXT_OP_SIZE(cmpeq) 12615285864985be9077e58e42235af6582dee72e841David 'Digit' TurnerIWMMXT_OP_SIZE(cmpgtu) 12625285864985be9077e58e42235af6582dee72e841David 'Digit' TurnerIWMMXT_OP_SIZE(cmpgts) 12635285864985be9077e58e42235af6582dee72e841David 'Digit' Turner 12645285864985be9077e58e42235af6582dee72e841David 'Digit' TurnerIWMMXT_OP_SIZE(mins) 12655285864985be9077e58e42235af6582dee72e841David 'Digit' TurnerIWMMXT_OP_SIZE(minu) 12665285864985be9077e58e42235af6582dee72e841David 'Digit' TurnerIWMMXT_OP_SIZE(maxs) 12675285864985be9077e58e42235af6582dee72e841David 'Digit' TurnerIWMMXT_OP_SIZE(maxu) 12685285864985be9077e58e42235af6582dee72e841David 'Digit' Turner 12695285864985be9077e58e42235af6582dee72e841David 'Digit' TurnerIWMMXT_OP_SIZE(subn) 12705285864985be9077e58e42235af6582dee72e841David 'Digit' TurnerIWMMXT_OP_SIZE(addn) 12715285864985be9077e58e42235af6582dee72e841David 'Digit' TurnerIWMMXT_OP_SIZE(subu) 12725285864985be9077e58e42235af6582dee72e841David 'Digit' TurnerIWMMXT_OP_SIZE(addu) 12735285864985be9077e58e42235af6582dee72e841David 'Digit' TurnerIWMMXT_OP_SIZE(subs) 12745285864985be9077e58e42235af6582dee72e841David 'Digit' TurnerIWMMXT_OP_SIZE(adds) 12755285864985be9077e58e42235af6582dee72e841David 'Digit' Turner 12765285864985be9077e58e42235af6582dee72e841David 'Digit' TurnerIWMMXT_OP(avgb0) 12775285864985be9077e58e42235af6582dee72e841David 'Digit' TurnerIWMMXT_OP(avgb1) 12785285864985be9077e58e42235af6582dee72e841David 'Digit' TurnerIWMMXT_OP(avgw0) 12795285864985be9077e58e42235af6582dee72e841David 'Digit' TurnerIWMMXT_OP(avgw1) 12808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 12818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectIWMMXT_OP(msadb) 12828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 12835285864985be9077e58e42235af6582dee72e841David 'Digit' TurnerIWMMXT_OP(packuw) 12845285864985be9077e58e42235af6582dee72e841David 'Digit' TurnerIWMMXT_OP(packul) 12855285864985be9077e58e42235af6582dee72e841David 'Digit' TurnerIWMMXT_OP(packuq) 12865285864985be9077e58e42235af6582dee72e841David 'Digit' TurnerIWMMXT_OP(packsw) 12875285864985be9077e58e42235af6582dee72e841David 'Digit' TurnerIWMMXT_OP(packsl) 12885285864985be9077e58e42235af6582dee72e841David 'Digit' TurnerIWMMXT_OP(packsq) 12898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 12908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void gen_op_iwmmxt_set_mup(void) 12918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 12928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project TCGv tmp; 12938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_cpu_field(iwmmxt.cregs[ARM_IWMMXT_wCon]); 12948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_ori_i32(tmp, tmp, 2); 12958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project store_cpu_field(tmp, iwmmxt.cregs[ARM_IWMMXT_wCon]); 12968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 12978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 12988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void gen_op_iwmmxt_set_cup(void) 12998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 13008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project TCGv tmp; 13018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_cpu_field(iwmmxt.cregs[ARM_IWMMXT_wCon]); 13028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_ori_i32(tmp, tmp, 1); 13038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project store_cpu_field(tmp, iwmmxt.cregs[ARM_IWMMXT_wCon]); 13048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 13058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 13068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void gen_op_iwmmxt_setpsr_nz(void) 13078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 13085285864985be9077e58e42235af6582dee72e841David 'Digit' Turner TCGv tmp = tcg_temp_new_i32(); 13098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_helper_iwmmxt_setpsr_nz(tmp, cpu_M0); 13108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project store_cpu_field(tmp, iwmmxt.cregs[ARM_IWMMXT_wCASF]); 13118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 13128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 13138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline void gen_op_iwmmxt_addl_M0_wRn(int rn) 13148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 13158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project iwmmxt_load_reg(cpu_V1, rn); 13168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_ext32u_i64(cpu_V1, cpu_V1); 13178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_add_i64(cpu_M0, cpu_M0, cpu_V1); 13188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 13198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 13205285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic inline int gen_iwmmxt_address(DisasContext *s, uint32_t insn, TCGv dest) 13218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 13228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int rd; 13238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project uint32_t offset; 13245285864985be9077e58e42235af6582dee72e841David 'Digit' Turner TCGv tmp; 13258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 13268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd = (insn >> 16) & 0xf; 13275285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = load_reg(s, rd); 13288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 13298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project offset = (insn & 0xff) << ((insn >> 7) & 2); 13308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 24)) { 13318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Pre indexed */ 13328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 23)) 13335285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_addi_i32(tmp, tmp, offset); 13348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 13355285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_addi_i32(tmp, tmp, -offset); 13365285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_mov_i32(dest, tmp); 13378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 21)) 13385285864985be9077e58e42235af6582dee72e841David 'Digit' Turner store_reg(s, rd, tmp); 13395285864985be9077e58e42235af6582dee72e841David 'Digit' Turner else 13405285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 13418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else if (insn & (1 << 21)) { 13428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Post indexed */ 13435285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_mov_i32(dest, tmp); 13448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 23)) 13455285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_addi_i32(tmp, tmp, offset); 13468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 13475285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_addi_i32(tmp, tmp, -offset); 13485285864985be9077e58e42235af6582dee72e841David 'Digit' Turner store_reg(s, rd, tmp); 13498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else if (!(insn & (1 << 23))) 13508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 13518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 0; 13528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 13538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 13545285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic inline int gen_iwmmxt_shift(uint32_t insn, uint32_t mask, TCGv dest) 13558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 13568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int rd = (insn >> 0) & 0xf; 13575285864985be9077e58e42235af6582dee72e841David 'Digit' Turner TCGv tmp; 13588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 13595285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (insn & (1 << 8)) { 13605285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (rd < ARM_IWMMXT_wCGR0 || rd > ARM_IWMMXT_wCGR3) { 13618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 13625285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } else { 13635285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = iwmmxt_load_creg(rd); 13645285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 13655285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } else { 13665285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = tcg_temp_new_i32(); 13675285864985be9077e58e42235af6582dee72e841David 'Digit' Turner iwmmxt_load_reg(cpu_V0, rd); 13685285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_trunc_i64_i32(tmp, cpu_V0); 13695285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 13705285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_andi_i32(tmp, tmp, mask); 13715285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_mov_i32(dest, tmp); 13725285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 13738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 0; 13748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 13758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 13765285864985be9077e58e42235af6582dee72e841David 'Digit' Turner/* Disassemble an iwMMXt instruction. Returns nonzero if an error occurred 13778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project (ie. an undefined instruction). */ 13788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int disas_iwmmxt_insn(CPUState *env, DisasContext *s, uint32_t insn) 13798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 13808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int rd, wrd; 13818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int rdhi, rdlo, rd0, rd1, i; 13825285864985be9077e58e42235af6582dee72e841David 'Digit' Turner TCGv addr; 13835285864985be9077e58e42235af6582dee72e841David 'Digit' Turner TCGv tmp, tmp2, tmp3; 13848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 13858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if ((insn & 0x0e000e00) == 0x0c000000) { 13868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if ((insn & 0x0fe00ff0) == 0x0c400000) { 13878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project wrd = insn & 0xf; 13888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rdlo = (insn >> 12) & 0xf; 13898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rdhi = (insn >> 16) & 0xf; 13908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & ARM_CP_RW_BIT) { /* TMRRC */ 13915285864985be9077e58e42235af6582dee72e841David 'Digit' Turner iwmmxt_load_reg(cpu_V0, wrd); 13925285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_trunc_i64_i32(cpu_R[rdlo], cpu_V0); 13935285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_shri_i64(cpu_V0, cpu_V0, 32); 13945285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_trunc_i64_i32(cpu_R[rdhi], cpu_V0); 13958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { /* TMCRR */ 13965285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_concat_i32_i64(cpu_V0, cpu_R[rdlo], cpu_R[rdhi]); 13975285864985be9077e58e42235af6582dee72e841David 'Digit' Turner iwmmxt_store_reg(cpu_V0, wrd); 13988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_set_mup(); 13998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 14008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 0; 14018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 14028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 14038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project wrd = (insn >> 12) & 0xf; 14045285864985be9077e58e42235af6582dee72e841David 'Digit' Turner addr = tcg_temp_new_i32(); 14055285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (gen_iwmmxt_address(s, insn, addr)) { 14065285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(addr); 14078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 14085285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 14098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & ARM_CP_RW_BIT) { 14108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if ((insn >> 28) == 0xf) { /* WLDRW wCx */ 14115285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = tcg_temp_new_i32(); 14125285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_qemu_ld32u(tmp, addr, IS_USER(s)); 14135285864985be9077e58e42235af6582dee72e841David 'Digit' Turner iwmmxt_store_creg(wrd, tmp); 14148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 14158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project i = 1; 14168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 8)) { 14178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 22)) { /* WLDRD */ 14185285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_qemu_ld64(cpu_M0, addr, IS_USER(s)); 14198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project i = 0; 14208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { /* WLDRW wRd */ 14215285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = gen_ld32(addr, IS_USER(s)); 14228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 14238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 14248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 22)) { /* WLDRH */ 14255285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = gen_ld16u(addr, IS_USER(s)); 14268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { /* WLDRB */ 14275285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = gen_ld8u(addr, IS_USER(s)); 14288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 14298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 14308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (i) { 14318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_extu_i32_i64(cpu_M0, tmp); 14325285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 14338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 14348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_movq_wRn_M0(wrd); 14358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 14368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 14378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if ((insn >> 28) == 0xf) { /* WSTRW wCx */ 14385285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = iwmmxt_load_creg(wrd); 14395285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_st32(tmp, addr, IS_USER(s)); 14408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 14418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_movq_M0_wRn(wrd); 14425285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = tcg_temp_new_i32(); 14438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 8)) { 14448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 22)) { /* WSTRD */ 14455285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 14465285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_qemu_st64(cpu_M0, addr, IS_USER(s)); 14478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { /* WSTRW wRd */ 14488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_trunc_i64_i32(tmp, cpu_M0); 14495285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_st32(tmp, addr, IS_USER(s)); 14508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 14518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 14528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 22)) { /* WSTRH */ 14538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_trunc_i64_i32(tmp, cpu_M0); 14545285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_st16(tmp, addr, IS_USER(s)); 14558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { /* WSTRB */ 14568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_trunc_i64_i32(tmp, cpu_M0); 14575285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_st8(tmp, addr, IS_USER(s)); 14588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 14598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 14608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 14618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 14625285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(addr); 14638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 0; 14648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 14658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 14668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if ((insn & 0x0f000000) != 0x0e000000) 14678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 14688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 14698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (((insn >> 12) & 0xf00) | ((insn >> 4) & 0xff)) { 14708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x000: /* WOR */ 14718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project wrd = (insn >> 12) & 0xf; 14728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd0 = (insn >> 0) & 0xf; 14738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd1 = (insn >> 16) & 0xf; 14748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_movq_M0_wRn(rd0); 14758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_orq_M0_wRn(rd1); 14768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_setpsr_nz(); 14778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_movq_wRn_M0(wrd); 14788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_set_mup(); 14798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_set_cup(); 14808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 14818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x011: /* TMCR */ 14828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & 0xf) 14838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 14848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd = (insn >> 12) & 0xf; 14858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project wrd = (insn >> 16) & 0xf; 14868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (wrd) { 14878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case ARM_IWMMXT_wCID: 14888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case ARM_IWMMXT_wCASF: 14898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 14908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case ARM_IWMMXT_wCon: 14918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_set_cup(); 14928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Fall through. */ 14938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case ARM_IWMMXT_wCSSF: 14945285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = iwmmxt_load_creg(wrd); 14955285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp2 = load_reg(s, rd); 14965285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_andc_i32(tmp, tmp, tmp2); 14975285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 14985285864985be9077e58e42235af6582dee72e841David 'Digit' Turner iwmmxt_store_creg(wrd, tmp); 14998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 15008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case ARM_IWMMXT_wCGR0: 15018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case ARM_IWMMXT_wCGR1: 15028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case ARM_IWMMXT_wCGR2: 15038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case ARM_IWMMXT_wCGR3: 15048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_set_cup(); 15055285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = load_reg(s, rd); 15065285864985be9077e58e42235af6582dee72e841David 'Digit' Turner iwmmxt_store_creg(wrd, tmp); 15078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 15088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project default: 15098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 15108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 15118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 15128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x100: /* WXOR */ 15138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project wrd = (insn >> 12) & 0xf; 15148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd0 = (insn >> 0) & 0xf; 15158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd1 = (insn >> 16) & 0xf; 15168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_movq_M0_wRn(rd0); 15178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_xorq_M0_wRn(rd1); 15188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_setpsr_nz(); 15198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_movq_wRn_M0(wrd); 15208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_set_mup(); 15218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_set_cup(); 15228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 15238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x111: /* TMRC */ 15248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & 0xf) 15258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 15268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd = (insn >> 12) & 0xf; 15278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project wrd = (insn >> 16) & 0xf; 15285285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = iwmmxt_load_creg(wrd); 15295285864985be9077e58e42235af6582dee72e841David 'Digit' Turner store_reg(s, rd, tmp); 15308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 15318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x300: /* WANDN */ 15328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project wrd = (insn >> 12) & 0xf; 15338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd0 = (insn >> 0) & 0xf; 15348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd1 = (insn >> 16) & 0xf; 15358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_movq_M0_wRn(rd0); 15368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_neg_i64(cpu_M0, cpu_M0); 15378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_andq_M0_wRn(rd1); 15388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_setpsr_nz(); 15398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_movq_wRn_M0(wrd); 15408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_set_mup(); 15418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_set_cup(); 15428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 15438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x200: /* WAND */ 15448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project wrd = (insn >> 12) & 0xf; 15458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd0 = (insn >> 0) & 0xf; 15468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd1 = (insn >> 16) & 0xf; 15478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_movq_M0_wRn(rd0); 15488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_andq_M0_wRn(rd1); 15498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_setpsr_nz(); 15508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_movq_wRn_M0(wrd); 15518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_set_mup(); 15528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_set_cup(); 15538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 15548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x810: case 0xa10: /* WMADD */ 15558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project wrd = (insn >> 12) & 0xf; 15568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd0 = (insn >> 0) & 0xf; 15578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd1 = (insn >> 16) & 0xf; 15588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_movq_M0_wRn(rd0); 15598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 21)) 15608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_maddsq_M0_wRn(rd1); 15618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 15628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_madduq_M0_wRn(rd1); 15638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_movq_wRn_M0(wrd); 15648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_set_mup(); 15658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 15668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x10e: case 0x50e: case 0x90e: case 0xd0e: /* WUNPCKIL */ 15678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project wrd = (insn >> 12) & 0xf; 15688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd0 = (insn >> 16) & 0xf; 15698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd1 = (insn >> 0) & 0xf; 15708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_movq_M0_wRn(rd0); 15718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch ((insn >> 22) & 3) { 15728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0: 15738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_unpacklb_M0_wRn(rd1); 15748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 15758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 1: 15768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_unpacklw_M0_wRn(rd1); 15778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 15788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 2: 15798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_unpackll_M0_wRn(rd1); 15808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 15818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 3: 15828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 15838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 15848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_movq_wRn_M0(wrd); 15858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_set_mup(); 15868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_set_cup(); 15878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 15888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x10c: case 0x50c: case 0x90c: case 0xd0c: /* WUNPCKIH */ 15898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project wrd = (insn >> 12) & 0xf; 15908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd0 = (insn >> 16) & 0xf; 15918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd1 = (insn >> 0) & 0xf; 15928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_movq_M0_wRn(rd0); 15938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch ((insn >> 22) & 3) { 15948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0: 15958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_unpackhb_M0_wRn(rd1); 15968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 15978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 1: 15988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_unpackhw_M0_wRn(rd1); 15998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 16008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 2: 16018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_unpackhl_M0_wRn(rd1); 16028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 16038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 3: 16048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 16058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 16068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_movq_wRn_M0(wrd); 16078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_set_mup(); 16088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_set_cup(); 16098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 16108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x012: case 0x112: case 0x412: case 0x512: /* WSAD */ 16118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project wrd = (insn >> 12) & 0xf; 16128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd0 = (insn >> 16) & 0xf; 16138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd1 = (insn >> 0) & 0xf; 16148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_movq_M0_wRn(rd0); 16158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 22)) 16168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_sadw_M0_wRn(rd1); 16178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 16188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_sadb_M0_wRn(rd1); 16198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (!(insn & (1 << 20))) 16208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_addl_M0_wRn(wrd); 16218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_movq_wRn_M0(wrd); 16228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_set_mup(); 16238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 16248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x010: case 0x110: case 0x210: case 0x310: /* WMUL */ 16258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project wrd = (insn >> 12) & 0xf; 16268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd0 = (insn >> 16) & 0xf; 16278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd1 = (insn >> 0) & 0xf; 16288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_movq_M0_wRn(rd0); 16298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 21)) { 16308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 20)) 16318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_mulshw_M0_wRn(rd1); 16328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 16338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_mulslw_M0_wRn(rd1); 16348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 16358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 20)) 16368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_muluhw_M0_wRn(rd1); 16378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 16388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_mululw_M0_wRn(rd1); 16398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 16408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_movq_wRn_M0(wrd); 16418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_set_mup(); 16428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 16438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x410: case 0x510: case 0x610: case 0x710: /* WMAC */ 16448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project wrd = (insn >> 12) & 0xf; 16458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd0 = (insn >> 16) & 0xf; 16468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd1 = (insn >> 0) & 0xf; 16478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_movq_M0_wRn(rd0); 16488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 21)) 16498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_macsw_M0_wRn(rd1); 16508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 16518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_macuw_M0_wRn(rd1); 16528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (!(insn & (1 << 20))) { 16538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project iwmmxt_load_reg(cpu_V1, wrd); 16548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_add_i64(cpu_M0, cpu_M0, cpu_V1); 16558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 16568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_movq_wRn_M0(wrd); 16578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_set_mup(); 16588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 16598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x006: case 0x406: case 0x806: case 0xc06: /* WCMPEQ */ 16608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project wrd = (insn >> 12) & 0xf; 16618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd0 = (insn >> 16) & 0xf; 16628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd1 = (insn >> 0) & 0xf; 16638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_movq_M0_wRn(rd0); 16648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch ((insn >> 22) & 3) { 16658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0: 16668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_cmpeqb_M0_wRn(rd1); 16678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 16688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 1: 16698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_cmpeqw_M0_wRn(rd1); 16708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 16718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 2: 16728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_cmpeql_M0_wRn(rd1); 16738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 16748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 3: 16758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 16768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 16778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_movq_wRn_M0(wrd); 16788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_set_mup(); 16798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_set_cup(); 16808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 16818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x800: case 0x900: case 0xc00: case 0xd00: /* WAVG2 */ 16828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project wrd = (insn >> 12) & 0xf; 16838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd0 = (insn >> 16) & 0xf; 16848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd1 = (insn >> 0) & 0xf; 16858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_movq_M0_wRn(rd0); 16868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 22)) { 16878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 20)) 16888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_avgw1_M0_wRn(rd1); 16898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 16908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_avgw0_M0_wRn(rd1); 16918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 16928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 20)) 16938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_avgb1_M0_wRn(rd1); 16948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 16958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_avgb0_M0_wRn(rd1); 16968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 16978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_movq_wRn_M0(wrd); 16988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_set_mup(); 16998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_set_cup(); 17008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 17018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x802: case 0x902: case 0xa02: case 0xb02: /* WALIGNR */ 17028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project wrd = (insn >> 12) & 0xf; 17038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd0 = (insn >> 16) & 0xf; 17048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd1 = (insn >> 0) & 0xf; 17058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_movq_M0_wRn(rd0); 17065285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = iwmmxt_load_creg(ARM_IWMMXT_wCGR0 + ((insn >> 20) & 3)); 17075285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_andi_i32(tmp, tmp, 7); 17085285864985be9077e58e42235af6582dee72e841David 'Digit' Turner iwmmxt_load_reg(cpu_V1, rd1); 17095285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_iwmmxt_align(cpu_M0, cpu_M0, cpu_V1, tmp); 17105285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 17118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_movq_wRn_M0(wrd); 17128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_set_mup(); 17138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 17148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x601: case 0x605: case 0x609: case 0x60d: /* TINSR */ 17155285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (((insn >> 6) & 3) == 3) 17165285864985be9077e58e42235af6582dee72e841David 'Digit' Turner return 1; 17178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd = (insn >> 12) & 0xf; 17188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project wrd = (insn >> 16) & 0xf; 17195285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = load_reg(s, rd); 17208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_movq_M0_wRn(wrd); 17218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch ((insn >> 6) & 3) { 17228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0: 17235285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp2 = tcg_const_i32(0xff); 17245285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp3 = tcg_const_i32((insn & 7) << 3); 17258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 17268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 1: 17275285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp2 = tcg_const_i32(0xffff); 17285285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp3 = tcg_const_i32((insn & 3) << 4); 17298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 17308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 2: 17315285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp2 = tcg_const_i32(0xffffffff); 17325285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp3 = tcg_const_i32((insn & 1) << 5); 17338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 17345285864985be9077e58e42235af6582dee72e841David 'Digit' Turner default: 17355285864985be9077e58e42235af6582dee72e841David 'Digit' Turner TCGV_UNUSED(tmp2); 17365285864985be9077e58e42235af6582dee72e841David 'Digit' Turner TCGV_UNUSED(tmp3); 17378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 17385285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_iwmmxt_insr(cpu_M0, cpu_M0, tmp, tmp2, tmp3); 17395285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free(tmp3); 17405285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free(tmp2); 17415285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 17428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_movq_wRn_M0(wrd); 17438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_set_mup(); 17448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 17458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x107: case 0x507: case 0x907: case 0xd07: /* TEXTRM */ 17468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd = (insn >> 12) & 0xf; 17478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project wrd = (insn >> 16) & 0xf; 17485285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (rd == 15 || ((insn >> 22) & 3) == 3) 17498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 17508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_movq_M0_wRn(wrd); 17515285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = tcg_temp_new_i32(); 17528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch ((insn >> 22) & 3) { 17538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0: 17545285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_shri_i64(cpu_M0, cpu_M0, (insn & 7) << 3); 17555285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_trunc_i64_i32(tmp, cpu_M0); 17565285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (insn & 8) { 17575285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_ext8s_i32(tmp, tmp); 17585285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } else { 17595285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_andi_i32(tmp, tmp, 0xff); 17608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 17618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 17628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 1: 17635285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_shri_i64(cpu_M0, cpu_M0, (insn & 3) << 4); 17645285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_trunc_i64_i32(tmp, cpu_M0); 17655285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (insn & 8) { 17665285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_ext16s_i32(tmp, tmp); 17675285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } else { 17685285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_andi_i32(tmp, tmp, 0xffff); 17698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 17708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 17718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 2: 17725285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_shri_i64(cpu_M0, cpu_M0, (insn & 1) << 5); 17735285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_trunc_i64_i32(tmp, cpu_M0); 17748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 17758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 17765285864985be9077e58e42235af6582dee72e841David 'Digit' Turner store_reg(s, rd, tmp); 17778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 17788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x117: case 0x517: case 0x917: case 0xd17: /* TEXTRC */ 17795285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if ((insn & 0x000ff008) != 0x0003f000 || ((insn >> 22) & 3) == 3) 17808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 17815285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = iwmmxt_load_creg(ARM_IWMMXT_wCASF); 17828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch ((insn >> 22) & 3) { 17838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0: 17845285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_shri_i32(tmp, tmp, ((insn & 7) << 2) + 0); 17858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 17868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 1: 17875285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_shri_i32(tmp, tmp, ((insn & 3) << 3) + 4); 17888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 17898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 2: 17905285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_shri_i32(tmp, tmp, ((insn & 1) << 4) + 12); 17918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 17928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 17935285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_shli_i32(tmp, tmp, 28); 17945285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_set_nzcv(tmp); 17955285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 17968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 17978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x401: case 0x405: case 0x409: case 0x40d: /* TBCST */ 17985285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (((insn >> 6) & 3) == 3) 17995285864985be9077e58e42235af6582dee72e841David 'Digit' Turner return 1; 18008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd = (insn >> 12) & 0xf; 18018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project wrd = (insn >> 16) & 0xf; 18025285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = load_reg(s, rd); 18038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch ((insn >> 6) & 3) { 18048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0: 18055285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_iwmmxt_bcstb(cpu_M0, tmp); 18068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 18078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 1: 18085285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_iwmmxt_bcstw(cpu_M0, tmp); 18098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 18108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 2: 18115285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_iwmmxt_bcstl(cpu_M0, tmp); 18128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 18138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 18145285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 18158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_movq_wRn_M0(wrd); 18168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_set_mup(); 18178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 18188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x113: case 0x513: case 0x913: case 0xd13: /* TANDC */ 18195285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if ((insn & 0x000ff00f) != 0x0003f000 || ((insn >> 22) & 3) == 3) 18208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 18215285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = iwmmxt_load_creg(ARM_IWMMXT_wCASF); 18225285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp2 = tcg_temp_new_i32(); 18235285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_mov_i32(tmp2, tmp); 18248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch ((insn >> 22) & 3) { 18258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0: 18268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project for (i = 0; i < 7; i ++) { 18275285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_shli_i32(tmp2, tmp2, 4); 18285285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_and_i32(tmp, tmp, tmp2); 18298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 18308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 18318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 1: 18328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project for (i = 0; i < 3; i ++) { 18335285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_shli_i32(tmp2, tmp2, 8); 18345285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_and_i32(tmp, tmp, tmp2); 18358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 18368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 18378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 2: 18385285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_shli_i32(tmp2, tmp2, 16); 18395285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_and_i32(tmp, tmp, tmp2); 18408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 18418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 18425285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_set_nzcv(tmp); 18435285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 18445285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 18458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 18468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x01c: case 0x41c: case 0x81c: case 0xc1c: /* WACC */ 18478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project wrd = (insn >> 12) & 0xf; 18488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd0 = (insn >> 16) & 0xf; 18498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_movq_M0_wRn(rd0); 18508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch ((insn >> 22) & 3) { 18518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0: 18528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_helper_iwmmxt_addcb(cpu_M0, cpu_M0); 18538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 18548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 1: 18558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_helper_iwmmxt_addcw(cpu_M0, cpu_M0); 18568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 18578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 2: 18588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_helper_iwmmxt_addcl(cpu_M0, cpu_M0); 18598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 18608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 3: 18618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 18628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 18638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_movq_wRn_M0(wrd); 18648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_set_mup(); 18658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 18668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x115: case 0x515: case 0x915: case 0xd15: /* TORC */ 18675285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if ((insn & 0x000ff00f) != 0x0003f000 || ((insn >> 22) & 3) == 3) 18688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 18695285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = iwmmxt_load_creg(ARM_IWMMXT_wCASF); 18705285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp2 = tcg_temp_new_i32(); 18715285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_mov_i32(tmp2, tmp); 18728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch ((insn >> 22) & 3) { 18738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0: 18748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project for (i = 0; i < 7; i ++) { 18755285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_shli_i32(tmp2, tmp2, 4); 18765285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_or_i32(tmp, tmp, tmp2); 18778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 18788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 18798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 1: 18808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project for (i = 0; i < 3; i ++) { 18815285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_shli_i32(tmp2, tmp2, 8); 18825285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_or_i32(tmp, tmp, tmp2); 18838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 18848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 18858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 2: 18865285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_shli_i32(tmp2, tmp2, 16); 18875285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_or_i32(tmp, tmp, tmp2); 18888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 18898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 18905285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_set_nzcv(tmp); 18915285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 18925285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 18938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 18948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x103: case 0x503: case 0x903: case 0xd03: /* TMOVMSK */ 18958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd = (insn >> 12) & 0xf; 18968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd0 = (insn >> 16) & 0xf; 18975285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if ((insn & 0xf) != 0 || ((insn >> 22) & 3) == 3) 18988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 18998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_movq_M0_wRn(rd0); 19005285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = tcg_temp_new_i32(); 19018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch ((insn >> 22) & 3) { 19028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0: 19035285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_iwmmxt_msbb(tmp, cpu_M0); 19048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 19058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 1: 19065285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_iwmmxt_msbw(tmp, cpu_M0); 19078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 19088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 2: 19095285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_iwmmxt_msbl(tmp, cpu_M0); 19108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 19118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 19125285864985be9077e58e42235af6582dee72e841David 'Digit' Turner store_reg(s, rd, tmp); 19138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 19148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x106: case 0x306: case 0x506: case 0x706: /* WCMPGT */ 19158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x906: case 0xb06: case 0xd06: case 0xf06: 19168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project wrd = (insn >> 12) & 0xf; 19178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd0 = (insn >> 16) & 0xf; 19188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd1 = (insn >> 0) & 0xf; 19198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_movq_M0_wRn(rd0); 19208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch ((insn >> 22) & 3) { 19218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0: 19228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 21)) 19238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_cmpgtsb_M0_wRn(rd1); 19248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 19258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_cmpgtub_M0_wRn(rd1); 19268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 19278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 1: 19288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 21)) 19298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_cmpgtsw_M0_wRn(rd1); 19308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 19318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_cmpgtuw_M0_wRn(rd1); 19328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 19338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 2: 19348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 21)) 19358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_cmpgtsl_M0_wRn(rd1); 19368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 19378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_cmpgtul_M0_wRn(rd1); 19388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 19398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 3: 19408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 19418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 19428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_movq_wRn_M0(wrd); 19438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_set_mup(); 19448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_set_cup(); 19458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 19468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x00e: case 0x20e: case 0x40e: case 0x60e: /* WUNPCKEL */ 19478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x80e: case 0xa0e: case 0xc0e: case 0xe0e: 19488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project wrd = (insn >> 12) & 0xf; 19498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd0 = (insn >> 16) & 0xf; 19508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_movq_M0_wRn(rd0); 19518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch ((insn >> 22) & 3) { 19528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0: 19538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 21)) 19548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_unpacklsb_M0(); 19558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 19568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_unpacklub_M0(); 19578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 19588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 1: 19598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 21)) 19608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_unpacklsw_M0(); 19618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 19628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_unpackluw_M0(); 19638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 19648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 2: 19658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 21)) 19668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_unpacklsl_M0(); 19678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 19688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_unpacklul_M0(); 19698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 19708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 3: 19718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 19728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 19738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_movq_wRn_M0(wrd); 19748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_set_mup(); 19758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_set_cup(); 19768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 19778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x00c: case 0x20c: case 0x40c: case 0x60c: /* WUNPCKEH */ 19788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x80c: case 0xa0c: case 0xc0c: case 0xe0c: 19798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project wrd = (insn >> 12) & 0xf; 19808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd0 = (insn >> 16) & 0xf; 19818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_movq_M0_wRn(rd0); 19828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch ((insn >> 22) & 3) { 19838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0: 19848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 21)) 19858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_unpackhsb_M0(); 19868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 19878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_unpackhub_M0(); 19888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 19898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 1: 19908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 21)) 19918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_unpackhsw_M0(); 19928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 19938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_unpackhuw_M0(); 19948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 19958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 2: 19968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 21)) 19978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_unpackhsl_M0(); 19988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 19998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_unpackhul_M0(); 20008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 20018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 3: 20028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 20038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 20048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_movq_wRn_M0(wrd); 20058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_set_mup(); 20068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_set_cup(); 20078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 20088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x204: case 0x604: case 0xa04: case 0xe04: /* WSRL */ 20098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x214: case 0x614: case 0xa14: case 0xe14: 20105285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (((insn >> 22) & 3) == 0) 20115285864985be9077e58e42235af6582dee72e841David 'Digit' Turner return 1; 20128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project wrd = (insn >> 12) & 0xf; 20138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd0 = (insn >> 16) & 0xf; 20148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_movq_M0_wRn(rd0); 20155285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = tcg_temp_new_i32(); 20165285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (gen_iwmmxt_shift(insn, 0xff, tmp)) { 20175285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 20188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 20195285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 20208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch ((insn >> 22) & 3) { 20218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 1: 20225285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_iwmmxt_srlw(cpu_M0, cpu_M0, tmp); 20238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 20248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 2: 20255285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_iwmmxt_srll(cpu_M0, cpu_M0, tmp); 20268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 20278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 3: 20285285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_iwmmxt_srlq(cpu_M0, cpu_M0, tmp); 20298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 20308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 20315285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 20328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_movq_wRn_M0(wrd); 20338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_set_mup(); 20348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_set_cup(); 20358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 20368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x004: case 0x404: case 0x804: case 0xc04: /* WSRA */ 20378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x014: case 0x414: case 0x814: case 0xc14: 20385285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (((insn >> 22) & 3) == 0) 20395285864985be9077e58e42235af6582dee72e841David 'Digit' Turner return 1; 20408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project wrd = (insn >> 12) & 0xf; 20418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd0 = (insn >> 16) & 0xf; 20428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_movq_M0_wRn(rd0); 20435285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = tcg_temp_new_i32(); 20445285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (gen_iwmmxt_shift(insn, 0xff, tmp)) { 20455285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 20468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 20475285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 20488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch ((insn >> 22) & 3) { 20498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 1: 20505285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_iwmmxt_sraw(cpu_M0, cpu_M0, tmp); 20518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 20528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 2: 20535285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_iwmmxt_sral(cpu_M0, cpu_M0, tmp); 20548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 20558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 3: 20565285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_iwmmxt_sraq(cpu_M0, cpu_M0, tmp); 20578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 20588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 20595285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 20608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_movq_wRn_M0(wrd); 20618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_set_mup(); 20628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_set_cup(); 20638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 20648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x104: case 0x504: case 0x904: case 0xd04: /* WSLL */ 20658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x114: case 0x514: case 0x914: case 0xd14: 20665285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (((insn >> 22) & 3) == 0) 20675285864985be9077e58e42235af6582dee72e841David 'Digit' Turner return 1; 20688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project wrd = (insn >> 12) & 0xf; 20698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd0 = (insn >> 16) & 0xf; 20708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_movq_M0_wRn(rd0); 20715285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = tcg_temp_new_i32(); 20725285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (gen_iwmmxt_shift(insn, 0xff, tmp)) { 20735285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 20748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 20755285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 20768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch ((insn >> 22) & 3) { 20778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 1: 20785285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_iwmmxt_sllw(cpu_M0, cpu_M0, tmp); 20798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 20808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 2: 20815285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_iwmmxt_slll(cpu_M0, cpu_M0, tmp); 20828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 20838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 3: 20845285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_iwmmxt_sllq(cpu_M0, cpu_M0, tmp); 20858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 20868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 20875285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 20888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_movq_wRn_M0(wrd); 20898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_set_mup(); 20908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_set_cup(); 20918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 20928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x304: case 0x704: case 0xb04: case 0xf04: /* WROR */ 20938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x314: case 0x714: case 0xb14: case 0xf14: 20945285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (((insn >> 22) & 3) == 0) 20955285864985be9077e58e42235af6582dee72e841David 'Digit' Turner return 1; 20968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project wrd = (insn >> 12) & 0xf; 20978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd0 = (insn >> 16) & 0xf; 20988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_movq_M0_wRn(rd0); 20995285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = tcg_temp_new_i32(); 21008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch ((insn >> 22) & 3) { 21018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 1: 21025285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (gen_iwmmxt_shift(insn, 0xf, tmp)) { 21035285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 21048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 21055285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 21065285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_iwmmxt_rorw(cpu_M0, cpu_M0, tmp); 21078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 21088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 2: 21095285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (gen_iwmmxt_shift(insn, 0x1f, tmp)) { 21105285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 21118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 21125285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 21135285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_iwmmxt_rorl(cpu_M0, cpu_M0, tmp); 21148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 21158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 3: 21165285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (gen_iwmmxt_shift(insn, 0x3f, tmp)) { 21175285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 21188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 21195285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 21205285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_iwmmxt_rorq(cpu_M0, cpu_M0, tmp); 21218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 21228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 21235285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 21248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_movq_wRn_M0(wrd); 21258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_set_mup(); 21268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_set_cup(); 21278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 21288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x116: case 0x316: case 0x516: case 0x716: /* WMIN */ 21298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x916: case 0xb16: case 0xd16: case 0xf16: 21308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project wrd = (insn >> 12) & 0xf; 21318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd0 = (insn >> 16) & 0xf; 21328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd1 = (insn >> 0) & 0xf; 21338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_movq_M0_wRn(rd0); 21348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch ((insn >> 22) & 3) { 21358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0: 21368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 21)) 21378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_minsb_M0_wRn(rd1); 21388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 21398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_minub_M0_wRn(rd1); 21408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 21418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 1: 21428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 21)) 21438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_minsw_M0_wRn(rd1); 21448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 21458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_minuw_M0_wRn(rd1); 21468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 21478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 2: 21488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 21)) 21498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_minsl_M0_wRn(rd1); 21508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 21518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_minul_M0_wRn(rd1); 21528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 21538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 3: 21548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 21558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 21568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_movq_wRn_M0(wrd); 21578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_set_mup(); 21588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 21598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x016: case 0x216: case 0x416: case 0x616: /* WMAX */ 21608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x816: case 0xa16: case 0xc16: case 0xe16: 21618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project wrd = (insn >> 12) & 0xf; 21628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd0 = (insn >> 16) & 0xf; 21638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd1 = (insn >> 0) & 0xf; 21648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_movq_M0_wRn(rd0); 21658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch ((insn >> 22) & 3) { 21668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0: 21678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 21)) 21688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_maxsb_M0_wRn(rd1); 21698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 21708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_maxub_M0_wRn(rd1); 21718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 21728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 1: 21738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 21)) 21748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_maxsw_M0_wRn(rd1); 21758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 21768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_maxuw_M0_wRn(rd1); 21778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 21788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 2: 21798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 21)) 21808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_maxsl_M0_wRn(rd1); 21818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 21828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_maxul_M0_wRn(rd1); 21838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 21848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 3: 21858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 21868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 21878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_movq_wRn_M0(wrd); 21888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_set_mup(); 21898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 21908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x002: case 0x102: case 0x202: case 0x302: /* WALIGNI */ 21918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x402: case 0x502: case 0x602: case 0x702: 21928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project wrd = (insn >> 12) & 0xf; 21938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd0 = (insn >> 16) & 0xf; 21948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd1 = (insn >> 0) & 0xf; 21958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_movq_M0_wRn(rd0); 21965285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = tcg_const_i32((insn >> 20) & 3); 21975285864985be9077e58e42235af6582dee72e841David 'Digit' Turner iwmmxt_load_reg(cpu_V1, rd1); 21985285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_iwmmxt_align(cpu_M0, cpu_M0, cpu_V1, tmp); 21995285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free(tmp); 22008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_movq_wRn_M0(wrd); 22018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_set_mup(); 22028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 22038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x01a: case 0x11a: case 0x21a: case 0x31a: /* WSUB */ 22048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x41a: case 0x51a: case 0x61a: case 0x71a: 22058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x81a: case 0x91a: case 0xa1a: case 0xb1a: 22068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0xc1a: case 0xd1a: case 0xe1a: case 0xf1a: 22078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project wrd = (insn >> 12) & 0xf; 22088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd0 = (insn >> 16) & 0xf; 22098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd1 = (insn >> 0) & 0xf; 22108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_movq_M0_wRn(rd0); 22118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch ((insn >> 20) & 0xf) { 22128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x0: 22138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_subnb_M0_wRn(rd1); 22148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 22158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x1: 22168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_subub_M0_wRn(rd1); 22178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 22188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x3: 22198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_subsb_M0_wRn(rd1); 22208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 22218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x4: 22228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_subnw_M0_wRn(rd1); 22238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 22248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x5: 22258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_subuw_M0_wRn(rd1); 22268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 22278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x7: 22288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_subsw_M0_wRn(rd1); 22298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 22308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x8: 22318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_subnl_M0_wRn(rd1); 22328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 22338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x9: 22348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_subul_M0_wRn(rd1); 22358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 22368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0xb: 22378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_subsl_M0_wRn(rd1); 22388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 22398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project default: 22408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 22418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 22428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_movq_wRn_M0(wrd); 22438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_set_mup(); 22448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_set_cup(); 22458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 22468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x01e: case 0x11e: case 0x21e: case 0x31e: /* WSHUFH */ 22478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x41e: case 0x51e: case 0x61e: case 0x71e: 22488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x81e: case 0x91e: case 0xa1e: case 0xb1e: 22498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0xc1e: case 0xd1e: case 0xe1e: case 0xf1e: 22508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project wrd = (insn >> 12) & 0xf; 22518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd0 = (insn >> 16) & 0xf; 22528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_movq_M0_wRn(rd0); 22535285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = tcg_const_i32(((insn >> 16) & 0xf0) | (insn & 0x0f)); 22545285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_iwmmxt_shufh(cpu_M0, cpu_M0, tmp); 22555285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free(tmp); 22568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_movq_wRn_M0(wrd); 22578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_set_mup(); 22588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_set_cup(); 22598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 22608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x018: case 0x118: case 0x218: case 0x318: /* WADD */ 22618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x418: case 0x518: case 0x618: case 0x718: 22628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x818: case 0x918: case 0xa18: case 0xb18: 22638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0xc18: case 0xd18: case 0xe18: case 0xf18: 22648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project wrd = (insn >> 12) & 0xf; 22658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd0 = (insn >> 16) & 0xf; 22668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd1 = (insn >> 0) & 0xf; 22678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_movq_M0_wRn(rd0); 22688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch ((insn >> 20) & 0xf) { 22698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x0: 22708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_addnb_M0_wRn(rd1); 22718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 22728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x1: 22738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_addub_M0_wRn(rd1); 22748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 22758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x3: 22768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_addsb_M0_wRn(rd1); 22778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 22788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x4: 22798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_addnw_M0_wRn(rd1); 22808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 22818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x5: 22828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_adduw_M0_wRn(rd1); 22838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 22848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x7: 22858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_addsw_M0_wRn(rd1); 22868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 22878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x8: 22888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_addnl_M0_wRn(rd1); 22898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 22908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x9: 22918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_addul_M0_wRn(rd1); 22928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 22938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0xb: 22948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_addsl_M0_wRn(rd1); 22958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 22968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project default: 22978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 22988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 22998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_movq_wRn_M0(wrd); 23008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_set_mup(); 23018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_set_cup(); 23028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 23038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x008: case 0x108: case 0x208: case 0x308: /* WPACK */ 23048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x408: case 0x508: case 0x608: case 0x708: 23058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x808: case 0x908: case 0xa08: case 0xb08: 23068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0xc08: case 0xd08: case 0xe08: case 0xf08: 23075285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (!(insn & (1 << 20)) || ((insn >> 22) & 3) == 0) 23085285864985be9077e58e42235af6582dee72e841David 'Digit' Turner return 1; 23098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project wrd = (insn >> 12) & 0xf; 23108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd0 = (insn >> 16) & 0xf; 23118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd1 = (insn >> 0) & 0xf; 23128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_movq_M0_wRn(rd0); 23138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch ((insn >> 22) & 3) { 23148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 1: 23158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 21)) 23168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_packsw_M0_wRn(rd1); 23178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 23188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_packuw_M0_wRn(rd1); 23198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 23208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 2: 23218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 21)) 23228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_packsl_M0_wRn(rd1); 23238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 23248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_packul_M0_wRn(rd1); 23258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 23268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 3: 23278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 21)) 23288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_packsq_M0_wRn(rd1); 23298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 23308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_packuq_M0_wRn(rd1); 23318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 23328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 23338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_movq_wRn_M0(wrd); 23348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_set_mup(); 23358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_set_cup(); 23368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 23378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x201: case 0x203: case 0x205: case 0x207: 23388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x209: case 0x20b: case 0x20d: case 0x20f: 23398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x211: case 0x213: case 0x215: case 0x217: 23408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x219: case 0x21b: case 0x21d: case 0x21f: 23418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project wrd = (insn >> 5) & 0xf; 23428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd0 = (insn >> 12) & 0xf; 23438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd1 = (insn >> 0) & 0xf; 23448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (rd0 == 0xf || rd1 == 0xf) 23458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 23468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_movq_M0_wRn(wrd); 23475285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = load_reg(s, rd0); 23485285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp2 = load_reg(s, rd1); 23498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch ((insn >> 16) & 0xf) { 23508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x0: /* TMIA */ 23515285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_iwmmxt_muladdsl(cpu_M0, cpu_M0, tmp, tmp2); 23528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 23538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x8: /* TMIAPH */ 23545285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_iwmmxt_muladdsw(cpu_M0, cpu_M0, tmp, tmp2); 23558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 23568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0xc: case 0xd: case 0xe: case 0xf: /* TMIAxy */ 23578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 16)) 23585285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_shri_i32(tmp, tmp, 16); 23598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 17)) 23605285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_shri_i32(tmp2, tmp2, 16); 23615285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_iwmmxt_muladdswl(cpu_M0, cpu_M0, tmp, tmp2); 23628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 23638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project default: 23645285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 23655285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 23668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 23678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 23685285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 23695285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 23708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_movq_wRn_M0(wrd); 23718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_set_mup(); 23728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 23738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project default: 23748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 23758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 23768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 23778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 0; 23788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 23798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 23805285864985be9077e58e42235af6582dee72e841David 'Digit' Turner/* Disassemble an XScale DSP instruction. Returns nonzero if an error occurred 23818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project (ie. an undefined instruction). */ 23828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int disas_dsp_insn(CPUState *env, DisasContext *s, uint32_t insn) 23838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 23848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int acc, rd0, rd1, rdhi, rdlo; 23855285864985be9077e58e42235af6582dee72e841David 'Digit' Turner TCGv tmp, tmp2; 23868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 23878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if ((insn & 0x0ff00f10) == 0x0e200010) { 23888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Multiply with Internal Accumulate Format */ 23898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd0 = (insn >> 12) & 0xf; 23908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd1 = insn & 0xf; 23918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project acc = (insn >> 5) & 7; 23928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 23938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (acc != 0) 23948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 23958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 23965285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = load_reg(s, rd0); 23975285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp2 = load_reg(s, rd1); 23988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch ((insn >> 16) & 0xf) { 23998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x0: /* MIA */ 24005285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_iwmmxt_muladdsl(cpu_M0, cpu_M0, tmp, tmp2); 24018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 24028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x8: /* MIAPH */ 24035285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_iwmmxt_muladdsw(cpu_M0, cpu_M0, tmp, tmp2); 24048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 24058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0xc: /* MIABB */ 24068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0xd: /* MIABT */ 24078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0xe: /* MIATB */ 24088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0xf: /* MIATT */ 24098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 16)) 24105285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_shri_i32(tmp, tmp, 16); 24118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 17)) 24125285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_shri_i32(tmp2, tmp2, 16); 24135285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_iwmmxt_muladdswl(cpu_M0, cpu_M0, tmp, tmp2); 24148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 24158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project default: 24168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 24178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 24185285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 24195285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 24208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 24218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_op_iwmmxt_movq_wRn_M0(acc); 24228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 0; 24238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 24248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 24258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if ((insn & 0x0fe00ff8) == 0x0c400000) { 24268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Internal Accumulator Access Format */ 24278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rdhi = (insn >> 16) & 0xf; 24288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rdlo = (insn >> 12) & 0xf; 24298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project acc = insn & 7; 24308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 24318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (acc != 0) 24328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 24338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 24348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & ARM_CP_RW_BIT) { /* MRA */ 24355285864985be9077e58e42235af6582dee72e841David 'Digit' Turner iwmmxt_load_reg(cpu_V0, acc); 24365285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_trunc_i64_i32(cpu_R[rdlo], cpu_V0); 24375285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_shri_i64(cpu_V0, cpu_V0, 32); 24385285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_trunc_i64_i32(cpu_R[rdhi], cpu_V0); 24395285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_andi_i32(cpu_R[rdhi], cpu_R[rdhi], (1 << (40 - 32)) - 1); 24408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { /* MAR */ 24415285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_concat_i32_i64(cpu_V0, cpu_R[rdlo], cpu_R[rdhi]); 24425285864985be9077e58e42235af6582dee72e841David 'Digit' Turner iwmmxt_store_reg(cpu_V0, acc); 24438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 24448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 0; 24458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 24468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 24478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 24488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 24498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 24508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Disassemble system coprocessor instruction. Return nonzero if 24518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project instruction is not defined. */ 24528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int disas_cp_insn(CPUState *env, DisasContext *s, uint32_t insn) 24538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 24545285864985be9077e58e42235af6582dee72e841David 'Digit' Turner TCGv tmp, tmp2; 24558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project uint32_t rd = (insn >> 12) & 0xf; 24568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project uint32_t cp = (insn >> 8) & 0xf; 24578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 24588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & ARM_CP_RW_BIT) { 24598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (!env->cp[cp].cp_read) 24608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 24618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_set_pc_im(s->pc); 24625285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = tcg_temp_new_i32(); 24635285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp2 = tcg_const_i32(insn); 24645285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_get_cp(tmp, cpu_env, tmp2); 24655285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free(tmp2); 24668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project store_reg(s, rd, tmp); 24678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 24688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (!env->cp[cp].cp_write) 24698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 24708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_set_pc_im(s->pc); 24718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_reg(s, rd); 24725285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp2 = tcg_const_i32(insn); 24735285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_set_cp(cpu_env, tmp2, tmp); 24745285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free(tmp2); 24755285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 24768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 24778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 0; 24788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 24798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 24808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int cp15_user_ok(uint32_t insn) 24818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 24828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int cpn = (insn >> 16) & 0xf; 24838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int cpm = insn & 0xf; 24848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int op = ((insn >> 5) & 7) | ((insn >> 18) & 0x38); 24858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 24868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (cpn == 13 && cpm == 0) { 24878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* TLS register. */ 24888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (op == 2 || (op == 3 && (insn & ARM_CP_RW_BIT))) 24898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 24908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 24918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (cpn == 7) { 24928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* ISB, DSB, DMB. */ 24938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if ((cpm == 5 && op == 4) 24948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project || (cpm == 10 && (op == 4 || op == 5))) 24958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 24968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 24978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 0; 24988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 24998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 25005285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic int cp15_tls_load_store(CPUState *env, DisasContext *s, uint32_t insn, uint32_t rd) 25015285864985be9077e58e42235af6582dee72e841David 'Digit' Turner{ 25025285864985be9077e58e42235af6582dee72e841David 'Digit' Turner TCGv tmp; 25035285864985be9077e58e42235af6582dee72e841David 'Digit' Turner int cpn = (insn >> 16) & 0xf; 25045285864985be9077e58e42235af6582dee72e841David 'Digit' Turner int cpm = insn & 0xf; 25055285864985be9077e58e42235af6582dee72e841David 'Digit' Turner int op = ((insn >> 5) & 7) | ((insn >> 18) & 0x38); 25065285864985be9077e58e42235af6582dee72e841David 'Digit' Turner 25075285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (!arm_feature(env, ARM_FEATURE_V6K)) 25085285864985be9077e58e42235af6582dee72e841David 'Digit' Turner return 0; 25095285864985be9077e58e42235af6582dee72e841David 'Digit' Turner 25105285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (!(cpn == 13 && cpm == 0)) 25115285864985be9077e58e42235af6582dee72e841David 'Digit' Turner return 0; 25125285864985be9077e58e42235af6582dee72e841David 'Digit' Turner 25135285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (insn & ARM_CP_RW_BIT) { 25145285864985be9077e58e42235af6582dee72e841David 'Digit' Turner switch (op) { 25155285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 2: 25165285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = load_cpu_field(cp15.c13_tls1); 25175285864985be9077e58e42235af6582dee72e841David 'Digit' Turner break; 25185285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 3: 25195285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = load_cpu_field(cp15.c13_tls2); 25205285864985be9077e58e42235af6582dee72e841David 'Digit' Turner break; 25215285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 4: 25225285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = load_cpu_field(cp15.c13_tls3); 25235285864985be9077e58e42235af6582dee72e841David 'Digit' Turner break; 25245285864985be9077e58e42235af6582dee72e841David 'Digit' Turner default: 25255285864985be9077e58e42235af6582dee72e841David 'Digit' Turner return 0; 25265285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 25275285864985be9077e58e42235af6582dee72e841David 'Digit' Turner store_reg(s, rd, tmp); 25285285864985be9077e58e42235af6582dee72e841David 'Digit' Turner 25295285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } else { 25305285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = load_reg(s, rd); 25315285864985be9077e58e42235af6582dee72e841David 'Digit' Turner switch (op) { 25325285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 2: 25335285864985be9077e58e42235af6582dee72e841David 'Digit' Turner store_cpu_field(tmp, cp15.c13_tls1); 25345285864985be9077e58e42235af6582dee72e841David 'Digit' Turner break; 25355285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 3: 25365285864985be9077e58e42235af6582dee72e841David 'Digit' Turner store_cpu_field(tmp, cp15.c13_tls2); 25375285864985be9077e58e42235af6582dee72e841David 'Digit' Turner break; 25385285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 4: 25395285864985be9077e58e42235af6582dee72e841David 'Digit' Turner store_cpu_field(tmp, cp15.c13_tls3); 25405285864985be9077e58e42235af6582dee72e841David 'Digit' Turner break; 25415285864985be9077e58e42235af6582dee72e841David 'Digit' Turner default: 25425285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 25435285864985be9077e58e42235af6582dee72e841David 'Digit' Turner return 0; 25445285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 25455285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 25465285864985be9077e58e42235af6582dee72e841David 'Digit' Turner return 1; 25475285864985be9077e58e42235af6582dee72e841David 'Digit' Turner} 25485285864985be9077e58e42235af6582dee72e841David 'Digit' Turner 25498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Disassemble system coprocessor (cp15) instruction. Return nonzero if 25508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project instruction is not defined. */ 25518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int disas_cp15_insn(CPUState *env, DisasContext *s, uint32_t insn) 25528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 25538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project uint32_t rd; 25545285864985be9077e58e42235af6582dee72e841David 'Digit' Turner TCGv tmp, tmp2; 25558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 25568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* M profile cores use memory mapped registers instead of cp15. */ 25578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (arm_feature(env, ARM_FEATURE_M)) 25588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 25598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 25608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if ((insn & (1 << 25)) == 0) { 25618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 20)) { 25628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* mrrc */ 25638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 25648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 25658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* mcrr. Used for block cache operations, so implement as no-op. */ 25668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 0; 25678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 25688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if ((insn & (1 << 4)) == 0) { 25698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* cdp */ 25708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 25718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 25728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (IS_USER(s) && !cp15_user_ok(insn)) { 25738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 25748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 25755285864985be9077e58e42235af6582dee72e841David 'Digit' Turner 25765285864985be9077e58e42235af6582dee72e841David 'Digit' Turner /* Pre-v7 versions of the architecture implemented WFI via coprocessor 25775285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * instructions rather than a separate instruction. 25785285864985be9077e58e42235af6582dee72e841David 'Digit' Turner */ 25795285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if ((insn & 0x0fff0fff) == 0x0e070f90) { 25805285864985be9077e58e42235af6582dee72e841David 'Digit' Turner /* 0,c7,c0,4: Standard v6 WFI (also used in some pre-v6 cores). 25815285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * In v7, this must NOP. 25825285864985be9077e58e42235af6582dee72e841David 'Digit' Turner */ 25835285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (!arm_feature(env, ARM_FEATURE_V7)) { 25845285864985be9077e58e42235af6582dee72e841David 'Digit' Turner /* Wait for interrupt. */ 25855285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_set_pc_im(s->pc); 25865285864985be9077e58e42235af6582dee72e841David 'Digit' Turner s->is_jmp = DISAS_WFI; 25875285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 25888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 0; 25898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 25905285864985be9077e58e42235af6582dee72e841David 'Digit' Turner 25915285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if ((insn & 0x0fff0fff) == 0x0e070f58) { 25925285864985be9077e58e42235af6582dee72e841David 'Digit' Turner /* 0,c7,c8,2: Not all pre-v6 cores implemented this WFI, 25935285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * so this is slightly over-broad. 25945285864985be9077e58e42235af6582dee72e841David 'Digit' Turner */ 25955285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (!arm_feature(env, ARM_FEATURE_V6)) { 25965285864985be9077e58e42235af6582dee72e841David 'Digit' Turner /* Wait for interrupt. */ 25975285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_set_pc_im(s->pc); 25985285864985be9077e58e42235af6582dee72e841David 'Digit' Turner s->is_jmp = DISAS_WFI; 25995285864985be9077e58e42235af6582dee72e841David 'Digit' Turner return 0; 26005285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 26015285864985be9077e58e42235af6582dee72e841David 'Digit' Turner /* Otherwise fall through to handle via helper function. 26025285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * In particular, on v7 and some v6 cores this is one of 26035285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * the VA-PA registers. 26045285864985be9077e58e42235af6582dee72e841David 'Digit' Turner */ 26055285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 26065285864985be9077e58e42235af6582dee72e841David 'Digit' Turner 26078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd = (insn >> 12) & 0xf; 26085285864985be9077e58e42235af6582dee72e841David 'Digit' Turner 26095285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (cp15_tls_load_store(env, s, insn, rd)) 26105285864985be9077e58e42235af6582dee72e841David 'Digit' Turner return 0; 26115285864985be9077e58e42235af6582dee72e841David 'Digit' Turner 26125285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp2 = tcg_const_i32(insn); 26138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & ARM_CP_RW_BIT) { 26145285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = tcg_temp_new_i32(); 26155285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_get_cp15(tmp, cpu_env, tmp2); 26168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* If the destination register is r15 then sets condition codes. */ 26178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (rd != 15) 26188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project store_reg(s, rd, tmp); 26198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 26205285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 26218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 26228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_reg(s, rd); 26235285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_set_cp15(cpu_env, tmp2, tmp); 26245285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 26258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Normally we would always end the TB here, but Linux 26268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * arch/arm/mach-pxa/sleep.S expects two instructions following 26278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * an MMU enable to execute from cache. Imitate this behaviour. */ 26288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (!arm_feature(env, ARM_FEATURE_XSCALE) || 26298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project (insn & 0x0fff0fff) != 0x0e010f10) 26308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_lookup_tb(s); 26318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 26325285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 26338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 0; 26348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 26358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 26368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define VFP_REG_SHR(x, n) (((n) > 0) ? (x) >> (n) : (x) << -(n)) 26378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define VFP_SREG(insn, bigbit, smallbit) \ 26388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ((VFP_REG_SHR(insn, bigbit - 1) & 0x1e) | (((insn) >> (smallbit)) & 1)) 26398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define VFP_DREG(reg, insn, bigbit, smallbit) do { \ 26408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (arm_feature(env, ARM_FEATURE_VFP3)) { \ 26418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project reg = (((insn) >> (bigbit)) & 0x0f) \ 26428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project | (((insn) >> ((smallbit) - 4)) & 0x10); \ 26438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { \ 26448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << (smallbit))) \ 26458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; \ 26468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project reg = ((insn) >> (bigbit)) & 0x0f; \ 26478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project }} while (0) 26488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 26498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define VFP_SREG_D(insn) VFP_SREG(insn, 12, 22) 26508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define VFP_DREG_D(reg, insn) VFP_DREG(reg, insn, 12, 22) 26518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define VFP_SREG_N(insn) VFP_SREG(insn, 16, 7) 26528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define VFP_DREG_N(reg, insn) VFP_DREG(reg, insn, 16, 7) 26538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define VFP_SREG_M(insn) VFP_SREG(insn, 0, 5) 26548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define VFP_DREG_M(reg, insn) VFP_DREG(reg, insn, 0, 5) 26558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 26568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Move between integer and VFP cores. */ 26578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic TCGv gen_vfp_mrs(void) 26588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 26595285864985be9077e58e42235af6582dee72e841David 'Digit' Turner TCGv tmp = tcg_temp_new_i32(); 26608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_mov_i32(tmp, cpu_F0s); 26618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return tmp; 26628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 26638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 26648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void gen_vfp_msr(TCGv tmp) 26658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 26668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_mov_i32(cpu_F0s, tmp); 26675285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 26688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 26698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 26708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void gen_neon_dup_u8(TCGv var, int shift) 26718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 26725285864985be9077e58e42235af6582dee72e841David 'Digit' Turner TCGv tmp = tcg_temp_new_i32(); 26738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (shift) 26748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_shri_i32(var, var, shift); 26758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_ext8u_i32(var, var); 26768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_shli_i32(tmp, var, 8); 26778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_or_i32(var, var, tmp); 26788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_shli_i32(tmp, var, 16); 26798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_or_i32(var, var, tmp); 26805285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 26818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 26828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 26838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void gen_neon_dup_low16(TCGv var) 26848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 26855285864985be9077e58e42235af6582dee72e841David 'Digit' Turner TCGv tmp = tcg_temp_new_i32(); 26868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_ext16u_i32(var, var); 26878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_shli_i32(tmp, var, 16); 26888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_or_i32(var, var, tmp); 26895285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 26908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 26918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 26928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void gen_neon_dup_high16(TCGv var) 26938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 26945285864985be9077e58e42235af6582dee72e841David 'Digit' Turner TCGv tmp = tcg_temp_new_i32(); 26958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_andi_i32(var, var, 0xffff0000); 26968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_shri_i32(tmp, var, 16); 26978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_or_i32(var, var, tmp); 26985285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 26995285864985be9077e58e42235af6582dee72e841David 'Digit' Turner} 27005285864985be9077e58e42235af6582dee72e841David 'Digit' Turner 27015285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic TCGv gen_load_and_replicate(DisasContext *s, TCGv addr, int size) 27025285864985be9077e58e42235af6582dee72e841David 'Digit' Turner{ 27035285864985be9077e58e42235af6582dee72e841David 'Digit' Turner /* Load a single Neon element and replicate into a 32 bit TCG reg */ 27045285864985be9077e58e42235af6582dee72e841David 'Digit' Turner TCGv tmp; 27055285864985be9077e58e42235af6582dee72e841David 'Digit' Turner switch (size) { 27065285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 0: 27075285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = gen_ld8u(addr, IS_USER(s)); 27085285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_neon_dup_u8(tmp, 0); 27095285864985be9077e58e42235af6582dee72e841David 'Digit' Turner break; 27105285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 1: 27115285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = gen_ld16u(addr, IS_USER(s)); 27125285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_neon_dup_low16(tmp); 27135285864985be9077e58e42235af6582dee72e841David 'Digit' Turner break; 27145285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 2: 27155285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = gen_ld32(addr, IS_USER(s)); 27165285864985be9077e58e42235af6582dee72e841David 'Digit' Turner break; 27175285864985be9077e58e42235af6582dee72e841David 'Digit' Turner default: /* Avoid compiler warnings. */ 27185285864985be9077e58e42235af6582dee72e841David 'Digit' Turner abort(); 27195285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 27205285864985be9077e58e42235af6582dee72e841David 'Digit' Turner return tmp; 27218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 27228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 27235285864985be9077e58e42235af6582dee72e841David 'Digit' Turner/* Disassemble a VFP instruction. Returns nonzero if an error occurred 27248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project (ie. an undefined instruction). */ 27258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int disas_vfp_insn(CPUState * env, DisasContext *s, uint32_t insn) 27268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 27278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project uint32_t rd, rn, rm, op, i, n, offset, delta_d, delta_m, bank_mask; 27288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int dp, veclen; 27295285864985be9077e58e42235af6582dee72e841David 'Digit' Turner TCGv addr; 27308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project TCGv tmp; 27318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project TCGv tmp2; 27328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 27338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (!arm_feature(env, ARM_FEATURE_VFP)) 27348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 27358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 27365285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (!s->vfp_enabled) { 27378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* VFP disabled. Only allow fmxr/fmrx to/from some control regs. */ 27388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if ((insn & 0x0fe00fff) != 0x0ee00a10) 27398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 27408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rn = (insn >> 16) & 0xf; 27418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (rn != ARM_VFP_FPSID && rn != ARM_VFP_FPEXC 27428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project && rn != ARM_VFP_MVFR1 && rn != ARM_VFP_MVFR0) 27438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 27448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 27458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project dp = ((insn & 0xf00) == 0xb00); 27468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch ((insn >> 24) & 0xf) { 27478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0xe: 27488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 4)) { 27498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* single register transfer */ 27508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd = (insn >> 12) & 0xf; 27518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (dp) { 27528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int size; 27538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int pass; 27548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 27558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project VFP_DREG_N(rn, insn); 27568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & 0xf) 27578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 27588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & 0x00c00060 27598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project && !arm_feature(env, ARM_FEATURE_NEON)) 27608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 27618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 27628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project pass = (insn >> 21) & 1; 27638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 22)) { 27648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project size = 0; 27658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project offset = ((insn >> 5) & 3) * 8; 27668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else if (insn & (1 << 5)) { 27678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project size = 1; 27688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project offset = (insn & (1 << 6)) ? 16 : 0; 27698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 27708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project size = 2; 27718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project offset = 0; 27728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 27738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & ARM_CP_RW_BIT) { 27748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* vfp->arm */ 27758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = neon_load_reg(rn, pass); 27768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (size) { 27778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0: 27788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (offset) 27798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_shri_i32(tmp, tmp, offset); 27808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 23)) 27818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_uxtb(tmp); 27828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 27838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_sxtb(tmp); 27848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 27858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 1: 27868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 23)) { 27878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (offset) { 27888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_shri_i32(tmp, tmp, 16); 27898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 27908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_uxth(tmp); 27918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 27928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 27938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (offset) { 27948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_sari_i32(tmp, tmp, 16); 27958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 27968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_sxth(tmp); 27978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 27988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 27998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 28008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 2: 28018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 28028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 28038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project store_reg(s, rd, tmp); 28048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 28058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* arm->vfp */ 28068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_reg(s, rd); 28078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 23)) { 28088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* VDUP */ 28098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (size == 0) { 28108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_neon_dup_u8(tmp, 0); 28118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else if (size == 1) { 28128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_neon_dup_low16(tmp); 28138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 28145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner for (n = 0; n <= pass * 2; n++) { 28155285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp2 = tcg_temp_new_i32(); 28165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tcg_gen_mov_i32(tmp2, tmp); 28175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner neon_store_reg(rn, n, tmp2); 28185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 28195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner neon_store_reg(rn, n, tmp); 28208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 28218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* VMOV */ 28228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (size) { 28238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0: 28248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp2 = neon_load_reg(rn, pass); 28258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_bfi(tmp, tmp2, tmp, offset, 0xff); 28265285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 28278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 28288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 1: 28298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp2 = neon_load_reg(rn, pass); 28308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_bfi(tmp, tmp2, tmp, offset, 0xffff); 28315285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 28328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 28338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 2: 28348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 28358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 28368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project neon_store_reg(rn, pass, tmp); 28378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 28388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 28398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { /* !dp */ 28408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if ((insn & 0x6f) != 0x00) 28418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 28428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rn = VFP_SREG_N(insn); 28438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & ARM_CP_RW_BIT) { 28448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* vfp->arm */ 28458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 21)) { 28468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* system register */ 28478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rn >>= 1; 28488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 28498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (rn) { 28508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case ARM_VFP_FPSID: 28518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* VFP2 allows access to FSID from userspace. 28528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project VFP3 restricts all id registers to privileged 28538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project accesses. */ 28548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (IS_USER(s) 28558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project && arm_feature(env, ARM_FEATURE_VFP3)) 28568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 28578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_cpu_field(vfp.xregs[rn]); 28588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 28598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case ARM_VFP_FPEXC: 28608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (IS_USER(s)) 28618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 28628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_cpu_field(vfp.xregs[rn]); 28638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 28648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case ARM_VFP_FPINST: 28658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case ARM_VFP_FPINST2: 28668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Not present in VFP3. */ 28678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (IS_USER(s) 28688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project || arm_feature(env, ARM_FEATURE_VFP3)) 28698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 28708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_cpu_field(vfp.xregs[rn]); 28718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 28728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case ARM_VFP_FPSCR: 28738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (rd == 15) { 28748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_cpu_field(vfp.xregs[ARM_VFP_FPSCR]); 28758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_andi_i32(tmp, tmp, 0xf0000000); 28768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 28775285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = tcg_temp_new_i32(); 28788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_helper_vfp_get_fpscr(tmp, cpu_env); 28798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 28808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 28818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case ARM_VFP_MVFR0: 28828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case ARM_VFP_MVFR1: 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 default: 28898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 28908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 28918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 28928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_mov_F0_vreg(0, rn); 28938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = gen_vfp_mrs(); 28948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 28958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (rd == 15) { 28968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Set the 4 flag bits in the CPSR. */ 28978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_set_nzcv(tmp); 28985285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 28998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 29008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project store_reg(s, rd, tmp); 29018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 29028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 29038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* arm->vfp */ 29048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_reg(s, rd); 29058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 21)) { 29068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rn >>= 1; 29078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* system register */ 29088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (rn) { 29098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case ARM_VFP_FPSID: 29108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case ARM_VFP_MVFR0: 29118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case ARM_VFP_MVFR1: 29128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Writes are ignored. */ 29138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 29148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case ARM_VFP_FPSCR: 29158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_helper_vfp_set_fpscr(cpu_env, tmp); 29165285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 29178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_lookup_tb(s); 29188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 29198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case ARM_VFP_FPEXC: 29208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (IS_USER(s)) 29218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 29225285864985be9077e58e42235af6582dee72e841David 'Digit' Turner /* TODO: VFP subarchitecture support. 29235285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * For now, keep the EN bit only */ 29245285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_andi_i32(tmp, tmp, 1 << 30); 29258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project store_cpu_field(tmp, vfp.xregs[rn]); 29268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_lookup_tb(s); 29278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 29288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case ARM_VFP_FPINST: 29298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case ARM_VFP_FPINST2: 29308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project store_cpu_field(tmp, vfp.xregs[rn]); 29318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 29328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project default: 29338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 29348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 29358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 29368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_vfp_msr(tmp); 29378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_mov_vreg_F0(0, rn); 29388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 29398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 29408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 29418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 29428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* data processing */ 29438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* The opcode is in bits 23, 21, 20 and 6. */ 29448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project op = ((insn >> 20) & 8) | ((insn >> 19) & 6) | ((insn >> 6) & 1); 29458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (dp) { 29468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (op == 15) { 29478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* rn is opcode */ 29488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rn = ((insn >> 15) & 0x1e) | ((insn >> 7) & 1); 29498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 29508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* rn is register number */ 29518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project VFP_DREG_N(rn, insn); 29528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 29538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 29545285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (op == 15 && (rn == 15 || ((rn & 0x1c) == 0x18))) { 29558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Integer or single precision destination. */ 29568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd = VFP_SREG_D(insn); 29578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 29588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project VFP_DREG_D(rd, insn); 29598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 29605285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (op == 15 && 29615285864985be9077e58e42235af6582dee72e841David 'Digit' Turner (((rn & 0x1c) == 0x10) || ((rn & 0x14) == 0x14))) { 29625285864985be9077e58e42235af6582dee72e841David 'Digit' Turner /* VCVT from int is always from S reg regardless of dp bit. 29635285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * VCVT with immediate frac_bits has same format as SREG_M 29645285864985be9077e58e42235af6582dee72e841David 'Digit' Turner */ 29655285864985be9077e58e42235af6582dee72e841David 'Digit' Turner rm = VFP_SREG_M(insn); 29668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 29678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project VFP_DREG_M(rm, insn); 29688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 29698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 29708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rn = VFP_SREG_N(insn); 29718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (op == 15 && rn == 15) { 29728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Double precision destination. */ 29738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project VFP_DREG_D(rd, insn); 29748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 29758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd = VFP_SREG_D(insn); 29768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 29775285864985be9077e58e42235af6582dee72e841David 'Digit' Turner /* NB that we implicitly rely on the encoding for the frac_bits 29785285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * in VCVT of fixed to float being the same as that of an SREG_M 29795285864985be9077e58e42235af6582dee72e841David 'Digit' Turner */ 29808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rm = VFP_SREG_M(insn); 29818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 29828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 29835285864985be9077e58e42235af6582dee72e841David 'Digit' Turner veclen = s->vec_len; 29848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (op == 15 && rn > 3) 29858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project veclen = 0; 29868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 29878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Shut up compiler warnings. */ 29888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project delta_m = 0; 29898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project delta_d = 0; 29908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project bank_mask = 0; 29918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 29928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (veclen > 0) { 29938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (dp) 29948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project bank_mask = 0xc; 29958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 29968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project bank_mask = 0x18; 29978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 29988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Figure out what type of vector operation this is. */ 29998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if ((rd & bank_mask) == 0) { 30008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* scalar */ 30018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project veclen = 0; 30028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 30038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (dp) 30045285864985be9077e58e42235af6582dee72e841David 'Digit' Turner delta_d = (s->vec_stride >> 1) + 1; 30058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 30065285864985be9077e58e42235af6582dee72e841David 'Digit' Turner delta_d = s->vec_stride + 1; 30078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 30088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if ((rm & bank_mask) == 0) { 30098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* mixed scalar/vector */ 30108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project delta_m = 0; 30118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 30128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* vector */ 30138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project delta_m = delta_d; 30148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 30158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 30168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 30178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 30188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Load the initial operands. */ 30198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (op == 15) { 30208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (rn) { 30218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 16: 30228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 17: 30238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Integer source */ 30248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_mov_F0_vreg(0, rm); 30258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 30268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 8: 30278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 9: 30288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Compare */ 30298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_mov_F0_vreg(dp, rd); 30308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_mov_F1_vreg(dp, rm); 30318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 30328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 10: 30338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 11: 30348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Compare with zero */ 30358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_mov_F0_vreg(dp, rd); 30368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_vfp_F1_ld0(dp); 30378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 30388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 20: 30398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 21: 30408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 22: 30418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 23: 30425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner case 28: 30435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner case 29: 30445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner case 30: 30455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner case 31: 30468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Source and destination the same. */ 30478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_mov_F0_vreg(dp, rd); 30488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 30498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project default: 30508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* One source operand. */ 30518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_mov_F0_vreg(dp, rm); 30528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 30538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 30548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 30558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Two source operands. */ 30568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_mov_F0_vreg(dp, rn); 30578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_mov_F1_vreg(dp, rm); 30588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 30598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 30608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project for (;;) { 30618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Perform the calculation. */ 30628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (op) { 30635285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 0: /* VMLA: fd + (fn * fm) */ 30645285864985be9077e58e42235af6582dee72e841David 'Digit' Turner /* Note that order of inputs to the add matters for NaNs */ 30655285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_vfp_F1_mul(dp); 30665285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_mov_F0_vreg(dp, rd); 30678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_vfp_add(dp); 30688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 30695285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 1: /* VMLS: fd + -(fn * fm) */ 30708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_vfp_mul(dp); 30715285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_vfp_F1_neg(dp); 30725285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_mov_F0_vreg(dp, rd); 30738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_vfp_add(dp); 30748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 30755285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 2: /* VNMLS: -fd + (fn * fm) */ 30765285864985be9077e58e42235af6582dee72e841David 'Digit' Turner /* Note that it isn't valid to replace (-A + B) with (B - A) 30775285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * or similar plausible looking simplifications 30785285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * because this will give wrong results for NaNs. 30795285864985be9077e58e42235af6582dee72e841David 'Digit' Turner */ 30805285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_vfp_F1_mul(dp); 30815285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_mov_F0_vreg(dp, rd); 30825285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_vfp_neg(dp); 30835285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_vfp_add(dp); 30848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 30855285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 3: /* VNMLA: -fd + -(fn * fm) */ 30868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_vfp_mul(dp); 30875285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_vfp_F1_neg(dp); 30885285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_mov_F0_vreg(dp, rd); 30898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_vfp_neg(dp); 30905285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_vfp_add(dp); 30918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 30928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 4: /* mul: fn * fm */ 30938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_vfp_mul(dp); 30948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 30958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 5: /* nmul: -(fn * fm) */ 30968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_vfp_mul(dp); 30978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_vfp_neg(dp); 30988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 30998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 6: /* add: fn + fm */ 31008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_vfp_add(dp); 31018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 31028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 7: /* sub: fn - fm */ 31038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_vfp_sub(dp); 31048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 31058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 8: /* div: fn / fm */ 31068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_vfp_div(dp); 31078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 31088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 14: /* fconst */ 31098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (!arm_feature(env, ARM_FEATURE_VFP3)) 31108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 31118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 31128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project n = (insn << 12) & 0x80000000; 31138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project i = ((insn >> 12) & 0x70) | (insn & 0xf); 31148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (dp) { 31158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (i & 0x40) 31168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project i |= 0x3f80; 31178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 31188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project i |= 0x4000; 31198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project n |= i << 16; 31208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_movi_i64(cpu_F0d, ((uint64_t)n) << 32); 31218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 31228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (i & 0x40) 31238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project i |= 0x780; 31248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 31258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project i |= 0x800; 31268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project n |= i << 19; 31278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_movi_i32(cpu_F0s, n); 31288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 31298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 31308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 15: /* extension space */ 31318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (rn) { 31328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0: /* cpy */ 31338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* no-op */ 31348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 31358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 1: /* abs */ 31368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_vfp_abs(dp); 31378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 31388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 2: /* neg */ 31398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_vfp_neg(dp); 31408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 31418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 3: /* sqrt */ 31428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_vfp_sqrt(dp); 31438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 31445285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 4: /* vcvtb.f32.f16 */ 31455285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (!arm_feature(env, ARM_FEATURE_VFP_FP16)) 31465285864985be9077e58e42235af6582dee72e841David 'Digit' Turner return 1; 31475285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = gen_vfp_mrs(); 31485285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_ext16u_i32(tmp, tmp); 31495285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s, tmp, cpu_env); 31505285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 31515285864985be9077e58e42235af6582dee72e841David 'Digit' Turner break; 31525285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 5: /* vcvtt.f32.f16 */ 31535285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (!arm_feature(env, ARM_FEATURE_VFP_FP16)) 31545285864985be9077e58e42235af6582dee72e841David 'Digit' Turner return 1; 31555285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = gen_vfp_mrs(); 31565285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_shri_i32(tmp, tmp, 16); 31575285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s, tmp, cpu_env); 31585285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 31595285864985be9077e58e42235af6582dee72e841David 'Digit' Turner break; 31605285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 6: /* vcvtb.f16.f32 */ 31615285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (!arm_feature(env, ARM_FEATURE_VFP_FP16)) 31625285864985be9077e58e42235af6582dee72e841David 'Digit' Turner return 1; 31635285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = tcg_temp_new_i32(); 31645285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_vfp_fcvt_f32_to_f16(tmp, cpu_F0s, cpu_env); 31655285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_mov_F0_vreg(0, rd); 31665285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp2 = gen_vfp_mrs(); 31675285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_andi_i32(tmp2, tmp2, 0xffff0000); 31685285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_or_i32(tmp, tmp, tmp2); 31695285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 31705285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_vfp_msr(tmp); 31715285864985be9077e58e42235af6582dee72e841David 'Digit' Turner break; 31725285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 7: /* vcvtt.f16.f32 */ 31735285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (!arm_feature(env, ARM_FEATURE_VFP_FP16)) 31745285864985be9077e58e42235af6582dee72e841David 'Digit' Turner return 1; 31755285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = tcg_temp_new_i32(); 31765285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_vfp_fcvt_f32_to_f16(tmp, cpu_F0s, cpu_env); 31775285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_shli_i32(tmp, tmp, 16); 31785285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_mov_F0_vreg(0, rd); 31795285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp2 = gen_vfp_mrs(); 31805285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_ext16u_i32(tmp2, tmp2); 31815285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_or_i32(tmp, tmp, tmp2); 31825285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 31835285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_vfp_msr(tmp); 31845285864985be9077e58e42235af6582dee72e841David 'Digit' Turner break; 31858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 8: /* cmp */ 31868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_vfp_cmp(dp); 31878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 31888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 9: /* cmpe */ 31898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_vfp_cmpe(dp); 31908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 31918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 10: /* cmpz */ 31928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_vfp_cmp(dp); 31938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 31948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 11: /* cmpez */ 31958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_vfp_F1_ld0(dp); 31968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_vfp_cmpe(dp); 31978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 31988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 15: /* single<->double conversion */ 31998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (dp) 32008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_helper_vfp_fcvtsd(cpu_F0s, cpu_F0d, cpu_env); 32018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 32028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_helper_vfp_fcvtds(cpu_F0d, cpu_F0s, cpu_env); 32038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 32048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 16: /* fuito */ 32055285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_vfp_uito(dp, 0); 32068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 32078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 17: /* fsito */ 32085285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_vfp_sito(dp, 0); 32098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 32108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 20: /* fshto */ 32118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (!arm_feature(env, ARM_FEATURE_VFP3)) 32128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 32135285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_vfp_shto(dp, 16 - rm, 0); 32148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 32158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 21: /* fslto */ 32168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (!arm_feature(env, ARM_FEATURE_VFP3)) 32178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 32185285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_vfp_slto(dp, 32 - rm, 0); 32198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 32208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 22: /* fuhto */ 32218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (!arm_feature(env, ARM_FEATURE_VFP3)) 32228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 32235285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_vfp_uhto(dp, 16 - rm, 0); 32248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 32258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 23: /* fulto */ 32268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (!arm_feature(env, ARM_FEATURE_VFP3)) 32278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 32285285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_vfp_ulto(dp, 32 - rm, 0); 32298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 32308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 24: /* ftoui */ 32315285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_vfp_toui(dp, 0); 32328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 32338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 25: /* ftouiz */ 32345285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_vfp_touiz(dp, 0); 32358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 32368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 26: /* ftosi */ 32375285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_vfp_tosi(dp, 0); 32388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 32398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 27: /* ftosiz */ 32405285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_vfp_tosiz(dp, 0); 32418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 32428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 28: /* ftosh */ 32438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (!arm_feature(env, ARM_FEATURE_VFP3)) 32448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 32455285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_vfp_tosh(dp, 16 - rm, 0); 32468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 32478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 29: /* ftosl */ 32488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (!arm_feature(env, ARM_FEATURE_VFP3)) 32498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 32505285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_vfp_tosl(dp, 32 - rm, 0); 32518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 32528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 30: /* ftouh */ 32538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (!arm_feature(env, ARM_FEATURE_VFP3)) 32548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 32555285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_vfp_touh(dp, 16 - rm, 0); 32568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 32578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 31: /* ftoul */ 32588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (!arm_feature(env, ARM_FEATURE_VFP3)) 32598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 32605285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_vfp_toul(dp, 32 - rm, 0); 32618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 32628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project default: /* undefined */ 32638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project printf ("rn:%d\n", rn); 32648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 32658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 32668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 32678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project default: /* undefined */ 32688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project printf ("op:%d\n", op); 32698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 32708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 32718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 32728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Write back the result. */ 32738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (op == 15 && (rn >= 8 && rn <= 11)) 32748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ; /* Comparison, do nothing. */ 32755285864985be9077e58e42235af6582dee72e841David 'Digit' Turner else if (op == 15 && dp && ((rn & 0x1c) == 0x18)) 32765285864985be9077e58e42235af6582dee72e841David 'Digit' Turner /* VCVT double to int: always integer result. */ 32778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_mov_vreg_F0(0, rd); 32788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else if (op == 15 && rn == 15) 32798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* conversion */ 32808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_mov_vreg_F0(!dp, rd); 32818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 32828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_mov_vreg_F0(dp, rd); 32838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 32848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* break out of the loop if we have finished */ 32858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (veclen == 0) 32868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 32878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 32888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (op == 15 && delta_m == 0) { 32898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* single source one-many */ 32908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project while (veclen--) { 32918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd = ((rd + delta_d) & (bank_mask - 1)) 32928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project | (rd & bank_mask); 32938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_mov_vreg_F0(dp, rd); 32948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 32958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 32968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 32978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Setup the next operands. */ 32988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project veclen--; 32998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd = ((rd + delta_d) & (bank_mask - 1)) 33008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project | (rd & bank_mask); 33018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 33028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (op == 15) { 33038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* One source operand. */ 33048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rm = ((rm + delta_m) & (bank_mask - 1)) 33058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project | (rm & bank_mask); 33068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_mov_F0_vreg(dp, rm); 33078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 33088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Two source operands. */ 33098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rn = ((rn + delta_d) & (bank_mask - 1)) 33108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project | (rn & bank_mask); 33118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_mov_F0_vreg(dp, rn); 33128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (delta_m) { 33138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rm = ((rm + delta_m) & (bank_mask - 1)) 33148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project | (rm & bank_mask); 33158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_mov_F1_vreg(dp, rm); 33168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 33178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 33188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 33198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 33208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 33218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0xc: 33228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0xd: 33235285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if ((insn & 0x03e00000) == 0x00400000) { 33248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* two-register transfer */ 33258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rn = (insn >> 16) & 0xf; 33268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd = (insn >> 12) & 0xf; 33278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (dp) { 33288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project VFP_DREG_M(rm, insn); 33298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 33308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rm = VFP_SREG_M(insn); 33318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 33328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 33338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & ARM_CP_RW_BIT) { 33348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* vfp->arm */ 33358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (dp) { 33368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_mov_F0_vreg(0, rm * 2); 33378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = gen_vfp_mrs(); 33388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project store_reg(s, rd, tmp); 33398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_mov_F0_vreg(0, rm * 2 + 1); 33408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = gen_vfp_mrs(); 33418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project store_reg(s, rn, tmp); 33428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 33438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_mov_F0_vreg(0, rm); 33448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = gen_vfp_mrs(); 33455285864985be9077e58e42235af6582dee72e841David 'Digit' Turner store_reg(s, rd, tmp); 33468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_mov_F0_vreg(0, rm + 1); 33478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = gen_vfp_mrs(); 33485285864985be9077e58e42235af6582dee72e841David 'Digit' Turner store_reg(s, rn, tmp); 33498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 33508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 33518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* arm->vfp */ 33528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (dp) { 33538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_reg(s, rd); 33548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_vfp_msr(tmp); 33558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_mov_vreg_F0(0, rm * 2); 33568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_reg(s, rn); 33578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_vfp_msr(tmp); 33588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_mov_vreg_F0(0, rm * 2 + 1); 33598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 33605285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = load_reg(s, rd); 33618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_vfp_msr(tmp); 33628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_mov_vreg_F0(0, rm); 33635285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = load_reg(s, rn); 33648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_vfp_msr(tmp); 33658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_mov_vreg_F0(0, rm + 1); 33668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 33678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 33688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 33698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Load/store */ 33708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rn = (insn >> 16) & 0xf; 33718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (dp) 33728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project VFP_DREG_D(rd, insn); 33738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 33748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd = VFP_SREG_D(insn); 33758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (s->thumb && rn == 15) { 33765285864985be9077e58e42235af6582dee72e841David 'Digit' Turner addr = tcg_temp_new_i32(); 33775285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_movi_i32(addr, s->pc & ~2); 33788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 33795285864985be9077e58e42235af6582dee72e841David 'Digit' Turner addr = load_reg(s, rn); 33808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 33818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if ((insn & 0x01200000) == 0x01000000) { 33828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Single load/store */ 33838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project offset = (insn & 0xff) << 2; 33848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if ((insn & (1 << 23)) == 0) 33858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project offset = -offset; 33865285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_addi_i32(addr, addr, offset); 33878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 20)) { 33885285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_vfp_ld(s, dp, addr); 33898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_mov_vreg_F0(dp, rd); 33908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 33918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_mov_F0_vreg(dp, rd); 33925285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_vfp_st(s, dp, addr); 33938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 33945285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(addr); 33958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 33968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* load/store multiple */ 33978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (dp) 33988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project n = (insn >> 1) & 0x7f; 33998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 34008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project n = insn & 0xff; 34018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 34028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 24)) /* pre-decrement */ 34035285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_addi_i32(addr, addr, -((insn & 0xff) << 2)); 34048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 34058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (dp) 34068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project offset = 8; 34078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 34088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project offset = 4; 34095285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = tcg_const_i32(offset); 34108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project for (i = 0; i < n; i++) { 34118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & ARM_CP_RW_BIT) { 34128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* load */ 34135285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_vfp_ld(s, dp, addr); 34148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_mov_vreg_F0(dp, rd + i); 34158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 34168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* store */ 34178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_mov_F0_vreg(dp, rd + i); 34185285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_vfp_st(s, dp, addr); 34198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 34205285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_add_i32(addr, addr, tmp); 34218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 34225285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 34238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 21)) { 34248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* writeback */ 34258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 24)) 34268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project offset = -offset * n; 34278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else if (dp && (insn & 1)) 34288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project offset = 4; 34298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 34308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project offset = 0; 34318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 34328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (offset != 0) 34335285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_addi_i32(addr, addr, offset); 34345285864985be9077e58e42235af6582dee72e841David 'Digit' Turner store_reg(s, rn, addr); 34355285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } else { 34365285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(addr); 34378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 34388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 34398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 34408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 34418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project default: 34428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Should never happen. */ 34438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 34448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 34458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 0; 34468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 34478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 34488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline void gen_goto_tb(DisasContext *s, int n, uint32_t dest) 34498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 34508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project TranslationBlock *tb; 34518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 34528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tb = s->tb; 34538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)) { 34548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_goto_tb(n); 34558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_set_pc_im(dest); 34565285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_exit_tb((tcg_target_long)tb + n); 34578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 34588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_set_pc_im(dest); 34598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_exit_tb(0); 34608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 34618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 34628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 34638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline void gen_jmp (DisasContext *s, uint32_t dest) 34648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 34658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (unlikely(s->singlestep_enabled)) { 34668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* An indirect jump so that we still trigger the debug exception. */ 34678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (s->thumb) 34688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project dest |= 1; 34698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_bx_im(s, dest); 34708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 34718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_goto_tb(s, 0, dest); 34728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project s->is_jmp = DISAS_TB_JUMP; 34738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 34748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 34758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 34768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline void gen_mulxy(TCGv t0, TCGv t1, int x, int y) 34778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 34788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (x) 34798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_sari_i32(t0, t0, 16); 34808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 34818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_sxth(t0); 34828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (y) 34838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_sari_i32(t1, t1, 16); 34848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 34858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_sxth(t1); 34868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_mul_i32(t0, t0, t1); 34878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 34888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 34898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Return the mask of PSR bits set by a MSR instruction. */ 34908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic uint32_t msr_mask(CPUState *env, DisasContext *s, int flags, int spsr) { 34918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project uint32_t mask; 34928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 34938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project mask = 0; 34948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (flags & (1 << 0)) 34958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project mask |= 0xff; 34968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (flags & (1 << 1)) 34978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project mask |= 0xff00; 34988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (flags & (1 << 2)) 34998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project mask |= 0xff0000; 35008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (flags & (1 << 3)) 35018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project mask |= 0xff000000; 35028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 35038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Mask out undefined bits. */ 35048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project mask &= ~CPSR_RESERVED; 35055285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (!arm_feature(env, ARM_FEATURE_V4T)) 35065285864985be9077e58e42235af6582dee72e841David 'Digit' Turner mask &= ~CPSR_T; 35075285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (!arm_feature(env, ARM_FEATURE_V5)) 35085285864985be9077e58e42235af6582dee72e841David 'Digit' Turner mask &= ~CPSR_Q; /* V5TE in reality*/ 35098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (!arm_feature(env, ARM_FEATURE_V6)) 35108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project mask &= ~(CPSR_E | CPSR_GE); 35118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (!arm_feature(env, ARM_FEATURE_THUMB2)) 35128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project mask &= ~CPSR_IT; 35138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Mask out execution state bits. */ 35148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (!spsr) 35158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project mask &= ~CPSR_EXEC; 35168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Mask out privileged bits. */ 35178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (IS_USER(s)) 35188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project mask &= CPSR_USER; 35198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return mask; 35208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 35218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 35225285864985be9077e58e42235af6582dee72e841David 'Digit' Turner/* Returns nonzero if access to the PSR is not permitted. Marks t0 as dead. */ 35235285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic int gen_set_psr(DisasContext *s, uint32_t mask, int spsr, TCGv t0) 35248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 35258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project TCGv tmp; 35268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (spsr) { 35278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* ??? This is also undefined in system mode. */ 35288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (IS_USER(s)) 35298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 35308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 35318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_cpu_field(spsr); 35328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_andi_i32(tmp, tmp, ~mask); 35335285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_andi_i32(t0, t0, mask); 35345285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_or_i32(tmp, tmp, t0); 35358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project store_cpu_field(tmp, spsr); 35368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 35375285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_set_cpsr(t0, mask); 35388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 35395285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(t0); 35408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_lookup_tb(s); 35418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 0; 35428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 35438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 35445285864985be9077e58e42235af6582dee72e841David 'Digit' Turner/* Returns nonzero if access to the PSR is not permitted. */ 35455285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic int gen_set_psr_im(DisasContext *s, uint32_t mask, int spsr, uint32_t val) 35465285864985be9077e58e42235af6582dee72e841David 'Digit' Turner{ 35475285864985be9077e58e42235af6582dee72e841David 'Digit' Turner TCGv tmp; 35485285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = tcg_temp_new_i32(); 35495285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_movi_i32(tmp, val); 35505285864985be9077e58e42235af6582dee72e841David 'Digit' Turner return gen_set_psr(s, mask, spsr, tmp); 35515285864985be9077e58e42235af6582dee72e841David 'Digit' Turner} 35525285864985be9077e58e42235af6582dee72e841David 'Digit' Turner 35535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner/* Generate an old-style exception return. Marks pc as dead. */ 35545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void gen_exception_return(DisasContext *s, TCGv pc) 35558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 35568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project TCGv tmp; 35575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner store_reg(s, 15, pc); 35588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_cpu_field(spsr); 35598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_set_cpsr(tmp, 0xffffffff); 35605285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 35618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project s->is_jmp = DISAS_UPDATE; 35628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 35638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 35648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Generate a v6 exception return. Marks both values as dead. */ 35658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void gen_rfe(DisasContext *s, TCGv pc, TCGv cpsr) 35668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 35678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_set_cpsr(cpsr, 0xffffffff); 35685285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(cpsr); 35698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project store_reg(s, 15, pc); 35708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project s->is_jmp = DISAS_UPDATE; 35718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 35728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 35738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline void 35748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectgen_set_condexec (DisasContext *s) 35758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 3576a1204591a52bf668ee72c86f98f53189621572a2Vladimir Chtchetkine if (s->condexec_mask) { 3577a1204591a52bf668ee72c86f98f53189621572a2Vladimir Chtchetkine uint32_t val = (s->condexec_cond << 4) | (s->condexec_mask >> 1); 35785285864985be9077e58e42235af6582dee72e841David 'Digit' Turner TCGv tmp = tcg_temp_new_i32(); 3579a1204591a52bf668ee72c86f98f53189621572a2Vladimir Chtchetkine tcg_gen_movi_i32(tmp, val); 3580a1204591a52bf668ee72c86f98f53189621572a2Vladimir Chtchetkine store_cpu_field(tmp, condexec_bits); 3581a1204591a52bf668ee72c86f98f53189621572a2Vladimir Chtchetkine } 35825285864985be9077e58e42235af6582dee72e841David 'Digit' Turner} 35835285864985be9077e58e42235af6582dee72e841David 'Digit' Turner 35845285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic void gen_exception_insn(DisasContext *s, int offset, int excp) 35855285864985be9077e58e42235af6582dee72e841David 'Digit' Turner{ 35865285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_set_condexec(s); 35875285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_set_pc_im(s->pc - offset); 35885285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_exception(excp); 35895285864985be9077e58e42235af6582dee72e841David 'Digit' Turner s->is_jmp = DISAS_JUMP; 35908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 35918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 35928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void gen_nop_hint(DisasContext *s, int val) 35938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 35948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (val) { 35958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 3: /* wfi */ 35968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_set_pc_im(s->pc); 35978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project s->is_jmp = DISAS_WFI; 35988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 35998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 2: /* wfe */ 36008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 4: /* sev */ 36018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* TODO: Implement SEV and WFE. May help SMP performance. */ 36028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project default: /* nop */ 36038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 36048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 36058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 36068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 36078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define CPU_V001 cpu_V0, cpu_V0, cpu_V1 36088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 36095285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic inline void gen_neon_add(int size, TCGv t0, TCGv t1) 36108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 36118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (size) { 36125285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 0: gen_helper_neon_add_u8(t0, t0, t1); break; 36135285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 1: gen_helper_neon_add_u16(t0, t0, t1); break; 36145285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 2: tcg_gen_add_i32(t0, t0, t1); break; 36155285864985be9077e58e42235af6582dee72e841David 'Digit' Turner default: abort(); 36168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 36178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 36188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 36195285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic inline void gen_neon_rsb(int size, TCGv t0, TCGv t1) 36208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 36218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (size) { 36225285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 0: gen_helper_neon_sub_u8(t0, t1, t0); break; 36235285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 1: gen_helper_neon_sub_u16(t0, t1, t0); break; 36245285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 2: tcg_gen_sub_i32(t0, t1, t0); break; 36258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project default: return; 36268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 36278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 36288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 36298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* 32-bit pairwise ops end up the same as the elementwise versions. */ 36308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define gen_helper_neon_pmax_s32 gen_helper_neon_max_s32 36318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define gen_helper_neon_pmax_u32 gen_helper_neon_max_u32 36328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define gen_helper_neon_pmin_s32 gen_helper_neon_min_s32 36338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define gen_helper_neon_pmin_u32 gen_helper_neon_min_u32 36348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 36358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define GEN_NEON_INTEGER_OP(name) do { \ 36368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch ((size << 1) | u) { \ 36378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0: \ 36385285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_neon_##name##_s8(tmp, tmp, tmp2); \ 36398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; \ 36408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 1: \ 36415285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_neon_##name##_u8(tmp, tmp, tmp2); \ 36428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; \ 36438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 2: \ 36445285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_neon_##name##_s16(tmp, tmp, tmp2); \ 36458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; \ 36468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 3: \ 36475285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_neon_##name##_u16(tmp, tmp, tmp2); \ 36488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; \ 36498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 4: \ 36505285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_neon_##name##_s32(tmp, tmp, tmp2); \ 36518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; \ 36528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 5: \ 36535285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_neon_##name##_u32(tmp, tmp, tmp2); \ 36548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; \ 36558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project default: return 1; \ 36568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project }} while (0) 36578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 36585285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic TCGv neon_load_scratch(int scratch) 36598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 36605285864985be9077e58e42235af6582dee72e841David 'Digit' Turner TCGv tmp = tcg_temp_new_i32(); 36615285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_ld_i32(tmp, cpu_env, offsetof(CPUARMState, vfp.scratch[scratch])); 36625285864985be9077e58e42235af6582dee72e841David 'Digit' Turner return tmp; 36638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 36648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 36655285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic void neon_store_scratch(int scratch, TCGv var) 36668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 36675285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_st_i32(var, cpu_env, offsetof(CPUARMState, vfp.scratch[scratch])); 36685285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(var); 36698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 36708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 36715285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic inline TCGv neon_get_scalar(int size, int reg) 36728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 36735285864985be9077e58e42235af6582dee72e841David 'Digit' Turner TCGv tmp; 36745285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (size == 1) { 36755285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = neon_load_reg(reg & 7, reg >> 4); 36765285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (reg & 8) { 36775285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_neon_dup_high16(tmp); 36785285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } else { 36795285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_neon_dup_low16(tmp); 36805285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 36815285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } else { 36825285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = neon_load_reg(reg & 15, reg >> 4); 36835285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 36845285864985be9077e58e42235af6582dee72e841David 'Digit' Turner return tmp; 36858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 36868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 36875285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic int gen_neon_unzip(int rd, int rm, int size, int q) 36888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 36895285864985be9077e58e42235af6582dee72e841David 'Digit' Turner TCGv tmp, tmp2; 36905285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (!q && size == 2) { 36915285864985be9077e58e42235af6582dee72e841David 'Digit' Turner return 1; 36925285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 36935285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = tcg_const_i32(rd); 36945285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp2 = tcg_const_i32(rm); 36955285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (q) { 36965285864985be9077e58e42235af6582dee72e841David 'Digit' Turner switch (size) { 36975285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 0: 36985285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_neon_qunzip8(tmp, tmp2); 36995285864985be9077e58e42235af6582dee72e841David 'Digit' Turner break; 37005285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 1: 37015285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_neon_qunzip16(tmp, tmp2); 37025285864985be9077e58e42235af6582dee72e841David 'Digit' Turner break; 37035285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 2: 37045285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_neon_qunzip32(tmp, tmp2); 37055285864985be9077e58e42235af6582dee72e841David 'Digit' Turner break; 37065285864985be9077e58e42235af6582dee72e841David 'Digit' Turner default: 37075285864985be9077e58e42235af6582dee72e841David 'Digit' Turner abort(); 37085285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 37095285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } else { 37105285864985be9077e58e42235af6582dee72e841David 'Digit' Turner switch (size) { 37115285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 0: 37125285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_neon_unzip8(tmp, tmp2); 37135285864985be9077e58e42235af6582dee72e841David 'Digit' Turner break; 37145285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 1: 37155285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_neon_unzip16(tmp, tmp2); 37165285864985be9077e58e42235af6582dee72e841David 'Digit' Turner break; 37175285864985be9077e58e42235af6582dee72e841David 'Digit' Turner default: 37185285864985be9077e58e42235af6582dee72e841David 'Digit' Turner abort(); 37195285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 37205285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 37215285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 37225285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 37235285864985be9077e58e42235af6582dee72e841David 'Digit' Turner return 0; 37248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 37258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 37265285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic int gen_neon_zip(int rd, int rm, int size, int q) 37278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 37285285864985be9077e58e42235af6582dee72e841David 'Digit' Turner TCGv tmp, tmp2; 37295285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (!q && size == 2) { 37305285864985be9077e58e42235af6582dee72e841David 'Digit' Turner return 1; 37315285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 37325285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = tcg_const_i32(rd); 37335285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp2 = tcg_const_i32(rm); 37345285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (q) { 37355285864985be9077e58e42235af6582dee72e841David 'Digit' Turner switch (size) { 37365285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 0: 37375285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_neon_qzip8(tmp, tmp2); 37385285864985be9077e58e42235af6582dee72e841David 'Digit' Turner break; 37395285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 1: 37405285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_neon_qzip16(tmp, tmp2); 37415285864985be9077e58e42235af6582dee72e841David 'Digit' Turner break; 37425285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 2: 37435285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_neon_qzip32(tmp, tmp2); 37445285864985be9077e58e42235af6582dee72e841David 'Digit' Turner break; 37455285864985be9077e58e42235af6582dee72e841David 'Digit' Turner default: 37465285864985be9077e58e42235af6582dee72e841David 'Digit' Turner abort(); 37475285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 37488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 37495285864985be9077e58e42235af6582dee72e841David 'Digit' Turner switch (size) { 37505285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 0: 37515285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_neon_zip8(tmp, tmp2); 37525285864985be9077e58e42235af6582dee72e841David 'Digit' Turner break; 37535285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 1: 37545285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_neon_zip16(tmp, tmp2); 37555285864985be9077e58e42235af6582dee72e841David 'Digit' Turner break; 37565285864985be9077e58e42235af6582dee72e841David 'Digit' Turner default: 37575285864985be9077e58e42235af6582dee72e841David 'Digit' Turner abort(); 37585285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 37598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 37605285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 37615285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 37625285864985be9077e58e42235af6582dee72e841David 'Digit' Turner return 0; 37638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 37648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 37655285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic void gen_neon_trn_u8(TCGv t0, TCGv t1) 37668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 37675285864985be9077e58e42235af6582dee72e841David 'Digit' Turner TCGv rd, tmp; 37688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 37695285864985be9077e58e42235af6582dee72e841David 'Digit' Turner rd = tcg_temp_new_i32(); 37705285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = tcg_temp_new_i32(); 37715285864985be9077e58e42235af6582dee72e841David 'Digit' Turner 37725285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_shli_i32(rd, t0, 8); 37735285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_andi_i32(rd, rd, 0xff00ff00); 37745285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_andi_i32(tmp, t1, 0x00ff00ff); 37755285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_or_i32(rd, rd, tmp); 37765285864985be9077e58e42235af6582dee72e841David 'Digit' Turner 37775285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_shri_i32(t1, t1, 8); 37785285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_andi_i32(t1, t1, 0x00ff00ff); 37795285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_andi_i32(tmp, t0, 0xff00ff00); 37805285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_or_i32(t1, t1, tmp); 37815285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_mov_i32(t0, rd); 37825285864985be9077e58e42235af6582dee72e841David 'Digit' Turner 37835285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 37845285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(rd); 37858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 37868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 37875285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic void gen_neon_trn_u16(TCGv t0, TCGv t1) 37885285864985be9077e58e42235af6582dee72e841David 'Digit' Turner{ 37895285864985be9077e58e42235af6582dee72e841David 'Digit' Turner TCGv rd, tmp; 37905285864985be9077e58e42235af6582dee72e841David 'Digit' Turner 37915285864985be9077e58e42235af6582dee72e841David 'Digit' Turner rd = tcg_temp_new_i32(); 37925285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = tcg_temp_new_i32(); 37935285864985be9077e58e42235af6582dee72e841David 'Digit' Turner 37945285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_shli_i32(rd, t0, 16); 37955285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_andi_i32(tmp, t1, 0xffff); 37965285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_or_i32(rd, rd, tmp); 37975285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_shri_i32(t1, t1, 16); 37985285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_andi_i32(tmp, t0, 0xffff0000); 37995285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_or_i32(t1, t1, tmp); 38005285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_mov_i32(t0, rd); 38015285864985be9077e58e42235af6582dee72e841David 'Digit' Turner 38025285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 38035285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(rd); 38045285864985be9077e58e42235af6582dee72e841David 'Digit' Turner} 38055285864985be9077e58e42235af6582dee72e841David 'Digit' Turner 38065285864985be9077e58e42235af6582dee72e841David 'Digit' Turner 38075285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic struct { 38085285864985be9077e58e42235af6582dee72e841David 'Digit' Turner int nregs; 38095285864985be9077e58e42235af6582dee72e841David 'Digit' Turner int interleave; 38105285864985be9077e58e42235af6582dee72e841David 'Digit' Turner int spacing; 38115285864985be9077e58e42235af6582dee72e841David 'Digit' Turner} neon_ls_element_type[11] = { 38125285864985be9077e58e42235af6582dee72e841David 'Digit' Turner {4, 4, 1}, 38135285864985be9077e58e42235af6582dee72e841David 'Digit' Turner {4, 4, 2}, 38148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project {4, 1, 1}, 38158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project {4, 2, 1}, 38168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project {3, 3, 1}, 38178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project {3, 3, 2}, 38188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project {3, 1, 1}, 38198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project {1, 1, 1}, 38208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project {2, 2, 1}, 38218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project {2, 2, 2}, 38228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project {2, 1, 1} 38238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}; 38248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 38258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Translate a NEON load/store element instruction. Return nonzero if the 38268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project instruction is invalid. */ 38278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int disas_neon_ls_insn(CPUState * env, DisasContext *s, uint32_t insn) 38288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 38298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int rd, rn, rm; 38308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int op; 38318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int nregs; 38328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int interleave; 38335285864985be9077e58e42235af6582dee72e841David 'Digit' Turner int spacing; 38348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int stride; 38358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int size; 38368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int reg; 38378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int pass; 38388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int load; 38398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int shift; 38405285864985be9077e58e42235af6582dee72e841David 'Digit' Turner TCGv addr; 38418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project TCGv tmp; 38428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project TCGv tmp2; 38438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 38445285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (!s->vfp_enabled) 38458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 38468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project VFP_DREG_D(rd, insn); 38478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rn = (insn >> 16) & 0xf; 38488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rm = insn & 0xf; 38498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project load = (insn & (1 << 21)) != 0; 38508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if ((insn & (1 << 23)) == 0) { 38518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Load store all elements. */ 38528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project op = (insn >> 8) & 0xf; 38538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project size = (insn >> 6) & 3; 38545285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (op > 10) 38558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 38565285864985be9077e58e42235af6582dee72e841David 'Digit' Turner /* Catch UNDEF cases for bad values of align field */ 38575285864985be9077e58e42235af6582dee72e841David 'Digit' Turner switch (op & 0xc) { 38585285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 4: 38595285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (((insn >> 5) & 1) == 1) { 38605285864985be9077e58e42235af6582dee72e841David 'Digit' Turner return 1; 38615285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 38625285864985be9077e58e42235af6582dee72e841David 'Digit' Turner break; 38635285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 8: 38645285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (((insn >> 4) & 3) == 3) { 38655285864985be9077e58e42235af6582dee72e841David 'Digit' Turner return 1; 38665285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 38675285864985be9077e58e42235af6582dee72e841David 'Digit' Turner break; 38685285864985be9077e58e42235af6582dee72e841David 'Digit' Turner default: 38695285864985be9077e58e42235af6582dee72e841David 'Digit' Turner break; 38705285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 38718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project nregs = neon_ls_element_type[op].nregs; 38728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project interleave = neon_ls_element_type[op].interleave; 38735285864985be9077e58e42235af6582dee72e841David 'Digit' Turner spacing = neon_ls_element_type[op].spacing; 38745285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (size == 3 && (interleave | spacing) != 1) { 38755285864985be9077e58e42235af6582dee72e841David 'Digit' Turner return 1; 38768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 38775285864985be9077e58e42235af6582dee72e841David 'Digit' Turner addr = tcg_const_i32(insn); 38785285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_neon_vldst_all(addr); 38795285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(addr); 38808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project stride = nregs * 8; 38818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 38828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project size = (insn >> 10) & 3; 38838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (size == 3) { 38848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Load single element to all lanes. */ 38855285864985be9077e58e42235af6582dee72e841David 'Digit' Turner int a = (insn >> 4) & 1; 38865285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (!load) { 38878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 38885285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 38898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project size = (insn >> 6) & 3; 38908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project nregs = ((insn >> 8) & 3) + 1; 38915285864985be9077e58e42235af6582dee72e841David 'Digit' Turner 38925285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (size == 3) { 38935285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (nregs != 4 || a == 0) { 38948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 38958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 38965285864985be9077e58e42235af6582dee72e841David 'Digit' Turner /* For VLD4 size==3 a == 1 means 32 bits at 16 byte alignment */ 38975285864985be9077e58e42235af6582dee72e841David 'Digit' Turner size = 2; 38985285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 38995285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (nregs == 1 && a == 1 && size == 0) { 39005285864985be9077e58e42235af6582dee72e841David 'Digit' Turner return 1; 39015285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 39025285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (nregs == 3 && a == 1) { 39035285864985be9077e58e42235af6582dee72e841David 'Digit' Turner return 1; 39045285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 39055285864985be9077e58e42235af6582dee72e841David 'Digit' Turner addr = tcg_temp_new_i32(); 39065285864985be9077e58e42235af6582dee72e841David 'Digit' Turner load_reg_var(s, addr, rn); 39075285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (nregs == 1) { 39085285864985be9077e58e42235af6582dee72e841David 'Digit' Turner /* VLD1 to all lanes: bit 5 indicates how many Dregs to write */ 39095285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = gen_load_and_replicate(s, addr, size); 39105285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_st_i32(tmp, cpu_env, neon_reg_offset(rd, 0)); 39115285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_st_i32(tmp, cpu_env, neon_reg_offset(rd, 1)); 39125285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (insn & (1 << 5)) { 39135285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_st_i32(tmp, cpu_env, neon_reg_offset(rd + 1, 0)); 39145285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_st_i32(tmp, cpu_env, neon_reg_offset(rd + 1, 1)); 39155285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 39165285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 39175285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } else { 39185285864985be9077e58e42235af6582dee72e841David 'Digit' Turner /* VLD2/3/4 to all lanes: bit 5 indicates register stride */ 39195285864985be9077e58e42235af6582dee72e841David 'Digit' Turner stride = (insn & (1 << 5)) ? 2 : 1; 39205285864985be9077e58e42235af6582dee72e841David 'Digit' Turner for (reg = 0; reg < nregs; reg++) { 39215285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = gen_load_and_replicate(s, addr, size); 39225285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_st_i32(tmp, cpu_env, neon_reg_offset(rd, 0)); 39235285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_st_i32(tmp, cpu_env, neon_reg_offset(rd, 1)); 39245285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 39255285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_addi_i32(addr, addr, 1 << size); 39265285864985be9077e58e42235af6582dee72e841David 'Digit' Turner rd += stride; 39275285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 39288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 39295285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(addr); 39308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project stride = (1 << size) * nregs; 39318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 39328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Single element. */ 39335285864985be9077e58e42235af6582dee72e841David 'Digit' Turner int idx = (insn >> 4) & 0xf; 39348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project pass = (insn >> 7) & 1; 39358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (size) { 39368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0: 39378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project shift = ((insn >> 5) & 3) * 8; 39388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project stride = 1; 39398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 39408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 1: 39418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project shift = ((insn >> 6) & 1) * 16; 39428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project stride = (insn & (1 << 5)) ? 2 : 1; 39438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 39448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 2: 39458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project shift = 0; 39468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project stride = (insn & (1 << 6)) ? 2 : 1; 39478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 39488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project default: 39498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project abort(); 39508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 39518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project nregs = ((insn >> 8) & 3) + 1; 39525285864985be9077e58e42235af6582dee72e841David 'Digit' Turner /* Catch the UNDEF cases. This is unavoidably a bit messy. */ 39535285864985be9077e58e42235af6582dee72e841David 'Digit' Turner switch (nregs) { 39545285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 1: 39555285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (((idx & (1 << size)) != 0) || 39565285864985be9077e58e42235af6582dee72e841David 'Digit' Turner (size == 2 && ((idx & 3) == 1 || (idx & 3) == 2))) { 39575285864985be9077e58e42235af6582dee72e841David 'Digit' Turner return 1; 39585285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 39595285864985be9077e58e42235af6582dee72e841David 'Digit' Turner break; 39605285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 3: 39615285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if ((idx & 1) != 0) { 39625285864985be9077e58e42235af6582dee72e841David 'Digit' Turner return 1; 39635285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 39645285864985be9077e58e42235af6582dee72e841David 'Digit' Turner /* fall through */ 39655285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 2: 39665285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (size == 2 && (idx & 2) != 0) { 39675285864985be9077e58e42235af6582dee72e841David 'Digit' Turner return 1; 39685285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 39695285864985be9077e58e42235af6582dee72e841David 'Digit' Turner break; 39705285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 4: 39715285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if ((size == 2) && ((idx & 3) == 3)) { 39725285864985be9077e58e42235af6582dee72e841David 'Digit' Turner return 1; 39735285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 39745285864985be9077e58e42235af6582dee72e841David 'Digit' Turner break; 39755285864985be9077e58e42235af6582dee72e841David 'Digit' Turner default: 39765285864985be9077e58e42235af6582dee72e841David 'Digit' Turner abort(); 39775285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 39785285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if ((rd + stride * (nregs - 1)) > 31) { 39795285864985be9077e58e42235af6582dee72e841David 'Digit' Turner /* Attempts to write off the end of the register file 39805285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * are UNPREDICTABLE; we choose to UNDEF because otherwise 39815285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * the neon_load_reg() would write off the end of the array. 39825285864985be9077e58e42235af6582dee72e841David 'Digit' Turner */ 39835285864985be9077e58e42235af6582dee72e841David 'Digit' Turner return 1; 39845285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 39855285864985be9077e58e42235af6582dee72e841David 'Digit' Turner addr = tcg_temp_new_i32(); 39865285864985be9077e58e42235af6582dee72e841David 'Digit' Turner load_reg_var(s, addr, rn); 39878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project for (reg = 0; reg < nregs; reg++) { 39888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (load) { 39898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (size) { 39908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0: 39915285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = gen_ld8u(addr, IS_USER(s)); 39928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 39938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 1: 39945285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = gen_ld16u(addr, IS_USER(s)); 39958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 39968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 2: 39975285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = gen_ld32(addr, IS_USER(s)); 39988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 39998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project default: /* Avoid compiler warnings. */ 40008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project abort(); 40018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 40028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (size != 2) { 40038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp2 = neon_load_reg(rd, pass); 40048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_bfi(tmp, tmp2, tmp, shift, size ? 0xffff : 0xff); 40055285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 40068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 40078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project neon_store_reg(rd, pass, tmp); 40088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { /* Store */ 40098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = neon_load_reg(rd, pass); 40108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (shift) 40118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_shri_i32(tmp, tmp, shift); 40128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (size) { 40138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0: 40145285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_st8(tmp, addr, IS_USER(s)); 40158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 40168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 1: 40175285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_st16(tmp, addr, IS_USER(s)); 40188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 40198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 2: 40205285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_st32(tmp, addr, IS_USER(s)); 40218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 40228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 40238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 40248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd += stride; 40255285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_addi_i32(addr, addr, 1 << size); 40268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 40275285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(addr); 40288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project stride = nregs * (1 << size); 40298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 40308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 40318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (rm != 15) { 40328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project TCGv base; 40338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 40348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project base = load_reg(s, rn); 40358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (rm == 13) { 40368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_addi_i32(base, base, stride); 40378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 40388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project TCGv index; 40398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project index = load_reg(s, rm); 40408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_add_i32(base, base, index); 40415285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(index); 40428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 40438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project store_reg(s, rn, base); 40448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 40458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 0; 40468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 40478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 40488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Bitwise select. dest = c ? t : f. Clobbers T and F. */ 40498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void gen_neon_bsl(TCGv dest, TCGv t, TCGv f, TCGv c) 40508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 40518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_and_i32(t, t, c); 40525285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_andc_i32(f, f, c); 40538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_or_i32(dest, t, f); 40548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 40558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 40565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic inline void gen_neon_narrow(int size, TCGv dest, TCGv_i64 src) 40578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 40588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (size) { 40598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0: gen_helper_neon_narrow_u8(dest, src); break; 40608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 1: gen_helper_neon_narrow_u16(dest, src); break; 40618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 2: tcg_gen_trunc_i64_i32(dest, src); break; 40628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project default: abort(); 40638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 40648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 40658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 40665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic inline void gen_neon_narrow_sats(int size, TCGv dest, TCGv_i64 src) 40678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 40688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (size) { 40695285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 0: gen_helper_neon_narrow_sat_s8(dest, src); break; 40705285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 1: gen_helper_neon_narrow_sat_s16(dest, src); break; 40715285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 2: gen_helper_neon_narrow_sat_s32(dest, src); break; 40728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project default: abort(); 40738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 40748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 40758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 40765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic inline void gen_neon_narrow_satu(int size, TCGv dest, TCGv_i64 src) 40778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 40788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (size) { 40795285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 0: gen_helper_neon_narrow_sat_u8(dest, src); break; 40805285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 1: gen_helper_neon_narrow_sat_u16(dest, src); break; 40815285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 2: gen_helper_neon_narrow_sat_u32(dest, src); break; 40825285864985be9077e58e42235af6582dee72e841David 'Digit' Turner default: abort(); 40835285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 40845285864985be9077e58e42235af6582dee72e841David 'Digit' Turner} 40855285864985be9077e58e42235af6582dee72e841David 'Digit' Turner 40865285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic inline void gen_neon_unarrow_sats(int size, TCGv dest, TCGv_i64 src) 40875285864985be9077e58e42235af6582dee72e841David 'Digit' Turner{ 40885285864985be9077e58e42235af6582dee72e841David 'Digit' Turner switch (size) { 40895285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 0: gen_helper_neon_unarrow_sat8(dest, src); break; 40905285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 1: gen_helper_neon_unarrow_sat16(dest, src); break; 40915285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 2: gen_helper_neon_unarrow_sat32(dest, src); break; 40928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project default: abort(); 40938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 40948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 40958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 40968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline void gen_neon_shift_narrow(int size, TCGv var, TCGv shift, 40978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int q, int u) 40988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 40998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (q) { 41008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (u) { 41018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (size) { 41028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 1: gen_helper_neon_rshl_u16(var, var, shift); break; 41038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 2: gen_helper_neon_rshl_u32(var, var, shift); break; 41048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project default: abort(); 41058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 41068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 41078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (size) { 41088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 1: gen_helper_neon_rshl_s16(var, var, shift); break; 41098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 2: gen_helper_neon_rshl_s32(var, var, shift); break; 41108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project default: abort(); 41118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 41128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 41138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 41148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (u) { 41158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (size) { 41165285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 1: gen_helper_neon_shl_u16(var, var, shift); break; 41175285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 2: gen_helper_neon_shl_u32(var, var, shift); break; 41188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project default: abort(); 41198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 41208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 41218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (size) { 41228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 1: gen_helper_neon_shl_s16(var, var, shift); break; 41238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 2: gen_helper_neon_shl_s32(var, var, shift); break; 41248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project default: abort(); 41258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 41268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 41278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 41288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 41298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 41305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic inline void gen_neon_widen(TCGv_i64 dest, TCGv src, int size, int u) 41318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 41328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (u) { 41338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (size) { 41348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0: gen_helper_neon_widen_u8(dest, src); break; 41358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 1: gen_helper_neon_widen_u16(dest, src); break; 41368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 2: tcg_gen_extu_i32_i64(dest, src); break; 41378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project default: abort(); 41388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 41398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 41408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (size) { 41418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0: gen_helper_neon_widen_s8(dest, src); break; 41428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 1: gen_helper_neon_widen_s16(dest, src); break; 41438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 2: tcg_gen_ext_i32_i64(dest, src); break; 41448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project default: abort(); 41458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 41468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 41475285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(src); 41488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 41498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 41508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline void gen_neon_addl(int size) 41518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 41528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (size) { 41538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0: gen_helper_neon_addl_u16(CPU_V001); break; 41548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 1: gen_helper_neon_addl_u32(CPU_V001); break; 41558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 2: tcg_gen_add_i64(CPU_V001); break; 41568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project default: abort(); 41578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 41588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 41598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 41608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline void gen_neon_subl(int size) 41618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 41628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (size) { 41638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0: gen_helper_neon_subl_u16(CPU_V001); break; 41648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 1: gen_helper_neon_subl_u32(CPU_V001); break; 41658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 2: tcg_gen_sub_i64(CPU_V001); break; 41668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project default: abort(); 41678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 41688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 41698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 41705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic inline void gen_neon_negl(TCGv_i64 var, int size) 41718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 41728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (size) { 41738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0: gen_helper_neon_negl_u16(var, var); break; 41748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 1: gen_helper_neon_negl_u32(var, var); break; 41758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 2: gen_helper_neon_negl_u64(var, var); break; 41768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project default: abort(); 41778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 41788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 41798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 41805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic inline void gen_neon_addl_saturate(TCGv_i64 op0, TCGv_i64 op1, int size) 41818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 41828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (size) { 41835285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 1: gen_helper_neon_addl_saturate_s32(op0, op0, op1); break; 41845285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 2: gen_helper_neon_addl_saturate_s64(op0, op0, op1); break; 41858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project default: abort(); 41868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 41878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 41888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 41895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic inline void gen_neon_mull(TCGv_i64 dest, TCGv a, TCGv b, int size, int u) 41908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 41915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner TCGv_i64 tmp; 41928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 41938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch ((size << 1) | u) { 41948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0: gen_helper_neon_mull_s8(dest, a, b); break; 41958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 1: gen_helper_neon_mull_u8(dest, a, b); break; 41968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 2: gen_helper_neon_mull_s16(dest, a, b); break; 41978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 3: gen_helper_neon_mull_u16(dest, a, b); break; 41988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 4: 41998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = gen_muls_i64_i32(a, b); 42008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_mov_i64(dest, tmp); 42015285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i64(tmp); 42028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 42038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 5: 42048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = gen_mulu_i64_i32(a, b); 42058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_mov_i64(dest, tmp); 42065285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i64(tmp); 42078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 42088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project default: abort(); 42098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 42105285864985be9077e58e42235af6582dee72e841David 'Digit' Turner 42115285864985be9077e58e42235af6582dee72e841David 'Digit' Turner /* gen_helper_neon_mull_[su]{8|16} do not free their parameters. 42125285864985be9077e58e42235af6582dee72e841David 'Digit' Turner Don't forget to clean them now. */ 42138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (size < 2) { 42145285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(a); 42155285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(b); 42168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 42178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 42188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 42195285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic void gen_neon_narrow_op(int op, int u, int size, TCGv dest, TCGv_i64 src) 42205285864985be9077e58e42235af6582dee72e841David 'Digit' Turner{ 42215285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (op) { 42225285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (u) { 42235285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_neon_unarrow_sats(size, dest, src); 42245285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } else { 42255285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_neon_narrow(size, dest, src); 42265285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 42275285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } else { 42285285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (u) { 42295285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_neon_narrow_satu(size, dest, src); 42305285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } else { 42315285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_neon_narrow_sats(size, dest, src); 42325285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 42335285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 42345285864985be9077e58e42235af6582dee72e841David 'Digit' Turner} 42355285864985be9077e58e42235af6582dee72e841David 'Digit' Turner 42365285864985be9077e58e42235af6582dee72e841David 'Digit' Turner/* Symbolic constants for op fields for Neon 3-register same-length. 42375285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * The values correspond to bits [11:8,4]; see the ARM ARM DDI0406B 42385285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * table A7-9. 42395285864985be9077e58e42235af6582dee72e841David 'Digit' Turner */ 42405285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_3R_VHADD 0 42415285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_3R_VQADD 1 42425285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_3R_VRHADD 2 42435285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_3R_LOGIC 3 /* VAND,VBIC,VORR,VMOV,VORN,VEOR,VBIF,VBIT,VBSL */ 42445285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_3R_VHSUB 4 42455285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_3R_VQSUB 5 42465285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_3R_VCGT 6 42475285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_3R_VCGE 7 42485285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_3R_VSHL 8 42495285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_3R_VQSHL 9 42505285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_3R_VRSHL 10 42515285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_3R_VQRSHL 11 42525285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_3R_VMAX 12 42535285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_3R_VMIN 13 42545285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_3R_VABD 14 42555285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_3R_VABA 15 42565285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_3R_VADD_VSUB 16 42575285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_3R_VTST_VCEQ 17 42585285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_3R_VML 18 /* VMLA, VMLAL, VMLS, VMLSL */ 42595285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_3R_VMUL 19 42605285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_3R_VPMAX 20 42615285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_3R_VPMIN 21 42625285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_3R_VQDMULH_VQRDMULH 22 42635285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_3R_VPADD 23 42645285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_3R_FLOAT_ARITH 26 /* float VADD, VSUB, VPADD, VABD */ 42655285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_3R_FLOAT_MULTIPLY 27 /* float VMLA, VMLS, VMUL */ 42665285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_3R_FLOAT_CMP 28 /* float VCEQ, VCGE, VCGT */ 42675285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_3R_FLOAT_ACMP 29 /* float VACGE, VACGT, VACLE, VACLT */ 42685285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_3R_FLOAT_MINMAX 30 /* float VMIN, VMAX */ 42695285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_3R_VRECPS_VRSQRTS 31 /* float VRECPS, VRSQRTS */ 42705285864985be9077e58e42235af6582dee72e841David 'Digit' Turner 42715285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic const uint8_t neon_3r_sizes[] = { 42725285864985be9077e58e42235af6582dee72e841David 'Digit' Turner [NEON_3R_VHADD] = 0x7, 42735285864985be9077e58e42235af6582dee72e841David 'Digit' Turner [NEON_3R_VQADD] = 0xf, 42745285864985be9077e58e42235af6582dee72e841David 'Digit' Turner [NEON_3R_VRHADD] = 0x7, 42755285864985be9077e58e42235af6582dee72e841David 'Digit' Turner [NEON_3R_LOGIC] = 0xf, /* size field encodes op type */ 42765285864985be9077e58e42235af6582dee72e841David 'Digit' Turner [NEON_3R_VHSUB] = 0x7, 42775285864985be9077e58e42235af6582dee72e841David 'Digit' Turner [NEON_3R_VQSUB] = 0xf, 42785285864985be9077e58e42235af6582dee72e841David 'Digit' Turner [NEON_3R_VCGT] = 0x7, 42795285864985be9077e58e42235af6582dee72e841David 'Digit' Turner [NEON_3R_VCGE] = 0x7, 42805285864985be9077e58e42235af6582dee72e841David 'Digit' Turner [NEON_3R_VSHL] = 0xf, 42815285864985be9077e58e42235af6582dee72e841David 'Digit' Turner [NEON_3R_VQSHL] = 0xf, 42825285864985be9077e58e42235af6582dee72e841David 'Digit' Turner [NEON_3R_VRSHL] = 0xf, 42835285864985be9077e58e42235af6582dee72e841David 'Digit' Turner [NEON_3R_VQRSHL] = 0xf, 42845285864985be9077e58e42235af6582dee72e841David 'Digit' Turner [NEON_3R_VMAX] = 0x7, 42855285864985be9077e58e42235af6582dee72e841David 'Digit' Turner [NEON_3R_VMIN] = 0x7, 42865285864985be9077e58e42235af6582dee72e841David 'Digit' Turner [NEON_3R_VABD] = 0x7, 42875285864985be9077e58e42235af6582dee72e841David 'Digit' Turner [NEON_3R_VABA] = 0x7, 42885285864985be9077e58e42235af6582dee72e841David 'Digit' Turner [NEON_3R_VADD_VSUB] = 0xf, 42895285864985be9077e58e42235af6582dee72e841David 'Digit' Turner [NEON_3R_VTST_VCEQ] = 0x7, 42905285864985be9077e58e42235af6582dee72e841David 'Digit' Turner [NEON_3R_VML] = 0x7, 42915285864985be9077e58e42235af6582dee72e841David 'Digit' Turner [NEON_3R_VMUL] = 0x7, 42925285864985be9077e58e42235af6582dee72e841David 'Digit' Turner [NEON_3R_VPMAX] = 0x7, 42935285864985be9077e58e42235af6582dee72e841David 'Digit' Turner [NEON_3R_VPMIN] = 0x7, 42945285864985be9077e58e42235af6582dee72e841David 'Digit' Turner [NEON_3R_VQDMULH_VQRDMULH] = 0x6, 42955285864985be9077e58e42235af6582dee72e841David 'Digit' Turner [NEON_3R_VPADD] = 0x7, 42965285864985be9077e58e42235af6582dee72e841David 'Digit' Turner [NEON_3R_FLOAT_ARITH] = 0x5, /* size bit 1 encodes op */ 42975285864985be9077e58e42235af6582dee72e841David 'Digit' Turner [NEON_3R_FLOAT_MULTIPLY] = 0x5, /* size bit 1 encodes op */ 42985285864985be9077e58e42235af6582dee72e841David 'Digit' Turner [NEON_3R_FLOAT_CMP] = 0x5, /* size bit 1 encodes op */ 42995285864985be9077e58e42235af6582dee72e841David 'Digit' Turner [NEON_3R_FLOAT_ACMP] = 0x5, /* size bit 1 encodes op */ 43005285864985be9077e58e42235af6582dee72e841David 'Digit' Turner [NEON_3R_FLOAT_MINMAX] = 0x5, /* size bit 1 encodes op */ 43015285864985be9077e58e42235af6582dee72e841David 'Digit' Turner [NEON_3R_VRECPS_VRSQRTS] = 0x5, /* size bit 1 encodes op */ 43025285864985be9077e58e42235af6582dee72e841David 'Digit' Turner}; 43035285864985be9077e58e42235af6582dee72e841David 'Digit' Turner 43045285864985be9077e58e42235af6582dee72e841David 'Digit' Turner/* Symbolic constants for op fields for Neon 2-register miscellaneous. 43055285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * The values correspond to bits [17:16,10:7]; see the ARM ARM DDI0406B 43065285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * table A7-13. 43075285864985be9077e58e42235af6582dee72e841David 'Digit' Turner */ 43085285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VREV64 0 43095285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VREV32 1 43105285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VREV16 2 43115285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VPADDL 4 43125285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VPADDL_U 5 43135285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VCLS 8 43145285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VCLZ 9 43155285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VCNT 10 43165285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VMVN 11 43175285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VPADAL 12 43185285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VPADAL_U 13 43195285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VQABS 14 43205285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VQNEG 15 43215285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VCGT0 16 43225285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VCGE0 17 43235285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VCEQ0 18 43245285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VCLE0 19 43255285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VCLT0 20 43265285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VABS 22 43275285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VNEG 23 43285285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VCGT0_F 24 43295285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VCGE0_F 25 43305285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VCEQ0_F 26 43315285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VCLE0_F 27 43325285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VCLT0_F 28 43335285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VABS_F 30 43345285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VNEG_F 31 43355285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VSWP 32 43365285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VTRN 33 43375285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VUZP 34 43385285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VZIP 35 43395285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VMOVN 36 /* Includes VQMOVN, VQMOVUN */ 43405285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VQMOVN 37 /* Includes VQMOVUN */ 43415285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VSHLL 38 43425285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VCVT_F16_F32 44 43435285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VCVT_F32_F16 46 43445285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VRECPE 56 43455285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VRSQRTE 57 43465285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VRECPE_F 58 43475285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VRSQRTE_F 59 43485285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VCVT_FS 60 43495285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VCVT_FU 61 43505285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VCVT_SF 62 43515285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VCVT_UF 63 43525285864985be9077e58e42235af6582dee72e841David 'Digit' Turner 43535285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic int neon_2rm_is_float_op(int op) 43545285864985be9077e58e42235af6582dee72e841David 'Digit' Turner{ 43555285864985be9077e58e42235af6582dee72e841David 'Digit' Turner /* Return true if this neon 2reg-misc op is float-to-float */ 43565285864985be9077e58e42235af6582dee72e841David 'Digit' Turner return (op == NEON_2RM_VABS_F || op == NEON_2RM_VNEG_F || 43575285864985be9077e58e42235af6582dee72e841David 'Digit' Turner op >= NEON_2RM_VRECPE_F); 43585285864985be9077e58e42235af6582dee72e841David 'Digit' Turner} 43595285864985be9077e58e42235af6582dee72e841David 'Digit' Turner 43605285864985be9077e58e42235af6582dee72e841David 'Digit' Turner/* Each entry in this array has bit n set if the insn allows 43615285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * size value n (otherwise it will UNDEF). Since unallocated 43625285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * op values will have no bits set they always UNDEF. 43635285864985be9077e58e42235af6582dee72e841David 'Digit' Turner */ 43645285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic const uint8_t neon_2rm_sizes[] = { 43655285864985be9077e58e42235af6582dee72e841David 'Digit' Turner [NEON_2RM_VREV64] = 0x7, 43665285864985be9077e58e42235af6582dee72e841David 'Digit' Turner [NEON_2RM_VREV32] = 0x3, 43675285864985be9077e58e42235af6582dee72e841David 'Digit' Turner [NEON_2RM_VREV16] = 0x1, 43685285864985be9077e58e42235af6582dee72e841David 'Digit' Turner [NEON_2RM_VPADDL] = 0x7, 43695285864985be9077e58e42235af6582dee72e841David 'Digit' Turner [NEON_2RM_VPADDL_U] = 0x7, 43705285864985be9077e58e42235af6582dee72e841David 'Digit' Turner [NEON_2RM_VCLS] = 0x7, 43715285864985be9077e58e42235af6582dee72e841David 'Digit' Turner [NEON_2RM_VCLZ] = 0x7, 43725285864985be9077e58e42235af6582dee72e841David 'Digit' Turner [NEON_2RM_VCNT] = 0x1, 43735285864985be9077e58e42235af6582dee72e841David 'Digit' Turner [NEON_2RM_VMVN] = 0x1, 43745285864985be9077e58e42235af6582dee72e841David 'Digit' Turner [NEON_2RM_VPADAL] = 0x7, 43755285864985be9077e58e42235af6582dee72e841David 'Digit' Turner [NEON_2RM_VPADAL_U] = 0x7, 43765285864985be9077e58e42235af6582dee72e841David 'Digit' Turner [NEON_2RM_VQABS] = 0x7, 43775285864985be9077e58e42235af6582dee72e841David 'Digit' Turner [NEON_2RM_VQNEG] = 0x7, 43785285864985be9077e58e42235af6582dee72e841David 'Digit' Turner [NEON_2RM_VCGT0] = 0x7, 43795285864985be9077e58e42235af6582dee72e841David 'Digit' Turner [NEON_2RM_VCGE0] = 0x7, 43805285864985be9077e58e42235af6582dee72e841David 'Digit' Turner [NEON_2RM_VCEQ0] = 0x7, 43815285864985be9077e58e42235af6582dee72e841David 'Digit' Turner [NEON_2RM_VCLE0] = 0x7, 43825285864985be9077e58e42235af6582dee72e841David 'Digit' Turner [NEON_2RM_VCLT0] = 0x7, 43835285864985be9077e58e42235af6582dee72e841David 'Digit' Turner [NEON_2RM_VABS] = 0x7, 43845285864985be9077e58e42235af6582dee72e841David 'Digit' Turner [NEON_2RM_VNEG] = 0x7, 43855285864985be9077e58e42235af6582dee72e841David 'Digit' Turner [NEON_2RM_VCGT0_F] = 0x4, 43865285864985be9077e58e42235af6582dee72e841David 'Digit' Turner [NEON_2RM_VCGE0_F] = 0x4, 43875285864985be9077e58e42235af6582dee72e841David 'Digit' Turner [NEON_2RM_VCEQ0_F] = 0x4, 43885285864985be9077e58e42235af6582dee72e841David 'Digit' Turner [NEON_2RM_VCLE0_F] = 0x4, 43895285864985be9077e58e42235af6582dee72e841David 'Digit' Turner [NEON_2RM_VCLT0_F] = 0x4, 43905285864985be9077e58e42235af6582dee72e841David 'Digit' Turner [NEON_2RM_VABS_F] = 0x4, 43915285864985be9077e58e42235af6582dee72e841David 'Digit' Turner [NEON_2RM_VNEG_F] = 0x4, 43925285864985be9077e58e42235af6582dee72e841David 'Digit' Turner [NEON_2RM_VSWP] = 0x1, 43935285864985be9077e58e42235af6582dee72e841David 'Digit' Turner [NEON_2RM_VTRN] = 0x7, 43945285864985be9077e58e42235af6582dee72e841David 'Digit' Turner [NEON_2RM_VUZP] = 0x7, 43955285864985be9077e58e42235af6582dee72e841David 'Digit' Turner [NEON_2RM_VZIP] = 0x7, 43965285864985be9077e58e42235af6582dee72e841David 'Digit' Turner [NEON_2RM_VMOVN] = 0x7, 43975285864985be9077e58e42235af6582dee72e841David 'Digit' Turner [NEON_2RM_VQMOVN] = 0x7, 43985285864985be9077e58e42235af6582dee72e841David 'Digit' Turner [NEON_2RM_VSHLL] = 0x7, 43995285864985be9077e58e42235af6582dee72e841David 'Digit' Turner [NEON_2RM_VCVT_F16_F32] = 0x2, 44005285864985be9077e58e42235af6582dee72e841David 'Digit' Turner [NEON_2RM_VCVT_F32_F16] = 0x2, 44015285864985be9077e58e42235af6582dee72e841David 'Digit' Turner [NEON_2RM_VRECPE] = 0x4, 44025285864985be9077e58e42235af6582dee72e841David 'Digit' Turner [NEON_2RM_VRSQRTE] = 0x4, 44035285864985be9077e58e42235af6582dee72e841David 'Digit' Turner [NEON_2RM_VRECPE_F] = 0x4, 44045285864985be9077e58e42235af6582dee72e841David 'Digit' Turner [NEON_2RM_VRSQRTE_F] = 0x4, 44055285864985be9077e58e42235af6582dee72e841David 'Digit' Turner [NEON_2RM_VCVT_FS] = 0x4, 44065285864985be9077e58e42235af6582dee72e841David 'Digit' Turner [NEON_2RM_VCVT_FU] = 0x4, 44075285864985be9077e58e42235af6582dee72e841David 'Digit' Turner [NEON_2RM_VCVT_SF] = 0x4, 44085285864985be9077e58e42235af6582dee72e841David 'Digit' Turner [NEON_2RM_VCVT_UF] = 0x4, 44095285864985be9077e58e42235af6582dee72e841David 'Digit' Turner}; 44105285864985be9077e58e42235af6582dee72e841David 'Digit' Turner 44118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Translate a NEON data processing instruction. Return nonzero if the 44128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project instruction is invalid. 44138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project We process data in a mixture of 32-bit and 64-bit chunks. 44148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project Mostly we use 32-bit chunks so we can use normal scalar instructions. */ 44158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 44168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn) 44178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 44188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int op; 44198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int q; 44208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int rd, rn, rm; 44218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int size; 44228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int shift; 44238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int pass; 44248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int count; 44258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int pairwise; 44268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int u; 44275285864985be9077e58e42235af6582dee72e841David 'Digit' Turner uint32_t imm, mask; 44285285864985be9077e58e42235af6582dee72e841David 'Digit' Turner TCGv tmp, tmp2, tmp3, tmp4, tmp5; 44295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner TCGv_i64 tmp64; 44308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 44315285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (!s->vfp_enabled) 44328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 44338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project q = (insn & (1 << 6)) != 0; 44348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project u = (insn >> 24) & 1; 44358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project VFP_DREG_D(rd, insn); 44368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project VFP_DREG_N(rn, insn); 44378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project VFP_DREG_M(rm, insn); 44388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project size = (insn >> 20) & 3; 44398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if ((insn & (1 << 23)) == 0) { 44408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Three register same length. */ 44418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project op = ((insn >> 7) & 0x1e) | ((insn >> 4) & 1); 44425285864985be9077e58e42235af6582dee72e841David 'Digit' Turner /* Catch invalid op and bad size combinations: UNDEF */ 44435285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if ((neon_3r_sizes[op] & (1 << size)) == 0) { 44445285864985be9077e58e42235af6582dee72e841David 'Digit' Turner return 1; 44455285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 44465285864985be9077e58e42235af6582dee72e841David 'Digit' Turner /* All insns of this form UNDEF for either this condition or the 44475285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * superset of cases "Q==1"; we catch the latter later. 44485285864985be9077e58e42235af6582dee72e841David 'Digit' Turner */ 44495285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (q && ((rd | rn | rm) & 1)) { 44505285864985be9077e58e42235af6582dee72e841David 'Digit' Turner return 1; 44515285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 44525285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (size == 3 && op != NEON_3R_LOGIC) { 44535285864985be9077e58e42235af6582dee72e841David 'Digit' Turner /* 64-bit element instructions. */ 44548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project for (pass = 0; pass < (q ? 2 : 1); pass++) { 44558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project neon_load_reg64(cpu_V0, rn + pass); 44568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project neon_load_reg64(cpu_V1, rm + pass); 44578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (op) { 44585285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_3R_VQADD: 44598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (u) { 44605285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_neon_qadd_u64(cpu_V0, cpu_V0, cpu_V1); 44618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 44625285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_neon_qadd_s64(cpu_V0, cpu_V0, cpu_V1); 44638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 44648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 44655285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_3R_VQSUB: 44668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (u) { 44675285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_neon_qsub_u64(cpu_V0, cpu_V0, cpu_V1); 44688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 44695285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_neon_qsub_s64(cpu_V0, cpu_V0, cpu_V1); 44708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 44718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 44725285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_3R_VSHL: 44738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (u) { 44748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_helper_neon_shl_u64(cpu_V0, cpu_V1, cpu_V0); 44758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 44768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_helper_neon_shl_s64(cpu_V0, cpu_V1, cpu_V0); 44778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 44788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 44795285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_3R_VQSHL: 44808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (u) { 44815285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_neon_qshl_u64(cpu_V0, cpu_V1, cpu_V0); 44828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 44835285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_neon_qshl_s64(cpu_V0, cpu_V1, cpu_V0); 44848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 44858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 44865285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_3R_VRSHL: 44878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (u) { 44888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_helper_neon_rshl_u64(cpu_V0, cpu_V1, cpu_V0); 44898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 44908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_helper_neon_rshl_s64(cpu_V0, cpu_V1, cpu_V0); 44918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 44928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 44935285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_3R_VQRSHL: 44948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (u) { 44955285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_neon_qrshl_u64(cpu_V0, cpu_V1, cpu_V0); 44968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 44975285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_neon_qrshl_s64(cpu_V0, cpu_V1, cpu_V0); 44988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 44998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 45005285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_3R_VADD_VSUB: 45018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (u) { 45028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_sub_i64(CPU_V001); 45038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 45048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_add_i64(CPU_V001); 45058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 45068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 45078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project default: 45088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project abort(); 45098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 45108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project neon_store_reg64(cpu_V0, rd + pass); 45118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 45128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 0; 45138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 45145285864985be9077e58e42235af6582dee72e841David 'Digit' Turner pairwise = 0; 45158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (op) { 45165285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_3R_VSHL: 45175285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_3R_VQSHL: 45185285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_3R_VRSHL: 45195285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_3R_VQRSHL: 45208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project { 45218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int rtmp; 45228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Shift instruction operands are reversed. */ 45238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rtmp = rn; 45248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rn = rm; 45258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rm = rtmp; 45268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 45278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 45285285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_3R_VPADD: 45295285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (u) { 45305285864985be9077e58e42235af6582dee72e841David 'Digit' Turner return 1; 45315285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 45325285864985be9077e58e42235af6582dee72e841David 'Digit' Turner /* Fall through */ 45335285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_3R_VPMAX: 45345285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_3R_VPMIN: 45358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project pairwise = 1; 45368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 45375285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_3R_FLOAT_ARITH: 45385285864985be9077e58e42235af6582dee72e841David 'Digit' Turner pairwise = (u && size < 2); /* if VPADD (float) */ 45398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 45405285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_3R_FLOAT_MINMAX: 45415285864985be9077e58e42235af6582dee72e841David 'Digit' Turner pairwise = u; /* if VPMIN/VPMAX (float) */ 45425285864985be9077e58e42235af6582dee72e841David 'Digit' Turner break; 45435285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_3R_FLOAT_CMP: 45445285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (!u && size) { 45455285864985be9077e58e42235af6582dee72e841David 'Digit' Turner /* no encoding for U=0 C=1x */ 45465285864985be9077e58e42235af6582dee72e841David 'Digit' Turner return 1; 45475285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 45485285864985be9077e58e42235af6582dee72e841David 'Digit' Turner break; 45495285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_3R_FLOAT_ACMP: 45505285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (!u) { 45515285864985be9077e58e42235af6582dee72e841David 'Digit' Turner return 1; 45525285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 45535285864985be9077e58e42235af6582dee72e841David 'Digit' Turner break; 45545285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_3R_VRECPS_VRSQRTS: 45555285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (u) { 45565285864985be9077e58e42235af6582dee72e841David 'Digit' Turner return 1; 45575285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 45585285864985be9077e58e42235af6582dee72e841David 'Digit' Turner break; 45595285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_3R_VMUL: 45605285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (u && (size != 0)) { 45615285864985be9077e58e42235af6582dee72e841David 'Digit' Turner /* UNDEF on invalid size for polynomial subcase */ 45625285864985be9077e58e42235af6582dee72e841David 'Digit' Turner return 1; 45635285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 45648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 45658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project default: 45668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 45678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 45685285864985be9077e58e42235af6582dee72e841David 'Digit' Turner 45695285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (pairwise && q) { 45705285864985be9077e58e42235af6582dee72e841David 'Digit' Turner /* All the pairwise insns UNDEF if Q is set */ 45715285864985be9077e58e42235af6582dee72e841David 'Digit' Turner return 1; 45725285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 45735285864985be9077e58e42235af6582dee72e841David 'Digit' Turner 45748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project for (pass = 0; pass < (q ? 4 : 2); pass++) { 45758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 45768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (pairwise) { 45778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Pairwise. */ 45785285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (pass < 1) { 45795285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = neon_load_reg(rn, 0); 45805285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp2 = neon_load_reg(rn, 1); 45818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 45825285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = neon_load_reg(rm, 0); 45835285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp2 = neon_load_reg(rm, 1); 45848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 45858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 45868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Elementwise. */ 45875285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = neon_load_reg(rn, pass); 45885285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp2 = neon_load_reg(rm, pass); 45898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 45908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (op) { 45915285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_3R_VHADD: 45928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project GEN_NEON_INTEGER_OP(hadd); 45938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 45945285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_3R_VQADD: 45955285864985be9077e58e42235af6582dee72e841David 'Digit' Turner GEN_NEON_INTEGER_OP(qadd); 45968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 45975285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_3R_VRHADD: 45988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project GEN_NEON_INTEGER_OP(rhadd); 45998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 46005285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_3R_LOGIC: /* Logic ops. */ 46018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch ((u << 2) | size) { 46028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0: /* VAND */ 46035285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_and_i32(tmp, tmp, tmp2); 46048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 46058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 1: /* BIC */ 46065285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_andc_i32(tmp, tmp, tmp2); 46078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 46088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 2: /* VORR */ 46095285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_or_i32(tmp, tmp, tmp2); 46108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 46118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 3: /* VORN */ 46125285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_orc_i32(tmp, tmp, tmp2); 46138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 46148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 4: /* VEOR */ 46155285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_xor_i32(tmp, tmp, tmp2); 46168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 46178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 5: /* VBSL */ 46185285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp3 = neon_load_reg(rd, pass); 46195285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_neon_bsl(tmp, tmp, tmp2, tmp3); 46205285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp3); 46218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 46228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 6: /* VBIT */ 46235285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp3 = neon_load_reg(rd, pass); 46245285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_neon_bsl(tmp, tmp, tmp3, tmp2); 46255285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp3); 46268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 46278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 7: /* VBIF */ 46285285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp3 = neon_load_reg(rd, pass); 46295285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_neon_bsl(tmp, tmp3, tmp, tmp2); 46305285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp3); 46318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 46328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 46338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 46345285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_3R_VHSUB: 46358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project GEN_NEON_INTEGER_OP(hsub); 46368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 46375285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_3R_VQSUB: 46385285864985be9077e58e42235af6582dee72e841David 'Digit' Turner GEN_NEON_INTEGER_OP(qsub); 46398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 46405285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_3R_VCGT: 46418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project GEN_NEON_INTEGER_OP(cgt); 46428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 46435285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_3R_VCGE: 46448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project GEN_NEON_INTEGER_OP(cge); 46458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 46465285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_3R_VSHL: 46478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project GEN_NEON_INTEGER_OP(shl); 46488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 46495285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_3R_VQSHL: 46505285864985be9077e58e42235af6582dee72e841David 'Digit' Turner GEN_NEON_INTEGER_OP(qshl); 46518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 46525285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_3R_VRSHL: 46538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project GEN_NEON_INTEGER_OP(rshl); 46548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 46555285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_3R_VQRSHL: 46565285864985be9077e58e42235af6582dee72e841David 'Digit' Turner GEN_NEON_INTEGER_OP(qrshl); 46578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 46585285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_3R_VMAX: 46598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project GEN_NEON_INTEGER_OP(max); 46608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 46615285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_3R_VMIN: 46628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project GEN_NEON_INTEGER_OP(min); 46638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 46645285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_3R_VABD: 46658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project GEN_NEON_INTEGER_OP(abd); 46668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 46675285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_3R_VABA: 46688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project GEN_NEON_INTEGER_OP(abd); 46695285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 46705285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp2 = neon_load_reg(rd, pass); 46715285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_neon_add(size, tmp, tmp2); 46728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 46735285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_3R_VADD_VSUB: 46748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (!u) { /* VADD */ 46755285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_neon_add(size, tmp, tmp2); 46768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { /* VSUB */ 46778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (size) { 46785285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 0: gen_helper_neon_sub_u8(tmp, tmp, tmp2); break; 46795285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 1: gen_helper_neon_sub_u16(tmp, tmp, tmp2); break; 46805285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 2: tcg_gen_sub_i32(tmp, tmp, tmp2); break; 46815285864985be9077e58e42235af6582dee72e841David 'Digit' Turner default: abort(); 46828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 46838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 46848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 46855285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_3R_VTST_VCEQ: 46868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (!u) { /* VTST */ 46878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (size) { 46885285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 0: gen_helper_neon_tst_u8(tmp, tmp, tmp2); break; 46895285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 1: gen_helper_neon_tst_u16(tmp, tmp, tmp2); break; 46905285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 2: gen_helper_neon_tst_u32(tmp, tmp, tmp2); break; 46915285864985be9077e58e42235af6582dee72e841David 'Digit' Turner default: abort(); 46928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 46938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { /* VCEQ */ 46948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (size) { 46955285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 0: gen_helper_neon_ceq_u8(tmp, tmp, tmp2); break; 46965285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 1: gen_helper_neon_ceq_u16(tmp, tmp, tmp2); break; 46975285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 2: gen_helper_neon_ceq_u32(tmp, tmp, tmp2); break; 46985285864985be9077e58e42235af6582dee72e841David 'Digit' Turner default: abort(); 46998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 47008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 47018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 47025285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_3R_VML: /* VMLA, VMLAL, VMLS,VMLSL */ 47038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (size) { 47045285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 0: gen_helper_neon_mul_u8(tmp, tmp, tmp2); break; 47055285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 1: gen_helper_neon_mul_u16(tmp, tmp, tmp2); break; 47065285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 2: tcg_gen_mul_i32(tmp, tmp, tmp2); break; 47075285864985be9077e58e42235af6582dee72e841David 'Digit' Turner default: abort(); 47088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 47095285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 47105285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp2 = neon_load_reg(rd, pass); 47118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (u) { /* VMLS */ 47125285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_neon_rsb(size, tmp, tmp2); 47138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { /* VMLA */ 47145285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_neon_add(size, tmp, tmp2); 47158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 47168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 47175285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_3R_VMUL: 47188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (u) { /* polynomial */ 47195285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_neon_mul_p8(tmp, tmp, tmp2); 47208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { /* Integer */ 47218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (size) { 47225285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 0: gen_helper_neon_mul_u8(tmp, tmp, tmp2); break; 47235285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 1: gen_helper_neon_mul_u16(tmp, tmp, tmp2); break; 47245285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 2: tcg_gen_mul_i32(tmp, tmp, tmp2); break; 47255285864985be9077e58e42235af6582dee72e841David 'Digit' Turner default: abort(); 47268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 47278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 47288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 47295285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_3R_VPMAX: 47308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project GEN_NEON_INTEGER_OP(pmax); 47318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 47325285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_3R_VPMIN: 47338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project GEN_NEON_INTEGER_OP(pmin); 47348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 47355285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_3R_VQDMULH_VQRDMULH: /* Multiply high. */ 47368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (!u) { /* VQDMULH */ 47378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (size) { 47385285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 1: gen_helper_neon_qdmulh_s16(tmp, tmp, tmp2); break; 47395285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 2: gen_helper_neon_qdmulh_s32(tmp, tmp, tmp2); break; 47405285864985be9077e58e42235af6582dee72e841David 'Digit' Turner default: abort(); 47418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 47425285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } else { /* VQRDMULH */ 47438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (size) { 47445285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 1: gen_helper_neon_qrdmulh_s16(tmp, tmp, tmp2); break; 47455285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 2: gen_helper_neon_qrdmulh_s32(tmp, tmp, tmp2); break; 47465285864985be9077e58e42235af6582dee72e841David 'Digit' Turner default: abort(); 47478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 47488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 47498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 47505285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_3R_VPADD: 47518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (size) { 47525285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 0: gen_helper_neon_padd_u8(tmp, tmp, tmp2); break; 47535285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 1: gen_helper_neon_padd_u16(tmp, tmp, tmp2); break; 47545285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 2: tcg_gen_add_i32(tmp, tmp, tmp2); break; 47555285864985be9077e58e42235af6582dee72e841David 'Digit' Turner default: abort(); 47568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 47578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 47585285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_3R_FLOAT_ARITH: /* Floating point arithmetic. */ 47598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch ((u << 2) | size) { 47608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0: /* VADD */ 47615285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_neon_add_f32(tmp, tmp, tmp2); 47628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 47638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 2: /* VSUB */ 47645285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_neon_sub_f32(tmp, tmp, tmp2); 47658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 47668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 4: /* VPADD */ 47675285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_neon_add_f32(tmp, tmp, tmp2); 47688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 47698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 6: /* VABD */ 47705285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_neon_abd_f32(tmp, tmp, tmp2); 47718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 47728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project default: 47735285864985be9077e58e42235af6582dee72e841David 'Digit' Turner abort(); 47748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 47758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 47765285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_3R_FLOAT_MULTIPLY: 47775285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_neon_mul_f32(tmp, tmp, tmp2); 47788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (!u) { 47795285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 47805285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp2 = neon_load_reg(rd, pass); 47818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (size == 0) { 47825285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_neon_add_f32(tmp, tmp, tmp2); 47838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 47845285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_neon_sub_f32(tmp, tmp2, tmp); 47858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 47868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 47878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 47885285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_3R_FLOAT_CMP: 47898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (!u) { 47905285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_neon_ceq_f32(tmp, tmp, tmp2); 47918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 47928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (size == 0) 47935285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_neon_cge_f32(tmp, tmp, tmp2); 47948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 47955285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_neon_cgt_f32(tmp, tmp, tmp2); 47968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 47978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 47985285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_3R_FLOAT_ACMP: 47998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (size == 0) 48005285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_neon_acge_f32(tmp, tmp, tmp2); 48018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 48025285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_neon_acgt_f32(tmp, tmp, tmp2); 48038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 48045285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_3R_FLOAT_MINMAX: 48058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (size == 0) 48065285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_neon_max_f32(tmp, tmp, tmp2); 48078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 48085285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_neon_min_f32(tmp, tmp, tmp2); 48098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 48105285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_3R_VRECPS_VRSQRTS: 48118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (size == 0) 48125285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_recps_f32(tmp, tmp, tmp2, cpu_env); 48138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 48145285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_rsqrts_f32(tmp, tmp, tmp2, cpu_env); 48158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 48168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project default: 48178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project abort(); 48188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 48195285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 48205285864985be9077e58e42235af6582dee72e841David 'Digit' Turner 48218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Save the result. For elementwise operations we can put it 48228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project straight into the destination register. For pairwise operations 48238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project we have to be careful to avoid clobbering the source operands. */ 48248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (pairwise && rd == rm) { 48255285864985be9077e58e42235af6582dee72e841David 'Digit' Turner neon_store_scratch(pass, tmp); 48268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 48275285864985be9077e58e42235af6582dee72e841David 'Digit' Turner neon_store_reg(rd, pass, tmp); 48288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 48298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 48308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } /* for pass */ 48318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (pairwise && rd == rm) { 48328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project for (pass = 0; pass < (q ? 4 : 2); pass++) { 48335285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = neon_load_scratch(pass); 48345285864985be9077e58e42235af6582dee72e841David 'Digit' Turner neon_store_reg(rd, pass, tmp); 48358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 48368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 48378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* End of 3 register same size operations. */ 48388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else if (insn & (1 << 4)) { 48398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if ((insn & 0x00380080) != 0) { 48408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Two registers and shift. */ 48418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project op = (insn >> 8) & 0xf; 48428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 7)) { 48435285864985be9077e58e42235af6582dee72e841David 'Digit' Turner /* 64-bit shift. */ 48445285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (op > 7) { 48455285864985be9077e58e42235af6582dee72e841David 'Digit' Turner return 1; 48465285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 48478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project size = 3; 48488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 48498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project size = 2; 48508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project while ((insn & (1 << (size + 19))) == 0) 48518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project size--; 48528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 48538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project shift = (insn >> 16) & ((1 << (3 + size)) - 1); 48548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* To avoid excessive dumplication of ops we implement shift 48558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project by immediate using the variable shift operations. */ 48568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (op < 8) { 48578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Shift by immediate: 48588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project VSHR, VSRA, VRSHR, VRSRA, VSRI, VSHL, VQSHL, VQSHLU. */ 48595285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (q && ((rd | rm) & 1)) { 48605285864985be9077e58e42235af6582dee72e841David 'Digit' Turner return 1; 48615285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 48625285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (!u && (op == 4 || op == 6)) { 48635285864985be9077e58e42235af6582dee72e841David 'Digit' Turner return 1; 48645285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 48658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Right shifts are encoded as N - shift, where N is the 48668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project element size in bits. */ 48678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (op <= 4) 48688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project shift = shift - (1 << (size + 3)); 48698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (size == 3) { 48708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project count = q + 1; 48718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 48728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project count = q ? 4: 2; 48738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 48748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (size) { 48758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0: 48768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project imm = (uint8_t) shift; 48778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project imm |= imm << 8; 48788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project imm |= imm << 16; 48798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 48808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 1: 48818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project imm = (uint16_t) shift; 48828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project imm |= imm << 16; 48838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 48848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 2: 48858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 3: 48868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project imm = shift; 48878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 48888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project default: 48898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project abort(); 48908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 48918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 48928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project for (pass = 0; pass < count; pass++) { 48938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (size == 3) { 48948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project neon_load_reg64(cpu_V0, rm + pass); 48958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_movi_i64(cpu_V1, imm); 48968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (op) { 48978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0: /* VSHR */ 48988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 1: /* VSRA */ 48998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (u) 49008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_helper_neon_shl_u64(cpu_V0, cpu_V0, cpu_V1); 49018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 49028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_helper_neon_shl_s64(cpu_V0, cpu_V0, cpu_V1); 49038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 49048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 2: /* VRSHR */ 49058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 3: /* VRSRA */ 49068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (u) 49078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_helper_neon_rshl_u64(cpu_V0, cpu_V0, cpu_V1); 49088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 49098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_helper_neon_rshl_s64(cpu_V0, cpu_V0, cpu_V1); 49108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 49118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 4: /* VSRI */ 49128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 5: /* VSHL, VSLI */ 49138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_helper_neon_shl_u64(cpu_V0, cpu_V0, cpu_V1); 49148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 49155285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 6: /* VQSHLU */ 49165285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_neon_qshlu_s64(cpu_V0, cpu_V0, cpu_V1); 49178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 49185285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 7: /* VQSHL */ 49195285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (u) { 49205285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_neon_qshl_u64(cpu_V0, 49215285864985be9077e58e42235af6582dee72e841David 'Digit' Turner cpu_V0, cpu_V1); 49225285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } else { 49235285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_neon_qshl_s64(cpu_V0, 49245285864985be9077e58e42235af6582dee72e841David 'Digit' Turner cpu_V0, cpu_V1); 49255285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 49268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 49278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 49288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (op == 1 || op == 3) { 49298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Accumulate. */ 49305285864985be9077e58e42235af6582dee72e841David 'Digit' Turner neon_load_reg64(cpu_V1, rd + pass); 49318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_add_i64(cpu_V0, cpu_V0, cpu_V1); 49328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else if (op == 4 || (op == 5 && u)) { 49338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Insert */ 49345285864985be9077e58e42235af6582dee72e841David 'Digit' Turner neon_load_reg64(cpu_V1, rd + pass); 49355285864985be9077e58e42235af6582dee72e841David 'Digit' Turner uint64_t mask; 49365285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (shift < -63 || shift > 63) { 49375285864985be9077e58e42235af6582dee72e841David 'Digit' Turner mask = 0; 49385285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } else { 49395285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (op == 4) { 49405285864985be9077e58e42235af6582dee72e841David 'Digit' Turner mask = 0xffffffffffffffffull >> -shift; 49415285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } else { 49425285864985be9077e58e42235af6582dee72e841David 'Digit' Turner mask = 0xffffffffffffffffull << shift; 49435285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 49445285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 49455285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_andi_i64(cpu_V1, cpu_V1, ~mask); 49465285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_or_i64(cpu_V0, cpu_V0, cpu_V1); 49478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 49488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project neon_store_reg64(cpu_V0, rd + pass); 49498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { /* size < 3 */ 49508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Operands in T0 and T1. */ 49515285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = neon_load_reg(rm, pass); 49525285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp2 = tcg_const_i32(imm); 49538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (op) { 49548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0: /* VSHR */ 49558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 1: /* VSRA */ 49568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project GEN_NEON_INTEGER_OP(shl); 49578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 49588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 2: /* VRSHR */ 49598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 3: /* VRSRA */ 49608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project GEN_NEON_INTEGER_OP(rshl); 49618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 49628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 4: /* VSRI */ 49638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 5: /* VSHL, VSLI */ 49648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (size) { 49655285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 0: gen_helper_neon_shl_u8(tmp, tmp, tmp2); break; 49665285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 1: gen_helper_neon_shl_u16(tmp, tmp, tmp2); break; 49675285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 2: gen_helper_neon_shl_u32(tmp, tmp, tmp2); break; 49685285864985be9077e58e42235af6582dee72e841David 'Digit' Turner default: abort(); 49698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 49708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 49715285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 6: /* VQSHLU */ 49728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (size) { 49735285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 0: 49745285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_neon_qshlu_s8(tmp, tmp, tmp2); 49755285864985be9077e58e42235af6582dee72e841David 'Digit' Turner break; 49765285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 1: 49775285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_neon_qshlu_s16(tmp, tmp, tmp2); 49785285864985be9077e58e42235af6582dee72e841David 'Digit' Turner break; 49795285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 2: 49805285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_neon_qshlu_s32(tmp, tmp, tmp2); 49815285864985be9077e58e42235af6582dee72e841David 'Digit' Turner break; 49825285864985be9077e58e42235af6582dee72e841David 'Digit' Turner default: 49835285864985be9077e58e42235af6582dee72e841David 'Digit' Turner abort(); 49848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 49858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 49865285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 7: /* VQSHL */ 49875285864985be9077e58e42235af6582dee72e841David 'Digit' Turner GEN_NEON_INTEGER_OP(qshl); 49885285864985be9077e58e42235af6582dee72e841David 'Digit' Turner break; 49898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 49905285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 49918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 49928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (op == 1 || op == 3) { 49938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Accumulate. */ 49945285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp2 = neon_load_reg(rd, pass); 49955285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_neon_add(size, tmp, tmp2); 49965285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 49978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else if (op == 4 || (op == 5 && u)) { 49988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Insert */ 49998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (size) { 50008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0: 50018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (op == 4) 50025285864985be9077e58e42235af6582dee72e841David 'Digit' Turner mask = 0xff >> -shift; 50038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 50045285864985be9077e58e42235af6582dee72e841David 'Digit' Turner mask = (uint8_t)(0xff << shift); 50055285864985be9077e58e42235af6582dee72e841David 'Digit' Turner mask |= mask << 8; 50065285864985be9077e58e42235af6582dee72e841David 'Digit' Turner mask |= mask << 16; 50078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 50088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 1: 50098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (op == 4) 50105285864985be9077e58e42235af6582dee72e841David 'Digit' Turner mask = 0xffff >> -shift; 50118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 50125285864985be9077e58e42235af6582dee72e841David 'Digit' Turner mask = (uint16_t)(0xffff << shift); 50135285864985be9077e58e42235af6582dee72e841David 'Digit' Turner mask |= mask << 16; 50148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 50158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 2: 50165285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (shift < -31 || shift > 31) { 50175285864985be9077e58e42235af6582dee72e841David 'Digit' Turner mask = 0; 50185285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } else { 50195285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (op == 4) 50205285864985be9077e58e42235af6582dee72e841David 'Digit' Turner mask = 0xffffffffu >> -shift; 50215285864985be9077e58e42235af6582dee72e841David 'Digit' Turner else 50225285864985be9077e58e42235af6582dee72e841David 'Digit' Turner mask = 0xffffffffu << shift; 50235285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 50248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 50258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project default: 50268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project abort(); 50278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 50285285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp2 = neon_load_reg(rd, pass); 50295285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_andi_i32(tmp, tmp, mask); 50305285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_andi_i32(tmp2, tmp2, ~mask); 50315285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_or_i32(tmp, tmp, tmp2); 50325285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 50338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 50345285864985be9077e58e42235af6582dee72e841David 'Digit' Turner neon_store_reg(rd, pass, tmp); 50358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 50368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } /* for pass */ 50378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else if (op < 10) { 50388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Shift by immediate and narrow: 50398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project VSHRN, VRSHRN, VQSHRN, VQRSHRN. */ 50405285864985be9077e58e42235af6582dee72e841David 'Digit' Turner int input_unsigned = (op == 8) ? !u : u; 50415285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (rm & 1) { 50425285864985be9077e58e42235af6582dee72e841David 'Digit' Turner return 1; 50435285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 50448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project shift = shift - (1 << (size + 3)); 50458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project size++; 50465285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (size == 3) { 50475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tmp64 = tcg_const_i64(shift); 50485285864985be9077e58e42235af6582dee72e841David 'Digit' Turner neon_load_reg64(cpu_V0, rm); 50495285864985be9077e58e42235af6582dee72e841David 'Digit' Turner neon_load_reg64(cpu_V1, rm + 1); 50505285864985be9077e58e42235af6582dee72e841David 'Digit' Turner for (pass = 0; pass < 2; pass++) { 50515285864985be9077e58e42235af6582dee72e841David 'Digit' Turner TCGv_i64 in; 50525285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (pass == 0) { 50535285864985be9077e58e42235af6582dee72e841David 'Digit' Turner in = cpu_V0; 50545285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } else { 50555285864985be9077e58e42235af6582dee72e841David 'Digit' Turner in = cpu_V1; 50565285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 50578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (q) { 50585285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (input_unsigned) { 50595285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_neon_rshl_u64(cpu_V0, in, tmp64); 50605285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } else { 50615285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_neon_rshl_s64(cpu_V0, in, tmp64); 50625285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 50638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 50645285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (input_unsigned) { 50655285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_neon_shl_u64(cpu_V0, in, tmp64); 50665285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } else { 50675285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_neon_shl_s64(cpu_V0, in, tmp64); 50685285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 50698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 50705285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = tcg_temp_new_i32(); 50715285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_neon_narrow_op(op == 8, u, size - 1, tmp, cpu_V0); 50725285864985be9077e58e42235af6582dee72e841David 'Digit' Turner neon_store_reg(rd, pass, tmp); 50735285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } /* for pass */ 50745285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i64(tmp64); 50755285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } else { 50765285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (size == 1) { 50775285864985be9077e58e42235af6582dee72e841David 'Digit' Turner imm = (uint16_t)shift; 50785285864985be9077e58e42235af6582dee72e841David 'Digit' Turner imm |= imm << 16; 50798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 50805285864985be9077e58e42235af6582dee72e841David 'Digit' Turner /* size == 2 */ 50815285864985be9077e58e42235af6582dee72e841David 'Digit' Turner imm = (uint32_t)shift; 50828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 50835285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp2 = tcg_const_i32(imm); 50845285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp4 = neon_load_reg(rm + 1, 0); 50855285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp5 = neon_load_reg(rm + 1, 1); 50865285864985be9077e58e42235af6582dee72e841David 'Digit' Turner for (pass = 0; pass < 2; pass++) { 50875285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (pass == 0) { 50885285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = neon_load_reg(rm, 0); 50895285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } else { 50905285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = tmp4; 50915285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 50925285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_neon_shift_narrow(size, tmp, tmp2, q, 50935285864985be9077e58e42235af6582dee72e841David 'Digit' Turner input_unsigned); 50945285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (pass == 0) { 50955285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp3 = neon_load_reg(rm, 1); 50965285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } else { 50975285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp3 = tmp5; 50985285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 50995285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_neon_shift_narrow(size, tmp3, tmp2, q, 51005285864985be9077e58e42235af6582dee72e841David 'Digit' Turner input_unsigned); 51015285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_concat_i32_i64(cpu_V0, tmp, tmp3); 51025285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 51035285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp3); 51045285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = tcg_temp_new_i32(); 51055285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_neon_narrow_op(op == 8, u, size - 1, tmp, cpu_V0); 51065285864985be9077e58e42235af6582dee72e841David 'Digit' Turner neon_store_reg(rd, pass, tmp); 51075285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } /* for pass */ 51085285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 51095285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 51108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else if (op == 10) { 51115285864985be9077e58e42235af6582dee72e841David 'Digit' Turner /* VSHLL, VMOVL */ 51125285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (q || (rd & 1)) { 51138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 51145285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 51158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = neon_load_reg(rm, 0); 51168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp2 = neon_load_reg(rm, 1); 51178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project for (pass = 0; pass < 2; pass++) { 51188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (pass == 1) 51198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = tmp2; 51208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 51218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_neon_widen(cpu_V0, tmp, size, u); 51228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 51238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (shift != 0) { 51248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* The shift is less than the width of the source 51258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project type, so we can just shift the whole register. */ 51268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_shli_i64(cpu_V0, cpu_V0, shift); 51275285864985be9077e58e42235af6582dee72e841David 'Digit' Turner /* Widen the result of shift: we need to clear 51285285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * the potential overflow bits resulting from 51295285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * left bits of the narrow input appearing as 51305285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * right bits of left the neighbour narrow 51315285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * input. */ 51328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (size < 2 || !u) { 51338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project uint64_t imm64; 51348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (size == 0) { 51358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project imm = (0xffu >> (8 - shift)); 51368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project imm |= imm << 16; 51375285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } else if (size == 1) { 51388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project imm = 0xffff >> (16 - shift); 51395285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } else { 51405285864985be9077e58e42235af6582dee72e841David 'Digit' Turner /* size == 2 */ 51415285864985be9077e58e42235af6582dee72e841David 'Digit' Turner imm = 0xffffffff >> (32 - shift); 51428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 51435285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (size < 2) { 51445285864985be9077e58e42235af6582dee72e841David 'Digit' Turner imm64 = imm | (((uint64_t)imm) << 32); 51455285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } else { 51465285864985be9077e58e42235af6582dee72e841David 'Digit' Turner imm64 = imm; 51475285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 51485285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_andi_i64(cpu_V0, cpu_V0, ~imm64); 51498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 51508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 51518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project neon_store_reg64(cpu_V0, rd + pass); 51528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 51535285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } else if (op >= 14) { 51548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* VCVT fixed-point. */ 51555285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (!(insn & (1 << 21)) || (q && ((rd | rm) & 1))) { 51565285864985be9077e58e42235af6582dee72e841David 'Digit' Turner return 1; 51575285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 51585285864985be9077e58e42235af6582dee72e841David 'Digit' Turner /* We have already masked out the must-be-1 top bit of imm6, 51595285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * hence this 32-shift where the ARM ARM has 64-imm6. 51605285864985be9077e58e42235af6582dee72e841David 'Digit' Turner */ 51615285864985be9077e58e42235af6582dee72e841David 'Digit' Turner shift = 32 - shift; 51628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project for (pass = 0; pass < (q ? 4 : 2); pass++) { 51638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, pass)); 51645285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (!(op & 1)) { 51658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (u) 51665285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_vfp_ulto(0, shift, 1); 51678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 51685285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_vfp_slto(0, shift, 1); 51698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 51708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (u) 51715285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_vfp_toul(0, shift, 1); 51728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 51735285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_vfp_tosl(0, shift, 1); 51748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 51758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, pass)); 51768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 51778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 51788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 51798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 51808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { /* (insn & 0x00380080) == 0 */ 51818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int invert; 51825285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (q && (rd & 1)) { 51835285864985be9077e58e42235af6582dee72e841David 'Digit' Turner return 1; 51845285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 51858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 51868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project op = (insn >> 8) & 0xf; 51878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* One register and immediate. */ 51888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project imm = (u << 7) | ((insn >> 12) & 0x70) | (insn & 0xf); 51898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project invert = (insn & (1 << 5)) != 0; 51905285864985be9077e58e42235af6582dee72e841David 'Digit' Turner /* Note that op = 2,3,4,5,6,7,10,11,12,13 imm=0 is UNPREDICTABLE. 51915285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * We choose to not special-case this and will behave as if a 51925285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * valid constant encoding of 0 had been given. 51935285864985be9077e58e42235af6582dee72e841David 'Digit' Turner */ 51948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (op) { 51958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0: case 1: 51968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* no-op */ 51978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 51988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 2: case 3: 51998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project imm <<= 8; 52008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 52018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 4: case 5: 52028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project imm <<= 16; 52038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 52048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 6: case 7: 52058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project imm <<= 24; 52068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 52078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 8: case 9: 52088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project imm |= imm << 16; 52098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 52108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 10: case 11: 52118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project imm = (imm << 8) | (imm << 24); 52128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 52138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 12: 52145285864985be9077e58e42235af6582dee72e841David 'Digit' Turner imm = (imm << 8) | 0xff; 52158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 52168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 13: 52178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project imm = (imm << 16) | 0xffff; 52188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 52198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 14: 52208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project imm |= (imm << 8) | (imm << 16) | (imm << 24); 52218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (invert) 52228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project imm = ~imm; 52238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 52248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 15: 52255285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (invert) { 52265285864985be9077e58e42235af6582dee72e841David 'Digit' Turner return 1; 52275285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 52288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project imm = ((imm & 0x80) << 24) | ((imm & 0x3f) << 19) 52298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project | ((imm & 0x40) ? (0x1f << 25) : (1 << 30)); 52308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 52318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 52328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (invert) 52338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project imm = ~imm; 52348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 52358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project for (pass = 0; pass < (q ? 4 : 2); pass++) { 52368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (op & 1 && op < 12) { 52378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = neon_load_reg(rd, pass); 52388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (invert) { 52398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* The immediate value has already been inverted, so 52408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project BIC becomes AND. */ 52418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_andi_i32(tmp, tmp, imm); 52428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 52438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_ori_i32(tmp, tmp, imm); 52448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 52458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 52468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* VMOV, VMVN. */ 52475285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = tcg_temp_new_i32(); 52488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (op == 14 && invert) { 52495285864985be9077e58e42235af6582dee72e841David 'Digit' Turner int n; 52508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project uint32_t val; 52518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project val = 0; 52528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project for (n = 0; n < 4; n++) { 52538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (imm & (1 << (n + (pass & 1) * 4))) 52548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project val |= 0xff << (n * 8); 52558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 52568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_movi_i32(tmp, val); 52578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 52588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_movi_i32(tmp, imm); 52598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 52608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 52618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project neon_store_reg(rd, pass, tmp); 52628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 52638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 52645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } else { /* (insn & 0x00800010 == 0x00800000) */ 52658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (size != 3) { 52668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project op = (insn >> 8) & 0xf; 52678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if ((insn & (1 << 6)) == 0) { 52688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Three registers of different lengths. */ 52698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int src1_wide; 52708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int src2_wide; 52718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int prewiden; 52725285864985be9077e58e42235af6582dee72e841David 'Digit' Turner /* undefreq: bit 0 : UNDEF if size != 0 52735285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * bit 1 : UNDEF if size == 0 52745285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * bit 2 : UNDEF if U == 1 52755285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * Note that [1:0] set implies 'always UNDEF' 52765285864985be9077e58e42235af6582dee72e841David 'Digit' Turner */ 52775285864985be9077e58e42235af6582dee72e841David 'Digit' Turner int undefreq; 52785285864985be9077e58e42235af6582dee72e841David 'Digit' Turner /* prewiden, src1_wide, src2_wide, undefreq */ 52795285864985be9077e58e42235af6582dee72e841David 'Digit' Turner static const int neon_3reg_wide[16][4] = { 52805285864985be9077e58e42235af6582dee72e841David 'Digit' Turner {1, 0, 0, 0}, /* VADDL */ 52815285864985be9077e58e42235af6582dee72e841David 'Digit' Turner {1, 1, 0, 0}, /* VADDW */ 52825285864985be9077e58e42235af6582dee72e841David 'Digit' Turner {1, 0, 0, 0}, /* VSUBL */ 52835285864985be9077e58e42235af6582dee72e841David 'Digit' Turner {1, 1, 0, 0}, /* VSUBW */ 52845285864985be9077e58e42235af6582dee72e841David 'Digit' Turner {0, 1, 1, 0}, /* VADDHN */ 52855285864985be9077e58e42235af6582dee72e841David 'Digit' Turner {0, 0, 0, 0}, /* VABAL */ 52865285864985be9077e58e42235af6582dee72e841David 'Digit' Turner {0, 1, 1, 0}, /* VSUBHN */ 52875285864985be9077e58e42235af6582dee72e841David 'Digit' Turner {0, 0, 0, 0}, /* VABDL */ 52885285864985be9077e58e42235af6582dee72e841David 'Digit' Turner {0, 0, 0, 0}, /* VMLAL */ 52895285864985be9077e58e42235af6582dee72e841David 'Digit' Turner {0, 0, 0, 6}, /* VQDMLAL */ 52905285864985be9077e58e42235af6582dee72e841David 'Digit' Turner {0, 0, 0, 0}, /* VMLSL */ 52915285864985be9077e58e42235af6582dee72e841David 'Digit' Turner {0, 0, 0, 6}, /* VQDMLSL */ 52925285864985be9077e58e42235af6582dee72e841David 'Digit' Turner {0, 0, 0, 0}, /* Integer VMULL */ 52935285864985be9077e58e42235af6582dee72e841David 'Digit' Turner {0, 0, 0, 2}, /* VQDMULL */ 52945285864985be9077e58e42235af6582dee72e841David 'Digit' Turner {0, 0, 0, 5}, /* Polynomial VMULL */ 52955285864985be9077e58e42235af6582dee72e841David 'Digit' Turner {0, 0, 0, 3}, /* Reserved: always UNDEF */ 52968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project }; 52978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 52988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project prewiden = neon_3reg_wide[op][0]; 52998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project src1_wide = neon_3reg_wide[op][1]; 53008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project src2_wide = neon_3reg_wide[op][2]; 53015285864985be9077e58e42235af6582dee72e841David 'Digit' Turner undefreq = neon_3reg_wide[op][3]; 53028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 53035285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (((undefreq & 1) && (size != 0)) || 53045285864985be9077e58e42235af6582dee72e841David 'Digit' Turner ((undefreq & 2) && (size == 0)) || 53055285864985be9077e58e42235af6582dee72e841David 'Digit' Turner ((undefreq & 4) && u)) { 53065285864985be9077e58e42235af6582dee72e841David 'Digit' Turner return 1; 53075285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 53085285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if ((src1_wide && (rn & 1)) || 53095285864985be9077e58e42235af6582dee72e841David 'Digit' Turner (src2_wide && (rm & 1)) || 53105285864985be9077e58e42235af6582dee72e841David 'Digit' Turner (!src2_wide && (rd & 1))) { 53118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 53125285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 53138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 53148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Avoid overlapping operands. Wide source operands are 53158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project always aligned so will never overlap with wide 53168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project destinations in problematic ways. */ 53178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (rd == rm && !src2_wide) { 53185285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = neon_load_reg(rm, 1); 53195285864985be9077e58e42235af6582dee72e841David 'Digit' Turner neon_store_scratch(2, tmp); 53208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else if (rd == rn && !src1_wide) { 53215285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = neon_load_reg(rn, 1); 53225285864985be9077e58e42235af6582dee72e841David 'Digit' Turner neon_store_scratch(2, tmp); 53238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 53248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project TCGV_UNUSED(tmp3); 53258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project for (pass = 0; pass < 2; pass++) { 53268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (src1_wide) { 53278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project neon_load_reg64(cpu_V0, rn + pass); 53288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project TCGV_UNUSED(tmp); 53298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 53308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (pass == 1 && rd == rn) { 53315285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = neon_load_scratch(2); 53328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 53338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = neon_load_reg(rn, pass); 53348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 53358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (prewiden) { 53368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_neon_widen(cpu_V0, tmp, size, u); 53378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 53388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 53398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (src2_wide) { 53408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project neon_load_reg64(cpu_V1, rm + pass); 53418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project TCGV_UNUSED(tmp2); 53428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 53438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (pass == 1 && rd == rm) { 53445285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp2 = neon_load_scratch(2); 53458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 53468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp2 = neon_load_reg(rm, pass); 53478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 53488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (prewiden) { 53498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_neon_widen(cpu_V1, tmp2, size, u); 53508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 53518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 53528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (op) { 53538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0: case 1: case 4: /* VADDL, VADDW, VADDHN, VRADDHN */ 53548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_neon_addl(size); 53558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 53565285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 2: case 3: case 6: /* VSUBL, VSUBW, VSUBHN, VRSUBHN */ 53578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_neon_subl(size); 53588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 53598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 5: case 7: /* VABAL, VABDL */ 53608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch ((size << 1) | u) { 53618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0: 53628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_helper_neon_abdl_s16(cpu_V0, tmp, tmp2); 53638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 53648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 1: 53658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_helper_neon_abdl_u16(cpu_V0, tmp, tmp2); 53668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 53678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 2: 53688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_helper_neon_abdl_s32(cpu_V0, tmp, tmp2); 53698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 53708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 3: 53718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_helper_neon_abdl_u32(cpu_V0, tmp, tmp2); 53728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 53738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 4: 53748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_helper_neon_abdl_s64(cpu_V0, tmp, tmp2); 53758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 53768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 5: 53778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_helper_neon_abdl_u64(cpu_V0, tmp, tmp2); 53788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 53798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project default: abort(); 53808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 53815285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 53825285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 53838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 53848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 8: case 9: case 10: case 11: case 12: case 13: 53858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* VMLAL, VQDMLAL, VMLSL, VQDMLSL, VMULL, VQDMULL */ 53868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_neon_mull(cpu_V0, tmp, tmp2, size, u); 53878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 53888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 14: /* Polynomial VMULL */ 53895285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_neon_mull_p8(cpu_V0, tmp, tmp2); 53905285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 53915285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 53925285864985be9077e58e42235af6582dee72e841David 'Digit' Turner break; 53935285864985be9077e58e42235af6582dee72e841David 'Digit' Turner default: /* 15 is RESERVED: caught earlier */ 53945285864985be9077e58e42235af6582dee72e841David 'Digit' Turner abort(); 53955285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 53965285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (op == 13) { 53975285864985be9077e58e42235af6582dee72e841David 'Digit' Turner /* VQDMULL */ 53985285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_neon_addl_saturate(cpu_V0, cpu_V0, size); 53995285864985be9077e58e42235af6582dee72e841David 'Digit' Turner neon_store_reg64(cpu_V0, rd + pass); 54005285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } else if (op == 5 || (op >= 8 && op <= 11)) { 54015285864985be9077e58e42235af6582dee72e841David 'Digit' Turner /* Accumulate. */ 54025285864985be9077e58e42235af6582dee72e841David 'Digit' Turner neon_load_reg64(cpu_V1, rd + pass); 54038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (op) { 54045285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 10: /* VMLSL */ 54055285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_neon_negl(cpu_V0, size); 54065285864985be9077e58e42235af6582dee72e841David 'Digit' Turner /* Fall through */ 54075285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 5: case 8: /* VABAL, VMLAL */ 54088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_neon_addl(size); 54098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 54108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 9: case 11: /* VQDMLAL, VQDMLSL */ 54118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_neon_addl_saturate(cpu_V0, cpu_V0, size); 54125285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (op == 11) { 54135285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_neon_negl(cpu_V0, size); 54145285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 54158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_neon_addl_saturate(cpu_V0, cpu_V1, size); 54168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 54178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project default: 54188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project abort(); 54198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 54208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project neon_store_reg64(cpu_V0, rd + pass); 54218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else if (op == 4 || op == 6) { 54228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Narrowing operation. */ 54235285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = tcg_temp_new_i32(); 54245285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (!u) { 54258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (size) { 54268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0: 54278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_helper_neon_narrow_high_u8(tmp, cpu_V0); 54288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 54298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 1: 54308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_helper_neon_narrow_high_u16(tmp, cpu_V0); 54318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 54328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 2: 54338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_shri_i64(cpu_V0, cpu_V0, 32); 54348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_trunc_i64_i32(tmp, cpu_V0); 54358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 54368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project default: abort(); 54378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 54388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 54398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (size) { 54408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0: 54418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_helper_neon_narrow_round_high_u8(tmp, cpu_V0); 54428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 54438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 1: 54448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_helper_neon_narrow_round_high_u16(tmp, cpu_V0); 54458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 54468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 2: 54478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_addi_i64(cpu_V0, cpu_V0, 1u << 31); 54488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_shri_i64(cpu_V0, cpu_V0, 32); 54498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_trunc_i64_i32(tmp, cpu_V0); 54508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 54518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project default: abort(); 54528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 54538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 54548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (pass == 0) { 54558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp3 = tmp; 54568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 54578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project neon_store_reg(rd, 0, tmp3); 54588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project neon_store_reg(rd, 1, tmp); 54598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 54608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 54618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Write back the result. */ 54628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project neon_store_reg64(cpu_V0, rd + pass); 54638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 54648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 54658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 54665285864985be9077e58e42235af6582dee72e841David 'Digit' Turner /* Two registers and a scalar. NB that for ops of this form 54675285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * the ARM ARM labels bit 24 as Q, but it is in our variable 54685285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * 'u', not 'q'. 54695285864985be9077e58e42235af6582dee72e841David 'Digit' Turner */ 54705285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (size == 0) { 54715285864985be9077e58e42235af6582dee72e841David 'Digit' Turner return 1; 54725285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 54738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (op) { 54748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 1: /* Float VMLA scalar */ 54758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 5: /* Floating point VMLS scalar */ 54768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 9: /* Floating point VMUL scalar */ 54775285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (size == 1) { 54785285864985be9077e58e42235af6582dee72e841David 'Digit' Turner return 1; 54795285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 54805285864985be9077e58e42235af6582dee72e841David 'Digit' Turner /* fall through */ 54815285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 0: /* Integer VMLA scalar */ 54825285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 4: /* Integer VMLS scalar */ 54835285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 8: /* Integer VMUL scalar */ 54848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 12: /* VQDMULH scalar */ 54858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 13: /* VQRDMULH scalar */ 54865285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (u && ((rd | rn) & 1)) { 54875285864985be9077e58e42235af6582dee72e841David 'Digit' Turner return 1; 54885285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 54895285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = neon_get_scalar(size, rm); 54905285864985be9077e58e42235af6582dee72e841David 'Digit' Turner neon_store_scratch(0, tmp); 54918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project for (pass = 0; pass < (u ? 4 : 2); pass++) { 54925285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = neon_load_scratch(0); 54935285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp2 = neon_load_reg(rn, pass); 54948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (op == 12) { 54958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (size == 1) { 54965285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_neon_qdmulh_s16(tmp, tmp, tmp2); 54978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 54985285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_neon_qdmulh_s32(tmp, tmp, tmp2); 54998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 55008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else if (op == 13) { 55018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (size == 1) { 55025285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_neon_qrdmulh_s16(tmp, tmp, tmp2); 55038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 55045285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_neon_qrdmulh_s32(tmp, tmp, tmp2); 55058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 55068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else if (op & 1) { 55075285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_neon_mul_f32(tmp, tmp, tmp2); 55088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 55098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (size) { 55105285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 0: gen_helper_neon_mul_u8(tmp, tmp, tmp2); break; 55115285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 1: gen_helper_neon_mul_u16(tmp, tmp, tmp2); break; 55125285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 2: tcg_gen_mul_i32(tmp, tmp, tmp2); break; 55135285864985be9077e58e42235af6582dee72e841David 'Digit' Turner default: abort(); 55148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 55158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 55165285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 55178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (op < 8) { 55188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Accumulate. */ 55195285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp2 = neon_load_reg(rd, pass); 55208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (op) { 55218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0: 55225285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_neon_add(size, tmp, tmp2); 55238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 55248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 1: 55255285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_neon_add_f32(tmp, tmp, tmp2); 55268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 55278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 4: 55285285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_neon_rsb(size, tmp, tmp2); 55298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 55308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 5: 55315285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_neon_sub_f32(tmp, tmp2, tmp); 55328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 55338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project default: 55348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project abort(); 55358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 55365285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 55378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 55385285864985be9077e58e42235af6582dee72e841David 'Digit' Turner neon_store_reg(rd, pass, tmp); 55398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 55408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 55418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 3: /* VQDMLAL scalar */ 55428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 7: /* VQDMLSL scalar */ 55438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 11: /* VQDMULL scalar */ 55445285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (u == 1) { 55458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 55465285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 55475285864985be9077e58e42235af6582dee72e841David 'Digit' Turner /* fall through */ 55485285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 2: /* VMLAL sclar */ 55495285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 6: /* VMLSL scalar */ 55505285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 10: /* VMULL scalar */ 55515285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (rd & 1) { 55525285864985be9077e58e42235af6582dee72e841David 'Digit' Turner return 1; 55535285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 55545285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp2 = neon_get_scalar(size, rm); 55555285864985be9077e58e42235af6582dee72e841David 'Digit' Turner /* We need a copy of tmp2 because gen_neon_mull 55565285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * deletes it during pass 0. */ 55575285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp4 = tcg_temp_new_i32(); 55585285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_mov_i32(tmp4, tmp2); 55595285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp3 = neon_load_reg(rn, 1); 55608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 55618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project for (pass = 0; pass < 2; pass++) { 55628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (pass == 0) { 55638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = neon_load_reg(rn, 0); 55648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 55655285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = tmp3; 55665285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp2 = tmp4; 55678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 55688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_neon_mull(cpu_V0, tmp, tmp2, size, u); 55698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (op != 11) { 55708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project neon_load_reg64(cpu_V1, rd + pass); 55718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 55728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (op) { 55735285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 6: 55745285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_neon_negl(cpu_V0, size); 55755285864985be9077e58e42235af6582dee72e841David 'Digit' Turner /* Fall through */ 55765285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 2: 55778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_neon_addl(size); 55788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 55798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 3: case 7: 55808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_neon_addl_saturate(cpu_V0, cpu_V0, size); 55815285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (op == 7) { 55825285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_neon_negl(cpu_V0, size); 55835285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 55848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_neon_addl_saturate(cpu_V0, cpu_V1, size); 55858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 55868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 10: 55878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* no-op */ 55888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 55898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 11: 55908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_neon_addl_saturate(cpu_V0, cpu_V0, size); 55918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 55928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project default: 55938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project abort(); 55948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 55958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project neon_store_reg64(cpu_V0, rd + pass); 55968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 55975285864985be9077e58e42235af6582dee72e841David 'Digit' Turner 55985285864985be9077e58e42235af6582dee72e841David 'Digit' Turner 55998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 56008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project default: /* 14 and 15 are RESERVED */ 56018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 56028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 56038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 56048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { /* size == 3 */ 56058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (!u) { 56068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Extract. */ 56078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project imm = (insn >> 8) & 0xf; 56088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 56098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (imm > 7 && !q) 56108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 56118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 56125285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (q && ((rd | rn | rm) & 1)) { 56135285864985be9077e58e42235af6582dee72e841David 'Digit' Turner return 1; 56145285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 56155285864985be9077e58e42235af6582dee72e841David 'Digit' Turner 56168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (imm == 0) { 56178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project neon_load_reg64(cpu_V0, rn); 56188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (q) { 56198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project neon_load_reg64(cpu_V1, rn + 1); 56208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 56218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else if (imm == 8) { 56228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project neon_load_reg64(cpu_V0, rn + 1); 56238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (q) { 56248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project neon_load_reg64(cpu_V1, rm); 56258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 56268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else if (q) { 56275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tmp64 = tcg_temp_new_i64(); 56288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (imm < 8) { 56298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project neon_load_reg64(cpu_V0, rn); 56305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner neon_load_reg64(tmp64, rn + 1); 56318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 56328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project neon_load_reg64(cpu_V0, rn + 1); 56335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner neon_load_reg64(tmp64, rm); 56348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 56358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_shri_i64(cpu_V0, cpu_V0, (imm & 7) * 8); 56365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tcg_gen_shli_i64(cpu_V1, tmp64, 64 - ((imm & 7) * 8)); 56378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_or_i64(cpu_V0, cpu_V0, cpu_V1); 56388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (imm < 8) { 56398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project neon_load_reg64(cpu_V1, rm); 56408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 56418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project neon_load_reg64(cpu_V1, rm + 1); 56428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project imm -= 8; 56438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 56448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_shli_i64(cpu_V1, cpu_V1, 64 - (imm * 8)); 56455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tcg_gen_shri_i64(tmp64, tmp64, imm * 8); 56465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tcg_gen_or_i64(cpu_V1, cpu_V1, tmp64); 56475285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i64(tmp64); 56488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 56495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* BUGFIX */ 56508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project neon_load_reg64(cpu_V0, rn); 56515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tcg_gen_shri_i64(cpu_V0, cpu_V0, imm * 8); 56528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project neon_load_reg64(cpu_V1, rm); 56535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tcg_gen_shli_i64(cpu_V1, cpu_V1, 64 - (imm * 8)); 56548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_or_i64(cpu_V0, cpu_V0, cpu_V1); 56558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 56568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project neon_store_reg64(cpu_V0, rd); 56578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (q) { 56588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project neon_store_reg64(cpu_V1, rd + 1); 56598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 56608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else if ((insn & (1 << 11)) == 0) { 56618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Two register misc. */ 56628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project op = ((insn >> 12) & 0x30) | ((insn >> 7) & 0xf); 56638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project size = (insn >> 18) & 3; 56645285864985be9077e58e42235af6582dee72e841David 'Digit' Turner /* UNDEF for unknown op values and bad op-size combinations */ 56655285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if ((neon_2rm_sizes[op] & (1 << size)) == 0) { 56665285864985be9077e58e42235af6582dee72e841David 'Digit' Turner return 1; 56675285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 56685285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if ((op != NEON_2RM_VMOVN && op != NEON_2RM_VQMOVN) && 56695285864985be9077e58e42235af6582dee72e841David 'Digit' Turner q && ((rm | rd) & 1)) { 56705285864985be9077e58e42235af6582dee72e841David 'Digit' Turner return 1; 56715285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 56728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (op) { 56735285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_2RM_VREV64: 56748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project for (pass = 0; pass < (q ? 2 : 1); pass++) { 56755285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = neon_load_reg(rm, pass * 2); 56765285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp2 = neon_load_reg(rm, pass * 2 + 1); 56778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (size) { 56785285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 0: tcg_gen_bswap32_i32(tmp, tmp); break; 56795285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 1: gen_swap_half(tmp); break; 56808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 2: /* no-op */ break; 56818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project default: abort(); 56828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 56835285864985be9077e58e42235af6582dee72e841David 'Digit' Turner neon_store_reg(rd, pass * 2 + 1, tmp); 56848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (size == 2) { 56855285864985be9077e58e42235af6582dee72e841David 'Digit' Turner neon_store_reg(rd, pass * 2, tmp2); 56868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 56878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (size) { 56885285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 0: tcg_gen_bswap32_i32(tmp2, tmp2); break; 56895285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 1: gen_swap_half(tmp2); break; 56908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project default: abort(); 56918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 56925285864985be9077e58e42235af6582dee72e841David 'Digit' Turner neon_store_reg(rd, pass * 2, tmp2); 56938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 56948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 56958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 56965285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_2RM_VPADDL: case NEON_2RM_VPADDL_U: 56975285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_2RM_VPADAL: case NEON_2RM_VPADAL_U: 56988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project for (pass = 0; pass < q + 1; pass++) { 56998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = neon_load_reg(rm, pass * 2); 57008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_neon_widen(cpu_V0, tmp, size, op & 1); 57018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = neon_load_reg(rm, pass * 2 + 1); 57028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_neon_widen(cpu_V1, tmp, size, op & 1); 57038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (size) { 57048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0: gen_helper_neon_paddl_u16(CPU_V001); break; 57058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 1: gen_helper_neon_paddl_u32(CPU_V001); break; 57068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 2: tcg_gen_add_i64(CPU_V001); break; 57078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project default: abort(); 57088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 57095285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (op >= NEON_2RM_VPADAL) { 57108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Accumulate. */ 57118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project neon_load_reg64(cpu_V1, rd + pass); 57128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_neon_addl(size); 57138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 57148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project neon_store_reg64(cpu_V0, rd + pass); 57158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 57168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 57175285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_2RM_VTRN: 57188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (size == 2) { 57195285864985be9077e58e42235af6582dee72e841David 'Digit' Turner int n; 57208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project for (n = 0; n < (q ? 4 : 2); n += 2) { 57215285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = neon_load_reg(rm, n); 57225285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp2 = neon_load_reg(rd, n + 1); 57235285864985be9077e58e42235af6582dee72e841David 'Digit' Turner neon_store_reg(rm, n, tmp2); 57245285864985be9077e58e42235af6582dee72e841David 'Digit' Turner neon_store_reg(rd, n + 1, tmp); 57258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 57268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 57278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto elementwise; 57288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 57298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 57305285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_2RM_VUZP: 57315285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (gen_neon_unzip(rd, rm, size, q)) { 57328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 57338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 57348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 57355285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_2RM_VZIP: 57365285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (gen_neon_zip(rd, rm, size, q)) { 57378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 57388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 57398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 57405285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_2RM_VMOVN: case NEON_2RM_VQMOVN: 57415285864985be9077e58e42235af6582dee72e841David 'Digit' Turner /* also VQMOVUN; op field and mnemonics don't line up */ 57425285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (rm & 1) { 57438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 57445285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 57458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project TCGV_UNUSED(tmp2); 57468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project for (pass = 0; pass < 2; pass++) { 57478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project neon_load_reg64(cpu_V0, rm + pass); 57485285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = tcg_temp_new_i32(); 57495285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_neon_narrow_op(op == NEON_2RM_VMOVN, q, size, 57505285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp, cpu_V0); 57518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (pass == 0) { 57528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp2 = tmp; 57538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 57548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project neon_store_reg(rd, 0, tmp2); 57558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project neon_store_reg(rd, 1, tmp); 57568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 57578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 57588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 57595285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_2RM_VSHLL: 57605285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (q || (rd & 1)) { 57618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 57625285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 57638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = neon_load_reg(rm, 0); 57648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp2 = neon_load_reg(rm, 1); 57658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project for (pass = 0; pass < 2; pass++) { 57668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (pass == 1) 57678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = tmp2; 57688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_neon_widen(cpu_V0, tmp, size, 1); 57695285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_shli_i64(cpu_V0, cpu_V0, 8 << size); 57708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project neon_store_reg64(cpu_V0, rd + pass); 57718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 57728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 57735285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_2RM_VCVT_F16_F32: 57745285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (!arm_feature(env, ARM_FEATURE_VFP_FP16) || 57755285864985be9077e58e42235af6582dee72e841David 'Digit' Turner q || (rm & 1)) { 57765285864985be9077e58e42235af6582dee72e841David 'Digit' Turner return 1; 57775285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 57785285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = tcg_temp_new_i32(); 57795285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp2 = tcg_temp_new_i32(); 57805285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, 0)); 57815285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_neon_fcvt_f32_to_f16(tmp, cpu_F0s, cpu_env); 57825285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, 1)); 57835285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_neon_fcvt_f32_to_f16(tmp2, cpu_F0s, cpu_env); 57845285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_shli_i32(tmp2, tmp2, 16); 57855285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_or_i32(tmp2, tmp2, tmp); 57865285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, 2)); 57875285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_neon_fcvt_f32_to_f16(tmp, cpu_F0s, cpu_env); 57885285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, 3)); 57895285864985be9077e58e42235af6582dee72e841David 'Digit' Turner neon_store_reg(rd, 0, tmp2); 57905285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp2 = tcg_temp_new_i32(); 57915285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_neon_fcvt_f32_to_f16(tmp2, cpu_F0s, cpu_env); 57925285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_shli_i32(tmp2, tmp2, 16); 57935285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_or_i32(tmp2, tmp2, tmp); 57945285864985be9077e58e42235af6582dee72e841David 'Digit' Turner neon_store_reg(rd, 1, tmp2); 57955285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 57965285864985be9077e58e42235af6582dee72e841David 'Digit' Turner break; 57975285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_2RM_VCVT_F32_F16: 57985285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (!arm_feature(env, ARM_FEATURE_VFP_FP16) || 57995285864985be9077e58e42235af6582dee72e841David 'Digit' Turner q || (rd & 1)) { 58005285864985be9077e58e42235af6582dee72e841David 'Digit' Turner return 1; 58015285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 58025285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp3 = tcg_temp_new_i32(); 58035285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = neon_load_reg(rm, 0); 58045285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp2 = neon_load_reg(rm, 1); 58055285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_ext16u_i32(tmp3, tmp); 58065285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_neon_fcvt_f16_to_f32(cpu_F0s, tmp3, cpu_env); 58075285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, 0)); 58085285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_shri_i32(tmp3, tmp, 16); 58095285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_neon_fcvt_f16_to_f32(cpu_F0s, tmp3, cpu_env); 58105285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, 1)); 58115285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 58125285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_ext16u_i32(tmp3, tmp2); 58135285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_neon_fcvt_f16_to_f32(cpu_F0s, tmp3, cpu_env); 58145285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, 2)); 58155285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_shri_i32(tmp3, tmp2, 16); 58165285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_neon_fcvt_f16_to_f32(cpu_F0s, tmp3, cpu_env); 58175285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, 3)); 58185285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 58195285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp3); 58205285864985be9077e58e42235af6582dee72e841David 'Digit' Turner break; 58218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project default: 58228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project elementwise: 58238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project for (pass = 0; pass < (q ? 4 : 2); pass++) { 58245285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (neon_2rm_is_float_op(op)) { 58258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_ld_f32(cpu_F0s, cpu_env, 58268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project neon_reg_offset(rm, pass)); 58275285864985be9077e58e42235af6582dee72e841David 'Digit' Turner TCGV_UNUSED(tmp); 58288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 58295285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = neon_load_reg(rm, pass); 58308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 58318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (op) { 58325285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_2RM_VREV32: 58338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (size) { 58345285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 0: tcg_gen_bswap32_i32(tmp, tmp); break; 58355285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 1: gen_swap_half(tmp); break; 58365285864985be9077e58e42235af6582dee72e841David 'Digit' Turner default: abort(); 58378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 58388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 58395285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_2RM_VREV16: 58405285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_rev16(tmp); 58418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 58425285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_2RM_VCLS: 58438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (size) { 58445285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 0: gen_helper_neon_cls_s8(tmp, tmp); break; 58455285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 1: gen_helper_neon_cls_s16(tmp, tmp); break; 58465285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 2: gen_helper_neon_cls_s32(tmp, tmp); break; 58475285864985be9077e58e42235af6582dee72e841David 'Digit' Turner default: abort(); 58488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 58498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 58505285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_2RM_VCLZ: 58518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (size) { 58525285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 0: gen_helper_neon_clz_u8(tmp, tmp); break; 58535285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 1: gen_helper_neon_clz_u16(tmp, tmp); break; 58545285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 2: gen_helper_clz(tmp, tmp); break; 58555285864985be9077e58e42235af6582dee72e841David 'Digit' Turner default: abort(); 58568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 58578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 58585285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_2RM_VCNT: 58595285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_neon_cnt_u8(tmp, tmp); 58608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 58615285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_2RM_VMVN: 58625285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_not_i32(tmp, tmp); 58638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 58645285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_2RM_VQABS: 58658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (size) { 58665285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 0: gen_helper_neon_qabs_s8(tmp, tmp); break; 58675285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 1: gen_helper_neon_qabs_s16(tmp, tmp); break; 58685285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 2: gen_helper_neon_qabs_s32(tmp, tmp); break; 58695285864985be9077e58e42235af6582dee72e841David 'Digit' Turner default: abort(); 58708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 58718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 58725285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_2RM_VQNEG: 58738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (size) { 58745285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 0: gen_helper_neon_qneg_s8(tmp, tmp); break; 58755285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 1: gen_helper_neon_qneg_s16(tmp, tmp); break; 58765285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 2: gen_helper_neon_qneg_s32(tmp, tmp); break; 58775285864985be9077e58e42235af6582dee72e841David 'Digit' Turner default: abort(); 58788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 58798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 58805285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_2RM_VCGT0: case NEON_2RM_VCLE0: 58815285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp2 = tcg_const_i32(0); 58828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch(size) { 58835285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 0: gen_helper_neon_cgt_s8(tmp, tmp, tmp2); break; 58845285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 1: gen_helper_neon_cgt_s16(tmp, tmp, tmp2); break; 58855285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 2: gen_helper_neon_cgt_s32(tmp, tmp, tmp2); break; 58865285864985be9077e58e42235af6582dee72e841David 'Digit' Turner default: abort(); 58875285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 58885285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free(tmp2); 58895285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (op == NEON_2RM_VCLE0) { 58905285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_not_i32(tmp, tmp); 58918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 58928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 58935285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_2RM_VCGE0: case NEON_2RM_VCLT0: 58945285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp2 = tcg_const_i32(0); 58958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch(size) { 58965285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 0: gen_helper_neon_cge_s8(tmp, tmp, tmp2); break; 58975285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 1: gen_helper_neon_cge_s16(tmp, tmp, tmp2); break; 58985285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 2: gen_helper_neon_cge_s32(tmp, tmp, tmp2); break; 58995285864985be9077e58e42235af6582dee72e841David 'Digit' Turner default: abort(); 59005285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 59015285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free(tmp2); 59025285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (op == NEON_2RM_VCLT0) { 59035285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_not_i32(tmp, tmp); 59048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 59058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 59065285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_2RM_VCEQ0: 59075285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp2 = tcg_const_i32(0); 59088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch(size) { 59095285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 0: gen_helper_neon_ceq_u8(tmp, tmp, tmp2); break; 59105285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 1: gen_helper_neon_ceq_u16(tmp, tmp, tmp2); break; 59115285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 2: gen_helper_neon_ceq_u32(tmp, tmp, tmp2); break; 59125285864985be9077e58e42235af6582dee72e841David 'Digit' Turner default: abort(); 59138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 59145285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free(tmp2); 59158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 59165285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_2RM_VABS: 59178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch(size) { 59185285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 0: gen_helper_neon_abs_s8(tmp, tmp); break; 59195285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 1: gen_helper_neon_abs_s16(tmp, tmp); break; 59205285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 2: tcg_gen_abs_i32(tmp, tmp); break; 59215285864985be9077e58e42235af6582dee72e841David 'Digit' Turner default: abort(); 59228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 59238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 59245285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_2RM_VNEG: 59255285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp2 = tcg_const_i32(0); 59265285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_neon_rsb(size, tmp, tmp2); 59275285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free(tmp2); 59288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 59295285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_2RM_VCGT0_F: 59305285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp2 = tcg_const_i32(0); 59315285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_neon_cgt_f32(tmp, tmp, tmp2); 59325285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free(tmp2); 59338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 59345285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_2RM_VCGE0_F: 59355285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp2 = tcg_const_i32(0); 59365285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_neon_cge_f32(tmp, tmp, tmp2); 59375285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free(tmp2); 59388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 59395285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_2RM_VCEQ0_F: 59405285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp2 = tcg_const_i32(0); 59415285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_neon_ceq_f32(tmp, tmp, tmp2); 59425285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free(tmp2); 59438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 59445285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_2RM_VCLE0_F: 59455285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp2 = tcg_const_i32(0); 59465285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_neon_cge_f32(tmp, tmp2, tmp); 59475285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free(tmp2); 59485285864985be9077e58e42235af6582dee72e841David 'Digit' Turner break; 59495285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_2RM_VCLT0_F: 59505285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp2 = tcg_const_i32(0); 59515285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_neon_cgt_f32(tmp, tmp2, tmp); 59525285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free(tmp2); 59535285864985be9077e58e42235af6582dee72e841David 'Digit' Turner break; 59545285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_2RM_VABS_F: 59558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_vfp_abs(0); 59568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 59575285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_2RM_VNEG_F: 59588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_vfp_neg(0); 59598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 59605285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_2RM_VSWP: 59615285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp2 = neon_load_reg(rd, pass); 59625285864985be9077e58e42235af6582dee72e841David 'Digit' Turner neon_store_reg(rm, pass, tmp2); 59638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 59645285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_2RM_VTRN: 59655285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp2 = neon_load_reg(rd, pass); 59668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (size) { 59675285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 0: gen_neon_trn_u8(tmp, tmp2); break; 59685285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 1: gen_neon_trn_u16(tmp, tmp2); break; 59695285864985be9077e58e42235af6582dee72e841David 'Digit' Turner default: abort(); 59708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 59715285864985be9077e58e42235af6582dee72e841David 'Digit' Turner neon_store_reg(rm, pass, tmp2); 59728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 59735285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_2RM_VRECPE: 59745285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_recpe_u32(tmp, tmp, cpu_env); 59758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 59765285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_2RM_VRSQRTE: 59775285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_rsqrte_u32(tmp, tmp, cpu_env); 59788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 59795285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_2RM_VRECPE_F: 59808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_helper_recpe_f32(cpu_F0s, cpu_F0s, cpu_env); 59818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 59825285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_2RM_VRSQRTE_F: 59838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_helper_rsqrte_f32(cpu_F0s, cpu_F0s, cpu_env); 59848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 59855285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_2RM_VCVT_FS: /* VCVT.F32.S32 */ 59865285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_vfp_sito(0, 1); 59878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 59885285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_2RM_VCVT_FU: /* VCVT.F32.U32 */ 59895285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_vfp_uito(0, 1); 59908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 59915285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_2RM_VCVT_SF: /* VCVT.S32.F32 */ 59925285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_vfp_tosiz(0, 1); 59938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 59945285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case NEON_2RM_VCVT_UF: /* VCVT.U32.F32 */ 59955285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_vfp_touiz(0, 1); 59968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 59978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project default: 59985285864985be9077e58e42235af6582dee72e841David 'Digit' Turner /* Reserved op values were caught by the 59995285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * neon_2rm_sizes[] check earlier. 60005285864985be9077e58e42235af6582dee72e841David 'Digit' Turner */ 60015285864985be9077e58e42235af6582dee72e841David 'Digit' Turner abort(); 60028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 60035285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (neon_2rm_is_float_op(op)) { 60048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_st_f32(cpu_F0s, cpu_env, 60058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project neon_reg_offset(rd, pass)); 60068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 60075285864985be9077e58e42235af6582dee72e841David 'Digit' Turner neon_store_reg(rd, pass, tmp); 60088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 60098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 60108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 60118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 60128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else if ((insn & (1 << 10)) == 0) { 60138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* VTBL, VTBX. */ 60145285864985be9077e58e42235af6582dee72e841David 'Digit' Turner int n = ((insn >> 8) & 3) + 1; 60155285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if ((rn + n) > 32) { 60165285864985be9077e58e42235af6582dee72e841David 'Digit' Turner /* This is UNPREDICTABLE; we choose to UNDEF to avoid the 60175285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * helper function running off the end of the register file. 60185285864985be9077e58e42235af6582dee72e841David 'Digit' Turner */ 60195285864985be9077e58e42235af6582dee72e841David 'Digit' Turner return 1; 60205285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 60215285864985be9077e58e42235af6582dee72e841David 'Digit' Turner n <<= 3; 60228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 6)) { 60238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = neon_load_reg(rd, 0); 60248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 60255285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = tcg_temp_new_i32(); 60268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_movi_i32(tmp, 0); 60278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 60288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp2 = neon_load_reg(rm, 0); 60295285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp4 = tcg_const_i32(rn); 60305285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp5 = tcg_const_i32(n); 60315285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_neon_tbl(tmp2, tmp2, tmp, tmp4, tmp5); 60325285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 60338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 6)) { 60348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = neon_load_reg(rd, 1); 60358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 60365285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = tcg_temp_new_i32(); 60378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_movi_i32(tmp, 0); 60388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 60398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp3 = neon_load_reg(rm, 1); 60405285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_neon_tbl(tmp3, tmp3, tmp, tmp4, tmp5); 60415285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp5); 60425285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp4); 60438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project neon_store_reg(rd, 0, tmp2); 60445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner neon_store_reg(rd, 1, tmp3); 60455285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 60468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else if ((insn & 0x380) == 0) { 60478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* VDUP */ 60485285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if ((insn & (7 << 16)) == 0 || (q && (rd & 1))) { 60495285864985be9077e58e42235af6582dee72e841David 'Digit' Turner return 1; 60505285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 60518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 19)) { 60525285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = neon_load_reg(rm, 1); 60538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 60545285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = neon_load_reg(rm, 0); 60558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 60568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 16)) { 60575285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_neon_dup_u8(tmp, ((insn >> 17) & 3) * 8); 60588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else if (insn & (1 << 17)) { 60598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if ((insn >> 18) & 1) 60605285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_neon_dup_high16(tmp); 60618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 60625285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_neon_dup_low16(tmp); 60638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 60648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project for (pass = 0; pass < (q ? 4 : 2); pass++) { 60655285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp2 = tcg_temp_new_i32(); 60665285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_mov_i32(tmp2, tmp); 60675285864985be9077e58e42235af6582dee72e841David 'Digit' Turner neon_store_reg(rd, pass, tmp2); 60688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 60695285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 60708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 60718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 60728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 60738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 60748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 60758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 0; 60768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 60778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 60785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic int disas_cp14_read(CPUState * env, DisasContext *s, uint32_t insn) 60795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 60805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int crn = (insn >> 16) & 0xf; 60815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int crm = insn & 0xf; 60825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int op1 = (insn >> 21) & 7; 60835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int op2 = (insn >> 5) & 7; 60845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int rt = (insn >> 12) & 0xf; 60855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner TCGv tmp; 60865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 60875285864985be9077e58e42235af6582dee72e841David 'Digit' Turner /* Minimal set of debug registers, since we don't support debug */ 60885285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (op1 == 0 && crn == 0 && op2 == 0) { 60895285864985be9077e58e42235af6582dee72e841David 'Digit' Turner switch (crm) { 60905285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 0: 60915285864985be9077e58e42235af6582dee72e841David 'Digit' Turner /* DBGDIDR: just RAZ. In particular this means the 60925285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * "debug architecture version" bits will read as 60935285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * a reserved value, which should cause Linux to 60945285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * not try to use the debug hardware. 60955285864985be9077e58e42235af6582dee72e841David 'Digit' Turner */ 60965285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = tcg_const_i32(0); 60975285864985be9077e58e42235af6582dee72e841David 'Digit' Turner store_reg(s, rt, tmp); 60985285864985be9077e58e42235af6582dee72e841David 'Digit' Turner return 0; 60995285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 1: 61005285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 2: 61015285864985be9077e58e42235af6582dee72e841David 'Digit' Turner /* DBGDRAR and DBGDSAR: v7 only. Always RAZ since we 61025285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * don't implement memory mapped debug components 61035285864985be9077e58e42235af6582dee72e841David 'Digit' Turner */ 61045285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (ENABLE_ARCH_7) { 61055285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = tcg_const_i32(0); 61065285864985be9077e58e42235af6582dee72e841David 'Digit' Turner store_reg(s, rt, tmp); 61075285864985be9077e58e42235af6582dee72e841David 'Digit' Turner return 0; 61085285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 61095285864985be9077e58e42235af6582dee72e841David 'Digit' Turner break; 61105285864985be9077e58e42235af6582dee72e841David 'Digit' Turner default: 61115285864985be9077e58e42235af6582dee72e841David 'Digit' Turner break; 61125285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 61135285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 61145285864985be9077e58e42235af6582dee72e841David 'Digit' Turner 61155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (arm_feature(env, ARM_FEATURE_THUMB2EE)) { 61165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (op1 == 6 && crn == 0 && crm == 0 && op2 == 0) { 61175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* TEECR */ 61185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (IS_USER(s)) 61195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return 1; 61205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tmp = load_cpu_field(teecr); 61215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner store_reg(s, rt, tmp); 61225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return 0; 61235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 61245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (op1 == 6 && crn == 1 && crm == 0 && op2 == 0) { 61255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* TEEHBR */ 61265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (IS_USER(s) && (env->teecr & 1)) 61275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return 1; 61285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tmp = load_cpu_field(teehbr); 61295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner store_reg(s, rt, tmp); 61305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return 0; 61315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 61325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 61335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner fprintf(stderr, "Unknown cp14 read op1:%d crn:%d crm:%d op2:%d\n", 61345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner op1, crn, crm, op2); 61355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return 1; 61365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 61375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 61385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic int disas_cp14_write(CPUState * env, DisasContext *s, uint32_t insn) 61395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 61405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int crn = (insn >> 16) & 0xf; 61415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int crm = insn & 0xf; 61425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int op1 = (insn >> 21) & 7; 61435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int op2 = (insn >> 5) & 7; 61445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int rt = (insn >> 12) & 0xf; 61455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner TCGv tmp; 61465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 61475285864985be9077e58e42235af6582dee72e841David 'Digit' Turner /* Minimal set of debug registers, since we don't support debug */ 61485285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (op1 == 0 && crn == 0 && op2 == 0) { 61495285864985be9077e58e42235af6582dee72e841David 'Digit' Turner switch (crm) { 61505285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 0: 61515285864985be9077e58e42235af6582dee72e841David 'Digit' Turner /* DBGDIDR */ 61525285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = load_cpu_field(cp14_dbgdidr); 61535285864985be9077e58e42235af6582dee72e841David 'Digit' Turner store_reg(s, rt, tmp); 61545285864985be9077e58e42235af6582dee72e841David 'Digit' Turner return 0; 61555285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 1: 61565285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 2: 61575285864985be9077e58e42235af6582dee72e841David 'Digit' Turner /* DBGDRAR and DBGDSAR: v7 only. Always RAZ since we 61585285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * don't implement memory mapped debug components 61595285864985be9077e58e42235af6582dee72e841David 'Digit' Turner */ 61605285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (ENABLE_ARCH_7) { 61615285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = tcg_const_i32(0); 61625285864985be9077e58e42235af6582dee72e841David 'Digit' Turner store_reg(s, rt, tmp); 61635285864985be9077e58e42235af6582dee72e841David 'Digit' Turner return 0; 61645285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 61655285864985be9077e58e42235af6582dee72e841David 'Digit' Turner break; 61665285864985be9077e58e42235af6582dee72e841David 'Digit' Turner default: 61675285864985be9077e58e42235af6582dee72e841David 'Digit' Turner break; 61685285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 61695285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 61705285864985be9077e58e42235af6582dee72e841David 'Digit' Turner 61715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (arm_feature(env, ARM_FEATURE_THUMB2EE)) { 61725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (op1 == 6 && crn == 0 && crm == 0 && op2 == 0) { 61735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* TEECR */ 61745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (IS_USER(s)) 61755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return 1; 61765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tmp = load_reg(s, rt); 61775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner gen_helper_set_teecr(cpu_env, tmp); 61785285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 61795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return 0; 61805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 61815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (op1 == 6 && crn == 1 && crm == 0 && op2 == 0) { 61825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* TEEHBR */ 61835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (IS_USER(s) && (env->teecr & 1)) 61845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return 1; 61855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tmp = load_reg(s, rt); 61865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner store_cpu_field(tmp, teehbr); 61875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return 0; 61885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 61895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 61905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner fprintf(stderr, "Unknown cp14 write op1:%d crn:%d crm:%d op2:%d\n", 61915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner op1, crn, crm, op2); 61925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return 1; 61935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 61945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 61958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int disas_coproc_insn(CPUState * env, DisasContext *s, uint32_t insn) 61968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 61978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int cpnum; 61988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 61998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project cpnum = (insn >> 8) & 0xf; 62008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (arm_feature(env, ARM_FEATURE_XSCALE) 62018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project && ((env->cp15.c15_cpar ^ 0x3fff) & (1 << cpnum))) 62028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 62038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 62048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (cpnum) { 62058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0: 62068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 1: 62078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (arm_feature(env, ARM_FEATURE_IWMMXT)) { 62088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return disas_iwmmxt_insn(env, s, insn); 62098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else if (arm_feature(env, ARM_FEATURE_XSCALE)) { 62108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return disas_dsp_insn(env, s, insn); 62118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 62125285864985be9077e58e42235af6582dee72e841David 'Digit' Turner goto board; 62138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 10: 62148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 11: 62158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return disas_vfp_insn (env, s, insn); 62165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner case 14: 62175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* Coprocessors 7-15 are architecturally reserved by ARM. 62185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner Unfortunately Intel decided to ignore this. */ 62195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (arm_feature(env, ARM_FEATURE_XSCALE)) 62205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner goto board; 62215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (insn & (1 << 20)) 62225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return disas_cp14_read(env, s, insn); 62235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner else 62245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return disas_cp14_write(env, s, insn); 62258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 15: 62268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return disas_cp15_insn (env, s, insn); 62278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project default: 62285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner board: 62298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Unknown coprocessor. See if the board has hooked it. */ 62308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return disas_cp_insn (env, s, insn); 62318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 62328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 62338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 62348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 62358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Store a 64-bit value to a register pair. Clobbers val. */ 62365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void gen_storeq_reg(DisasContext *s, int rlow, int rhigh, TCGv_i64 val) 62378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 62388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project TCGv tmp; 62395285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = tcg_temp_new_i32(); 62408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_trunc_i64_i32(tmp, val); 62418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project store_reg(s, rlow, tmp); 62425285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = tcg_temp_new_i32(); 62438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_shri_i64(val, val, 32); 62448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_trunc_i64_i32(tmp, val); 62458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project store_reg(s, rhigh, tmp); 62468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 62478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 62488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* load a 32-bit value from a register and perform a 64-bit accumulate. */ 62495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void gen_addq_lo(DisasContext *s, TCGv_i64 val, int rlow) 62508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 62515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner TCGv_i64 tmp; 62528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project TCGv tmp2; 62538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 62545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* Load value and extend to 64 bits. */ 62555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tmp = tcg_temp_new_i64(); 62568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp2 = load_reg(s, rlow); 62578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_extu_i32_i64(tmp, tmp2); 62585285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 62598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_add_i64(val, val, tmp); 62605285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i64(tmp); 62618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 62628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 62638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* load and add a 64-bit value from a register pair. */ 62645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void gen_addq(DisasContext *s, TCGv_i64 val, int rlow, int rhigh) 62658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 62665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner TCGv_i64 tmp; 62675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner TCGv tmpl; 62685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner TCGv tmph; 62698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 62708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Load 64-bit value rd:rn. */ 62715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tmpl = load_reg(s, rlow); 62725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tmph = load_reg(s, rhigh); 62735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tmp = tcg_temp_new_i64(); 62745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tcg_gen_concat_i32_i64(tmp, tmpl, tmph); 62755285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmpl); 62765285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmph); 62778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_add_i64(val, val, tmp); 62785285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i64(tmp); 62798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 62808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 62818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Set N and Z flags from a 64-bit value. */ 62825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void gen_logicq_cc(TCGv_i64 val) 62838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 62845285864985be9077e58e42235af6582dee72e841David 'Digit' Turner TCGv tmp = tcg_temp_new_i32(); 62858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_helper_logicq_cc(tmp, val); 62868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_logic_CC(tmp); 62875285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 62885285864985be9077e58e42235af6582dee72e841David 'Digit' Turner} 62895285864985be9077e58e42235af6582dee72e841David 'Digit' Turner 62905285864985be9077e58e42235af6582dee72e841David 'Digit' Turner/* Load/Store exclusive instructions are implemented by remembering 62915285864985be9077e58e42235af6582dee72e841David 'Digit' Turner the value/address loaded, and seeing if these are the same 62925285864985be9077e58e42235af6582dee72e841David 'Digit' Turner when the store is performed. This should be is sufficient to implement 62935285864985be9077e58e42235af6582dee72e841David 'Digit' Turner the architecturally mandated semantics, and avoids having to monitor 62945285864985be9077e58e42235af6582dee72e841David 'Digit' Turner regular stores. 62955285864985be9077e58e42235af6582dee72e841David 'Digit' Turner 62965285864985be9077e58e42235af6582dee72e841David 'Digit' Turner In system emulation mode only one CPU will be running at once, so 62975285864985be9077e58e42235af6582dee72e841David 'Digit' Turner this sequence is effectively atomic. In user emulation mode we 62985285864985be9077e58e42235af6582dee72e841David 'Digit' Turner throw an exception and handle the atomic operation elsewhere. */ 62995285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic void gen_load_exclusive(DisasContext *s, int rt, int rt2, 63005285864985be9077e58e42235af6582dee72e841David 'Digit' Turner TCGv addr, int size) 63015285864985be9077e58e42235af6582dee72e841David 'Digit' Turner{ 63025285864985be9077e58e42235af6582dee72e841David 'Digit' Turner TCGv tmp; 63035285864985be9077e58e42235af6582dee72e841David 'Digit' Turner 63045285864985be9077e58e42235af6582dee72e841David 'Digit' Turner switch (size) { 63055285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 0: 63065285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = gen_ld8u(addr, IS_USER(s)); 63075285864985be9077e58e42235af6582dee72e841David 'Digit' Turner break; 63085285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 1: 63095285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = gen_ld16u(addr, IS_USER(s)); 63105285864985be9077e58e42235af6582dee72e841David 'Digit' Turner break; 63115285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 2: 63125285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 3: 63135285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = gen_ld32(addr, IS_USER(s)); 63145285864985be9077e58e42235af6582dee72e841David 'Digit' Turner break; 63155285864985be9077e58e42235af6582dee72e841David 'Digit' Turner default: 63165285864985be9077e58e42235af6582dee72e841David 'Digit' Turner abort(); 63175285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 63185285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_mov_i32(cpu_exclusive_val, tmp); 63195285864985be9077e58e42235af6582dee72e841David 'Digit' Turner store_reg(s, rt, tmp); 63205285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (size == 3) { 63215285864985be9077e58e42235af6582dee72e841David 'Digit' Turner TCGv tmp2 = tcg_temp_new_i32(); 63225285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_addi_i32(tmp2, addr, 4); 63235285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = gen_ld32(tmp2, IS_USER(s)); 63245285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 63255285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_mov_i32(cpu_exclusive_high, tmp); 63265285864985be9077e58e42235af6582dee72e841David 'Digit' Turner store_reg(s, rt2, tmp); 63275285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 63285285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_mov_i32(cpu_exclusive_addr, addr); 63295285864985be9077e58e42235af6582dee72e841David 'Digit' Turner} 63305285864985be9077e58e42235af6582dee72e841David 'Digit' Turner 63315285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic void gen_clrex(DisasContext *s) 63325285864985be9077e58e42235af6582dee72e841David 'Digit' Turner{ 63335285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_movi_i32(cpu_exclusive_addr, -1); 63348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 63358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 63365285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#ifdef CONFIG_USER_ONLY 63375285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic void gen_store_exclusive(DisasContext *s, int rd, int rt, int rt2, 63385285864985be9077e58e42235af6582dee72e841David 'Digit' Turner TCGv addr, int size) 63395285864985be9077e58e42235af6582dee72e841David 'Digit' Turner{ 63405285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_mov_i32(cpu_exclusive_test, addr); 63415285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_movi_i32(cpu_exclusive_info, 63425285864985be9077e58e42235af6582dee72e841David 'Digit' Turner size | (rd << 4) | (rt << 8) | (rt2 << 12)); 63435285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_exception_insn(s, 4, EXCP_STREX); 63445285864985be9077e58e42235af6582dee72e841David 'Digit' Turner} 63455285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#else 63465285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic void gen_store_exclusive(DisasContext *s, int rd, int rt, int rt2, 63475285864985be9077e58e42235af6582dee72e841David 'Digit' Turner TCGv addr, int size) 63485285864985be9077e58e42235af6582dee72e841David 'Digit' Turner{ 63495285864985be9077e58e42235af6582dee72e841David 'Digit' Turner TCGv tmp; 63505285864985be9077e58e42235af6582dee72e841David 'Digit' Turner int done_label; 63515285864985be9077e58e42235af6582dee72e841David 'Digit' Turner int fail_label; 63525285864985be9077e58e42235af6582dee72e841David 'Digit' Turner 63535285864985be9077e58e42235af6582dee72e841David 'Digit' Turner /* if (env->exclusive_addr == addr && env->exclusive_val == [addr]) { 63545285864985be9077e58e42235af6582dee72e841David 'Digit' Turner [addr] = {Rt}; 63555285864985be9077e58e42235af6582dee72e841David 'Digit' Turner {Rd} = 0; 63565285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } else { 63575285864985be9077e58e42235af6582dee72e841David 'Digit' Turner {Rd} = 1; 63585285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } */ 63595285864985be9077e58e42235af6582dee72e841David 'Digit' Turner fail_label = gen_new_label(); 63605285864985be9077e58e42235af6582dee72e841David 'Digit' Turner done_label = gen_new_label(); 63615285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_brcond_i32(TCG_COND_NE, addr, cpu_exclusive_addr, fail_label); 63625285864985be9077e58e42235af6582dee72e841David 'Digit' Turner switch (size) { 63635285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 0: 63645285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = gen_ld8u(addr, IS_USER(s)); 63655285864985be9077e58e42235af6582dee72e841David 'Digit' Turner break; 63665285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 1: 63675285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = gen_ld16u(addr, IS_USER(s)); 63685285864985be9077e58e42235af6582dee72e841David 'Digit' Turner break; 63695285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 2: 63705285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 3: 63715285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = gen_ld32(addr, IS_USER(s)); 63725285864985be9077e58e42235af6582dee72e841David 'Digit' Turner break; 63735285864985be9077e58e42235af6582dee72e841David 'Digit' Turner default: 63745285864985be9077e58e42235af6582dee72e841David 'Digit' Turner abort(); 63755285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 63765285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_brcond_i32(TCG_COND_NE, tmp, cpu_exclusive_val, fail_label); 63775285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 63785285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (size == 3) { 63795285864985be9077e58e42235af6582dee72e841David 'Digit' Turner TCGv tmp2 = tcg_temp_new_i32(); 63805285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_addi_i32(tmp2, addr, 4); 63815285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = gen_ld32(tmp2, IS_USER(s)); 63825285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 63835285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_brcond_i32(TCG_COND_NE, tmp, cpu_exclusive_high, fail_label); 63845285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 63855285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 63865285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = load_reg(s, rt); 63875285864985be9077e58e42235af6582dee72e841David 'Digit' Turner switch (size) { 63885285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 0: 63895285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_st8(tmp, addr, IS_USER(s)); 63905285864985be9077e58e42235af6582dee72e841David 'Digit' Turner break; 63915285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 1: 63925285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_st16(tmp, addr, IS_USER(s)); 63935285864985be9077e58e42235af6582dee72e841David 'Digit' Turner break; 63945285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 2: 63955285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 3: 63965285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_st32(tmp, addr, IS_USER(s)); 63975285864985be9077e58e42235af6582dee72e841David 'Digit' Turner break; 63985285864985be9077e58e42235af6582dee72e841David 'Digit' Turner default: 63995285864985be9077e58e42235af6582dee72e841David 'Digit' Turner abort(); 64005285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 64015285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (size == 3) { 64025285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_addi_i32(addr, addr, 4); 64035285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = load_reg(s, rt2); 64045285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_st32(tmp, addr, IS_USER(s)); 64055285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 64065285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_movi_i32(cpu_R[rd], 0); 64075285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_br(done_label); 64085285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_set_label(fail_label); 64095285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_movi_i32(cpu_R[rd], 1); 64105285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_set_label(done_label); 64115285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_movi_i32(cpu_exclusive_addr, -1); 64125285864985be9077e58e42235af6582dee72e841David 'Digit' Turner} 64135285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#endif 6414a577fcadc0b365ee629aec313f57a65d54fe5d89David 'Digit' Turner 64158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void disas_arm_insn(CPUState * env, DisasContext *s) 64168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 64178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project unsigned int cond, insn, val, op1, i, shift, rm, rs, rn, rd, sh; 6418288208c386810fef725aa448a9f46bd2772bec8cDavid 'Digit' Turner ANDROID_TRACE_DECLS 64198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project TCGv tmp; 64208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project TCGv tmp2; 64218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project TCGv tmp3; 64228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project TCGv addr; 64235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner TCGv_i64 tmp64; 64245285864985be9077e58e42235af6582dee72e841David 'Digit' Turner 64258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project insn = ldl_code(s->pc); 64265389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine 6427288208c386810fef725aa448a9f46bd2772bec8cDavid 'Digit' Turner ANDROID_WATCH_CALLSTACK_ARM(s); 64285389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine 6429288208c386810fef725aa448a9f46bd2772bec8cDavid 'Digit' Turner ANDROID_TRACE_START_ARM(); 64305389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine 64318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project s->pc += 4; 64328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 64338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* M variants do not implement ARM mode. */ 64348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (IS_M(env)) 64358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto illegal_op; 64368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project cond = insn >> 28; 64378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (cond == 0xf){ 64385285864985be9077e58e42235af6582dee72e841David 'Digit' Turner /* In ARMv3 and v4 the NV condition is UNPREDICTABLE; we 64395285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * choose to UNDEF. In ARMv5 and above the space is used 64405285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * for miscellaneous unconditional instructions. 64415285864985be9077e58e42235af6582dee72e841David 'Digit' Turner */ 64425285864985be9077e58e42235af6582dee72e841David 'Digit' Turner ARCH(5); 64435285864985be9077e58e42235af6582dee72e841David 'Digit' Turner 6444288208c386810fef725aa448a9f46bd2772bec8cDavid 'Digit' Turner ANDROID_TRACE_GEN_TICKS(); 64458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Unconditional instructions. */ 64468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (((insn >> 25) & 7) == 1) { 64478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* NEON Data processing. */ 64488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (!arm_feature(env, ARM_FEATURE_NEON)) 64498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto illegal_op; 64508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 64518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (disas_neon_data_insn(env, s, insn)) 64528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto illegal_op; 64538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return; 64548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 64558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if ((insn & 0x0f100000) == 0x04000000) { 64568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* NEON load/store. */ 64578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (!arm_feature(env, ARM_FEATURE_NEON)) 64588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto illegal_op; 64598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 64608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (disas_neon_ls_insn(env, s, insn)) 64618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto illegal_op; 64628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return; 64638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 64645285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (((insn & 0x0f30f000) == 0x0510f000) || 64655285864985be9077e58e42235af6582dee72e841David 'Digit' Turner ((insn & 0x0f30f010) == 0x0710f000)) { 64665285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if ((insn & (1 << 22)) == 0) { 64675285864985be9077e58e42235af6582dee72e841David 'Digit' Turner /* PLDW; v7MP */ 64685285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (!arm_feature(env, ARM_FEATURE_V7MP)) { 64695285864985be9077e58e42235af6582dee72e841David 'Digit' Turner goto illegal_op; 64705285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 64715285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 64725285864985be9077e58e42235af6582dee72e841David 'Digit' Turner /* Otherwise PLD; v5TE+ */ 64735285864985be9077e58e42235af6582dee72e841David 'Digit' Turner ARCH(5TE); 64745285864985be9077e58e42235af6582dee72e841David 'Digit' Turner return; 64755285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 64765285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (((insn & 0x0f70f000) == 0x0450f000) || 64775285864985be9077e58e42235af6582dee72e841David 'Digit' Turner ((insn & 0x0f70f010) == 0x0650f000)) { 64785285864985be9077e58e42235af6582dee72e841David 'Digit' Turner ARCH(7); 64795285864985be9077e58e42235af6582dee72e841David 'Digit' Turner return; /* PLI; V7 */ 64805285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 64815285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (((insn & 0x0f700000) == 0x04100000) || 64825285864985be9077e58e42235af6582dee72e841David 'Digit' Turner ((insn & 0x0f700010) == 0x06100000)) { 64835285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (!arm_feature(env, ARM_FEATURE_V7MP)) { 64845285864985be9077e58e42235af6582dee72e841David 'Digit' Turner goto illegal_op; 64855285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 64865285864985be9077e58e42235af6582dee72e841David 'Digit' Turner return; /* v7MP: Unallocated memory hint: must NOP */ 64875285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 64885285864985be9077e58e42235af6582dee72e841David 'Digit' Turner 64895285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if ((insn & 0x0ffffdff) == 0x01010000) { 64908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ARCH(6); 64918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* setend */ 64928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 9)) { 64938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* BE8 mode not implemented. */ 64948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto illegal_op; 64958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 64968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return; 64978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else if ((insn & 0x0fffff00) == 0x057ff000) { 64988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch ((insn >> 4) & 0xf) { 64998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 1: /* clrex */ 65008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ARCH(6K); 65015285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_clrex(s); 65028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return; 65038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 4: /* dsb */ 65048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 5: /* dmb */ 65058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 6: /* isb */ 65068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ARCH(7); 65078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* We don't emulate caches so these are a no-op. */ 65088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return; 65098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project default: 65108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto illegal_op; 65118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 65128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else if ((insn & 0x0e5fffe0) == 0x084d0500) { 65138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* srs */ 65145285864985be9077e58e42235af6582dee72e841David 'Digit' Turner int32_t offset; 65158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (IS_USER(s)) 65168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto illegal_op; 65178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ARCH(6); 65188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project op1 = (insn & 0x1f); 65195285864985be9077e58e42235af6582dee72e841David 'Digit' Turner addr = tcg_temp_new_i32(); 65205285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = tcg_const_i32(op1); 65215285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_get_r13_banked(addr, cpu_env, tmp); 65225285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 65238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project i = (insn >> 23) & 3; 65248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (i) { 65258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0: offset = -4; break; /* DA */ 65265285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 1: offset = 0; break; /* IA */ 65275285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 2: offset = -8; break; /* DB */ 65288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 3: offset = 4; break; /* IB */ 65298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project default: abort(); 65308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 65318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (offset) 65328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_addi_i32(addr, addr, offset); 65338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_reg(s, 14); 65348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_st32(tmp, addr, 0); 65355285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = load_cpu_field(spsr); 65368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_addi_i32(addr, addr, 4); 65378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_st32(tmp, addr, 0); 65388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 21)) { 65398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Base writeback. */ 65408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (i) { 65418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0: offset = -8; break; 65425285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 1: offset = 4; break; 65435285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 2: offset = -4; break; 65448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 3: offset = 0; break; 65458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project default: abort(); 65468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 65478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (offset) 65485285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_addi_i32(addr, addr, offset); 65495285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = tcg_const_i32(op1); 65505285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_set_r13_banked(cpu_env, tmp, addr); 65515285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 65525285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(addr); 65538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 65545285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(addr); 65558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 65565285864985be9077e58e42235af6582dee72e841David 'Digit' Turner return; 65575285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } else if ((insn & 0x0e50ffe0) == 0x08100a00) { 65588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* rfe */ 65595285864985be9077e58e42235af6582dee72e841David 'Digit' Turner int32_t offset; 65608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (IS_USER(s)) 65618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto illegal_op; 65628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ARCH(6); 65638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rn = (insn >> 16) & 0xf; 65648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project addr = load_reg(s, rn); 65658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project i = (insn >> 23) & 3; 65668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (i) { 65678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0: offset = -4; break; /* DA */ 65685285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 1: offset = 0; break; /* IA */ 65695285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 2: offset = -8; break; /* DB */ 65708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 3: offset = 4; break; /* IB */ 65718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project default: abort(); 65728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 65738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (offset) 65748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_addi_i32(addr, addr, offset); 65758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Load PC into tmp and CPSR into tmp2. */ 65768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = gen_ld32(addr, 0); 65778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_addi_i32(addr, addr, 4); 65788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp2 = gen_ld32(addr, 0); 65798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 21)) { 65808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Base writeback. */ 65818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (i) { 65828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0: offset = -8; break; 65835285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 1: offset = 4; break; 65845285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 2: offset = -4; break; 65858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 3: offset = 0; break; 65868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project default: abort(); 65878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 65888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (offset) 65898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_addi_i32(addr, addr, offset); 65908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project store_reg(s, rn, addr); 65918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 65925285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(addr); 65938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 65948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_rfe(s, tmp, tmp2); 65955285864985be9077e58e42235af6582dee72e841David 'Digit' Turner return; 65968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else if ((insn & 0x0e000000) == 0x0a000000) { 65978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* branch link and change to thumb (blx <offset>) */ 65988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int32_t offset; 65998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 66008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project val = (uint32_t)s->pc; 66015285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = tcg_temp_new_i32(); 66028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_movi_i32(tmp, val); 66038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project store_reg(s, 14, tmp); 66048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Sign-extend the 24-bit offset */ 66058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project offset = (((int32_t)insn) << 8) >> 8; 66068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* offset * 4 + bit24 * 2 + (thumb bit) */ 66078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project val += (offset << 2) | ((insn >> 23) & 2) | 1; 66088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* pipeline offset */ 66098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project val += 4; 66105285864985be9077e58e42235af6582dee72e841David 'Digit' Turner /* protected by ARCH(5); above, near the start of uncond block */ 66118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_bx_im(s, val); 66128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return; 66138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else if ((insn & 0x0e000f00) == 0x0c000100) { 66148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (arm_feature(env, ARM_FEATURE_IWMMXT)) { 66158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* iWMMXt register transfer. */ 66168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (env->cp15.c15_cpar & (1 << 1)) 66178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (!disas_iwmmxt_insn(env, s, insn)) 66188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return; 66198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 66208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else if ((insn & 0x0fe00000) == 0x0c400000) { 66218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Coprocessor double register transfer. */ 66225285864985be9077e58e42235af6582dee72e841David 'Digit' Turner ARCH(5TE); 66238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else if ((insn & 0x0f000010) == 0x0e000010) { 66248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Additional coprocessor register transfer. */ 66255285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (!disas_coproc_insn(env, s, insn)) { 66265285864985be9077e58e42235af6582dee72e841David 'Digit' Turner return; 66275285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 66288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else if ((insn & 0x0ff10020) == 0x01000000) { 66298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project uint32_t mask; 66308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project uint32_t val; 66318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* cps (privileged) */ 66328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (IS_USER(s)) 66338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return; 66348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project mask = val = 0; 66358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 19)) { 66368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 8)) 66378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project mask |= CPSR_A; 66388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 7)) 66398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project mask |= CPSR_I; 66408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 6)) 66418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project mask |= CPSR_F; 66428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 18)) 66438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project val |= mask; 66448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 66458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 17)) { 66468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project mask |= CPSR_M; 66478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project val |= (insn & 0x1f); 66488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 66498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (mask) { 66505285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_set_psr_im(s, mask, 0, val); 66518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 66528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return; 66538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 66548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto illegal_op; 66558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 66568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (cond != 0xe) { 6657288208c386810fef725aa448a9f46bd2772bec8cDavid 'Digit' Turner ANDROID_TRACE_GEN_SINGLE_TICK(); 66588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* if not always execute, we generate a conditional jump to 66598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project next instruction */ 66608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project s->condlabel = gen_new_label(); 66618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_test_cc(cond ^ 1, s->condlabel); 66628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project s->condjmp = 1; 66638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 6664288208c386810fef725aa448a9f46bd2772bec8cDavid 'Digit' Turner ANDROID_TRACE_GEN_OTHER_TICKS(); 66658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if ((insn & 0x0f900000) == 0x03000000) { 66668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if ((insn & (1 << 21)) == 0) { 66678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ARCH(6T2); 66688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd = (insn >> 12) & 0xf; 66698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project val = ((insn >> 4) & 0xf000) | (insn & 0xfff); 66708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if ((insn & (1 << 22)) == 0) { 66718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* MOVW */ 66725285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = tcg_temp_new_i32(); 66738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_movi_i32(tmp, val); 66748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 66758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* MOVT */ 66768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_reg(s, rd); 66778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_ext16u_i32(tmp, tmp); 66788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_ori_i32(tmp, tmp, val << 16); 66798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 66808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project store_reg(s, rd, tmp); 66818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 66828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (((insn >> 12) & 0xf) != 0xf) 66838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto illegal_op; 66848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (((insn >> 16) & 0xf) == 0) { 66858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_nop_hint(s, insn & 0xff); 66868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 66878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* CPSR = immediate */ 66888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project val = insn & 0xff; 66898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project shift = ((insn >> 8) & 0xf) * 2; 66908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (shift) 66918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project val = (val >> shift) | (val << (32 - shift)); 66928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project i = ((insn & (1 << 22)) != 0); 66935285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (gen_set_psr_im(s, msr_mask(env, s, (insn >> 16) & 0xf, i), i, val)) 66948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto illegal_op; 66958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 66968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 66978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else if ((insn & 0x0f900000) == 0x01000000 66988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project && (insn & 0x00000090) != 0x00000090) { 66998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* miscellaneous instructions */ 67008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project op1 = (insn >> 21) & 3; 67018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project sh = (insn >> 4) & 0xf; 67028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rm = insn & 0xf; 67038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (sh) { 67048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x0: /* move program status register */ 67058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (op1 & 1) { 67068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* PSR = reg */ 67075285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = load_reg(s, rm); 67088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project i = ((op1 & 2) != 0); 67095285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (gen_set_psr(s, msr_mask(env, s, (insn >> 16) & 0xf, i), i, tmp)) 67108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto illegal_op; 67118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 67128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* reg = PSR */ 67138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd = (insn >> 12) & 0xf; 67148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (op1 & 2) { 67158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (IS_USER(s)) 67168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto illegal_op; 67178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_cpu_field(spsr); 67188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 67195285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = tcg_temp_new_i32(); 67208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_helper_cpsr_read(tmp); 67218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 67228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project store_reg(s, rd, tmp); 67238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 67248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 67258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x1: 67268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (op1 == 1) { 67278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* branch/exchange thumb (bx). */ 67285285864985be9077e58e42235af6582dee72e841David 'Digit' Turner ARCH(4T); 67298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_reg(s, rm); 67308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_bx(s, tmp); 67318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else if (op1 == 3) { 67328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* clz */ 67335285864985be9077e58e42235af6582dee72e841David 'Digit' Turner ARCH(5); 67348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd = (insn >> 12) & 0xf; 67358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_reg(s, rm); 67368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_helper_clz(tmp, tmp); 67378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project store_reg(s, rd, tmp); 67388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 67398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto illegal_op; 67408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 67418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 67428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x2: 67438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (op1 == 1) { 67448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ARCH(5J); /* bxj */ 67458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Trivial implementation equivalent to bx. */ 67468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_reg(s, rm); 67478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_bx(s, tmp); 67488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 67498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto illegal_op; 67508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 67518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 67528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x3: 67538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (op1 != 1) 67548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto illegal_op; 67558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 67565285864985be9077e58e42235af6582dee72e841David 'Digit' Turner ARCH(5); 67578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* branch link/exchange thumb (blx) */ 67588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_reg(s, rm); 67595285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp2 = tcg_temp_new_i32(); 67608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_movi_i32(tmp2, s->pc); 67618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project store_reg(s, 14, tmp2); 67628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_bx(s, tmp); 67638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 67648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x5: /* saturating add/subtract */ 67655285864985be9077e58e42235af6582dee72e841David 'Digit' Turner ARCH(5TE); 67668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd = (insn >> 12) & 0xf; 67678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rn = (insn >> 16) & 0xf; 676880562525ca945d9e921eb49f96d52f1b5a0e693dDavid 'Digit' Turner tmp = load_reg(s, rm); 67698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp2 = load_reg(s, rn); 67708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (op1 & 2) 67718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_helper_double_saturate(tmp2, tmp2); 67728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (op1 & 1) 67738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_helper_sub_saturate(tmp, tmp, tmp2); 67748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 67758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_helper_add_saturate(tmp, tmp, tmp2); 67765285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 67778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project store_reg(s, rd, tmp); 67788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 67795285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 7: 67805285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (op1 == 1) { 67815285864985be9077e58e42235af6582dee72e841David 'Digit' Turner /* bkpt */ 67825285864985be9077e58e42235af6582dee72e841David 'Digit' Turner ARCH(5); 67835285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_exception_insn(s, 4, EXCP_BKPT); 67845285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } else if (op1 == 3) { 67855285864985be9077e58e42235af6582dee72e841David 'Digit' Turner /* smi/smc */ 67865285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (!(env->cp15.c0_c2[4] & 0xf000) || IS_USER(s)) { 67875285864985be9077e58e42235af6582dee72e841David 'Digit' Turner goto illegal_op; 67885285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 67895285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_smc(env, s); 67905285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } else { 67915285864985be9077e58e42235af6582dee72e841David 'Digit' Turner goto illegal_op; 67925285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 67938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 67948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x8: /* signed multiply */ 67958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0xa: 67968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0xc: 67978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0xe: 67985285864985be9077e58e42235af6582dee72e841David 'Digit' Turner ARCH(5TE); 67998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rs = (insn >> 8) & 0xf; 68008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rn = (insn >> 12) & 0xf; 68018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd = (insn >> 16) & 0xf; 68028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (op1 == 1) { 68038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* (32 * 16) >> 16 */ 68048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_reg(s, rm); 68058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp2 = load_reg(s, rs); 68068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (sh & 4) 68078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_sari_i32(tmp2, tmp2, 16); 68088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 68098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_sxth(tmp2); 68105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tmp64 = gen_muls_i64_i32(tmp, tmp2); 68115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tcg_gen_shri_i64(tmp64, tmp64, 16); 68125285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = tcg_temp_new_i32(); 68135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tcg_gen_trunc_i64_i32(tmp, tmp64); 68145285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i64(tmp64); 68158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if ((sh & 2) == 0) { 68168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp2 = load_reg(s, rn); 68178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_helper_add_setq(tmp, tmp, tmp2); 68185285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 68198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 68208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project store_reg(s, rd, tmp); 68218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 68228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 16 * 16 */ 68238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_reg(s, rm); 68248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp2 = load_reg(s, rs); 68258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_mulxy(tmp, tmp2, sh & 2, sh & 4); 68265285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 68278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (op1 == 2) { 68285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tmp64 = tcg_temp_new_i64(); 68295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tcg_gen_ext_i32_i64(tmp64, tmp); 68305285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 68315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner gen_addq(s, tmp64, rn, rd); 68325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner gen_storeq_reg(s, rn, rd, tmp64); 68335285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i64(tmp64); 68348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 68358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (op1 == 0) { 68368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp2 = load_reg(s, rn); 68378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_helper_add_setq(tmp, tmp, tmp2); 68385285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 68398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 68408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project store_reg(s, rd, tmp); 68418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 68428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 68438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 68448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project default: 68458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto illegal_op; 68468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 68478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else if (((insn & 0x0e000000) == 0 && 68488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project (insn & 0x00000090) != 0x90) || 68498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ((insn & 0x0e000000) == (1 << 25))) { 68508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int set_cc, logic_cc, shiftop; 68518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 68528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project op1 = (insn >> 21) & 0xf; 68538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project set_cc = (insn >> 20) & 1; 68548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project logic_cc = table_logic_cc[op1] & set_cc; 68558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 68568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* data processing instruction */ 68578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 25)) { 68588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* immediate operand */ 68598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project val = insn & 0xff; 68608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project shift = ((insn >> 8) & 0xf) * 2; 68615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (shift) { 68628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project val = (val >> shift) | (val << (32 - shift)); 68635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 68645285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp2 = tcg_temp_new_i32(); 68655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tcg_gen_movi_i32(tmp2, val); 68665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (logic_cc && shift) { 68675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner gen_set_CF_bit31(tmp2); 68685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 68698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 68708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* register */ 68718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rm = (insn) & 0xf; 68725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tmp2 = load_reg(s, rm); 68738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project shiftop = (insn >> 5) & 3; 68748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (!(insn & (1 << 4))) { 68758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project shift = (insn >> 7) & 0x1f; 68765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner gen_arm_shift_im(tmp2, shiftop, shift, logic_cc); 68778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 68788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rs = (insn >> 8) & 0xf; 68798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_reg(s, rs); 68805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner gen_arm_shift_reg(tmp2, shiftop, tmp, logic_cc); 68818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 68828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 68838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (op1 != 0x0f && op1 != 0x0d) { 68848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rn = (insn >> 16) & 0xf; 68855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tmp = load_reg(s, rn); 68865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } else { 68875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner TCGV_UNUSED(tmp); 68888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 68898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd = (insn >> 12) & 0xf; 68908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch(op1) { 68918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x00: 68925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tcg_gen_and_i32(tmp, tmp, tmp2); 68935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (logic_cc) { 68945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner gen_logic_CC(tmp); 68955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 68965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner store_reg_bx(env, s, rd, tmp); 68978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 68988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x01: 68995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tcg_gen_xor_i32(tmp, tmp, tmp2); 69005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (logic_cc) { 69015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner gen_logic_CC(tmp); 69025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 69035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner store_reg_bx(env, s, rd, tmp); 69048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 69058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x02: 69068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (set_cc && rd == 15) { 69078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* SUBS r15, ... is used for exception return. */ 69085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (IS_USER(s)) { 69098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto illegal_op; 69105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 69115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner gen_helper_sub_cc(tmp, tmp, tmp2); 69125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner gen_exception_return(s, tmp); 69138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 69145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (set_cc) { 69155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner gen_helper_sub_cc(tmp, tmp, tmp2); 69165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } else { 69175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tcg_gen_sub_i32(tmp, tmp, tmp2); 69185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 69195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner store_reg_bx(env, s, rd, tmp); 69208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 69218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 69228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x03: 69235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (set_cc) { 69245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner gen_helper_sub_cc(tmp, tmp2, tmp); 69255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } else { 69265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tcg_gen_sub_i32(tmp, tmp2, tmp); 69275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 69285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner store_reg_bx(env, s, rd, tmp); 69298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 69308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x04: 69315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (set_cc) { 69325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner gen_helper_add_cc(tmp, tmp, tmp2); 69335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } else { 69345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tcg_gen_add_i32(tmp, tmp, tmp2); 69355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 69365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner store_reg_bx(env, s, rd, tmp); 69378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 69388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x05: 69395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (set_cc) { 69405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner gen_helper_adc_cc(tmp, tmp, tmp2); 69415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } else { 69425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner gen_add_carry(tmp, tmp, tmp2); 69435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 69445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner store_reg_bx(env, s, rd, tmp); 69458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 69468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x06: 69475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (set_cc) { 69485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner gen_helper_sbc_cc(tmp, tmp, tmp2); 69495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } else { 69505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner gen_sub_carry(tmp, tmp, tmp2); 69515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 69525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner store_reg_bx(env, s, rd, tmp); 69538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 69548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x07: 69555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (set_cc) { 69565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner gen_helper_sbc_cc(tmp, tmp2, tmp); 69575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } else { 69585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner gen_sub_carry(tmp, tmp2, tmp); 69595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 69605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner store_reg_bx(env, s, rd, tmp); 69618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 69628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x08: 69638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (set_cc) { 69645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tcg_gen_and_i32(tmp, tmp, tmp2); 69655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner gen_logic_CC(tmp); 69668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 69675285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 69688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 69698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x09: 69708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (set_cc) { 69715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tcg_gen_xor_i32(tmp, tmp, tmp2); 69725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner gen_logic_CC(tmp); 69738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 69745285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 69758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 69768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x0a: 69778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (set_cc) { 69785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner gen_helper_sub_cc(tmp, tmp, tmp2); 69798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 69805285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 69818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 69828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x0b: 69838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (set_cc) { 69845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner gen_helper_add_cc(tmp, tmp, tmp2); 69858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 69865285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 69878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 69888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x0c: 69895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tcg_gen_or_i32(tmp, tmp, tmp2); 69905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (logic_cc) { 69915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner gen_logic_CC(tmp); 69925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 69935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner store_reg_bx(env, s, rd, tmp); 69948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 69958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x0d: 69968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (logic_cc && rd == 15) { 69978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* MOVS r15, ... is used for exception return. */ 69985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (IS_USER(s)) { 69998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto illegal_op; 70005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 70015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner gen_exception_return(s, tmp2); 70028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 70035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (logic_cc) { 70045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner gen_logic_CC(tmp2); 70055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 70065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner store_reg_bx(env, s, rd, tmp2); 70078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 70088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 70098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x0e: 70105285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_andc_i32(tmp, tmp, tmp2); 70115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (logic_cc) { 70125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner gen_logic_CC(tmp); 70135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 70145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner store_reg_bx(env, s, rd, tmp); 70158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 70168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project default: 70178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x0f: 70185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tcg_gen_not_i32(tmp2, tmp2); 70195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (logic_cc) { 70205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner gen_logic_CC(tmp2); 70215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 70225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner store_reg_bx(env, s, rd, tmp2); 70238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 70248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 70255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (op1 != 0x0f && op1 != 0x0d) { 70265285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 70275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 70288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 70298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* other instructions */ 70308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project op1 = (insn >> 24) & 0xf; 70318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch(op1) { 70328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x0: 70338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x1: 70348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* multiplies, extra load/stores */ 70358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project sh = (insn >> 5) & 3; 70368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (sh == 0) { 70378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (op1 == 0x0) { 70388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd = (insn >> 16) & 0xf; 70398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rn = (insn >> 12) & 0xf; 70408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rs = (insn >> 8) & 0xf; 70418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rm = (insn) & 0xf; 70428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project op1 = (insn >> 20) & 0xf; 70438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (op1) { 70448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0: case 1: case 2: case 3: case 6: 70458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 32 bit mul */ 70468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_reg(s, rs); 70478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp2 = load_reg(s, rm); 70488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_mul_i32(tmp, tmp, tmp2); 70495285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 70508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 22)) { 70518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Subtract (mls) */ 70528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ARCH(6T2); 70538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp2 = load_reg(s, rn); 70548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_sub_i32(tmp, tmp2, tmp); 70555285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 70568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else if (insn & (1 << 21)) { 70578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Add */ 70588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp2 = load_reg(s, rn); 70598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_add_i32(tmp, tmp, tmp2); 70605285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 70618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 70628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 20)) 70638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_logic_CC(tmp); 70648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project store_reg(s, rd, tmp); 70658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 70665285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 4: 70675285864985be9077e58e42235af6582dee72e841David 'Digit' Turner /* 64 bit mul double accumulate (UMAAL) */ 70685285864985be9077e58e42235af6582dee72e841David 'Digit' Turner ARCH(6); 70698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_reg(s, rs); 70708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp2 = load_reg(s, rm); 70715285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp64 = gen_mulu_i64_i32(tmp, tmp2); 70725285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_addq_lo(s, tmp64, rn); 70735285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_addq_lo(s, tmp64, rd); 70745285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_storeq_reg(s, rn, rd, tmp64); 70755285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i64(tmp64); 70765285864985be9077e58e42235af6582dee72e841David 'Digit' Turner break; 70775285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 8: case 9: case 10: case 11: 70785285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 12: case 13: case 14: case 15: 70795285864985be9077e58e42235af6582dee72e841David 'Digit' Turner /* 64 bit mul: UMULL, UMLAL, SMULL, SMLAL. */ 70805285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = load_reg(s, rs); 70815285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp2 = load_reg(s, rm); 70825285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (insn & (1 << 22)) { 70835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tmp64 = gen_muls_i64_i32(tmp, tmp2); 70845285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } else { 70855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tmp64 = gen_mulu_i64_i32(tmp, tmp2); 70865285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 70875285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (insn & (1 << 21)) { /* mult accumulate */ 70885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner gen_addq(s, tmp64, rn, rd); 70898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 70905285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (insn & (1 << 20)) { 70915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner gen_logicq_cc(tmp64); 70925285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 70935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner gen_storeq_reg(s, rn, rd, tmp64); 70945285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i64(tmp64); 70958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 70965285864985be9077e58e42235af6582dee72e841David 'Digit' Turner default: 70975285864985be9077e58e42235af6582dee72e841David 'Digit' Turner goto illegal_op; 70988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 70998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 71008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rn = (insn >> 16) & 0xf; 71018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd = (insn >> 12) & 0xf; 71028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 23)) { 71038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* load/store exclusive */ 71045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner op1 = (insn >> 21) & 0x3; 71055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (op1) 71065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ARCH(6K); 71075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner else 71085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ARCH(6); 71095285864985be9077e58e42235af6582dee72e841David 'Digit' Turner addr = tcg_temp_local_new_i32(); 71105285864985be9077e58e42235af6582dee72e841David 'Digit' Turner load_reg_var(s, addr, rn); 71118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 20)) { 71125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner switch (op1) { 71135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner case 0: /* ldrex */ 71145285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_load_exclusive(s, rd, 15, addr, 2); 71155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner break; 71165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner case 1: /* ldrexd */ 71175285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_load_exclusive(s, rd, rd + 1, addr, 3); 71185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner break; 71195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner case 2: /* ldrexb */ 71205285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_load_exclusive(s, rd, 15, addr, 0); 71215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner break; 71225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner case 3: /* ldrexh */ 71235285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_load_exclusive(s, rd, 15, addr, 1); 71245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner break; 71255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner default: 71265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner abort(); 71275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 71288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 71298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rm = insn & 0xf; 71305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner switch (op1) { 71315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner case 0: /* strex */ 71325285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_store_exclusive(s, rd, rm, 15, addr, 2); 71335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner break; 71345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner case 1: /* strexd */ 71355285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_store_exclusive(s, rd, rm, rm + 1, addr, 3); 71365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner break; 71375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner case 2: /* strexb */ 71385285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_store_exclusive(s, rd, rm, 15, addr, 0); 71395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner break; 71405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner case 3: /* strexh */ 71415285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_store_exclusive(s, rd, rm, 15, addr, 1); 71425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner break; 71435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner default: 71445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner abort(); 71455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 71468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 71475285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free(addr); 71488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 71498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* SWP instruction */ 71508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rm = (insn) & 0xf; 71518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 71528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* ??? This is not really atomic. However we know 71538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project we never have multiple CPUs running in parallel, 71548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project so it is good enough. */ 71558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project addr = load_reg(s, rn); 71568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_reg(s, rm); 71578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 22)) { 71588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp2 = gen_ld8u(addr, IS_USER(s)); 71598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_st8(tmp, addr, IS_USER(s)); 71608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 71618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp2 = gen_ld32(addr, IS_USER(s)); 71628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_st32(tmp, addr, IS_USER(s)); 71638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 71645285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(addr); 71658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project store_reg(s, rd, tmp2); 71668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 71678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 71688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 71698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int address_offset; 71708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int load; 71718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Misc load/store */ 71728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rn = (insn >> 16) & 0xf; 71738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd = (insn >> 12) & 0xf; 71748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project addr = load_reg(s, rn); 71758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 24)) 71768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_add_datah_offset(s, insn, 0, addr); 71778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project address_offset = 0; 71788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 20)) { 71798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* load */ 71808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch(sh) { 71818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 1: 71828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = gen_ld16u(addr, IS_USER(s)); 71838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 71848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 2: 71858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = gen_ld8s(addr, IS_USER(s)); 71868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 71878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project default: 71888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 3: 71898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = gen_ld16s(addr, IS_USER(s)); 71908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 71918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 71928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project load = 1; 71938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else if (sh & 2) { 71945285864985be9077e58e42235af6582dee72e841David 'Digit' Turner ARCH(5TE); 71958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* doubleword */ 71968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (sh & 1) { 71978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* store */ 71988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_reg(s, rd); 71998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_st32(tmp, addr, IS_USER(s)); 72008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_addi_i32(addr, addr, 4); 72018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_reg(s, rd + 1); 72028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_st32(tmp, addr, IS_USER(s)); 72038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project load = 0; 72048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 72058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* load */ 72068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = gen_ld32(addr, IS_USER(s)); 72078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project store_reg(s, rd, tmp); 72088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_addi_i32(addr, addr, 4); 72098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = gen_ld32(addr, IS_USER(s)); 72108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd++; 72118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project load = 1; 72128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 72138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project address_offset = -4; 72148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 72158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* store */ 72168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_reg(s, rd); 72178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_st16(tmp, addr, IS_USER(s)); 72188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project load = 0; 72198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 72208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Perform base writeback before the loaded value to 72218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ensure correct behavior with overlapping index registers. 72228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ldrd with base writeback is is undefined if the 72238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project destination and index registers overlap. */ 72248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (!(insn & (1 << 24))) { 72258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_add_datah_offset(s, insn, address_offset, addr); 72268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project store_reg(s, rn, addr); 72278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else if (insn & (1 << 21)) { 72288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (address_offset) 72298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_addi_i32(addr, addr, address_offset); 72308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project store_reg(s, rn, addr); 72318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 72325285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(addr); 72338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 72348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (load) { 72358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Complete the load. */ 72368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project store_reg(s, rd, tmp); 72378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 72388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 72398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 72408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x4: 72418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x5: 72428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto do_ldst; 72438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x6: 72448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x7: 72458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 4)) { 72468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ARCH(6); 72478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Armv6 Media instructions. */ 72488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rm = insn & 0xf; 72498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rn = (insn >> 16) & 0xf; 72508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd = (insn >> 12) & 0xf; 72518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rs = (insn >> 8) & 0xf; 72528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch ((insn >> 23) & 3) { 72538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0: /* Parallel add/subtract. */ 72548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project op1 = (insn >> 20) & 7; 72558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_reg(s, rn); 72568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp2 = load_reg(s, rm); 72578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project sh = (insn >> 5) & 7; 72588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if ((op1 & 3) == 0 || sh == 5 || sh == 6) 72598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto illegal_op; 72608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_arm_parallel_addsub(op1, sh, tmp, tmp2); 72615285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 72628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project store_reg(s, rd, tmp); 72638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 72648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 1: 72658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if ((insn & 0x00700020) == 0) { 72668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Halfword pack. */ 72678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_reg(s, rn); 72688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp2 = load_reg(s, rm); 72698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project shift = (insn >> 7) & 0x1f; 72708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 6)) { 72718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* pkhtb */ 72728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (shift == 0) 72738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project shift = 31; 72748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_sari_i32(tmp2, tmp2, shift); 72758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_andi_i32(tmp, tmp, 0xffff0000); 72768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_ext16u_i32(tmp2, tmp2); 72778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 72788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* pkhbt */ 72798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (shift) 72808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_shli_i32(tmp2, tmp2, shift); 72818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_ext16u_i32(tmp, tmp); 72828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_andi_i32(tmp2, tmp2, 0xffff0000); 72838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 72848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_or_i32(tmp, tmp, tmp2); 72855285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 72868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project store_reg(s, rd, tmp); 72878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else if ((insn & 0x00200020) == 0x00200000) { 72888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* [us]sat */ 72898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_reg(s, rm); 72908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project shift = (insn >> 7) & 0x1f; 72918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 6)) { 72928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (shift == 0) 72938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project shift = 31; 72948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_sari_i32(tmp, tmp, shift); 72958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 72968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_shli_i32(tmp, tmp, shift); 72978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 72988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project sh = (insn >> 16) & 0x1f; 72995285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp2 = tcg_const_i32(sh); 73005285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (insn & (1 << 22)) 73015285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_usat(tmp, tmp, tmp2); 73025285864985be9077e58e42235af6582dee72e841David 'Digit' Turner else 73035285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_ssat(tmp, tmp, tmp2); 73045285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 73058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project store_reg(s, rd, tmp); 73068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else if ((insn & 0x00300fe0) == 0x00200f20) { 73078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* [us]sat16 */ 73088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_reg(s, rm); 73098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project sh = (insn >> 16) & 0x1f; 73105285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp2 = tcg_const_i32(sh); 73115285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (insn & (1 << 22)) 73125285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_usat16(tmp, tmp, tmp2); 73135285864985be9077e58e42235af6582dee72e841David 'Digit' Turner else 73145285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_ssat16(tmp, tmp, tmp2); 73155285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 73168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project store_reg(s, rd, tmp); 73178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else if ((insn & 0x00700fe0) == 0x00000fa0) { 73188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Select bytes. */ 73198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_reg(s, rn); 73208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp2 = load_reg(s, rm); 73215285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp3 = tcg_temp_new_i32(); 73228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_ld_i32(tmp3, cpu_env, offsetof(CPUState, GE)); 73238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_helper_sel_flags(tmp, tmp3, tmp, tmp2); 73245285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp3); 73255285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 73268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project store_reg(s, rd, tmp); 73278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else if ((insn & 0x000003e0) == 0x00000060) { 73288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_reg(s, rm); 73298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project shift = (insn >> 10) & 3; 73305285864985be9077e58e42235af6582dee72e841David 'Digit' Turner /* ??? In many cases it's not necessary to do a 73318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rotate, a shift is sufficient. */ 73328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (shift != 0) 73335285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_rotri_i32(tmp, tmp, shift * 8); 73348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project op1 = (insn >> 20) & 7; 73358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (op1) { 73368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0: gen_sxtb16(tmp); break; 73378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 2: gen_sxtb(tmp); break; 73388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 3: gen_sxth(tmp); break; 73398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 4: gen_uxtb16(tmp); break; 73408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 6: gen_uxtb(tmp); break; 73418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 7: gen_uxth(tmp); break; 73425285864985be9077e58e42235af6582dee72e841David 'Digit' Turner default: tcg_temp_free_i32(tmp); goto illegal_op; 73438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 73448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (rn != 15) { 73458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp2 = load_reg(s, rn); 73468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if ((op1 & 3) == 0) { 73478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_add16(tmp, tmp2); 73488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 73498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_add_i32(tmp, tmp, tmp2); 73505285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 73518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 73528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 73538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project store_reg(s, rd, tmp); 73548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else if ((insn & 0x003f0f60) == 0x003f0f20) { 73558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* rev */ 73568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_reg(s, rm); 73578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 22)) { 73588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 7)) { 73598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_revsh(tmp); 73608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 73618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ARCH(6T2); 73628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_helper_rbit(tmp, tmp); 73638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 73648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 73658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 7)) 73668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_rev16(tmp); 73678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 73685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tcg_gen_bswap32_i32(tmp, tmp); 73698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 73708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project store_reg(s, rd, tmp); 73718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 73728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto illegal_op; 73738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 73748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 73758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 2: /* Multiplies (Type 3). */ 73768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_reg(s, rm); 73778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp2 = load_reg(s, rs); 73788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 20)) { 73795285864985be9077e58e42235af6582dee72e841David 'Digit' Turner /* Signed multiply most significant [accumulate]. 73805285864985be9077e58e42235af6582dee72e841David 'Digit' Turner (SMMUL, SMMLA, SMMLS) */ 73815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tmp64 = gen_muls_i64_i32(tmp, tmp2); 73825285864985be9077e58e42235af6582dee72e841David 'Digit' Turner 73835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (rd != 15) { 73845285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = load_reg(s, rd); 73858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 6)) { 73865285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp64 = gen_subq_msw(tmp64, tmp); 73878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 73885285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp64 = gen_addq_msw(tmp64, tmp); 73898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 73908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 73915285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (insn & (1 << 5)) { 73925285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_addi_i64(tmp64, tmp64, 0x80000000u); 73935285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 73945285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_shri_i64(tmp64, tmp64, 32); 73955285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = tcg_temp_new_i32(); 73965285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_trunc_i64_i32(tmp, tmp64); 73975285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i64(tmp64); 73985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner store_reg(s, rn, tmp); 73998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 74008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 5)) 74018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_swap_half(tmp2); 74028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_smul_dual(tmp, tmp2); 74038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 6)) { 74045285864985be9077e58e42235af6582dee72e841David 'Digit' Turner /* This subtraction cannot overflow. */ 74058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_sub_i32(tmp, tmp, tmp2); 74068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 74075285864985be9077e58e42235af6582dee72e841David 'Digit' Turner /* This addition cannot overflow 32 bits; 74085285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * however it may overflow considered as a signed 74095285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * operation, in which case we must set the Q flag. 74105285864985be9077e58e42235af6582dee72e841David 'Digit' Turner */ 74115285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_add_setq(tmp, tmp, tmp2); 74128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 74135285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 74148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 22)) { 74158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* smlald, smlsld */ 74165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tmp64 = tcg_temp_new_i64(); 74175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tcg_gen_ext_i32_i64(tmp64, tmp); 74185285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 74195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner gen_addq(s, tmp64, rd, rn); 74205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner gen_storeq_reg(s, rd, rn, tmp64); 74215285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i64(tmp64); 74228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 74238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* smuad, smusd, smlad, smlsd */ 74248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (rd != 15) 74258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project { 74268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp2 = load_reg(s, rd); 74278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_helper_add_setq(tmp, tmp, tmp2); 74285285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 74298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 74308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project store_reg(s, rn, tmp); 74318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 74328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 74338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 74348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 3: 74358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project op1 = ((insn >> 17) & 0x38) | ((insn >> 5) & 7); 74368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (op1) { 74378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0: /* Unsigned sum of absolute differences. */ 74388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ARCH(6); 74398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_reg(s, rm); 74408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp2 = load_reg(s, rs); 74418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_helper_usad8(tmp, tmp, tmp2); 74425285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 74435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (rd != 15) { 74445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tmp2 = load_reg(s, rd); 74458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_add_i32(tmp, tmp, tmp2); 74465285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 74478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 74485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner store_reg(s, rn, tmp); 74498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 74508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x20: case 0x24: case 0x28: case 0x2c: 74518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Bitfield insert/clear. */ 74528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ARCH(6T2); 74538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project shift = (insn >> 7) & 0x1f; 74548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project i = (insn >> 16) & 0x1f; 74558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project i = i + 1 - shift; 74568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (rm == 15) { 74575285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = tcg_temp_new_i32(); 74588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_movi_i32(tmp, 0); 74598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 74608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_reg(s, rm); 74618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 74628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (i != 32) { 74638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp2 = load_reg(s, rd); 74648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_bfi(tmp, tmp2, tmp, shift, (1u << i) - 1); 74655285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 74668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 74678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project store_reg(s, rd, tmp); 74688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 74698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x12: case 0x16: case 0x1a: case 0x1e: /* sbfx */ 74708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x32: case 0x36: case 0x3a: case 0x3e: /* ubfx */ 74715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ARCH(6T2); 74728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_reg(s, rm); 74738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project shift = (insn >> 7) & 0x1f; 74748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project i = ((insn >> 16) & 0x1f) + 1; 74758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (shift + i > 32) 74768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto illegal_op; 74778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (i < 32) { 74788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (op1 & 0x20) { 74798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_ubfx(tmp, shift, (1u << i) - 1); 74808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 74818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_sbfx(tmp, shift, i); 74828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 74838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 74848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project store_reg(s, rd, tmp); 74858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 74868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project default: 74878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto illegal_op; 74888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 74898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 74908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 74918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 74928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 74938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project do_ldst: 74948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Check for undefined extension instructions 74958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * per the ARM Bible IE: 74968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * xxxx 0111 1111 xxxx xxxx xxxx 1111 xxxx 74978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 74988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project sh = (0xf << 20) | (0xf << 4); 74998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (op1 == 0x7 && ((insn & sh) == sh)) 75008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project { 75018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto illegal_op; 75028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 75038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* load/store byte/word */ 75048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rn = (insn >> 16) & 0xf; 75058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd = (insn >> 12) & 0xf; 75068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp2 = load_reg(s, rn); 75078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project i = (IS_USER(s) || (insn & 0x01200000) == 0x00200000); 75088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 24)) 75098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_add_data_offset(s, insn, tmp2); 75108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 20)) { 75118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* load */ 75128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 22)) { 75138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = gen_ld8u(tmp2, i); 75148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 75158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = gen_ld32(tmp2, i); 75168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 75178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 75188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* store */ 75198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_reg(s, rd); 75208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 22)) 75218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_st8(tmp, tmp2, i); 75228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 75238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_st32(tmp, tmp2, i); 75248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 75258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (!(insn & (1 << 24))) { 75268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_add_data_offset(s, insn, tmp2); 75278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project store_reg(s, rn, tmp2); 75288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else if (insn & (1 << 21)) { 75298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project store_reg(s, rn, tmp2); 75308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 75315285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 75328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 75338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 20)) { 75348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Complete the load. */ 75355285864985be9077e58e42235af6582dee72e841David 'Digit' Turner store_reg_from_load(env, s, rd, tmp); 75368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 75378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 75388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x08: 75398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x09: 75408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project { 75418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int j, n, user, loaded_base; 75428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project TCGv loaded_var; 75438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* load/store multiple words */ 75448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* XXX: store correct base if write back */ 75458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project user = 0; 75468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 22)) { 75478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (IS_USER(s)) 75488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto illegal_op; /* only usable in supervisor mode */ 75498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 75508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if ((insn & (1 << 15)) == 0) 75518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project user = 1; 75528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 75538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rn = (insn >> 16) & 0xf; 75548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project addr = load_reg(s, rn); 75555285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp3 = tcg_const_i32(4); 75568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 75578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* compute total size */ 75588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project loaded_base = 0; 75598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project TCGV_UNUSED(loaded_var); 75608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project n = 0; 75618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project for(i=0;i<16;i++) { 75628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << i)) 75638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project n++; 75648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 75658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* XXX: test invalid n == 0 case ? */ 75668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 23)) { 75678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 24)) { 75688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* pre increment */ 75695285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_add_i32(addr, addr, tmp3); 75708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 75718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* post increment */ 75728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 75738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 75748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 24)) { 75758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* pre decrement */ 75768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_addi_i32(addr, addr, -(n * 4)); 75778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 75788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* post decrement */ 75798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (n != 1) 75808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_addi_i32(addr, addr, -((n - 1) * 4)); 75818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 75828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 75838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project j = 0; 75848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project for(i=0;i<16;i++) { 75858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << i)) { 75868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 20)) { 75878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* load */ 75888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = gen_ld32(addr, IS_USER(s)); 75895285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (user) { 75905285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp2 = tcg_const_i32(i); 75915285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_set_user_reg(tmp2, tmp); 75925285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 75935285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 75948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else if (i == rn) { 75958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project loaded_var = tmp; 75968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project loaded_base = 1; 75978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 75985285864985be9077e58e42235af6582dee72e841David 'Digit' Turner store_reg_from_load(env, s, i, tmp); 75998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 76008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 76018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* store */ 76028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (i == 15) { 76038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* special case: r15 = PC + 8 */ 76048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project val = (long)s->pc + 4; 76055285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = tcg_temp_new_i32(); 76068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_movi_i32(tmp, val); 76078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else if (user) { 76085285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = tcg_temp_new_i32(); 76095285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp2 = tcg_const_i32(i); 76105285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_get_user_reg(tmp, tmp2); 76115285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 76128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 76138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_reg(s, i); 76148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 76158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_st32(tmp, addr, IS_USER(s)); 76168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 76178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project j++; 76188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* no need to add after the last transfer */ 76198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (j != n) 76205285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_add_i32(addr, addr, tmp3); 76218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 76228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 76238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 21)) { 76248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* write back */ 76258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 23)) { 76268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 24)) { 76278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* pre increment */ 76288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 76298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* post increment */ 76305285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_add_i32(addr, addr, tmp3); 76318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 76328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 76338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 24)) { 76348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* pre decrement */ 76358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (n != 1) 76368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_addi_i32(addr, addr, -((n - 1) * 4)); 76378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 76388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* post decrement */ 76398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_addi_i32(addr, addr, -(n * 4)); 76408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 76418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 76428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project store_reg(s, rn, addr); 76438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 76445285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(addr); 76458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 76465285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp3); 76478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (loaded_base) { 76488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project store_reg(s, rn, loaded_var); 76498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 76508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if ((insn & (1 << 22)) && !user) { 76518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Restore CPSR from SPSR. */ 76528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_cpu_field(spsr); 76538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_set_cpsr(tmp, 0xffffffff); 76545285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 76558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project s->is_jmp = DISAS_UPDATE; 76568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 76578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 76588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 76598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0xa: 76608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0xb: 76618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project { 76628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int32_t offset; 76635285864985be9077e58e42235af6582dee72e841David 'Digit' Turner 76648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* branch (and link) */ 76658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project val = (int32_t)s->pc; 76668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 24)) { 76675285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = tcg_temp_new_i32(); 76688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_movi_i32(tmp, val); 76698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project store_reg(s, 14, tmp); 76708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 76718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project offset = (((int32_t)insn << 8) >> 8); 76728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project val += (offset << 2) + 4; 76738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_jmp(s, val); 76748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 76758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 76768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0xc: 76778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0xd: 76788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0xe: 76798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Coprocessor. */ 76808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (disas_coproc_insn(env, s, insn)) 76818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto illegal_op; 76828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 76838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0xf: 76848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* swi */ 76858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_set_pc_im(s->pc); 76868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project s->is_jmp = DISAS_SWI; 76878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 76888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project default: 76898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project illegal_op: 76905285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_exception_insn(s, 4, EXCP_UDEF); 76918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 76928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 76938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 76948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 76958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 76968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Return true if this is a Thumb-2 logical op. */ 76978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int 76988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectthumb2_logic_op(int op) 76998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 77008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return (op < 8); 77018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 77028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 77038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Generate code for a Thumb-2 data processing operation. If CONDS is nonzero 77048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project then set condition code flags based on the result of the operation. 77058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project If SHIFTER_OUT is nonzero then set the carry flag for logical operations 77068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project to the high bit of T1. 77078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project Returns zero if the opcode is valid. */ 77088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 77098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int 77105285864985be9077e58e42235af6582dee72e841David 'Digit' Turnergen_thumb2_data_op(DisasContext *s, int op, int conds, uint32_t shifter_out, TCGv t0, TCGv t1) 77118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 77128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int logic_cc; 77138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 77148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project logic_cc = 0; 77158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (op) { 77168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0: /* and */ 77175285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_and_i32(t0, t0, t1); 77188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project logic_cc = conds; 77198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 77208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 1: /* bic */ 77215285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_andc_i32(t0, t0, t1); 77228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project logic_cc = conds; 77238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 77248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 2: /* orr */ 77255285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_or_i32(t0, t0, t1); 77268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project logic_cc = conds; 77278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 77288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 3: /* orn */ 77295285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_orc_i32(t0, t0, t1); 77308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project logic_cc = conds; 77318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 77328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 4: /* eor */ 77335285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_xor_i32(t0, t0, t1); 77348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project logic_cc = conds; 77358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 77368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 8: /* add */ 77378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (conds) 77385285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_add_cc(t0, t0, t1); 77398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 77405285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_add_i32(t0, t0, t1); 77418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 77428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 10: /* adc */ 77438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (conds) 77445285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_adc_cc(t0, t0, t1); 77458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 77465285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_adc(t0, t1); 77478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 77488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 11: /* sbc */ 77498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (conds) 77505285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_sbc_cc(t0, t0, t1); 77518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 77525285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_sub_carry(t0, t0, t1); 77538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 77548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 13: /* sub */ 77558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (conds) 77565285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_sub_cc(t0, t0, t1); 77578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 77585285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_sub_i32(t0, t0, t1); 77598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 77608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 14: /* rsb */ 77618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (conds) 77625285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_sub_cc(t0, t1, t0); 77638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 77645285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_sub_i32(t0, t1, t0); 77658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 77668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project default: /* 5, 6, 7, 9, 12, 15. */ 77678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 77688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 77698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (logic_cc) { 77705285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_logic_CC(t0); 77718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (shifter_out) 77725285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_set_CF_bit31(t1); 77738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 77748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 0; 77758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 77768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 77778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Translate a 32-bit thumb instruction. Returns nonzero if the instruction 77788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project is not legal. */ 77798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1) 77808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 77818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project uint32_t insn, imm, shift, offset; 77828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project uint32_t rd, rn, rm, rs; 77838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project TCGv tmp; 77848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project TCGv tmp2; 77858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project TCGv tmp3; 77868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project TCGv addr; 77875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner TCGv_i64 tmp64; 77888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int op; 77898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int shiftop; 77908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int conds; 77918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int logic_cc; 77928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 77938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (!(arm_feature(env, ARM_FEATURE_THUMB2) 77948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project || arm_feature (env, ARM_FEATURE_M))) { 77958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Thumb-1 cores may need to treat bl and blx as a pair of 77968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 16-bit instructions to get correct prefetch abort behavior. */ 77978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project insn = insn_hw1; 77988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if ((insn & (1 << 12)) == 0) { 77995285864985be9077e58e42235af6582dee72e841David 'Digit' Turner ARCH(5); 78008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Second half of blx. */ 78018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project offset = ((insn & 0x7ff) << 1); 78028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_reg(s, 14); 78038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_addi_i32(tmp, tmp, offset); 78048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_andi_i32(tmp, tmp, 0xfffffffc); 78058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 78065285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp2 = tcg_temp_new_i32(); 78078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_movi_i32(tmp2, s->pc | 1); 78088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project store_reg(s, 14, tmp2); 78098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_bx(s, tmp); 78108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 0; 78118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 78128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 11)) { 78138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Second half of bl. */ 78148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project offset = ((insn & 0x7ff) << 1) | 1; 78158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_reg(s, 14); 78168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_addi_i32(tmp, tmp, offset); 78178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 78185285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp2 = tcg_temp_new_i32(); 78198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_movi_i32(tmp2, s->pc | 1); 78208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project store_reg(s, 14, tmp2); 78218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_bx(s, tmp); 78228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 0; 78238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 78248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if ((s->pc & ~TARGET_PAGE_MASK) == 0) { 78258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Instruction spans a page boundary. Implement it as two 78268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 16-bit instructions in case the second half causes an 78278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project prefetch abort. */ 78288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project offset = ((int32_t)insn << 21) >> 9; 78295285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_movi_i32(cpu_R[14], s->pc + 2 + offset); 78308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 0; 78318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 78328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Fall through to 32-bit decode. */ 78338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 78348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 78358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project insn = lduw_code(s->pc); 7836288208c386810fef725aa448a9f46bd2772bec8cDavid 'Digit' Turner ANDROID_TRACE_START_THUMB(); 78375389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine s->pc += 2; 78385285864985be9077e58e42235af6582dee72e841David 'Digit' Turner insn |= (uint32_t)insn_hw1 << 16; 78395389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine 78408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if ((insn & 0xf800e800) != 0xf000e800) { 78418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ARCH(6T2); 78428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 78438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 78448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rn = (insn >> 16) & 0xf; 78458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rs = (insn >> 12) & 0xf; 78468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd = (insn >> 8) & 0xf; 78478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rm = insn & 0xf; 78488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch ((insn >> 25) & 0xf) { 78498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0: case 1: case 2: case 3: 78508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 16-bit instructions. Should never happen. */ 78518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project abort(); 78528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 4: 78538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 22)) { 78548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Other load/store, table branch. */ 78558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & 0x01200000) { 78568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Load/store doubleword. */ 78578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (rn == 15) { 78585285864985be9077e58e42235af6582dee72e841David 'Digit' Turner addr = tcg_temp_new_i32(); 78598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_movi_i32(addr, s->pc & ~3); 78608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 78618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project addr = load_reg(s, rn); 78628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 78638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project offset = (insn & 0xff) * 4; 78648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if ((insn & (1 << 23)) == 0) 78658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project offset = -offset; 78668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 24)) { 78678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_addi_i32(addr, addr, offset); 78688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project offset = 0; 78698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 78708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 20)) { 78718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* ldrd */ 78728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = gen_ld32(addr, IS_USER(s)); 78738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project store_reg(s, rs, tmp); 78748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_addi_i32(addr, addr, 4); 78758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = gen_ld32(addr, IS_USER(s)); 78768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project store_reg(s, rd, tmp); 78778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 78788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* strd */ 78798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_reg(s, rs); 78808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_st32(tmp, addr, IS_USER(s)); 78818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_addi_i32(addr, addr, 4); 78828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_reg(s, rd); 78838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_st32(tmp, addr, IS_USER(s)); 78848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 78858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 21)) { 78868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Base writeback. */ 78878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (rn == 15) 78888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto illegal_op; 78898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_addi_i32(addr, addr, offset - 4); 78908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project store_reg(s, rn, addr); 78918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 78925285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(addr); 78938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 78948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else if ((insn & (1 << 23)) == 0) { 78958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Load/store exclusive word. */ 78965285864985be9077e58e42235af6582dee72e841David 'Digit' Turner addr = tcg_temp_local_new(); 78975285864985be9077e58e42235af6582dee72e841David 'Digit' Turner load_reg_var(s, addr, rn); 78985285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_addi_i32(addr, addr, (insn & 0xff) << 2); 78998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 20)) { 79005285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_load_exclusive(s, rs, 15, addr, 2); 79018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 79025285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_store_exclusive(s, rd, rs, 15, addr, 2); 79038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 79045285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free(addr); 79058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else if ((insn & (1 << 6)) == 0) { 79068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Table Branch. */ 79078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (rn == 15) { 79085285864985be9077e58e42235af6582dee72e841David 'Digit' Turner addr = tcg_temp_new_i32(); 79098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_movi_i32(addr, s->pc); 79108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 79118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project addr = load_reg(s, rn); 79128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 79138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_reg(s, rm); 79148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_add_i32(addr, addr, tmp); 79158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 4)) { 79168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* tbh */ 79178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_add_i32(addr, addr, tmp); 79185285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 79198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = gen_ld16u(addr, IS_USER(s)); 79208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { /* tbb */ 79215285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 79228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = gen_ld8u(addr, IS_USER(s)); 79238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 79245285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(addr); 79258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_shli_i32(tmp, tmp, 1); 79268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_addi_i32(tmp, tmp, s->pc); 79278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project store_reg(s, 15, tmp); 79288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 79298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Load/store exclusive byte/halfword/doubleword. */ 79305285864985be9077e58e42235af6582dee72e841David 'Digit' Turner ARCH(7); 79318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project op = (insn >> 4) & 0x3; 79325285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (op == 2) { 79335285864985be9077e58e42235af6582dee72e841David 'Digit' Turner goto illegal_op; 79345285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 79355285864985be9077e58e42235af6582dee72e841David 'Digit' Turner addr = tcg_temp_local_new(); 79365285864985be9077e58e42235af6582dee72e841David 'Digit' Turner load_reg_var(s, addr, rn); 79378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 20)) { 79385285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_load_exclusive(s, rs, rd, addr, op); 79398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 79405285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_store_exclusive(s, rm, rs, rd, addr, op); 79418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 79425285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free(addr); 79438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 79448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 79458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Load/store multiple, RFE, SRS. */ 79468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (((insn >> 23) & 1) == ((insn >> 24) & 1)) { 79478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Not available in user mode. */ 79488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (IS_USER(s)) 79498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto illegal_op; 79508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 20)) { 79518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* rfe */ 79528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project addr = load_reg(s, rn); 79538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if ((insn & (1 << 24)) == 0) 79548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_addi_i32(addr, addr, -8); 79558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Load PC into tmp and CPSR into tmp2. */ 79568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = gen_ld32(addr, 0); 79578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_addi_i32(addr, addr, 4); 79588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp2 = gen_ld32(addr, 0); 79598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 21)) { 79608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Base writeback. */ 79618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 24)) { 79628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_addi_i32(addr, addr, 4); 79638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 79648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_addi_i32(addr, addr, -4); 79658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 79668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project store_reg(s, rn, addr); 79678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 79685285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(addr); 79698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 79708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_rfe(s, tmp, tmp2); 79718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 79728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* srs */ 79738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project op = (insn & 0x1f); 79745285864985be9077e58e42235af6582dee72e841David 'Digit' Turner addr = tcg_temp_new_i32(); 79755285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = tcg_const_i32(op); 79765285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_get_r13_banked(addr, cpu_env, tmp); 79775285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 79788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if ((insn & (1 << 24)) == 0) { 79798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_addi_i32(addr, addr, -8); 79808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 79818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_reg(s, 14); 79828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_st32(tmp, addr, 0); 79838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_addi_i32(addr, addr, 4); 79845285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = tcg_temp_new_i32(); 79858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_helper_cpsr_read(tmp); 79868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_st32(tmp, addr, 0); 79878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 21)) { 79888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if ((insn & (1 << 24)) == 0) { 79898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_addi_i32(addr, addr, -4); 79908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 79918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_addi_i32(addr, addr, 4); 79928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 79935285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = tcg_const_i32(op); 79945285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_set_r13_banked(cpu_env, tmp, addr); 79955285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 79968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 79975285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(addr); 79988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 79998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 80008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 80015285864985be9077e58e42235af6582dee72e841David 'Digit' Turner int i, loaded_base = 0; 80025285864985be9077e58e42235af6582dee72e841David 'Digit' Turner TCGv loaded_var; 80038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Load/store multiple. */ 80048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project addr = load_reg(s, rn); 80058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project offset = 0; 80068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project for (i = 0; i < 16; i++) { 80078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << i)) 80088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project offset += 4; 80098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 80108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 24)) { 80118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_addi_i32(addr, addr, -offset); 80128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 80138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 80145285864985be9077e58e42235af6582dee72e841David 'Digit' Turner TCGV_UNUSED(loaded_var); 80155285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp2 = tcg_const_i32(4); 80168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project for (i = 0; i < 16; i++) { 80178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if ((insn & (1 << i)) == 0) 80188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project continue; 80198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 20)) { 80208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Load. */ 80218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = gen_ld32(addr, IS_USER(s)); 80228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (i == 15) { 80238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_bx(s, tmp); 80245285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } else if (i == rn) { 80255285864985be9077e58e42235af6582dee72e841David 'Digit' Turner loaded_var = tmp; 80265285864985be9077e58e42235af6582dee72e841David 'Digit' Turner loaded_base = 1; 80278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 80288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project store_reg(s, i, tmp); 80298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 80308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 80318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Store. */ 80328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_reg(s, i); 80338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_st32(tmp, addr, IS_USER(s)); 80348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 80355285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_add_i32(addr, addr, tmp2); 80365285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 80375285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (loaded_base) { 80385285864985be9077e58e42235af6582dee72e841David 'Digit' Turner store_reg(s, rn, loaded_var); 80398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 80405285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 80418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 21)) { 80428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Base register writeback. */ 80438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 24)) { 80448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_addi_i32(addr, addr, -offset); 80458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 80468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Fault if writeback register is in register list. */ 80478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << rn)) 80488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto illegal_op; 80498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project store_reg(s, rn, addr); 80508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 80515285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(addr); 80528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 80538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 80548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 80558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 80565285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 5: 80575285864985be9077e58e42235af6582dee72e841David 'Digit' Turner 80588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project op = (insn >> 21) & 0xf; 80595285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (op == 6) { 80605285864985be9077e58e42235af6582dee72e841David 'Digit' Turner /* Halfword pack. */ 80615285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = load_reg(s, rn); 80625285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp2 = load_reg(s, rm); 80635285864985be9077e58e42235af6582dee72e841David 'Digit' Turner shift = ((insn >> 10) & 0x1c) | ((insn >> 6) & 0x3); 80645285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (insn & (1 << 5)) { 80655285864985be9077e58e42235af6582dee72e841David 'Digit' Turner /* pkhtb */ 80665285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (shift == 0) 80675285864985be9077e58e42235af6582dee72e841David 'Digit' Turner shift = 31; 80685285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_sari_i32(tmp2, tmp2, shift); 80695285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_andi_i32(tmp, tmp, 0xffff0000); 80705285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_ext16u_i32(tmp2, tmp2); 80715285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } else { 80725285864985be9077e58e42235af6582dee72e841David 'Digit' Turner /* pkhbt */ 80735285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (shift) 80745285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_shli_i32(tmp2, tmp2, shift); 80755285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_ext16u_i32(tmp, tmp); 80765285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_andi_i32(tmp2, tmp2, 0xffff0000); 80775285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 80785285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_or_i32(tmp, tmp, tmp2); 80795285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 80805285864985be9077e58e42235af6582dee72e841David 'Digit' Turner store_reg(s, rd, tmp); 80815285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } else { 80825285864985be9077e58e42235af6582dee72e841David 'Digit' Turner /* Data processing register constant shift. */ 80835285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (rn == 15) { 80845285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = tcg_temp_new_i32(); 80855285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_movi_i32(tmp, 0); 80865285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } else { 80875285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = load_reg(s, rn); 80885285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 80895285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp2 = load_reg(s, rm); 80905285864985be9077e58e42235af6582dee72e841David 'Digit' Turner 80915285864985be9077e58e42235af6582dee72e841David 'Digit' Turner shiftop = (insn >> 4) & 3; 80925285864985be9077e58e42235af6582dee72e841David 'Digit' Turner shift = ((insn >> 6) & 3) | ((insn >> 10) & 0x1c); 80935285864985be9077e58e42235af6582dee72e841David 'Digit' Turner conds = (insn & (1 << 20)) != 0; 80945285864985be9077e58e42235af6582dee72e841David 'Digit' Turner logic_cc = (conds && thumb2_logic_op(op)); 80955285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_arm_shift_im(tmp2, shiftop, shift, logic_cc); 80965285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (gen_thumb2_data_op(s, op, conds, 0, tmp, tmp2)) 80975285864985be9077e58e42235af6582dee72e841David 'Digit' Turner goto illegal_op; 80985285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 80995285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (rd != 15) { 81005285864985be9077e58e42235af6582dee72e841David 'Digit' Turner store_reg(s, rd, tmp); 81015285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } else { 81025285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 81035285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 81045285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 81058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 81068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 13: /* Misc data processing. */ 81078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project op = ((insn >> 22) & 6) | ((insn >> 7) & 1); 81088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (op < 4 && (insn & 0xf000) != 0xf000) 81098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto illegal_op; 81108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (op) { 81118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0: /* Register controlled shift. */ 81128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_reg(s, rn); 81138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp2 = load_reg(s, rm); 81148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if ((insn & 0x70) != 0) 81158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto illegal_op; 81168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project op = (insn >> 21) & 3; 81178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project logic_cc = (insn & (1 << 20)) != 0; 81188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_arm_shift_reg(tmp, op, tmp2, logic_cc); 81198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (logic_cc) 81208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_logic_CC(tmp); 81215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner store_reg_bx(env, s, rd, tmp); 81228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 81238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 1: /* Sign/zero extend. */ 81248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_reg(s, rm); 81258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project shift = (insn >> 4) & 3; 81265285864985be9077e58e42235af6582dee72e841David 'Digit' Turner /* ??? In many cases it's not necessary to do a 81278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rotate, a shift is sufficient. */ 81288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (shift != 0) 81295285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_rotri_i32(tmp, tmp, shift * 8); 81308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project op = (insn >> 20) & 7; 81318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (op) { 81328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0: gen_sxth(tmp); break; 81338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 1: gen_uxth(tmp); break; 81348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 2: gen_sxtb16(tmp); break; 81358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 3: gen_uxtb16(tmp); break; 81368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 4: gen_sxtb(tmp); break; 81378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 5: gen_uxtb(tmp); break; 81388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project default: goto illegal_op; 81398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 81408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (rn != 15) { 81418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp2 = load_reg(s, rn); 81428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if ((op >> 1) == 1) { 81438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_add16(tmp, tmp2); 81448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 81458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_add_i32(tmp, tmp, tmp2); 81465285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 81478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 81488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 81498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project store_reg(s, rd, tmp); 81508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 81518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 2: /* SIMD add/subtract. */ 81528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project op = (insn >> 20) & 7; 81538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project shift = (insn >> 4) & 7; 81548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if ((op & 3) == 3 || (shift & 3) == 3) 81558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto illegal_op; 81568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_reg(s, rn); 81578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp2 = load_reg(s, rm); 81588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_thumb2_parallel_addsub(op, shift, tmp, tmp2); 81595285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 81608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project store_reg(s, rd, tmp); 81618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 81628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 3: /* Other data processing. */ 81638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project op = ((insn >> 17) & 0x38) | ((insn >> 4) & 7); 81648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (op < 4) { 81658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Saturating add/subtract. */ 81668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_reg(s, rn); 81678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp2 = load_reg(s, rm); 81688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (op & 1) 81695285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_double_saturate(tmp, tmp); 81705285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (op & 2) 81718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_helper_sub_saturate(tmp, tmp2, tmp); 81728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 81738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_helper_add_saturate(tmp, tmp, tmp2); 81745285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 81758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 81768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_reg(s, rn); 81778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (op) { 81788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x0a: /* rbit */ 81798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_helper_rbit(tmp, tmp); 81808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 81818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x08: /* rev */ 81825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tcg_gen_bswap32_i32(tmp, tmp); 81838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 81848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x09: /* rev16 */ 81858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_rev16(tmp); 81868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 81878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x0b: /* revsh */ 81888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_revsh(tmp); 81898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 81908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x10: /* sel */ 81918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp2 = load_reg(s, rm); 81925285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp3 = tcg_temp_new_i32(); 81938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_ld_i32(tmp3, cpu_env, offsetof(CPUState, GE)); 81948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_helper_sel_flags(tmp, tmp3, tmp, tmp2); 81955285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp3); 81965285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 81978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 81988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x18: /* clz */ 81998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_helper_clz(tmp, tmp); 82008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 82018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project default: 82028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto illegal_op; 82038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 82048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 82058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project store_reg(s, rd, tmp); 82068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 82078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 4: case 5: /* 32-bit multiply. Sum of absolute differences. */ 82088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project op = (insn >> 4) & 0xf; 82098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_reg(s, rn); 82108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp2 = load_reg(s, rm); 82118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch ((insn >> 20) & 7) { 82128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0: /* 32 x 32 -> 32 */ 82138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_mul_i32(tmp, tmp, tmp2); 82145285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 82158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (rs != 15) { 82168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp2 = load_reg(s, rs); 82178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (op) 82188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_sub_i32(tmp, tmp2, tmp); 82198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 82208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_add_i32(tmp, tmp, tmp2); 82215285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 82228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 82238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 82248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 1: /* 16 x 16 -> 32 */ 82258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_mulxy(tmp, tmp2, op & 2, op & 1); 82265285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 82278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (rs != 15) { 82288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp2 = load_reg(s, rs); 82298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_helper_add_setq(tmp, tmp, tmp2); 82305285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 82318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 82328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 82338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 2: /* Dual multiply add. */ 82348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 4: /* Dual multiply subtract. */ 82358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (op) 82368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_swap_half(tmp2); 82378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_smul_dual(tmp, tmp2); 82388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 22)) { 82395285864985be9077e58e42235af6582dee72e841David 'Digit' Turner /* This subtraction cannot overflow. */ 82408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_sub_i32(tmp, tmp, tmp2); 82418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 82425285864985be9077e58e42235af6582dee72e841David 'Digit' Turner /* This addition cannot overflow 32 bits; 82435285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * however it may overflow considered as a signed 82445285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * operation, in which case we must set the Q flag. 82455285864985be9077e58e42235af6582dee72e841David 'Digit' Turner */ 82465285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_add_setq(tmp, tmp, tmp2); 82478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 82485285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 82498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (rs != 15) 82508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project { 82518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp2 = load_reg(s, rs); 82528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_helper_add_setq(tmp, tmp, tmp2); 82535285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 82548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 82558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 82568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 3: /* 32 * 16 -> 32msb */ 82578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (op) 82588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_sari_i32(tmp2, tmp2, 16); 82598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 82608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_sxth(tmp2); 82615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tmp64 = gen_muls_i64_i32(tmp, tmp2); 82625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tcg_gen_shri_i64(tmp64, tmp64, 16); 82635285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = tcg_temp_new_i32(); 82645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tcg_gen_trunc_i64_i32(tmp, tmp64); 82655285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i64(tmp64); 82668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (rs != 15) 82678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project { 82688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp2 = load_reg(s, rs); 82698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_helper_add_setq(tmp, tmp, tmp2); 82705285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 82718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 82728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 82735285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 5: case 6: /* 32 * 32 -> 32msb (SMMUL, SMMLA, SMMLS) */ 82745285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp64 = gen_muls_i64_i32(tmp, tmp2); 82758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (rs != 15) { 82765285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = load_reg(s, rs); 82775285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (insn & (1 << 20)) { 82785285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp64 = gen_addq_msw(tmp64, tmp); 82798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 82805285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp64 = gen_subq_msw(tmp64, tmp); 82818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 82828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 82835285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (insn & (1 << 4)) { 82845285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_addi_i64(tmp64, tmp64, 0x80000000u); 82855285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 82865285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_shri_i64(tmp64, tmp64, 32); 82875285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = tcg_temp_new_i32(); 82885285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_trunc_i64_i32(tmp, tmp64); 82895285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i64(tmp64); 82908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 82918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 7: /* Unsigned sum of absolute differences. */ 82928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_helper_usad8(tmp, tmp, tmp2); 82935285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 82948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (rs != 15) { 82958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp2 = load_reg(s, rs); 82968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_add_i32(tmp, tmp, tmp2); 82975285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 82988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 82998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 83008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 83018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project store_reg(s, rd, tmp); 83028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 83038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 6: case 7: /* 64-bit multiply, Divide. */ 83048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project op = ((insn >> 4) & 0xf) | ((insn >> 16) & 0x70); 83058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_reg(s, rn); 83068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp2 = load_reg(s, rm); 83078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if ((op & 0x50) == 0x10) { 83088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* sdiv, udiv */ 83098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (!arm_feature(env, ARM_FEATURE_DIV)) 83108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto illegal_op; 83118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (op & 0x20) 83128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_helper_udiv(tmp, tmp, tmp2); 83138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 83148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_helper_sdiv(tmp, tmp, tmp2); 83155285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 83168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project store_reg(s, rd, tmp); 83178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else if ((op & 0xe) == 0xc) { 83188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Dual multiply accumulate long. */ 83198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (op & 1) 83208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_swap_half(tmp2); 83218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_smul_dual(tmp, tmp2); 83228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (op & 0x10) { 83238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_sub_i32(tmp, tmp, tmp2); 83248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 83258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_add_i32(tmp, tmp, tmp2); 83268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 83275285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 83285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* BUGFIX */ 83295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tmp64 = tcg_temp_new_i64(); 83305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tcg_gen_ext_i32_i64(tmp64, tmp); 83315285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 83325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner gen_addq(s, tmp64, rs, rd); 83335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner gen_storeq_reg(s, rs, rd, tmp64); 83345285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i64(tmp64); 83358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 83368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (op & 0x20) { 83378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Unsigned 64-bit multiply */ 83385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tmp64 = gen_mulu_i64_i32(tmp, tmp2); 83398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 83408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (op & 8) { 83418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* smlalxy */ 83428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_mulxy(tmp, tmp2, op & 2, op & 1); 83435285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 83445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tmp64 = tcg_temp_new_i64(); 83455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tcg_gen_ext_i32_i64(tmp64, tmp); 83465285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 83478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 83488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Signed 64-bit multiply */ 83495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tmp64 = gen_muls_i64_i32(tmp, tmp2); 83508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 83518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 83528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (op & 4) { 83538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* umaal */ 83545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner gen_addq_lo(s, tmp64, rs); 83555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner gen_addq_lo(s, tmp64, rd); 83568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else if (op & 0x40) { 83578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 64-bit accumulate. */ 83585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner gen_addq(s, tmp64, rs, rd); 83598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 83605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner gen_storeq_reg(s, rs, rd, tmp64); 83615285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i64(tmp64); 83628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 83638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 83648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 83658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 83668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 6: case 7: case 14: case 15: 83678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Coprocessor. */ 83688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (((insn >> 24) & 3) == 3) { 83698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Translate into the equivalent ARM encoding. */ 83705285864985be9077e58e42235af6582dee72e841David 'Digit' Turner insn = (insn & 0xe2ffffff) | ((insn & (1 << 28)) >> 4) | (1 << 28); 83718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (disas_neon_data_insn(env, s, insn)) 83728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto illegal_op; 83738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 83748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 28)) 83758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto illegal_op; 83768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (disas_coproc_insn (env, s, insn)) 83778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto illegal_op; 83788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 83798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 83808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 8: case 9: case 10: case 11: 83818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 15)) { 83828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Branches, misc control. */ 83838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & 0x5000) { 83848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Unconditional branch. */ 83858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* signextend(hw1[10:0]) -> offset[:12]. */ 83868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project offset = ((int32_t)insn << 5) >> 9 & ~(int32_t)0xfff; 83878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* hw1[10:0] -> offset[11:1]. */ 83888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project offset |= (insn & 0x7ff) << 1; 83898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* (~hw2[13, 11] ^ offset[24]) -> offset[23,22] 83908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project offset[24:22] already have the same value because of the 83918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project sign extension above. */ 83928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project offset ^= ((~insn) & (1 << 13)) << 10; 83938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project offset ^= ((~insn) & (1 << 11)) << 11; 83948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 83958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 14)) { 83968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Branch and link. */ 83975285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_movi_i32(cpu_R[14], s->pc | 1); 83988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 83998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 84008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project offset += s->pc; 84018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 12)) { 84028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* b/bl */ 84038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_jmp(s, offset); 84048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 84058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* blx */ 84068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project offset &= ~(uint32_t)2; 84075285864985be9077e58e42235af6582dee72e841David 'Digit' Turner /* thumb2 bx, no need to check */ 84088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_bx_im(s, offset); 84098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 84108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else if (((insn >> 23) & 7) == 7) { 84118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Misc control */ 84128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 13)) 84138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto illegal_op; 84148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 84158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 26)) { 84165285864985be9077e58e42235af6582dee72e841David 'Digit' Turner /* Secure monitor call / smc (v6Z) */ 84175285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (!(env->cp15.c0_c2[4] & 0xf000) || IS_USER(s)) { 84185285864985be9077e58e42235af6582dee72e841David 'Digit' Turner goto illegal_op; 84195285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 84205285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_smc(env, s); 84218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 84228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project op = (insn >> 20) & 7; 84238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (op) { 84248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0: /* msr cpsr. */ 84258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (IS_M(env)) { 84268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_reg(s, rn); 84278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project addr = tcg_const_i32(insn & 0xff); 84288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_helper_v7m_msr(cpu_env, addr, tmp); 84295285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(addr); 84305285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 84318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_lookup_tb(s); 84328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 84338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 84348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* fall through */ 84358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 1: /* msr spsr. */ 84368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (IS_M(env)) 84378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto illegal_op; 84385285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = load_reg(s, rn); 84395285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (gen_set_psr(s, 84408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project msr_mask(env, s, (insn >> 8) & 0xf, op == 1), 84415285864985be9077e58e42235af6582dee72e841David 'Digit' Turner op == 1, tmp)) 84428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto illegal_op; 84438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 84448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 2: /* cps, nop-hint. */ 84458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (((insn >> 8) & 7) == 0) { 84468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_nop_hint(s, insn & 0xff); 84478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 84488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Implemented as NOP in user mode. */ 84498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (IS_USER(s)) 84508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 84518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project offset = 0; 84528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project imm = 0; 84538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 10)) { 84548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 7)) 84558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project offset |= CPSR_A; 84568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 6)) 84578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project offset |= CPSR_I; 84588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 5)) 84598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project offset |= CPSR_F; 84608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 9)) 84618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project imm = CPSR_A | CPSR_I | CPSR_F; 84628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 84638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 8)) { 84648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project offset |= 0x1f; 84658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project imm |= (insn & 0x1f); 84668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 84678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (offset) { 84685285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_set_psr_im(s, offset, 0, imm); 84698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 84708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 84718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 3: /* Special control operations. */ 84725285864985be9077e58e42235af6582dee72e841David 'Digit' Turner ARCH(7); 84738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project op = (insn >> 4) & 0xf; 84748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (op) { 84758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 2: /* clrex */ 84765285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_clrex(s); 84778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 84788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 4: /* dsb */ 84798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 5: /* dmb */ 84808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 6: /* isb */ 84818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* These execute as NOPs. */ 84828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 84838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project default: 84848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto illegal_op; 84858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 84868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 84878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 4: /* bxj */ 84888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Trivial implementation equivalent to bx. */ 84898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_reg(s, rn); 84908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_bx(s, tmp); 84918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 84928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 5: /* Exception return. */ 84935285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (IS_USER(s)) { 84945285864985be9077e58e42235af6582dee72e841David 'Digit' Turner goto illegal_op; 84955285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 84965285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (rn != 14 || rd != 15) { 84975285864985be9077e58e42235af6582dee72e841David 'Digit' Turner goto illegal_op; 84985285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 84995285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = load_reg(s, rn); 85005285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_subi_i32(tmp, tmp, insn & 0xff); 85015285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_exception_return(s, tmp); 85025285864985be9077e58e42235af6582dee72e841David 'Digit' Turner break; 85038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 6: /* mrs cpsr. */ 85045285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = tcg_temp_new_i32(); 85058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (IS_M(env)) { 85068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project addr = tcg_const_i32(insn & 0xff); 85078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_helper_v7m_mrs(tmp, cpu_env, addr); 85085285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(addr); 85098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 85108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_helper_cpsr_read(tmp); 85118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 85128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project store_reg(s, rd, tmp); 85138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 85148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 7: /* mrs spsr. */ 85158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Not accessible in user mode. */ 85168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (IS_USER(s) || IS_M(env)) 85178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto illegal_op; 85188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_cpu_field(spsr); 85198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project store_reg(s, rd, tmp); 85208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 85218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 85228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 85238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 85248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Conditional branch. */ 85258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project op = (insn >> 22) & 0xf; 85268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Generate a conditional jump to next instruction. */ 85278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project s->condlabel = gen_new_label(); 85288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_test_cc(op ^ 1, s->condlabel); 85298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project s->condjmp = 1; 85308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 85318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* offset[11:1] = insn[10:0] */ 85328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project offset = (insn & 0x7ff) << 1; 85338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* offset[17:12] = insn[21:16]. */ 85348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project offset |= (insn & 0x003f0000) >> 4; 85358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* offset[31:20] = insn[26]. */ 85368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project offset |= ((int32_t)((insn << 5) & 0x80000000)) >> 11; 85378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* offset[18] = insn[13]. */ 85388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project offset |= (insn & (1 << 13)) << 5; 85398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* offset[19] = insn[11]. */ 85408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project offset |= (insn & (1 << 11)) << 8; 85418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 85428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* jump to the offset */ 85438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_jmp(s, s->pc + offset); 85448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 85458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 85468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Data processing immediate. */ 85478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 25)) { 85488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 24)) { 85498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 20)) 85508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto illegal_op; 85518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Bitfield/Saturate. */ 85528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project op = (insn >> 21) & 7; 85538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project imm = insn & 0x1f; 85548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project shift = ((insn >> 6) & 3) | ((insn >> 10) & 0x1c); 85558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (rn == 15) { 85565285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = tcg_temp_new_i32(); 85578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_movi_i32(tmp, 0); 85588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 85598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_reg(s, rn); 85608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 85618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (op) { 85628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 2: /* Signed bitfield extract. */ 85638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project imm++; 85648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (shift + imm > 32) 85658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto illegal_op; 85668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (imm < 32) 85678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_sbfx(tmp, shift, imm); 85688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 85698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 6: /* Unsigned bitfield extract. */ 85708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project imm++; 85718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (shift + imm > 32) 85728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto illegal_op; 85738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (imm < 32) 85748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_ubfx(tmp, shift, (1u << imm) - 1); 85758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 85768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 3: /* Bitfield insert/clear. */ 85778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (imm < shift) 85788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto illegal_op; 85798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project imm = imm + 1 - shift; 85808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (imm != 32) { 85818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp2 = load_reg(s, rd); 85828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_bfi(tmp, tmp2, tmp, shift, (1u << imm) - 1); 85835285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 85848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 85858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 85868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 7: 85878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto illegal_op; 85888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project default: /* Saturate. */ 85898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (shift) { 85908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (op & 1) 85918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_sari_i32(tmp, tmp, shift); 85928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 85938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_shli_i32(tmp, tmp, shift); 85948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 85958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp2 = tcg_const_i32(imm); 85968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (op & 4) { 85978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Unsigned. */ 85988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if ((op & 1) && shift == 0) 85998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_helper_usat16(tmp, tmp, tmp2); 86008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 86018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_helper_usat(tmp, tmp, tmp2); 86028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 86038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Signed. */ 86048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if ((op & 1) && shift == 0) 86058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_helper_ssat16(tmp, tmp, tmp2); 86068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 86078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_helper_ssat(tmp, tmp, tmp2); 86088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 86095285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 86108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 86118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 86128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project store_reg(s, rd, tmp); 86138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 86148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project imm = ((insn & 0x04000000) >> 15) 86158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project | ((insn & 0x7000) >> 4) | (insn & 0xff); 86168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 22)) { 86178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* 16-bit immediate. */ 86188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project imm |= (insn >> 4) & 0xf000; 86198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 23)) { 86208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* movt */ 86218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_reg(s, rd); 86228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_ext16u_i32(tmp, tmp); 86238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_ori_i32(tmp, tmp, imm << 16); 86248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 86258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* movw */ 86265285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = tcg_temp_new_i32(); 86278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_movi_i32(tmp, imm); 86288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 86298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 86308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Add/sub 12-bit immediate. */ 86318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (rn == 15) { 86328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project offset = s->pc & ~(uint32_t)3; 86338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 23)) 86348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project offset -= imm; 86358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 86368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project offset += imm; 86375285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = tcg_temp_new_i32(); 86388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_movi_i32(tmp, offset); 86398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 86408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_reg(s, rn); 86418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 23)) 86428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_subi_i32(tmp, tmp, imm); 86438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 86448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_addi_i32(tmp, tmp, imm); 86458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 86468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 86478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project store_reg(s, rd, tmp); 86488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 86498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 86508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int shifter_out = 0; 86518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* modified 12-bit immediate. */ 86528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project shift = ((insn & 0x04000000) >> 23) | ((insn & 0x7000) >> 12); 86538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project imm = (insn & 0xff); 86548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (shift) { 86558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0: /* XY */ 86568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Nothing to do. */ 86578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 86588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 1: /* 00XY00XY */ 86598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project imm |= imm << 16; 86608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 86618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 2: /* XY00XY00 */ 86628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project imm |= imm << 16; 86638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project imm <<= 8; 86648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 86658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 3: /* XYXYXYXY */ 86668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project imm |= imm << 16; 86678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project imm |= imm << 8; 86688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 86698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project default: /* Rotated constant. */ 86708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project shift = (shift << 1) | (imm >> 7); 86718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project imm |= 0x80; 86728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project imm = imm << (32 - shift); 86738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project shifter_out = 1; 86748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 86758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 86765285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp2 = tcg_temp_new_i32(); 86775285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_movi_i32(tmp2, imm); 86788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rn = (insn >> 16) & 0xf; 86795285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (rn == 15) { 86805285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = tcg_temp_new_i32(); 86815285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_movi_i32(tmp, 0); 86825285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } else { 86835285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = load_reg(s, rn); 86845285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 86858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project op = (insn >> 21) & 0xf; 86868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (gen_thumb2_data_op(s, op, (insn & (1 << 20)) != 0, 86875285864985be9077e58e42235af6582dee72e841David 'Digit' Turner shifter_out, tmp, tmp2)) 86888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto illegal_op; 86895285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 86908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd = (insn >> 8) & 0xf; 86918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (rd != 15) { 86925285864985be9077e58e42235af6582dee72e841David 'Digit' Turner store_reg(s, rd, tmp); 86935285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } else { 86945285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 86958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 86968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 86978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 86988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 86998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 12: /* Load/store single data item. */ 87008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project { 87018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int postinc = 0; 87028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int writeback = 0; 87038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int user; 87048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if ((insn & 0x01100000) == 0x01000000) { 87058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (disas_neon_ls_insn(env, s, insn)) 87068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto illegal_op; 87078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 87088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 87095285864985be9077e58e42235af6582dee72e841David 'Digit' Turner op = ((insn >> 21) & 3) | ((insn >> 22) & 4); 87105285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (rs == 15) { 87115285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (!(insn & (1 << 20))) { 87125285864985be9077e58e42235af6582dee72e841David 'Digit' Turner goto illegal_op; 87135285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 87145285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (op != 2) { 87155285864985be9077e58e42235af6582dee72e841David 'Digit' Turner /* Byte or halfword load space with dest == r15 : memory hints. 87165285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * Catch them early so we don't emit pointless addressing code. 87175285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * This space is a mix of: 87185285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * PLD/PLDW/PLI, which we implement as NOPs (note that unlike 87195285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * the ARM encodings, PLDW space doesn't UNDEF for non-v7MP 87205285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * cores) 87215285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * unallocated hints, which must be treated as NOPs 87225285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * UNPREDICTABLE space, which we NOP or UNDEF depending on 87235285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * which is easiest for the decoding logic 87245285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * Some space which must UNDEF 87255285864985be9077e58e42235af6582dee72e841David 'Digit' Turner */ 87265285864985be9077e58e42235af6582dee72e841David 'Digit' Turner int op1 = (insn >> 23) & 3; 87275285864985be9077e58e42235af6582dee72e841David 'Digit' Turner int op2 = (insn >> 6) & 0x3f; 87285285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (op & 2) { 87295285864985be9077e58e42235af6582dee72e841David 'Digit' Turner goto illegal_op; 87305285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 87315285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (rn == 15) { 87325285864985be9077e58e42235af6582dee72e841David 'Digit' Turner /* UNPREDICTABLE or unallocated hint */ 87335285864985be9077e58e42235af6582dee72e841David 'Digit' Turner return 0; 87345285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 87355285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (op1 & 1) { 87365285864985be9077e58e42235af6582dee72e841David 'Digit' Turner return 0; /* PLD* or unallocated hint */ 87375285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 87385285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if ((op2 == 0) || ((op2 & 0x3c) == 0x30)) { 87395285864985be9077e58e42235af6582dee72e841David 'Digit' Turner return 0; /* PLD* or unallocated hint */ 87405285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 87415285864985be9077e58e42235af6582dee72e841David 'Digit' Turner /* UNDEF space, or an UNPREDICTABLE */ 87425285864985be9077e58e42235af6582dee72e841David 'Digit' Turner return 1; 87435285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 87445285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 87458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project user = IS_USER(s); 87468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (rn == 15) { 87475285864985be9077e58e42235af6582dee72e841David 'Digit' Turner addr = tcg_temp_new_i32(); 87488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* PC relative. */ 87498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* s->pc has already been incremented by 4. */ 87508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project imm = s->pc & 0xfffffffc; 87518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 23)) 87528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project imm += insn & 0xfff; 87538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 87548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project imm -= insn & 0xfff; 87558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_movi_i32(addr, imm); 87568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 87578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project addr = load_reg(s, rn); 87588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 23)) { 87598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Positive offset. */ 87608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project imm = insn & 0xfff; 87618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_addi_i32(addr, addr, imm); 87628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 87638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project imm = insn & 0xff; 87645285864985be9077e58e42235af6582dee72e841David 'Digit' Turner switch ((insn >> 8) & 0xf) { 87655285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 0x0: /* Shifted Register. */ 87668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project shift = (insn >> 4) & 0xf; 87675285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (shift > 3) { 87685285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(addr); 87698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto illegal_op; 87705285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 87718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_reg(s, rm); 87728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (shift) 87738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_shli_i32(tmp, tmp, shift); 87748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_add_i32(addr, addr, tmp); 87755285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 87768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 87775285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 0xc: /* Negative offset. */ 87788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_addi_i32(addr, addr, -imm); 87798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 87805285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 0xe: /* User privilege. */ 87818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_addi_i32(addr, addr, imm); 87828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project user = 1; 87838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 87845285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 0x9: /* Post-decrement. */ 87858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project imm = -imm; 87868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Fall through. */ 87875285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 0xb: /* Post-increment. */ 87888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project postinc = 1; 87898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project writeback = 1; 87908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 87915285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 0xd: /* Pre-decrement. */ 87928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project imm = -imm; 87938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Fall through. */ 87945285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 0xf: /* Pre-increment. */ 87958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_addi_i32(addr, addr, imm); 87968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project writeback = 1; 87978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 87988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project default: 87995285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(addr); 88008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto illegal_op; 88018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 88028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 88038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 88048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 20)) { 88058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Load. */ 88065285864985be9077e58e42235af6582dee72e841David 'Digit' Turner switch (op) { 88075285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 0: tmp = gen_ld8u(addr, user); break; 88085285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 4: tmp = gen_ld8s(addr, user); break; 88095285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 1: tmp = gen_ld16u(addr, user); break; 88105285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 5: tmp = gen_ld16s(addr, user); break; 88115285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 2: tmp = gen_ld32(addr, user); break; 88125285864985be9077e58e42235af6582dee72e841David 'Digit' Turner default: 88135285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(addr); 88145285864985be9077e58e42235af6582dee72e841David 'Digit' Turner goto illegal_op; 88155285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 88165285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (rs == 15) { 88175285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_bx(s, tmp); 88188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 88195285864985be9077e58e42235af6582dee72e841David 'Digit' Turner store_reg(s, rs, tmp); 88208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 88218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 88228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Store. */ 88238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_reg(s, rs); 88248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (op) { 88258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0: gen_st8(tmp, addr, user); break; 88268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 1: gen_st16(tmp, addr, user); break; 88278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 2: gen_st32(tmp, addr, user); break; 88285285864985be9077e58e42235af6582dee72e841David 'Digit' Turner default: 88295285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(addr); 88305285864985be9077e58e42235af6582dee72e841David 'Digit' Turner goto illegal_op; 88318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 88328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 88338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (postinc) 88348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_addi_i32(addr, addr, imm); 88358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (writeback) { 88368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project store_reg(s, rn, addr); 88378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 88385285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(addr); 88398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 88408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 88418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 88428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project default: 88438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto illegal_op; 88448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 88458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 0; 88468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectillegal_op: 88478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 1; 88488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 88498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 88508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void disas_thumb_insn(CPUState *env, DisasContext *s) 88518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 88528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project uint32_t val, insn, op, rm, rn, rd, shift, cond; 88538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int32_t offset; 88548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int i; 88558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project TCGv tmp; 88568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project TCGv tmp2; 88578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project TCGv addr; 88588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 8859a1204591a52bf668ee72c86f98f53189621572a2Vladimir Chtchetkine if (s->condexec_mask) { 8860a1204591a52bf668ee72c86f98f53189621572a2Vladimir Chtchetkine cond = s->condexec_cond; 88615285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (cond != 0x0e) { /* Skip conditional when condition is AL. */ 88625285864985be9077e58e42235af6582dee72e841David 'Digit' Turner s->condlabel = gen_new_label(); 88635285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_test_cc(cond ^ 1, s->condlabel); 88645285864985be9077e58e42235af6582dee72e841David 'Digit' Turner s->condjmp = 1; 88655285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 88668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 88678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 88688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project insn = lduw_code(s->pc); 88695389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine 8870288208c386810fef725aa448a9f46bd2772bec8cDavid 'Digit' Turner ANDROID_WATCH_CALLSTACK_THUMB(s); 8871288208c386810fef725aa448a9f46bd2772bec8cDavid 'Digit' Turner 8872288208c386810fef725aa448a9f46bd2772bec8cDavid 'Digit' Turner ANDROID_TRACE_START_THUMB(); 8873288208c386810fef725aa448a9f46bd2772bec8cDavid 'Digit' Turner 88748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project s->pc += 2; 88758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 88768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (insn >> 12) { 88778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0: case 1: 88785285864985be9077e58e42235af6582dee72e841David 'Digit' Turner 88798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd = insn & 7; 88808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project op = (insn >> 11) & 3; 88818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (op == 3) { 88828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* add/subtract */ 88838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rn = (insn >> 3) & 7; 88845285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = load_reg(s, rn); 88858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 10)) { 88868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* immediate */ 88875285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp2 = tcg_temp_new_i32(); 88885285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_movi_i32(tmp2, (insn >> 6) & 7); 88898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 88908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* reg */ 88918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rm = (insn >> 6) & 7; 88925285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp2 = load_reg(s, rm); 88938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 88948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 9)) { 88958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (s->condexec_mask) 88965285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_sub_i32(tmp, tmp, tmp2); 88978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 88985285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_sub_cc(tmp, tmp, tmp2); 88998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 89008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (s->condexec_mask) 89015285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_add_i32(tmp, tmp, tmp2); 89028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 89035285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_add_cc(tmp, tmp, tmp2); 89048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 89055285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 89065285864985be9077e58e42235af6582dee72e841David 'Digit' Turner store_reg(s, rd, tmp); 89078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 89088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* shift immediate */ 89098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rm = (insn >> 3) & 7; 89108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project shift = (insn >> 6) & 0x1f; 89118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_reg(s, rm); 89128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_arm_shift_im(tmp, op, shift, s->condexec_mask == 0); 89138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (!s->condexec_mask) 89148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_logic_CC(tmp); 89158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project store_reg(s, rd, tmp); 89168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 89178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 89188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 2: case 3: 89198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* arithmetic large immediate */ 89208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project op = (insn >> 11) & 3; 89218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd = (insn >> 8) & 0x7; 89225285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (op == 0) { /* mov */ 89235285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = tcg_temp_new_i32(); 89245285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_movi_i32(tmp, insn & 0xff); 89258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (!s->condexec_mask) 89265285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_logic_CC(tmp); 89275285864985be9077e58e42235af6582dee72e841David 'Digit' Turner store_reg(s, rd, tmp); 89285285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } else { 89295285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = load_reg(s, rd); 89305285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp2 = tcg_temp_new_i32(); 89315285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_movi_i32(tmp2, insn & 0xff); 89325285864985be9077e58e42235af6582dee72e841David 'Digit' Turner switch (op) { 89335285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 1: /* cmp */ 89345285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_sub_cc(tmp, tmp, tmp2); 89355285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 89365285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 89375285864985be9077e58e42235af6582dee72e841David 'Digit' Turner break; 89385285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 2: /* add */ 89395285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (s->condexec_mask) 89405285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_add_i32(tmp, tmp, tmp2); 89415285864985be9077e58e42235af6582dee72e841David 'Digit' Turner else 89425285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_add_cc(tmp, tmp, tmp2); 89435285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 89445285864985be9077e58e42235af6582dee72e841David 'Digit' Turner store_reg(s, rd, tmp); 89455285864985be9077e58e42235af6582dee72e841David 'Digit' Turner break; 89465285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case 3: /* sub */ 89475285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (s->condexec_mask) 89485285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_sub_i32(tmp, tmp, tmp2); 89495285864985be9077e58e42235af6582dee72e841David 'Digit' Turner else 89505285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_sub_cc(tmp, tmp, tmp2); 89515285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 89525285864985be9077e58e42235af6582dee72e841David 'Digit' Turner store_reg(s, rd, tmp); 89535285864985be9077e58e42235af6582dee72e841David 'Digit' Turner break; 89545285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 89558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 89568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 89578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 4: 89588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 11)) { 89598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd = (insn >> 8) & 7; 89608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* load pc-relative. Bit 1 of PC is ignored. */ 89618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project val = s->pc + 2 + ((insn & 0xff) * 4); 89628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project val &= ~(uint32_t)2; 89635285864985be9077e58e42235af6582dee72e841David 'Digit' Turner addr = tcg_temp_new_i32(); 89648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_movi_i32(addr, val); 89658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = gen_ld32(addr, IS_USER(s)); 89665285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(addr); 89678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project store_reg(s, rd, tmp); 89688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 89698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 89708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 10)) { 89718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* data processing extended or blx */ 89728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd = (insn & 7) | ((insn >> 4) & 8); 89738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rm = (insn >> 3) & 0xf; 89748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project op = (insn >> 8) & 3; 89758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (op) { 89768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0: /* add */ 89775285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = load_reg(s, rd); 89785285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp2 = load_reg(s, rm); 89795285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_add_i32(tmp, tmp, tmp2); 89805285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 89815285864985be9077e58e42235af6582dee72e841David 'Digit' Turner store_reg(s, rd, tmp); 89828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 89838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 1: /* cmp */ 89845285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = load_reg(s, rd); 89855285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp2 = load_reg(s, rm); 89865285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_sub_cc(tmp, tmp, tmp2); 89875285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 89885285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 89898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 89908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 2: /* mov/cpy */ 89915285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = load_reg(s, rm); 89925285864985be9077e58e42235af6582dee72e841David 'Digit' Turner store_reg(s, rd, tmp); 89938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 89948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 3:/* branch [and link] exchange thumb register */ 89958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_reg(s, rm); 89968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 7)) { 89975285864985be9077e58e42235af6582dee72e841David 'Digit' Turner ARCH(5); 89988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project val = (uint32_t)s->pc | 1; 89995285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp2 = tcg_temp_new_i32(); 90008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_movi_i32(tmp2, val); 90018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project store_reg(s, 14, tmp2); 90028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 90035285864985be9077e58e42235af6582dee72e841David 'Digit' Turner /* already thumb, no need to check */ 90048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_bx(s, tmp); 90058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 90068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 90078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 90088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 90098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 90108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* data processing register */ 90118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd = insn & 7; 90128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rm = (insn >> 3) & 7; 90138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project op = (insn >> 6) & 0xf; 90148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (op == 2 || op == 3 || op == 4 || op == 7) { 90158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* the shift/rotate ops want the operands backwards */ 90168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project val = rm; 90178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rm = rd; 90188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd = val; 90198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project val = 1; 90208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 90218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project val = 0; 90228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 90238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 90245285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (op == 9) { /* neg */ 90255285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = tcg_temp_new_i32(); 90265285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_movi_i32(tmp, 0); 90275285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } else if (op != 0xf) { /* mvn doesn't read its first operand */ 90285285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = load_reg(s, rd); 90295285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } else { 90305285864985be9077e58e42235af6582dee72e841David 'Digit' Turner TCGV_UNUSED(tmp); 90315285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 90328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 90335285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp2 = load_reg(s, rm); 90348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (op) { 90358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x0: /* and */ 90365285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_and_i32(tmp, tmp, tmp2); 90378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (!s->condexec_mask) 90385285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_logic_CC(tmp); 90398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 90408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x1: /* eor */ 90415285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_xor_i32(tmp, tmp, tmp2); 90428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (!s->condexec_mask) 90435285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_logic_CC(tmp); 90448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 90458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x2: /* lsl */ 90468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (s->condexec_mask) { 90475285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_shl(tmp2, tmp2, tmp); 90488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 90495285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_shl_cc(tmp2, tmp2, tmp); 90505285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_logic_CC(tmp2); 90518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 90528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 90538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x3: /* lsr */ 90548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (s->condexec_mask) { 90555285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_shr(tmp2, tmp2, tmp); 90568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 90575285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_shr_cc(tmp2, tmp2, tmp); 90585285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_logic_CC(tmp2); 90598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 90608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 90618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x4: /* asr */ 90628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (s->condexec_mask) { 90635285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_sar(tmp2, tmp2, tmp); 90648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 90655285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_sar_cc(tmp2, tmp2, tmp); 90665285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_logic_CC(tmp2); 90678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 90688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 90698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x5: /* adc */ 90708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (s->condexec_mask) 90715285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_adc(tmp, tmp2); 90728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 90735285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_adc_cc(tmp, tmp, tmp2); 90748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 90758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x6: /* sbc */ 90768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (s->condexec_mask) 90775285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_sub_carry(tmp, tmp, tmp2); 90788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 90795285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_sbc_cc(tmp, tmp, tmp2); 90808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 90818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x7: /* ror */ 90828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (s->condexec_mask) { 90835285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_andi_i32(tmp, tmp, 0x1f); 90845285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_rotr_i32(tmp2, tmp2, tmp); 90858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 90865285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_ror_cc(tmp2, tmp2, tmp); 90875285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_logic_CC(tmp2); 90888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 90898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 90908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x8: /* tst */ 90915285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_and_i32(tmp, tmp, tmp2); 90925285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_logic_CC(tmp); 90938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd = 16; 90948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 90958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0x9: /* neg */ 90968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (s->condexec_mask) 90975285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_neg_i32(tmp, tmp2); 90988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 90995285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_sub_cc(tmp, tmp, tmp2); 91008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 91018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0xa: /* cmp */ 91025285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_sub_cc(tmp, tmp, tmp2); 91038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd = 16; 91048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 91058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0xb: /* cmn */ 91065285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_helper_add_cc(tmp, tmp, tmp2); 91078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd = 16; 91088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 91098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0xc: /* orr */ 91105285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_or_i32(tmp, tmp, tmp2); 91118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (!s->condexec_mask) 91125285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_logic_CC(tmp); 91138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 91148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0xd: /* mul */ 91155285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_mul_i32(tmp, tmp, tmp2); 91168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (!s->condexec_mask) 91175285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_logic_CC(tmp); 91188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 91198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0xe: /* bic */ 91205285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_andc_i32(tmp, tmp, tmp2); 91218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (!s->condexec_mask) 91225285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_logic_CC(tmp); 91238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 91248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0xf: /* mvn */ 91255285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_not_i32(tmp2, tmp2); 91268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (!s->condexec_mask) 91275285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_logic_CC(tmp2); 91288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project val = 1; 91298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rm = rd; 91308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 91318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 91328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (rd != 16) { 91335285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (val) { 91345285864985be9077e58e42235af6582dee72e841David 'Digit' Turner store_reg(s, rm, tmp2); 91355285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (op != 0xf) 91365285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 91375285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } else { 91385285864985be9077e58e42235af6582dee72e841David 'Digit' Turner store_reg(s, rd, tmp); 91395285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 91405285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 91415285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } else { 91425285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 91435285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 91448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 91458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 91468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 91478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 5: 91488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* load/store register offset. */ 91498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd = insn & 7; 91508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rn = (insn >> 3) & 7; 91518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rm = (insn >> 6) & 7; 91528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project op = (insn >> 9) & 7; 91538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project addr = load_reg(s, rn); 91548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_reg(s, rm); 91558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_add_i32(addr, addr, tmp); 91565285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 91578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 91588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (op < 3) /* store */ 91598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_reg(s, rd); 91608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 91618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (op) { 91628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0: /* str */ 91638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_st32(tmp, addr, IS_USER(s)); 91648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 91658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 1: /* strh */ 91668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_st16(tmp, addr, IS_USER(s)); 91678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 91688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 2: /* strb */ 91698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_st8(tmp, addr, IS_USER(s)); 91708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 91718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 3: /* ldrsb */ 91728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = gen_ld8s(addr, IS_USER(s)); 91738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 91748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 4: /* ldr */ 91758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = gen_ld32(addr, IS_USER(s)); 91768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 91778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 5: /* ldrh */ 91788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = gen_ld16u(addr, IS_USER(s)); 91798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 91808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 6: /* ldrb */ 91818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = gen_ld8u(addr, IS_USER(s)); 91828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 91838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 7: /* ldrsh */ 91848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = gen_ld16s(addr, IS_USER(s)); 91858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 91868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 91878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (op >= 3) /* load */ 91888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project store_reg(s, rd, tmp); 91895285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(addr); 91908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 91918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 91928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 6: 91938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* load/store word immediate offset */ 91948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd = insn & 7; 91958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rn = (insn >> 3) & 7; 91968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project addr = load_reg(s, rn); 91978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project val = (insn >> 4) & 0x7c; 91988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_addi_i32(addr, addr, val); 91998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 92008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 11)) { 92018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* load */ 92028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = gen_ld32(addr, IS_USER(s)); 92038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project store_reg(s, rd, tmp); 92048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 92058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* store */ 92068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_reg(s, rd); 92078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_st32(tmp, addr, IS_USER(s)); 92088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 92095285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(addr); 92108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 92118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 92128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 7: 92138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* load/store byte immediate offset */ 92148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd = insn & 7; 92158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rn = (insn >> 3) & 7; 92168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project addr = load_reg(s, rn); 92178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project val = (insn >> 6) & 0x1f; 92188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_addi_i32(addr, addr, val); 92198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 92208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 11)) { 92218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* load */ 92228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = gen_ld8u(addr, IS_USER(s)); 92238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project store_reg(s, rd, tmp); 92248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 92258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* store */ 92268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_reg(s, rd); 92278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_st8(tmp, addr, IS_USER(s)); 92288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 92295285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(addr); 92308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 92318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 92328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 8: 92338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* load/store halfword immediate offset */ 92348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd = insn & 7; 92358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rn = (insn >> 3) & 7; 92368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project addr = load_reg(s, rn); 92378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project val = (insn >> 5) & 0x3e; 92388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_addi_i32(addr, addr, val); 92398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 92408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 11)) { 92418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* load */ 92428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = gen_ld16u(addr, IS_USER(s)); 92438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project store_reg(s, rd, tmp); 92448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 92458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* store */ 92468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_reg(s, rd); 92478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_st16(tmp, addr, IS_USER(s)); 92488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 92495285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(addr); 92508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 92518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 92528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 9: 92538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* load/store from stack */ 92548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd = (insn >> 8) & 7; 92558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project addr = load_reg(s, 13); 92568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project val = (insn & 0xff) * 4; 92578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_addi_i32(addr, addr, val); 92588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 92598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 11)) { 92608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* load */ 92618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = gen_ld32(addr, IS_USER(s)); 92628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project store_reg(s, rd, tmp); 92638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 92648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* store */ 92658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_reg(s, rd); 92668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_st32(tmp, addr, IS_USER(s)); 92678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 92685285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(addr); 92698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 92708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 92718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 10: 92728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* add to high reg */ 92738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd = (insn >> 8) & 7; 92748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 11)) { 92758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* SP */ 92768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_reg(s, 13); 92778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 92788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* PC. bit 1 is ignored. */ 92795285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp = tcg_temp_new_i32(); 92808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_movi_i32(tmp, (s->pc + 2) & ~(uint32_t)2); 92818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 92828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project val = (insn & 0xff) * 4; 92838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_addi_i32(tmp, tmp, val); 92848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project store_reg(s, rd, tmp); 92858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 92868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 92878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 11: 92888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* misc */ 92898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project op = (insn >> 8) & 0xf; 92908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (op) { 92918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0: 92928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* adjust stack pointer */ 92938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_reg(s, 13); 92948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project val = (insn & 0x7f) * 4; 92958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 7)) 92968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project val = -(int32_t)val; 92978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_addi_i32(tmp, tmp, val); 92988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project store_reg(s, 13, tmp); 92998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 93008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 93018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 2: /* sign/zero extend. */ 93028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ARCH(6); 93038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd = insn & 7; 93048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rm = (insn >> 3) & 7; 93058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_reg(s, rm); 93068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch ((insn >> 6) & 3) { 93078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0: gen_sxth(tmp); break; 93088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 1: gen_sxtb(tmp); break; 93098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 2: gen_uxth(tmp); break; 93108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 3: gen_uxtb(tmp); break; 93118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 93128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project store_reg(s, rd, tmp); 93138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 93148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 4: case 5: case 0xc: case 0xd: 93158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* push/pop */ 93168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project addr = load_reg(s, 13); 93178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 8)) 93188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project offset = 4; 93198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 93208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project offset = 0; 93218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project for (i = 0; i < 8; i++) { 93228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << i)) 93238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project offset += 4; 93248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 93258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if ((insn & (1 << 11)) == 0) { 93268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_addi_i32(addr, addr, -offset); 93278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 93285285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tmp2 = tcg_const_i32(4); 93298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project for (i = 0; i < 8; i++) { 93308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << i)) { 93318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 11)) { 93328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* pop */ 93338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = gen_ld32(addr, IS_USER(s)); 93348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project store_reg(s, i, tmp); 93358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 93368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* push */ 93378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_reg(s, i); 93388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_st32(tmp, addr, IS_USER(s)); 93398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 93408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* advance to the next address. */ 93415285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_add_i32(addr, addr, tmp2); 93428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 93438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 93448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project TCGV_UNUSED(tmp); 93458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 8)) { 93468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 11)) { 93478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* pop pc */ 93488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = gen_ld32(addr, IS_USER(s)); 93498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* don't set the pc until the rest of the instruction 93508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project has completed */ 93518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 93528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* push lr */ 93538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_reg(s, 14); 93548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_st32(tmp, addr, IS_USER(s)); 93558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 93565285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_add_i32(addr, addr, tmp2); 93578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 93585285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp2); 93598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if ((insn & (1 << 11)) == 0) { 93608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_addi_i32(addr, addr, -offset); 93618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 93628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* write back the new stack pointer */ 93638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project store_reg(s, 13, addr); 93648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* set the new PC value */ 93655285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if ((insn & 0x0900) == 0x0900) { 93665285864985be9077e58e42235af6582dee72e841David 'Digit' Turner store_reg_from_load(env, s, 15, tmp); 93675285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 93688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 93698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 93708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 1: case 3: case 9: case 11: /* czb */ 93718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rm = insn & 7; 93728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_reg(s, rm); 93738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project s->condlabel = gen_new_label(); 93748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project s->condjmp = 1; 93758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 11)) 93768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, s->condlabel); 93778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 93788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, s->condlabel); 93795285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 93808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project offset = ((insn & 0xf8) >> 2) | (insn & 0x200) >> 3; 93818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project val = (uint32_t)s->pc + 2; 93828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project val += offset; 93838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_jmp(s, val); 93848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 93858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 93868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 15: /* IT, nop-hint. */ 93878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if ((insn & 0xf) == 0) { 93888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_nop_hint(s, (insn >> 4) & 0xf); 93898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 93908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 93918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* If Then. */ 9392a1204591a52bf668ee72c86f98f53189621572a2Vladimir Chtchetkine s->condexec_cond = (insn >> 4) & 0xe; 9393a1204591a52bf668ee72c86f98f53189621572a2Vladimir Chtchetkine s->condexec_mask = insn & 0x1f; 93948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* No actual code generated for this insn, just setup state. */ 93958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 93968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 93978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0xe: /* bkpt */ 93985285864985be9077e58e42235af6582dee72e841David 'Digit' Turner ARCH(5); 93995285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_exception_insn(s, 2, EXCP_BKPT); 94008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 94018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 94028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 0xa: /* rev */ 94038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ARCH(6); 94048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rn = (insn >> 3) & 0x7; 94058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rd = insn & 0x7; 94068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_reg(s, rn); 94078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch ((insn >> 6) & 3) { 94085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner case 0: tcg_gen_bswap32_i32(tmp, tmp); break; 94098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 1: gen_rev16(tmp); break; 94108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 3: gen_revsh(tmp); break; 94118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project default: goto illegal_op; 94128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 94138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project store_reg(s, rd, tmp); 94148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 94158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 94168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 6: /* cps */ 94178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ARCH(6); 94188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (IS_USER(s)) 94198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 94208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (IS_M(env)) { 94218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = tcg_const_i32((insn & (1 << 4)) != 0); 94228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* PRIMASK */ 94238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & 1) { 94248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project addr = tcg_const_i32(16); 94258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_helper_v7m_msr(cpu_env, addr, tmp); 94265285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(addr); 94278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 94288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* FAULTMASK */ 94298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & 2) { 94308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project addr = tcg_const_i32(17); 94318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_helper_v7m_msr(cpu_env, addr, tmp); 94325285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(addr); 94338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 94345285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(tmp); 94358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_lookup_tb(s); 94368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 94378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 4)) 94388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project shift = CPSR_A | CPSR_I | CPSR_F; 94398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 94408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project shift = 0; 94415285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_set_psr_im(s, ((insn & 7) << 6), 0, shift); 94428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 94438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 94448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 94458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project default: 94468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto undef; 94478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 94488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 94498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 94508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 12: 94515285864985be9077e58e42235af6582dee72e841David 'Digit' Turner { 94528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* load/store multiple */ 94535285864985be9077e58e42235af6582dee72e841David 'Digit' Turner TCGv loaded_var; 94545285864985be9077e58e42235af6582dee72e841David 'Digit' Turner TCGV_UNUSED(loaded_var); 94558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project rn = (insn >> 8) & 0x7; 94568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project addr = load_reg(s, rn); 94578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project for (i = 0; i < 8; i++) { 94588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << i)) { 94598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 11)) { 94608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* load */ 94618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = gen_ld32(addr, IS_USER(s)); 94625285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (i == rn) { 94635285864985be9077e58e42235af6582dee72e841David 'Digit' Turner loaded_var = tmp; 94645285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } else { 94655285864985be9077e58e42235af6582dee72e841David 'Digit' Turner store_reg(s, i, tmp); 94665285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 94678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 94688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* store */ 94698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tmp = load_reg(s, i); 94708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_st32(tmp, addr, IS_USER(s)); 94718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 94728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* advance to the next address */ 94738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_addi_i32(addr, addr, 4); 94748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 94758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 94768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if ((insn & (1 << rn)) == 0) { 94775285864985be9077e58e42235af6582dee72e841David 'Digit' Turner /* base reg not in list: base register writeback */ 94788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project store_reg(s, rn, addr); 94798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 94805285864985be9077e58e42235af6582dee72e841David 'Digit' Turner /* base reg in list: if load, complete it now */ 94815285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (insn & (1 << 11)) { 94825285864985be9077e58e42235af6582dee72e841David 'Digit' Turner store_reg(s, rn, loaded_var); 94835285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 94845285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_temp_free_i32(addr); 94858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 94868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 94875285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 94888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 13: 94898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* conditional branch or swi */ 94908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project cond = (insn >> 8) & 0xf; 94918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (cond == 0xe) 94928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto undef; 94938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 94948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (cond == 0xf) { 94958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* swi */ 94968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_set_pc_im(s->pc); 94978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project s->is_jmp = DISAS_SWI; 94988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 94998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 95008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* generate a conditional jump to next instruction */ 95018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project s->condlabel = gen_new_label(); 95028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_test_cc(cond ^ 1, s->condlabel); 95038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project s->condjmp = 1; 95048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 95058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* jump to the offset */ 95068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project val = (uint32_t)s->pc + 2; 95078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project offset = ((int32_t)insn << 24) >> 24; 95088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project val += offset << 1; 95098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_jmp(s, val); 95108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 95118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 95128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 14: 95138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (insn & (1 << 11)) { 95148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (disas_thumb2_insn(env, s, insn)) 95158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto undef32; 95168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 95178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 95188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* unconditional branch */ 95198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project val = (uint32_t)s->pc; 95208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project offset = ((int32_t)insn << 21) >> 21; 95218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project val += (offset << 1) + 2; 95228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_jmp(s, val); 95238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 95248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 95258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case 15: 95268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (disas_thumb2_insn(env, s, insn)) 95278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto undef32; 95288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 95298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 95308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return; 95318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectundef32: 95325285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_exception_insn(s, 4, EXCP_UDEF); 95338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return; 95348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectillegal_op: 95358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectundef: 95365285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_exception_insn(s, 2, EXCP_UDEF); 95378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 95388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 95398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* generate intermediate code in gen_opc_buf and gen_opparam_buf for 95408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project basic block 'tb'. If search_pc is TRUE, also generate PC 95418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project information for each intermediate instruction. */ 95428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline void gen_intermediate_code_internal(CPUState *env, 95438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project TranslationBlock *tb, 95448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int search_pc) 95458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 95468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project DisasContext dc1, *dc = &dc1; 95475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner CPUBreakpoint *bp; 95488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project uint16_t *gen_opc_end; 95498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int j, lj; 95508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project target_ulong pc_start; 95518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project uint32_t next_page_start; 95528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int num_insns; 95538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int max_insns; 95548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 95558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* generate intermediate code */ 95568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project pc_start = tb->pc; 95578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 95588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project dc->tb = tb; 95598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 95608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_opc_end = gen_opc_buf + OPC_MAX_SIZE; 95618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 95628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project dc->is_jmp = DISAS_NEXT; 95638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project dc->pc = pc_start; 95648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project dc->singlestep_enabled = env->singlestep_enabled; 95658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project dc->condjmp = 0; 95665285864985be9077e58e42235af6582dee72e841David 'Digit' Turner dc->thumb = ARM_TBFLAG_THUMB(tb->flags); 95675285864985be9077e58e42235af6582dee72e841David 'Digit' Turner dc->condexec_mask = (ARM_TBFLAG_CONDEXEC(tb->flags) & 0xf) << 1; 95685285864985be9077e58e42235af6582dee72e841David 'Digit' Turner dc->condexec_cond = ARM_TBFLAG_CONDEXEC(tb->flags) >> 4; 95698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if !defined(CONFIG_USER_ONLY) 95705285864985be9077e58e42235af6582dee72e841David 'Digit' Turner dc->user = (ARM_TBFLAG_PRIV(tb->flags) == 0); 95718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif 9572288208c386810fef725aa448a9f46bd2772bec8cDavid 'Digit' Turner ANDROID_START_CODEGEN(search_pc); 95735285864985be9077e58e42235af6582dee72e841David 'Digit' Turner dc->vfp_enabled = ARM_TBFLAG_VFPEN(tb->flags); 95745285864985be9077e58e42235af6582dee72e841David 'Digit' Turner dc->vec_len = ARM_TBFLAG_VECLEN(tb->flags); 95755285864985be9077e58e42235af6582dee72e841David 'Digit' Turner dc->vec_stride = ARM_TBFLAG_VECSTRIDE(tb->flags); 95765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner cpu_F0s = tcg_temp_new_i32(); 95775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner cpu_F1s = tcg_temp_new_i32(); 95785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner cpu_F0d = tcg_temp_new_i64(); 95795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner cpu_F1d = tcg_temp_new_i64(); 95808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project cpu_V0 = cpu_F0d; 95818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project cpu_V1 = cpu_F1d; 95828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* FIXME: cpu_M0 can probably be the same as cpu_V0. */ 95835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner cpu_M0 = tcg_temp_new_i64(); 95848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE; 95858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project lj = -1; 95868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project num_insns = 0; 95878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project max_insns = tb->cflags & CF_COUNT_MASK; 95888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (max_insns == 0) 95898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project max_insns = CF_COUNT_MASK; 95908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 95918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_icount_start(); 9592288208c386810fef725aa448a9f46bd2772bec8cDavid 'Digit' Turner ANDROID_TRACE_START_BB(); 95938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 95945285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_clear_temp_count(); 95955285864985be9077e58e42235af6582dee72e841David 'Digit' Turner 95965285864985be9077e58e42235af6582dee72e841David 'Digit' Turner /* A note on handling of the condexec (IT) bits: 95975285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * 95985285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * We want to avoid the overhead of having to write the updated condexec 95995285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * bits back to the CPUState for every instruction in an IT block. So: 96005285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * (1) if the condexec bits are not already zero then we write 96015285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * zero back into the CPUState now. This avoids complications trying 96025285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * to do it at the end of the block. (For example if we don't do this 96035285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * it's hard to identify whether we can safely skip writing condexec 96045285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * at the end of the TB, which we definitely want to do for the case 96055285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * where a TB doesn't do anything with the IT state at all.) 96065285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * (2) if we are going to leave the TB then we call gen_set_condexec() 96075285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * which will write the correct value into CPUState if zero is wrong. 96085285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * This is done both for leaving the TB at the end, and for leaving 96095285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * it because of an exception we know will happen, which is done in 96105285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * gen_exception_insn(). The latter is necessary because we need to 96115285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * leave the TB with the PC/IT state just prior to execution of the 96125285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * instruction which caused the exception. 96135285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * (3) if we leave the TB unexpectedly (eg a data abort on a load) 96145285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * then the CPUState will be wrong and we need to reset it. 96155285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * This is handled in the same way as restoration of the 96165285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * PC in these situations: we will be called again with search_pc=1 96175285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * and generate a mapping of the condexec bits for each PC in 96185285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * gen_opc_condexec_bits[]. restore_state_to_opc() then uses 96195285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * this to restore the condexec bits. 96205285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * 96215285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * Note that there are no instructions which can read the condexec 96225285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * bits, and none which can write non-static values to them, so 96235285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * we don't need to care about whether CPUState is correct in the 96245285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * middle of a TB. 96255285864985be9077e58e42235af6582dee72e841David 'Digit' Turner */ 96265285864985be9077e58e42235af6582dee72e841David 'Digit' Turner 96275285864985be9077e58e42235af6582dee72e841David 'Digit' Turner /* Reset the conditional execution bits immediately. This avoids 96285285864985be9077e58e42235af6582dee72e841David 'Digit' Turner complications trying to do it at the end of the block. */ 96295285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (dc->condexec_mask || dc->condexec_cond) 96305285864985be9077e58e42235af6582dee72e841David 'Digit' Turner { 96315285864985be9077e58e42235af6582dee72e841David 'Digit' Turner TCGv tmp = tcg_temp_new_i32(); 96325285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_movi_i32(tmp, 0); 96335285864985be9077e58e42235af6582dee72e841David 'Digit' Turner store_cpu_field(tmp, condexec_bits); 96345285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 96358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project do { 96368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef CONFIG_USER_ONLY 96378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Intercept jump to the magic kernel page. */ 96388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (dc->pc >= 0xffff0000) { 96398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* We always get here via a jump, so know we are not in a 96408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project conditional execution block. */ 96418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_exception(EXCP_KERNEL_TRAP); 96428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project dc->is_jmp = DISAS_UPDATE; 96438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 96448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 96458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else 96468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (dc->pc >= 0xfffffff0 && IS_M(env)) { 96478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* We always get here via a jump, so know we are not in a 96488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project conditional execution block. */ 96498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_exception(EXCP_EXCEPTION_EXIT); 96508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project dc->is_jmp = DISAS_UPDATE; 96518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 96528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 96538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif 96548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 9655a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) { 9656a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner QTAILQ_FOREACH(bp, &env->breakpoints, entry) { 96575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (bp->pc == dc->pc) { 96585285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_exception_insn(dc, 0, EXCP_DEBUG); 96598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Advance PC so that clearing the breakpoint will 96608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project invalidate this TB. */ 96618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project dc->pc += 2; 96628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project goto done_generating; 96638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 96648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 96658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 96668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 96675389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine 9668288208c386810fef725aa448a9f46bd2772bec8cDavid 'Digit' Turner if (ANDROID_CHECK_CODEGEN_PC(search_pc)) { 96698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project j = gen_opc_ptr - gen_opc_buf; 96708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (lj < j) { 96718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project lj++; 96728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project while (lj < j) 96738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_opc_instr_start[lj++] = 0; 96748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 96758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_opc_pc[lj] = dc->pc; 96765285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_opc_condexec_bits[lj] = (dc->condexec_cond << 4) | (dc->condexec_mask >> 1); 96778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_opc_instr_start[lj] = 1; 96788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_opc_icount[lj] = num_insns; 96798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 96808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 96818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO)) 96828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_io_start(); 96838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 96845285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP))) { 96855285864985be9077e58e42235af6582dee72e841David 'Digit' Turner tcg_gen_debug_insn_start(dc->pc); 96865285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 96875285864985be9077e58e42235af6582dee72e841David 'Digit' Turner 96885285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (dc->thumb) { 96898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project disas_thumb_insn(env, dc); 96908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (dc->condexec_mask) { 9691a1204591a52bf668ee72c86f98f53189621572a2Vladimir Chtchetkine dc->condexec_cond = (dc->condexec_cond & 0xe) 9692a1204591a52bf668ee72c86f98f53189621572a2Vladimir Chtchetkine | ((dc->condexec_mask >> 4) & 1); 9693a1204591a52bf668ee72c86f98f53189621572a2Vladimir Chtchetkine dc->condexec_mask = (dc->condexec_mask << 1) & 0x1f; 9694a1204591a52bf668ee72c86f98f53189621572a2Vladimir Chtchetkine if (dc->condexec_mask == 0) { 9695a1204591a52bf668ee72c86f98f53189621572a2Vladimir Chtchetkine dc->condexec_cond = 0; 96968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 96978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 96988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 96998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project disas_arm_insn(env, dc); 97008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 97018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 97028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (dc->condjmp && !dc->is_jmp) { 97038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_set_label(dc->condlabel); 97048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project dc->condjmp = 0; 97058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 97065285864985be9077e58e42235af6582dee72e841David 'Digit' Turner 97075285864985be9077e58e42235af6582dee72e841David 'Digit' Turner if (tcg_check_temp_count()) { 97085285864985be9077e58e42235af6582dee72e841David 'Digit' Turner fprintf(stderr, "TCG temporary leak before %08x\n", dc->pc); 97095285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } 97105285864985be9077e58e42235af6582dee72e841David 'Digit' Turner 97115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* Translation stops when a conditional branch is encountered. 97128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Otherwise the subsequent code could get translated several times. 97138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Also stop translation when a page boundary is reached. This 97148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * ensures prefetch aborts occur at the right place. */ 97158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project num_insns ++; 97168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } while (!dc->is_jmp && gen_opc_ptr < gen_opc_end && 97178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project !env->singlestep_enabled && 97185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner !singlestep && 97198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project dc->pc < next_page_start && 97208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project num_insns < max_insns); 97218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 9722288208c386810fef725aa448a9f46bd2772bec8cDavid 'Digit' Turner ANDROID_TRACE_END_BB(); 97238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 97248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (tb->cflags & CF_LAST_IO) { 97258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (dc->condjmp) { 97268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* FIXME: This can theoretically happen with self-modifying 97278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project code. */ 97288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project cpu_abort(env, "IO on conditional branch instruction"); 97298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 97308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_io_end(); 97318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 97328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 97338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* At this stage dc->condjmp will only be set when the skipped 97348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project instruction was a conditional branch or trap, and the PC has 97358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project already been written. */ 97368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (unlikely(env->singlestep_enabled)) { 97378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Make sure the pc is updated, and raise a debug exception. */ 97388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (dc->condjmp) { 97398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_set_condexec(dc); 97408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (dc->is_jmp == DISAS_SWI) { 97418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_exception(EXCP_SWI); 97425285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } else if (dc->is_jmp == DISAS_SMC) { 97435285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_exception(EXCP_SMC); 97448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 97458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_exception(EXCP_DEBUG); 97468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 97478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_set_label(dc->condlabel); 97488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 97498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (dc->condjmp || !dc->is_jmp) { 97508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_set_pc_im(dc->pc); 97518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project dc->condjmp = 0; 97528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 97538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_set_condexec(dc); 97548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (dc->is_jmp == DISAS_SWI && !dc->condjmp) { 97558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_exception(EXCP_SWI); 97565285864985be9077e58e42235af6582dee72e841David 'Digit' Turner } else if (dc->is_jmp == DISAS_SMC && !dc->condjmp) { 97575285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_exception(EXCP_SMC); 97588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 97598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* FIXME: Single stepping a WFI insn will not halt 97608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project the CPU. */ 97618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_exception(EXCP_DEBUG); 97628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 97638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 97648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* While branches must always occur at the end of an IT block, 97658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project there are a few other things that can cause us to terminate 97668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project the TB in the middel of an IT block: 97678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project - Exception generating instructions (bkpt, swi, undefined). 97688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project - Page boundaries. 97698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project - Hardware watchpoints. 97708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project Hardware breakpoints have already been handled and skip this code. 97718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 97728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_set_condexec(dc); 97738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch(dc->is_jmp) { 97748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case DISAS_NEXT: 97758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_goto_tb(dc, 1, dc->pc); 97768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 97778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project default: 97788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case DISAS_JUMP: 97798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case DISAS_UPDATE: 97808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* indicate that the hash table must be used to find the next TB */ 97818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tcg_gen_exit_tb(0); 97828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 97838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case DISAS_TB_JUMP: 97848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* nothing more to generate */ 97858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 97868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case DISAS_WFI: 97878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_helper_wfi(); 97888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 97898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project case DISAS_SWI: 97908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_exception(EXCP_SWI); 97918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 97925285864985be9077e58e42235af6582dee72e841David 'Digit' Turner case DISAS_SMC: 97935285864985be9077e58e42235af6582dee72e841David 'Digit' Turner gen_exception(EXCP_SMC); 97945285864985be9077e58e42235af6582dee72e841David 'Digit' Turner break; 97958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 97968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (dc->condjmp) { 97978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_set_label(dc->condlabel); 97988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_set_condexec(dc); 97998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_goto_tb(dc, 1, dc->pc); 98008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project dc->condjmp = 0; 98018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 98028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 98038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 98048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdone_generating: 98058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_icount_end(tb, num_insns); 98068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *gen_opc_ptr = INDEX_op_end; 98078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 98088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef DEBUG_DISAS 98095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) { 98105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_log("----------------\n"); 98115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_log("IN: %s\n", lookup_symbol(pc_start)); 98125285864985be9077e58e42235af6582dee72e841David 'Digit' Turner log_target_disas(pc_start, dc->pc - pc_start, dc->thumb); 98135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_log("\n"); 98148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 98158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif 98168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (search_pc) { 98178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project j = gen_opc_ptr - gen_opc_buf; 98188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project lj++; 98198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project while (lj <= j) 98208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_opc_instr_start[lj++] = 0; 98218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 9822288208c386810fef725aa448a9f46bd2772bec8cDavid 'Digit' Turner ANDROID_END_CODEGEN(); 98238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tb->size = dc->pc - pc_start; 98248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project tb->icount = num_insns; 98258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 98268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 98278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 98288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid gen_intermediate_code(CPUState *env, TranslationBlock *tb) 98298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 98308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_intermediate_code_internal(env, tb, 0); 98318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 98328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 98338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid gen_intermediate_code_pc(CPUState *env, TranslationBlock *tb) 98348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 98358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gen_intermediate_code_internal(env, tb, 1); 98368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 98378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 98388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic const char *cpu_mode_names[16] = { 98398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project "usr", "fiq", "irq", "svc", "???", "???", "???", "abt", 98408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project "???", "???", "???", "und", "???", "???", "???", "sys" 98418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}; 98428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 98435285864985be9077e58e42235af6582dee72e841David 'Digit' Turnervoid cpu_dump_state(CPUState *env, FILE *f, fprintf_function cpu_fprintf, 98448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int flags) 98458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 98468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int i; 98478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if 0 98488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project union { 98498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project uint32_t i; 98508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project float s; 98518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } s0, s1; 98528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project CPU_DoubleU d; 98538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* ??? This assumes float64 and double have the same layout. 98548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project Oh well, it's only debug dumps. */ 98558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project union { 98568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project float64 f64; 98578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project double d; 98588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } d0; 98598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif 98608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project uint32_t psr; 98618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 98628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project for(i=0;i<16;i++) { 98638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project cpu_fprintf(f, "R%02d=%08x", i, env->regs[i]); 98648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if ((i % 4) == 3) 98658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project cpu_fprintf(f, "\n"); 98668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 98678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project cpu_fprintf(f, " "); 98688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 98698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project psr = cpsr_read(env); 98708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project cpu_fprintf(f, "PSR=%08x %c%c%c%c %c %s%d\n", 98718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project psr, 98728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project psr & (1 << 31) ? 'N' : '-', 98738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project psr & (1 << 30) ? 'Z' : '-', 98748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project psr & (1 << 29) ? 'C' : '-', 98758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project psr & (1 << 28) ? 'V' : '-', 98768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project psr & CPSR_T ? 'T' : 'A', 98778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project cpu_mode_names[psr & 0xf], (psr & 0x10) ? 32 : 26); 98788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 98798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if 0 98808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project for (i = 0; i < 16; i++) { 98818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project d.d = env->vfp.regs[i]; 98828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project s0.i = d.l.lower; 98838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project s1.i = d.l.upper; 98848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project d0.f64 = d.d; 98858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project cpu_fprintf(f, "s%02d=%08x(%8g) s%02d=%08x(%8g) d%02d=%08x%08x(%8g)\n", 98868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project i * 2, (int)s0.i, s0.s, 98878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project i * 2 + 1, (int)s1.i, s1.s, 98888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project i, (int)(uint32_t)d.l.upper, (int)(uint32_t)d.l.lower, 98898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project d0.d); 98908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 98918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project cpu_fprintf(f, "FPSCR: %08x\n", (int)env->vfp.xregs[ARM_VFP_FPSCR]); 98928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif 98938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 98948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 9895d3d4468189618e89f74d8f51b8470f277e000938David 'Digit' Turnervoid restore_state_to_opc(CPUState *env, TranslationBlock *tb, int pc_pos) 98968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 98978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project env->regs[15] = gen_opc_pc[pc_pos]; 98985285864985be9077e58e42235af6582dee72e841David 'Digit' Turner env->condexec_bits = gen_opc_condexec_bits[pc_pos]; 98998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 9900