18b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*
28b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *  ARM translation
38b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *
48b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *  Copyright (c) 2003 Fabrice Bellard
58b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *  Copyright (c) 2005-2007 CodeSourcery
68b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *  Copyright (c) 2007 OpenedHand, Ltd.
78b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *
88b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * This library is free software; you can redistribute it and/or
98b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * modify it under the terms of the GNU Lesser General Public
108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * License as published by the Free Software Foundation; either
118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * version 2 of the License, or (at your option) any later version.
128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *
138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * This library is distributed in the hope that it will be useful,
148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * but WITHOUT ANY WARRANTY; without even the implied warranty of
158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Lesser General Public License for more details.
178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *
188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * You should have received a copy of the GNU Lesser General Public
19a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner * License along with this library; if not, see <http://www.gnu.org/licenses/>.
208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */
218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include <stdarg.h>
228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include <stdlib.h>
238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include <stdio.h>
248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include <string.h>
258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include <inttypes.h>
268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "cpu.h"
28852088c7e08182c2de563872d558309815cbfa0dDavid 'Digit' Turner#include "exec/exec-all.h"
29cc33b2d8035092608c7cba4154e9c44452727e1bDavid 'Digit' Turner#include "disas/disas.h"
308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "tcg-op.h"
31e1e03df288d5a44bfbffbd86588395c7cbbc27dfDavid 'Digit' Turner#include "qemu/log.h"
328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
335285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#include "helper.h"
348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define GEN_HELPER 1
355285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#include "helper.h"
368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
375285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define ENABLE_ARCH_4T    arm_feature(env, ARM_FEATURE_V4T)
385285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define ENABLE_ARCH_5     arm_feature(env, ARM_FEATURE_V5)
395285864985be9077e58e42235af6582dee72e841David 'Digit' Turner/* currently all emulated v5 cores are also v5TE, so don't bother */
405285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define ENABLE_ARCH_5TE   arm_feature(env, ARM_FEATURE_V5)
418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define ENABLE_ARCH_5J    0
428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define ENABLE_ARCH_6     arm_feature(env, ARM_FEATURE_V6)
438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define ENABLE_ARCH_6K   arm_feature(env, ARM_FEATURE_V6K)
448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define ENABLE_ARCH_6T2   arm_feature(env, ARM_FEATURE_THUMB2)
458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define ENABLE_ARCH_7     arm_feature(env, ARM_FEATURE_V7)
468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#define ARCH(x) do { if (!ENABLE_ARCH_##x) goto illegal_op; } while(0)
488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* internal defines */
508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projecttypedef struct DisasContext {
518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    target_ulong pc;
528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int is_jmp;
538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* Nonzero if this instruction has been conditionally skipped.  */
548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int condjmp;
558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* The label that will be jumped to when the instruction is skipped.  */
568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int condlabel;
578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* Thumb-2 condtional execution bits.  */
588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int condexec_mask;
59a1204591a52bf668ee72c86f98f53189621572a2Vladimir Chtchetkine    int condexec_cond;
608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    struct TranslationBlock *tb;
618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int singlestep_enabled;
628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int thumb;
638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if !defined(CONFIG_USER_ONLY)
648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int user;
658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
665285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    int vfp_enabled;
675285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    int vec_len;
685285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    int vec_stride;
698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} DisasContext;
708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7186b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turnerstatic uint32_t gen_opc_condexec_bits[OPC_BUF_SIZE];
72288208c386810fef725aa448a9f46bd2772bec8cDavid 'Digit' Turner
738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if defined(CONFIG_USER_ONLY)
748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define IS_USER(s) 1
758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else
768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define IS_USER(s) (s->user)
778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* These instructions trap after executing, so defer them until after the
808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   conditional executions state has been updated.  */
818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define DISAS_WFI 4
828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define DISAS_SWI 5
835285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define DISAS_SMC 6
848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic TCGv_ptr cpu_env;
868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* We reuse the same 64-bit temporaries for efficiency.  */
875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic TCGv_i64 cpu_V0, cpu_V1, cpu_M0;
885285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic TCGv_i32 cpu_R[16];
895285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic TCGv_i32 cpu_exclusive_addr;
905285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic TCGv_i32 cpu_exclusive_val;
915285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic TCGv_i32 cpu_exclusive_high;
925285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#ifdef CONFIG_USER_ONLY
935285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic TCGv_i32 cpu_exclusive_test;
945285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic TCGv_i32 cpu_exclusive_info;
955285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#endif
968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* FIXME:  These should be removed.  */
985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic TCGv cpu_F0s, cpu_F1s;
995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic TCGv_i64 cpu_F0d, cpu_F1d;
1008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
101852088c7e08182c2de563872d558309815cbfa0dDavid 'Digit' Turner#include "exec/gen-icount.h"
1028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1035285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic const char *regnames[] =
1045285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    { "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
1055285864985be9077e58e42235af6582dee72e841David 'Digit' Turner      "r8", "r9", "r10", "r11", "r12", "r13", "r14", "pc" };
1065285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
1078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* initialize TCG globals.  */
1088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid arm_translate_init(void)
1098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1105285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    int i;
1115285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
1125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
1135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
1145285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    for (i = 0; i < 16; i++) {
1155285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        cpu_R[i] = tcg_global_mem_new_i32(TCG_AREG0,
116e2678e116c8cdb0f36b247a5bd9cfacc849362fcDavid 'Digit' Turner                                          offsetof(CPUARMState, regs[i]),
1175285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                                          regnames[i]);
1185285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    }
1195285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    cpu_exclusive_addr = tcg_global_mem_new_i32(TCG_AREG0,
120e2678e116c8cdb0f36b247a5bd9cfacc849362fcDavid 'Digit' Turner        offsetof(CPUARMState, exclusive_addr), "exclusive_addr");
1215285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    cpu_exclusive_val = tcg_global_mem_new_i32(TCG_AREG0,
122e2678e116c8cdb0f36b247a5bd9cfacc849362fcDavid 'Digit' Turner        offsetof(CPUARMState, exclusive_val), "exclusive_val");
1235285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    cpu_exclusive_high = tcg_global_mem_new_i32(TCG_AREG0,
124e2678e116c8cdb0f36b247a5bd9cfacc849362fcDavid 'Digit' Turner        offsetof(CPUARMState, exclusive_high), "exclusive_high");
1255285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#ifdef CONFIG_USER_ONLY
1265285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    cpu_exclusive_test = tcg_global_mem_new_i32(TCG_AREG0,
127e2678e116c8cdb0f36b247a5bd9cfacc849362fcDavid 'Digit' Turner        offsetof(CPUARMState, exclusive_test), "exclusive_test");
1285285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    cpu_exclusive_info = tcg_global_mem_new_i32(TCG_AREG0,
129e2678e116c8cdb0f36b247a5bd9cfacc849362fcDavid 'Digit' Turner        offsetof(CPUARMState, exclusive_info), "exclusive_info");
1305285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#endif
1318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
1328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline TCGv load_cpu_offset(int offset)
1348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1355285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    TCGv tmp = tcg_temp_new_i32();
1368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_gen_ld_i32(tmp, cpu_env, offset);
1378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return tmp;
1388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
1398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
140e2678e116c8cdb0f36b247a5bd9cfacc849362fcDavid 'Digit' Turner#define load_cpu_field(name) load_cpu_offset(offsetof(CPUARMState, name))
1418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline void store_cpu_offset(TCGv var, int offset)
1438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_gen_st_i32(var, cpu_env, offset);
1455285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_temp_free_i32(var);
1468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
1478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define store_cpu_field(var, name) \
149e2678e116c8cdb0f36b247a5bd9cfacc849362fcDavid 'Digit' Turner    store_cpu_offset(var, offsetof(CPUARMState, name))
1508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Set a variable to the value of a CPU register.  */
1528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void load_reg_var(DisasContext *s, TCGv var, int reg)
1538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (reg == 15) {
1558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        uint32_t addr;
1568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* normaly, since we updated PC, we need only to add one insn */
1578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (s->thumb)
1588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            addr = (long)s->pc + 2;
1598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        else
1608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            addr = (long)s->pc + 4;
1618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tcg_gen_movi_i32(var, addr);
1628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } else {
1635285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tcg_gen_mov_i32(var, cpu_R[reg]);
1648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
1658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
1668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Create a new temporary and set it to the value of a CPU register.  */
1688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline TCGv load_reg(DisasContext *s, int reg)
1698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1705285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    TCGv tmp = tcg_temp_new_i32();
1718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    load_reg_var(s, tmp, reg);
1728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return tmp;
1738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
1748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Set a CPU register.  The source must be a temporary and will be
1768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   marked as dead.  */
1778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void store_reg(DisasContext *s, int reg, TCGv var)
1788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (reg == 15) {
1808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tcg_gen_andi_i32(var, var, ~1);
1818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        s->is_jmp = DISAS_JUMP;
1828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
1835285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_gen_mov_i32(cpu_R[reg], var);
1845285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_temp_free_i32(var);
1858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
1868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Value extensions.  */
1888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define gen_uxtb(var) tcg_gen_ext8u_i32(var, var)
1898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define gen_uxth(var) tcg_gen_ext16u_i32(var, var)
1908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define gen_sxtb(var) tcg_gen_ext8s_i32(var, var)
1918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define gen_sxth(var) tcg_gen_ext16s_i32(var, var)
1928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define gen_sxtb16(var) gen_helper_sxtb16(var, var)
1948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define gen_uxtb16(var) gen_helper_uxtb16(var, var)
1958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1975285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic inline void gen_set_cpsr(TCGv var, uint32_t mask)
1985285864985be9077e58e42235af6582dee72e841David 'Digit' Turner{
1995285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    TCGv tmp_mask = tcg_const_i32(mask);
2000b4c9e8457959b01cd26f60ef214e9b5b7a297d4David 'Digit' Turner    gen_helper_cpsr_write(cpu_env, var, tmp_mask);
2015285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_temp_free_i32(tmp_mask);
2025285864985be9077e58e42235af6582dee72e841David 'Digit' Turner}
2038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Set NZCV flags from the high 4 bits of var.  */
2048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define gen_set_nzcv(var) gen_set_cpsr(var, CPSR_NZCV)
2058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void gen_exception(int excp)
2078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
2085285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    TCGv tmp = tcg_temp_new_i32();
2098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_gen_movi_i32(tmp, excp);
2100b4c9e8457959b01cd26f60ef214e9b5b7a297d4David 'Digit' Turner    gen_helper_exception(cpu_env, tmp);
2115285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_temp_free_i32(tmp);
2128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
2138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void gen_smul_dual(TCGv a, TCGv b)
2158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
2165285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    TCGv tmp1 = tcg_temp_new_i32();
2175285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    TCGv tmp2 = tcg_temp_new_i32();
2188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_gen_ext16s_i32(tmp1, a);
2198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_gen_ext16s_i32(tmp2, b);
2208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_gen_mul_i32(tmp1, tmp1, tmp2);
2215285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_temp_free_i32(tmp2);
2228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_gen_sari_i32(a, a, 16);
2238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_gen_sari_i32(b, b, 16);
2248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_gen_mul_i32(b, b, a);
2258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_gen_mov_i32(a, tmp1);
2265285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_temp_free_i32(tmp1);
2278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
2288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Byteswap each halfword.  */
2308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void gen_rev16(TCGv var)
2318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
2325285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    TCGv tmp = tcg_temp_new_i32();
2338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_gen_shri_i32(tmp, var, 8);
2348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_gen_andi_i32(tmp, tmp, 0x00ff00ff);
2358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_gen_shli_i32(var, var, 8);
2368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_gen_andi_i32(var, var, 0xff00ff00);
2378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_gen_or_i32(var, var, tmp);
2385285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_temp_free_i32(tmp);
2398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
2408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Byteswap low halfword and sign extend.  */
2428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void gen_revsh(TCGv var)
2438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
2445285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_gen_ext16u_i32(var, var);
2455285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_gen_bswap16_i32(var, var);
2465285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_gen_ext16s_i32(var, var);
2478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
2488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Unsigned bitfield extract.  */
2508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void gen_ubfx(TCGv var, int shift, uint32_t mask)
2518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
2528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (shift)
2538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tcg_gen_shri_i32(var, var, shift);
2548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_gen_andi_i32(var, var, mask);
2558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
2568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Signed bitfield extract.  */
2588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void gen_sbfx(TCGv var, int shift, int width)
2598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
2608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    uint32_t signbit;
2618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (shift)
2638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tcg_gen_sari_i32(var, var, shift);
2648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (shift + width < 32) {
2658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        signbit = 1u << (width - 1);
2668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tcg_gen_andi_i32(var, var, (1u << width) - 1);
2678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tcg_gen_xori_i32(var, var, signbit);
2688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tcg_gen_subi_i32(var, var, signbit);
2698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
2708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
2718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Bitfield insertion.  Insert val into base.  Clobbers base and val.  */
2738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void gen_bfi(TCGv dest, TCGv base, TCGv val, int shift, uint32_t mask)
2748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
2758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_gen_andi_i32(val, val, mask);
2768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_gen_shli_i32(val, val, shift);
2778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_gen_andi_i32(base, base, ~(mask << shift));
2788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_gen_or_i32(dest, base, val);
2798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
2808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2815285864985be9077e58e42235af6582dee72e841David 'Digit' Turner/* Return (b << 32) + a. Mark inputs as dead */
2825285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic TCGv_i64 gen_addq_msw(TCGv_i64 a, TCGv b)
2835285864985be9077e58e42235af6582dee72e841David 'Digit' Turner{
2845285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    TCGv_i64 tmp64 = tcg_temp_new_i64();
2855285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
2865285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_gen_extu_i32_i64(tmp64, b);
2875285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_temp_free_i32(b);
2885285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_gen_shli_i64(tmp64, tmp64, 32);
2895285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_gen_add_i64(a, tmp64, a);
2905285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
2915285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_temp_free_i64(tmp64);
2925285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    return a;
2935285864985be9077e58e42235af6582dee72e841David 'Digit' Turner}
2945285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
2955285864985be9077e58e42235af6582dee72e841David 'Digit' Turner/* Return (b << 32) - a. Mark inputs as dead. */
2965285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic TCGv_i64 gen_subq_msw(TCGv_i64 a, TCGv b)
2978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
2985285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    TCGv_i64 tmp64 = tcg_temp_new_i64();
2995285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
3005285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_gen_extu_i32_i64(tmp64, b);
3015285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_temp_free_i32(b);
3025285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_gen_shli_i64(tmp64, tmp64, 32);
3035285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_gen_sub_i64(a, tmp64, a);
3045285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
3055285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_temp_free_i64(tmp64);
3065285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    return a;
3078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
3088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* FIXME: Most targets have native widening multiplication.
3108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   It would be good to use that instead of a full wide multiply.  */
3118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* 32x32->64 multiply.  Marks inputs as dead.  */
3125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic TCGv_i64 gen_mulu_i64_i32(TCGv a, TCGv b)
3138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
3145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    TCGv_i64 tmp1 = tcg_temp_new_i64();
3155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    TCGv_i64 tmp2 = tcg_temp_new_i64();
3168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_gen_extu_i32_i64(tmp1, a);
3185285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_temp_free_i32(a);
3198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_gen_extu_i32_i64(tmp2, b);
3205285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_temp_free_i32(b);
3218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_gen_mul_i64(tmp1, tmp1, tmp2);
3225285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_temp_free_i64(tmp2);
3238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return tmp1;
3248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
3258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic TCGv_i64 gen_muls_i64_i32(TCGv a, TCGv b)
3278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
3285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    TCGv_i64 tmp1 = tcg_temp_new_i64();
3295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    TCGv_i64 tmp2 = tcg_temp_new_i64();
3308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_gen_ext_i32_i64(tmp1, a);
3325285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_temp_free_i32(a);
3338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_gen_ext_i32_i64(tmp2, b);
3345285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_temp_free_i32(b);
3358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_gen_mul_i64(tmp1, tmp1, tmp2);
3365285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_temp_free_i64(tmp2);
3378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return tmp1;
3388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
3398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Swap low and high halfwords.  */
3418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void gen_swap_half(TCGv var)
3428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
3435285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    TCGv tmp = tcg_temp_new_i32();
3448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_gen_shri_i32(tmp, var, 16);
3458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_gen_shli_i32(var, var, 16);
3468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_gen_or_i32(var, var, tmp);
3475285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_temp_free_i32(tmp);
3488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
3498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Dual 16-bit add.  Result placed in t0 and t1 is marked as dead.
3518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tmp = (t0 ^ t1) & 0x8000;
3528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    t0 &= ~0x8000;
3538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    t1 &= ~0x8000;
3548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    t0 = (t0 + t1) ^ tmp;
3558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */
3568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void gen_add16(TCGv t0, TCGv t1)
3588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
3595285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    TCGv tmp = tcg_temp_new_i32();
3608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_gen_xor_i32(tmp, t0, t1);
3618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_gen_andi_i32(tmp, tmp, 0x8000);
3628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_gen_andi_i32(t0, t0, ~0x8000);
3638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_gen_andi_i32(t1, t1, ~0x8000);
3648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_gen_add_i32(t0, t0, t1);
3658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_gen_xor_i32(t0, t0, tmp);
3665285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_temp_free_i32(tmp);
3675285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_temp_free_i32(t1);
3688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
3698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
370e2678e116c8cdb0f36b247a5bd9cfacc849362fcDavid 'Digit' Turner#define gen_set_CF(var) tcg_gen_st_i32(var, cpu_env, offsetof(CPUARMState, CF))
3718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Set CF to the top bit of var.  */
3738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void gen_set_CF_bit31(TCGv var)
3748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
3755285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    TCGv tmp = tcg_temp_new_i32();
3768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_gen_shri_i32(tmp, var, 31);
3775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    gen_set_CF(tmp);
3785285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_temp_free_i32(tmp);
3798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
3808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Set N and Z flags from var.  */
3828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline void gen_logic_CC(TCGv var)
3838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
384e2678e116c8cdb0f36b247a5bd9cfacc849362fcDavid 'Digit' Turner    tcg_gen_st_i32(var, cpu_env, offsetof(CPUARMState, NF));
385e2678e116c8cdb0f36b247a5bd9cfacc849362fcDavid 'Digit' Turner    tcg_gen_st_i32(var, cpu_env, offsetof(CPUARMState, ZF));
3868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
3878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* T0 += T1 + CF.  */
3895285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic void gen_adc(TCGv t0, TCGv t1)
3908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
3918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    TCGv tmp;
3925285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_gen_add_i32(t0, t0, t1);
3938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tmp = load_cpu_field(CF);
3945285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_gen_add_i32(t0, t0, tmp);
3955285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_temp_free_i32(tmp);
3968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
3978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner/* dest = T0 + T1 + CF. */
3995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void gen_add_carry(TCGv dest, TCGv t0, TCGv t1)
4005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
4015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    TCGv tmp;
4025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    tcg_gen_add_i32(dest, t0, t1);
4035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    tmp = load_cpu_field(CF);
4045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    tcg_gen_add_i32(dest, dest, tmp);
4055285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_temp_free_i32(tmp);
4065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
4075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
4088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* dest = T0 - T1 + CF - 1.  */
4098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void gen_sub_carry(TCGv dest, TCGv t0, TCGv t1)
4108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
4118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    TCGv tmp;
4128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_gen_sub_i32(dest, t0, t1);
4138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tmp = load_cpu_field(CF);
4148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_gen_add_i32(dest, dest, tmp);
4158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_gen_subi_i32(dest, dest, 1);
4165285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_temp_free_i32(tmp);
4178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
4188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* FIXME:  Implement this natively.  */
4208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define tcg_gen_abs_i32(t0, t1) gen_helper_abs(t0, t1)
4218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void shifter_out_im(TCGv var, int shift)
4238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
4245285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    TCGv tmp = tcg_temp_new_i32();
4258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (shift == 0) {
4268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tcg_gen_andi_i32(tmp, var, 1);
4278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } else {
4288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tcg_gen_shri_i32(tmp, var, shift);
4295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (shift != 31)
4308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tcg_gen_andi_i32(tmp, tmp, 1);
4318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
4328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    gen_set_CF(tmp);
4335285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_temp_free_i32(tmp);
4348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
4358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Shift by immediate.  Includes special handling for shift == 0.  */
4378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline void gen_arm_shift_im(TCGv var, int shiftop, int shift, int flags)
4388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
4398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    switch (shiftop) {
4408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0: /* LSL */
4418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (shift != 0) {
4428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (flags)
4438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                shifter_out_im(var, 32 - shift);
4448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tcg_gen_shli_i32(var, var, shift);
4458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
4468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
4478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 1: /* LSR */
4488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (shift == 0) {
4498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (flags) {
4508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                tcg_gen_shri_i32(var, var, 31);
4518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                gen_set_CF(var);
4528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
4538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tcg_gen_movi_i32(var, 0);
4548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        } else {
4558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (flags)
4568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                shifter_out_im(var, shift - 1);
4578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tcg_gen_shri_i32(var, var, shift);
4588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
4598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
4608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 2: /* ASR */
4618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (shift == 0)
4628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            shift = 32;
4638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (flags)
4648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            shifter_out_im(var, shift - 1);
4658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (shift == 32)
4668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project          shift = 31;
4678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tcg_gen_sari_i32(var, var, shift);
4688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
4698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 3: /* ROR/RRX */
4708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (shift != 0) {
4718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (flags)
4728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                shifter_out_im(var, shift - 1);
4735285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tcg_gen_rotri_i32(var, var, shift); break;
4748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        } else {
4758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            TCGv tmp = load_cpu_field(CF);
4768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (flags)
4778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                shifter_out_im(var, 0);
4788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tcg_gen_shri_i32(var, var, 1);
4798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tcg_gen_shli_i32(tmp, tmp, 31);
4808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tcg_gen_or_i32(var, var, tmp);
4815285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tcg_temp_free_i32(tmp);
4828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
4838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
4848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project};
4858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline void gen_arm_shift_reg(TCGv var, int shiftop,
4878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                     TCGv shift, int flags)
4888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
4898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (flags) {
4908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        switch (shiftop) {
4910b4c9e8457959b01cd26f60ef214e9b5b7a297d4David 'Digit' Turner        case 0: gen_helper_shl_cc(var, cpu_env, var, shift); break;
4920b4c9e8457959b01cd26f60ef214e9b5b7a297d4David 'Digit' Turner        case 1: gen_helper_shr_cc(var, cpu_env, var, shift); break;
4930b4c9e8457959b01cd26f60ef214e9b5b7a297d4David 'Digit' Turner        case 2: gen_helper_sar_cc(var, cpu_env, var, shift); break;
4940b4c9e8457959b01cd26f60ef214e9b5b7a297d4David 'Digit' Turner        case 3: gen_helper_ror_cc(var, cpu_env, var, shift); break;
4958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
4968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } else {
4978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        switch (shiftop) {
4988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0: gen_helper_shl(var, var, shift); break;
4998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 1: gen_helper_shr(var, var, shift); break;
5008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 2: gen_helper_sar(var, var, shift); break;
5015285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        case 3: tcg_gen_andi_i32(shift, shift, 0x1f);
5025285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_gen_rotr_i32(var, var, shift); break;
5038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
5048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
5055285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_temp_free_i32(shift);
5068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
5078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define PAS_OP(pfx) \
5098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    switch (op2) {  \
5108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0: gen_pas_helper(glue(pfx,add16)); break; \
5118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 1: gen_pas_helper(glue(pfx,addsubx)); break; \
5128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 2: gen_pas_helper(glue(pfx,subaddx)); break; \
5138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 3: gen_pas_helper(glue(pfx,sub16)); break; \
5148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 4: gen_pas_helper(glue(pfx,add8)); break; \
5158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 7: gen_pas_helper(glue(pfx,sub8)); break; \
5168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
5178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void gen_arm_parallel_addsub(int op1, int op2, TCGv a, TCGv b)
5188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
5195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    TCGv_ptr tmp;
5208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    switch (op1) {
5228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b, tmp)
5238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 1:
5245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        tmp = tcg_temp_new_ptr();
525e2678e116c8cdb0f36b247a5bd9cfacc849362fcDavid 'Digit' Turner        tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUARMState, GE));
5268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        PAS_OP(s)
5275285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tcg_temp_free_ptr(tmp);
5288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
5298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 5:
5305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        tmp = tcg_temp_new_ptr();
531e2678e116c8cdb0f36b247a5bd9cfacc849362fcDavid 'Digit' Turner        tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUARMState, GE));
5328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        PAS_OP(u)
5335285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tcg_temp_free_ptr(tmp);
5348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
5358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#undef gen_pas_helper
5368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b)
5378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 2:
5388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        PAS_OP(q);
5398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
5408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 3:
5418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        PAS_OP(sh);
5428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
5438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 6:
5448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        PAS_OP(uq);
5458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
5468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 7:
5478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        PAS_OP(uh);
5488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
5498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#undef gen_pas_helper
5508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
5518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
5528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#undef PAS_OP
5538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* For unknown reasons Arm and Thumb-2 use arbitrarily different encodings.  */
5558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define PAS_OP(pfx) \
5565285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    switch (op1) {  \
5578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0: gen_pas_helper(glue(pfx,add8)); break; \
5588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 1: gen_pas_helper(glue(pfx,add16)); break; \
5598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 2: gen_pas_helper(glue(pfx,addsubx)); break; \
5608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 4: gen_pas_helper(glue(pfx,sub8)); break; \
5618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 5: gen_pas_helper(glue(pfx,sub16)); break; \
5628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 6: gen_pas_helper(glue(pfx,subaddx)); break; \
5638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
5648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void gen_thumb2_parallel_addsub(int op1, int op2, TCGv a, TCGv b)
5658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
5665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    TCGv_ptr tmp;
5678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5685285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    switch (op2) {
5698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b, tmp)
5708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0:
5715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        tmp = tcg_temp_new_ptr();
572e2678e116c8cdb0f36b247a5bd9cfacc849362fcDavid 'Digit' Turner        tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUARMState, GE));
5738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        PAS_OP(s)
5745285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tcg_temp_free_ptr(tmp);
5758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
5768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 4:
5775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        tmp = tcg_temp_new_ptr();
578e2678e116c8cdb0f36b247a5bd9cfacc849362fcDavid 'Digit' Turner        tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUARMState, GE));
5798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        PAS_OP(u)
5805285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tcg_temp_free_ptr(tmp);
5818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
5828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#undef gen_pas_helper
5838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b)
5848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 1:
5858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        PAS_OP(q);
5868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
5878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 2:
5888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        PAS_OP(sh);
5898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
5908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 5:
5918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        PAS_OP(uq);
5928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
5938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 6:
5948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        PAS_OP(uh);
5958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
5968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#undef gen_pas_helper
5978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
5988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
5998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#undef PAS_OP
6008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void gen_test_cc(int cc, int label)
6028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
6038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    TCGv tmp;
6048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    TCGv tmp2;
6058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int inv;
6068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    switch (cc) {
6088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0: /* eq: Z */
6098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tmp = load_cpu_field(ZF);
6108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, label);
6118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
6128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 1: /* ne: !Z */
6138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tmp = load_cpu_field(ZF);
6148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, label);
6158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
6168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 2: /* cs: C */
6178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tmp = load_cpu_field(CF);
6188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, label);
6198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
6208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 3: /* cc: !C */
6218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tmp = load_cpu_field(CF);
6228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, label);
6238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
6248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 4: /* mi: N */
6258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tmp = load_cpu_field(NF);
6268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tcg_gen_brcondi_i32(TCG_COND_LT, tmp, 0, label);
6278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
6288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 5: /* pl: !N */
6298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tmp = load_cpu_field(NF);
6308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tcg_gen_brcondi_i32(TCG_COND_GE, tmp, 0, label);
6318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
6328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 6: /* vs: V */
6338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tmp = load_cpu_field(VF);
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 7: /* vc: !V */
6378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tmp = load_cpu_field(VF);
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 8: /* hi: C && !Z */
6418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        inv = gen_new_label();
6428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tmp = load_cpu_field(CF);
6438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, inv);
6445285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tcg_temp_free_i32(tmp);
6458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tmp = load_cpu_field(ZF);
6468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, label);
6478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_set_label(inv);
6488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
6498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 9: /* ls: !C || Z */
6508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tmp = load_cpu_field(CF);
6518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, label);
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_EQ, tmp, 0, label);
6558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
6568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 10: /* ge: N == V -> N ^ V == 0 */
6578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tmp = load_cpu_field(VF);
6588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tmp2 = load_cpu_field(NF);
6598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tcg_gen_xor_i32(tmp, tmp, tmp2);
6605285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tcg_temp_free_i32(tmp2);
6618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tcg_gen_brcondi_i32(TCG_COND_GE, tmp, 0, label);
6628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
6638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 11: /* lt: N != V -> N ^ V != 0 */
6648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tmp = load_cpu_field(VF);
6658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tmp2 = load_cpu_field(NF);
6668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tcg_gen_xor_i32(tmp, tmp, tmp2);
6675285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tcg_temp_free_i32(tmp2);
6688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tcg_gen_brcondi_i32(TCG_COND_LT, tmp, 0, label);
6698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
6708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 12: /* gt: !Z && N == V */
6718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        inv = gen_new_label();
6728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tmp = load_cpu_field(ZF);
6738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, inv);
6745285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tcg_temp_free_i32(tmp);
6758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tmp = load_cpu_field(VF);
6768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tmp2 = load_cpu_field(NF);
6778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tcg_gen_xor_i32(tmp, tmp, tmp2);
6785285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tcg_temp_free_i32(tmp2);
6798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tcg_gen_brcondi_i32(TCG_COND_GE, tmp, 0, label);
6808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_set_label(inv);
6818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
6828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 13: /* le: Z || N != V */
6838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tmp = load_cpu_field(ZF);
6848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, label);
6855285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tcg_temp_free_i32(tmp);
6868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tmp = load_cpu_field(VF);
6878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tmp2 = load_cpu_field(NF);
6888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tcg_gen_xor_i32(tmp, tmp, tmp2);
6895285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tcg_temp_free_i32(tmp2);
6908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tcg_gen_brcondi_i32(TCG_COND_LT, tmp, 0, label);
6918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
6928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    default:
6938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        fprintf(stderr, "Bad condition code 0x%x\n", cc);
6948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        abort();
6958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
6965285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_temp_free_i32(tmp);
6978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
6988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic const uint8_t table_logic_cc[16] = {
7008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    1, /* and */
7018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    1, /* xor */
7028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    0, /* sub */
7038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    0, /* rsb */
7048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    0, /* add */
7058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    0, /* adc */
7068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    0, /* sbc */
7078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    0, /* rsc */
7088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    1, /* andl */
7098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    1, /* xorl */
7108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    0, /* cmp */
7118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    0, /* cmn */
7128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    1, /* orr */
7138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    1, /* mov */
7148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    1, /* bic */
7158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    1, /* mvn */
7168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project};
7178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Set PC and Thumb state from an immediate address.  */
7198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline void gen_bx_im(DisasContext *s, uint32_t addr)
7208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
7218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    TCGv tmp;
7228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    s->is_jmp = DISAS_UPDATE;
7248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (s->thumb != (addr & 1)) {
7255285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tmp = tcg_temp_new_i32();
7268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tcg_gen_movi_i32(tmp, addr & 1);
727e2678e116c8cdb0f36b247a5bd9cfacc849362fcDavid 'Digit' Turner        tcg_gen_st_i32(tmp, cpu_env, offsetof(CPUARMState, thumb));
7285285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tcg_temp_free_i32(tmp);
7298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
7305285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_gen_movi_i32(cpu_R[15], addr & ~1);
7318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
7328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Set PC and Thumb state from var.  var is marked as dead.  */
7348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline void gen_bx(DisasContext *s, TCGv var)
7358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
7368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    s->is_jmp = DISAS_UPDATE;
7375285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_gen_andi_i32(cpu_R[15], var, ~1);
7385285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_gen_andi_i32(var, var, 1);
7395285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    store_cpu_field(var, thumb);
7408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
7418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner/* Variant of store_reg which uses branch&exchange logic when storing
7435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner   to r15 in ARM architecture v7 and above. The source must be a temporary
7445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner   and will be marked as dead. */
745e2678e116c8cdb0f36b247a5bd9cfacc849362fcDavid 'Digit' Turnerstatic inline void store_reg_bx(CPUARMState *env, DisasContext *s,
7465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                                int reg, TCGv var)
7475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
7485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (reg == 15 && ENABLE_ARCH_7) {
7495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        gen_bx(s, var);
7505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    } else {
7515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        store_reg(s, reg, var);
7525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
7535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
7545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
7555285864985be9077e58e42235af6582dee72e841David 'Digit' Turner/* Variant of store_reg which uses branch&exchange logic when storing
7565285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * to r15 in ARM architecture v5T and above. This is used for storing
7575285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * the results of a LDR/LDM/POP into r15, and corresponds to the cases
7585285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * in the ARM ARM which use the LoadWritePC() pseudocode function. */
759e2678e116c8cdb0f36b247a5bd9cfacc849362fcDavid 'Digit' Turnerstatic inline void store_reg_from_load(CPUARMState *env, DisasContext *s,
7605285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                                int reg, TCGv var)
7615285864985be9077e58e42235af6582dee72e841David 'Digit' Turner{
7625285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    if (reg == 15 && ENABLE_ARCH_5) {
7635285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        gen_bx(s, var);
7645285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    } else {
7655285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        store_reg(s, reg, var);
7665285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    }
7675285864985be9077e58e42235af6582dee72e841David 'Digit' Turner}
7685285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
769e2678e116c8cdb0f36b247a5bd9cfacc849362fcDavid 'Digit' Turnerstatic inline void gen_smc(CPUARMState *env, DisasContext *s)
7705285864985be9077e58e42235af6582dee72e841David 'Digit' Turner{
7715285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_gen_movi_i32(cpu_R[15], s->pc);
7725285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    s->is_jmp = DISAS_SMC;
7735285864985be9077e58e42235af6582dee72e841David 'Digit' Turner}
7745285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
7758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline TCGv gen_ld8s(TCGv addr, int index)
7768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
7775285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    TCGv tmp = tcg_temp_new_i32();
7788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_gen_qemu_ld8s(tmp, addr, index);
7798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return tmp;
7808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
7818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline TCGv gen_ld8u(TCGv addr, int index)
7828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
7835285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    TCGv tmp = tcg_temp_new_i32();
7848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_gen_qemu_ld8u(tmp, addr, index);
7858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return tmp;
7868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
7878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline TCGv gen_ld16s(TCGv addr, int index)
7888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
7895285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    TCGv tmp = tcg_temp_new_i32();
7908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_gen_qemu_ld16s(tmp, addr, index);
7918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return tmp;
7928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
7938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline TCGv gen_ld16u(TCGv addr, int index)
7948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
7955285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    TCGv tmp = tcg_temp_new_i32();
7968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_gen_qemu_ld16u(tmp, addr, index);
7978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return tmp;
7988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
7998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline TCGv gen_ld32(TCGv addr, int index)
8008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
8015285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    TCGv tmp = tcg_temp_new_i32();
8028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_gen_qemu_ld32u(tmp, addr, index);
8038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return tmp;
8048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
8055285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic inline TCGv_i64 gen_ld64(TCGv addr, int index)
8065285864985be9077e58e42235af6582dee72e841David 'Digit' Turner{
8075285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    TCGv_i64 tmp = tcg_temp_new_i64();
8085285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_gen_qemu_ld64(tmp, addr, index);
8095285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    return tmp;
8105285864985be9077e58e42235af6582dee72e841David 'Digit' Turner}
8118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline void gen_st8(TCGv val, TCGv addr, int index)
8128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
8138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_gen_qemu_st8(val, addr, index);
8145285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_temp_free_i32(val);
8158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
8168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline void gen_st16(TCGv val, TCGv addr, int index)
8178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
8188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_gen_qemu_st16(val, addr, index);
8195285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_temp_free_i32(val);
8208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
8218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline void gen_st32(TCGv val, TCGv addr, int index)
8228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
8238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_gen_qemu_st32(val, addr, index);
8245285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_temp_free_i32(val);
8258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
8265285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic inline void gen_st64(TCGv_i64 val, TCGv addr, int index)
8278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
8285285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_gen_qemu_st64(val, addr, index);
8295285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_temp_free_i64(val);
8308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
8318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline void gen_set_pc_im(uint32_t val)
8338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
8345285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_gen_movi_i32(cpu_R[15], val);
8358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
8368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Force a TB lookup after an instruction that changes the CPU state.  */
8388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline void gen_lookup_tb(DisasContext *s)
8398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
8405285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_gen_movi_i32(cpu_R[15], s->pc & ~1);
8418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    s->is_jmp = DISAS_UPDATE;
8428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
8438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline void gen_add_data_offset(DisasContext *s, unsigned int insn,
8458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                       TCGv var)
8468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
8478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int val, rm, shift, shiftop;
8488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    TCGv offset;
8498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!(insn & (1 << 25))) {
8518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* immediate */
8528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        val = insn & 0xfff;
8538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (!(insn & (1 << 23)))
8548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            val = -val;
8558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (val != 0)
8568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tcg_gen_addi_i32(var, var, val);
8578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } else {
8588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* shift/register */
8598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        rm = (insn) & 0xf;
8608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        shift = (insn >> 7) & 0x1f;
8618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        shiftop = (insn >> 5) & 3;
8628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        offset = load_reg(s, rm);
8638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_arm_shift_im(offset, shiftop, shift, 0);
8648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (!(insn & (1 << 23)))
8658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tcg_gen_sub_i32(var, var, offset);
8668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        else
8678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tcg_gen_add_i32(var, var, offset);
8685285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tcg_temp_free_i32(offset);
8698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
8708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
8718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline void gen_add_datah_offset(DisasContext *s, unsigned int insn,
8738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                        int extra, TCGv var)
8748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
8758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int val, rm;
8768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    TCGv offset;
8778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (insn & (1 << 22)) {
8798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* immediate */
8808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        val = (insn & 0xf) | ((insn >> 4) & 0xf0);
8818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (!(insn & (1 << 23)))
8828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            val = -val;
8838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        val += extra;
8848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (val != 0)
8858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tcg_gen_addi_i32(var, var, val);
8868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } else {
8878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* register */
8888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (extra)
8898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tcg_gen_addi_i32(var, var, extra);
8908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        rm = (insn) & 0xf;
8918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        offset = load_reg(s, rm);
8928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (!(insn & (1 << 23)))
8938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tcg_gen_sub_i32(var, var, offset);
8948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        else
8958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tcg_gen_add_i32(var, var, offset);
8965285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tcg_temp_free_i32(offset);
8978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
8988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
8998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
90016998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turnerstatic TCGv_ptr get_fpstatus_ptr(int neon)
90116998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner{
90216998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner    TCGv_ptr statusptr = tcg_temp_new_ptr();
90316998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner    int offset;
90416998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner    if (neon) {
90516998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner        offset = offsetof(CPUARMState, vfp.standard_fp_status);
90616998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner    } else {
90716998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner        offset = offsetof(CPUARMState, vfp.fp_status);
90816998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner    }
90916998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner    tcg_gen_addi_ptr(statusptr, cpu_env, offset);
91016998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner    return statusptr;
91116998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner}
91216998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner
9138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define VFP_OP2(name)                                                 \
9148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline void gen_vfp_##name(int dp)                             \
9158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{                                                                     \
91616998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner    TCGv_ptr fpst = get_fpstatus_ptr(0);                              \
91716998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner    if (dp) {                                                         \
91816998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner        gen_helper_vfp_##name##d(cpu_F0d, cpu_F0d, cpu_F1d, fpst);    \
91916998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner    } else {                                                          \
92016998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner        gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, cpu_F1s, fpst);    \
92116998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner    }                                                                 \
92216998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner    tcg_temp_free_ptr(fpst);                                          \
9238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
9248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectVFP_OP2(add)
9268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectVFP_OP2(sub)
9278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectVFP_OP2(mul)
9288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectVFP_OP2(div)
9298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#undef VFP_OP2
9318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9325285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic inline void gen_vfp_F1_mul(int dp)
9335285864985be9077e58e42235af6582dee72e841David 'Digit' Turner{
9345285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    /* Like gen_vfp_mul() but put result in F1 */
93516998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner    TCGv_ptr fpst = get_fpstatus_ptr(0);
9365285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    if (dp) {
93716998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner        gen_helper_vfp_muld(cpu_F1d, cpu_F0d, cpu_F1d, fpst);
9385285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    } else {
93916998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner        gen_helper_vfp_muls(cpu_F1s, cpu_F0s, cpu_F1s, fpst);
9405285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    }
9415285864985be9077e58e42235af6582dee72e841David 'Digit' Turner}
9425285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
9435285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic inline void gen_vfp_F1_neg(int dp)
9445285864985be9077e58e42235af6582dee72e841David 'Digit' Turner{
9455285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    /* Like gen_vfp_neg() but put result in F1 */
9465285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    if (dp) {
9475285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        gen_helper_vfp_negd(cpu_F1d, cpu_F0d);
9485285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    } else {
9495285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        gen_helper_vfp_negs(cpu_F1s, cpu_F0s);
9505285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    }
9515285864985be9077e58e42235af6582dee72e841David 'Digit' Turner}
9525285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
9538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline void gen_vfp_abs(int dp)
9548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
9558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (dp)
9568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_helper_vfp_absd(cpu_F0d, cpu_F0d);
9578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    else
9588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_helper_vfp_abss(cpu_F0s, cpu_F0s);
9598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
9608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline void gen_vfp_neg(int dp)
9628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
9638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (dp)
9648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_helper_vfp_negd(cpu_F0d, cpu_F0d);
9658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    else
9668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_helper_vfp_negs(cpu_F0s, cpu_F0s);
9678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
9688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline void gen_vfp_sqrt(int dp)
9708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
9718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (dp)
9728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_helper_vfp_sqrtd(cpu_F0d, cpu_F0d, cpu_env);
9738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    else
9748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_helper_vfp_sqrts(cpu_F0s, cpu_F0s, cpu_env);
9758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
9768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline void gen_vfp_cmp(int dp)
9788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
9798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (dp)
9808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_helper_vfp_cmpd(cpu_F0d, cpu_F1d, cpu_env);
9818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    else
9828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_helper_vfp_cmps(cpu_F0s, cpu_F1s, cpu_env);
9838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
9848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline void gen_vfp_cmpe(int dp)
9868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
9878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (dp)
9888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_helper_vfp_cmped(cpu_F0d, cpu_F1d, cpu_env);
9898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    else
9908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_helper_vfp_cmpes(cpu_F0s, cpu_F1s, cpu_env);
9918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
9928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline void gen_vfp_F1_ld0(int dp)
9948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
9958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (dp)
9968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tcg_gen_movi_i64(cpu_F1d, 0);
9978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    else
9988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tcg_gen_movi_i32(cpu_F1s, 0);
9998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
10008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10015285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define VFP_GEN_ITOF(name) \
10025285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic inline void gen_vfp_##name(int dp, int neon) \
10035285864985be9077e58e42235af6582dee72e841David 'Digit' Turner{ \
100416998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner    TCGv_ptr statusptr = get_fpstatus_ptr(neon); \
10055285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    if (dp) { \
10065285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        gen_helper_vfp_##name##d(cpu_F0d, cpu_F0s, statusptr); \
10075285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    } else { \
10085285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, statusptr); \
10095285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    } \
10105285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_temp_free_ptr(statusptr); \
10118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
10128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10135285864985be9077e58e42235af6582dee72e841David 'Digit' TurnerVFP_GEN_ITOF(uito)
10145285864985be9077e58e42235af6582dee72e841David 'Digit' TurnerVFP_GEN_ITOF(sito)
10155285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#undef VFP_GEN_ITOF
10168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10175285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define VFP_GEN_FTOI(name) \
10185285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic inline void gen_vfp_##name(int dp, int neon) \
10195285864985be9077e58e42235af6582dee72e841David 'Digit' Turner{ \
102016998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner    TCGv_ptr statusptr = get_fpstatus_ptr(neon); \
10215285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    if (dp) { \
10225285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        gen_helper_vfp_##name##d(cpu_F0s, cpu_F0d, statusptr); \
10235285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    } else { \
10245285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, statusptr); \
10255285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    } \
10265285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_temp_free_ptr(statusptr); \
10278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
10288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10295285864985be9077e58e42235af6582dee72e841David 'Digit' TurnerVFP_GEN_FTOI(toui)
10305285864985be9077e58e42235af6582dee72e841David 'Digit' TurnerVFP_GEN_FTOI(touiz)
10315285864985be9077e58e42235af6582dee72e841David 'Digit' TurnerVFP_GEN_FTOI(tosi)
10325285864985be9077e58e42235af6582dee72e841David 'Digit' TurnerVFP_GEN_FTOI(tosiz)
10335285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#undef VFP_GEN_FTOI
10348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define VFP_GEN_FIX(name) \
10365285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic inline void gen_vfp_##name(int dp, int shift, int neon) \
10378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ \
10385285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    TCGv tmp_shift = tcg_const_i32(shift); \
103916998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner    TCGv_ptr statusptr = get_fpstatus_ptr(neon); \
10405285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    if (dp) { \
10415285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        gen_helper_vfp_##name##d(cpu_F0d, cpu_F0d, tmp_shift, statusptr); \
10425285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    } else { \
10435285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, tmp_shift, statusptr); \
10445285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    } \
10455285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_temp_free_i32(tmp_shift); \
10465285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_temp_free_ptr(statusptr); \
10478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
10488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectVFP_GEN_FIX(tosh)
10498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectVFP_GEN_FIX(tosl)
10508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectVFP_GEN_FIX(touh)
10518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectVFP_GEN_FIX(toul)
10528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectVFP_GEN_FIX(shto)
10538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectVFP_GEN_FIX(slto)
10548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectVFP_GEN_FIX(uhto)
10558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectVFP_GEN_FIX(ulto)
10568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#undef VFP_GEN_FIX
10578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10585285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic inline void gen_vfp_ld(DisasContext *s, int dp, TCGv addr)
10598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
10608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (dp)
10615285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tcg_gen_qemu_ld64(cpu_F0d, addr, IS_USER(s));
10628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    else
10635285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tcg_gen_qemu_ld32u(cpu_F0s, addr, IS_USER(s));
10648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
10658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10665285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic inline void gen_vfp_st(DisasContext *s, int dp, TCGv addr)
10678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
10688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (dp)
10695285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tcg_gen_qemu_st64(cpu_F0d, addr, IS_USER(s));
10708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    else
10715285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tcg_gen_qemu_st32(cpu_F0s, addr, IS_USER(s));
10728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
10738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline long
10758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvfp_reg_offset (int dp, int reg)
10768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
10778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (dp)
10788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return offsetof(CPUARMState, vfp.regs[reg]);
10798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    else if (reg & 1) {
10808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return offsetof(CPUARMState, vfp.regs[reg >> 1])
10818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project          + offsetof(CPU_DoubleU, l.upper);
10828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } else {
10838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return offsetof(CPUARMState, vfp.regs[reg >> 1])
10848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project          + offsetof(CPU_DoubleU, l.lower);
10858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
10868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
10878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Return the offset of a 32-bit piece of a NEON register.
10898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   zero is the least significant end of the register.  */
10908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline long
10918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectneon_reg_offset (int reg, int n)
10928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
10938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int sreg;
10948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    sreg = reg * 2 + n;
10958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return vfp_reg_offset(0, sreg);
10968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
10978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic TCGv neon_load_reg(int reg, int pass)
10998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
11005285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    TCGv tmp = tcg_temp_new_i32();
11018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_gen_ld_i32(tmp, cpu_env, neon_reg_offset(reg, pass));
11028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return tmp;
11038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
11048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void neon_store_reg(int reg, int pass, TCGv var)
11068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
11078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_gen_st_i32(var, cpu_env, neon_reg_offset(reg, pass));
11085285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_temp_free_i32(var);
11098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
11108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic inline void neon_load_reg64(TCGv_i64 var, int reg)
11128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
11138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_gen_ld_i64(var, cpu_env, vfp_reg_offset(1, reg));
11148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
11158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic inline void neon_store_reg64(TCGv_i64 var, int reg)
11178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
11188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_gen_st_i64(var, cpu_env, vfp_reg_offset(1, reg));
11198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
11208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define tcg_gen_ld_f32 tcg_gen_ld_i32
11228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define tcg_gen_ld_f64 tcg_gen_ld_i64
11238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define tcg_gen_st_f32 tcg_gen_st_i32
11248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define tcg_gen_st_f64 tcg_gen_st_i64
11258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline void gen_mov_F0_vreg(int dp, int reg)
11278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
11288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (dp)
11298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tcg_gen_ld_f64(cpu_F0d, cpu_env, vfp_reg_offset(dp, reg));
11308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    else
11318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tcg_gen_ld_f32(cpu_F0s, cpu_env, vfp_reg_offset(dp, reg));
11328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
11338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline void gen_mov_F1_vreg(int dp, int reg)
11358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
11368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (dp)
11378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tcg_gen_ld_f64(cpu_F1d, cpu_env, vfp_reg_offset(dp, reg));
11388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    else
11398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tcg_gen_ld_f32(cpu_F1s, cpu_env, vfp_reg_offset(dp, reg));
11408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
11418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline void gen_mov_vreg_F0(int dp, int reg)
11438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
11448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (dp)
11458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tcg_gen_st_f64(cpu_F0d, cpu_env, vfp_reg_offset(dp, reg));
11468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    else
11478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tcg_gen_st_f32(cpu_F0s, cpu_env, vfp_reg_offset(dp, reg));
11488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
11498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define ARM_CP_RW_BIT	(1 << 20)
11518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic inline void iwmmxt_load_reg(TCGv_i64 var, int reg)
11538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1154e2678e116c8cdb0f36b247a5bd9cfacc849362fcDavid 'Digit' Turner    tcg_gen_ld_i64(var, cpu_env, offsetof(CPUARMState, iwmmxt.regs[reg]));
11558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
11568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic inline void iwmmxt_store_reg(TCGv_i64 var, int reg)
11588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1159e2678e116c8cdb0f36b247a5bd9cfacc849362fcDavid 'Digit' Turner    tcg_gen_st_i64(var, cpu_env, offsetof(CPUARMState, iwmmxt.regs[reg]));
11608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
11618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11625285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic inline TCGv iwmmxt_load_creg(int reg)
11638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
11645285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    TCGv var = tcg_temp_new_i32();
1165e2678e116c8cdb0f36b247a5bd9cfacc849362fcDavid 'Digit' Turner    tcg_gen_ld_i32(var, cpu_env, offsetof(CPUARMState, iwmmxt.cregs[reg]));
11665285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    return var;
11678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
11688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11695285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic inline void iwmmxt_store_creg(int reg, TCGv var)
11708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1171e2678e116c8cdb0f36b247a5bd9cfacc849362fcDavid 'Digit' Turner    tcg_gen_st_i32(var, cpu_env, offsetof(CPUARMState, iwmmxt.cregs[reg]));
11725285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_temp_free_i32(var);
11738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
11748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline void gen_op_iwmmxt_movq_wRn_M0(int rn)
11768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
11778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    iwmmxt_store_reg(cpu_M0, rn);
11788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
11798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline void gen_op_iwmmxt_movq_M0_wRn(int rn)
11818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
11828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    iwmmxt_load_reg(cpu_M0, rn);
11838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
11848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline void gen_op_iwmmxt_orq_M0_wRn(int rn)
11868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
11878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    iwmmxt_load_reg(cpu_V1, rn);
11888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_gen_or_i64(cpu_M0, cpu_M0, cpu_V1);
11898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
11908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline void gen_op_iwmmxt_andq_M0_wRn(int rn)
11928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
11938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    iwmmxt_load_reg(cpu_V1, rn);
11948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_gen_and_i64(cpu_M0, cpu_M0, cpu_V1);
11958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
11968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline void gen_op_iwmmxt_xorq_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_xor_i64(cpu_M0, cpu_M0, cpu_V1);
12018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
12028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define IWMMXT_OP(name) \
12048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline void gen_op_iwmmxt_##name##_M0_wRn(int rn) \
12058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ \
12068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    iwmmxt_load_reg(cpu_V1, rn); \
12078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    gen_helper_iwmmxt_##name(cpu_M0, cpu_M0, cpu_V1); \
12088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
12098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1210c4e7d8228a1f893b3a5a639da5b99b53720224bdDavid 'Digit' Turner#define IWMMXT_OP_ENV(name) \
1211c4e7d8228a1f893b3a5a639da5b99b53720224bdDavid 'Digit' Turnerstatic inline void gen_op_iwmmxt_##name##_M0_wRn(int rn) \
1212c4e7d8228a1f893b3a5a639da5b99b53720224bdDavid 'Digit' Turner{ \
1213c4e7d8228a1f893b3a5a639da5b99b53720224bdDavid 'Digit' Turner    iwmmxt_load_reg(cpu_V1, rn); \
1214c4e7d8228a1f893b3a5a639da5b99b53720224bdDavid 'Digit' Turner    gen_helper_iwmmxt_##name(cpu_M0, cpu_env, cpu_M0, cpu_V1); \
1215c4e7d8228a1f893b3a5a639da5b99b53720224bdDavid 'Digit' Turner}
1216c4e7d8228a1f893b3a5a639da5b99b53720224bdDavid 'Digit' Turner
1217c4e7d8228a1f893b3a5a639da5b99b53720224bdDavid 'Digit' Turner#define IWMMXT_OP_ENV_SIZE(name) \
1218c4e7d8228a1f893b3a5a639da5b99b53720224bdDavid 'Digit' TurnerIWMMXT_OP_ENV(name##b) \
1219c4e7d8228a1f893b3a5a639da5b99b53720224bdDavid 'Digit' TurnerIWMMXT_OP_ENV(name##w) \
1220c4e7d8228a1f893b3a5a639da5b99b53720224bdDavid 'Digit' TurnerIWMMXT_OP_ENV(name##l)
12218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1222c4e7d8228a1f893b3a5a639da5b99b53720224bdDavid 'Digit' Turner#define IWMMXT_OP_ENV1(name) \
12238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline void gen_op_iwmmxt_##name##_M0(void) \
12248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ \
1225c4e7d8228a1f893b3a5a639da5b99b53720224bdDavid 'Digit' Turner    gen_helper_iwmmxt_##name(cpu_M0, cpu_env, cpu_M0); \
12268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
12278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectIWMMXT_OP(maddsq)
12298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectIWMMXT_OP(madduq)
12308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectIWMMXT_OP(sadb)
12318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectIWMMXT_OP(sadw)
12328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectIWMMXT_OP(mulslw)
12338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectIWMMXT_OP(mulshw)
12348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectIWMMXT_OP(mululw)
12358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectIWMMXT_OP(muluhw)
12368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectIWMMXT_OP(macsw)
12378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectIWMMXT_OP(macuw)
12388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1239c4e7d8228a1f893b3a5a639da5b99b53720224bdDavid 'Digit' TurnerIWMMXT_OP_ENV_SIZE(unpackl)
1240c4e7d8228a1f893b3a5a639da5b99b53720224bdDavid 'Digit' TurnerIWMMXT_OP_ENV_SIZE(unpackh)
1241c4e7d8228a1f893b3a5a639da5b99b53720224bdDavid 'Digit' Turner
1242c4e7d8228a1f893b3a5a639da5b99b53720224bdDavid 'Digit' TurnerIWMMXT_OP_ENV1(unpacklub)
1243c4e7d8228a1f893b3a5a639da5b99b53720224bdDavid 'Digit' TurnerIWMMXT_OP_ENV1(unpackluw)
1244c4e7d8228a1f893b3a5a639da5b99b53720224bdDavid 'Digit' TurnerIWMMXT_OP_ENV1(unpacklul)
1245c4e7d8228a1f893b3a5a639da5b99b53720224bdDavid 'Digit' TurnerIWMMXT_OP_ENV1(unpackhub)
1246c4e7d8228a1f893b3a5a639da5b99b53720224bdDavid 'Digit' TurnerIWMMXT_OP_ENV1(unpackhuw)
1247c4e7d8228a1f893b3a5a639da5b99b53720224bdDavid 'Digit' TurnerIWMMXT_OP_ENV1(unpackhul)
1248c4e7d8228a1f893b3a5a639da5b99b53720224bdDavid 'Digit' TurnerIWMMXT_OP_ENV1(unpacklsb)
1249c4e7d8228a1f893b3a5a639da5b99b53720224bdDavid 'Digit' TurnerIWMMXT_OP_ENV1(unpacklsw)
1250c4e7d8228a1f893b3a5a639da5b99b53720224bdDavid 'Digit' TurnerIWMMXT_OP_ENV1(unpacklsl)
1251c4e7d8228a1f893b3a5a639da5b99b53720224bdDavid 'Digit' TurnerIWMMXT_OP_ENV1(unpackhsb)
1252c4e7d8228a1f893b3a5a639da5b99b53720224bdDavid 'Digit' TurnerIWMMXT_OP_ENV1(unpackhsw)
1253c4e7d8228a1f893b3a5a639da5b99b53720224bdDavid 'Digit' TurnerIWMMXT_OP_ENV1(unpackhsl)
1254c4e7d8228a1f893b3a5a639da5b99b53720224bdDavid 'Digit' Turner
1255c4e7d8228a1f893b3a5a639da5b99b53720224bdDavid 'Digit' TurnerIWMMXT_OP_ENV_SIZE(cmpeq)
1256c4e7d8228a1f893b3a5a639da5b99b53720224bdDavid 'Digit' TurnerIWMMXT_OP_ENV_SIZE(cmpgtu)
1257c4e7d8228a1f893b3a5a639da5b99b53720224bdDavid 'Digit' TurnerIWMMXT_OP_ENV_SIZE(cmpgts)
1258c4e7d8228a1f893b3a5a639da5b99b53720224bdDavid 'Digit' Turner
1259c4e7d8228a1f893b3a5a639da5b99b53720224bdDavid 'Digit' TurnerIWMMXT_OP_ENV_SIZE(mins)
1260c4e7d8228a1f893b3a5a639da5b99b53720224bdDavid 'Digit' TurnerIWMMXT_OP_ENV_SIZE(minu)
1261c4e7d8228a1f893b3a5a639da5b99b53720224bdDavid 'Digit' TurnerIWMMXT_OP_ENV_SIZE(maxs)
1262c4e7d8228a1f893b3a5a639da5b99b53720224bdDavid 'Digit' TurnerIWMMXT_OP_ENV_SIZE(maxu)
1263c4e7d8228a1f893b3a5a639da5b99b53720224bdDavid 'Digit' Turner
1264c4e7d8228a1f893b3a5a639da5b99b53720224bdDavid 'Digit' TurnerIWMMXT_OP_ENV_SIZE(subn)
1265c4e7d8228a1f893b3a5a639da5b99b53720224bdDavid 'Digit' TurnerIWMMXT_OP_ENV_SIZE(addn)
1266c4e7d8228a1f893b3a5a639da5b99b53720224bdDavid 'Digit' TurnerIWMMXT_OP_ENV_SIZE(subu)
1267c4e7d8228a1f893b3a5a639da5b99b53720224bdDavid 'Digit' TurnerIWMMXT_OP_ENV_SIZE(addu)
1268c4e7d8228a1f893b3a5a639da5b99b53720224bdDavid 'Digit' TurnerIWMMXT_OP_ENV_SIZE(subs)
1269c4e7d8228a1f893b3a5a639da5b99b53720224bdDavid 'Digit' TurnerIWMMXT_OP_ENV_SIZE(adds)
1270c4e7d8228a1f893b3a5a639da5b99b53720224bdDavid 'Digit' Turner
1271c4e7d8228a1f893b3a5a639da5b99b53720224bdDavid 'Digit' TurnerIWMMXT_OP_ENV(avgb0)
1272c4e7d8228a1f893b3a5a639da5b99b53720224bdDavid 'Digit' TurnerIWMMXT_OP_ENV(avgb1)
1273c4e7d8228a1f893b3a5a639da5b99b53720224bdDavid 'Digit' TurnerIWMMXT_OP_ENV(avgw0)
1274c4e7d8228a1f893b3a5a639da5b99b53720224bdDavid 'Digit' TurnerIWMMXT_OP_ENV(avgw1)
12758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectIWMMXT_OP(msadb)
12778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1278c4e7d8228a1f893b3a5a639da5b99b53720224bdDavid 'Digit' TurnerIWMMXT_OP_ENV(packuw)
1279c4e7d8228a1f893b3a5a639da5b99b53720224bdDavid 'Digit' TurnerIWMMXT_OP_ENV(packul)
1280c4e7d8228a1f893b3a5a639da5b99b53720224bdDavid 'Digit' TurnerIWMMXT_OP_ENV(packuq)
1281c4e7d8228a1f893b3a5a639da5b99b53720224bdDavid 'Digit' TurnerIWMMXT_OP_ENV(packsw)
1282c4e7d8228a1f893b3a5a639da5b99b53720224bdDavid 'Digit' TurnerIWMMXT_OP_ENV(packsl)
1283c4e7d8228a1f893b3a5a639da5b99b53720224bdDavid 'Digit' TurnerIWMMXT_OP_ENV(packsq)
12848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void gen_op_iwmmxt_set_mup(void)
12868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
12878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    TCGv tmp;
12888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tmp = load_cpu_field(iwmmxt.cregs[ARM_IWMMXT_wCon]);
12898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_gen_ori_i32(tmp, tmp, 2);
12908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    store_cpu_field(tmp, iwmmxt.cregs[ARM_IWMMXT_wCon]);
12918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
12928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void gen_op_iwmmxt_set_cup(void)
12948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
12958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    TCGv tmp;
12968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tmp = load_cpu_field(iwmmxt.cregs[ARM_IWMMXT_wCon]);
12978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_gen_ori_i32(tmp, tmp, 1);
12988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    store_cpu_field(tmp, iwmmxt.cregs[ARM_IWMMXT_wCon]);
12998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
13008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void gen_op_iwmmxt_setpsr_nz(void)
13028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
13035285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    TCGv tmp = tcg_temp_new_i32();
13048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    gen_helper_iwmmxt_setpsr_nz(tmp, cpu_M0);
13058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    store_cpu_field(tmp, iwmmxt.cregs[ARM_IWMMXT_wCASF]);
13068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
13078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline void gen_op_iwmmxt_addl_M0_wRn(int rn)
13098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
13108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    iwmmxt_load_reg(cpu_V1, rn);
13118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_gen_ext32u_i64(cpu_V1, cpu_V1);
13128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_gen_add_i64(cpu_M0, cpu_M0, cpu_V1);
13138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
13148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13155285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic inline int gen_iwmmxt_address(DisasContext *s, uint32_t insn, TCGv dest)
13168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
13178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int rd;
13188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    uint32_t offset;
13195285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    TCGv tmp;
13208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    rd = (insn >> 16) & 0xf;
13225285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tmp = load_reg(s, rd);
13238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    offset = (insn & 0xff) << ((insn >> 7) & 2);
13258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (insn & (1 << 24)) {
13268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* Pre indexed */
13278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (insn & (1 << 23))
13285285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tcg_gen_addi_i32(tmp, tmp, offset);
13298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        else
13305285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tcg_gen_addi_i32(tmp, tmp, -offset);
13315285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tcg_gen_mov_i32(dest, tmp);
13328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (insn & (1 << 21))
13335285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            store_reg(s, rd, tmp);
13345285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        else
13355285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tcg_temp_free_i32(tmp);
13368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } else if (insn & (1 << 21)) {
13378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* Post indexed */
13385285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tcg_gen_mov_i32(dest, tmp);
13398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (insn & (1 << 23))
13405285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tcg_gen_addi_i32(tmp, tmp, offset);
13418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        else
13425285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tcg_gen_addi_i32(tmp, tmp, -offset);
13435285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        store_reg(s, rd, tmp);
13448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } else if (!(insn & (1 << 23)))
13458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return 1;
13468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
13478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
13488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13495285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic inline int gen_iwmmxt_shift(uint32_t insn, uint32_t mask, TCGv dest)
13508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
13518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int rd = (insn >> 0) & 0xf;
13525285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    TCGv tmp;
13538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13545285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    if (insn & (1 << 8)) {
13555285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        if (rd < ARM_IWMMXT_wCGR0 || rd > ARM_IWMMXT_wCGR3) {
13568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 1;
13575285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        } else {
13585285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tmp = iwmmxt_load_creg(rd);
13595285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        }
13605285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    } else {
13615285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tmp = tcg_temp_new_i32();
13625285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        iwmmxt_load_reg(cpu_V0, rd);
13635285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tcg_gen_trunc_i64_i32(tmp, cpu_V0);
13645285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    }
13655285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_gen_andi_i32(tmp, tmp, mask);
13665285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_gen_mov_i32(dest, tmp);
13675285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_temp_free_i32(tmp);
13688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
13698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
13708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13715285864985be9077e58e42235af6582dee72e841David 'Digit' Turner/* Disassemble an iwMMXt instruction.  Returns nonzero if an error occurred
13728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   (ie. an undefined instruction).  */
1373e2678e116c8cdb0f36b247a5bd9cfacc849362fcDavid 'Digit' Turnerstatic int disas_iwmmxt_insn(CPUARMState *env, DisasContext *s, uint32_t insn)
13748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
13758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int rd, wrd;
13768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int rdhi, rdlo, rd0, rd1, i;
13775285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    TCGv addr;
13785285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    TCGv tmp, tmp2, tmp3;
13798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if ((insn & 0x0e000e00) == 0x0c000000) {
13818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if ((insn & 0x0fe00ff0) == 0x0c400000) {
13828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            wrd = insn & 0xf;
13838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            rdlo = (insn >> 12) & 0xf;
13848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            rdhi = (insn >> 16) & 0xf;
13858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (insn & ARM_CP_RW_BIT) {			/* TMRRC */
13865285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                iwmmxt_load_reg(cpu_V0, wrd);
13875285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_gen_trunc_i64_i32(cpu_R[rdlo], cpu_V0);
13885285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_gen_shri_i64(cpu_V0, cpu_V0, 32);
13895285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_gen_trunc_i64_i32(cpu_R[rdhi], cpu_V0);
13908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            } else {					/* TMCRR */
13915285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_gen_concat_i32_i64(cpu_V0, cpu_R[rdlo], cpu_R[rdhi]);
13925285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                iwmmxt_store_reg(cpu_V0, wrd);
13938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                gen_op_iwmmxt_set_mup();
13948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
13958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 0;
13968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
13978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        wrd = (insn >> 12) & 0xf;
13995285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        addr = tcg_temp_new_i32();
14005285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        if (gen_iwmmxt_address(s, insn, addr)) {
14015285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tcg_temp_free_i32(addr);
14028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 1;
14035285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        }
14048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (insn & ARM_CP_RW_BIT) {
14058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if ((insn >> 28) == 0xf) {			/* WLDRW wCx */
14065285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tmp = tcg_temp_new_i32();
14075285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_gen_qemu_ld32u(tmp, addr, IS_USER(s));
14085285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                iwmmxt_store_creg(wrd, tmp);
14098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            } else {
14108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                i = 1;
14118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (insn & (1 << 8)) {
14128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if (insn & (1 << 22)) {		/* WLDRD */
14135285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tcg_gen_qemu_ld64(cpu_M0, addr, IS_USER(s));
14148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        i = 0;
14158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    } else {				/* WLDRW wRd */
14165285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tmp = gen_ld32(addr, IS_USER(s));
14178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
14188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                } else {
14198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if (insn & (1 << 22)) {		/* WLDRH */
14205285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tmp = gen_ld16u(addr, IS_USER(s));
14218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    } else {				/* WLDRB */
14225285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tmp = gen_ld8u(addr, IS_USER(s));
14238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
14248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
14258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (i) {
14268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    tcg_gen_extu_i32_i64(cpu_M0, tmp);
14275285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tcg_temp_free_i32(tmp);
14288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
14298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                gen_op_iwmmxt_movq_wRn_M0(wrd);
14308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
14318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        } else {
14328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if ((insn >> 28) == 0xf) {			/* WSTRW wCx */
14335285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tmp = iwmmxt_load_creg(wrd);
14345285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                gen_st32(tmp, addr, IS_USER(s));
14358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            } else {
14368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                gen_op_iwmmxt_movq_M0_wRn(wrd);
14375285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tmp = tcg_temp_new_i32();
14388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (insn & (1 << 8)) {
14398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if (insn & (1 << 22)) {		/* WSTRD */
14405285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tcg_temp_free_i32(tmp);
14415285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tcg_gen_qemu_st64(cpu_M0, addr, IS_USER(s));
14428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    } else {				/* WSTRW wRd */
14438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        tcg_gen_trunc_i64_i32(tmp, cpu_M0);
14445285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        gen_st32(tmp, addr, IS_USER(s));
14458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
14468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                } else {
14478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if (insn & (1 << 22)) {		/* WSTRH */
14488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        tcg_gen_trunc_i64_i32(tmp, cpu_M0);
14495285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        gen_st16(tmp, addr, IS_USER(s));
14508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    } else {				/* WSTRB */
14518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        tcg_gen_trunc_i64_i32(tmp, cpu_M0);
14525285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        gen_st8(tmp, addr, IS_USER(s));
14538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
14548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
14558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
14568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
14575285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tcg_temp_free_i32(addr);
14588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return 0;
14598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
14608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
14618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if ((insn & 0x0f000000) != 0x0e000000)
14628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return 1;
14638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
14648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    switch (((insn >> 12) & 0xf00) | ((insn >> 4) & 0xff)) {
14658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0x000:						/* WOR */
14668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        wrd = (insn >> 12) & 0xf;
14678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        rd0 = (insn >> 0) & 0xf;
14688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        rd1 = (insn >> 16) & 0xf;
14698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_movq_M0_wRn(rd0);
14708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_orq_M0_wRn(rd1);
14718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_setpsr_nz();
14728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_movq_wRn_M0(wrd);
14738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_set_mup();
14748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_set_cup();
14758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
14768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0x011:						/* TMCR */
14778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (insn & 0xf)
14788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 1;
14798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        rd = (insn >> 12) & 0xf;
14808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        wrd = (insn >> 16) & 0xf;
14818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        switch (wrd) {
14828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case ARM_IWMMXT_wCID:
14838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case ARM_IWMMXT_wCASF:
14848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
14858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case ARM_IWMMXT_wCon:
14868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            gen_op_iwmmxt_set_cup();
14878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* Fall through.  */
14888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case ARM_IWMMXT_wCSSF:
14895285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tmp = iwmmxt_load_creg(wrd);
14905285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tmp2 = load_reg(s, rd);
14915285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tcg_gen_andc_i32(tmp, tmp, tmp2);
14925285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tcg_temp_free_i32(tmp2);
14935285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            iwmmxt_store_creg(wrd, tmp);
14948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
14958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case ARM_IWMMXT_wCGR0:
14968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case ARM_IWMMXT_wCGR1:
14978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case ARM_IWMMXT_wCGR2:
14988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case ARM_IWMMXT_wCGR3:
14998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            gen_op_iwmmxt_set_cup();
15005285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tmp = load_reg(s, rd);
15015285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            iwmmxt_store_creg(wrd, tmp);
15028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
15038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        default:
15048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 1;
15058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
15068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
15078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0x100:						/* WXOR */
15088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        wrd = (insn >> 12) & 0xf;
15098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        rd0 = (insn >> 0) & 0xf;
15108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        rd1 = (insn >> 16) & 0xf;
15118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_movq_M0_wRn(rd0);
15128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_xorq_M0_wRn(rd1);
15138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_setpsr_nz();
15148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_movq_wRn_M0(wrd);
15158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_set_mup();
15168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_set_cup();
15178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
15188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0x111:						/* TMRC */
15198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (insn & 0xf)
15208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 1;
15218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        rd = (insn >> 12) & 0xf;
15228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        wrd = (insn >> 16) & 0xf;
15235285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tmp = iwmmxt_load_creg(wrd);
15245285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        store_reg(s, rd, tmp);
15258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
15268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0x300:						/* WANDN */
15278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        wrd = (insn >> 12) & 0xf;
15288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        rd0 = (insn >> 0) & 0xf;
15298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        rd1 = (insn >> 16) & 0xf;
15308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_movq_M0_wRn(rd0);
15318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tcg_gen_neg_i64(cpu_M0, cpu_M0);
15328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_andq_M0_wRn(rd1);
15338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_setpsr_nz();
15348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_movq_wRn_M0(wrd);
15358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_set_mup();
15368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_set_cup();
15378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
15388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0x200:						/* WAND */
15398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        wrd = (insn >> 12) & 0xf;
15408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        rd0 = (insn >> 0) & 0xf;
15418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        rd1 = (insn >> 16) & 0xf;
15428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_movq_M0_wRn(rd0);
15438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_andq_M0_wRn(rd1);
15448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_setpsr_nz();
15458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_movq_wRn_M0(wrd);
15468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_set_mup();
15478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_set_cup();
15488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
15498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0x810: case 0xa10:				/* WMADD */
15508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        wrd = (insn >> 12) & 0xf;
15518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        rd0 = (insn >> 0) & 0xf;
15528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        rd1 = (insn >> 16) & 0xf;
15538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_movq_M0_wRn(rd0);
15548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (insn & (1 << 21))
15558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            gen_op_iwmmxt_maddsq_M0_wRn(rd1);
15568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        else
15578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            gen_op_iwmmxt_madduq_M0_wRn(rd1);
15588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_movq_wRn_M0(wrd);
15598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_set_mup();
15608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
15618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0x10e: case 0x50e: case 0x90e: case 0xd0e:	/* WUNPCKIL */
15628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        wrd = (insn >> 12) & 0xf;
15638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        rd0 = (insn >> 16) & 0xf;
15648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        rd1 = (insn >> 0) & 0xf;
15658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_movq_M0_wRn(rd0);
15668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        switch ((insn >> 22) & 3) {
15678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0:
15688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            gen_op_iwmmxt_unpacklb_M0_wRn(rd1);
15698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
15708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 1:
15718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            gen_op_iwmmxt_unpacklw_M0_wRn(rd1);
15728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
15738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 2:
15748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            gen_op_iwmmxt_unpackll_M0_wRn(rd1);
15758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
15768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 3:
15778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 1;
15788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
15798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_movq_wRn_M0(wrd);
15808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_set_mup();
15818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_set_cup();
15828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
15838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0x10c: case 0x50c: case 0x90c: case 0xd0c:	/* WUNPCKIH */
15848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        wrd = (insn >> 12) & 0xf;
15858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        rd0 = (insn >> 16) & 0xf;
15868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        rd1 = (insn >> 0) & 0xf;
15878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_movq_M0_wRn(rd0);
15888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        switch ((insn >> 22) & 3) {
15898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0:
15908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            gen_op_iwmmxt_unpackhb_M0_wRn(rd1);
15918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
15928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 1:
15938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            gen_op_iwmmxt_unpackhw_M0_wRn(rd1);
15948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
15958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 2:
15968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            gen_op_iwmmxt_unpackhl_M0_wRn(rd1);
15978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
15988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 3:
15998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 1;
16008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
16018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_movq_wRn_M0(wrd);
16028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_set_mup();
16038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_set_cup();
16048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
16058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0x012: case 0x112: case 0x412: case 0x512:	/* WSAD */
16068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        wrd = (insn >> 12) & 0xf;
16078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        rd0 = (insn >> 16) & 0xf;
16088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        rd1 = (insn >> 0) & 0xf;
16098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_movq_M0_wRn(rd0);
16108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (insn & (1 << 22))
16118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            gen_op_iwmmxt_sadw_M0_wRn(rd1);
16128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        else
16138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            gen_op_iwmmxt_sadb_M0_wRn(rd1);
16148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (!(insn & (1 << 20)))
16158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            gen_op_iwmmxt_addl_M0_wRn(wrd);
16168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_movq_wRn_M0(wrd);
16178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_set_mup();
16188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
16198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0x010: case 0x110: case 0x210: case 0x310:	/* WMUL */
16208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        wrd = (insn >> 12) & 0xf;
16218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        rd0 = (insn >> 16) & 0xf;
16228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        rd1 = (insn >> 0) & 0xf;
16238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_movq_M0_wRn(rd0);
16248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (insn & (1 << 21)) {
16258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (insn & (1 << 20))
16268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                gen_op_iwmmxt_mulshw_M0_wRn(rd1);
16278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            else
16288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                gen_op_iwmmxt_mulslw_M0_wRn(rd1);
16298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        } else {
16308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (insn & (1 << 20))
16318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                gen_op_iwmmxt_muluhw_M0_wRn(rd1);
16328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            else
16338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                gen_op_iwmmxt_mululw_M0_wRn(rd1);
16348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
16358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_movq_wRn_M0(wrd);
16368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_set_mup();
16378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
16388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0x410: case 0x510: case 0x610: case 0x710:	/* WMAC */
16398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        wrd = (insn >> 12) & 0xf;
16408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        rd0 = (insn >> 16) & 0xf;
16418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        rd1 = (insn >> 0) & 0xf;
16428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_movq_M0_wRn(rd0);
16438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (insn & (1 << 21))
16448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            gen_op_iwmmxt_macsw_M0_wRn(rd1);
16458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        else
16468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            gen_op_iwmmxt_macuw_M0_wRn(rd1);
16478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (!(insn & (1 << 20))) {
16488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            iwmmxt_load_reg(cpu_V1, wrd);
16498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tcg_gen_add_i64(cpu_M0, cpu_M0, cpu_V1);
16508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
16518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_movq_wRn_M0(wrd);
16528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_set_mup();
16538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
16548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0x006: case 0x406: case 0x806: case 0xc06:	/* WCMPEQ */
16558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        wrd = (insn >> 12) & 0xf;
16568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        rd0 = (insn >> 16) & 0xf;
16578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        rd1 = (insn >> 0) & 0xf;
16588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_movq_M0_wRn(rd0);
16598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        switch ((insn >> 22) & 3) {
16608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0:
16618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            gen_op_iwmmxt_cmpeqb_M0_wRn(rd1);
16628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
16638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 1:
16648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            gen_op_iwmmxt_cmpeqw_M0_wRn(rd1);
16658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
16668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 2:
16678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            gen_op_iwmmxt_cmpeql_M0_wRn(rd1);
16688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
16698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 3:
16708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 1;
16718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
16728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_movq_wRn_M0(wrd);
16738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_set_mup();
16748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_set_cup();
16758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
16768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0x800: case 0x900: case 0xc00: case 0xd00:	/* WAVG2 */
16778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        wrd = (insn >> 12) & 0xf;
16788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        rd0 = (insn >> 16) & 0xf;
16798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        rd1 = (insn >> 0) & 0xf;
16808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_movq_M0_wRn(rd0);
16818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (insn & (1 << 22)) {
16828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (insn & (1 << 20))
16838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                gen_op_iwmmxt_avgw1_M0_wRn(rd1);
16848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            else
16858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                gen_op_iwmmxt_avgw0_M0_wRn(rd1);
16868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        } else {
16878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (insn & (1 << 20))
16888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                gen_op_iwmmxt_avgb1_M0_wRn(rd1);
16898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            else
16908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                gen_op_iwmmxt_avgb0_M0_wRn(rd1);
16918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
16928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_movq_wRn_M0(wrd);
16938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_set_mup();
16948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_set_cup();
16958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
16968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0x802: case 0x902: case 0xa02: case 0xb02:	/* WALIGNR */
16978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        wrd = (insn >> 12) & 0xf;
16988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        rd0 = (insn >> 16) & 0xf;
16998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        rd1 = (insn >> 0) & 0xf;
17008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_movq_M0_wRn(rd0);
17015285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tmp = iwmmxt_load_creg(ARM_IWMMXT_wCGR0 + ((insn >> 20) & 3));
17025285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tcg_gen_andi_i32(tmp, tmp, 7);
17035285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        iwmmxt_load_reg(cpu_V1, rd1);
17045285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        gen_helper_iwmmxt_align(cpu_M0, cpu_M0, cpu_V1, tmp);
17055285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tcg_temp_free_i32(tmp);
17068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_movq_wRn_M0(wrd);
17078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_set_mup();
17088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
17098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0x601: case 0x605: case 0x609: case 0x60d:	/* TINSR */
17105285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        if (((insn >> 6) & 3) == 3)
17115285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            return 1;
17128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        rd = (insn >> 12) & 0xf;
17138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        wrd = (insn >> 16) & 0xf;
17145285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tmp = load_reg(s, rd);
17158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_movq_M0_wRn(wrd);
17168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        switch ((insn >> 6) & 3) {
17178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0:
17185285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tmp2 = tcg_const_i32(0xff);
17195285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tmp3 = tcg_const_i32((insn & 7) << 3);
17208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
17218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 1:
17225285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tmp2 = tcg_const_i32(0xffff);
17235285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tmp3 = tcg_const_i32((insn & 3) << 4);
17248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
17258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 2:
17265285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tmp2 = tcg_const_i32(0xffffffff);
17275285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tmp3 = tcg_const_i32((insn & 1) << 5);
17288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
17295285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        default:
17305285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            TCGV_UNUSED(tmp2);
17315285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            TCGV_UNUSED(tmp3);
17328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
17335285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        gen_helper_iwmmxt_insr(cpu_M0, cpu_M0, tmp, tmp2, tmp3);
17345285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tcg_temp_free(tmp3);
17355285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tcg_temp_free(tmp2);
17365285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tcg_temp_free_i32(tmp);
17378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_movq_wRn_M0(wrd);
17388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_set_mup();
17398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
17408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0x107: case 0x507: case 0x907: case 0xd07:	/* TEXTRM */
17418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        rd = (insn >> 12) & 0xf;
17428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        wrd = (insn >> 16) & 0xf;
17435285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        if (rd == 15 || ((insn >> 22) & 3) == 3)
17448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 1;
17458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_movq_M0_wRn(wrd);
17465285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tmp = tcg_temp_new_i32();
17478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        switch ((insn >> 22) & 3) {
17488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0:
17495285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tcg_gen_shri_i64(cpu_M0, cpu_M0, (insn & 7) << 3);
17505285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tcg_gen_trunc_i64_i32(tmp, cpu_M0);
17515285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            if (insn & 8) {
17525285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_gen_ext8s_i32(tmp, tmp);
17535285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            } else {
17545285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_gen_andi_i32(tmp, tmp, 0xff);
17558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
17568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
17578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 1:
17585285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tcg_gen_shri_i64(cpu_M0, cpu_M0, (insn & 3) << 4);
17595285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tcg_gen_trunc_i64_i32(tmp, cpu_M0);
17605285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            if (insn & 8) {
17615285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_gen_ext16s_i32(tmp, tmp);
17625285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            } else {
17635285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_gen_andi_i32(tmp, tmp, 0xffff);
17648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
17658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
17668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 2:
17675285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tcg_gen_shri_i64(cpu_M0, cpu_M0, (insn & 1) << 5);
17685285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tcg_gen_trunc_i64_i32(tmp, cpu_M0);
17698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
17708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
17715285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        store_reg(s, rd, tmp);
17728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
17738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0x117: case 0x517: case 0x917: case 0xd17:	/* TEXTRC */
17745285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        if ((insn & 0x000ff008) != 0x0003f000 || ((insn >> 22) & 3) == 3)
17758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 1;
17765285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tmp = iwmmxt_load_creg(ARM_IWMMXT_wCASF);
17778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        switch ((insn >> 22) & 3) {
17788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0:
17795285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tcg_gen_shri_i32(tmp, tmp, ((insn & 7) << 2) + 0);
17808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
17818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 1:
17825285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tcg_gen_shri_i32(tmp, tmp, ((insn & 3) << 3) + 4);
17838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
17848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 2:
17855285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tcg_gen_shri_i32(tmp, tmp, ((insn & 1) << 4) + 12);
17868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
17878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
17885285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tcg_gen_shli_i32(tmp, tmp, 28);
17895285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        gen_set_nzcv(tmp);
17905285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tcg_temp_free_i32(tmp);
17918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
17928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0x401: case 0x405: case 0x409: case 0x40d:	/* TBCST */
17935285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        if (((insn >> 6) & 3) == 3)
17945285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            return 1;
17958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        rd = (insn >> 12) & 0xf;
17968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        wrd = (insn >> 16) & 0xf;
17975285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tmp = load_reg(s, rd);
17988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        switch ((insn >> 6) & 3) {
17998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0:
18005285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            gen_helper_iwmmxt_bcstb(cpu_M0, tmp);
18018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
18028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 1:
18035285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            gen_helper_iwmmxt_bcstw(cpu_M0, tmp);
18048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
18058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 2:
18065285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            gen_helper_iwmmxt_bcstl(cpu_M0, tmp);
18078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
18088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
18095285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tcg_temp_free_i32(tmp);
18108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_movq_wRn_M0(wrd);
18118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_set_mup();
18128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
18138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0x113: case 0x513: case 0x913: case 0xd13:	/* TANDC */
18145285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        if ((insn & 0x000ff00f) != 0x0003f000 || ((insn >> 22) & 3) == 3)
18158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 1;
18165285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tmp = iwmmxt_load_creg(ARM_IWMMXT_wCASF);
18175285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tmp2 = tcg_temp_new_i32();
18185285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tcg_gen_mov_i32(tmp2, tmp);
18198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        switch ((insn >> 22) & 3) {
18208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0:
18218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            for (i = 0; i < 7; i ++) {
18225285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_gen_shli_i32(tmp2, tmp2, 4);
18235285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_gen_and_i32(tmp, tmp, tmp2);
18248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
18258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
18268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 1:
18278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            for (i = 0; i < 3; i ++) {
18285285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_gen_shli_i32(tmp2, tmp2, 8);
18295285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_gen_and_i32(tmp, tmp, tmp2);
18308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
18318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
18328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 2:
18335285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tcg_gen_shli_i32(tmp2, tmp2, 16);
18345285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tcg_gen_and_i32(tmp, tmp, tmp2);
18358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
18368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
18375285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        gen_set_nzcv(tmp);
18385285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tcg_temp_free_i32(tmp2);
18395285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tcg_temp_free_i32(tmp);
18408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
18418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0x01c: case 0x41c: case 0x81c: case 0xc1c:	/* WACC */
18428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        wrd = (insn >> 12) & 0xf;
18438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        rd0 = (insn >> 16) & 0xf;
18448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_movq_M0_wRn(rd0);
18458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        switch ((insn >> 22) & 3) {
18468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0:
18478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            gen_helper_iwmmxt_addcb(cpu_M0, cpu_M0);
18488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
18498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 1:
18508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            gen_helper_iwmmxt_addcw(cpu_M0, cpu_M0);
18518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
18528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 2:
18538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            gen_helper_iwmmxt_addcl(cpu_M0, cpu_M0);
18548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
18558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 3:
18568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 1;
18578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
18588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_movq_wRn_M0(wrd);
18598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_set_mup();
18608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
18618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0x115: case 0x515: case 0x915: case 0xd15:	/* TORC */
18625285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        if ((insn & 0x000ff00f) != 0x0003f000 || ((insn >> 22) & 3) == 3)
18638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 1;
18645285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tmp = iwmmxt_load_creg(ARM_IWMMXT_wCASF);
18655285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tmp2 = tcg_temp_new_i32();
18665285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tcg_gen_mov_i32(tmp2, tmp);
18678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        switch ((insn >> 22) & 3) {
18688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0:
18698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            for (i = 0; i < 7; i ++) {
18705285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_gen_shli_i32(tmp2, tmp2, 4);
18715285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_gen_or_i32(tmp, tmp, tmp2);
18728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
18738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
18748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 1:
18758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            for (i = 0; i < 3; i ++) {
18765285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_gen_shli_i32(tmp2, tmp2, 8);
18775285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_gen_or_i32(tmp, tmp, tmp2);
18788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
18798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
18808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 2:
18815285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tcg_gen_shli_i32(tmp2, tmp2, 16);
18825285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tcg_gen_or_i32(tmp, tmp, tmp2);
18838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
18848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
18855285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        gen_set_nzcv(tmp);
18865285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tcg_temp_free_i32(tmp2);
18875285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tcg_temp_free_i32(tmp);
18888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
18898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0x103: case 0x503: case 0x903: case 0xd03:	/* TMOVMSK */
18908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        rd = (insn >> 12) & 0xf;
18918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        rd0 = (insn >> 16) & 0xf;
18925285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        if ((insn & 0xf) != 0 || ((insn >> 22) & 3) == 3)
18938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 1;
18948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_movq_M0_wRn(rd0);
18955285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tmp = tcg_temp_new_i32();
18968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        switch ((insn >> 22) & 3) {
18978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0:
18985285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            gen_helper_iwmmxt_msbb(tmp, cpu_M0);
18998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
19008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 1:
19015285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            gen_helper_iwmmxt_msbw(tmp, cpu_M0);
19028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
19038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 2:
19045285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            gen_helper_iwmmxt_msbl(tmp, cpu_M0);
19058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
19068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
19075285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        store_reg(s, rd, tmp);
19088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
19098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0x106: case 0x306: case 0x506: case 0x706:	/* WCMPGT */
19108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0x906: case 0xb06: case 0xd06: case 0xf06:
19118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        wrd = (insn >> 12) & 0xf;
19128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        rd0 = (insn >> 16) & 0xf;
19138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        rd1 = (insn >> 0) & 0xf;
19148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_movq_M0_wRn(rd0);
19158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        switch ((insn >> 22) & 3) {
19168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0:
19178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (insn & (1 << 21))
19188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                gen_op_iwmmxt_cmpgtsb_M0_wRn(rd1);
19198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            else
19208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                gen_op_iwmmxt_cmpgtub_M0_wRn(rd1);
19218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
19228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 1:
19238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (insn & (1 << 21))
19248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                gen_op_iwmmxt_cmpgtsw_M0_wRn(rd1);
19258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            else
19268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                gen_op_iwmmxt_cmpgtuw_M0_wRn(rd1);
19278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
19288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 2:
19298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (insn & (1 << 21))
19308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                gen_op_iwmmxt_cmpgtsl_M0_wRn(rd1);
19318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            else
19328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                gen_op_iwmmxt_cmpgtul_M0_wRn(rd1);
19338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
19348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 3:
19358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 1;
19368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
19378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_movq_wRn_M0(wrd);
19388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_set_mup();
19398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_set_cup();
19408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
19418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0x00e: case 0x20e: case 0x40e: case 0x60e:	/* WUNPCKEL */
19428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0x80e: case 0xa0e: case 0xc0e: case 0xe0e:
19438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        wrd = (insn >> 12) & 0xf;
19448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        rd0 = (insn >> 16) & 0xf;
19458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_movq_M0_wRn(rd0);
19468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        switch ((insn >> 22) & 3) {
19478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0:
19488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (insn & (1 << 21))
19498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                gen_op_iwmmxt_unpacklsb_M0();
19508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            else
19518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                gen_op_iwmmxt_unpacklub_M0();
19528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
19538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 1:
19548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (insn & (1 << 21))
19558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                gen_op_iwmmxt_unpacklsw_M0();
19568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            else
19578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                gen_op_iwmmxt_unpackluw_M0();
19588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
19598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 2:
19608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (insn & (1 << 21))
19618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                gen_op_iwmmxt_unpacklsl_M0();
19628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            else
19638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                gen_op_iwmmxt_unpacklul_M0();
19648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
19658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 3:
19668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 1;
19678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
19688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_movq_wRn_M0(wrd);
19698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_set_mup();
19708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_set_cup();
19718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
19728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0x00c: case 0x20c: case 0x40c: case 0x60c:	/* WUNPCKEH */
19738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0x80c: case 0xa0c: case 0xc0c: case 0xe0c:
19748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        wrd = (insn >> 12) & 0xf;
19758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        rd0 = (insn >> 16) & 0xf;
19768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_movq_M0_wRn(rd0);
19778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        switch ((insn >> 22) & 3) {
19788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0:
19798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (insn & (1 << 21))
19808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                gen_op_iwmmxt_unpackhsb_M0();
19818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            else
19828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                gen_op_iwmmxt_unpackhub_M0();
19838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
19848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 1:
19858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (insn & (1 << 21))
19868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                gen_op_iwmmxt_unpackhsw_M0();
19878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            else
19888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                gen_op_iwmmxt_unpackhuw_M0();
19898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
19908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 2:
19918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (insn & (1 << 21))
19928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                gen_op_iwmmxt_unpackhsl_M0();
19938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            else
19948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                gen_op_iwmmxt_unpackhul_M0();
19958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
19968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 3:
19978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 1;
19988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
19998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_movq_wRn_M0(wrd);
20008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_set_mup();
20018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_set_cup();
20028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
20038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0x204: case 0x604: case 0xa04: case 0xe04:	/* WSRL */
20048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0x214: case 0x614: case 0xa14: case 0xe14:
20055285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        if (((insn >> 22) & 3) == 0)
20065285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            return 1;
20078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        wrd = (insn >> 12) & 0xf;
20088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        rd0 = (insn >> 16) & 0xf;
20098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_movq_M0_wRn(rd0);
20105285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tmp = tcg_temp_new_i32();
20115285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        if (gen_iwmmxt_shift(insn, 0xff, tmp)) {
20125285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tcg_temp_free_i32(tmp);
20138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 1;
20145285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        }
20158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        switch ((insn >> 22) & 3) {
20168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 1:
2017c4e7d8228a1f893b3a5a639da5b99b53720224bdDavid 'Digit' Turner            gen_helper_iwmmxt_srlw(cpu_M0, cpu_env, cpu_M0, tmp);
20188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
20198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 2:
2020c4e7d8228a1f893b3a5a639da5b99b53720224bdDavid 'Digit' Turner            gen_helper_iwmmxt_srll(cpu_M0, cpu_env, cpu_M0, tmp);
20218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
20228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 3:
2023c4e7d8228a1f893b3a5a639da5b99b53720224bdDavid 'Digit' Turner            gen_helper_iwmmxt_srlq(cpu_M0, cpu_env, cpu_M0, tmp);
20248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
20258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
20265285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tcg_temp_free_i32(tmp);
20278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_movq_wRn_M0(wrd);
20288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_set_mup();
20298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_set_cup();
20308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
20318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0x004: case 0x404: case 0x804: case 0xc04:	/* WSRA */
20328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0x014: case 0x414: case 0x814: case 0xc14:
20335285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        if (((insn >> 22) & 3) == 0)
20345285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            return 1;
20358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        wrd = (insn >> 12) & 0xf;
20368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        rd0 = (insn >> 16) & 0xf;
20378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_movq_M0_wRn(rd0);
20385285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tmp = tcg_temp_new_i32();
20395285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        if (gen_iwmmxt_shift(insn, 0xff, tmp)) {
20405285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tcg_temp_free_i32(tmp);
20418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 1;
20425285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        }
20438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        switch ((insn >> 22) & 3) {
20448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 1:
2045c4e7d8228a1f893b3a5a639da5b99b53720224bdDavid 'Digit' Turner            gen_helper_iwmmxt_sraw(cpu_M0, cpu_env, cpu_M0, tmp);
20468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
20478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 2:
2048c4e7d8228a1f893b3a5a639da5b99b53720224bdDavid 'Digit' Turner            gen_helper_iwmmxt_sral(cpu_M0, cpu_env, cpu_M0, tmp);
20498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
20508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 3:
2051c4e7d8228a1f893b3a5a639da5b99b53720224bdDavid 'Digit' Turner            gen_helper_iwmmxt_sraq(cpu_M0, cpu_env, cpu_M0, tmp);
20528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
20538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
20545285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tcg_temp_free_i32(tmp);
20558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_movq_wRn_M0(wrd);
20568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_set_mup();
20578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_set_cup();
20588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
20598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0x104: case 0x504: case 0x904: case 0xd04:	/* WSLL */
20608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0x114: case 0x514: case 0x914: case 0xd14:
20615285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        if (((insn >> 22) & 3) == 0)
20625285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            return 1;
20638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        wrd = (insn >> 12) & 0xf;
20648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        rd0 = (insn >> 16) & 0xf;
20658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_movq_M0_wRn(rd0);
20665285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tmp = tcg_temp_new_i32();
20675285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        if (gen_iwmmxt_shift(insn, 0xff, tmp)) {
20685285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tcg_temp_free_i32(tmp);
20698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 1;
20705285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        }
20718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        switch ((insn >> 22) & 3) {
20728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 1:
2073c4e7d8228a1f893b3a5a639da5b99b53720224bdDavid 'Digit' Turner            gen_helper_iwmmxt_sllw(cpu_M0, cpu_env, cpu_M0, tmp);
20748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
20758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 2:
2076c4e7d8228a1f893b3a5a639da5b99b53720224bdDavid 'Digit' Turner            gen_helper_iwmmxt_slll(cpu_M0, cpu_env, cpu_M0, tmp);
20778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
20788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 3:
2079c4e7d8228a1f893b3a5a639da5b99b53720224bdDavid 'Digit' Turner            gen_helper_iwmmxt_sllq(cpu_M0, cpu_env, cpu_M0, tmp);
20808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
20818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
20825285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tcg_temp_free_i32(tmp);
20838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_movq_wRn_M0(wrd);
20848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_set_mup();
20858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_set_cup();
20868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
20878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0x304: case 0x704: case 0xb04: case 0xf04:	/* WROR */
20888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0x314: case 0x714: case 0xb14: case 0xf14:
20895285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        if (((insn >> 22) & 3) == 0)
20905285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            return 1;
20918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        wrd = (insn >> 12) & 0xf;
20928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        rd0 = (insn >> 16) & 0xf;
20938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_movq_M0_wRn(rd0);
20945285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tmp = tcg_temp_new_i32();
20958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        switch ((insn >> 22) & 3) {
20968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 1:
20975285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            if (gen_iwmmxt_shift(insn, 0xf, tmp)) {
20985285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_temp_free_i32(tmp);
20998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                return 1;
21005285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            }
2101c4e7d8228a1f893b3a5a639da5b99b53720224bdDavid 'Digit' Turner            gen_helper_iwmmxt_rorw(cpu_M0, cpu_env, cpu_M0, tmp);
21028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
21038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 2:
21045285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            if (gen_iwmmxt_shift(insn, 0x1f, tmp)) {
21055285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_temp_free_i32(tmp);
21068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                return 1;
21075285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            }
2108c4e7d8228a1f893b3a5a639da5b99b53720224bdDavid 'Digit' Turner            gen_helper_iwmmxt_rorl(cpu_M0, cpu_env, cpu_M0, tmp);
21098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
21108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 3:
21115285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            if (gen_iwmmxt_shift(insn, 0x3f, tmp)) {
21125285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_temp_free_i32(tmp);
21138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                return 1;
21145285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            }
2115c4e7d8228a1f893b3a5a639da5b99b53720224bdDavid 'Digit' Turner            gen_helper_iwmmxt_rorq(cpu_M0, cpu_env, cpu_M0, tmp);
21168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
21178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
21185285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tcg_temp_free_i32(tmp);
21198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_movq_wRn_M0(wrd);
21208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_set_mup();
21218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_set_cup();
21228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
21238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0x116: case 0x316: case 0x516: case 0x716:	/* WMIN */
21248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0x916: case 0xb16: case 0xd16: case 0xf16:
21258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        wrd = (insn >> 12) & 0xf;
21268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        rd0 = (insn >> 16) & 0xf;
21278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        rd1 = (insn >> 0) & 0xf;
21288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_movq_M0_wRn(rd0);
21298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        switch ((insn >> 22) & 3) {
21308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0:
21318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (insn & (1 << 21))
21328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                gen_op_iwmmxt_minsb_M0_wRn(rd1);
21338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            else
21348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                gen_op_iwmmxt_minub_M0_wRn(rd1);
21358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
21368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 1:
21378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (insn & (1 << 21))
21388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                gen_op_iwmmxt_minsw_M0_wRn(rd1);
21398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            else
21408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                gen_op_iwmmxt_minuw_M0_wRn(rd1);
21418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
21428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 2:
21438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (insn & (1 << 21))
21448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                gen_op_iwmmxt_minsl_M0_wRn(rd1);
21458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            else
21468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                gen_op_iwmmxt_minul_M0_wRn(rd1);
21478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
21488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 3:
21498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 1;
21508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
21518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_movq_wRn_M0(wrd);
21528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_set_mup();
21538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
21548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0x016: case 0x216: case 0x416: case 0x616:	/* WMAX */
21558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0x816: case 0xa16: case 0xc16: case 0xe16:
21568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        wrd = (insn >> 12) & 0xf;
21578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        rd0 = (insn >> 16) & 0xf;
21588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        rd1 = (insn >> 0) & 0xf;
21598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_movq_M0_wRn(rd0);
21608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        switch ((insn >> 22) & 3) {
21618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0:
21628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (insn & (1 << 21))
21638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                gen_op_iwmmxt_maxsb_M0_wRn(rd1);
21648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            else
21658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                gen_op_iwmmxt_maxub_M0_wRn(rd1);
21668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
21678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 1:
21688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (insn & (1 << 21))
21698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                gen_op_iwmmxt_maxsw_M0_wRn(rd1);
21708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            else
21718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                gen_op_iwmmxt_maxuw_M0_wRn(rd1);
21728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
21738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 2:
21748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (insn & (1 << 21))
21758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                gen_op_iwmmxt_maxsl_M0_wRn(rd1);
21768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            else
21778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                gen_op_iwmmxt_maxul_M0_wRn(rd1);
21788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
21798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 3:
21808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 1;
21818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
21828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_movq_wRn_M0(wrd);
21838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_set_mup();
21848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
21858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0x002: case 0x102: case 0x202: case 0x302:	/* WALIGNI */
21868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0x402: case 0x502: case 0x602: case 0x702:
21878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        wrd = (insn >> 12) & 0xf;
21888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        rd0 = (insn >> 16) & 0xf;
21898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        rd1 = (insn >> 0) & 0xf;
21908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_movq_M0_wRn(rd0);
21915285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tmp = tcg_const_i32((insn >> 20) & 3);
21925285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        iwmmxt_load_reg(cpu_V1, rd1);
21935285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        gen_helper_iwmmxt_align(cpu_M0, cpu_M0, cpu_V1, tmp);
21945285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tcg_temp_free(tmp);
21958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_movq_wRn_M0(wrd);
21968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_set_mup();
21978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
21988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0x01a: case 0x11a: case 0x21a: case 0x31a:	/* WSUB */
21998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0x41a: case 0x51a: case 0x61a: case 0x71a:
22008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0x81a: case 0x91a: case 0xa1a: case 0xb1a:
22018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0xc1a: case 0xd1a: case 0xe1a: case 0xf1a:
22028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        wrd = (insn >> 12) & 0xf;
22038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        rd0 = (insn >> 16) & 0xf;
22048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        rd1 = (insn >> 0) & 0xf;
22058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_movq_M0_wRn(rd0);
22068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        switch ((insn >> 20) & 0xf) {
22078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0x0:
22088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            gen_op_iwmmxt_subnb_M0_wRn(rd1);
22098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
22108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0x1:
22118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            gen_op_iwmmxt_subub_M0_wRn(rd1);
22128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
22138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0x3:
22148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            gen_op_iwmmxt_subsb_M0_wRn(rd1);
22158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
22168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0x4:
22178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            gen_op_iwmmxt_subnw_M0_wRn(rd1);
22188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
22198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0x5:
22208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            gen_op_iwmmxt_subuw_M0_wRn(rd1);
22218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
22228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0x7:
22238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            gen_op_iwmmxt_subsw_M0_wRn(rd1);
22248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
22258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0x8:
22268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            gen_op_iwmmxt_subnl_M0_wRn(rd1);
22278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
22288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0x9:
22298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            gen_op_iwmmxt_subul_M0_wRn(rd1);
22308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
22318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0xb:
22328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            gen_op_iwmmxt_subsl_M0_wRn(rd1);
22338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
22348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        default:
22358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 1;
22368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
22378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_movq_wRn_M0(wrd);
22388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_set_mup();
22398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_set_cup();
22408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
22418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0x01e: case 0x11e: case 0x21e: case 0x31e:	/* WSHUFH */
22428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0x41e: case 0x51e: case 0x61e: case 0x71e:
22438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0x81e: case 0x91e: case 0xa1e: case 0xb1e:
22448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0xc1e: case 0xd1e: case 0xe1e: case 0xf1e:
22458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        wrd = (insn >> 12) & 0xf;
22468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        rd0 = (insn >> 16) & 0xf;
22478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_movq_M0_wRn(rd0);
22485285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tmp = tcg_const_i32(((insn >> 16) & 0xf0) | (insn & 0x0f));
2249c4e7d8228a1f893b3a5a639da5b99b53720224bdDavid 'Digit' Turner        gen_helper_iwmmxt_shufh(cpu_M0, cpu_env, cpu_M0, tmp);
22505285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tcg_temp_free(tmp);
22518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_movq_wRn_M0(wrd);
22528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_set_mup();
22538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_set_cup();
22548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
22558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0x018: case 0x118: case 0x218: case 0x318:	/* WADD */
22568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0x418: case 0x518: case 0x618: case 0x718:
22578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0x818: case 0x918: case 0xa18: case 0xb18:
22588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0xc18: case 0xd18: case 0xe18: case 0xf18:
22598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        wrd = (insn >> 12) & 0xf;
22608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        rd0 = (insn >> 16) & 0xf;
22618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        rd1 = (insn >> 0) & 0xf;
22628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_movq_M0_wRn(rd0);
22638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        switch ((insn >> 20) & 0xf) {
22648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0x0:
22658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            gen_op_iwmmxt_addnb_M0_wRn(rd1);
22668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
22678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0x1:
22688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            gen_op_iwmmxt_addub_M0_wRn(rd1);
22698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
22708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0x3:
22718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            gen_op_iwmmxt_addsb_M0_wRn(rd1);
22728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
22738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0x4:
22748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            gen_op_iwmmxt_addnw_M0_wRn(rd1);
22758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
22768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0x5:
22778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            gen_op_iwmmxt_adduw_M0_wRn(rd1);
22788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
22798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0x7:
22808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            gen_op_iwmmxt_addsw_M0_wRn(rd1);
22818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
22828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0x8:
22838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            gen_op_iwmmxt_addnl_M0_wRn(rd1);
22848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
22858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0x9:
22868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            gen_op_iwmmxt_addul_M0_wRn(rd1);
22878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
22888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0xb:
22898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            gen_op_iwmmxt_addsl_M0_wRn(rd1);
22908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
22918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        default:
22928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 1;
22938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
22948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_movq_wRn_M0(wrd);
22958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_set_mup();
22968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_set_cup();
22978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
22988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0x008: case 0x108: case 0x208: case 0x308:	/* WPACK */
22998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0x408: case 0x508: case 0x608: case 0x708:
23008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0x808: case 0x908: case 0xa08: case 0xb08:
23018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0xc08: case 0xd08: case 0xe08: case 0xf08:
23025285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        if (!(insn & (1 << 20)) || ((insn >> 22) & 3) == 0)
23035285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            return 1;
23048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        wrd = (insn >> 12) & 0xf;
23058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        rd0 = (insn >> 16) & 0xf;
23068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        rd1 = (insn >> 0) & 0xf;
23078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_movq_M0_wRn(rd0);
23088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        switch ((insn >> 22) & 3) {
23098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 1:
23108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (insn & (1 << 21))
23118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                gen_op_iwmmxt_packsw_M0_wRn(rd1);
23128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            else
23138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                gen_op_iwmmxt_packuw_M0_wRn(rd1);
23148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
23158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 2:
23168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (insn & (1 << 21))
23178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                gen_op_iwmmxt_packsl_M0_wRn(rd1);
23188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            else
23198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                gen_op_iwmmxt_packul_M0_wRn(rd1);
23208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
23218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 3:
23228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (insn & (1 << 21))
23238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                gen_op_iwmmxt_packsq_M0_wRn(rd1);
23248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            else
23258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                gen_op_iwmmxt_packuq_M0_wRn(rd1);
23268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
23278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
23288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_movq_wRn_M0(wrd);
23298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_set_mup();
23308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_set_cup();
23318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
23328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0x201: case 0x203: case 0x205: case 0x207:
23338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0x209: case 0x20b: case 0x20d: case 0x20f:
23348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0x211: case 0x213: case 0x215: case 0x217:
23358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0x219: case 0x21b: case 0x21d: case 0x21f:
23368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        wrd = (insn >> 5) & 0xf;
23378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        rd0 = (insn >> 12) & 0xf;
23388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        rd1 = (insn >> 0) & 0xf;
23398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (rd0 == 0xf || rd1 == 0xf)
23408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 1;
23418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_movq_M0_wRn(wrd);
23425285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tmp = load_reg(s, rd0);
23435285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tmp2 = load_reg(s, rd1);
23448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        switch ((insn >> 16) & 0xf) {
23458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0x0:					/* TMIA */
23465285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            gen_helper_iwmmxt_muladdsl(cpu_M0, cpu_M0, tmp, tmp2);
23478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
23488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0x8:					/* TMIAPH */
23495285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            gen_helper_iwmmxt_muladdsw(cpu_M0, cpu_M0, tmp, tmp2);
23508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
23518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0xc: case 0xd: case 0xe: case 0xf:		/* TMIAxy */
23528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (insn & (1 << 16))
23535285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_gen_shri_i32(tmp, tmp, 16);
23548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (insn & (1 << 17))
23555285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_gen_shri_i32(tmp2, tmp2, 16);
23565285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            gen_helper_iwmmxt_muladdswl(cpu_M0, cpu_M0, tmp, tmp2);
23578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
23588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        default:
23595285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tcg_temp_free_i32(tmp2);
23605285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tcg_temp_free_i32(tmp);
23618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 1;
23628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
23635285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tcg_temp_free_i32(tmp2);
23645285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tcg_temp_free_i32(tmp);
23658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_movq_wRn_M0(wrd);
23668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_set_mup();
23678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
23688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    default:
23698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return 1;
23708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
23718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
23728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
23738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
23748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
23755285864985be9077e58e42235af6582dee72e841David 'Digit' Turner/* Disassemble an XScale DSP instruction.  Returns nonzero if an error occurred
23768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   (ie. an undefined instruction).  */
2377e2678e116c8cdb0f36b247a5bd9cfacc849362fcDavid 'Digit' Turnerstatic int disas_dsp_insn(CPUARMState *env, DisasContext *s, uint32_t insn)
23788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
23798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int acc, rd0, rd1, rdhi, rdlo;
23805285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    TCGv tmp, tmp2;
23818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
23828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if ((insn & 0x0ff00f10) == 0x0e200010) {
23838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* Multiply with Internal Accumulate Format */
23848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        rd0 = (insn >> 12) & 0xf;
23858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        rd1 = insn & 0xf;
23868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        acc = (insn >> 5) & 7;
23878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
23888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (acc != 0)
23898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 1;
23908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
23915285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tmp = load_reg(s, rd0);
23925285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tmp2 = load_reg(s, rd1);
23938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        switch ((insn >> 16) & 0xf) {
23948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0x0:					/* MIA */
23955285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            gen_helper_iwmmxt_muladdsl(cpu_M0, cpu_M0, tmp, tmp2);
23968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
23978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0x8:					/* MIAPH */
23985285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            gen_helper_iwmmxt_muladdsw(cpu_M0, cpu_M0, tmp, tmp2);
23998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
24008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0xc:					/* MIABB */
24018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0xd:					/* MIABT */
24028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0xe:					/* MIATB */
24038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0xf:					/* MIATT */
24048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (insn & (1 << 16))
24055285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_gen_shri_i32(tmp, tmp, 16);
24068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (insn & (1 << 17))
24075285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_gen_shri_i32(tmp2, tmp2, 16);
24085285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            gen_helper_iwmmxt_muladdswl(cpu_M0, cpu_M0, tmp, tmp2);
24098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
24108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        default:
24118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 1;
24128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
24135285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tcg_temp_free_i32(tmp2);
24145285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tcg_temp_free_i32(tmp);
24158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
24168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_movq_wRn_M0(acc);
24178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return 0;
24188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
24198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
24208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if ((insn & 0x0fe00ff8) == 0x0c400000) {
24218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* Internal Accumulator Access Format */
24228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        rdhi = (insn >> 16) & 0xf;
24238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        rdlo = (insn >> 12) & 0xf;
24248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        acc = insn & 7;
24258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
24268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (acc != 0)
24278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 1;
24288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
24298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (insn & ARM_CP_RW_BIT) {			/* MRA */
24305285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            iwmmxt_load_reg(cpu_V0, acc);
24315285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tcg_gen_trunc_i64_i32(cpu_R[rdlo], cpu_V0);
24325285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tcg_gen_shri_i64(cpu_V0, cpu_V0, 32);
24335285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tcg_gen_trunc_i64_i32(cpu_R[rdhi], cpu_V0);
24345285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tcg_gen_andi_i32(cpu_R[rdhi], cpu_R[rdhi], (1 << (40 - 32)) - 1);
24358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        } else {					/* MAR */
24365285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tcg_gen_concat_i32_i64(cpu_V0, cpu_R[rdlo], cpu_R[rdhi]);
24375285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            iwmmxt_store_reg(cpu_V0, acc);
24388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
24398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return 0;
24408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
24418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
24428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 1;
24438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
24448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
24458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Disassemble system coprocessor instruction.  Return nonzero if
24468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   instruction is not defined.  */
2447e2678e116c8cdb0f36b247a5bd9cfacc849362fcDavid 'Digit' Turnerstatic int disas_cp_insn(CPUARMState *env, DisasContext *s, uint32_t insn)
24488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
24495285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    TCGv tmp, tmp2;
24508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    uint32_t rd = (insn >> 12) & 0xf;
24518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    uint32_t cp = (insn >> 8) & 0xf;
24528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
24538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (insn & ARM_CP_RW_BIT) {
24548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (!env->cp[cp].cp_read)
24558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 1;
24568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_set_pc_im(s->pc);
24575285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tmp = tcg_temp_new_i32();
24585285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tmp2 = tcg_const_i32(insn);
24595285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        gen_helper_get_cp(tmp, cpu_env, tmp2);
24605285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tcg_temp_free(tmp2);
24618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        store_reg(s, rd, tmp);
24628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } else {
24638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (!env->cp[cp].cp_write)
24648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 1;
24658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_set_pc_im(s->pc);
24668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tmp = load_reg(s, rd);
24675285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tmp2 = tcg_const_i32(insn);
24685285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        gen_helper_set_cp(cpu_env, tmp2, tmp);
24695285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tcg_temp_free(tmp2);
24705285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tcg_temp_free_i32(tmp);
24718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
24728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
24738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
24748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2475d9ac10a8a8351cb852c660e77dbe361365d3a8a7David 'Digit' Turnerstatic int cp15_user_ok(CPUARMState *env, uint32_t insn)
24768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
24778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int cpn = (insn >> 16) & 0xf;
24788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int cpm = insn & 0xf;
24798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int op = ((insn >> 5) & 7) | ((insn >> 18) & 0x38);
24808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2481d9ac10a8a8351cb852c660e77dbe361365d3a8a7David 'Digit' Turner    if (arm_feature(env, ARM_FEATURE_V7) && cpn == 9) {
2482d9ac10a8a8351cb852c660e77dbe361365d3a8a7David 'Digit' Turner        /* Performance monitor registers fall into three categories:
2483d9ac10a8a8351cb852c660e77dbe361365d3a8a7David 'Digit' Turner         *  (a) always UNDEF in usermode
2484d9ac10a8a8351cb852c660e77dbe361365d3a8a7David 'Digit' Turner         *  (b) UNDEF only if PMUSERENR.EN is 0
2485d9ac10a8a8351cb852c660e77dbe361365d3a8a7David 'Digit' Turner         *  (c) always read OK and UNDEF on write (PMUSERENR only)
2486d9ac10a8a8351cb852c660e77dbe361365d3a8a7David 'Digit' Turner         */
2487d9ac10a8a8351cb852c660e77dbe361365d3a8a7David 'Digit' Turner        if ((cpm == 12 && (op < 6)) ||
2488d9ac10a8a8351cb852c660e77dbe361365d3a8a7David 'Digit' Turner            (cpm == 13 && (op < 3))) {
2489d9ac10a8a8351cb852c660e77dbe361365d3a8a7David 'Digit' Turner            return env->cp15.c9_pmuserenr;
2490d9ac10a8a8351cb852c660e77dbe361365d3a8a7David 'Digit' Turner        } else if (cpm == 14 && op == 0 && (insn & ARM_CP_RW_BIT)) {
2491d9ac10a8a8351cb852c660e77dbe361365d3a8a7David 'Digit' Turner            /* PMUSERENR, read only */
2492d9ac10a8a8351cb852c660e77dbe361365d3a8a7David 'Digit' Turner            return 1;
2493d9ac10a8a8351cb852c660e77dbe361365d3a8a7David 'Digit' Turner        }
2494d9ac10a8a8351cb852c660e77dbe361365d3a8a7David 'Digit' Turner        return 0;
2495d9ac10a8a8351cb852c660e77dbe361365d3a8a7David 'Digit' Turner    }
2496d9ac10a8a8351cb852c660e77dbe361365d3a8a7David 'Digit' Turner
24978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (cpn == 13 && cpm == 0) {
24988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* TLS register.  */
24998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (op == 2 || (op == 3 && (insn & ARM_CP_RW_BIT)))
25008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 1;
25018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
25028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
25038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
25048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2505e2678e116c8cdb0f36b247a5bd9cfacc849362fcDavid 'Digit' Turnerstatic int cp15_tls_load_store(CPUARMState *env, DisasContext *s, uint32_t insn, uint32_t rd)
25065285864985be9077e58e42235af6582dee72e841David 'Digit' Turner{
25075285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    TCGv tmp;
25085285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    int cpn = (insn >> 16) & 0xf;
25095285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    int cpm = insn & 0xf;
25105285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    int op = ((insn >> 5) & 7) | ((insn >> 18) & 0x38);
25115285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
25125285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    if (!arm_feature(env, ARM_FEATURE_V6K))
25135285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        return 0;
25145285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
25155285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    if (!(cpn == 13 && cpm == 0))
25165285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        return 0;
25175285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
25185285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    if (insn & ARM_CP_RW_BIT) {
25195285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        switch (op) {
25205285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        case 2:
25215285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tmp = load_cpu_field(cp15.c13_tls1);
25225285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            break;
25235285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        case 3:
25245285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tmp = load_cpu_field(cp15.c13_tls2);
25255285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            break;
25265285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        case 4:
25275285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tmp = load_cpu_field(cp15.c13_tls3);
25285285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            break;
25295285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        default:
25305285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            return 0;
25315285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        }
25325285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        store_reg(s, rd, tmp);
25335285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
25345285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    } else {
25355285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tmp = load_reg(s, rd);
25365285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        switch (op) {
25375285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        case 2:
25385285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            store_cpu_field(tmp, cp15.c13_tls1);
25395285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            break;
25405285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        case 3:
25415285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            store_cpu_field(tmp, cp15.c13_tls2);
25425285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            break;
25435285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        case 4:
25445285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            store_cpu_field(tmp, cp15.c13_tls3);
25455285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            break;
25465285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        default:
25475285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tcg_temp_free_i32(tmp);
25485285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            return 0;
25495285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        }
25505285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    }
25515285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    return 1;
25525285864985be9077e58e42235af6582dee72e841David 'Digit' Turner}
25535285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
25548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Disassemble system coprocessor (cp15) instruction.  Return nonzero if
25558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   instruction is not defined.  */
2556e2678e116c8cdb0f36b247a5bd9cfacc849362fcDavid 'Digit' Turnerstatic int disas_cp15_insn(CPUARMState *env, DisasContext *s, uint32_t insn)
25578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
25588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    uint32_t rd;
25595285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    TCGv tmp, tmp2;
25608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
25618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* M profile cores use memory mapped registers instead of cp15.  */
25628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (arm_feature(env, ARM_FEATURE_M))
25638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	return 1;
25648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
25658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if ((insn & (1 << 25)) == 0) {
25668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (insn & (1 << 20)) {
25678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* mrrc */
25688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 1;
25698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
25708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* mcrr.  Used for block cache operations, so implement as no-op.  */
25718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return 0;
25728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
25738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if ((insn & (1 << 4)) == 0) {
25748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* cdp */
25758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return 1;
25768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
257760148dcfccd177ca1dd47fe5292584b44a70df87David 'Digit' Turner    /* We special case a number of cp15 instructions which were used
257860148dcfccd177ca1dd47fe5292584b44a70df87David 'Digit' Turner     * for things which are real instructions in ARMv7. This allows
257960148dcfccd177ca1dd47fe5292584b44a70df87David 'Digit' Turner     * them to work in linux-user mode which doesn't provide functional
258060148dcfccd177ca1dd47fe5292584b44a70df87David 'Digit' Turner     * get_cp15/set_cp15 helpers, and is more efficient anyway.
25815285864985be9077e58e42235af6582dee72e841David 'Digit' Turner     */
258260148dcfccd177ca1dd47fe5292584b44a70df87David 'Digit' Turner    switch ((insn & 0x0fff0fff)) {
258360148dcfccd177ca1dd47fe5292584b44a70df87David 'Digit' Turner    case 0x0e070f90:
25845285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        /* 0,c7,c0,4: Standard v6 WFI (also used in some pre-v6 cores).
25855285864985be9077e58e42235af6582dee72e841David 'Digit' Turner         * In v7, this must NOP.
25865285864985be9077e58e42235af6582dee72e841David 'Digit' Turner         */
258760148dcfccd177ca1dd47fe5292584b44a70df87David 'Digit' Turner        if (IS_USER(s)) {
258860148dcfccd177ca1dd47fe5292584b44a70df87David 'Digit' Turner            return 1;
258960148dcfccd177ca1dd47fe5292584b44a70df87David 'Digit' Turner        }
25905285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        if (!arm_feature(env, ARM_FEATURE_V7)) {
25915285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            /* Wait for interrupt.  */
25925285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            gen_set_pc_im(s->pc);
25935285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            s->is_jmp = DISAS_WFI;
25945285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        }
25958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return 0;
259660148dcfccd177ca1dd47fe5292584b44a70df87David 'Digit' Turner    case 0x0e070f58:
25975285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        /* 0,c7,c8,2: Not all pre-v6 cores implemented this WFI,
25985285864985be9077e58e42235af6582dee72e841David 'Digit' Turner         * so this is slightly over-broad.
25995285864985be9077e58e42235af6582dee72e841David 'Digit' Turner         */
260060148dcfccd177ca1dd47fe5292584b44a70df87David 'Digit' Turner        if (!IS_USER(s) && !arm_feature(env, ARM_FEATURE_V6)) {
26015285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            /* Wait for interrupt.  */
26025285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            gen_set_pc_im(s->pc);
26035285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            s->is_jmp = DISAS_WFI;
26045285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            return 0;
26055285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        }
260660148dcfccd177ca1dd47fe5292584b44a70df87David 'Digit' Turner        /* Otherwise continue to handle via helper function.
26075285864985be9077e58e42235af6582dee72e841David 'Digit' Turner         * In particular, on v7 and some v6 cores this is one of
26085285864985be9077e58e42235af6582dee72e841David 'Digit' Turner         * the VA-PA registers.
26095285864985be9077e58e42235af6582dee72e841David 'Digit' Turner         */
261060148dcfccd177ca1dd47fe5292584b44a70df87David 'Digit' Turner        break;
261160148dcfccd177ca1dd47fe5292584b44a70df87David 'Digit' Turner    case 0x0e070f3d:
261260148dcfccd177ca1dd47fe5292584b44a70df87David 'Digit' Turner        /* 0,c7,c13,1: prefetch-by-MVA in v6, NOP in v7 */
261360148dcfccd177ca1dd47fe5292584b44a70df87David 'Digit' Turner        if (arm_feature(env, ARM_FEATURE_V6)) {
261460148dcfccd177ca1dd47fe5292584b44a70df87David 'Digit' Turner            return IS_USER(s) ? 1 : 0;
261560148dcfccd177ca1dd47fe5292584b44a70df87David 'Digit' Turner        }
261660148dcfccd177ca1dd47fe5292584b44a70df87David 'Digit' Turner        break;
261760148dcfccd177ca1dd47fe5292584b44a70df87David 'Digit' Turner    case 0x0e070f95: /* 0,c7,c5,4 : ISB */
261860148dcfccd177ca1dd47fe5292584b44a70df87David 'Digit' Turner    case 0x0e070f9a: /* 0,c7,c10,4: DSB */
261960148dcfccd177ca1dd47fe5292584b44a70df87David 'Digit' Turner    case 0x0e070fba: /* 0,c7,c10,5: DMB */
262060148dcfccd177ca1dd47fe5292584b44a70df87David 'Digit' Turner        /* Barriers in both v6 and v7 */
262160148dcfccd177ca1dd47fe5292584b44a70df87David 'Digit' Turner        if (arm_feature(env, ARM_FEATURE_V6)) {
262260148dcfccd177ca1dd47fe5292584b44a70df87David 'Digit' Turner            return 0;
262360148dcfccd177ca1dd47fe5292584b44a70df87David 'Digit' Turner        }
262460148dcfccd177ca1dd47fe5292584b44a70df87David 'Digit' Turner        break;
262560148dcfccd177ca1dd47fe5292584b44a70df87David 'Digit' Turner    default:
262660148dcfccd177ca1dd47fe5292584b44a70df87David 'Digit' Turner        break;
262760148dcfccd177ca1dd47fe5292584b44a70df87David 'Digit' Turner    }
262860148dcfccd177ca1dd47fe5292584b44a70df87David 'Digit' Turner
262960148dcfccd177ca1dd47fe5292584b44a70df87David 'Digit' Turner    if (IS_USER(s) && !cp15_user_ok(env, insn)) {
263060148dcfccd177ca1dd47fe5292584b44a70df87David 'Digit' Turner        return 1;
26315285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    }
26325285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
26338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    rd = (insn >> 12) & 0xf;
26345285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
26355285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    if (cp15_tls_load_store(env, s, insn, rd))
26365285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        return 0;
26375285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
26385285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tmp2 = tcg_const_i32(insn);
26398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (insn & ARM_CP_RW_BIT) {
26405285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tmp = tcg_temp_new_i32();
26415285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        gen_helper_get_cp15(tmp, cpu_env, tmp2);
26428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* If the destination register is r15 then sets condition codes.  */
26438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (rd != 15)
26448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            store_reg(s, rd, tmp);
26458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        else
26465285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tcg_temp_free_i32(tmp);
26478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } else {
26488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tmp = load_reg(s, rd);
26495285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        gen_helper_set_cp15(cpu_env, tmp2, tmp);
26505285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tcg_temp_free_i32(tmp);
26518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* Normally we would always end the TB here, but Linux
26528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         * arch/arm/mach-pxa/sleep.S expects two instructions following
26538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         * an MMU enable to execute from cache.  Imitate this behaviour.  */
26548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (!arm_feature(env, ARM_FEATURE_XSCALE) ||
26558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                (insn & 0x0fff0fff) != 0x0e010f10)
26568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            gen_lookup_tb(s);
26578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
26585285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_temp_free_i32(tmp2);
26598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
26608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
26618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
26628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define VFP_REG_SHR(x, n) (((n) > 0) ? (x) >> (n) : (x) << -(n))
26638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define VFP_SREG(insn, bigbit, smallbit) \
26648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project  ((VFP_REG_SHR(insn, bigbit - 1) & 0x1e) | (((insn) >> (smallbit)) & 1))
26658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define VFP_DREG(reg, insn, bigbit, smallbit) do { \
26668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (arm_feature(env, ARM_FEATURE_VFP3)) { \
26678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        reg = (((insn) >> (bigbit)) & 0x0f) \
26688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project              | (((insn) >> ((smallbit) - 4)) & 0x10); \
26698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } else { \
26708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (insn & (1 << (smallbit))) \
26718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 1; \
26728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        reg = ((insn) >> (bigbit)) & 0x0f; \
26738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }} while (0)
26748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
26758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define VFP_SREG_D(insn) VFP_SREG(insn, 12, 22)
26768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define VFP_DREG_D(reg, insn) VFP_DREG(reg, insn, 12, 22)
26778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define VFP_SREG_N(insn) VFP_SREG(insn, 16,  7)
26788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define VFP_DREG_N(reg, insn) VFP_DREG(reg, insn, 16,  7)
26798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define VFP_SREG_M(insn) VFP_SREG(insn,  0,  5)
26808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define VFP_DREG_M(reg, insn) VFP_DREG(reg, insn,  0,  5)
26818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
26828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Move between integer and VFP cores.  */
26838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic TCGv gen_vfp_mrs(void)
26848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
26855285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    TCGv tmp = tcg_temp_new_i32();
26868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_gen_mov_i32(tmp, cpu_F0s);
26878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return tmp;
26888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
26898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
26908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void gen_vfp_msr(TCGv tmp)
26918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
26928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_gen_mov_i32(cpu_F0s, tmp);
26935285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_temp_free_i32(tmp);
26948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
26958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
26968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void gen_neon_dup_u8(TCGv var, int shift)
26978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
26985285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    TCGv tmp = tcg_temp_new_i32();
26998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (shift)
27008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tcg_gen_shri_i32(var, var, shift);
27018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_gen_ext8u_i32(var, var);
27028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_gen_shli_i32(tmp, var, 8);
27038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_gen_or_i32(var, var, tmp);
27048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_gen_shli_i32(tmp, var, 16);
27058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_gen_or_i32(var, var, tmp);
27065285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_temp_free_i32(tmp);
27078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
27088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
27098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void gen_neon_dup_low16(TCGv var)
27108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
27115285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    TCGv tmp = tcg_temp_new_i32();
27128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_gen_ext16u_i32(var, var);
27138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_gen_shli_i32(tmp, var, 16);
27148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_gen_or_i32(var, var, tmp);
27155285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_temp_free_i32(tmp);
27168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
27178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
27188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void gen_neon_dup_high16(TCGv var)
27198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
27205285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    TCGv tmp = tcg_temp_new_i32();
27218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_gen_andi_i32(var, var, 0xffff0000);
27228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_gen_shri_i32(tmp, var, 16);
27238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_gen_or_i32(var, var, tmp);
27245285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_temp_free_i32(tmp);
27255285864985be9077e58e42235af6582dee72e841David 'Digit' Turner}
27265285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
27275285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic TCGv gen_load_and_replicate(DisasContext *s, TCGv addr, int size)
27285285864985be9077e58e42235af6582dee72e841David 'Digit' Turner{
27295285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    /* Load a single Neon element and replicate into a 32 bit TCG reg */
27305285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    TCGv tmp;
27315285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    switch (size) {
27325285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    case 0:
27335285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tmp = gen_ld8u(addr, IS_USER(s));
27345285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        gen_neon_dup_u8(tmp, 0);
27355285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        break;
27365285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    case 1:
27375285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tmp = gen_ld16u(addr, IS_USER(s));
27385285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        gen_neon_dup_low16(tmp);
27395285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        break;
27405285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    case 2:
27415285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tmp = gen_ld32(addr, IS_USER(s));
27425285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        break;
27435285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    default: /* Avoid compiler warnings.  */
27445285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        abort();
27455285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    }
27465285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    return tmp;
27478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
27488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
27495285864985be9077e58e42235af6582dee72e841David 'Digit' Turner/* Disassemble a VFP instruction.  Returns nonzero if an error occurred
27508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   (ie. an undefined instruction).  */
2751e2678e116c8cdb0f36b247a5bd9cfacc849362fcDavid 'Digit' Turnerstatic int disas_vfp_insn(CPUARMState * env, DisasContext *s, uint32_t insn)
27528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
27538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    uint32_t rd, rn, rm, op, i, n, offset, delta_d, delta_m, bank_mask;
27548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int dp, veclen;
27555285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    TCGv addr;
27568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    TCGv tmp;
27578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    TCGv tmp2;
27588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
27598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!arm_feature(env, ARM_FEATURE_VFP))
27608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return 1;
27618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
27625285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    if (!s->vfp_enabled) {
27638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* VFP disabled.  Only allow fmxr/fmrx to/from some control regs.  */
27648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if ((insn & 0x0fe00fff) != 0x0ee00a10)
27658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 1;
27668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        rn = (insn >> 16) & 0xf;
27678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (rn != ARM_VFP_FPSID && rn != ARM_VFP_FPEXC
27688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            && rn != ARM_VFP_MVFR1 && rn != ARM_VFP_MVFR0)
27698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 1;
27708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
27718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    dp = ((insn & 0xf00) == 0xb00);
27728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    switch ((insn >> 24) & 0xf) {
27738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0xe:
27748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (insn & (1 << 4)) {
27758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* single register transfer */
27768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            rd = (insn >> 12) & 0xf;
27778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (dp) {
27788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                int size;
27798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                int pass;
27808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
27818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                VFP_DREG_N(rn, insn);
27828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (insn & 0xf)
27838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    return 1;
27848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (insn & 0x00c00060
27858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    && !arm_feature(env, ARM_FEATURE_NEON))
27868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    return 1;
27878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
27888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                pass = (insn >> 21) & 1;
27898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (insn & (1 << 22)) {
27908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    size = 0;
27918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    offset = ((insn >> 5) & 3) * 8;
27928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                } else if (insn & (1 << 5)) {
27938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    size = 1;
27948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    offset = (insn & (1 << 6)) ? 16 : 0;
27958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                } else {
27968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    size = 2;
27978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    offset = 0;
27988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
27998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (insn & ARM_CP_RW_BIT) {
28008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    /* vfp->arm */
28018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    tmp = neon_load_reg(rn, pass);
28028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    switch (size) {
28038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    case 0:
28048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        if (offset)
28058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            tcg_gen_shri_i32(tmp, tmp, offset);
28068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        if (insn & (1 << 23))
28078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            gen_uxtb(tmp);
28088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        else
28098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            gen_sxtb(tmp);
28108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        break;
28118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    case 1:
28128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        if (insn & (1 << 23)) {
28138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            if (offset) {
28148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                tcg_gen_shri_i32(tmp, tmp, 16);
28158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            } else {
28168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                gen_uxth(tmp);
28178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            }
28188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        } else {
28198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            if (offset) {
28208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                tcg_gen_sari_i32(tmp, tmp, 16);
28218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            } else {
28228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                gen_sxth(tmp);
28238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            }
28248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        }
28258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        break;
28268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    case 2:
28278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        break;
28288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
28298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    store_reg(s, rd, tmp);
28308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                } else {
28318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    /* arm->vfp */
28328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    tmp = load_reg(s, rd);
28338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if (insn & (1 << 23)) {
28348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        /* VDUP */
28358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        if (size == 0) {
28368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            gen_neon_dup_u8(tmp, 0);
28378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        } else if (size == 1) {
28388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            gen_neon_dup_low16(tmp);
28398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        }
28405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                        for (n = 0; n <= pass * 2; n++) {
28415285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            tmp2 = tcg_temp_new_i32();
28425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                            tcg_gen_mov_i32(tmp2, tmp);
28435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                            neon_store_reg(rn, n, tmp2);
28445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                        }
28455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                        neon_store_reg(rn, n, tmp);
28468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    } else {
28478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        /* VMOV */
28488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        switch (size) {
28498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        case 0:
28508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            tmp2 = neon_load_reg(rn, pass);
28518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            gen_bfi(tmp, tmp2, tmp, offset, 0xff);
28525285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            tcg_temp_free_i32(tmp2);
28538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            break;
28548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        case 1:
28558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            tmp2 = neon_load_reg(rn, pass);
28568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            gen_bfi(tmp, tmp2, tmp, offset, 0xffff);
28575285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            tcg_temp_free_i32(tmp2);
28588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            break;
28598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        case 2:
28608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            break;
28618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        }
28628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        neon_store_reg(rn, pass, tmp);
28638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
28648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
28658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            } else { /* !dp */
28668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if ((insn & 0x6f) != 0x00)
28678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    return 1;
28688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                rn = VFP_SREG_N(insn);
28698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (insn & ARM_CP_RW_BIT) {
28708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    /* vfp->arm */
28718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if (insn & (1 << 21)) {
28728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        /* system register */
28738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        rn >>= 1;
28748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
28758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        switch (rn) {
28768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        case ARM_VFP_FPSID:
28778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            /* VFP2 allows access to FSID from userspace.
28788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                               VFP3 restricts all id registers to privileged
28798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                               accesses.  */
28808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            if (IS_USER(s)
28818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                && arm_feature(env, ARM_FEATURE_VFP3))
28828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                return 1;
28838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            tmp = load_cpu_field(vfp.xregs[rn]);
28848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            break;
28858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        case ARM_VFP_FPEXC:
28868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            if (IS_USER(s))
28878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                return 1;
28888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            tmp = load_cpu_field(vfp.xregs[rn]);
28898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            break;
28908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        case ARM_VFP_FPINST:
28918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        case ARM_VFP_FPINST2:
28928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            /* Not present in VFP3.  */
28938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            if (IS_USER(s)
28948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                || arm_feature(env, ARM_FEATURE_VFP3))
28958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                return 1;
28968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            tmp = load_cpu_field(vfp.xregs[rn]);
28978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            break;
28988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        case ARM_VFP_FPSCR:
28998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            if (rd == 15) {
29008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                tmp = load_cpu_field(vfp.xregs[ARM_VFP_FPSCR]);
29018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                tcg_gen_andi_i32(tmp, tmp, 0xf0000000);
29028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            } else {
29035285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                                tmp = tcg_temp_new_i32();
29048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                gen_helper_vfp_get_fpscr(tmp, cpu_env);
29058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            }
29068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            break;
29078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        case ARM_VFP_MVFR0:
29088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        case ARM_VFP_MVFR1:
29098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            if (IS_USER(s)
29108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                || !arm_feature(env, ARM_FEATURE_VFP3))
29118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                return 1;
29128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            tmp = load_cpu_field(vfp.xregs[rn]);
29138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            break;
29148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        default:
29158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            return 1;
29168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        }
29178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    } else {
29188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        gen_mov_F0_vreg(0, rn);
29198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        tmp = gen_vfp_mrs();
29208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
29218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if (rd == 15) {
29228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        /* Set the 4 flag bits in the CPSR.  */
29238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        gen_set_nzcv(tmp);
29245285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tcg_temp_free_i32(tmp);
29258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    } else {
29268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        store_reg(s, rd, tmp);
29278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
29288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                } else {
29298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    /* arm->vfp */
29308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    tmp = load_reg(s, rd);
29318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if (insn & (1 << 21)) {
29328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        rn >>= 1;
29338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        /* system register */
29348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        switch (rn) {
29358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        case ARM_VFP_FPSID:
29368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        case ARM_VFP_MVFR0:
29378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        case ARM_VFP_MVFR1:
29388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            /* Writes are ignored.  */
29398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            break;
29408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        case ARM_VFP_FPSCR:
29418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            gen_helper_vfp_set_fpscr(cpu_env, tmp);
29425285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            tcg_temp_free_i32(tmp);
29438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            gen_lookup_tb(s);
29448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            break;
29458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        case ARM_VFP_FPEXC:
29468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            if (IS_USER(s))
29478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                return 1;
29485285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            /* TODO: VFP subarchitecture support.
29495285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                             * For now, keep the EN bit only */
29505285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            tcg_gen_andi_i32(tmp, tmp, 1 << 30);
29518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            store_cpu_field(tmp, vfp.xregs[rn]);
29528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            gen_lookup_tb(s);
29538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            break;
29548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        case ARM_VFP_FPINST:
29558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        case ARM_VFP_FPINST2:
29568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            store_cpu_field(tmp, vfp.xregs[rn]);
29578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            break;
29588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        default:
29598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            return 1;
29608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        }
29618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    } else {
29628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        gen_vfp_msr(tmp);
29638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        gen_mov_vreg_F0(0, rn);
29648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
29658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
29668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
29678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        } else {
29688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* data processing */
29698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* The opcode is in bits 23, 21, 20 and 6.  */
29708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            op = ((insn >> 20) & 8) | ((insn >> 19) & 6) | ((insn >> 6) & 1);
29718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (dp) {
29728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (op == 15) {
29738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    /* rn is opcode */
29748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    rn = ((insn >> 15) & 0x1e) | ((insn >> 7) & 1);
29758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                } else {
29768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    /* rn is register number */
29778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    VFP_DREG_N(rn, insn);
29788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
29798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
29805285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                if (op == 15 && (rn == 15 || ((rn & 0x1c) == 0x18))) {
29818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    /* Integer or single precision destination.  */
29828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    rd = VFP_SREG_D(insn);
29838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                } else {
29848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    VFP_DREG_D(rd, insn);
29858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
29865285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                if (op == 15 &&
29875285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    (((rn & 0x1c) == 0x10) || ((rn & 0x14) == 0x14))) {
29885285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    /* VCVT from int is always from S reg regardless of dp bit.
29895285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                     * VCVT with immediate frac_bits has same format as SREG_M
29905285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                     */
29915285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    rm = VFP_SREG_M(insn);
29928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                } else {
29938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    VFP_DREG_M(rm, insn);
29948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
29958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            } else {
29968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                rn = VFP_SREG_N(insn);
29978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (op == 15 && rn == 15) {
29988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    /* Double precision destination.  */
29998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    VFP_DREG_D(rd, insn);
30008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                } else {
30018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    rd = VFP_SREG_D(insn);
30028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
30035285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                /* NB that we implicitly rely on the encoding for the frac_bits
30045285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                 * in VCVT of fixed to float being the same as that of an SREG_M
30055285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                 */
30068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                rm = VFP_SREG_M(insn);
30078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
30088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
30095285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            veclen = s->vec_len;
30108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (op == 15 && rn > 3)
30118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                veclen = 0;
30128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
30138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* Shut up compiler warnings.  */
30148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            delta_m = 0;
30158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            delta_d = 0;
30168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            bank_mask = 0;
30178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
30188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (veclen > 0) {
30198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (dp)
30208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    bank_mask = 0xc;
30218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                else
30228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    bank_mask = 0x18;
30238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
30248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* Figure out what type of vector operation this is.  */
30258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if ((rd & bank_mask) == 0) {
30268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    /* scalar */
30278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    veclen = 0;
30288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                } else {
30298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if (dp)
30305285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        delta_d = (s->vec_stride >> 1) + 1;
30318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    else
30325285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        delta_d = s->vec_stride + 1;
30338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
30348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if ((rm & bank_mask) == 0) {
30358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        /* mixed scalar/vector */
30368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        delta_m = 0;
30378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    } else {
30388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        /* vector */
30398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        delta_m = delta_d;
30408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
30418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
30428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
30438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
30448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* Load the initial operands.  */
30458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (op == 15) {
30468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                switch (rn) {
30478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                case 16:
30488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                case 17:
30498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    /* Integer source */
30508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    gen_mov_F0_vreg(0, rm);
30518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    break;
30528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                case 8:
30538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                case 9:
30548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    /* Compare */
30558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    gen_mov_F0_vreg(dp, rd);
30568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    gen_mov_F1_vreg(dp, rm);
30578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    break;
30588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                case 10:
30598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                case 11:
30608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    /* Compare with zero */
30618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    gen_mov_F0_vreg(dp, rd);
30628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    gen_vfp_F1_ld0(dp);
30638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    break;
30648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                case 20:
30658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                case 21:
30668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                case 22:
30678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                case 23:
30685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                case 28:
30695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                case 29:
30705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                case 30:
30715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                case 31:
30728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    /* Source and destination the same.  */
30738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    gen_mov_F0_vreg(dp, rd);
30748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    break;
3075cf2ea59d58aa0a4eefd75827ce9c9cc6b718f65bDavid 'Digit' Turner                case 4:
3076cf2ea59d58aa0a4eefd75827ce9c9cc6b718f65bDavid 'Digit' Turner                case 5:
3077cf2ea59d58aa0a4eefd75827ce9c9cc6b718f65bDavid 'Digit' Turner                case 6:
3078cf2ea59d58aa0a4eefd75827ce9c9cc6b718f65bDavid 'Digit' Turner                case 7:
3079cf2ea59d58aa0a4eefd75827ce9c9cc6b718f65bDavid 'Digit' Turner                    /* VCVTB, VCVTT: only present with the halfprec extension,
3080cf2ea59d58aa0a4eefd75827ce9c9cc6b718f65bDavid 'Digit' Turner                     * UNPREDICTABLE if bit 8 is set (we choose to UNDEF)
3081cf2ea59d58aa0a4eefd75827ce9c9cc6b718f65bDavid 'Digit' Turner                     */
3082cf2ea59d58aa0a4eefd75827ce9c9cc6b718f65bDavid 'Digit' Turner                    if (dp || !arm_feature(env, ARM_FEATURE_VFP_FP16)) {
3083cf2ea59d58aa0a4eefd75827ce9c9cc6b718f65bDavid 'Digit' Turner                        return 1;
3084cf2ea59d58aa0a4eefd75827ce9c9cc6b718f65bDavid 'Digit' Turner                    }
3085cf2ea59d58aa0a4eefd75827ce9c9cc6b718f65bDavid 'Digit' Turner                    /* Otherwise fall through */
30868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                default:
30878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    /* One source operand.  */
30888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    gen_mov_F0_vreg(dp, rm);
30898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    break;
30908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
30918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            } else {
30928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* Two source operands.  */
30938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                gen_mov_F0_vreg(dp, rn);
30948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                gen_mov_F1_vreg(dp, rm);
30958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
30968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
30978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            for (;;) {
30988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* Perform the calculation.  */
30998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                switch (op) {
31005285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                case 0: /* VMLA: fd + (fn * fm) */
31015285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    /* Note that order of inputs to the add matters for NaNs */
31025285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    gen_vfp_F1_mul(dp);
31035285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    gen_mov_F0_vreg(dp, rd);
31048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    gen_vfp_add(dp);
31058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    break;
31065285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                case 1: /* VMLS: fd + -(fn * fm) */
31078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    gen_vfp_mul(dp);
31085285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    gen_vfp_F1_neg(dp);
31095285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    gen_mov_F0_vreg(dp, rd);
31108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    gen_vfp_add(dp);
31118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    break;
31125285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                case 2: /* VNMLS: -fd + (fn * fm) */
31135285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    /* Note that it isn't valid to replace (-A + B) with (B - A)
31145285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                     * or similar plausible looking simplifications
31155285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                     * because this will give wrong results for NaNs.
31165285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                     */
31175285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    gen_vfp_F1_mul(dp);
31185285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    gen_mov_F0_vreg(dp, rd);
31195285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    gen_vfp_neg(dp);
31205285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    gen_vfp_add(dp);
31218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    break;
31225285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                case 3: /* VNMLA: -fd + -(fn * fm) */
31238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    gen_vfp_mul(dp);
31245285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    gen_vfp_F1_neg(dp);
31255285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    gen_mov_F0_vreg(dp, rd);
31268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    gen_vfp_neg(dp);
31275285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    gen_vfp_add(dp);
31288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    break;
31298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                case 4: /* mul: fn * fm */
31308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    gen_vfp_mul(dp);
31318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    break;
31328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                case 5: /* nmul: -(fn * fm) */
31338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    gen_vfp_mul(dp);
31348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    gen_vfp_neg(dp);
31358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    break;
31368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                case 6: /* add: fn + fm */
31378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    gen_vfp_add(dp);
31388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    break;
31398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                case 7: /* sub: fn - fm */
31408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    gen_vfp_sub(dp);
31418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    break;
31428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                case 8: /* div: fn / fm */
31438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    gen_vfp_div(dp);
31448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    break;
31458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                case 14: /* fconst */
31468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if (!arm_feature(env, ARM_FEATURE_VFP3))
31478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                      return 1;
31488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
31498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    n = (insn << 12) & 0x80000000;
31508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    i = ((insn >> 12) & 0x70) | (insn & 0xf);
31518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if (dp) {
31528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        if (i & 0x40)
31538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            i |= 0x3f80;
31548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        else
31558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            i |= 0x4000;
31568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        n |= i << 16;
31578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        tcg_gen_movi_i64(cpu_F0d, ((uint64_t)n) << 32);
31588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    } else {
31598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        if (i & 0x40)
31608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            i |= 0x780;
31618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        else
31628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            i |= 0x800;
31638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        n |= i << 19;
31648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        tcg_gen_movi_i32(cpu_F0s, n);
31658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
31668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    break;
31678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                case 15: /* extension space */
31688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    switch (rn) {
31698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    case 0: /* cpy */
31708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        /* no-op */
31718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        break;
31728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    case 1: /* abs */
31738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        gen_vfp_abs(dp);
31748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        break;
31758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    case 2: /* neg */
31768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        gen_vfp_neg(dp);
31778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        break;
31788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    case 3: /* sqrt */
31798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        gen_vfp_sqrt(dp);
31808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        break;
31815285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    case 4: /* vcvtb.f32.f16 */
31825285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tmp = gen_vfp_mrs();
31835285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tcg_gen_ext16u_i32(tmp, tmp);
31845285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s, tmp, cpu_env);
31855285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tcg_temp_free_i32(tmp);
31865285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        break;
31875285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    case 5: /* vcvtt.f32.f16 */
31885285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tmp = gen_vfp_mrs();
31895285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tcg_gen_shri_i32(tmp, tmp, 16);
31905285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s, tmp, cpu_env);
31915285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tcg_temp_free_i32(tmp);
31925285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        break;
31935285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    case 6: /* vcvtb.f16.f32 */
31945285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tmp = tcg_temp_new_i32();
31955285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        gen_helper_vfp_fcvt_f32_to_f16(tmp, cpu_F0s, cpu_env);
31965285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        gen_mov_F0_vreg(0, rd);
31975285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tmp2 = gen_vfp_mrs();
31985285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tcg_gen_andi_i32(tmp2, tmp2, 0xffff0000);
31995285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tcg_gen_or_i32(tmp, tmp, tmp2);
32005285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tcg_temp_free_i32(tmp2);
32015285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        gen_vfp_msr(tmp);
32025285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        break;
32035285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    case 7: /* vcvtt.f16.f32 */
32045285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tmp = tcg_temp_new_i32();
32055285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        gen_helper_vfp_fcvt_f32_to_f16(tmp, cpu_F0s, cpu_env);
32065285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tcg_gen_shli_i32(tmp, tmp, 16);
32075285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        gen_mov_F0_vreg(0, rd);
32085285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tmp2 = gen_vfp_mrs();
32095285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tcg_gen_ext16u_i32(tmp2, tmp2);
32105285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tcg_gen_or_i32(tmp, tmp, tmp2);
32115285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tcg_temp_free_i32(tmp2);
32125285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        gen_vfp_msr(tmp);
32135285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        break;
32148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    case 8: /* cmp */
32158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        gen_vfp_cmp(dp);
32168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        break;
32178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    case 9: /* cmpe */
32188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        gen_vfp_cmpe(dp);
32198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        break;
32208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    case 10: /* cmpz */
32218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        gen_vfp_cmp(dp);
32228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        break;
32238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    case 11: /* cmpez */
32248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        gen_vfp_F1_ld0(dp);
32258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        gen_vfp_cmpe(dp);
32268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        break;
32278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    case 15: /* single<->double conversion */
32288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        if (dp)
32298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            gen_helper_vfp_fcvtsd(cpu_F0s, cpu_F0d, cpu_env);
32308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        else
32318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            gen_helper_vfp_fcvtds(cpu_F0d, cpu_F0s, cpu_env);
32328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        break;
32338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    case 16: /* fuito */
32345285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        gen_vfp_uito(dp, 0);
32358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        break;
32368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    case 17: /* fsito */
32375285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        gen_vfp_sito(dp, 0);
32388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        break;
32398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    case 20: /* fshto */
32408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        if (!arm_feature(env, ARM_FEATURE_VFP3))
32418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                          return 1;
32425285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        gen_vfp_shto(dp, 16 - rm, 0);
32438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        break;
32448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    case 21: /* fslto */
32458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        if (!arm_feature(env, ARM_FEATURE_VFP3))
32468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                          return 1;
32475285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        gen_vfp_slto(dp, 32 - rm, 0);
32488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        break;
32498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    case 22: /* fuhto */
32508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        if (!arm_feature(env, ARM_FEATURE_VFP3))
32518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                          return 1;
32525285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        gen_vfp_uhto(dp, 16 - rm, 0);
32538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        break;
32548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    case 23: /* fulto */
32558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        if (!arm_feature(env, ARM_FEATURE_VFP3))
32568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                          return 1;
32575285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        gen_vfp_ulto(dp, 32 - rm, 0);
32588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        break;
32598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    case 24: /* ftoui */
32605285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        gen_vfp_toui(dp, 0);
32618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        break;
32628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    case 25: /* ftouiz */
32635285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        gen_vfp_touiz(dp, 0);
32648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        break;
32658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    case 26: /* ftosi */
32665285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        gen_vfp_tosi(dp, 0);
32678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        break;
32688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    case 27: /* ftosiz */
32695285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        gen_vfp_tosiz(dp, 0);
32708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        break;
32718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    case 28: /* ftosh */
32728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        if (!arm_feature(env, ARM_FEATURE_VFP3))
32738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                          return 1;
32745285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        gen_vfp_tosh(dp, 16 - rm, 0);
32758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        break;
32768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    case 29: /* ftosl */
32778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        if (!arm_feature(env, ARM_FEATURE_VFP3))
32788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                          return 1;
32795285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        gen_vfp_tosl(dp, 32 - rm, 0);
32808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        break;
32818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    case 30: /* ftouh */
32828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        if (!arm_feature(env, ARM_FEATURE_VFP3))
32838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                          return 1;
32845285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        gen_vfp_touh(dp, 16 - rm, 0);
32858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        break;
32868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    case 31: /* ftoul */
32878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        if (!arm_feature(env, ARM_FEATURE_VFP3))
32888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                          return 1;
32895285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        gen_vfp_toul(dp, 32 - rm, 0);
32908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        break;
32918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    default: /* undefined */
32928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        printf ("rn:%d\n", rn);
32938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        return 1;
32948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
32958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    break;
32968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                default: /* undefined */
32978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    printf ("op:%d\n", op);
32988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    return 1;
32998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
33008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
33018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* Write back the result.  */
33028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (op == 15 && (rn >= 8 && rn <= 11))
33038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    ; /* Comparison, do nothing.  */
33045285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                else if (op == 15 && dp && ((rn & 0x1c) == 0x18))
33055285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    /* VCVT double to int: always integer result. */
33068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    gen_mov_vreg_F0(0, rd);
33078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                else if (op == 15 && rn == 15)
33088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    /* conversion */
33098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    gen_mov_vreg_F0(!dp, rd);
33108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                else
33118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    gen_mov_vreg_F0(dp, rd);
33128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
33138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* break out of the loop if we have finished  */
33148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (veclen == 0)
33158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    break;
33168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
33178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (op == 15 && delta_m == 0) {
33188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    /* single source one-many */
33198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    while (veclen--) {
33208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        rd = ((rd + delta_d) & (bank_mask - 1))
33218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                             | (rd & bank_mask);
33228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        gen_mov_vreg_F0(dp, rd);
33238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
33248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    break;
33258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
33268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* Setup the next operands.  */
33278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                veclen--;
33288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                rd = ((rd + delta_d) & (bank_mask - 1))
33298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                     | (rd & bank_mask);
33308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
33318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (op == 15) {
33328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    /* One source operand.  */
33338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    rm = ((rm + delta_m) & (bank_mask - 1))
33348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                         | (rm & bank_mask);
33358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    gen_mov_F0_vreg(dp, rm);
33368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                } else {
33378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    /* Two source operands.  */
33388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    rn = ((rn + delta_d) & (bank_mask - 1))
33398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                         | (rn & bank_mask);
33408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    gen_mov_F0_vreg(dp, rn);
33418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if (delta_m) {
33428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        rm = ((rm + delta_m) & (bank_mask - 1))
33438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                             | (rm & bank_mask);
33448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        gen_mov_F1_vreg(dp, rm);
33458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
33468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
33478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
33488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
33498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
33508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0xc:
33518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0xd:
33525285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        if ((insn & 0x03e00000) == 0x00400000) {
33538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* two-register transfer */
33548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            rn = (insn >> 16) & 0xf;
33558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            rd = (insn >> 12) & 0xf;
33568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (dp) {
33578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                VFP_DREG_M(rm, insn);
33588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            } else {
33598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                rm = VFP_SREG_M(insn);
33608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
33618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
33628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (insn & ARM_CP_RW_BIT) {
33638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* vfp->arm */
33648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (dp) {
33658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    gen_mov_F0_vreg(0, rm * 2);
33668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    tmp = gen_vfp_mrs();
33678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    store_reg(s, rd, tmp);
33688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    gen_mov_F0_vreg(0, rm * 2 + 1);
33698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    tmp = gen_vfp_mrs();
33708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    store_reg(s, rn, tmp);
33718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                } else {
33728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    gen_mov_F0_vreg(0, rm);
33738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    tmp = gen_vfp_mrs();
33745285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    store_reg(s, rd, tmp);
33758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    gen_mov_F0_vreg(0, rm + 1);
33768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    tmp = gen_vfp_mrs();
33775285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    store_reg(s, rn, tmp);
33788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
33798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            } else {
33808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* arm->vfp */
33818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (dp) {
33828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    tmp = load_reg(s, rd);
33838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    gen_vfp_msr(tmp);
33848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    gen_mov_vreg_F0(0, rm * 2);
33858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    tmp = load_reg(s, rn);
33868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    gen_vfp_msr(tmp);
33878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    gen_mov_vreg_F0(0, rm * 2 + 1);
33888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                } else {
33895285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tmp = load_reg(s, rd);
33908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    gen_vfp_msr(tmp);
33918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    gen_mov_vreg_F0(0, rm);
33925285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tmp = load_reg(s, rn);
33938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    gen_vfp_msr(tmp);
33948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    gen_mov_vreg_F0(0, rm + 1);
33958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
33968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
33978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        } else {
33988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* Load/store */
33998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            rn = (insn >> 16) & 0xf;
34008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (dp)
34018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                VFP_DREG_D(rd, insn);
34028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            else
34038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                rd = VFP_SREG_D(insn);
34048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if ((insn & 0x01200000) == 0x01000000) {
34058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* Single load/store */
34068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                offset = (insn & 0xff) << 2;
34078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if ((insn & (1 << 23)) == 0)
34088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    offset = -offset;
340997c98d3448da9d3fad00545063fb6cd2d2980accDavid 'Digit' Turner                if (s->thumb && rn == 15) {
341097c98d3448da9d3fad00545063fb6cd2d2980accDavid 'Digit' Turner                    /* This is actually UNPREDICTABLE */
341197c98d3448da9d3fad00545063fb6cd2d2980accDavid 'Digit' Turner                    addr = tcg_temp_new_i32();
341297c98d3448da9d3fad00545063fb6cd2d2980accDavid 'Digit' Turner                    tcg_gen_movi_i32(addr, s->pc & ~2);
341397c98d3448da9d3fad00545063fb6cd2d2980accDavid 'Digit' Turner                } else {
341497c98d3448da9d3fad00545063fb6cd2d2980accDavid 'Digit' Turner                    addr = load_reg(s, rn);
341597c98d3448da9d3fad00545063fb6cd2d2980accDavid 'Digit' Turner                }
34165285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_gen_addi_i32(addr, addr, offset);
34178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (insn & (1 << 20)) {
34185285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    gen_vfp_ld(s, dp, addr);
34198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    gen_mov_vreg_F0(dp, rd);
34208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                } else {
34218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    gen_mov_F0_vreg(dp, rd);
34225285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    gen_vfp_st(s, dp, addr);
34238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
34245285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_temp_free_i32(addr);
34258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            } else {
34268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* load/store multiple */
342797c98d3448da9d3fad00545063fb6cd2d2980accDavid 'Digit' Turner                int w = insn & (1 << 21);
34288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (dp)
34298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    n = (insn >> 1) & 0x7f;
34308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                else
34318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    n = insn & 0xff;
34328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
343397c98d3448da9d3fad00545063fb6cd2d2980accDavid 'Digit' Turner                if (w && !(((insn >> 23) ^ (insn >> 24)) & 1)) {
343497c98d3448da9d3fad00545063fb6cd2d2980accDavid 'Digit' Turner                    /* P == U , W == 1  => UNDEF */
343597c98d3448da9d3fad00545063fb6cd2d2980accDavid 'Digit' Turner                    return 1;
343697c98d3448da9d3fad00545063fb6cd2d2980accDavid 'Digit' Turner                }
343797c98d3448da9d3fad00545063fb6cd2d2980accDavid 'Digit' Turner                if (n == 0 || (rd + n) > 32 || (dp && n > 16)) {
343897c98d3448da9d3fad00545063fb6cd2d2980accDavid 'Digit' Turner                    /* UNPREDICTABLE cases for bad immediates: we choose to
343997c98d3448da9d3fad00545063fb6cd2d2980accDavid 'Digit' Turner                     * UNDEF to avoid generating huge numbers of TCG ops
344097c98d3448da9d3fad00545063fb6cd2d2980accDavid 'Digit' Turner                     */
344197c98d3448da9d3fad00545063fb6cd2d2980accDavid 'Digit' Turner                    return 1;
344297c98d3448da9d3fad00545063fb6cd2d2980accDavid 'Digit' Turner                }
344397c98d3448da9d3fad00545063fb6cd2d2980accDavid 'Digit' Turner                if (rn == 15 && w) {
344497c98d3448da9d3fad00545063fb6cd2d2980accDavid 'Digit' Turner                    /* writeback to PC is UNPREDICTABLE, we choose to UNDEF */
344597c98d3448da9d3fad00545063fb6cd2d2980accDavid 'Digit' Turner                    return 1;
344697c98d3448da9d3fad00545063fb6cd2d2980accDavid 'Digit' Turner                }
344797c98d3448da9d3fad00545063fb6cd2d2980accDavid 'Digit' Turner
344897c98d3448da9d3fad00545063fb6cd2d2980accDavid 'Digit' Turner                if (s->thumb && rn == 15) {
344997c98d3448da9d3fad00545063fb6cd2d2980accDavid 'Digit' Turner                    /* This is actually UNPREDICTABLE */
345097c98d3448da9d3fad00545063fb6cd2d2980accDavid 'Digit' Turner                    addr = tcg_temp_new_i32();
345197c98d3448da9d3fad00545063fb6cd2d2980accDavid 'Digit' Turner                    tcg_gen_movi_i32(addr, s->pc & ~2);
345297c98d3448da9d3fad00545063fb6cd2d2980accDavid 'Digit' Turner                } else {
345397c98d3448da9d3fad00545063fb6cd2d2980accDavid 'Digit' Turner                    addr = load_reg(s, rn);
345497c98d3448da9d3fad00545063fb6cd2d2980accDavid 'Digit' Turner                }
34558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (insn & (1 << 24)) /* pre-decrement */
34565285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tcg_gen_addi_i32(addr, addr, -((insn & 0xff) << 2));
34578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
34588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (dp)
34598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    offset = 8;
34608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                else
34618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    offset = 4;
34625285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tmp = tcg_const_i32(offset);
34638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                for (i = 0; i < n; i++) {
34648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if (insn & ARM_CP_RW_BIT) {
34658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        /* load */
34665285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        gen_vfp_ld(s, dp, addr);
34678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        gen_mov_vreg_F0(dp, rd + i);
34688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    } else {
34698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        /* store */
34708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        gen_mov_F0_vreg(dp, rd + i);
34715285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        gen_vfp_st(s, dp, addr);
34728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
34735285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tcg_gen_add_i32(addr, addr, tmp);
34748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
34755285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_temp_free_i32(tmp);
347697c98d3448da9d3fad00545063fb6cd2d2980accDavid 'Digit' Turner                if (w) {
34778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    /* writeback */
34788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if (insn & (1 << 24))
34798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        offset = -offset * n;
34808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    else if (dp && (insn & 1))
34818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        offset = 4;
34828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    else
34838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        offset = 0;
34848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
34858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if (offset != 0)
34865285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tcg_gen_addi_i32(addr, addr, offset);
34875285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    store_reg(s, rn, addr);
34885285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                } else {
34895285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tcg_temp_free_i32(addr);
34908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
34918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
34928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
34938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
34948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    default:
34958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* Should never happen.  */
34968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return 1;
34978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
34988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
34998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
35008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
35018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline void gen_goto_tb(DisasContext *s, int n, uint32_t dest)
35028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
35038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    TranslationBlock *tb;
35048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
35058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tb = s->tb;
35068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)) {
35078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tcg_gen_goto_tb(n);
35088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_set_pc_im(dest);
35095285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tcg_gen_exit_tb((tcg_target_long)tb + n);
35108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } else {
35118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_set_pc_im(dest);
35128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tcg_gen_exit_tb(0);
35138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
35148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
35158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
35168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline void gen_jmp (DisasContext *s, uint32_t dest)
35178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
35188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (unlikely(s->singlestep_enabled)) {
35198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* An indirect jump so that we still trigger the debug exception.  */
35208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (s->thumb)
35218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            dest |= 1;
35228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_bx_im(s, dest);
35238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } else {
35248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_goto_tb(s, 0, dest);
35258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        s->is_jmp = DISAS_TB_JUMP;
35268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
35278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
35288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
35298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline void gen_mulxy(TCGv t0, TCGv t1, int x, int y)
35308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
35318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (x)
35328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tcg_gen_sari_i32(t0, t0, 16);
35338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    else
35348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_sxth(t0);
35358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (y)
35368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tcg_gen_sari_i32(t1, t1, 16);
35378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    else
35388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_sxth(t1);
35398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_gen_mul_i32(t0, t0, t1);
35408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
35418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
35428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Return the mask of PSR bits set by a MSR instruction.  */
3543e2678e116c8cdb0f36b247a5bd9cfacc849362fcDavid 'Digit' Turnerstatic uint32_t msr_mask(CPUARMState *env, DisasContext *s, int flags, int spsr) {
35448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    uint32_t mask;
35458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
35468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    mask = 0;
35478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (flags & (1 << 0))
35488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        mask |= 0xff;
35498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (flags & (1 << 1))
35508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        mask |= 0xff00;
35518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (flags & (1 << 2))
35528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        mask |= 0xff0000;
35538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (flags & (1 << 3))
35548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        mask |= 0xff000000;
35558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
35568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* Mask out undefined bits.  */
35578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    mask &= ~CPSR_RESERVED;
35585285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    if (!arm_feature(env, ARM_FEATURE_V4T))
35595285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        mask &= ~CPSR_T;
35605285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    if (!arm_feature(env, ARM_FEATURE_V5))
35615285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        mask &= ~CPSR_Q; /* V5TE in reality*/
35628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!arm_feature(env, ARM_FEATURE_V6))
35638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        mask &= ~(CPSR_E | CPSR_GE);
35648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!arm_feature(env, ARM_FEATURE_THUMB2))
35658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        mask &= ~CPSR_IT;
35668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* Mask out execution state bits.  */
35678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!spsr)
35688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        mask &= ~CPSR_EXEC;
35698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* Mask out privileged bits.  */
35708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (IS_USER(s))
35718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        mask &= CPSR_USER;
35728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return mask;
35738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
35748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
35755285864985be9077e58e42235af6582dee72e841David 'Digit' Turner/* Returns nonzero if access to the PSR is not permitted. Marks t0 as dead. */
35765285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic int gen_set_psr(DisasContext *s, uint32_t mask, int spsr, TCGv t0)
35778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
35788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    TCGv tmp;
35798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (spsr) {
35808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* ??? This is also undefined in system mode.  */
35818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (IS_USER(s))
35828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 1;
35838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
35848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tmp = load_cpu_field(spsr);
35858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tcg_gen_andi_i32(tmp, tmp, ~mask);
35865285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tcg_gen_andi_i32(t0, t0, mask);
35875285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tcg_gen_or_i32(tmp, tmp, t0);
35888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        store_cpu_field(tmp, spsr);
35898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } else {
35905285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        gen_set_cpsr(t0, mask);
35918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
35925285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_temp_free_i32(t0);
35938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    gen_lookup_tb(s);
35948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
35958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
35968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
35975285864985be9077e58e42235af6582dee72e841David 'Digit' Turner/* Returns nonzero if access to the PSR is not permitted.  */
35985285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic int gen_set_psr_im(DisasContext *s, uint32_t mask, int spsr, uint32_t val)
35995285864985be9077e58e42235af6582dee72e841David 'Digit' Turner{
36005285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    TCGv tmp;
36015285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tmp = tcg_temp_new_i32();
36025285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_gen_movi_i32(tmp, val);
36035285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    return gen_set_psr(s, mask, spsr, tmp);
36045285864985be9077e58e42235af6582dee72e841David 'Digit' Turner}
36055285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
36065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner/* Generate an old-style exception return. Marks pc as dead. */
36075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void gen_exception_return(DisasContext *s, TCGv pc)
36088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
36098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    TCGv tmp;
36105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    store_reg(s, 15, pc);
36118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tmp = load_cpu_field(spsr);
36128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    gen_set_cpsr(tmp, 0xffffffff);
36135285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_temp_free_i32(tmp);
36148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    s->is_jmp = DISAS_UPDATE;
36158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
36168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
36178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Generate a v6 exception return.  Marks both values as dead.  */
36188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void gen_rfe(DisasContext *s, TCGv pc, TCGv cpsr)
36198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
36208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    gen_set_cpsr(cpsr, 0xffffffff);
36215285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_temp_free_i32(cpsr);
36228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    store_reg(s, 15, pc);
36238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    s->is_jmp = DISAS_UPDATE;
36248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
36258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
36268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline void
36278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectgen_set_condexec (DisasContext *s)
36288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
3629a1204591a52bf668ee72c86f98f53189621572a2Vladimir Chtchetkine    if (s->condexec_mask) {
3630a1204591a52bf668ee72c86f98f53189621572a2Vladimir Chtchetkine        uint32_t val = (s->condexec_cond << 4) | (s->condexec_mask >> 1);
36315285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        TCGv tmp = tcg_temp_new_i32();
3632a1204591a52bf668ee72c86f98f53189621572a2Vladimir Chtchetkine        tcg_gen_movi_i32(tmp, val);
3633a1204591a52bf668ee72c86f98f53189621572a2Vladimir Chtchetkine        store_cpu_field(tmp, condexec_bits);
3634a1204591a52bf668ee72c86f98f53189621572a2Vladimir Chtchetkine    }
36355285864985be9077e58e42235af6582dee72e841David 'Digit' Turner}
36365285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
36375285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic void gen_exception_insn(DisasContext *s, int offset, int excp)
36385285864985be9077e58e42235af6582dee72e841David 'Digit' Turner{
36395285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    gen_set_condexec(s);
36405285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    gen_set_pc_im(s->pc - offset);
36415285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    gen_exception(excp);
36425285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    s->is_jmp = DISAS_JUMP;
36438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
36448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
36458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void gen_nop_hint(DisasContext *s, int val)
36468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
36478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    switch (val) {
36488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 3: /* wfi */
36498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_set_pc_im(s->pc);
36508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        s->is_jmp = DISAS_WFI;
36518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
36528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 2: /* wfe */
36538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 4: /* sev */
36548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* TODO: Implement SEV and WFE.  May help SMP performance.  */
36558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    default: /* nop */
36568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
36578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
36588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
36598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
36608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define CPU_V001 cpu_V0, cpu_V0, cpu_V1
36618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
36625285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic inline void gen_neon_add(int size, TCGv t0, TCGv t1)
36638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
36648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    switch (size) {
36655285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    case 0: gen_helper_neon_add_u8(t0, t0, t1); break;
36665285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    case 1: gen_helper_neon_add_u16(t0, t0, t1); break;
36675285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    case 2: tcg_gen_add_i32(t0, t0, t1); break;
36685285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    default: abort();
36698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
36708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
36718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
36725285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic inline void gen_neon_rsb(int size, TCGv t0, TCGv t1)
36738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
36748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    switch (size) {
36755285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    case 0: gen_helper_neon_sub_u8(t0, t1, t0); break;
36765285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    case 1: gen_helper_neon_sub_u16(t0, t1, t0); break;
36775285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    case 2: tcg_gen_sub_i32(t0, t1, t0); break;
36788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    default: return;
36798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
36808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
36818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
36828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* 32-bit pairwise ops end up the same as the elementwise versions.  */
36838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define gen_helper_neon_pmax_s32  gen_helper_neon_max_s32
36848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define gen_helper_neon_pmax_u32  gen_helper_neon_max_u32
36858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define gen_helper_neon_pmin_s32  gen_helper_neon_min_s32
36868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define gen_helper_neon_pmin_u32  gen_helper_neon_min_u32
36878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
36883d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner#define GEN_NEON_INTEGER_OP_ENV(name) do { \
36893d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner    switch ((size << 1) | u) { \
36903d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner    case 0: \
36913d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner        gen_helper_neon_##name##_s8(tmp, cpu_env, tmp, tmp2); \
36923d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner        break; \
36933d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner    case 1: \
36943d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner        gen_helper_neon_##name##_u8(tmp, cpu_env, tmp, tmp2); \
36953d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner        break; \
36963d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner    case 2: \
36973d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner        gen_helper_neon_##name##_s16(tmp, cpu_env, tmp, tmp2); \
36983d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner        break; \
36993d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner    case 3: \
37003d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner        gen_helper_neon_##name##_u16(tmp, cpu_env, tmp, tmp2); \
37013d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner        break; \
37023d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner    case 4: \
37033d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner        gen_helper_neon_##name##_s32(tmp, cpu_env, tmp, tmp2); \
37043d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner        break; \
37053d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner    case 5: \
37063d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner        gen_helper_neon_##name##_u32(tmp, cpu_env, tmp, tmp2); \
37073d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner        break; \
37083d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner    default: return 1; \
37093d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner    }} while (0)
37103d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner
37118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define GEN_NEON_INTEGER_OP(name) do { \
37128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    switch ((size << 1) | u) { \
37138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0: \
37145285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        gen_helper_neon_##name##_s8(tmp, tmp, tmp2); \
37158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break; \
37168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 1: \
37175285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        gen_helper_neon_##name##_u8(tmp, tmp, tmp2); \
37188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break; \
37198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 2: \
37205285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        gen_helper_neon_##name##_s16(tmp, tmp, tmp2); \
37218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break; \
37228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 3: \
37235285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        gen_helper_neon_##name##_u16(tmp, tmp, tmp2); \
37248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break; \
37258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 4: \
37265285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        gen_helper_neon_##name##_s32(tmp, tmp, tmp2); \
37278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break; \
37288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 5: \
37295285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        gen_helper_neon_##name##_u32(tmp, tmp, tmp2); \
37308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break; \
37318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    default: return 1; \
37328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }} while (0)
37338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
37345285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic TCGv neon_load_scratch(int scratch)
37358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
37365285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    TCGv tmp = tcg_temp_new_i32();
37375285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_gen_ld_i32(tmp, cpu_env, offsetof(CPUARMState, vfp.scratch[scratch]));
37385285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    return tmp;
37398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
37408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
37415285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic void neon_store_scratch(int scratch, TCGv var)
37428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
37435285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_gen_st_i32(var, cpu_env, offsetof(CPUARMState, vfp.scratch[scratch]));
37445285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_temp_free_i32(var);
37458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
37468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
37475285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic inline TCGv neon_get_scalar(int size, int reg)
37488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
37495285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    TCGv tmp;
37505285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    if (size == 1) {
37515285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tmp = neon_load_reg(reg & 7, reg >> 4);
37525285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        if (reg & 8) {
37535285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            gen_neon_dup_high16(tmp);
37545285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        } else {
37555285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            gen_neon_dup_low16(tmp);
37565285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        }
37575285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    } else {
37585285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tmp = neon_load_reg(reg & 15, reg >> 4);
37595285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    }
37605285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    return tmp;
37618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
37628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
37635285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic int gen_neon_unzip(int rd, int rm, int size, int q)
37648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
37655285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    TCGv tmp, tmp2;
37665285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    if (!q && size == 2) {
37675285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        return 1;
37685285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    }
37695285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tmp = tcg_const_i32(rd);
37705285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tmp2 = tcg_const_i32(rm);
37715285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    if (q) {
37725285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        switch (size) {
37735285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        case 0:
37743d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner            gen_helper_neon_qunzip8(cpu_env, tmp, tmp2);
37755285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            break;
37765285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        case 1:
37773d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner            gen_helper_neon_qunzip16(cpu_env, tmp, tmp2);
37785285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            break;
37795285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        case 2:
37803d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner            gen_helper_neon_qunzip32(cpu_env, tmp, tmp2);
37815285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            break;
37825285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        default:
37835285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            abort();
37845285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        }
37855285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    } else {
37865285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        switch (size) {
37875285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        case 0:
37883d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner            gen_helper_neon_unzip8(cpu_env, tmp, tmp2);
37895285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            break;
37905285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        case 1:
37913d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner            gen_helper_neon_unzip16(cpu_env, tmp, tmp2);
37925285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            break;
37935285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        default:
37945285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            abort();
37955285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        }
37965285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    }
37975285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_temp_free_i32(tmp);
37985285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_temp_free_i32(tmp2);
37995285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    return 0;
38008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
38018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
38025285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic int gen_neon_zip(int rd, int rm, int size, int q)
38038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
38045285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    TCGv tmp, tmp2;
38055285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    if (!q && size == 2) {
38065285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        return 1;
38075285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    }
38085285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tmp = tcg_const_i32(rd);
38095285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tmp2 = tcg_const_i32(rm);
38105285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    if (q) {
38115285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        switch (size) {
38125285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        case 0:
38133d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner            gen_helper_neon_qzip8(cpu_env, tmp, tmp2);
38145285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            break;
38155285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        case 1:
38163d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner            gen_helper_neon_qzip16(cpu_env, tmp, tmp2);
38175285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            break;
38185285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        case 2:
38193d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner            gen_helper_neon_qzip32(cpu_env, tmp, tmp2);
38205285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            break;
38215285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        default:
38225285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            abort();
38235285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        }
38248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } else {
38255285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        switch (size) {
38265285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        case 0:
38273d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner            gen_helper_neon_zip8(cpu_env, tmp, tmp2);
38285285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            break;
38295285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        case 1:
38303d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner            gen_helper_neon_zip16(cpu_env, tmp, tmp2);
38315285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            break;
38325285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        default:
38335285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            abort();
38345285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        }
38358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
38365285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_temp_free_i32(tmp);
38375285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_temp_free_i32(tmp2);
38385285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    return 0;
38398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
38408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
38415285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic void gen_neon_trn_u8(TCGv t0, TCGv t1)
38428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
38435285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    TCGv rd, tmp;
38448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
38455285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    rd = tcg_temp_new_i32();
38465285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tmp = tcg_temp_new_i32();
38475285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
38485285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_gen_shli_i32(rd, t0, 8);
38495285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_gen_andi_i32(rd, rd, 0xff00ff00);
38505285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_gen_andi_i32(tmp, t1, 0x00ff00ff);
38515285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_gen_or_i32(rd, rd, tmp);
38525285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
38535285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_gen_shri_i32(t1, t1, 8);
38545285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_gen_andi_i32(t1, t1, 0x00ff00ff);
38555285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_gen_andi_i32(tmp, t0, 0xff00ff00);
38565285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_gen_or_i32(t1, t1, tmp);
38575285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_gen_mov_i32(t0, rd);
38585285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
38595285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_temp_free_i32(tmp);
38605285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_temp_free_i32(rd);
38618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
38628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
38635285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic void gen_neon_trn_u16(TCGv t0, TCGv t1)
38645285864985be9077e58e42235af6582dee72e841David 'Digit' Turner{
38655285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    TCGv rd, tmp;
38665285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
38675285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    rd = tcg_temp_new_i32();
38685285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tmp = tcg_temp_new_i32();
38695285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
38705285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_gen_shli_i32(rd, t0, 16);
38715285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_gen_andi_i32(tmp, t1, 0xffff);
38725285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_gen_or_i32(rd, rd, tmp);
38735285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_gen_shri_i32(t1, t1, 16);
38745285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_gen_andi_i32(tmp, t0, 0xffff0000);
38755285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_gen_or_i32(t1, t1, tmp);
38765285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_gen_mov_i32(t0, rd);
38775285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
38785285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_temp_free_i32(tmp);
38795285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_temp_free_i32(rd);
38805285864985be9077e58e42235af6582dee72e841David 'Digit' Turner}
38815285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
38825285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
38835285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic struct {
38845285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    int nregs;
38855285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    int interleave;
38865285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    int spacing;
38875285864985be9077e58e42235af6582dee72e841David 'Digit' Turner} neon_ls_element_type[11] = {
38885285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    {4, 4, 1},
38895285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    {4, 4, 2},
38908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    {4, 1, 1},
38918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    {4, 2, 1},
38928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    {3, 3, 1},
38938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    {3, 3, 2},
38948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    {3, 1, 1},
38958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    {1, 1, 1},
38968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    {2, 2, 1},
38978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    {2, 2, 2},
38988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    {2, 1, 1}
38998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project};
39008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
39018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Translate a NEON load/store element instruction.  Return nonzero if the
39028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   instruction is invalid.  */
3903e2678e116c8cdb0f36b247a5bd9cfacc849362fcDavid 'Digit' Turnerstatic int disas_neon_ls_insn(CPUARMState * env, DisasContext *s, uint32_t insn)
39048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
39058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int rd, rn, rm;
39068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int op;
39078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int nregs;
39088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int interleave;
39095285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    int spacing;
39108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int stride;
39118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int size;
39128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int reg;
39138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int pass;
39148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int load;
39158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int shift;
39165285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    TCGv addr;
39178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    TCGv tmp;
39188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    TCGv tmp2;
39198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
39205285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    if (!s->vfp_enabled)
39218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      return 1;
39228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    VFP_DREG_D(rd, insn);
39238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    rn = (insn >> 16) & 0xf;
39248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    rm = insn & 0xf;
39258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    load = (insn & (1 << 21)) != 0;
39268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if ((insn & (1 << 23)) == 0) {
39278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* Load store all elements.  */
39288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        op = (insn >> 8) & 0xf;
39298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        size = (insn >> 6) & 3;
39305285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        if (op > 10)
39318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 1;
39325285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        /* Catch UNDEF cases for bad values of align field */
39335285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        switch (op & 0xc) {
39345285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        case 4:
39355285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            if (((insn >> 5) & 1) == 1) {
39365285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                return 1;
39375285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            }
39385285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            break;
39395285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        case 8:
39405285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            if (((insn >> 4) & 3) == 3) {
39415285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                return 1;
39425285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            }
39435285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            break;
39445285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        default:
39455285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            break;
39465285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        }
39478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        nregs = neon_ls_element_type[op].nregs;
39488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        interleave = neon_ls_element_type[op].interleave;
39495285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        spacing = neon_ls_element_type[op].spacing;
39505285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        if (size == 3 && (interleave | spacing) != 1) {
39515285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            return 1;
39528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
39535285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        addr = tcg_const_i32(insn);
39540b4c9e8457959b01cd26f60ef214e9b5b7a297d4David 'Digit' Turner        gen_helper_neon_vldst_all(cpu_env, addr);
39555285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tcg_temp_free_i32(addr);
39568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        stride = nregs * 8;
39578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } else {
39588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        size = (insn >> 10) & 3;
39598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (size == 3) {
39608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* Load single element to all lanes.  */
39615285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            int a = (insn >> 4) & 1;
39625285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            if (!load) {
39638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                return 1;
39645285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            }
39658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            size = (insn >> 6) & 3;
39668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            nregs = ((insn >> 8) & 3) + 1;
39675285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
39685285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            if (size == 3) {
39695285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                if (nregs != 4 || a == 0) {
39708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    return 1;
39718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
39725285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                /* For VLD4 size==3 a == 1 means 32 bits at 16 byte alignment */
39735285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                size = 2;
39745285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            }
39755285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            if (nregs == 1 && a == 1 && size == 0) {
39765285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                return 1;
39775285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            }
39785285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            if (nregs == 3 && a == 1) {
39795285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                return 1;
39805285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            }
39815285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            addr = tcg_temp_new_i32();
39825285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            load_reg_var(s, addr, rn);
39835285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            if (nregs == 1) {
39845285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                /* VLD1 to all lanes: bit 5 indicates how many Dregs to write */
39855285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tmp = gen_load_and_replicate(s, addr, size);
39865285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_gen_st_i32(tmp, cpu_env, neon_reg_offset(rd, 0));
39875285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_gen_st_i32(tmp, cpu_env, neon_reg_offset(rd, 1));
39885285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                if (insn & (1 << 5)) {
39895285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tcg_gen_st_i32(tmp, cpu_env, neon_reg_offset(rd + 1, 0));
39905285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tcg_gen_st_i32(tmp, cpu_env, neon_reg_offset(rd + 1, 1));
39915285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                }
39925285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_temp_free_i32(tmp);
39935285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            } else {
39945285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                /* VLD2/3/4 to all lanes: bit 5 indicates register stride */
39955285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                stride = (insn & (1 << 5)) ? 2 : 1;
39965285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                for (reg = 0; reg < nregs; reg++) {
39975285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tmp = gen_load_and_replicate(s, addr, size);
39985285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tcg_gen_st_i32(tmp, cpu_env, neon_reg_offset(rd, 0));
39995285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tcg_gen_st_i32(tmp, cpu_env, neon_reg_offset(rd, 1));
40005285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tcg_temp_free_i32(tmp);
40015285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tcg_gen_addi_i32(addr, addr, 1 << size);
40025285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    rd += stride;
40035285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                }
40048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
40055285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tcg_temp_free_i32(addr);
40068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            stride = (1 << size) * nregs;
40078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        } else {
40088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* Single element.  */
40095285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            int idx = (insn >> 4) & 0xf;
40108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            pass = (insn >> 7) & 1;
40118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            switch (size) {
40128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            case 0:
40138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                shift = ((insn >> 5) & 3) * 8;
40148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                stride = 1;
40158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                break;
40168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            case 1:
40178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                shift = ((insn >> 6) & 1) * 16;
40188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                stride = (insn & (1 << 5)) ? 2 : 1;
40198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                break;
40208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            case 2:
40218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                shift = 0;
40228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                stride = (insn & (1 << 6)) ? 2 : 1;
40238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                break;
40248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            default:
40258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                abort();
40268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
40278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            nregs = ((insn >> 8) & 3) + 1;
40285285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            /* Catch the UNDEF cases. This is unavoidably a bit messy. */
40295285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            switch (nregs) {
40305285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            case 1:
40315285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                if (((idx & (1 << size)) != 0) ||
40325285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    (size == 2 && ((idx & 3) == 1 || (idx & 3) == 2))) {
40335285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    return 1;
40345285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                }
40355285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                break;
40365285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            case 3:
40375285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                if ((idx & 1) != 0) {
40385285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    return 1;
40395285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                }
40405285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                /* fall through */
40415285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            case 2:
40425285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                if (size == 2 && (idx & 2) != 0) {
40435285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    return 1;
40445285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                }
40455285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                break;
40465285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            case 4:
40475285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                if ((size == 2) && ((idx & 3) == 3)) {
40485285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    return 1;
40495285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                }
40505285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                break;
40515285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            default:
40525285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                abort();
40535285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            }
40545285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            if ((rd + stride * (nregs - 1)) > 31) {
40555285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                /* Attempts to write off the end of the register file
40565285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                 * are UNPREDICTABLE; we choose to UNDEF because otherwise
40575285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                 * the neon_load_reg() would write off the end of the array.
40585285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                 */
40595285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                return 1;
40605285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            }
40615285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            addr = tcg_temp_new_i32();
40625285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            load_reg_var(s, addr, rn);
40638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            for (reg = 0; reg < nregs; reg++) {
40648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (load) {
40658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    switch (size) {
40668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    case 0:
40675285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tmp = gen_ld8u(addr, IS_USER(s));
40688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        break;
40698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    case 1:
40705285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tmp = gen_ld16u(addr, IS_USER(s));
40718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        break;
40728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    case 2:
40735285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tmp = gen_ld32(addr, IS_USER(s));
40748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        break;
40758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    default: /* Avoid compiler warnings.  */
40768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        abort();
40778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
40788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if (size != 2) {
40798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        tmp2 = neon_load_reg(rd, pass);
40808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        gen_bfi(tmp, tmp2, tmp, shift, size ? 0xffff : 0xff);
40815285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tcg_temp_free_i32(tmp2);
40828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
40838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    neon_store_reg(rd, pass, tmp);
40848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                } else { /* Store */
40858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    tmp = neon_load_reg(rd, pass);
40868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if (shift)
40878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        tcg_gen_shri_i32(tmp, tmp, shift);
40888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    switch (size) {
40898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    case 0:
40905285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        gen_st8(tmp, addr, IS_USER(s));
40918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        break;
40928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    case 1:
40935285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        gen_st16(tmp, addr, IS_USER(s));
40948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        break;
40958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    case 2:
40965285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        gen_st32(tmp, addr, IS_USER(s));
40978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        break;
40988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
40998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
41008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                rd += stride;
41015285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_gen_addi_i32(addr, addr, 1 << size);
41028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
41035285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tcg_temp_free_i32(addr);
41048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            stride = nregs * (1 << size);
41058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
41068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
41078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (rm != 15) {
41088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        TCGv base;
41098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
41108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        base = load_reg(s, rn);
41118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (rm == 13) {
41128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tcg_gen_addi_i32(base, base, stride);
41138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        } else {
41148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            TCGv index;
41158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            index = load_reg(s, rm);
41168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tcg_gen_add_i32(base, base, index);
41175285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tcg_temp_free_i32(index);
41188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
41198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        store_reg(s, rn, base);
41208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
41218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
41228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
41238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
41248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Bitwise select.  dest = c ? t : f.  Clobbers T and F.  */
41258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void gen_neon_bsl(TCGv dest, TCGv t, TCGv f, TCGv c)
41268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
41278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_gen_and_i32(t, t, c);
41285285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_gen_andc_i32(f, f, c);
41298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_gen_or_i32(dest, t, f);
41308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
41318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
41325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic inline void gen_neon_narrow(int size, TCGv dest, TCGv_i64 src)
41338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
41348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    switch (size) {
41358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0: gen_helper_neon_narrow_u8(dest, src); break;
41368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 1: gen_helper_neon_narrow_u16(dest, src); break;
41378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 2: tcg_gen_trunc_i64_i32(dest, src); break;
41388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    default: abort();
41398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
41408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
41418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
41425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic inline void gen_neon_narrow_sats(int size, TCGv dest, TCGv_i64 src)
41438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
41448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    switch (size) {
41453d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner    case 0: gen_helper_neon_narrow_sat_s8(dest, cpu_env, src); break;
41463d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner    case 1: gen_helper_neon_narrow_sat_s16(dest, cpu_env, src); break;
41473d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner    case 2: gen_helper_neon_narrow_sat_s32(dest, cpu_env, src); break;
41488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    default: abort();
41498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
41508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
41518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
41525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic inline void gen_neon_narrow_satu(int size, TCGv dest, TCGv_i64 src)
41538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
41548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    switch (size) {
41553d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner    case 0: gen_helper_neon_narrow_sat_u8(dest, cpu_env, src); break;
41563d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner    case 1: gen_helper_neon_narrow_sat_u16(dest, cpu_env, src); break;
41573d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner    case 2: gen_helper_neon_narrow_sat_u32(dest, cpu_env, src); break;
41585285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    default: abort();
41595285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    }
41605285864985be9077e58e42235af6582dee72e841David 'Digit' Turner}
41615285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
41625285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic inline void gen_neon_unarrow_sats(int size, TCGv dest, TCGv_i64 src)
41635285864985be9077e58e42235af6582dee72e841David 'Digit' Turner{
41645285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    switch (size) {
41653d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner    case 0: gen_helper_neon_unarrow_sat8(dest, cpu_env, src); break;
41663d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner    case 1: gen_helper_neon_unarrow_sat16(dest, cpu_env, src); break;
41673d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner    case 2: gen_helper_neon_unarrow_sat32(dest, cpu_env, src); break;
41688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    default: abort();
41698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
41708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
41718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
41728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline void gen_neon_shift_narrow(int size, TCGv var, TCGv shift,
41738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                         int q, int u)
41748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
41758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (q) {
41768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (u) {
41778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            switch (size) {
41788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            case 1: gen_helper_neon_rshl_u16(var, var, shift); break;
41798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            case 2: gen_helper_neon_rshl_u32(var, var, shift); break;
41808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            default: abort();
41818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
41828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        } else {
41838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            switch (size) {
41848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            case 1: gen_helper_neon_rshl_s16(var, var, shift); break;
41858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            case 2: gen_helper_neon_rshl_s32(var, var, shift); break;
41868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            default: abort();
41878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
41888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
41898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } else {
41908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (u) {
41918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            switch (size) {
41925285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            case 1: gen_helper_neon_shl_u16(var, var, shift); break;
41935285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            case 2: gen_helper_neon_shl_u32(var, var, shift); break;
41948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            default: abort();
41958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
41968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        } else {
41978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            switch (size) {
41988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            case 1: gen_helper_neon_shl_s16(var, var, shift); break;
41998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            case 2: gen_helper_neon_shl_s32(var, var, shift); break;
42008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            default: abort();
42018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
42028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
42038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
42048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
42058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
42065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic inline void gen_neon_widen(TCGv_i64 dest, TCGv src, int size, int u)
42078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
42088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (u) {
42098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        switch (size) {
42108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0: gen_helper_neon_widen_u8(dest, src); break;
42118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 1: gen_helper_neon_widen_u16(dest, src); break;
42128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 2: tcg_gen_extu_i32_i64(dest, src); break;
42138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        default: abort();
42148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
42158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } else {
42168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        switch (size) {
42178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0: gen_helper_neon_widen_s8(dest, src); break;
42188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 1: gen_helper_neon_widen_s16(dest, src); break;
42198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 2: tcg_gen_ext_i32_i64(dest, src); break;
42208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        default: abort();
42218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
42228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
42235285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_temp_free_i32(src);
42248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
42258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
42268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline void gen_neon_addl(int size)
42278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
42288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    switch (size) {
42298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0: gen_helper_neon_addl_u16(CPU_V001); break;
42308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 1: gen_helper_neon_addl_u32(CPU_V001); break;
42318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 2: tcg_gen_add_i64(CPU_V001); break;
42328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    default: abort();
42338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
42348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
42358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
42368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline void gen_neon_subl(int size)
42378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
42388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    switch (size) {
42398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0: gen_helper_neon_subl_u16(CPU_V001); break;
42408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 1: gen_helper_neon_subl_u32(CPU_V001); break;
42418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 2: tcg_gen_sub_i64(CPU_V001); break;
42428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    default: abort();
42438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
42448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
42458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
42465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic inline void gen_neon_negl(TCGv_i64 var, int size)
42478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
42488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    switch (size) {
42498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0: gen_helper_neon_negl_u16(var, var); break;
42508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 1: gen_helper_neon_negl_u32(var, var); break;
42518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 2: gen_helper_neon_negl_u64(var, var); break;
42528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    default: abort();
42538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
42548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
42558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
42565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic inline void gen_neon_addl_saturate(TCGv_i64 op0, TCGv_i64 op1, int size)
42578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
42588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    switch (size) {
42593d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner    case 1: gen_helper_neon_addl_saturate_s32(op0, cpu_env, op0, op1); break;
42603d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner    case 2: gen_helper_neon_addl_saturate_s64(op0, cpu_env, op0, op1); break;
42618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    default: abort();
42628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
42638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
42648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
42655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic inline void gen_neon_mull(TCGv_i64 dest, TCGv a, TCGv b, int size, int u)
42668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
42675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    TCGv_i64 tmp;
42688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
42698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    switch ((size << 1) | u) {
42708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0: gen_helper_neon_mull_s8(dest, a, b); break;
42718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 1: gen_helper_neon_mull_u8(dest, a, b); break;
42728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 2: gen_helper_neon_mull_s16(dest, a, b); break;
42738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 3: gen_helper_neon_mull_u16(dest, a, b); break;
42748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 4:
42758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tmp = gen_muls_i64_i32(a, b);
42768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tcg_gen_mov_i64(dest, tmp);
42775285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tcg_temp_free_i64(tmp);
42788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
42798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 5:
42808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tmp = gen_mulu_i64_i32(a, b);
42818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tcg_gen_mov_i64(dest, tmp);
42825285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tcg_temp_free_i64(tmp);
42838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
42848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    default: abort();
42858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
42865285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
42875285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    /* gen_helper_neon_mull_[su]{8|16} do not free their parameters.
42885285864985be9077e58e42235af6582dee72e841David 'Digit' Turner       Don't forget to clean them now.  */
42898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (size < 2) {
42905285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tcg_temp_free_i32(a);
42915285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tcg_temp_free_i32(b);
42928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
42938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
42948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
42955285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic void gen_neon_narrow_op(int op, int u, int size, TCGv dest, TCGv_i64 src)
42965285864985be9077e58e42235af6582dee72e841David 'Digit' Turner{
42975285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    if (op) {
42985285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        if (u) {
42995285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            gen_neon_unarrow_sats(size, dest, src);
43005285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        } else {
43015285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            gen_neon_narrow(size, dest, src);
43025285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        }
43035285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    } else {
43045285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        if (u) {
43055285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            gen_neon_narrow_satu(size, dest, src);
43065285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        } else {
43075285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            gen_neon_narrow_sats(size, dest, src);
43085285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        }
43095285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    }
43105285864985be9077e58e42235af6582dee72e841David 'Digit' Turner}
43115285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
43125285864985be9077e58e42235af6582dee72e841David 'Digit' Turner/* Symbolic constants for op fields for Neon 3-register same-length.
43135285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * The values correspond to bits [11:8,4]; see the ARM ARM DDI0406B
43145285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * table A7-9.
43155285864985be9077e58e42235af6582dee72e841David 'Digit' Turner */
43165285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_3R_VHADD 0
43175285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_3R_VQADD 1
43185285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_3R_VRHADD 2
43195285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_3R_LOGIC 3 /* VAND,VBIC,VORR,VMOV,VORN,VEOR,VBIF,VBIT,VBSL */
43205285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_3R_VHSUB 4
43215285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_3R_VQSUB 5
43225285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_3R_VCGT 6
43235285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_3R_VCGE 7
43245285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_3R_VSHL 8
43255285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_3R_VQSHL 9
43265285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_3R_VRSHL 10
43275285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_3R_VQRSHL 11
43285285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_3R_VMAX 12
43295285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_3R_VMIN 13
43305285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_3R_VABD 14
43315285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_3R_VABA 15
43325285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_3R_VADD_VSUB 16
43335285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_3R_VTST_VCEQ 17
43345285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_3R_VML 18 /* VMLA, VMLAL, VMLS, VMLSL */
43355285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_3R_VMUL 19
43365285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_3R_VPMAX 20
43375285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_3R_VPMIN 21
43385285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_3R_VQDMULH_VQRDMULH 22
43395285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_3R_VPADD 23
43405285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_3R_FLOAT_ARITH 26 /* float VADD, VSUB, VPADD, VABD */
43415285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_3R_FLOAT_MULTIPLY 27 /* float VMLA, VMLS, VMUL */
43425285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_3R_FLOAT_CMP 28 /* float VCEQ, VCGE, VCGT */
43435285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_3R_FLOAT_ACMP 29 /* float VACGE, VACGT, VACLE, VACLT */
43445285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_3R_FLOAT_MINMAX 30 /* float VMIN, VMAX */
43455285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_3R_VRECPS_VRSQRTS 31 /* float VRECPS, VRSQRTS */
43465285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
43475285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic const uint8_t neon_3r_sizes[] = {
43485285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    [NEON_3R_VHADD] = 0x7,
43495285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    [NEON_3R_VQADD] = 0xf,
43505285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    [NEON_3R_VRHADD] = 0x7,
43515285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    [NEON_3R_LOGIC] = 0xf, /* size field encodes op type */
43525285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    [NEON_3R_VHSUB] = 0x7,
43535285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    [NEON_3R_VQSUB] = 0xf,
43545285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    [NEON_3R_VCGT] = 0x7,
43555285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    [NEON_3R_VCGE] = 0x7,
43565285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    [NEON_3R_VSHL] = 0xf,
43575285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    [NEON_3R_VQSHL] = 0xf,
43585285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    [NEON_3R_VRSHL] = 0xf,
43595285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    [NEON_3R_VQRSHL] = 0xf,
43605285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    [NEON_3R_VMAX] = 0x7,
43615285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    [NEON_3R_VMIN] = 0x7,
43625285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    [NEON_3R_VABD] = 0x7,
43635285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    [NEON_3R_VABA] = 0x7,
43645285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    [NEON_3R_VADD_VSUB] = 0xf,
43655285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    [NEON_3R_VTST_VCEQ] = 0x7,
43665285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    [NEON_3R_VML] = 0x7,
43675285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    [NEON_3R_VMUL] = 0x7,
43685285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    [NEON_3R_VPMAX] = 0x7,
43695285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    [NEON_3R_VPMIN] = 0x7,
43705285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    [NEON_3R_VQDMULH_VQRDMULH] = 0x6,
43715285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    [NEON_3R_VPADD] = 0x7,
43725285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    [NEON_3R_FLOAT_ARITH] = 0x5, /* size bit 1 encodes op */
43735285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    [NEON_3R_FLOAT_MULTIPLY] = 0x5, /* size bit 1 encodes op */
43745285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    [NEON_3R_FLOAT_CMP] = 0x5, /* size bit 1 encodes op */
43755285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    [NEON_3R_FLOAT_ACMP] = 0x5, /* size bit 1 encodes op */
43765285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    [NEON_3R_FLOAT_MINMAX] = 0x5, /* size bit 1 encodes op */
43775285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    [NEON_3R_VRECPS_VRSQRTS] = 0x5, /* size bit 1 encodes op */
43785285864985be9077e58e42235af6582dee72e841David 'Digit' Turner};
43795285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
43805285864985be9077e58e42235af6582dee72e841David 'Digit' Turner/* Symbolic constants for op fields for Neon 2-register miscellaneous.
43815285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * The values correspond to bits [17:16,10:7]; see the ARM ARM DDI0406B
43825285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * table A7-13.
43835285864985be9077e58e42235af6582dee72e841David 'Digit' Turner */
43845285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VREV64 0
43855285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VREV32 1
43865285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VREV16 2
43875285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VPADDL 4
43885285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VPADDL_U 5
43895285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VCLS 8
43905285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VCLZ 9
43915285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VCNT 10
43925285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VMVN 11
43935285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VPADAL 12
43945285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VPADAL_U 13
43955285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VQABS 14
43965285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VQNEG 15
43975285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VCGT0 16
43985285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VCGE0 17
43995285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VCEQ0 18
44005285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VCLE0 19
44015285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VCLT0 20
44025285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VABS 22
44035285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VNEG 23
44045285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VCGT0_F 24
44055285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VCGE0_F 25
44065285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VCEQ0_F 26
44075285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VCLE0_F 27
44085285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VCLT0_F 28
44095285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VABS_F 30
44105285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VNEG_F 31
44115285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VSWP 32
44125285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VTRN 33
44135285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VUZP 34
44145285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VZIP 35
44155285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VMOVN 36 /* Includes VQMOVN, VQMOVUN */
44165285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VQMOVN 37 /* Includes VQMOVUN */
44175285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VSHLL 38
44185285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VCVT_F16_F32 44
44195285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VCVT_F32_F16 46
44205285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VRECPE 56
44215285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VRSQRTE 57
44225285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VRECPE_F 58
44235285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VRSQRTE_F 59
44245285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VCVT_FS 60
44255285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VCVT_FU 61
44265285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VCVT_SF 62
44275285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VCVT_UF 63
44285285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
44295285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic int neon_2rm_is_float_op(int op)
44305285864985be9077e58e42235af6582dee72e841David 'Digit' Turner{
44315285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    /* Return true if this neon 2reg-misc op is float-to-float */
44325285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    return (op == NEON_2RM_VABS_F || op == NEON_2RM_VNEG_F ||
44335285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            op >= NEON_2RM_VRECPE_F);
44345285864985be9077e58e42235af6582dee72e841David 'Digit' Turner}
44355285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
44365285864985be9077e58e42235af6582dee72e841David 'Digit' Turner/* Each entry in this array has bit n set if the insn allows
44375285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * size value n (otherwise it will UNDEF). Since unallocated
44385285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * op values will have no bits set they always UNDEF.
44395285864985be9077e58e42235af6582dee72e841David 'Digit' Turner */
44405285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic const uint8_t neon_2rm_sizes[] = {
44415285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    [NEON_2RM_VREV64] = 0x7,
44425285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    [NEON_2RM_VREV32] = 0x3,
44435285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    [NEON_2RM_VREV16] = 0x1,
44445285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    [NEON_2RM_VPADDL] = 0x7,
44455285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    [NEON_2RM_VPADDL_U] = 0x7,
44465285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    [NEON_2RM_VCLS] = 0x7,
44475285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    [NEON_2RM_VCLZ] = 0x7,
44485285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    [NEON_2RM_VCNT] = 0x1,
44495285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    [NEON_2RM_VMVN] = 0x1,
44505285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    [NEON_2RM_VPADAL] = 0x7,
44515285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    [NEON_2RM_VPADAL_U] = 0x7,
44525285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    [NEON_2RM_VQABS] = 0x7,
44535285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    [NEON_2RM_VQNEG] = 0x7,
44545285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    [NEON_2RM_VCGT0] = 0x7,
44555285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    [NEON_2RM_VCGE0] = 0x7,
44565285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    [NEON_2RM_VCEQ0] = 0x7,
44575285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    [NEON_2RM_VCLE0] = 0x7,
44585285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    [NEON_2RM_VCLT0] = 0x7,
44595285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    [NEON_2RM_VABS] = 0x7,
44605285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    [NEON_2RM_VNEG] = 0x7,
44615285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    [NEON_2RM_VCGT0_F] = 0x4,
44625285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    [NEON_2RM_VCGE0_F] = 0x4,
44635285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    [NEON_2RM_VCEQ0_F] = 0x4,
44645285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    [NEON_2RM_VCLE0_F] = 0x4,
44655285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    [NEON_2RM_VCLT0_F] = 0x4,
44665285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    [NEON_2RM_VABS_F] = 0x4,
44675285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    [NEON_2RM_VNEG_F] = 0x4,
44685285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    [NEON_2RM_VSWP] = 0x1,
44695285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    [NEON_2RM_VTRN] = 0x7,
44705285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    [NEON_2RM_VUZP] = 0x7,
44715285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    [NEON_2RM_VZIP] = 0x7,
44725285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    [NEON_2RM_VMOVN] = 0x7,
44735285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    [NEON_2RM_VQMOVN] = 0x7,
44745285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    [NEON_2RM_VSHLL] = 0x7,
44755285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    [NEON_2RM_VCVT_F16_F32] = 0x2,
44765285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    [NEON_2RM_VCVT_F32_F16] = 0x2,
44775285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    [NEON_2RM_VRECPE] = 0x4,
44785285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    [NEON_2RM_VRSQRTE] = 0x4,
44795285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    [NEON_2RM_VRECPE_F] = 0x4,
44805285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    [NEON_2RM_VRSQRTE_F] = 0x4,
44815285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    [NEON_2RM_VCVT_FS] = 0x4,
44825285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    [NEON_2RM_VCVT_FU] = 0x4,
44835285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    [NEON_2RM_VCVT_SF] = 0x4,
44845285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    [NEON_2RM_VCVT_UF] = 0x4,
44855285864985be9077e58e42235af6582dee72e841David 'Digit' Turner};
44865285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
44878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Translate a NEON data processing instruction.  Return nonzero if the
44888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   instruction is invalid.
44898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   We process data in a mixture of 32-bit and 64-bit chunks.
44908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   Mostly we use 32-bit chunks so we can use normal scalar instructions.  */
44918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4492e2678e116c8cdb0f36b247a5bd9cfacc849362fcDavid 'Digit' Turnerstatic int disas_neon_data_insn(CPUARMState * env, DisasContext *s, uint32_t insn)
44938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
44948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int op;
44958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int q;
44968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int rd, rn, rm;
44978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int size;
44988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int shift;
44998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int pass;
45008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int count;
45018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int pairwise;
45028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int u;
45035285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    uint32_t imm, mask;
45045285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    TCGv tmp, tmp2, tmp3, tmp4, tmp5;
45055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    TCGv_i64 tmp64;
45068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
45075285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    if (!s->vfp_enabled)
45088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      return 1;
45098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    q = (insn & (1 << 6)) != 0;
45108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    u = (insn >> 24) & 1;
45118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    VFP_DREG_D(rd, insn);
45128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    VFP_DREG_N(rn, insn);
45138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    VFP_DREG_M(rm, insn);
45148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    size = (insn >> 20) & 3;
45158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if ((insn & (1 << 23)) == 0) {
45168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* Three register same length.  */
45178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        op = ((insn >> 7) & 0x1e) | ((insn >> 4) & 1);
45185285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        /* Catch invalid op and bad size combinations: UNDEF */
45195285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        if ((neon_3r_sizes[op] & (1 << size)) == 0) {
45205285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            return 1;
45215285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        }
45225285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        /* All insns of this form UNDEF for either this condition or the
45235285864985be9077e58e42235af6582dee72e841David 'Digit' Turner         * superset of cases "Q==1"; we catch the latter later.
45245285864985be9077e58e42235af6582dee72e841David 'Digit' Turner         */
45255285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        if (q && ((rd | rn | rm) & 1)) {
45265285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            return 1;
45275285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        }
45285285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        if (size == 3 && op != NEON_3R_LOGIC) {
45295285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            /* 64-bit element instructions. */
45308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            for (pass = 0; pass < (q ? 2 : 1); pass++) {
45318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                neon_load_reg64(cpu_V0, rn + pass);
45328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                neon_load_reg64(cpu_V1, rm + pass);
45338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                switch (op) {
45345285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                case NEON_3R_VQADD:
45358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if (u) {
45363d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner                        gen_helper_neon_qadd_u64(cpu_V0, cpu_env,
45373d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner                                                 cpu_V0, cpu_V1);
45388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    } else {
45393d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner                        gen_helper_neon_qadd_s64(cpu_V0, cpu_env,
45403d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner                                                 cpu_V0, cpu_V1);
45418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
45428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    break;
45435285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                case NEON_3R_VQSUB:
45448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if (u) {
45453d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner                        gen_helper_neon_qsub_u64(cpu_V0, cpu_env,
45463d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner                                                 cpu_V0, cpu_V1);
45478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    } else {
45483d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner                        gen_helper_neon_qsub_s64(cpu_V0, cpu_env,
45493d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner                                                 cpu_V0, cpu_V1);
45508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
45518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    break;
45525285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                case NEON_3R_VSHL:
45538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if (u) {
45548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        gen_helper_neon_shl_u64(cpu_V0, cpu_V1, cpu_V0);
45558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    } else {
45568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        gen_helper_neon_shl_s64(cpu_V0, cpu_V1, cpu_V0);
45578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
45588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    break;
45595285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                case NEON_3R_VQSHL:
45608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if (u) {
45613d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner                        gen_helper_neon_qshl_u64(cpu_V0, cpu_env,
45623d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner                                                 cpu_V1, cpu_V0);
45638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    } else {
45643d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner                        gen_helper_neon_qshl_s64(cpu_V0, cpu_env,
45653d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner                                                 cpu_V1, cpu_V0);
45668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
45678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    break;
45685285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                case NEON_3R_VRSHL:
45698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if (u) {
45708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        gen_helper_neon_rshl_u64(cpu_V0, cpu_V1, cpu_V0);
45718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    } else {
45728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        gen_helper_neon_rshl_s64(cpu_V0, cpu_V1, cpu_V0);
45738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
45748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    break;
45755285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                case NEON_3R_VQRSHL:
45768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if (u) {
45773d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner                        gen_helper_neon_qrshl_u64(cpu_V0, cpu_env,
45783d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner                                                  cpu_V1, cpu_V0);
45798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    } else {
45803d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner                        gen_helper_neon_qrshl_s64(cpu_V0, cpu_env,
45813d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner                                                  cpu_V1, cpu_V0);
45828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
45838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    break;
45845285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                case NEON_3R_VADD_VSUB:
45858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if (u) {
45868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        tcg_gen_sub_i64(CPU_V001);
45878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    } else {
45888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        tcg_gen_add_i64(CPU_V001);
45898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
45908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    break;
45918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                default:
45928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    abort();
45938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
45948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                neon_store_reg64(cpu_V0, rd + pass);
45958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
45968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 0;
45978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
45985285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        pairwise = 0;
45998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        switch (op) {
46005285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        case NEON_3R_VSHL:
46015285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        case NEON_3R_VQSHL:
46025285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        case NEON_3R_VRSHL:
46035285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        case NEON_3R_VQRSHL:
46048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            {
46058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                int rtmp;
46068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* Shift instruction operands are reversed.  */
46078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                rtmp = rn;
46088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                rn = rm;
46098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                rm = rtmp;
46108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
46118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
46125285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        case NEON_3R_VPADD:
46135285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            if (u) {
46145285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                return 1;
46155285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            }
46165285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            /* Fall through */
46175285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        case NEON_3R_VPMAX:
46185285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        case NEON_3R_VPMIN:
46198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            pairwise = 1;
46208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
46215285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        case NEON_3R_FLOAT_ARITH:
46225285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            pairwise = (u && size < 2); /* if VPADD (float) */
46238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
46245285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        case NEON_3R_FLOAT_MINMAX:
46255285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            pairwise = u; /* if VPMIN/VPMAX (float) */
46265285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            break;
46275285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        case NEON_3R_FLOAT_CMP:
46285285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            if (!u && size) {
46295285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                /* no encoding for U=0 C=1x */
46305285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                return 1;
46315285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            }
46325285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            break;
46335285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        case NEON_3R_FLOAT_ACMP:
46345285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            if (!u) {
46355285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                return 1;
46365285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            }
46375285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            break;
46385285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        case NEON_3R_VRECPS_VRSQRTS:
46395285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            if (u) {
46405285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                return 1;
46415285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            }
46425285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            break;
46435285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        case NEON_3R_VMUL:
46445285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            if (u && (size != 0)) {
46455285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                /* UNDEF on invalid size for polynomial subcase */
46465285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                return 1;
46475285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            }
46488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
46498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        default:
46508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
46518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
46525285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
46535285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        if (pairwise && q) {
46545285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            /* All the pairwise insns UNDEF if Q is set */
46555285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            return 1;
46565285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        }
46575285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
46588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        for (pass = 0; pass < (q ? 4 : 2); pass++) {
46598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
46608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (pairwise) {
46618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* Pairwise.  */
46625285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            if (pass < 1) {
46635285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tmp = neon_load_reg(rn, 0);
46645285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tmp2 = neon_load_reg(rn, 1);
46658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            } else {
46665285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tmp = neon_load_reg(rm, 0);
46675285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tmp2 = neon_load_reg(rm, 1);
46688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
46698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        } else {
46708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* Elementwise.  */
46715285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tmp = neon_load_reg(rn, pass);
46725285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tmp2 = neon_load_reg(rm, pass);
46738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
46748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        switch (op) {
46755285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        case NEON_3R_VHADD:
46768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            GEN_NEON_INTEGER_OP(hadd);
46778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
46785285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        case NEON_3R_VQADD:
46793d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner            GEN_NEON_INTEGER_OP_ENV(qadd);
46808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
46815285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        case NEON_3R_VRHADD:
46828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            GEN_NEON_INTEGER_OP(rhadd);
46838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
46845285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        case NEON_3R_LOGIC: /* Logic ops.  */
46858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            switch ((u << 2) | size) {
46868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            case 0: /* VAND */
46875285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_gen_and_i32(tmp, tmp, tmp2);
46888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                break;
46898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            case 1: /* BIC */
46905285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_gen_andc_i32(tmp, tmp, tmp2);
46918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                break;
46928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            case 2: /* VORR */
46935285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_gen_or_i32(tmp, tmp, tmp2);
46948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                break;
46958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            case 3: /* VORN */
46965285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_gen_orc_i32(tmp, tmp, tmp2);
46978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                break;
46988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            case 4: /* VEOR */
46995285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_gen_xor_i32(tmp, tmp, tmp2);
47008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                break;
47018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            case 5: /* VBSL */
47025285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tmp3 = neon_load_reg(rd, pass);
47035285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                gen_neon_bsl(tmp, tmp, tmp2, tmp3);
47045285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_temp_free_i32(tmp3);
47058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                break;
47068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            case 6: /* VBIT */
47075285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tmp3 = neon_load_reg(rd, pass);
47085285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                gen_neon_bsl(tmp, tmp, tmp3, tmp2);
47095285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_temp_free_i32(tmp3);
47108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                break;
47118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            case 7: /* VBIF */
47125285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tmp3 = neon_load_reg(rd, pass);
47135285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                gen_neon_bsl(tmp, tmp3, tmp, tmp2);
47145285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_temp_free_i32(tmp3);
47158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                break;
47168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
47178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
47185285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        case NEON_3R_VHSUB:
47198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            GEN_NEON_INTEGER_OP(hsub);
47208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
47215285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        case NEON_3R_VQSUB:
47223d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner            GEN_NEON_INTEGER_OP_ENV(qsub);
47238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
47245285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        case NEON_3R_VCGT:
47258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            GEN_NEON_INTEGER_OP(cgt);
47268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
47275285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        case NEON_3R_VCGE:
47288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            GEN_NEON_INTEGER_OP(cge);
47298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
47305285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        case NEON_3R_VSHL:
47318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            GEN_NEON_INTEGER_OP(shl);
47328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
47335285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        case NEON_3R_VQSHL:
47343d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner            GEN_NEON_INTEGER_OP_ENV(qshl);
47358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
47365285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        case NEON_3R_VRSHL:
47378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            GEN_NEON_INTEGER_OP(rshl);
47388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
47395285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        case NEON_3R_VQRSHL:
47403d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner            GEN_NEON_INTEGER_OP_ENV(qrshl);
47418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
47425285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        case NEON_3R_VMAX:
47438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            GEN_NEON_INTEGER_OP(max);
47448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
47455285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        case NEON_3R_VMIN:
47468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            GEN_NEON_INTEGER_OP(min);
47478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
47485285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        case NEON_3R_VABD:
47498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            GEN_NEON_INTEGER_OP(abd);
47508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
47515285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        case NEON_3R_VABA:
47528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            GEN_NEON_INTEGER_OP(abd);
47535285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tcg_temp_free_i32(tmp2);
47545285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tmp2 = neon_load_reg(rd, pass);
47555285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            gen_neon_add(size, tmp, tmp2);
47568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
47575285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        case NEON_3R_VADD_VSUB:
47588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (!u) { /* VADD */
47595285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                gen_neon_add(size, tmp, tmp2);
47608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            } else { /* VSUB */
47618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                switch (size) {
47625285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                case 0: gen_helper_neon_sub_u8(tmp, tmp, tmp2); break;
47635285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                case 1: gen_helper_neon_sub_u16(tmp, tmp, tmp2); break;
47645285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                case 2: tcg_gen_sub_i32(tmp, tmp, tmp2); break;
47655285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                default: abort();
47668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
47678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
47688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
47695285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        case NEON_3R_VTST_VCEQ:
47708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (!u) { /* VTST */
47718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                switch (size) {
47725285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                case 0: gen_helper_neon_tst_u8(tmp, tmp, tmp2); break;
47735285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                case 1: gen_helper_neon_tst_u16(tmp, tmp, tmp2); break;
47745285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                case 2: gen_helper_neon_tst_u32(tmp, tmp, tmp2); break;
47755285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                default: abort();
47768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
47778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            } else { /* VCEQ */
47788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                switch (size) {
47795285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                case 0: gen_helper_neon_ceq_u8(tmp, tmp, tmp2); break;
47805285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                case 1: gen_helper_neon_ceq_u16(tmp, tmp, tmp2); break;
47815285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                case 2: gen_helper_neon_ceq_u32(tmp, tmp, tmp2); break;
47825285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                default: abort();
47838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
47848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
47858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
47865285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        case NEON_3R_VML: /* VMLA, VMLAL, VMLS,VMLSL */
47878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            switch (size) {
47885285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            case 0: gen_helper_neon_mul_u8(tmp, tmp, tmp2); break;
47895285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            case 1: gen_helper_neon_mul_u16(tmp, tmp, tmp2); break;
47905285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            case 2: tcg_gen_mul_i32(tmp, tmp, tmp2); break;
47915285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            default: abort();
47928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
47935285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tcg_temp_free_i32(tmp2);
47945285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tmp2 = neon_load_reg(rd, pass);
47958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (u) { /* VMLS */
47965285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                gen_neon_rsb(size, tmp, tmp2);
47978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            } else { /* VMLA */
47985285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                gen_neon_add(size, tmp, tmp2);
47998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
48008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
48015285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        case NEON_3R_VMUL:
48028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (u) { /* polynomial */
48035285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                gen_helper_neon_mul_p8(tmp, tmp, tmp2);
48048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            } else { /* Integer */
48058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                switch (size) {
48065285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                case 0: gen_helper_neon_mul_u8(tmp, tmp, tmp2); break;
48075285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                case 1: gen_helper_neon_mul_u16(tmp, tmp, tmp2); break;
48085285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                case 2: tcg_gen_mul_i32(tmp, tmp, tmp2); break;
48095285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                default: abort();
48108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
48118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
48128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
48135285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        case NEON_3R_VPMAX:
48148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            GEN_NEON_INTEGER_OP(pmax);
48158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
48165285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        case NEON_3R_VPMIN:
48178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            GEN_NEON_INTEGER_OP(pmin);
48188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
48195285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        case NEON_3R_VQDMULH_VQRDMULH: /* Multiply high.  */
48208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (!u) { /* VQDMULH */
48218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                switch (size) {
48223d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner                case 1:
48233d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner                    gen_helper_neon_qdmulh_s16(tmp, cpu_env, tmp, tmp2);
48243d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner                    break;
48253d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner                case 2:
48263d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner                    gen_helper_neon_qdmulh_s32(tmp, cpu_env, tmp, tmp2);
48273d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner                    break;
48285285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                default: abort();
48298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
48305285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            } else { /* VQRDMULH */
48318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                switch (size) {
48323d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner                case 1:
48333d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner                    gen_helper_neon_qrdmulh_s16(tmp, cpu_env, tmp, tmp2);
48343d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner                    break;
48353d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner                case 2:
48363d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner                    gen_helper_neon_qrdmulh_s32(tmp, cpu_env, tmp, tmp2);
48373d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner                    break;
48385285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                default: abort();
48398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
48408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
48418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
48425285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        case NEON_3R_VPADD:
48438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            switch (size) {
48445285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            case 0: gen_helper_neon_padd_u8(tmp, tmp, tmp2); break;
48455285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            case 1: gen_helper_neon_padd_u16(tmp, tmp, tmp2); break;
48465285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            case 2: tcg_gen_add_i32(tmp, tmp, tmp2); break;
48475285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            default: abort();
48488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
48498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
48505285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        case NEON_3R_FLOAT_ARITH: /* Floating point arithmetic. */
485116998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner        {
485216998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner            TCGv_ptr fpstatus = get_fpstatus_ptr(1);
48538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            switch ((u << 2) | size) {
48548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            case 0: /* VADD */
485516998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner            case 4: /* VPADD */
485616998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner                gen_helper_vfp_adds(tmp, tmp, tmp2, fpstatus);
48578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                break;
48588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            case 2: /* VSUB */
485916998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner                gen_helper_vfp_subs(tmp, tmp, tmp2, fpstatus);
48608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                break;
48618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            case 6: /* VABD */
486216998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner                gen_helper_neon_abd_f32(tmp, tmp, tmp2, fpstatus);
48638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                break;
48648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            default:
48655285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                abort();
48668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
486716998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner            tcg_temp_free_ptr(fpstatus);
48688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
486916998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner        }
48705285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        case NEON_3R_FLOAT_MULTIPLY:
487116998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner        {
487216998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner            TCGv_ptr fpstatus = get_fpstatus_ptr(1);
487316998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner            gen_helper_vfp_muls(tmp, tmp, tmp2, fpstatus);
48748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (!u) {
48755285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_temp_free_i32(tmp2);
48765285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tmp2 = neon_load_reg(rd, pass);
48778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (size == 0) {
487816998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner                    gen_helper_vfp_adds(tmp, tmp, tmp2, fpstatus);
48798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                } else {
488016998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner                    gen_helper_vfp_subs(tmp, tmp2, tmp, fpstatus);
48818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
48828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
488316998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner            tcg_temp_free_ptr(fpstatus);
48848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
488516998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner        }
48865285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        case NEON_3R_FLOAT_CMP:
488716998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner        {
488816998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner            TCGv_ptr fpstatus = get_fpstatus_ptr(1);
48898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (!u) {
489016998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner                gen_helper_neon_ceq_f32(tmp, tmp, tmp2, fpstatus);
48918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            } else {
489216998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner                if (size == 0) {
489316998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner                    gen_helper_neon_cge_f32(tmp, tmp, tmp2, fpstatus);
489416998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner                } else {
489516998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner                    gen_helper_neon_cgt_f32(tmp, tmp, tmp2, fpstatus);
489616998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner                }
48978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
489816998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner            tcg_temp_free_ptr(fpstatus);
48998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
490016998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner        }
49015285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        case NEON_3R_FLOAT_ACMP:
490216998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner        {
490316998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner            TCGv_ptr fpstatus = get_fpstatus_ptr(1);
490416998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner            if (size == 0) {
490516998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner                gen_helper_neon_acge_f32(tmp, tmp, tmp2, fpstatus);
490616998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner            } else {
490716998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner                gen_helper_neon_acgt_f32(tmp, tmp, tmp2, fpstatus);
490816998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner            }
490916998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner            tcg_temp_free_ptr(fpstatus);
49108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
491116998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner        }
49125285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        case NEON_3R_FLOAT_MINMAX:
491316998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner        {
491416998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner            TCGv_ptr fpstatus = get_fpstatus_ptr(1);
491516998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner            if (size == 0) {
491616998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner                gen_helper_neon_max_f32(tmp, tmp, tmp2, fpstatus);
491716998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner            } else {
491816998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner                gen_helper_neon_min_f32(tmp, tmp, tmp2, fpstatus);
491916998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner            }
492016998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner            tcg_temp_free_ptr(fpstatus);
49218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
492216998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner        }
49235285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        case NEON_3R_VRECPS_VRSQRTS:
49248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (size == 0)
49255285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                gen_helper_recps_f32(tmp, tmp, tmp2, cpu_env);
49268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            else
49275285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                gen_helper_rsqrts_f32(tmp, tmp, tmp2, cpu_env);
49288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
49298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        default:
49308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            abort();
49318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
49325285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tcg_temp_free_i32(tmp2);
49335285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
49348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* Save the result.  For elementwise operations we can put it
49358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project           straight into the destination register.  For pairwise operations
49368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project           we have to be careful to avoid clobbering the source operands.  */
49378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (pairwise && rd == rm) {
49385285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            neon_store_scratch(pass, tmp);
49398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        } else {
49405285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            neon_store_reg(rd, pass, tmp);
49418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
49428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
49438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        } /* for pass */
49448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (pairwise && rd == rm) {
49458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            for (pass = 0; pass < (q ? 4 : 2); pass++) {
49465285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tmp = neon_load_scratch(pass);
49475285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                neon_store_reg(rd, pass, tmp);
49488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
49498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
49508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* End of 3 register same size operations.  */
49518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } else if (insn & (1 << 4)) {
49528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if ((insn & 0x00380080) != 0) {
49538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* Two registers and shift.  */
49548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            op = (insn >> 8) & 0xf;
49558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (insn & (1 << 7)) {
49565285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                /* 64-bit shift. */
49575285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                if (op > 7) {
49585285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    return 1;
49595285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                }
49608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                size = 3;
49618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            } else {
49628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                size = 2;
49638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                while ((insn & (1 << (size + 19))) == 0)
49648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    size--;
49658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
49668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            shift = (insn >> 16) & ((1 << (3 + size)) - 1);
49678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* To avoid excessive dumplication of ops we implement shift
49688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project               by immediate using the variable shift operations.  */
49698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (op < 8) {
49708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* Shift by immediate:
49718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                   VSHR, VSRA, VRSHR, VRSRA, VSRI, VSHL, VQSHL, VQSHLU.  */
49725285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                if (q && ((rd | rm) & 1)) {
49735285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    return 1;
49745285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                }
49755285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                if (!u && (op == 4 || op == 6)) {
49765285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    return 1;
49775285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                }
49788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* Right shifts are encoded as N - shift, where N is the
49798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                   element size in bits.  */
49808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (op <= 4)
49818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    shift = shift - (1 << (size + 3));
49828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (size == 3) {
49838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    count = q + 1;
49848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                } else {
49858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    count = q ? 4: 2;
49868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
49878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                switch (size) {
49888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                case 0:
49898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    imm = (uint8_t) shift;
49908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    imm |= imm << 8;
49918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    imm |= imm << 16;
49928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    break;
49938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                case 1:
49948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    imm = (uint16_t) shift;
49958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    imm |= imm << 16;
49968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    break;
49978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                case 2:
49988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                case 3:
49998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    imm = shift;
50008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    break;
50018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                default:
50028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    abort();
50038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
50048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
50058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                for (pass = 0; pass < count; pass++) {
50068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if (size == 3) {
50078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        neon_load_reg64(cpu_V0, rm + pass);
50088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        tcg_gen_movi_i64(cpu_V1, imm);
50098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        switch (op) {
50108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        case 0:  /* VSHR */
50118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        case 1:  /* VSRA */
50128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            if (u)
50138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                gen_helper_neon_shl_u64(cpu_V0, cpu_V0, cpu_V1);
50148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            else
50158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                gen_helper_neon_shl_s64(cpu_V0, cpu_V0, cpu_V1);
50168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            break;
50178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        case 2: /* VRSHR */
50188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        case 3: /* VRSRA */
50198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            if (u)
50208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                gen_helper_neon_rshl_u64(cpu_V0, cpu_V0, cpu_V1);
50218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            else
50228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                gen_helper_neon_rshl_s64(cpu_V0, cpu_V0, cpu_V1);
50238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            break;
50248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        case 4: /* VSRI */
50258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        case 5: /* VSHL, VSLI */
50268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            gen_helper_neon_shl_u64(cpu_V0, cpu_V0, cpu_V1);
50278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            break;
50285285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        case 6: /* VQSHLU */
50293d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner                            gen_helper_neon_qshlu_s64(cpu_V0, cpu_env,
50303d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner                                                      cpu_V0, cpu_V1);
50318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            break;
50325285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        case 7: /* VQSHL */
50335285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            if (u) {
50343d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner                                gen_helper_neon_qshl_u64(cpu_V0, cpu_env,
50355285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                                                         cpu_V0, cpu_V1);
50365285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            } else {
50373d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner                                gen_helper_neon_qshl_s64(cpu_V0, cpu_env,
50385285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                                                         cpu_V0, cpu_V1);
50395285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            }
50408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            break;
50418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        }
50428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        if (op == 1 || op == 3) {
50438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            /* Accumulate.  */
50445285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            neon_load_reg64(cpu_V1, rd + pass);
50458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            tcg_gen_add_i64(cpu_V0, cpu_V0, cpu_V1);
50468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        } else if (op == 4 || (op == 5 && u)) {
50478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            /* Insert */
50485285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            neon_load_reg64(cpu_V1, rd + pass);
50495285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            uint64_t mask;
50505285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            if (shift < -63 || shift > 63) {
50515285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                                mask = 0;
50525285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            } else {
50535285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                                if (op == 4) {
50545285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                                    mask = 0xffffffffffffffffull >> -shift;
50555285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                                } else {
50565285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                                    mask = 0xffffffffffffffffull << shift;
50575285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                                }
50585285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            }
50595285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            tcg_gen_andi_i64(cpu_V1, cpu_V1, ~mask);
50605285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            tcg_gen_or_i64(cpu_V0, cpu_V0, cpu_V1);
50618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        }
50628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        neon_store_reg64(cpu_V0, rd + pass);
50638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    } else { /* size < 3 */
50648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        /* Operands in T0 and T1.  */
50655285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tmp = neon_load_reg(rm, pass);
50665285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tmp2 = tcg_const_i32(imm);
50678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        switch (op) {
50688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        case 0:  /* VSHR */
50698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        case 1:  /* VSRA */
50708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            GEN_NEON_INTEGER_OP(shl);
50718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            break;
50728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        case 2: /* VRSHR */
50738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        case 3: /* VRSRA */
50748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            GEN_NEON_INTEGER_OP(rshl);
50758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            break;
50768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        case 4: /* VSRI */
50778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        case 5: /* VSHL, VSLI */
50788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            switch (size) {
50795285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            case 0: gen_helper_neon_shl_u8(tmp, tmp, tmp2); break;
50805285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            case 1: gen_helper_neon_shl_u16(tmp, tmp, tmp2); break;
50815285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            case 2: gen_helper_neon_shl_u32(tmp, tmp, tmp2); break;
50825285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            default: abort();
50838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            }
50848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            break;
50855285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        case 6: /* VQSHLU */
50868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            switch (size) {
50875285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            case 0:
50883d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner                                gen_helper_neon_qshlu_s8(tmp, cpu_env,
50893d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner                                                         tmp, tmp2);
50905285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                                break;
50915285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            case 1:
50923d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner                                gen_helper_neon_qshlu_s16(tmp, cpu_env,
50933d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner                                                          tmp, tmp2);
50945285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                                break;
50955285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            case 2:
50963d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner                                gen_helper_neon_qshlu_s32(tmp, cpu_env,
50973d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner                                                          tmp, tmp2);
50985285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                                break;
50995285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            default:
51005285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                                abort();
51018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            }
51028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            break;
51035285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        case 7: /* VQSHL */
51043d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner                            GEN_NEON_INTEGER_OP_ENV(qshl);
51055285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            break;
51068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        }
51075285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tcg_temp_free_i32(tmp2);
51088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
51098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        if (op == 1 || op == 3) {
51108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            /* Accumulate.  */
51115285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            tmp2 = neon_load_reg(rd, pass);
51125285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            gen_neon_add(size, tmp, tmp2);
51135285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            tcg_temp_free_i32(tmp2);
51148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        } else if (op == 4 || (op == 5 && u)) {
51158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            /* Insert */
51168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            switch (size) {
51178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            case 0:
51188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                if (op == 4)
51195285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                                    mask = 0xff >> -shift;
51208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                else
51215285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                                    mask = (uint8_t)(0xff << shift);
51225285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                                mask |= mask << 8;
51235285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                                mask |= mask << 16;
51248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                break;
51258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            case 1:
51268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                if (op == 4)
51275285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                                    mask = 0xffff >> -shift;
51288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                else
51295285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                                    mask = (uint16_t)(0xffff << shift);
51305285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                                mask |= mask << 16;
51318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                break;
51328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            case 2:
51335285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                                if (shift < -31 || shift > 31) {
51345285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                                    mask = 0;
51355285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                                } else {
51365285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                                    if (op == 4)
51375285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                                        mask = 0xffffffffu >> -shift;
51385285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                                    else
51395285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                                        mask = 0xffffffffu << shift;
51405285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                                }
51418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                break;
51428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            default:
51438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                abort();
51448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            }
51455285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            tmp2 = neon_load_reg(rd, pass);
51465285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            tcg_gen_andi_i32(tmp, tmp, mask);
51475285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            tcg_gen_andi_i32(tmp2, tmp2, ~mask);
51485285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            tcg_gen_or_i32(tmp, tmp, tmp2);
51495285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            tcg_temp_free_i32(tmp2);
51508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        }
51515285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        neon_store_reg(rd, pass, tmp);
51528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
51538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                } /* for pass */
51548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            } else if (op < 10) {
51558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* Shift by immediate and narrow:
51568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                   VSHRN, VRSHRN, VQSHRN, VQRSHRN.  */
51575285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                int input_unsigned = (op == 8) ? !u : u;
51585285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                if (rm & 1) {
51595285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    return 1;
51605285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                }
51618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                shift = shift - (1 << (size + 3));
51628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                size++;
51635285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                if (size == 3) {
51645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                    tmp64 = tcg_const_i64(shift);
51655285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    neon_load_reg64(cpu_V0, rm);
51665285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    neon_load_reg64(cpu_V1, rm + 1);
51675285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    for (pass = 0; pass < 2; pass++) {
51685285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        TCGv_i64 in;
51695285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        if (pass == 0) {
51705285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            in = cpu_V0;
51715285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        } else {
51725285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            in = cpu_V1;
51735285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        }
51748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        if (q) {
51755285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            if (input_unsigned) {
51765285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                                gen_helper_neon_rshl_u64(cpu_V0, in, tmp64);
51775285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            } else {
51785285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                                gen_helper_neon_rshl_s64(cpu_V0, in, tmp64);
51795285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            }
51808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        } else {
51815285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            if (input_unsigned) {
51825285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                                gen_helper_neon_shl_u64(cpu_V0, in, tmp64);
51835285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            } else {
51845285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                                gen_helper_neon_shl_s64(cpu_V0, in, tmp64);
51855285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            }
51868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        }
51875285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tmp = tcg_temp_new_i32();
51885285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        gen_neon_narrow_op(op == 8, u, size - 1, tmp, cpu_V0);
51895285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        neon_store_reg(rd, pass, tmp);
51905285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    } /* for pass */
51915285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tcg_temp_free_i64(tmp64);
51925285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                } else {
51935285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    if (size == 1) {
51945285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        imm = (uint16_t)shift;
51955285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        imm |= imm << 16;
51968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    } else {
51975285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        /* size == 2 */
51985285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        imm = (uint32_t)shift;
51998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
52005285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tmp2 = tcg_const_i32(imm);
52015285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tmp4 = neon_load_reg(rm + 1, 0);
52025285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tmp5 = neon_load_reg(rm + 1, 1);
52035285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    for (pass = 0; pass < 2; pass++) {
52045285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        if (pass == 0) {
52055285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            tmp = neon_load_reg(rm, 0);
52065285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        } else {
52075285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            tmp = tmp4;
52085285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        }
52095285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        gen_neon_shift_narrow(size, tmp, tmp2, q,
52105285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                                              input_unsigned);
52115285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        if (pass == 0) {
52125285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            tmp3 = neon_load_reg(rm, 1);
52135285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        } else {
52145285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            tmp3 = tmp5;
52155285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        }
52165285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        gen_neon_shift_narrow(size, tmp3, tmp2, q,
52175285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                                              input_unsigned);
52185285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tcg_gen_concat_i32_i64(cpu_V0, tmp, tmp3);
52195285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tcg_temp_free_i32(tmp);
52205285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tcg_temp_free_i32(tmp3);
52215285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tmp = tcg_temp_new_i32();
52225285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        gen_neon_narrow_op(op == 8, u, size - 1, tmp, cpu_V0);
52235285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        neon_store_reg(rd, pass, tmp);
52245285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    } /* for pass */
52255285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tcg_temp_free_i32(tmp2);
52265285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                }
52278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            } else if (op == 10) {
52285285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                /* VSHLL, VMOVL */
52295285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                if (q || (rd & 1)) {
52308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    return 1;
52315285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                }
52328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                tmp = neon_load_reg(rm, 0);
52338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                tmp2 = neon_load_reg(rm, 1);
52348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                for (pass = 0; pass < 2; pass++) {
52358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if (pass == 1)
52368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        tmp = tmp2;
52378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
52388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    gen_neon_widen(cpu_V0, tmp, size, u);
52398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
52408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if (shift != 0) {
52418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        /* The shift is less than the width of the source
52428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                           type, so we can just shift the whole register.  */
52438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        tcg_gen_shli_i64(cpu_V0, cpu_V0, shift);
52445285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        /* Widen the result of shift: we need to clear
52455285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                         * the potential overflow bits resulting from
52465285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                         * left bits of the narrow input appearing as
52475285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                         * right bits of left the neighbour narrow
52485285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                         * input.  */
52498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        if (size < 2 || !u) {
52508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            uint64_t imm64;
52518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            if (size == 0) {
52528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                imm = (0xffu >> (8 - shift));
52538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                imm |= imm << 16;
52545285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            } else if (size == 1) {
52558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                imm = 0xffff >> (16 - shift);
52565285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            } else {
52575285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                                /* size == 2 */
52585285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                                imm = 0xffffffff >> (32 - shift);
52598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            }
52605285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            if (size < 2) {
52615285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                                imm64 = imm | (((uint64_t)imm) << 32);
52625285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            } else {
52635285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                                imm64 = imm;
52645285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            }
52655285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            tcg_gen_andi_i64(cpu_V0, cpu_V0, ~imm64);
52668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        }
52678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
52688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    neon_store_reg64(cpu_V0, rd + pass);
52698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
52705285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            } else if (op >= 14) {
52718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* VCVT fixed-point.  */
52725285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                if (!(insn & (1 << 21)) || (q && ((rd | rm) & 1))) {
52735285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    return 1;
52745285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                }
52755285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                /* We have already masked out the must-be-1 top bit of imm6,
52765285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                 * hence this 32-shift where the ARM ARM has 64-imm6.
52775285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                 */
52785285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                shift = 32 - shift;
52798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                for (pass = 0; pass < (q ? 4 : 2); pass++) {
52808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, pass));
52815285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    if (!(op & 1)) {
52828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        if (u)
52835285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            gen_vfp_ulto(0, shift, 1);
52848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        else
52855285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            gen_vfp_slto(0, shift, 1);
52868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    } else {
52878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        if (u)
52885285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            gen_vfp_toul(0, shift, 1);
52898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        else
52905285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            gen_vfp_tosl(0, shift, 1);
52918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
52928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, pass));
52938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
52948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            } else {
52958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                return 1;
52968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
52978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        } else { /* (insn & 0x00380080) == 0 */
52988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            int invert;
52995285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            if (q && (rd & 1)) {
53005285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                return 1;
53015285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            }
53028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
53038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            op = (insn >> 8) & 0xf;
53048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* One register and immediate.  */
53058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            imm = (u << 7) | ((insn >> 12) & 0x70) | (insn & 0xf);
53068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            invert = (insn & (1 << 5)) != 0;
53075285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            /* Note that op = 2,3,4,5,6,7,10,11,12,13 imm=0 is UNPREDICTABLE.
53085285864985be9077e58e42235af6582dee72e841David 'Digit' Turner             * We choose to not special-case this and will behave as if a
53095285864985be9077e58e42235af6582dee72e841David 'Digit' Turner             * valid constant encoding of 0 had been given.
53105285864985be9077e58e42235af6582dee72e841David 'Digit' Turner             */
53118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            switch (op) {
53128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            case 0: case 1:
53138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* no-op */
53148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                break;
53158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            case 2: case 3:
53168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                imm <<= 8;
53178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                break;
53188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            case 4: case 5:
53198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                imm <<= 16;
53208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                break;
53218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            case 6: case 7:
53228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                imm <<= 24;
53238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                break;
53248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            case 8: case 9:
53258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                imm |= imm << 16;
53268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                break;
53278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            case 10: case 11:
53288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                imm = (imm << 8) | (imm << 24);
53298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                break;
53308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            case 12:
53315285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                imm = (imm << 8) | 0xff;
53328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                break;
53338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            case 13:
53348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                imm = (imm << 16) | 0xffff;
53358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                break;
53368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            case 14:
53378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                imm |= (imm << 8) | (imm << 16) | (imm << 24);
53388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (invert)
53398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    imm = ~imm;
53408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                break;
53418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            case 15:
53425285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                if (invert) {
53435285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    return 1;
53445285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                }
53458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                imm = ((imm & 0x80) << 24) | ((imm & 0x3f) << 19)
53468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                      | ((imm & 0x40) ? (0x1f << 25) : (1 << 30));
53478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                break;
53488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
53498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (invert)
53508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                imm = ~imm;
53518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
53528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            for (pass = 0; pass < (q ? 4 : 2); pass++) {
53538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (op & 1 && op < 12) {
53548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    tmp = neon_load_reg(rd, pass);
53558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if (invert) {
53568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        /* The immediate value has already been inverted, so
53578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                           BIC becomes AND.  */
53588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        tcg_gen_andi_i32(tmp, tmp, imm);
53598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    } else {
53608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        tcg_gen_ori_i32(tmp, tmp, imm);
53618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
53628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                } else {
53638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    /* VMOV, VMVN.  */
53645285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tmp = tcg_temp_new_i32();
53658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if (op == 14 && invert) {
53665285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        int n;
53678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        uint32_t val;
53688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        val = 0;
53698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        for (n = 0; n < 4; n++) {
53708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            if (imm & (1 << (n + (pass & 1) * 4)))
53718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                val |= 0xff << (n * 8);
53728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        }
53738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        tcg_gen_movi_i32(tmp, val);
53748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    } else {
53758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        tcg_gen_movi_i32(tmp, imm);
53768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
53778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
53788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                neon_store_reg(rd, pass, tmp);
53798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
53808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
53815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    } else { /* (insn & 0x00800010 == 0x00800000) */
53828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (size != 3) {
53838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            op = (insn >> 8) & 0xf;
53848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if ((insn & (1 << 6)) == 0) {
53858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* Three registers of different lengths.  */
53868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                int src1_wide;
53878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                int src2_wide;
53888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                int prewiden;
53895285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                /* undefreq: bit 0 : UNDEF if size != 0
53905285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                 *           bit 1 : UNDEF if size == 0
53915285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                 *           bit 2 : UNDEF if U == 1
53925285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                 * Note that [1:0] set implies 'always UNDEF'
53935285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                 */
53945285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                int undefreq;
53955285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                /* prewiden, src1_wide, src2_wide, undefreq */
53965285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                static const int neon_3reg_wide[16][4] = {
53975285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    {1, 0, 0, 0}, /* VADDL */
53985285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    {1, 1, 0, 0}, /* VADDW */
53995285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    {1, 0, 0, 0}, /* VSUBL */
54005285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    {1, 1, 0, 0}, /* VSUBW */
54015285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    {0, 1, 1, 0}, /* VADDHN */
54025285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    {0, 0, 0, 0}, /* VABAL */
54035285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    {0, 1, 1, 0}, /* VSUBHN */
54045285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    {0, 0, 0, 0}, /* VABDL */
54055285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    {0, 0, 0, 0}, /* VMLAL */
54065285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    {0, 0, 0, 6}, /* VQDMLAL */
54075285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    {0, 0, 0, 0}, /* VMLSL */
54085285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    {0, 0, 0, 6}, /* VQDMLSL */
54095285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    {0, 0, 0, 0}, /* Integer VMULL */
54105285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    {0, 0, 0, 2}, /* VQDMULL */
54115285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    {0, 0, 0, 5}, /* Polynomial VMULL */
54125285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    {0, 0, 0, 3}, /* Reserved: always UNDEF */
54138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                };
54148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
54158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                prewiden = neon_3reg_wide[op][0];
54168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                src1_wide = neon_3reg_wide[op][1];
54178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                src2_wide = neon_3reg_wide[op][2];
54185285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                undefreq = neon_3reg_wide[op][3];
54198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
54205285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                if (((undefreq & 1) && (size != 0)) ||
54215285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    ((undefreq & 2) && (size == 0)) ||
54225285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    ((undefreq & 4) && u)) {
54235285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    return 1;
54245285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                }
54255285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                if ((src1_wide && (rn & 1)) ||
54265285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    (src2_wide && (rm & 1)) ||
54275285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    (!src2_wide && (rd & 1))) {
54288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    return 1;
54295285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                }
54308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
54318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* Avoid overlapping operands.  Wide source operands are
54328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                   always aligned so will never overlap with wide
54338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                   destinations in problematic ways.  */
54348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (rd == rm && !src2_wide) {
54355285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tmp = neon_load_reg(rm, 1);
54365285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    neon_store_scratch(2, tmp);
54378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                } else if (rd == rn && !src1_wide) {
54385285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tmp = neon_load_reg(rn, 1);
54395285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    neon_store_scratch(2, tmp);
54408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
54418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                TCGV_UNUSED(tmp3);
54428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                for (pass = 0; pass < 2; pass++) {
54438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if (src1_wide) {
54448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        neon_load_reg64(cpu_V0, rn + pass);
54458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        TCGV_UNUSED(tmp);
54468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    } else {
54478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        if (pass == 1 && rd == rn) {
54485285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            tmp = neon_load_scratch(2);
54498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        } else {
54508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            tmp = neon_load_reg(rn, pass);
54518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        }
54528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        if (prewiden) {
54538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            gen_neon_widen(cpu_V0, tmp, size, u);
54548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        }
54558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
54568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if (src2_wide) {
54578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        neon_load_reg64(cpu_V1, rm + pass);
54588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        TCGV_UNUSED(tmp2);
54598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    } else {
54608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        if (pass == 1 && rd == rm) {
54615285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            tmp2 = neon_load_scratch(2);
54628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        } else {
54638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            tmp2 = neon_load_reg(rm, pass);
54648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        }
54658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        if (prewiden) {
54668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            gen_neon_widen(cpu_V1, tmp2, size, u);
54678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        }
54688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
54698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    switch (op) {
54708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    case 0: case 1: case 4: /* VADDL, VADDW, VADDHN, VRADDHN */
54718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        gen_neon_addl(size);
54728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        break;
54735285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    case 2: case 3: case 6: /* VSUBL, VSUBW, VSUBHN, VRSUBHN */
54748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        gen_neon_subl(size);
54758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        break;
54768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    case 5: case 7: /* VABAL, VABDL */
54778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        switch ((size << 1) | u) {
54788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        case 0:
54798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            gen_helper_neon_abdl_s16(cpu_V0, tmp, tmp2);
54808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            break;
54818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        case 1:
54828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            gen_helper_neon_abdl_u16(cpu_V0, tmp, tmp2);
54838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            break;
54848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        case 2:
54858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            gen_helper_neon_abdl_s32(cpu_V0, tmp, tmp2);
54868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            break;
54878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        case 3:
54888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            gen_helper_neon_abdl_u32(cpu_V0, tmp, tmp2);
54898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            break;
54908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        case 4:
54918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            gen_helper_neon_abdl_s64(cpu_V0, tmp, tmp2);
54928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            break;
54938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        case 5:
54948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            gen_helper_neon_abdl_u64(cpu_V0, tmp, tmp2);
54958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            break;
54968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        default: abort();
54978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        }
54985285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tcg_temp_free_i32(tmp2);
54995285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tcg_temp_free_i32(tmp);
55008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        break;
55018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    case 8: case 9: case 10: case 11: case 12: case 13:
55028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        /* VMLAL, VQDMLAL, VMLSL, VQDMLSL, VMULL, VQDMULL */
55038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        gen_neon_mull(cpu_V0, tmp, tmp2, size, u);
55048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        break;
55058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    case 14: /* Polynomial VMULL */
55065285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        gen_helper_neon_mull_p8(cpu_V0, tmp, tmp2);
55075285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tcg_temp_free_i32(tmp2);
55085285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tcg_temp_free_i32(tmp);
55095285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        break;
55105285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    default: /* 15 is RESERVED: caught earlier  */
55115285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        abort();
55125285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    }
55135285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    if (op == 13) {
55145285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        /* VQDMULL */
55155285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
55165285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        neon_store_reg64(cpu_V0, rd + pass);
55175285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    } else if (op == 5 || (op >= 8 && op <= 11)) {
55185285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        /* Accumulate.  */
55195285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        neon_load_reg64(cpu_V1, rd + pass);
55208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        switch (op) {
55215285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        case 10: /* VMLSL */
55225285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            gen_neon_negl(cpu_V0, size);
55235285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            /* Fall through */
55245285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        case 5: case 8: /* VABAL, VMLAL */
55258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            gen_neon_addl(size);
55268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            break;
55278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        case 9: case 11: /* VQDMLAL, VQDMLSL */
55288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
55295285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            if (op == 11) {
55305285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                                gen_neon_negl(cpu_V0, size);
55315285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            }
55328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            gen_neon_addl_saturate(cpu_V0, cpu_V1, size);
55338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            break;
55348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        default:
55358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            abort();
55368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        }
55378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        neon_store_reg64(cpu_V0, rd + pass);
55388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    } else if (op == 4 || op == 6) {
55398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        /* Narrowing operation.  */
55405285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tmp = tcg_temp_new_i32();
55415285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        if (!u) {
55428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            switch (size) {
55438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            case 0:
55448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                gen_helper_neon_narrow_high_u8(tmp, cpu_V0);
55458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                break;
55468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            case 1:
55478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                gen_helper_neon_narrow_high_u16(tmp, cpu_V0);
55488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                break;
55498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            case 2:
55508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                tcg_gen_shri_i64(cpu_V0, cpu_V0, 32);
55518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                tcg_gen_trunc_i64_i32(tmp, cpu_V0);
55528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                break;
55538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            default: abort();
55548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            }
55558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        } else {
55568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            switch (size) {
55578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            case 0:
55588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                gen_helper_neon_narrow_round_high_u8(tmp, cpu_V0);
55598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                break;
55608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            case 1:
55618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                gen_helper_neon_narrow_round_high_u16(tmp, cpu_V0);
55628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                break;
55638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            case 2:
55648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                tcg_gen_addi_i64(cpu_V0, cpu_V0, 1u << 31);
55658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                tcg_gen_shri_i64(cpu_V0, cpu_V0, 32);
55668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                tcg_gen_trunc_i64_i32(tmp, cpu_V0);
55678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                break;
55688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            default: abort();
55698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            }
55708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        }
55718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        if (pass == 0) {
55728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            tmp3 = tmp;
55738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        } else {
55748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            neon_store_reg(rd, 0, tmp3);
55758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            neon_store_reg(rd, 1, tmp);
55768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        }
55778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    } else {
55788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        /* Write back the result.  */
55798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        neon_store_reg64(cpu_V0, rd + pass);
55808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
55818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
55828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            } else {
55835285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                /* Two registers and a scalar. NB that for ops of this form
55845285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                 * the ARM ARM labels bit 24 as Q, but it is in our variable
55855285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                 * 'u', not 'q'.
55865285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                 */
55875285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                if (size == 0) {
55885285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    return 1;
55895285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                }
55908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                switch (op) {
55918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                case 1: /* Float VMLA scalar */
55928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                case 5: /* Floating point VMLS scalar */
55938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                case 9: /* Floating point VMUL scalar */
55945285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    if (size == 1) {
55955285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        return 1;
55965285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    }
55975285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    /* fall through */
55985285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                case 0: /* Integer VMLA scalar */
55995285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                case 4: /* Integer VMLS scalar */
56005285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                case 8: /* Integer VMUL scalar */
56018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                case 12: /* VQDMULH scalar */
56028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                case 13: /* VQRDMULH scalar */
56035285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    if (u && ((rd | rn) & 1)) {
56045285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        return 1;
56055285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    }
56065285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tmp = neon_get_scalar(size, rm);
56075285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    neon_store_scratch(0, tmp);
56088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    for (pass = 0; pass < (u ? 4 : 2); pass++) {
56095285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tmp = neon_load_scratch(0);
56105285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tmp2 = neon_load_reg(rn, pass);
56118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        if (op == 12) {
56128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            if (size == 1) {
56133d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner                                gen_helper_neon_qdmulh_s16(tmp, cpu_env, tmp, tmp2);
56148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            } else {
56153d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner                                gen_helper_neon_qdmulh_s32(tmp, cpu_env, tmp, tmp2);
56168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            }
56178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        } else if (op == 13) {
56188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            if (size == 1) {
56193d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner                                gen_helper_neon_qrdmulh_s16(tmp, cpu_env, tmp, tmp2);
56208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            } else {
56213d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner                                gen_helper_neon_qrdmulh_s32(tmp, cpu_env, tmp, tmp2);
56228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            }
56238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        } else if (op & 1) {
562416998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner                            TCGv_ptr fpstatus = get_fpstatus_ptr(1);
562516998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner                            gen_helper_vfp_muls(tmp, tmp, tmp2, fpstatus);
562616998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner                            tcg_temp_free_ptr(fpstatus);
56278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        } else {
56288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            switch (size) {
56295285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            case 0: gen_helper_neon_mul_u8(tmp, tmp, tmp2); break;
56305285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            case 1: gen_helper_neon_mul_u16(tmp, tmp, tmp2); break;
56315285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            case 2: tcg_gen_mul_i32(tmp, tmp, tmp2); break;
56325285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            default: abort();
56338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            }
56348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        }
56355285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tcg_temp_free_i32(tmp2);
56368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        if (op < 8) {
56378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            /* Accumulate.  */
56385285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            tmp2 = neon_load_reg(rd, pass);
56398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            switch (op) {
56408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            case 0:
56415285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                                gen_neon_add(size, tmp, tmp2);
56428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                break;
56438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            case 1:
564416998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner                            {
564516998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner                                TCGv_ptr fpstatus = get_fpstatus_ptr(1);
564616998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner                                gen_helper_vfp_adds(tmp, tmp, tmp2, fpstatus);
564716998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner                                tcg_temp_free_ptr(fpstatus);
56488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                break;
564916998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner                            }
56508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            case 4:
56515285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                                gen_neon_rsb(size, tmp, tmp2);
56528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                break;
56538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            case 5:
565416998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner                            {
565516998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner                                TCGv_ptr fpstatus = get_fpstatus_ptr(1);
565616998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner                                gen_helper_vfp_subs(tmp, tmp2, tmp, fpstatus);
565716998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner                                tcg_temp_free_ptr(fpstatus);
56588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                break;
565916998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner                            }
56608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            default:
56618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                abort();
56628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            }
56635285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            tcg_temp_free_i32(tmp2);
56648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        }
56655285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        neon_store_reg(rd, pass, tmp);
56668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
56678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    break;
56688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                case 3: /* VQDMLAL scalar */
56698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                case 7: /* VQDMLSL scalar */
56708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                case 11: /* VQDMULL scalar */
56715285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    if (u == 1) {
56728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        return 1;
56735285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    }
56745285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    /* fall through */
56755285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                case 2: /* VMLAL sclar */
56765285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                case 6: /* VMLSL scalar */
56775285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                case 10: /* VMULL scalar */
56785285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    if (rd & 1) {
56795285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        return 1;
56805285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    }
56815285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tmp2 = neon_get_scalar(size, rm);
56825285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    /* We need a copy of tmp2 because gen_neon_mull
56835285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                     * deletes it during pass 0.  */
56845285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tmp4 = tcg_temp_new_i32();
56855285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tcg_gen_mov_i32(tmp4, tmp2);
56865285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tmp3 = neon_load_reg(rn, 1);
56878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
56888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    for (pass = 0; pass < 2; pass++) {
56898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        if (pass == 0) {
56908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            tmp = neon_load_reg(rn, 0);
56918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        } else {
56925285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            tmp = tmp3;
56935285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            tmp2 = tmp4;
56948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        }
56958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        gen_neon_mull(cpu_V0, tmp, tmp2, size, u);
56968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        if (op != 11) {
56978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            neon_load_reg64(cpu_V1, rd + pass);
56988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        }
56998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        switch (op) {
57005285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        case 6:
57015285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            gen_neon_negl(cpu_V0, size);
57025285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            /* Fall through */
57035285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        case 2:
57048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            gen_neon_addl(size);
57058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            break;
57068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        case 3: case 7:
57078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
57085285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            if (op == 7) {
57095285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                                gen_neon_negl(cpu_V0, size);
57105285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            }
57118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            gen_neon_addl_saturate(cpu_V0, cpu_V1, size);
57128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            break;
57138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        case 10:
57148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            /* no-op */
57158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            break;
57168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        case 11:
57178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
57188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            break;
57198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        default:
57208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            abort();
57218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        }
57228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        neon_store_reg64(cpu_V0, rd + pass);
57238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
57245285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
57255285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
57268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    break;
57278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                default: /* 14 and 15 are RESERVED */
57288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    return 1;
57298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
57308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
57318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        } else { /* size == 3 */
57328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (!u) {
57338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* Extract.  */
57348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                imm = (insn >> 8) & 0xf;
57358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
57368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (imm > 7 && !q)
57378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    return 1;
57388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
57395285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                if (q && ((rd | rn | rm) & 1)) {
57405285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    return 1;
57415285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                }
57425285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
57438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (imm == 0) {
57448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    neon_load_reg64(cpu_V0, rn);
57458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if (q) {
57468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        neon_load_reg64(cpu_V1, rn + 1);
57478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
57488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                } else if (imm == 8) {
57498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    neon_load_reg64(cpu_V0, rn + 1);
57508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if (q) {
57518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        neon_load_reg64(cpu_V1, rm);
57528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
57538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                } else if (q) {
57545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                    tmp64 = tcg_temp_new_i64();
57558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if (imm < 8) {
57568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        neon_load_reg64(cpu_V0, rn);
57575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                        neon_load_reg64(tmp64, rn + 1);
57588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    } else {
57598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        neon_load_reg64(cpu_V0, rn + 1);
57605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                        neon_load_reg64(tmp64, rm);
57618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
57628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    tcg_gen_shri_i64(cpu_V0, cpu_V0, (imm & 7) * 8);
57635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                    tcg_gen_shli_i64(cpu_V1, tmp64, 64 - ((imm & 7) * 8));
57648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    tcg_gen_or_i64(cpu_V0, cpu_V0, cpu_V1);
57658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if (imm < 8) {
57668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        neon_load_reg64(cpu_V1, rm);
57678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    } else {
57688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        neon_load_reg64(cpu_V1, rm + 1);
57698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        imm -= 8;
57708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
57718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    tcg_gen_shli_i64(cpu_V1, cpu_V1, 64 - (imm * 8));
57725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                    tcg_gen_shri_i64(tmp64, tmp64, imm * 8);
57735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                    tcg_gen_or_i64(cpu_V1, cpu_V1, tmp64);
57745285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tcg_temp_free_i64(tmp64);
57758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                } else {
57765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                    /* BUGFIX */
57778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    neon_load_reg64(cpu_V0, rn);
57785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                    tcg_gen_shri_i64(cpu_V0, cpu_V0, imm * 8);
57798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    neon_load_reg64(cpu_V1, rm);
57805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                    tcg_gen_shli_i64(cpu_V1, cpu_V1, 64 - (imm * 8));
57818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    tcg_gen_or_i64(cpu_V0, cpu_V0, cpu_V1);
57828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
57838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                neon_store_reg64(cpu_V0, rd);
57848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (q) {
57858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    neon_store_reg64(cpu_V1, rd + 1);
57868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
57878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            } else if ((insn & (1 << 11)) == 0) {
57888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* Two register misc.  */
57898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                op = ((insn >> 12) & 0x30) | ((insn >> 7) & 0xf);
57908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                size = (insn >> 18) & 3;
57915285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                /* UNDEF for unknown op values and bad op-size combinations */
57925285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                if ((neon_2rm_sizes[op] & (1 << size)) == 0) {
57935285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    return 1;
57945285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                }
57955285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                if ((op != NEON_2RM_VMOVN && op != NEON_2RM_VQMOVN) &&
57965285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    q && ((rm | rd) & 1)) {
57975285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    return 1;
57985285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                }
57998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                switch (op) {
58005285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                case NEON_2RM_VREV64:
58018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    for (pass = 0; pass < (q ? 2 : 1); pass++) {
58025285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tmp = neon_load_reg(rm, pass * 2);
58035285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tmp2 = neon_load_reg(rm, pass * 2 + 1);
58048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        switch (size) {
58055285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        case 0: tcg_gen_bswap32_i32(tmp, tmp); break;
58065285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        case 1: gen_swap_half(tmp); break;
58078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        case 2: /* no-op */ break;
58088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        default: abort();
58098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        }
58105285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        neon_store_reg(rd, pass * 2 + 1, tmp);
58118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        if (size == 2) {
58125285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            neon_store_reg(rd, pass * 2, tmp2);
58138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        } else {
58148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            switch (size) {
58155285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            case 0: tcg_gen_bswap32_i32(tmp2, tmp2); break;
58165285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            case 1: gen_swap_half(tmp2); break;
58178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            default: abort();
58188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            }
58195285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            neon_store_reg(rd, pass * 2, tmp2);
58208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        }
58218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
58228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    break;
58235285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                case NEON_2RM_VPADDL: case NEON_2RM_VPADDL_U:
58245285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                case NEON_2RM_VPADAL: case NEON_2RM_VPADAL_U:
58258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    for (pass = 0; pass < q + 1; pass++) {
58268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        tmp = neon_load_reg(rm, pass * 2);
58278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        gen_neon_widen(cpu_V0, tmp, size, op & 1);
58288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        tmp = neon_load_reg(rm, pass * 2 + 1);
58298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        gen_neon_widen(cpu_V1, tmp, size, op & 1);
58308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        switch (size) {
58318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        case 0: gen_helper_neon_paddl_u16(CPU_V001); break;
58328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        case 1: gen_helper_neon_paddl_u32(CPU_V001); break;
58338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        case 2: tcg_gen_add_i64(CPU_V001); break;
58348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        default: abort();
58358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        }
58365285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        if (op >= NEON_2RM_VPADAL) {
58378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            /* Accumulate.  */
58388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            neon_load_reg64(cpu_V1, rd + pass);
58398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            gen_neon_addl(size);
58408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        }
58418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        neon_store_reg64(cpu_V0, rd + pass);
58428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
58438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    break;
58445285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                case NEON_2RM_VTRN:
58458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if (size == 2) {
58465285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        int n;
58478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        for (n = 0; n < (q ? 4 : 2); n += 2) {
58485285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            tmp = neon_load_reg(rm, n);
58495285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            tmp2 = neon_load_reg(rd, n + 1);
58505285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            neon_store_reg(rm, n, tmp2);
58515285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            neon_store_reg(rd, n + 1, tmp);
58528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        }
58538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    } else {
58548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        goto elementwise;
58558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
58568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    break;
58575285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                case NEON_2RM_VUZP:
58585285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    if (gen_neon_unzip(rd, rm, size, q)) {
58598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        return 1;
58608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
58618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    break;
58625285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                case NEON_2RM_VZIP:
58635285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    if (gen_neon_zip(rd, rm, size, q)) {
58648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        return 1;
58658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
58668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    break;
58675285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                case NEON_2RM_VMOVN: case NEON_2RM_VQMOVN:
58685285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    /* also VQMOVUN; op field and mnemonics don't line up */
58695285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    if (rm & 1) {
58708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        return 1;
58715285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    }
58728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    TCGV_UNUSED(tmp2);
58738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    for (pass = 0; pass < 2; pass++) {
58748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        neon_load_reg64(cpu_V0, rm + pass);
58755285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tmp = tcg_temp_new_i32();
58765285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        gen_neon_narrow_op(op == NEON_2RM_VMOVN, q, size,
58775285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                                           tmp, cpu_V0);
58788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        if (pass == 0) {
58798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            tmp2 = tmp;
58808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        } else {
58818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            neon_store_reg(rd, 0, tmp2);
58828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            neon_store_reg(rd, 1, tmp);
58838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        }
58848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
58858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    break;
58865285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                case NEON_2RM_VSHLL:
58875285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    if (q || (rd & 1)) {
58888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        return 1;
58895285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    }
58908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    tmp = neon_load_reg(rm, 0);
58918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    tmp2 = neon_load_reg(rm, 1);
58928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    for (pass = 0; pass < 2; pass++) {
58938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        if (pass == 1)
58948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            tmp = tmp2;
58958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        gen_neon_widen(cpu_V0, tmp, size, 1);
58965285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tcg_gen_shli_i64(cpu_V0, cpu_V0, 8 << size);
58978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        neon_store_reg64(cpu_V0, rd + pass);
58988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
58998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    break;
59005285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                case NEON_2RM_VCVT_F16_F32:
59015285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    if (!arm_feature(env, ARM_FEATURE_VFP_FP16) ||
59025285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        q || (rm & 1)) {
59035285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        return 1;
59045285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    }
59055285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tmp = tcg_temp_new_i32();
59065285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tmp2 = tcg_temp_new_i32();
59075285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, 0));
59085285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    gen_helper_neon_fcvt_f32_to_f16(tmp, cpu_F0s, cpu_env);
59095285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, 1));
59105285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    gen_helper_neon_fcvt_f32_to_f16(tmp2, cpu_F0s, cpu_env);
59115285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tcg_gen_shli_i32(tmp2, tmp2, 16);
59125285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tcg_gen_or_i32(tmp2, tmp2, tmp);
59135285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, 2));
59145285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    gen_helper_neon_fcvt_f32_to_f16(tmp, cpu_F0s, cpu_env);
59155285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, 3));
59165285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    neon_store_reg(rd, 0, tmp2);
59175285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tmp2 = tcg_temp_new_i32();
59185285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    gen_helper_neon_fcvt_f32_to_f16(tmp2, cpu_F0s, cpu_env);
59195285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tcg_gen_shli_i32(tmp2, tmp2, 16);
59205285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tcg_gen_or_i32(tmp2, tmp2, tmp);
59215285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    neon_store_reg(rd, 1, tmp2);
59225285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tcg_temp_free_i32(tmp);
59235285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    break;
59245285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                case NEON_2RM_VCVT_F32_F16:
59255285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    if (!arm_feature(env, ARM_FEATURE_VFP_FP16) ||
59265285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        q || (rd & 1)) {
59275285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        return 1;
59285285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    }
59295285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tmp3 = tcg_temp_new_i32();
59305285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tmp = neon_load_reg(rm, 0);
59315285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tmp2 = neon_load_reg(rm, 1);
59325285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tcg_gen_ext16u_i32(tmp3, tmp);
59335285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    gen_helper_neon_fcvt_f16_to_f32(cpu_F0s, tmp3, cpu_env);
59345285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, 0));
59355285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tcg_gen_shri_i32(tmp3, tmp, 16);
59365285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    gen_helper_neon_fcvt_f16_to_f32(cpu_F0s, tmp3, cpu_env);
59375285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, 1));
59385285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tcg_temp_free_i32(tmp);
59395285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tcg_gen_ext16u_i32(tmp3, tmp2);
59405285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    gen_helper_neon_fcvt_f16_to_f32(cpu_F0s, tmp3, cpu_env);
59415285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, 2));
59425285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tcg_gen_shri_i32(tmp3, tmp2, 16);
59435285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    gen_helper_neon_fcvt_f16_to_f32(cpu_F0s, tmp3, cpu_env);
59445285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, 3));
59455285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tcg_temp_free_i32(tmp2);
59465285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tcg_temp_free_i32(tmp3);
59475285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    break;
59488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                default:
59498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                elementwise:
59508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    for (pass = 0; pass < (q ? 4 : 2); pass++) {
59515285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        if (neon_2rm_is_float_op(op)) {
59528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            tcg_gen_ld_f32(cpu_F0s, cpu_env,
59538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                           neon_reg_offset(rm, pass));
59545285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            TCGV_UNUSED(tmp);
59558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        } else {
59565285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            tmp = neon_load_reg(rm, pass);
59578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        }
59588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        switch (op) {
59595285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        case NEON_2RM_VREV32:
59608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            switch (size) {
59615285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            case 0: tcg_gen_bswap32_i32(tmp, tmp); break;
59625285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            case 1: gen_swap_half(tmp); break;
59635285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            default: abort();
59648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            }
59658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            break;
59665285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        case NEON_2RM_VREV16:
59675285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            gen_rev16(tmp);
59688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            break;
59695285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        case NEON_2RM_VCLS:
59708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            switch (size) {
59715285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            case 0: gen_helper_neon_cls_s8(tmp, tmp); break;
59725285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            case 1: gen_helper_neon_cls_s16(tmp, tmp); break;
59735285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            case 2: gen_helper_neon_cls_s32(tmp, tmp); break;
59745285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            default: abort();
59758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            }
59768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            break;
59775285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        case NEON_2RM_VCLZ:
59788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            switch (size) {
59795285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            case 0: gen_helper_neon_clz_u8(tmp, tmp); break;
59805285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            case 1: gen_helper_neon_clz_u16(tmp, tmp); break;
59815285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            case 2: gen_helper_clz(tmp, tmp); break;
59825285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            default: abort();
59838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            }
59848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            break;
59855285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        case NEON_2RM_VCNT:
59865285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            gen_helper_neon_cnt_u8(tmp, tmp);
59878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            break;
59885285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        case NEON_2RM_VMVN:
59895285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            tcg_gen_not_i32(tmp, tmp);
59908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            break;
59915285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        case NEON_2RM_VQABS:
59928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            switch (size) {
59933d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner                            case 0:
59943d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner                                gen_helper_neon_qabs_s8(tmp, cpu_env, tmp);
59953d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner                                break;
59963d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner                            case 1:
59973d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner                                gen_helper_neon_qabs_s16(tmp, cpu_env, tmp);
59983d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner                                break;
59993d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner                            case 2:
60003d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner                                gen_helper_neon_qabs_s32(tmp, cpu_env, tmp);
60013d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner                                break;
60025285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            default: abort();
60038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            }
60048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            break;
60055285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        case NEON_2RM_VQNEG:
60068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            switch (size) {
60073d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner                            case 0:
60083d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner                                gen_helper_neon_qneg_s8(tmp, cpu_env, tmp);
60093d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner                                break;
60103d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner                            case 1:
60113d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner                                gen_helper_neon_qneg_s16(tmp, cpu_env, tmp);
60123d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner                                break;
60133d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner                            case 2:
60143d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner                                gen_helper_neon_qneg_s32(tmp, cpu_env, tmp);
60153d323dda130b16c690a78f08b7f766becb84914fDavid 'Digit' Turner                                break;
60165285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            default: abort();
60178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            }
60188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            break;
60195285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        case NEON_2RM_VCGT0: case NEON_2RM_VCLE0:
60205285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            tmp2 = tcg_const_i32(0);
60218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            switch(size) {
60225285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            case 0: gen_helper_neon_cgt_s8(tmp, tmp, tmp2); break;
60235285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            case 1: gen_helper_neon_cgt_s16(tmp, tmp, tmp2); break;
60245285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            case 2: gen_helper_neon_cgt_s32(tmp, tmp, tmp2); break;
60255285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            default: abort();
60265285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            }
60275285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            tcg_temp_free(tmp2);
60285285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            if (op == NEON_2RM_VCLE0) {
60295285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                                tcg_gen_not_i32(tmp, tmp);
60308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            }
60318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            break;
60325285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        case NEON_2RM_VCGE0: case NEON_2RM_VCLT0:
60335285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            tmp2 = tcg_const_i32(0);
60348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            switch(size) {
60355285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            case 0: gen_helper_neon_cge_s8(tmp, tmp, tmp2); break;
60365285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            case 1: gen_helper_neon_cge_s16(tmp, tmp, tmp2); break;
60375285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            case 2: gen_helper_neon_cge_s32(tmp, tmp, tmp2); break;
60385285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            default: abort();
60395285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            }
60405285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            tcg_temp_free(tmp2);
60415285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            if (op == NEON_2RM_VCLT0) {
60425285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                                tcg_gen_not_i32(tmp, tmp);
60438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            }
60448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            break;
60455285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        case NEON_2RM_VCEQ0:
60465285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            tmp2 = tcg_const_i32(0);
60478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            switch(size) {
60485285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            case 0: gen_helper_neon_ceq_u8(tmp, tmp, tmp2); break;
60495285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            case 1: gen_helper_neon_ceq_u16(tmp, tmp, tmp2); break;
60505285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            case 2: gen_helper_neon_ceq_u32(tmp, tmp, tmp2); break;
60515285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            default: abort();
60528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            }
60535285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            tcg_temp_free(tmp2);
60548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            break;
60555285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        case NEON_2RM_VABS:
60568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            switch(size) {
60575285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            case 0: gen_helper_neon_abs_s8(tmp, tmp); break;
60585285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            case 1: gen_helper_neon_abs_s16(tmp, tmp); break;
60595285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            case 2: tcg_gen_abs_i32(tmp, tmp); break;
60605285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            default: abort();
60618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            }
60628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            break;
60635285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        case NEON_2RM_VNEG:
60645285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            tmp2 = tcg_const_i32(0);
60655285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            gen_neon_rsb(size, tmp, tmp2);
60665285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            tcg_temp_free(tmp2);
60678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            break;
60685285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        case NEON_2RM_VCGT0_F:
606916998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner                        {
607016998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner                            TCGv_ptr fpstatus = get_fpstatus_ptr(1);
60715285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            tmp2 = tcg_const_i32(0);
607216998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner                            gen_helper_neon_cgt_f32(tmp, tmp, tmp2, fpstatus);
60735285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            tcg_temp_free(tmp2);
60748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            break;
607516998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner                        }
60765285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        case NEON_2RM_VCGE0_F:
607716998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner                        {
607816998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner                            TCGv_ptr fpstatus = get_fpstatus_ptr(1);
60795285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            tmp2 = tcg_const_i32(0);
608016998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner                            gen_helper_neon_cge_f32(tmp, tmp, tmp2, fpstatus);
60815285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            tcg_temp_free(tmp2);
608216998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner                            tcg_temp_free_ptr(fpstatus);
60838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            break;
608416998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner                        }
60855285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        case NEON_2RM_VCEQ0_F:
608616998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner                        {
608716998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner                            TCGv_ptr fpstatus = get_fpstatus_ptr(1);
60885285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            tmp2 = tcg_const_i32(0);
608916998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner                            gen_helper_neon_ceq_f32(tmp, tmp, tmp2, fpstatus);
60905285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            tcg_temp_free(tmp2);
609116998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner                            tcg_temp_free_ptr(fpstatus);
60928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            break;
609316998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner                        }
60945285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        case NEON_2RM_VCLE0_F:
609516998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner                        {
609616998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner                            TCGv_ptr fpstatus = get_fpstatus_ptr(1);
60975285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            tmp2 = tcg_const_i32(0);
609816998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner                            gen_helper_neon_cge_f32(tmp, tmp2, tmp, fpstatus);
60995285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            tcg_temp_free(tmp2);
610016998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner                            tcg_temp_free_ptr(fpstatus);
61015285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            break;
610216998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner                        }
61035285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        case NEON_2RM_VCLT0_F:
610416998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner                        {
610516998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner                            TCGv_ptr fpstatus = get_fpstatus_ptr(1);
61065285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            tmp2 = tcg_const_i32(0);
610716998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner                            gen_helper_neon_cgt_f32(tmp, tmp2, tmp, fpstatus);
61085285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            tcg_temp_free(tmp2);
610916998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner                            tcg_temp_free_ptr(fpstatus);
61105285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            break;
611116998987568fa923e463d41735dcf5c1b28220b9David 'Digit' Turner                        }
61125285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        case NEON_2RM_VABS_F:
61138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            gen_vfp_abs(0);
61148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            break;
61155285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        case NEON_2RM_VNEG_F:
61168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            gen_vfp_neg(0);
61178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            break;
61185285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        case NEON_2RM_VSWP:
61195285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            tmp2 = neon_load_reg(rd, pass);
61205285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            neon_store_reg(rm, pass, tmp2);
61218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            break;
61225285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        case NEON_2RM_VTRN:
61235285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            tmp2 = neon_load_reg(rd, pass);
61248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            switch (size) {
61255285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            case 0: gen_neon_trn_u8(tmp, tmp2); break;
61265285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            case 1: gen_neon_trn_u16(tmp, tmp2); break;
61275285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            default: abort();
61288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            }
61295285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            neon_store_reg(rm, pass, tmp2);
61308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            break;
61315285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        case NEON_2RM_VRECPE:
61325285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            gen_helper_recpe_u32(tmp, tmp, cpu_env);
61338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            break;
61345285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        case NEON_2RM_VRSQRTE:
61355285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            gen_helper_rsqrte_u32(tmp, tmp, cpu_env);
61368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            break;
61375285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        case NEON_2RM_VRECPE_F:
61388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            gen_helper_recpe_f32(cpu_F0s, cpu_F0s, cpu_env);
61398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            break;
61405285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        case NEON_2RM_VRSQRTE_F:
61418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            gen_helper_rsqrte_f32(cpu_F0s, cpu_F0s, cpu_env);
61428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            break;
61435285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        case NEON_2RM_VCVT_FS: /* VCVT.F32.S32 */
61445285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            gen_vfp_sito(0, 1);
61458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            break;
61465285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        case NEON_2RM_VCVT_FU: /* VCVT.F32.U32 */
61475285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            gen_vfp_uito(0, 1);
61488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            break;
61495285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        case NEON_2RM_VCVT_SF: /* VCVT.S32.F32 */
61505285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            gen_vfp_tosiz(0, 1);
61518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            break;
61525285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        case NEON_2RM_VCVT_UF: /* VCVT.U32.F32 */
61535285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            gen_vfp_touiz(0, 1);
61548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            break;
61558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        default:
61565285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            /* Reserved op values were caught by the
61575285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                             * neon_2rm_sizes[] check earlier.
61585285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                             */
61595285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            abort();
61608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        }
61615285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        if (neon_2rm_is_float_op(op)) {
61628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            tcg_gen_st_f32(cpu_F0s, cpu_env,
61638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                           neon_reg_offset(rd, pass));
61648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        } else {
61655285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            neon_store_reg(rd, pass, tmp);
61668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        }
61678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
61688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    break;
61698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
61708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            } else if ((insn & (1 << 10)) == 0) {
61718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* VTBL, VTBX.  */
61725285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                int n = ((insn >> 8) & 3) + 1;
61735285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                if ((rn + n) > 32) {
61745285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    /* This is UNPREDICTABLE; we choose to UNDEF to avoid the
61755285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                     * helper function running off the end of the register file.
61765285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                     */
61775285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    return 1;
61785285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                }
61795285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                n <<= 3;
61808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (insn & (1 << 6)) {
61818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    tmp = neon_load_reg(rd, 0);
61828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                } else {
61835285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tmp = tcg_temp_new_i32();
61848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    tcg_gen_movi_i32(tmp, 0);
61858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
61868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                tmp2 = neon_load_reg(rm, 0);
61875285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tmp4 = tcg_const_i32(rn);
61885285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tmp5 = tcg_const_i32(n);
61890b4c9e8457959b01cd26f60ef214e9b5b7a297d4David 'Digit' Turner                gen_helper_neon_tbl(tmp2, cpu_env, tmp2, tmp, tmp4, tmp5);
61905285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_temp_free_i32(tmp);
61918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (insn & (1 << 6)) {
61928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    tmp = neon_load_reg(rd, 1);
61938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                } else {
61945285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tmp = tcg_temp_new_i32();
61958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    tcg_gen_movi_i32(tmp, 0);
61968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
61978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                tmp3 = neon_load_reg(rm, 1);
61980b4c9e8457959b01cd26f60ef214e9b5b7a297d4David 'Digit' Turner                gen_helper_neon_tbl(tmp3, cpu_env, tmp3, tmp, tmp4, tmp5);
61995285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_temp_free_i32(tmp5);
62005285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_temp_free_i32(tmp4);
62018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                neon_store_reg(rd, 0, tmp2);
62025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                neon_store_reg(rd, 1, tmp3);
62035285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_temp_free_i32(tmp);
62048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            } else if ((insn & 0x380) == 0) {
62058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* VDUP */
62065285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                if ((insn & (7 << 16)) == 0 || (q && (rd & 1))) {
62075285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    return 1;
62085285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                }
62098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (insn & (1 << 19)) {
62105285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tmp = neon_load_reg(rm, 1);
62118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                } else {
62125285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tmp = neon_load_reg(rm, 0);
62138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
62148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (insn & (1 << 16)) {
62155285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    gen_neon_dup_u8(tmp, ((insn >> 17) & 3) * 8);
62168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                } else if (insn & (1 << 17)) {
62178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if ((insn >> 18) & 1)
62185285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        gen_neon_dup_high16(tmp);
62198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    else
62205285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        gen_neon_dup_low16(tmp);
62218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
62228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                for (pass = 0; pass < (q ? 4 : 2); pass++) {
62235285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tmp2 = tcg_temp_new_i32();
62245285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tcg_gen_mov_i32(tmp2, tmp);
62255285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    neon_store_reg(rd, pass, tmp2);
62268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
62275285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_temp_free_i32(tmp);
62288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            } else {
62298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                return 1;
62308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
62318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
62328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
62338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
62348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
62358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6236e2678e116c8cdb0f36b247a5bd9cfacc849362fcDavid 'Digit' Turnerstatic int disas_cp14_read(CPUARMState * env, DisasContext *s, uint32_t insn)
62375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
62385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int crn = (insn >> 16) & 0xf;
62395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int crm = insn & 0xf;
62405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int op1 = (insn >> 21) & 7;
62415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int op2 = (insn >> 5) & 7;
62425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int rt = (insn >> 12) & 0xf;
62435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    TCGv tmp;
62445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
62455285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    /* Minimal set of debug registers, since we don't support debug */
62465285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    if (op1 == 0 && crn == 0 && op2 == 0) {
62475285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        switch (crm) {
62485285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        case 0:
62495285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            /* DBGDIDR: just RAZ. In particular this means the
62505285864985be9077e58e42235af6582dee72e841David 'Digit' Turner             * "debug architecture version" bits will read as
62515285864985be9077e58e42235af6582dee72e841David 'Digit' Turner             * a reserved value, which should cause Linux to
62525285864985be9077e58e42235af6582dee72e841David 'Digit' Turner             * not try to use the debug hardware.
62535285864985be9077e58e42235af6582dee72e841David 'Digit' Turner             */
62545285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tmp = tcg_const_i32(0);
62555285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            store_reg(s, rt, tmp);
62565285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            return 0;
62575285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        case 1:
62585285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        case 2:
62595285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            /* DBGDRAR and DBGDSAR: v7 only. Always RAZ since we
62605285864985be9077e58e42235af6582dee72e841David 'Digit' Turner             * don't implement memory mapped debug components
62615285864985be9077e58e42235af6582dee72e841David 'Digit' Turner             */
62625285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            if (ENABLE_ARCH_7) {
62635285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tmp = tcg_const_i32(0);
62645285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                store_reg(s, rt, tmp);
62655285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                return 0;
62665285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            }
62675285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            break;
62685285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        default:
62695285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            break;
62705285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        }
62715285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    }
62725285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
62735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (arm_feature(env, ARM_FEATURE_THUMB2EE)) {
62745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (op1 == 6 && crn == 0 && crm == 0 && op2 == 0) {
62755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            /* TEECR */
62765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            if (IS_USER(s))
62775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                return 1;
62785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            tmp = load_cpu_field(teecr);
62795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            store_reg(s, rt, tmp);
62805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            return 0;
62815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        }
62825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (op1 == 6 && crn == 1 && crm == 0 && op2 == 0) {
62835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            /* TEEHBR */
62845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            if (IS_USER(s) && (env->teecr & 1))
62855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                return 1;
62865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            tmp = load_cpu_field(teehbr);
62875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            store_reg(s, rt, tmp);
62885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            return 0;
62895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        }
62905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
62915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    fprintf(stderr, "Unknown cp14 read op1:%d crn:%d crm:%d op2:%d\n",
62925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            op1, crn, crm, op2);
62935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return 1;
62945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
62955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
6296e2678e116c8cdb0f36b247a5bd9cfacc849362fcDavid 'Digit' Turnerstatic int disas_cp14_write(CPUARMState * env, DisasContext *s, uint32_t insn)
62975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
62985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int crn = (insn >> 16) & 0xf;
62995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int crm = insn & 0xf;
63005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int op1 = (insn >> 21) & 7;
63015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int op2 = (insn >> 5) & 7;
63025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int rt = (insn >> 12) & 0xf;
63035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    TCGv tmp;
63045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
63055285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    /* Minimal set of debug registers, since we don't support debug */
63065285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    if (op1 == 0 && crn == 0 && op2 == 0) {
63075285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        switch (crm) {
63085285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        case 0:
63095285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            /* DBGDIDR */
63105285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tmp = load_cpu_field(cp14_dbgdidr);
63115285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            store_reg(s, rt, tmp);
63125285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            return 0;
63135285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        case 1:
63145285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        case 2:
63155285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            /* DBGDRAR and DBGDSAR: v7 only. Always RAZ since we
63165285864985be9077e58e42235af6582dee72e841David 'Digit' Turner             * don't implement memory mapped debug components
63175285864985be9077e58e42235af6582dee72e841David 'Digit' Turner             */
63185285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            if (ENABLE_ARCH_7) {
63195285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tmp = tcg_const_i32(0);
63205285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                store_reg(s, rt, tmp);
63215285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                return 0;
63225285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            }
63235285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            break;
63245285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        default:
63255285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            break;
63265285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        }
63275285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    }
63285285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
63295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (arm_feature(env, ARM_FEATURE_THUMB2EE)) {
63305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (op1 == 6 && crn == 0 && crm == 0 && op2 == 0) {
63315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            /* TEECR */
63325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            if (IS_USER(s))
63335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                return 1;
63345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            tmp = load_reg(s, rt);
63355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            gen_helper_set_teecr(cpu_env, tmp);
63365285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tcg_temp_free_i32(tmp);
63375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            return 0;
63385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        }
63395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (op1 == 6 && crn == 1 && crm == 0 && op2 == 0) {
63405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            /* TEEHBR */
63415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            if (IS_USER(s) && (env->teecr & 1))
63425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                return 1;
63435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            tmp = load_reg(s, rt);
63445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            store_cpu_field(tmp, teehbr);
63455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            return 0;
63465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        }
63475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
63485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    fprintf(stderr, "Unknown cp14 write op1:%d crn:%d crm:%d op2:%d\n",
63495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            op1, crn, crm, op2);
63505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return 1;
63515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
63525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
6353e2678e116c8cdb0f36b247a5bd9cfacc849362fcDavid 'Digit' Turnerstatic int disas_coproc_insn(CPUARMState * env, DisasContext *s, uint32_t insn)
63548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
63558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int cpnum;
63568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
63578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    cpnum = (insn >> 8) & 0xf;
63588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (arm_feature(env, ARM_FEATURE_XSCALE)
63598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	    && ((env->cp15.c15_cpar ^ 0x3fff) & (1 << cpnum)))
63608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	return 1;
63618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
63628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    switch (cpnum) {
63638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      case 0:
63648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      case 1:
63658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
63668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	    return disas_iwmmxt_insn(env, s, insn);
63678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	} else if (arm_feature(env, ARM_FEATURE_XSCALE)) {
63688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	    return disas_dsp_insn(env, s, insn);
63698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	}
63705285864985be9077e58e42235af6582dee72e841David 'Digit' Turner	goto board;
63718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 10:
63728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 11:
63738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	return disas_vfp_insn (env, s, insn);
63745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    case 14:
63755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        /* Coprocessors 7-15 are architecturally reserved by ARM.
63765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner           Unfortunately Intel decided to ignore this.  */
63775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (arm_feature(env, ARM_FEATURE_XSCALE))
63785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            goto board;
63795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (insn & (1 << 20))
63805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            return disas_cp14_read(env, s, insn);
63815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        else
63825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            return disas_cp14_write(env, s, insn);
63838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 15:
63848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	return disas_cp15_insn (env, s, insn);
63858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    default:
63865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    board:
63878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	/* Unknown coprocessor.  See if the board has hooked it.  */
63888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	return disas_cp_insn (env, s, insn);
63898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
63908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
63918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
63928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
63938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Store a 64-bit value to a register pair.  Clobbers val.  */
63945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void gen_storeq_reg(DisasContext *s, int rlow, int rhigh, TCGv_i64 val)
63958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
63968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    TCGv tmp;
63975285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tmp = tcg_temp_new_i32();
63988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_gen_trunc_i64_i32(tmp, val);
63998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    store_reg(s, rlow, tmp);
64005285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tmp = tcg_temp_new_i32();
64018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_gen_shri_i64(val, val, 32);
64028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_gen_trunc_i64_i32(tmp, val);
64038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    store_reg(s, rhigh, tmp);
64048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
64058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
64068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* load a 32-bit value from a register and perform a 64-bit accumulate.  */
64075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void gen_addq_lo(DisasContext *s, TCGv_i64 val, int rlow)
64088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
64095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    TCGv_i64 tmp;
64108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    TCGv tmp2;
64118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
64125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    /* Load value and extend to 64 bits.  */
64135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    tmp = tcg_temp_new_i64();
64148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tmp2 = load_reg(s, rlow);
64158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_gen_extu_i32_i64(tmp, tmp2);
64165285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_temp_free_i32(tmp2);
64178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_gen_add_i64(val, val, tmp);
64185285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_temp_free_i64(tmp);
64198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
64208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
64218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* load and add a 64-bit value from a register pair.  */
64225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void gen_addq(DisasContext *s, TCGv_i64 val, int rlow, int rhigh)
64238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
64245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    TCGv_i64 tmp;
64255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    TCGv tmpl;
64265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    TCGv tmph;
64278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
64288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* Load 64-bit value rd:rn.  */
64295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    tmpl = load_reg(s, rlow);
64305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    tmph = load_reg(s, rhigh);
64315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    tmp = tcg_temp_new_i64();
64325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    tcg_gen_concat_i32_i64(tmp, tmpl, tmph);
64335285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_temp_free_i32(tmpl);
64345285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_temp_free_i32(tmph);
64358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_gen_add_i64(val, val, tmp);
64365285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_temp_free_i64(tmp);
64378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
64388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
64398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Set N and Z flags from a 64-bit value.  */
64405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void gen_logicq_cc(TCGv_i64 val)
64418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
64425285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    TCGv tmp = tcg_temp_new_i32();
64438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    gen_helper_logicq_cc(tmp, val);
64448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    gen_logic_CC(tmp);
64455285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_temp_free_i32(tmp);
64465285864985be9077e58e42235af6582dee72e841David 'Digit' Turner}
64475285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
64485285864985be9077e58e42235af6582dee72e841David 'Digit' Turner/* Load/Store exclusive instructions are implemented by remembering
64495285864985be9077e58e42235af6582dee72e841David 'Digit' Turner   the value/address loaded, and seeing if these are the same
64505285864985be9077e58e42235af6582dee72e841David 'Digit' Turner   when the store is performed. This should be is sufficient to implement
64515285864985be9077e58e42235af6582dee72e841David 'Digit' Turner   the architecturally mandated semantics, and avoids having to monitor
64525285864985be9077e58e42235af6582dee72e841David 'Digit' Turner   regular stores.
64535285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
64545285864985be9077e58e42235af6582dee72e841David 'Digit' Turner   In system emulation mode only one CPU will be running at once, so
64555285864985be9077e58e42235af6582dee72e841David 'Digit' Turner   this sequence is effectively atomic.  In user emulation mode we
64565285864985be9077e58e42235af6582dee72e841David 'Digit' Turner   throw an exception and handle the atomic operation elsewhere.  */
64575285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic void gen_load_exclusive(DisasContext *s, int rt, int rt2,
64585285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                               TCGv addr, int size)
64595285864985be9077e58e42235af6582dee72e841David 'Digit' Turner{
64605285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    TCGv tmp;
64615285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
64625285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    switch (size) {
64635285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    case 0:
64645285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tmp = gen_ld8u(addr, IS_USER(s));
64655285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        break;
64665285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    case 1:
64675285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tmp = gen_ld16u(addr, IS_USER(s));
64685285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        break;
64695285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    case 2:
64705285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    case 3:
64715285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tmp = gen_ld32(addr, IS_USER(s));
64725285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        break;
64735285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    default:
64745285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        abort();
64755285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    }
64765285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_gen_mov_i32(cpu_exclusive_val, tmp);
64775285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    store_reg(s, rt, tmp);
64785285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    if (size == 3) {
64795285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        TCGv tmp2 = tcg_temp_new_i32();
64805285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tcg_gen_addi_i32(tmp2, addr, 4);
64815285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tmp = gen_ld32(tmp2, IS_USER(s));
64825285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tcg_temp_free_i32(tmp2);
64835285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tcg_gen_mov_i32(cpu_exclusive_high, tmp);
64845285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        store_reg(s, rt2, tmp);
64855285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    }
64865285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_gen_mov_i32(cpu_exclusive_addr, addr);
64875285864985be9077e58e42235af6582dee72e841David 'Digit' Turner}
64885285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
64895285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic void gen_clrex(DisasContext *s)
64905285864985be9077e58e42235af6582dee72e841David 'Digit' Turner{
64915285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_gen_movi_i32(cpu_exclusive_addr, -1);
64928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
64938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
64945285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#ifdef CONFIG_USER_ONLY
64955285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic void gen_store_exclusive(DisasContext *s, int rd, int rt, int rt2,
64965285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                                TCGv addr, int size)
64975285864985be9077e58e42235af6582dee72e841David 'Digit' Turner{
64985285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_gen_mov_i32(cpu_exclusive_test, addr);
64995285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_gen_movi_i32(cpu_exclusive_info,
65005285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                     size | (rd << 4) | (rt << 8) | (rt2 << 12));
65015285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    gen_exception_insn(s, 4, EXCP_STREX);
65025285864985be9077e58e42235af6582dee72e841David 'Digit' Turner}
65035285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#else
65045285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic void gen_store_exclusive(DisasContext *s, int rd, int rt, int rt2,
65055285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                                TCGv addr, int size)
65065285864985be9077e58e42235af6582dee72e841David 'Digit' Turner{
65075285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    TCGv tmp;
65085285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    int done_label;
65095285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    int fail_label;
65105285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
65115285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    /* if (env->exclusive_addr == addr && env->exclusive_val == [addr]) {
65125285864985be9077e58e42235af6582dee72e841David 'Digit' Turner         [addr] = {Rt};
65135285864985be9077e58e42235af6582dee72e841David 'Digit' Turner         {Rd} = 0;
65145285864985be9077e58e42235af6582dee72e841David 'Digit' Turner       } else {
65155285864985be9077e58e42235af6582dee72e841David 'Digit' Turner         {Rd} = 1;
65165285864985be9077e58e42235af6582dee72e841David 'Digit' Turner       } */
65175285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    fail_label = gen_new_label();
65185285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    done_label = gen_new_label();
65195285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_gen_brcond_i32(TCG_COND_NE, addr, cpu_exclusive_addr, fail_label);
65205285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    switch (size) {
65215285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    case 0:
65225285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tmp = gen_ld8u(addr, IS_USER(s));
65235285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        break;
65245285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    case 1:
65255285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tmp = gen_ld16u(addr, IS_USER(s));
65265285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        break;
65275285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    case 2:
65285285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    case 3:
65295285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tmp = gen_ld32(addr, IS_USER(s));
65305285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        break;
65315285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    default:
65325285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        abort();
65335285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    }
65345285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_gen_brcond_i32(TCG_COND_NE, tmp, cpu_exclusive_val, fail_label);
65355285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_temp_free_i32(tmp);
65365285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    if (size == 3) {
65375285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        TCGv tmp2 = tcg_temp_new_i32();
65385285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tcg_gen_addi_i32(tmp2, addr, 4);
65395285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tmp = gen_ld32(tmp2, IS_USER(s));
65405285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tcg_temp_free_i32(tmp2);
65415285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tcg_gen_brcond_i32(TCG_COND_NE, tmp, cpu_exclusive_high, fail_label);
65425285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tcg_temp_free_i32(tmp);
65435285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    }
65445285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tmp = load_reg(s, rt);
65455285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    switch (size) {
65465285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    case 0:
65475285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        gen_st8(tmp, addr, IS_USER(s));
65485285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        break;
65495285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    case 1:
65505285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        gen_st16(tmp, addr, IS_USER(s));
65515285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        break;
65525285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    case 2:
65535285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    case 3:
65545285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        gen_st32(tmp, addr, IS_USER(s));
65555285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        break;
65565285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    default:
65575285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        abort();
65585285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    }
65595285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    if (size == 3) {
65605285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tcg_gen_addi_i32(addr, addr, 4);
65615285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tmp = load_reg(s, rt2);
65625285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        gen_st32(tmp, addr, IS_USER(s));
65635285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    }
65645285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_gen_movi_i32(cpu_R[rd], 0);
65655285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_gen_br(done_label);
65665285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    gen_set_label(fail_label);
65675285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_gen_movi_i32(cpu_R[rd], 1);
65685285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    gen_set_label(done_label);
65695285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_gen_movi_i32(cpu_exclusive_addr, -1);
65705285864985be9077e58e42235af6582dee72e841David 'Digit' Turner}
65715285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#endif
6572a577fcadc0b365ee629aec313f57a65d54fe5d89David 'Digit' Turner
6573e2678e116c8cdb0f36b247a5bd9cfacc849362fcDavid 'Digit' Turnerstatic void disas_arm_insn(CPUARMState * env, DisasContext *s)
65748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
65758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    unsigned int cond, insn, val, op1, i, shift, rm, rs, rn, rd, sh;
65768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    TCGv tmp;
65778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    TCGv tmp2;
65788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    TCGv tmp3;
65798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    TCGv addr;
65805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    TCGv_i64 tmp64;
65815285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
6582eca7bc24e45fb6809582795ff88f13384b5ce7dfDavid 'Digit' Turner    insn = cpu_ldl_code(env, s->pc);
65835389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine
65848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    s->pc += 4;
65858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
65868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* M variants do not implement ARM mode.  */
65878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (IS_M(env))
65888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        goto illegal_op;
65898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    cond = insn >> 28;
65908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (cond == 0xf){
65915285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        /* In ARMv3 and v4 the NV condition is UNPREDICTABLE; we
65925285864985be9077e58e42235af6582dee72e841David 'Digit' Turner         * choose to UNDEF. In ARMv5 and above the space is used
65935285864985be9077e58e42235af6582dee72e841David 'Digit' Turner         * for miscellaneous unconditional instructions.
65945285864985be9077e58e42235af6582dee72e841David 'Digit' Turner         */
65955285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        ARCH(5);
65965285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
65978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* Unconditional instructions.  */
65988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (((insn >> 25) & 7) == 1) {
65998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* NEON Data processing.  */
66008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (!arm_feature(env, ARM_FEATURE_NEON))
66018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                goto illegal_op;
66028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
66038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (disas_neon_data_insn(env, s, insn))
66048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                goto illegal_op;
66058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return;
66068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
66078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if ((insn & 0x0f100000) == 0x04000000) {
66088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* NEON load/store.  */
66098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (!arm_feature(env, ARM_FEATURE_NEON))
66108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                goto illegal_op;
66118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
66128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (disas_neon_ls_insn(env, s, insn))
66138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                goto illegal_op;
66148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return;
66158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
66165285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        if (((insn & 0x0f30f000) == 0x0510f000) ||
66175285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            ((insn & 0x0f30f010) == 0x0710f000)) {
66185285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            if ((insn & (1 << 22)) == 0) {
66195285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                /* PLDW; v7MP */
66205285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                if (!arm_feature(env, ARM_FEATURE_V7MP)) {
66215285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    goto illegal_op;
66225285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                }
66235285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            }
66245285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            /* Otherwise PLD; v5TE+ */
66255285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            ARCH(5TE);
66265285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            return;
66275285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        }
66285285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        if (((insn & 0x0f70f000) == 0x0450f000) ||
66295285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            ((insn & 0x0f70f010) == 0x0650f000)) {
66305285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            ARCH(7);
66315285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            return; /* PLI; V7 */
66325285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        }
66335285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        if (((insn & 0x0f700000) == 0x04100000) ||
66345285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            ((insn & 0x0f700010) == 0x06100000)) {
66355285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            if (!arm_feature(env, ARM_FEATURE_V7MP)) {
66365285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                goto illegal_op;
66375285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            }
66385285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            return; /* v7MP: Unallocated memory hint: must NOP */
66395285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        }
66405285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
66415285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        if ((insn & 0x0ffffdff) == 0x01010000) {
66428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            ARCH(6);
66438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* setend */
66448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (insn & (1 << 9)) {
66458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* BE8 mode not implemented.  */
66468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                goto illegal_op;
66478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
66488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return;
66498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        } else if ((insn & 0x0fffff00) == 0x057ff000) {
66508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            switch ((insn >> 4) & 0xf) {
66518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            case 1: /* clrex */
66528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                ARCH(6K);
66535285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                gen_clrex(s);
66548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                return;
66558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            case 4: /* dsb */
66568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            case 5: /* dmb */
66578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            case 6: /* isb */
66588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                ARCH(7);
66598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* We don't emulate caches so these are a no-op.  */
66608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                return;
66618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            default:
66628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                goto illegal_op;
66638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
66648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        } else if ((insn & 0x0e5fffe0) == 0x084d0500) {
66658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* srs */
66665285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            int32_t offset;
66678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (IS_USER(s))
66688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                goto illegal_op;
66698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            ARCH(6);
66708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            op1 = (insn & 0x1f);
66715285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            addr = tcg_temp_new_i32();
66725285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tmp = tcg_const_i32(op1);
66735285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            gen_helper_get_r13_banked(addr, cpu_env, tmp);
66745285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tcg_temp_free_i32(tmp);
66758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            i = (insn >> 23) & 3;
66768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            switch (i) {
66778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            case 0: offset = -4; break; /* DA */
66785285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            case 1: offset = 0; break; /* IA */
66795285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            case 2: offset = -8; break; /* DB */
66808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            case 3: offset = 4; break; /* IB */
66818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            default: abort();
66828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
66838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (offset)
66848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                tcg_gen_addi_i32(addr, addr, offset);
66858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tmp = load_reg(s, 14);
66868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            gen_st32(tmp, addr, 0);
66875285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tmp = load_cpu_field(spsr);
66888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tcg_gen_addi_i32(addr, addr, 4);
66898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            gen_st32(tmp, addr, 0);
66908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (insn & (1 << 21)) {
66918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* Base writeback.  */
66928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                switch (i) {
66938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                case 0: offset = -8; break;
66945285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                case 1: offset = 4; break;
66955285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                case 2: offset = -4; break;
66968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                case 3: offset = 0; break;
66978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                default: abort();
66988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
66998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (offset)
67005285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tcg_gen_addi_i32(addr, addr, offset);
67015285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tmp = tcg_const_i32(op1);
67025285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                gen_helper_set_r13_banked(cpu_env, tmp, addr);
67035285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_temp_free_i32(tmp);
67045285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_temp_free_i32(addr);
67058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            } else {
67065285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_temp_free_i32(addr);
67078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
67085285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            return;
67095285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        } else if ((insn & 0x0e50ffe0) == 0x08100a00) {
67108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* rfe */
67115285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            int32_t offset;
67128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (IS_USER(s))
67138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                goto illegal_op;
67148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            ARCH(6);
67158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            rn = (insn >> 16) & 0xf;
67168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            addr = load_reg(s, rn);
67178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            i = (insn >> 23) & 3;
67188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            switch (i) {
67198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            case 0: offset = -4; break; /* DA */
67205285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            case 1: offset = 0; break; /* IA */
67215285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            case 2: offset = -8; break; /* DB */
67228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            case 3: offset = 4; break; /* IB */
67238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            default: abort();
67248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
67258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (offset)
67268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                tcg_gen_addi_i32(addr, addr, offset);
67278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* Load PC into tmp and CPSR into tmp2.  */
67288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tmp = gen_ld32(addr, 0);
67298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tcg_gen_addi_i32(addr, addr, 4);
67308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tmp2 = gen_ld32(addr, 0);
67318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (insn & (1 << 21)) {
67328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* Base writeback.  */
67338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                switch (i) {
67348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                case 0: offset = -8; break;
67355285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                case 1: offset = 4; break;
67365285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                case 2: offset = -4; break;
67378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                case 3: offset = 0; break;
67388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                default: abort();
67398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
67408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (offset)
67418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    tcg_gen_addi_i32(addr, addr, offset);
67428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                store_reg(s, rn, addr);
67438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            } else {
67445285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_temp_free_i32(addr);
67458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
67468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            gen_rfe(s, tmp, tmp2);
67475285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            return;
67488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        } else if ((insn & 0x0e000000) == 0x0a000000) {
67498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* branch link and change to thumb (blx <offset>) */
67508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            int32_t offset;
67518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
67528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            val = (uint32_t)s->pc;
67535285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tmp = tcg_temp_new_i32();
67548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tcg_gen_movi_i32(tmp, val);
67558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            store_reg(s, 14, tmp);
67568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* Sign-extend the 24-bit offset */
67578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            offset = (((int32_t)insn) << 8) >> 8;
67588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* offset * 4 + bit24 * 2 + (thumb bit) */
67598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            val += (offset << 2) | ((insn >> 23) & 2) | 1;
67608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* pipeline offset */
67618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            val += 4;
67625285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            /* protected by ARCH(5); above, near the start of uncond block */
67638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            gen_bx_im(s, val);
67648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return;
67658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        } else if ((insn & 0x0e000f00) == 0x0c000100) {
67668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
67678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* iWMMXt register transfer.  */
67688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (env->cp15.c15_cpar & (1 << 1))
67698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if (!disas_iwmmxt_insn(env, s, insn))
67708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        return;
67718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
67728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        } else if ((insn & 0x0fe00000) == 0x0c400000) {
67738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* Coprocessor double register transfer.  */
67745285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            ARCH(5TE);
67758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        } else if ((insn & 0x0f000010) == 0x0e000010) {
67768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* Additional coprocessor register transfer.  */
67775285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            if (!disas_coproc_insn(env, s, insn)) {
67785285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                return;
67795285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            }
67808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        } else if ((insn & 0x0ff10020) == 0x01000000) {
67818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            uint32_t mask;
67828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            uint32_t val;
67838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* cps (privileged) */
67848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (IS_USER(s))
67858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                return;
67868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            mask = val = 0;
67878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (insn & (1 << 19)) {
67888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (insn & (1 << 8))
67898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    mask |= CPSR_A;
67908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (insn & (1 << 7))
67918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    mask |= CPSR_I;
67928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (insn & (1 << 6))
67938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    mask |= CPSR_F;
67948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (insn & (1 << 18))
67958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    val |= mask;
67968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
67978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (insn & (1 << 17)) {
67988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                mask |= CPSR_M;
67998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                val |= (insn & 0x1f);
68008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
68018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (mask) {
68025285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                gen_set_psr_im(s, mask, 0, val);
68038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
68048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return;
68058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
68068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        goto illegal_op;
68078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
68088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (cond != 0xe) {
68098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* if not always execute, we generate a conditional jump to
68108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project           next instruction */
68118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        s->condlabel = gen_new_label();
68128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_test_cc(cond ^ 1, s->condlabel);
68138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        s->condjmp = 1;
68148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
68158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if ((insn & 0x0f900000) == 0x03000000) {
68168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if ((insn & (1 << 21)) == 0) {
68178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            ARCH(6T2);
68188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            rd = (insn >> 12) & 0xf;
68198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            val = ((insn >> 4) & 0xf000) | (insn & 0xfff);
68208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if ((insn & (1 << 22)) == 0) {
68218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* MOVW */
68225285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tmp = tcg_temp_new_i32();
68238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                tcg_gen_movi_i32(tmp, val);
68248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            } else {
68258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* MOVT */
68268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                tmp = load_reg(s, rd);
68278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                tcg_gen_ext16u_i32(tmp, tmp);
68288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                tcg_gen_ori_i32(tmp, tmp, val << 16);
68298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
68308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            store_reg(s, rd, tmp);
68318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        } else {
68328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (((insn >> 12) & 0xf) != 0xf)
68338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                goto illegal_op;
68348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (((insn >> 16) & 0xf) == 0) {
68358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                gen_nop_hint(s, insn & 0xff);
68368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            } else {
68378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* CPSR = immediate */
68388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                val = insn & 0xff;
68398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                shift = ((insn >> 8) & 0xf) * 2;
68408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (shift)
68418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    val = (val >> shift) | (val << (32 - shift));
68428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                i = ((insn & (1 << 22)) != 0);
68435285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                if (gen_set_psr_im(s, msr_mask(env, s, (insn >> 16) & 0xf, i), i, val))
68448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    goto illegal_op;
68458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
68468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
68478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } else if ((insn & 0x0f900000) == 0x01000000
68488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project               && (insn & 0x00000090) != 0x00000090) {
68498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* miscellaneous instructions */
68508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        op1 = (insn >> 21) & 3;
68518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        sh = (insn >> 4) & 0xf;
68528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        rm = insn & 0xf;
68538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        switch (sh) {
68548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0x0: /* move program status register */
68558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (op1 & 1) {
68568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* PSR = reg */
68575285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tmp = load_reg(s, rm);
68588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                i = ((op1 & 2) != 0);
68595285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                if (gen_set_psr(s, msr_mask(env, s, (insn >> 16) & 0xf, i), i, tmp))
68608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    goto illegal_op;
68618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            } else {
68628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* reg = PSR */
68638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                rd = (insn >> 12) & 0xf;
68648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (op1 & 2) {
68658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if (IS_USER(s))
68668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        goto illegal_op;
68678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    tmp = load_cpu_field(spsr);
68688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                } else {
68695285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tmp = tcg_temp_new_i32();
68700b4c9e8457959b01cd26f60ef214e9b5b7a297d4David 'Digit' Turner                    gen_helper_cpsr_read(tmp, cpu_env);
68718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
68728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                store_reg(s, rd, tmp);
68738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
68748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
68758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0x1:
68768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (op1 == 1) {
68778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* branch/exchange thumb (bx).  */
68785285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                ARCH(4T);
68798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                tmp = load_reg(s, rm);
68808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                gen_bx(s, tmp);
68818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            } else if (op1 == 3) {
68828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* clz */
68835285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                ARCH(5);
68848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                rd = (insn >> 12) & 0xf;
68858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                tmp = load_reg(s, rm);
68868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                gen_helper_clz(tmp, tmp);
68878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                store_reg(s, rd, tmp);
68888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            } else {
68898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                goto illegal_op;
68908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
68918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
68928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0x2:
68938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (op1 == 1) {
68948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                ARCH(5J); /* bxj */
68958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* Trivial implementation equivalent to bx.  */
68968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                tmp = load_reg(s, rm);
68978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                gen_bx(s, tmp);
68988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            } else {
68998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                goto illegal_op;
69008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
69018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
69028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0x3:
69038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (op1 != 1)
69048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project              goto illegal_op;
69058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
69065285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            ARCH(5);
69078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* branch link/exchange thumb (blx) */
69088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tmp = load_reg(s, rm);
69095285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tmp2 = tcg_temp_new_i32();
69108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tcg_gen_movi_i32(tmp2, s->pc);
69118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            store_reg(s, 14, tmp2);
69128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            gen_bx(s, tmp);
69138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
69148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0x5: /* saturating add/subtract */
69155285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            ARCH(5TE);
69168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            rd = (insn >> 12) & 0xf;
69178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            rn = (insn >> 16) & 0xf;
691880562525ca945d9e921eb49f96d52f1b5a0e693dDavid 'Digit' Turner            tmp = load_reg(s, rm);
69198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tmp2 = load_reg(s, rn);
69208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (op1 & 2)
69210b4c9e8457959b01cd26f60ef214e9b5b7a297d4David 'Digit' Turner                gen_helper_double_saturate(tmp2, cpu_env, tmp2);
69228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (op1 & 1)
69230b4c9e8457959b01cd26f60ef214e9b5b7a297d4David 'Digit' Turner                gen_helper_sub_saturate(tmp, cpu_env, tmp, tmp2);
69248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            else
69250b4c9e8457959b01cd26f60ef214e9b5b7a297d4David 'Digit' Turner                gen_helper_add_saturate(tmp, cpu_env, tmp, tmp2);
69265285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tcg_temp_free_i32(tmp2);
69278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            store_reg(s, rd, tmp);
69288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
69295285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        case 7:
69305285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            if (op1 == 1) {
69315285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                /* bkpt */
69325285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                ARCH(5);
69335285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                gen_exception_insn(s, 4, EXCP_BKPT);
69345285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            } else if (op1 == 3) {
69355285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                /* smi/smc */
69365285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                if (!(env->cp15.c0_c2[4] & 0xf000) || IS_USER(s)) {
69375285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    goto illegal_op;
69385285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                }
69395285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                gen_smc(env, s);
69405285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            } else {
69415285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                goto illegal_op;
69425285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            }
69438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
69448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0x8: /* signed multiply */
69458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0xa:
69468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0xc:
69478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0xe:
69485285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            ARCH(5TE);
69498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            rs = (insn >> 8) & 0xf;
69508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            rn = (insn >> 12) & 0xf;
69518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            rd = (insn >> 16) & 0xf;
69528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (op1 == 1) {
69538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* (32 * 16) >> 16 */
69548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                tmp = load_reg(s, rm);
69558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                tmp2 = load_reg(s, rs);
69568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (sh & 4)
69578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    tcg_gen_sari_i32(tmp2, tmp2, 16);
69588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                else
69598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    gen_sxth(tmp2);
69605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                tmp64 = gen_muls_i64_i32(tmp, tmp2);
69615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                tcg_gen_shri_i64(tmp64, tmp64, 16);
69625285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tmp = tcg_temp_new_i32();
69635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                tcg_gen_trunc_i64_i32(tmp, tmp64);
69645285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_temp_free_i64(tmp64);
69658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if ((sh & 2) == 0) {
69668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    tmp2 = load_reg(s, rn);
69670b4c9e8457959b01cd26f60ef214e9b5b7a297d4David 'Digit' Turner                    gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
69685285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tcg_temp_free_i32(tmp2);
69698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
69708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                store_reg(s, rd, tmp);
69718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            } else {
69728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* 16 * 16 */
69738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                tmp = load_reg(s, rm);
69748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                tmp2 = load_reg(s, rs);
69758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                gen_mulxy(tmp, tmp2, sh & 2, sh & 4);
69765285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_temp_free_i32(tmp2);
69778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (op1 == 2) {
69785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                    tmp64 = tcg_temp_new_i64();
69795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                    tcg_gen_ext_i32_i64(tmp64, tmp);
69805285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tcg_temp_free_i32(tmp);
69815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                    gen_addq(s, tmp64, rn, rd);
69825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                    gen_storeq_reg(s, rn, rd, tmp64);
69835285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tcg_temp_free_i64(tmp64);
69848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                } else {
69858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if (op1 == 0) {
69868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        tmp2 = load_reg(s, rn);
69870b4c9e8457959b01cd26f60ef214e9b5b7a297d4David 'Digit' Turner                        gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
69885285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tcg_temp_free_i32(tmp2);
69898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
69908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    store_reg(s, rd, tmp);
69918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
69928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
69938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
69948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        default:
69958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            goto illegal_op;
69968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
69978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } else if (((insn & 0x0e000000) == 0 &&
69988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                (insn & 0x00000090) != 0x90) ||
69998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project               ((insn & 0x0e000000) == (1 << 25))) {
70008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        int set_cc, logic_cc, shiftop;
70018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
70028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        op1 = (insn >> 21) & 0xf;
70038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        set_cc = (insn >> 20) & 1;
70048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        logic_cc = table_logic_cc[op1] & set_cc;
70058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
70068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* data processing instruction */
70078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (insn & (1 << 25)) {
70088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* immediate operand */
70098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            val = insn & 0xff;
70108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            shift = ((insn >> 8) & 0xf) * 2;
70115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            if (shift) {
70128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                val = (val >> shift) | (val << (32 - shift));
70135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            }
70145285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tmp2 = tcg_temp_new_i32();
70155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            tcg_gen_movi_i32(tmp2, val);
70165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            if (logic_cc && shift) {
70175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                gen_set_CF_bit31(tmp2);
70185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            }
70198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        } else {
70208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* register */
70218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            rm = (insn) & 0xf;
70225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            tmp2 = load_reg(s, rm);
70238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            shiftop = (insn >> 5) & 3;
70248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (!(insn & (1 << 4))) {
70258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                shift = (insn >> 7) & 0x1f;
70265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                gen_arm_shift_im(tmp2, shiftop, shift, logic_cc);
70278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            } else {
70288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                rs = (insn >> 8) & 0xf;
70298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                tmp = load_reg(s, rs);
70305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                gen_arm_shift_reg(tmp2, shiftop, tmp, logic_cc);
70318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
70328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
70338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (op1 != 0x0f && op1 != 0x0d) {
70348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            rn = (insn >> 16) & 0xf;
70355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            tmp = load_reg(s, rn);
70365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        } else {
70375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            TCGV_UNUSED(tmp);
70388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
70398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        rd = (insn >> 12) & 0xf;
70408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        switch(op1) {
70418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0x00:
70425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            tcg_gen_and_i32(tmp, tmp, tmp2);
70435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            if (logic_cc) {
70445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                gen_logic_CC(tmp);
70455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            }
70465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            store_reg_bx(env, s, rd, tmp);
70478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
70488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0x01:
70495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            tcg_gen_xor_i32(tmp, tmp, tmp2);
70505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            if (logic_cc) {
70515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                gen_logic_CC(tmp);
70525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            }
70535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            store_reg_bx(env, s, rd, tmp);
70548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
70558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0x02:
70568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (set_cc && rd == 15) {
70578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* SUBS r15, ... is used for exception return.  */
70585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                if (IS_USER(s)) {
70598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    goto illegal_op;
70605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                }
70610b4c9e8457959b01cd26f60ef214e9b5b7a297d4David 'Digit' Turner                gen_helper_sub_cc(tmp, cpu_env, tmp, tmp2);
70625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                gen_exception_return(s, tmp);
70638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            } else {
70645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                if (set_cc) {
70650b4c9e8457959b01cd26f60ef214e9b5b7a297d4David 'Digit' Turner                    gen_helper_sub_cc(tmp, cpu_env, tmp, tmp2);
70665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                } else {
70675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                    tcg_gen_sub_i32(tmp, tmp, tmp2);
70685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                }
70695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                store_reg_bx(env, s, rd, tmp);
70708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
70718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
70728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0x03:
70735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            if (set_cc) {
70740b4c9e8457959b01cd26f60ef214e9b5b7a297d4David 'Digit' Turner                gen_helper_sub_cc(tmp, cpu_env, tmp2, tmp);
70755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            } else {
70765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                tcg_gen_sub_i32(tmp, tmp2, tmp);
70775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            }
70785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            store_reg_bx(env, s, rd, tmp);
70798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
70808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0x04:
70815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            if (set_cc) {
70820b4c9e8457959b01cd26f60ef214e9b5b7a297d4David 'Digit' Turner                gen_helper_add_cc(tmp, cpu_env, tmp, tmp2);
70835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            } else {
70845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                tcg_gen_add_i32(tmp, tmp, tmp2);
70855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            }
70865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            store_reg_bx(env, s, rd, tmp);
70878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
70888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0x05:
70895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            if (set_cc) {
70900b4c9e8457959b01cd26f60ef214e9b5b7a297d4David 'Digit' Turner                gen_helper_adc_cc(tmp, cpu_env, tmp, tmp2);
70915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            } else {
70925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                gen_add_carry(tmp, tmp, tmp2);
70935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            }
70945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            store_reg_bx(env, s, rd, tmp);
70958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
70968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0x06:
70975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            if (set_cc) {
70980b4c9e8457959b01cd26f60ef214e9b5b7a297d4David 'Digit' Turner                gen_helper_sbc_cc(tmp, cpu_env, tmp, tmp2);
70995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            } else {
71005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                gen_sub_carry(tmp, tmp, tmp2);
71015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            }
71025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            store_reg_bx(env, s, rd, tmp);
71038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
71048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0x07:
71055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            if (set_cc) {
71060b4c9e8457959b01cd26f60ef214e9b5b7a297d4David 'Digit' Turner                gen_helper_sbc_cc(tmp, cpu_env, tmp2, tmp);
71075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            } else {
71085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                gen_sub_carry(tmp, tmp2, tmp);
71095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            }
71105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            store_reg_bx(env, s, rd, tmp);
71118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
71128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0x08:
71138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (set_cc) {
71145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                tcg_gen_and_i32(tmp, tmp, tmp2);
71155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                gen_logic_CC(tmp);
71168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
71175285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tcg_temp_free_i32(tmp);
71188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
71198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0x09:
71208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (set_cc) {
71215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                tcg_gen_xor_i32(tmp, tmp, tmp2);
71225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                gen_logic_CC(tmp);
71238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
71245285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tcg_temp_free_i32(tmp);
71258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
71268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0x0a:
71278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (set_cc) {
71280b4c9e8457959b01cd26f60ef214e9b5b7a297d4David 'Digit' Turner                gen_helper_sub_cc(tmp, cpu_env, tmp, tmp2);
71298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
71305285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tcg_temp_free_i32(tmp);
71318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
71328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0x0b:
71338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (set_cc) {
71340b4c9e8457959b01cd26f60ef214e9b5b7a297d4David 'Digit' Turner                gen_helper_add_cc(tmp, cpu_env, tmp, tmp2);
71358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
71365285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tcg_temp_free_i32(tmp);
71378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
71388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0x0c:
71395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            tcg_gen_or_i32(tmp, tmp, tmp2);
71405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            if (logic_cc) {
71415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                gen_logic_CC(tmp);
71425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            }
71435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            store_reg_bx(env, s, rd, tmp);
71448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
71458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0x0d:
71468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (logic_cc && rd == 15) {
71478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* MOVS r15, ... is used for exception return.  */
71485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                if (IS_USER(s)) {
71498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    goto illegal_op;
71505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                }
71515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                gen_exception_return(s, tmp2);
71528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            } else {
71535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                if (logic_cc) {
71545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                    gen_logic_CC(tmp2);
71555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                }
71565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                store_reg_bx(env, s, rd, tmp2);
71578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
71588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
71598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0x0e:
71605285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tcg_gen_andc_i32(tmp, tmp, tmp2);
71615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            if (logic_cc) {
71625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                gen_logic_CC(tmp);
71635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            }
71645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            store_reg_bx(env, s, rd, tmp);
71658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
71668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        default:
71678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0x0f:
71685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            tcg_gen_not_i32(tmp2, tmp2);
71695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            if (logic_cc) {
71705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                gen_logic_CC(tmp2);
71715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            }
71725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            store_reg_bx(env, s, rd, tmp2);
71738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
71748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
71755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (op1 != 0x0f && op1 != 0x0d) {
71765285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tcg_temp_free_i32(tmp2);
71775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        }
71788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } else {
71798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* other instructions */
71808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        op1 = (insn >> 24) & 0xf;
71818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        switch(op1) {
71828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0x0:
71838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0x1:
71848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* multiplies, extra load/stores */
71858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            sh = (insn >> 5) & 3;
71868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (sh == 0) {
71878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (op1 == 0x0) {
71888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    rd = (insn >> 16) & 0xf;
71898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    rn = (insn >> 12) & 0xf;
71908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    rs = (insn >> 8) & 0xf;
71918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    rm = (insn) & 0xf;
71928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    op1 = (insn >> 20) & 0xf;
71938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    switch (op1) {
71948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    case 0: case 1: case 2: case 3: case 6:
71958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        /* 32 bit mul */
71968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        tmp = load_reg(s, rs);
71978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        tmp2 = load_reg(s, rm);
71988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        tcg_gen_mul_i32(tmp, tmp, tmp2);
71995285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tcg_temp_free_i32(tmp2);
72008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        if (insn & (1 << 22)) {
72018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            /* Subtract (mls) */
72028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            ARCH(6T2);
72038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            tmp2 = load_reg(s, rn);
72048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            tcg_gen_sub_i32(tmp, tmp2, tmp);
72055285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            tcg_temp_free_i32(tmp2);
72068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        } else if (insn & (1 << 21)) {
72078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            /* Add */
72088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            tmp2 = load_reg(s, rn);
72098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            tcg_gen_add_i32(tmp, tmp, tmp2);
72105285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            tcg_temp_free_i32(tmp2);
72118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        }
72128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        if (insn & (1 << 20))
72138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            gen_logic_CC(tmp);
72148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        store_reg(s, rd, tmp);
72158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        break;
72165285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    case 4:
72175285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        /* 64 bit mul double accumulate (UMAAL) */
72185285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        ARCH(6);
72198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        tmp = load_reg(s, rs);
72208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        tmp2 = load_reg(s, rm);
72215285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tmp64 = gen_mulu_i64_i32(tmp, tmp2);
72225285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        gen_addq_lo(s, tmp64, rn);
72235285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        gen_addq_lo(s, tmp64, rd);
72245285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        gen_storeq_reg(s, rn, rd, tmp64);
72255285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tcg_temp_free_i64(tmp64);
72265285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        break;
72275285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    case 8: case 9: case 10: case 11:
72285285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    case 12: case 13: case 14: case 15:
72295285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        /* 64 bit mul: UMULL, UMLAL, SMULL, SMLAL. */
72305285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tmp = load_reg(s, rs);
72315285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tmp2 = load_reg(s, rm);
72325285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        if (insn & (1 << 22)) {
72335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                            tmp64 = gen_muls_i64_i32(tmp, tmp2);
72345285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        } else {
72355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                            tmp64 = gen_mulu_i64_i32(tmp, tmp2);
72365285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        }
72375285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        if (insn & (1 << 21)) { /* mult accumulate */
72385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                            gen_addq(s, tmp64, rn, rd);
72398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        }
72405285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        if (insn & (1 << 20)) {
72415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                            gen_logicq_cc(tmp64);
72425285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        }
72435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                        gen_storeq_reg(s, rn, rd, tmp64);
72445285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tcg_temp_free_i64(tmp64);
72458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        break;
72465285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    default:
72475285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        goto illegal_op;
72488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
72498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                } else {
72508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    rn = (insn >> 16) & 0xf;
72518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    rd = (insn >> 12) & 0xf;
72528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if (insn & (1 << 23)) {
72538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        /* load/store exclusive */
72545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                        op1 = (insn >> 21) & 0x3;
72555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                        if (op1)
72565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                            ARCH(6K);
72575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                        else
72585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                            ARCH(6);
72595285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        addr = tcg_temp_local_new_i32();
72605285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        load_reg_var(s, addr, rn);
72618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        if (insn & (1 << 20)) {
72625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                            switch (op1) {
72635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                            case 0: /* ldrex */
72645285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                                gen_load_exclusive(s, rd, 15, addr, 2);
72655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                                break;
72665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                            case 1: /* ldrexd */
72675285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                                gen_load_exclusive(s, rd, rd + 1, addr, 3);
72685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                                break;
72695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                            case 2: /* ldrexb */
72705285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                                gen_load_exclusive(s, rd, 15, addr, 0);
72715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                                break;
72725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                            case 3: /* ldrexh */
72735285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                                gen_load_exclusive(s, rd, 15, addr, 1);
72745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                                break;
72755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                            default:
72765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                                abort();
72775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                            }
72788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        } else {
72798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            rm = insn & 0xf;
72805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                            switch (op1) {
72815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                            case 0:  /*  strex */
72825285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                                gen_store_exclusive(s, rd, rm, 15, addr, 2);
72835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                                break;
72845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                            case 1: /*  strexd */
72855285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                                gen_store_exclusive(s, rd, rm, rm + 1, addr, 3);
72865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                                break;
72875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                            case 2: /*  strexb */
72885285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                                gen_store_exclusive(s, rd, rm, 15, addr, 0);
72895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                                break;
72905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                            case 3: /* strexh */
72915285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                                gen_store_exclusive(s, rd, rm, 15, addr, 1);
72925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                                break;
72935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                            default:
72945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                                abort();
72955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                            }
72968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        }
72975285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tcg_temp_free(addr);
72988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    } else {
72998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        /* SWP instruction */
73008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        rm = (insn) & 0xf;
73018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
73028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        /* ??? This is not really atomic.  However we know
73038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                           we never have multiple CPUs running in parallel,
73048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                           so it is good enough.  */
73058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        addr = load_reg(s, rn);
73068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        tmp = load_reg(s, rm);
73078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        if (insn & (1 << 22)) {
73088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            tmp2 = gen_ld8u(addr, IS_USER(s));
73098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            gen_st8(tmp, addr, IS_USER(s));
73108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        } else {
73118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            tmp2 = gen_ld32(addr, IS_USER(s));
73128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            gen_st32(tmp, addr, IS_USER(s));
73138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        }
73145285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tcg_temp_free_i32(addr);
73158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        store_reg(s, rd, tmp2);
73168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
73178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
73188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            } else {
73198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                int address_offset;
73208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                int load;
73218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* Misc load/store */
73228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                rn = (insn >> 16) & 0xf;
73238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                rd = (insn >> 12) & 0xf;
73248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                addr = load_reg(s, rn);
73258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (insn & (1 << 24))
73268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    gen_add_datah_offset(s, insn, 0, addr);
73278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                address_offset = 0;
73288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (insn & (1 << 20)) {
73298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    /* load */
73308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    switch(sh) {
73318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    case 1:
73328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        tmp = gen_ld16u(addr, IS_USER(s));
73338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        break;
73348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    case 2:
73358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        tmp = gen_ld8s(addr, IS_USER(s));
73368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        break;
73378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    default:
73388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    case 3:
73398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        tmp = gen_ld16s(addr, IS_USER(s));
73408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        break;
73418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
73428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    load = 1;
73438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                } else if (sh & 2) {
73445285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    ARCH(5TE);
73458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    /* doubleword */
73468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if (sh & 1) {
73478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        /* store */
73488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        tmp = load_reg(s, rd);
73498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        gen_st32(tmp, addr, IS_USER(s));
73508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        tcg_gen_addi_i32(addr, addr, 4);
73518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        tmp = load_reg(s, rd + 1);
73528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        gen_st32(tmp, addr, IS_USER(s));
73538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        load = 0;
73548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    } else {
73558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        /* load */
73568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        tmp = gen_ld32(addr, IS_USER(s));
73578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        store_reg(s, rd, tmp);
73588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        tcg_gen_addi_i32(addr, addr, 4);
73598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        tmp = gen_ld32(addr, IS_USER(s));
73608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        rd++;
73618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        load = 1;
73628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
73638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    address_offset = -4;
73648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                } else {
73658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    /* store */
73668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    tmp = load_reg(s, rd);
73678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    gen_st16(tmp, addr, IS_USER(s));
73688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    load = 0;
73698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
73708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* Perform base writeback before the loaded value to
73718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                   ensure correct behavior with overlapping index registers.
73728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                   ldrd with base writeback is is undefined if the
73738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                   destination and index registers overlap.  */
73748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (!(insn & (1 << 24))) {
73758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    gen_add_datah_offset(s, insn, address_offset, addr);
73768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    store_reg(s, rn, addr);
73778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                } else if (insn & (1 << 21)) {
73788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if (address_offset)
73798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        tcg_gen_addi_i32(addr, addr, address_offset);
73808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    store_reg(s, rn, addr);
73818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                } else {
73825285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tcg_temp_free_i32(addr);
73838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
73848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (load) {
73858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    /* Complete the load.  */
73868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    store_reg(s, rd, tmp);
73878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
73888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
73898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
73908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0x4:
73918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0x5:
73928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            goto do_ldst;
73938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0x6:
73948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0x7:
73958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (insn & (1 << 4)) {
73968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                ARCH(6);
73978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* Armv6 Media instructions.  */
73988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                rm = insn & 0xf;
73998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                rn = (insn >> 16) & 0xf;
74008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                rd = (insn >> 12) & 0xf;
74018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                rs = (insn >> 8) & 0xf;
74028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                switch ((insn >> 23) & 3) {
74038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                case 0: /* Parallel add/subtract.  */
74048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    op1 = (insn >> 20) & 7;
74058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    tmp = load_reg(s, rn);
74068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    tmp2 = load_reg(s, rm);
74078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    sh = (insn >> 5) & 7;
74088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if ((op1 & 3) == 0 || sh == 5 || sh == 6)
74098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        goto illegal_op;
74108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    gen_arm_parallel_addsub(op1, sh, tmp, tmp2);
74115285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tcg_temp_free_i32(tmp2);
74128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    store_reg(s, rd, tmp);
74138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    break;
74148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                case 1:
74158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if ((insn & 0x00700020) == 0) {
74168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        /* Halfword pack.  */
74178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        tmp = load_reg(s, rn);
74188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        tmp2 = load_reg(s, rm);
74198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        shift = (insn >> 7) & 0x1f;
74208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        if (insn & (1 << 6)) {
74218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            /* pkhtb */
74228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            if (shift == 0)
74238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                shift = 31;
74248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            tcg_gen_sari_i32(tmp2, tmp2, shift);
74258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            tcg_gen_andi_i32(tmp, tmp, 0xffff0000);
74268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            tcg_gen_ext16u_i32(tmp2, tmp2);
74278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        } else {
74288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            /* pkhbt */
74298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            if (shift)
74308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                tcg_gen_shli_i32(tmp2, tmp2, shift);
74318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            tcg_gen_ext16u_i32(tmp, tmp);
74328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            tcg_gen_andi_i32(tmp2, tmp2, 0xffff0000);
74338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        }
74348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        tcg_gen_or_i32(tmp, tmp, tmp2);
74355285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tcg_temp_free_i32(tmp2);
74368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        store_reg(s, rd, tmp);
74378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    } else if ((insn & 0x00200020) == 0x00200000) {
74388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        /* [us]sat */
74398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        tmp = load_reg(s, rm);
74408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        shift = (insn >> 7) & 0x1f;
74418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        if (insn & (1 << 6)) {
74428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            if (shift == 0)
74438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                shift = 31;
74448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            tcg_gen_sari_i32(tmp, tmp, shift);
74458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        } else {
74468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            tcg_gen_shli_i32(tmp, tmp, shift);
74478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        }
74488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        sh = (insn >> 16) & 0x1f;
74495285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tmp2 = tcg_const_i32(sh);
74505285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        if (insn & (1 << 22))
74510b4c9e8457959b01cd26f60ef214e9b5b7a297d4David 'Digit' Turner                          gen_helper_usat(tmp, cpu_env, tmp, tmp2);
74525285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        else
74530b4c9e8457959b01cd26f60ef214e9b5b7a297d4David 'Digit' Turner                          gen_helper_ssat(tmp, cpu_env, tmp, tmp2);
74545285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tcg_temp_free_i32(tmp2);
74558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        store_reg(s, rd, tmp);
74568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    } else if ((insn & 0x00300fe0) == 0x00200f20) {
74578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        /* [us]sat16 */
74588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        tmp = load_reg(s, rm);
74598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        sh = (insn >> 16) & 0x1f;
74605285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tmp2 = tcg_const_i32(sh);
74615285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        if (insn & (1 << 22))
74620b4c9e8457959b01cd26f60ef214e9b5b7a297d4David 'Digit' Turner                          gen_helper_usat16(tmp, cpu_env, tmp, tmp2);
74635285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        else
74640b4c9e8457959b01cd26f60ef214e9b5b7a297d4David 'Digit' Turner                          gen_helper_ssat16(tmp, cpu_env, tmp, tmp2);
74655285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tcg_temp_free_i32(tmp2);
74668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        store_reg(s, rd, tmp);
74678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    } else if ((insn & 0x00700fe0) == 0x00000fa0) {
74688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        /* Select bytes.  */
74698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        tmp = load_reg(s, rn);
74708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        tmp2 = load_reg(s, rm);
74715285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tmp3 = tcg_temp_new_i32();
7472e2678e116c8cdb0f36b247a5bd9cfacc849362fcDavid 'Digit' Turner                        tcg_gen_ld_i32(tmp3, cpu_env, offsetof(CPUARMState, GE));
74738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        gen_helper_sel_flags(tmp, tmp3, tmp, tmp2);
74745285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tcg_temp_free_i32(tmp3);
74755285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tcg_temp_free_i32(tmp2);
74768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        store_reg(s, rd, tmp);
74778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    } else if ((insn & 0x000003e0) == 0x00000060) {
74788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        tmp = load_reg(s, rm);
74798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        shift = (insn >> 10) & 3;
74805285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        /* ??? In many cases it's not necessary to do a
74818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                           rotate, a shift is sufficient.  */
74828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        if (shift != 0)
74835285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            tcg_gen_rotri_i32(tmp, tmp, shift * 8);
74848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        op1 = (insn >> 20) & 7;
74858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        switch (op1) {
74868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        case 0: gen_sxtb16(tmp);  break;
74878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        case 2: gen_sxtb(tmp);    break;
74888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        case 3: gen_sxth(tmp);    break;
74898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        case 4: gen_uxtb16(tmp);  break;
74908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        case 6: gen_uxtb(tmp);    break;
74918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        case 7: gen_uxth(tmp);    break;
74925285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        default: tcg_temp_free_i32(tmp); goto illegal_op;
74938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        }
74948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        if (rn != 15) {
74958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            tmp2 = load_reg(s, rn);
74968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            if ((op1 & 3) == 0) {
74978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                gen_add16(tmp, tmp2);
74988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            } else {
74998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                tcg_gen_add_i32(tmp, tmp, tmp2);
75005285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                                tcg_temp_free_i32(tmp2);
75018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            }
75028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        }
75038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        store_reg(s, rd, tmp);
75048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    } else if ((insn & 0x003f0f60) == 0x003f0f20) {
75058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        /* rev */
75068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        tmp = load_reg(s, rm);
75078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        if (insn & (1 << 22)) {
75088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            if (insn & (1 << 7)) {
75098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                gen_revsh(tmp);
75108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            } else {
75118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                ARCH(6T2);
75128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                gen_helper_rbit(tmp, tmp);
75138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            }
75148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        } else {
75158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            if (insn & (1 << 7))
75168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                gen_rev16(tmp);
75178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            else
75185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                                tcg_gen_bswap32_i32(tmp, tmp);
75198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        }
75208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        store_reg(s, rd, tmp);
75218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    } else {
75228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        goto illegal_op;
75238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
75248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    break;
75258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                case 2: /* Multiplies (Type 3).  */
75268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    tmp = load_reg(s, rm);
75278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    tmp2 = load_reg(s, rs);
75288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if (insn & (1 << 20)) {
75295285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        /* Signed multiply most significant [accumulate].
75305285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                           (SMMUL, SMMLA, SMMLS) */
75315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                        tmp64 = gen_muls_i64_i32(tmp, tmp2);
75325285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
75335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                        if (rd != 15) {
75345285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            tmp = load_reg(s, rd);
75358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            if (insn & (1 << 6)) {
75365285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                                tmp64 = gen_subq_msw(tmp64, tmp);
75378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            } else {
75385285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                                tmp64 = gen_addq_msw(tmp64, tmp);
75398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            }
75408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        }
75415285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        if (insn & (1 << 5)) {
75425285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            tcg_gen_addi_i64(tmp64, tmp64, 0x80000000u);
75435285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        }
75445285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tcg_gen_shri_i64(tmp64, tmp64, 32);
75455285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tmp = tcg_temp_new_i32();
75465285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tcg_gen_trunc_i64_i32(tmp, tmp64);
75475285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tcg_temp_free_i64(tmp64);
75485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                        store_reg(s, rn, tmp);
75498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    } else {
75508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        if (insn & (1 << 5))
75518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            gen_swap_half(tmp2);
75528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        gen_smul_dual(tmp, tmp2);
75538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        if (insn & (1 << 6)) {
75545285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            /* This subtraction cannot overflow. */
75558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            tcg_gen_sub_i32(tmp, tmp, tmp2);
75568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        } else {
75575285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            /* This addition cannot overflow 32 bits;
75585285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                             * however it may overflow considered as a signed
75595285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                             * operation, in which case we must set the Q flag.
75605285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                             */
75610b4c9e8457959b01cd26f60ef214e9b5b7a297d4David 'Digit' Turner                            gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
75628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        }
75635285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tcg_temp_free_i32(tmp2);
75648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        if (insn & (1 << 22)) {
75658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            /* smlald, smlsld */
75665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                            tmp64 = tcg_temp_new_i64();
75675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                            tcg_gen_ext_i32_i64(tmp64, tmp);
75685285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            tcg_temp_free_i32(tmp);
75695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                            gen_addq(s, tmp64, rd, rn);
75705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                            gen_storeq_reg(s, rd, rn, tmp64);
75715285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            tcg_temp_free_i64(tmp64);
75728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        } else {
75738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            /* smuad, smusd, smlad, smlsd */
75748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            if (rd != 15)
75758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                              {
75768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                tmp2 = load_reg(s, rd);
75770b4c9e8457959b01cd26f60ef214e9b5b7a297d4David 'Digit' Turner                                gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
75785285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                                tcg_temp_free_i32(tmp2);
75798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                              }
75808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            store_reg(s, rn, tmp);
75818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        }
75828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
75838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    break;
75848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                case 3:
75858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    op1 = ((insn >> 17) & 0x38) | ((insn >> 5) & 7);
75868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    switch (op1) {
75878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    case 0: /* Unsigned sum of absolute differences.  */
75888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        ARCH(6);
75898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        tmp = load_reg(s, rm);
75908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        tmp2 = load_reg(s, rs);
75918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        gen_helper_usad8(tmp, tmp, tmp2);
75925285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tcg_temp_free_i32(tmp2);
75935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                        if (rd != 15) {
75945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                            tmp2 = load_reg(s, rd);
75958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            tcg_gen_add_i32(tmp, tmp, tmp2);
75965285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            tcg_temp_free_i32(tmp2);
75978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        }
75985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                        store_reg(s, rn, tmp);
75998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        break;
76008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    case 0x20: case 0x24: case 0x28: case 0x2c:
76018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        /* Bitfield insert/clear.  */
76028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        ARCH(6T2);
76038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        shift = (insn >> 7) & 0x1f;
76048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        i = (insn >> 16) & 0x1f;
76058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        i = i + 1 - shift;
76068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        if (rm == 15) {
76075285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            tmp = tcg_temp_new_i32();
76088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            tcg_gen_movi_i32(tmp, 0);
76098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        } else {
76108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            tmp = load_reg(s, rm);
76118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        }
76128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        if (i != 32) {
76138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            tmp2 = load_reg(s, rd);
76148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            gen_bfi(tmp, tmp2, tmp, shift, (1u << i) - 1);
76155285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            tcg_temp_free_i32(tmp2);
76168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        }
76178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        store_reg(s, rd, tmp);
76188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        break;
76198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    case 0x12: case 0x16: case 0x1a: case 0x1e: /* sbfx */
76208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    case 0x32: case 0x36: case 0x3a: case 0x3e: /* ubfx */
76215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                        ARCH(6T2);
76228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        tmp = load_reg(s, rm);
76238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        shift = (insn >> 7) & 0x1f;
76248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        i = ((insn >> 16) & 0x1f) + 1;
76258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        if (shift + i > 32)
76268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            goto illegal_op;
76278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        if (i < 32) {
76288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            if (op1 & 0x20) {
76298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                gen_ubfx(tmp, shift, (1u << i) - 1);
76308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            } else {
76318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                gen_sbfx(tmp, shift, i);
76328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            }
76338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        }
76348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        store_reg(s, rd, tmp);
76358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        break;
76368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    default:
76378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        goto illegal_op;
76388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
76398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    break;
76408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
76418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                break;
76428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
76438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        do_ldst:
76448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* Check for undefined extension instructions
76458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project             * per the ARM Bible IE:
76468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project             * xxxx 0111 1111 xxxx  xxxx xxxx 1111 xxxx
76478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project             */
76488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            sh = (0xf << 20) | (0xf << 4);
76498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (op1 == 0x7 && ((insn & sh) == sh))
76508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            {
76518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                goto illegal_op;
76528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
76538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* load/store byte/word */
76548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            rn = (insn >> 16) & 0xf;
76558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            rd = (insn >> 12) & 0xf;
76568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tmp2 = load_reg(s, rn);
76578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            i = (IS_USER(s) || (insn & 0x01200000) == 0x00200000);
76588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (insn & (1 << 24))
76598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                gen_add_data_offset(s, insn, tmp2);
76608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (insn & (1 << 20)) {
76618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* load */
76628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (insn & (1 << 22)) {
76638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    tmp = gen_ld8u(tmp2, i);
76648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                } else {
76658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    tmp = gen_ld32(tmp2, i);
76668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
76678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            } else {
76688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* store */
76698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                tmp = load_reg(s, rd);
76708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (insn & (1 << 22))
76718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    gen_st8(tmp, tmp2, i);
76728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                else
76738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    gen_st32(tmp, tmp2, i);
76748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
76758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (!(insn & (1 << 24))) {
76768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                gen_add_data_offset(s, insn, tmp2);
76778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                store_reg(s, rn, tmp2);
76788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            } else if (insn & (1 << 21)) {
76798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                store_reg(s, rn, tmp2);
76808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            } else {
76815285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_temp_free_i32(tmp2);
76828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
76838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (insn & (1 << 20)) {
76848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* Complete the load.  */
76855285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                store_reg_from_load(env, s, rd, tmp);
76868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
76878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
76888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0x08:
76898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0x09:
76908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            {
76918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                int j, n, user, loaded_base;
76928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                TCGv loaded_var;
76938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* load/store multiple words */
76948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* XXX: store correct base if write back */
76958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                user = 0;
76968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (insn & (1 << 22)) {
76978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if (IS_USER(s))
76988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        goto illegal_op; /* only usable in supervisor mode */
76998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
77008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if ((insn & (1 << 15)) == 0)
77018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        user = 1;
77028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
77038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                rn = (insn >> 16) & 0xf;
77048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                addr = load_reg(s, rn);
77055285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tmp3 = tcg_const_i32(4);
77068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
77078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* compute total size */
77088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                loaded_base = 0;
77098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                TCGV_UNUSED(loaded_var);
77108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                n = 0;
77118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                for(i=0;i<16;i++) {
77128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if (insn & (1 << i))
77138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        n++;
77148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
77158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* XXX: test invalid n == 0 case ? */
77168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (insn & (1 << 23)) {
77178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if (insn & (1 << 24)) {
77188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        /* pre increment */
77195285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tcg_gen_add_i32(addr, addr, tmp3);
77208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    } else {
77218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        /* post increment */
77228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
77238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                } else {
77248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if (insn & (1 << 24)) {
77258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        /* pre decrement */
77268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        tcg_gen_addi_i32(addr, addr, -(n * 4));
77278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    } else {
77288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        /* post decrement */
77298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        if (n != 1)
77308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        tcg_gen_addi_i32(addr, addr, -((n - 1) * 4));
77318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
77328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
77338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                j = 0;
77348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                for(i=0;i<16;i++) {
77358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if (insn & (1 << i)) {
77368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        if (insn & (1 << 20)) {
77378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            /* load */
77388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            tmp = gen_ld32(addr, IS_USER(s));
77395285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            if (user) {
77405285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                                tmp2 = tcg_const_i32(i);
77410b4c9e8457959b01cd26f60ef214e9b5b7a297d4David 'Digit' Turner                                gen_helper_set_user_reg(cpu_env, tmp2, tmp);
77425285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                                tcg_temp_free_i32(tmp2);
77435285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                                tcg_temp_free_i32(tmp);
77448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            } else if (i == rn) {
77458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                loaded_var = tmp;
77468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                loaded_base = 1;
77478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            } else {
77485285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                                store_reg_from_load(env, s, i, tmp);
77498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            }
77508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        } else {
77518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            /* store */
77528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            if (i == 15) {
77538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                /* special case: r15 = PC + 8 */
77548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                val = (long)s->pc + 4;
77555285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                                tmp = tcg_temp_new_i32();
77568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                tcg_gen_movi_i32(tmp, val);
77578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            } else if (user) {
77585285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                                tmp = tcg_temp_new_i32();
77595285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                                tmp2 = tcg_const_i32(i);
77600b4c9e8457959b01cd26f60ef214e9b5b7a297d4David 'Digit' Turner                                gen_helper_get_user_reg(tmp, cpu_env, tmp2);
77615285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                                tcg_temp_free_i32(tmp2);
77628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            } else {
77638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                tmp = load_reg(s, i);
77648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            }
77658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            gen_st32(tmp, addr, IS_USER(s));
77668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        }
77678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        j++;
77688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        /* no need to add after the last transfer */
77698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        if (j != n)
77705285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            tcg_gen_add_i32(addr, addr, tmp3);
77718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
77728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
77738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (insn & (1 << 21)) {
77748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    /* write back */
77758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if (insn & (1 << 23)) {
77768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        if (insn & (1 << 24)) {
77778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            /* pre increment */
77788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        } else {
77798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            /* post increment */
77805285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            tcg_gen_add_i32(addr, addr, tmp3);
77818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        }
77828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    } else {
77838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        if (insn & (1 << 24)) {
77848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            /* pre decrement */
77858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            if (n != 1)
77868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                tcg_gen_addi_i32(addr, addr, -((n - 1) * 4));
77878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        } else {
77888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            /* post decrement */
77898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            tcg_gen_addi_i32(addr, addr, -(n * 4));
77908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        }
77918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
77928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    store_reg(s, rn, addr);
77938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                } else {
77945285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tcg_temp_free_i32(addr);
77958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
77965285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_temp_free_i32(tmp3);
77978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (loaded_base) {
77988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    store_reg(s, rn, loaded_var);
77998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
78008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if ((insn & (1 << 22)) && !user) {
78018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    /* Restore CPSR from SPSR.  */
78028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    tmp = load_cpu_field(spsr);
78038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    gen_set_cpsr(tmp, 0xffffffff);
78045285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tcg_temp_free_i32(tmp);
78058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    s->is_jmp = DISAS_UPDATE;
78068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
78078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
78088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
78098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0xa:
78108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0xb:
78118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            {
78128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                int32_t offset;
78135285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
78148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* branch (and link) */
78158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                val = (int32_t)s->pc;
78168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (insn & (1 << 24)) {
78175285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tmp = tcg_temp_new_i32();
78188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    tcg_gen_movi_i32(tmp, val);
78198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    store_reg(s, 14, tmp);
78208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
78218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                offset = (((int32_t)insn << 8) >> 8);
78228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                val += (offset << 2) + 4;
78238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                gen_jmp(s, val);
78248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
78258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
78268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0xc:
78278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0xd:
78288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0xe:
78298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* Coprocessor.  */
78308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (disas_coproc_insn(env, s, insn))
78318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                goto illegal_op;
78328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
78338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0xf:
78348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* swi */
78358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            gen_set_pc_im(s->pc);
78368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            s->is_jmp = DISAS_SWI;
78378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
78388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        default:
78398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        illegal_op:
78405285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            gen_exception_insn(s, 4, EXCP_UDEF);
78418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
78428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
78438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
78448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
78458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
78468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Return true if this is a Thumb-2 logical op.  */
78478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
78488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectthumb2_logic_op(int op)
78498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
78508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return (op < 8);
78518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
78528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
78538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Generate code for a Thumb-2 data processing operation.  If CONDS is nonzero
78548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   then set condition code flags based on the result of the operation.
78558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   If SHIFTER_OUT is nonzero then set the carry flag for logical operations
78568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   to the high bit of T1.
78578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   Returns zero if the opcode is valid.  */
78588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
78598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
78605285864985be9077e58e42235af6582dee72e841David 'Digit' Turnergen_thumb2_data_op(DisasContext *s, int op, int conds, uint32_t shifter_out, TCGv t0, TCGv t1)
78618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
78628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int logic_cc;
78638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
78648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    logic_cc = 0;
78658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    switch (op) {
78668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0: /* and */
78675285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tcg_gen_and_i32(t0, t0, t1);
78688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        logic_cc = conds;
78698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
78708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 1: /* bic */
78715285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tcg_gen_andc_i32(t0, t0, t1);
78728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        logic_cc = conds;
78738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
78748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 2: /* orr */
78755285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tcg_gen_or_i32(t0, t0, t1);
78768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        logic_cc = conds;
78778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
78788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 3: /* orn */
78795285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tcg_gen_orc_i32(t0, t0, t1);
78808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        logic_cc = conds;
78818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
78828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 4: /* eor */
78835285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tcg_gen_xor_i32(t0, t0, t1);
78848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        logic_cc = conds;
78858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
78868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 8: /* add */
78878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (conds)
78880b4c9e8457959b01cd26f60ef214e9b5b7a297d4David 'Digit' Turner            gen_helper_add_cc(t0, cpu_env, t0, t1);
78898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        else
78905285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tcg_gen_add_i32(t0, t0, t1);
78918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
78928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 10: /* adc */
78938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (conds)
78940b4c9e8457959b01cd26f60ef214e9b5b7a297d4David 'Digit' Turner            gen_helper_adc_cc(t0, cpu_env, t0, t1);
78958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        else
78965285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            gen_adc(t0, t1);
78978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
78988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 11: /* sbc */
78998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (conds)
79000b4c9e8457959b01cd26f60ef214e9b5b7a297d4David 'Digit' Turner            gen_helper_sbc_cc(t0, cpu_env, t0, t1);
79018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        else
79025285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            gen_sub_carry(t0, t0, t1);
79038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
79048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 13: /* sub */
79058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (conds)
79060b4c9e8457959b01cd26f60ef214e9b5b7a297d4David 'Digit' Turner            gen_helper_sub_cc(t0, cpu_env, t0, t1);
79078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        else
79085285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tcg_gen_sub_i32(t0, t0, t1);
79098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
79108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 14: /* rsb */
79118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (conds)
79120b4c9e8457959b01cd26f60ef214e9b5b7a297d4David 'Digit' Turner            gen_helper_sub_cc(t0, cpu_env, t1, t0);
79138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        else
79145285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tcg_gen_sub_i32(t0, t1, t0);
79158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
79168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    default: /* 5, 6, 7, 9, 12, 15. */
79178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return 1;
79188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
79198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (logic_cc) {
79205285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        gen_logic_CC(t0);
79218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (shifter_out)
79225285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            gen_set_CF_bit31(t1);
79238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
79248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
79258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
79268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
79278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Translate a 32-bit thumb instruction.  Returns nonzero if the instruction
79288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   is not legal.  */
7929e2678e116c8cdb0f36b247a5bd9cfacc849362fcDavid 'Digit' Turnerstatic int disas_thumb2_insn(CPUARMState *env, DisasContext *s, uint16_t insn_hw1)
79308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
79318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    uint32_t insn, imm, shift, offset;
79328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    uint32_t rd, rn, rm, rs;
79338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    TCGv tmp;
79348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    TCGv tmp2;
79358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    TCGv tmp3;
79368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    TCGv addr;
79375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    TCGv_i64 tmp64;
79388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int op;
79398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int shiftop;
79408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int conds;
79418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int logic_cc;
79428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
79438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!(arm_feature(env, ARM_FEATURE_THUMB2)
79448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project          || arm_feature (env, ARM_FEATURE_M))) {
79458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* Thumb-1 cores may need to treat bl and blx as a pair of
79468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project           16-bit instructions to get correct prefetch abort behavior.  */
79478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        insn = insn_hw1;
79488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if ((insn & (1 << 12)) == 0) {
79495285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            ARCH(5);
79508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* Second half of blx.  */
79518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            offset = ((insn & 0x7ff) << 1);
79528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tmp = load_reg(s, 14);
79538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tcg_gen_addi_i32(tmp, tmp, offset);
79548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tcg_gen_andi_i32(tmp, tmp, 0xfffffffc);
79558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
79565285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tmp2 = tcg_temp_new_i32();
79578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tcg_gen_movi_i32(tmp2, s->pc | 1);
79588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            store_reg(s, 14, tmp2);
79598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            gen_bx(s, tmp);
79608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 0;
79618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
79628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (insn & (1 << 11)) {
79638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* Second half of bl.  */
79648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            offset = ((insn & 0x7ff) << 1) | 1;
79658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tmp = load_reg(s, 14);
79668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tcg_gen_addi_i32(tmp, tmp, offset);
79678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
79685285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tmp2 = tcg_temp_new_i32();
79698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tcg_gen_movi_i32(tmp2, s->pc | 1);
79708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            store_reg(s, 14, tmp2);
79718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            gen_bx(s, tmp);
79728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 0;
79738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
79748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if ((s->pc & ~TARGET_PAGE_MASK) == 0) {
79758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* Instruction spans a page boundary.  Implement it as two
79768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project               16-bit instructions in case the second half causes an
79778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project               prefetch abort.  */
79788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            offset = ((int32_t)insn << 21) >> 9;
79795285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tcg_gen_movi_i32(cpu_R[14], s->pc + 2 + offset);
79808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 0;
79818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
79828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* Fall through to 32-bit decode.  */
79838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
79848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7985eca7bc24e45fb6809582795ff88f13384b5ce7dfDavid 'Digit' Turner    insn = cpu_lduw_code(env, s->pc);
79865389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine    s->pc += 2;
79875285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    insn |= (uint32_t)insn_hw1 << 16;
79885389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine
79898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if ((insn & 0xf800e800) != 0xf000e800) {
79908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        ARCH(6T2);
79918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
79928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
79938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    rn = (insn >> 16) & 0xf;
79948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    rs = (insn >> 12) & 0xf;
79958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    rd = (insn >> 8) & 0xf;
79968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    rm = insn & 0xf;
79978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    switch ((insn >> 25) & 0xf) {
79988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0: case 1: case 2: case 3:
79998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* 16-bit instructions.  Should never happen.  */
80008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        abort();
80018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 4:
80028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (insn & (1 << 22)) {
80038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* Other load/store, table branch.  */
80048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (insn & 0x01200000) {
80058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* Load/store doubleword.  */
80068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (rn == 15) {
80075285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    addr = tcg_temp_new_i32();
80088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    tcg_gen_movi_i32(addr, s->pc & ~3);
80098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                } else {
80108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    addr = load_reg(s, rn);
80118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
80128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                offset = (insn & 0xff) * 4;
80138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if ((insn & (1 << 23)) == 0)
80148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    offset = -offset;
80158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (insn & (1 << 24)) {
80168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    tcg_gen_addi_i32(addr, addr, offset);
80178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    offset = 0;
80188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
80198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (insn & (1 << 20)) {
80208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    /* ldrd */
80218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    tmp = gen_ld32(addr, IS_USER(s));
80228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    store_reg(s, rs, tmp);
80238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    tcg_gen_addi_i32(addr, addr, 4);
80248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    tmp = gen_ld32(addr, IS_USER(s));
80258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    store_reg(s, rd, tmp);
80268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                } else {
80278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    /* strd */
80288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    tmp = load_reg(s, rs);
80298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    gen_st32(tmp, addr, IS_USER(s));
80308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    tcg_gen_addi_i32(addr, addr, 4);
80318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    tmp = load_reg(s, rd);
80328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    gen_st32(tmp, addr, IS_USER(s));
80338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
80348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (insn & (1 << 21)) {
80358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    /* Base writeback.  */
80368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if (rn == 15)
80378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        goto illegal_op;
80388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    tcg_gen_addi_i32(addr, addr, offset - 4);
80398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    store_reg(s, rn, addr);
80408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                } else {
80415285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tcg_temp_free_i32(addr);
80428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
80438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            } else if ((insn & (1 << 23)) == 0) {
80448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* Load/store exclusive word.  */
80455285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                addr = tcg_temp_local_new();
80465285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                load_reg_var(s, addr, rn);
80475285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_gen_addi_i32(addr, addr, (insn & 0xff) << 2);
80488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (insn & (1 << 20)) {
80495285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    gen_load_exclusive(s, rs, 15, addr, 2);
80508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                } else {
80515285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    gen_store_exclusive(s, rd, rs, 15, addr, 2);
80528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
80535285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_temp_free(addr);
80548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            } else if ((insn & (1 << 6)) == 0) {
80558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* Table Branch.  */
80568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (rn == 15) {
80575285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    addr = tcg_temp_new_i32();
80588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    tcg_gen_movi_i32(addr, s->pc);
80598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                } else {
80608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    addr = load_reg(s, rn);
80618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
80628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                tmp = load_reg(s, rm);
80638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                tcg_gen_add_i32(addr, addr, tmp);
80648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (insn & (1 << 4)) {
80658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    /* tbh */
80668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    tcg_gen_add_i32(addr, addr, tmp);
80675285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tcg_temp_free_i32(tmp);
80688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    tmp = gen_ld16u(addr, IS_USER(s));
80698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                } else { /* tbb */
80705285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tcg_temp_free_i32(tmp);
80718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    tmp = gen_ld8u(addr, IS_USER(s));
80728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
80735285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_temp_free_i32(addr);
80748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                tcg_gen_shli_i32(tmp, tmp, 1);
80758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                tcg_gen_addi_i32(tmp, tmp, s->pc);
80768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                store_reg(s, 15, tmp);
80778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            } else {
80788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* Load/store exclusive byte/halfword/doubleword.  */
80795285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                ARCH(7);
80808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                op = (insn >> 4) & 0x3;
80815285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                if (op == 2) {
80825285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    goto illegal_op;
80835285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                }
80845285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                addr = tcg_temp_local_new();
80855285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                load_reg_var(s, addr, rn);
80868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (insn & (1 << 20)) {
80875285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    gen_load_exclusive(s, rs, rd, addr, op);
80888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                } else {
80895285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    gen_store_exclusive(s, rm, rs, rd, addr, op);
80908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
80915285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_temp_free(addr);
80928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
80938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        } else {
80948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* Load/store multiple, RFE, SRS.  */
80958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (((insn >> 23) & 1) == ((insn >> 24) & 1)) {
80968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* Not available in user mode.  */
80978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (IS_USER(s))
80988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    goto illegal_op;
80998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (insn & (1 << 20)) {
81008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    /* rfe */
81018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    addr = load_reg(s, rn);
81028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if ((insn & (1 << 24)) == 0)
81038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        tcg_gen_addi_i32(addr, addr, -8);
81048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    /* Load PC into tmp and CPSR into tmp2.  */
81058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    tmp = gen_ld32(addr, 0);
81068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    tcg_gen_addi_i32(addr, addr, 4);
81078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    tmp2 = gen_ld32(addr, 0);
81088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if (insn & (1 << 21)) {
81098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        /* Base writeback.  */
81108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        if (insn & (1 << 24)) {
81118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            tcg_gen_addi_i32(addr, addr, 4);
81128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        } else {
81138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            tcg_gen_addi_i32(addr, addr, -4);
81148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        }
81158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        store_reg(s, rn, addr);
81168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    } else {
81175285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tcg_temp_free_i32(addr);
81188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
81198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    gen_rfe(s, tmp, tmp2);
81208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                } else {
81218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    /* srs */
81228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    op = (insn & 0x1f);
81235285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    addr = tcg_temp_new_i32();
81245285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tmp = tcg_const_i32(op);
81255285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    gen_helper_get_r13_banked(addr, cpu_env, tmp);
81265285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tcg_temp_free_i32(tmp);
81278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if ((insn & (1 << 24)) == 0) {
81288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        tcg_gen_addi_i32(addr, addr, -8);
81298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
81308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    tmp = load_reg(s, 14);
81318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    gen_st32(tmp, addr, 0);
81328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    tcg_gen_addi_i32(addr, addr, 4);
81335285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tmp = tcg_temp_new_i32();
81340b4c9e8457959b01cd26f60ef214e9b5b7a297d4David 'Digit' Turner                    gen_helper_cpsr_read(tmp, cpu_env);
81358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    gen_st32(tmp, addr, 0);
81368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if (insn & (1 << 21)) {
81378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        if ((insn & (1 << 24)) == 0) {
81388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            tcg_gen_addi_i32(addr, addr, -4);
81398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        } else {
81408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            tcg_gen_addi_i32(addr, addr, 4);
81418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        }
81425285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tmp = tcg_const_i32(op);
81435285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        gen_helper_set_r13_banked(cpu_env, tmp, addr);
81445285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tcg_temp_free_i32(tmp);
81458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    } else {
81465285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tcg_temp_free_i32(addr);
81478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
81488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
81498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            } else {
81505285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                int i, loaded_base = 0;
81515285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                TCGv loaded_var;
81528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* Load/store multiple.  */
81538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                addr = load_reg(s, rn);
81548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                offset = 0;
81558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                for (i = 0; i < 16; i++) {
81568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if (insn & (1 << i))
81578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        offset += 4;
81588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
81598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (insn & (1 << 24)) {
81608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    tcg_gen_addi_i32(addr, addr, -offset);
81618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
81628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
81635285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                TCGV_UNUSED(loaded_var);
81645285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tmp2 = tcg_const_i32(4);
81658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                for (i = 0; i < 16; i++) {
81668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if ((insn & (1 << i)) == 0)
81678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        continue;
81688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if (insn & (1 << 20)) {
81698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        /* Load.  */
81708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        tmp = gen_ld32(addr, IS_USER(s));
81718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        if (i == 15) {
81728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            gen_bx(s, tmp);
81735285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        } else if (i == rn) {
81745285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            loaded_var = tmp;
81755285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            loaded_base = 1;
81768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        } else {
81778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            store_reg(s, i, tmp);
81788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        }
81798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    } else {
81808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        /* Store.  */
81818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        tmp = load_reg(s, i);
81828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        gen_st32(tmp, addr, IS_USER(s));
81838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
81845285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tcg_gen_add_i32(addr, addr, tmp2);
81855285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                }
81865285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                if (loaded_base) {
81875285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    store_reg(s, rn, loaded_var);
81888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
81895285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_temp_free_i32(tmp2);
81908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (insn & (1 << 21)) {
81918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    /* Base register writeback.  */
81928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if (insn & (1 << 24)) {
81938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        tcg_gen_addi_i32(addr, addr, -offset);
81948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
81958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    /* Fault if writeback register is in register list.  */
81968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if (insn & (1 << rn))
81978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        goto illegal_op;
81988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    store_reg(s, rn, addr);
81998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                } else {
82005285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tcg_temp_free_i32(addr);
82018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
82028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
82038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
82048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
82055285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    case 5:
82065285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
82078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        op = (insn >> 21) & 0xf;
82085285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        if (op == 6) {
82095285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            /* Halfword pack.  */
82105285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tmp = load_reg(s, rn);
82115285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tmp2 = load_reg(s, rm);
82125285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            shift = ((insn >> 10) & 0x1c) | ((insn >> 6) & 0x3);
82135285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            if (insn & (1 << 5)) {
82145285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                /* pkhtb */
82155285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                if (shift == 0)
82165285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    shift = 31;
82175285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_gen_sari_i32(tmp2, tmp2, shift);
82185285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_gen_andi_i32(tmp, tmp, 0xffff0000);
82195285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_gen_ext16u_i32(tmp2, tmp2);
82205285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            } else {
82215285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                /* pkhbt */
82225285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                if (shift)
82235285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tcg_gen_shli_i32(tmp2, tmp2, shift);
82245285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_gen_ext16u_i32(tmp, tmp);
82255285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_gen_andi_i32(tmp2, tmp2, 0xffff0000);
82265285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            }
82275285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tcg_gen_or_i32(tmp, tmp, tmp2);
82285285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tcg_temp_free_i32(tmp2);
82295285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            store_reg(s, rd, tmp);
82305285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        } else {
82315285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            /* Data processing register constant shift.  */
82325285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            if (rn == 15) {
82335285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tmp = tcg_temp_new_i32();
82345285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_gen_movi_i32(tmp, 0);
82355285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            } else {
82365285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tmp = load_reg(s, rn);
82375285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            }
82385285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tmp2 = load_reg(s, rm);
82395285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
82405285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            shiftop = (insn >> 4) & 3;
82415285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            shift = ((insn >> 6) & 3) | ((insn >> 10) & 0x1c);
82425285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            conds = (insn & (1 << 20)) != 0;
82435285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            logic_cc = (conds && thumb2_logic_op(op));
82445285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            gen_arm_shift_im(tmp2, shiftop, shift, logic_cc);
82455285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            if (gen_thumb2_data_op(s, op, conds, 0, tmp, tmp2))
82465285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                goto illegal_op;
82475285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tcg_temp_free_i32(tmp2);
82485285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            if (rd != 15) {
82495285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                store_reg(s, rd, tmp);
82505285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            } else {
82515285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_temp_free_i32(tmp);
82525285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            }
82535285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        }
82548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
82558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 13: /* Misc data processing.  */
82568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        op = ((insn >> 22) & 6) | ((insn >> 7) & 1);
82578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (op < 4 && (insn & 0xf000) != 0xf000)
82588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            goto illegal_op;
82598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        switch (op) {
82608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0: /* Register controlled shift.  */
82618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tmp = load_reg(s, rn);
82628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tmp2 = load_reg(s, rm);
82638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if ((insn & 0x70) != 0)
82648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                goto illegal_op;
82658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            op = (insn >> 21) & 3;
82668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            logic_cc = (insn & (1 << 20)) != 0;
82678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            gen_arm_shift_reg(tmp, op, tmp2, logic_cc);
82688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (logic_cc)
82698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                gen_logic_CC(tmp);
82705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            store_reg_bx(env, s, rd, tmp);
82718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
82728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 1: /* Sign/zero extend.  */
82738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tmp = load_reg(s, rm);
82748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            shift = (insn >> 4) & 3;
82755285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            /* ??? In many cases it's not necessary to do a
82768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project               rotate, a shift is sufficient.  */
82778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (shift != 0)
82785285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_gen_rotri_i32(tmp, tmp, shift * 8);
82798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            op = (insn >> 20) & 7;
82808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            switch (op) {
82818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            case 0: gen_sxth(tmp);   break;
82828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            case 1: gen_uxth(tmp);   break;
82838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            case 2: gen_sxtb16(tmp); break;
82848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            case 3: gen_uxtb16(tmp); break;
82858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            case 4: gen_sxtb(tmp);   break;
82868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            case 5: gen_uxtb(tmp);   break;
82878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            default: goto illegal_op;
82888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
82898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (rn != 15) {
82908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                tmp2 = load_reg(s, rn);
82918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if ((op >> 1) == 1) {
82928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    gen_add16(tmp, tmp2);
82938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                } else {
82948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    tcg_gen_add_i32(tmp, tmp, tmp2);
82955285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tcg_temp_free_i32(tmp2);
82968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
82978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
82988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            store_reg(s, rd, tmp);
82998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
83008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 2: /* SIMD add/subtract.  */
83018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            op = (insn >> 20) & 7;
83028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            shift = (insn >> 4) & 7;
83038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if ((op & 3) == 3 || (shift & 3) == 3)
83048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                goto illegal_op;
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            gen_thumb2_parallel_addsub(op, shift, tmp, tmp2);
83085285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tcg_temp_free_i32(tmp2);
83098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            store_reg(s, rd, tmp);
83108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
83118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 3: /* Other data processing.  */
83128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            op = ((insn >> 17) & 0x38) | ((insn >> 4) & 7);
83138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (op < 4) {
83148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* Saturating add/subtract.  */
83158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                tmp = load_reg(s, rn);
83168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                tmp2 = load_reg(s, rm);
83178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (op & 1)
83180b4c9e8457959b01cd26f60ef214e9b5b7a297d4David 'Digit' Turner                    gen_helper_double_saturate(tmp, cpu_env, tmp);
83195285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                if (op & 2)
83200b4c9e8457959b01cd26f60ef214e9b5b7a297d4David 'Digit' Turner                    gen_helper_sub_saturate(tmp, cpu_env, tmp2, tmp);
83218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                else
83220b4c9e8457959b01cd26f60ef214e9b5b7a297d4David 'Digit' Turner                    gen_helper_add_saturate(tmp, cpu_env, tmp, tmp2);
83235285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_temp_free_i32(tmp2);
83248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            } else {
83258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                tmp = load_reg(s, rn);
83268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                switch (op) {
83278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                case 0x0a: /* rbit */
83288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    gen_helper_rbit(tmp, tmp);
83298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    break;
83308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                case 0x08: /* rev */
83315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                    tcg_gen_bswap32_i32(tmp, tmp);
83328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    break;
83338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                case 0x09: /* rev16 */
83348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    gen_rev16(tmp);
83358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    break;
83368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                case 0x0b: /* revsh */
83378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    gen_revsh(tmp);
83388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    break;
83398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                case 0x10: /* sel */
83408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    tmp2 = load_reg(s, rm);
83415285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tmp3 = tcg_temp_new_i32();
8342e2678e116c8cdb0f36b247a5bd9cfacc849362fcDavid 'Digit' Turner                    tcg_gen_ld_i32(tmp3, cpu_env, offsetof(CPUARMState, GE));
83438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    gen_helper_sel_flags(tmp, tmp3, tmp, tmp2);
83445285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tcg_temp_free_i32(tmp3);
83455285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tcg_temp_free_i32(tmp2);
83468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    break;
83478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                case 0x18: /* clz */
83488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    gen_helper_clz(tmp, tmp);
83498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    break;
83508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                default:
83518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    goto illegal_op;
83528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
83538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
83548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            store_reg(s, rd, tmp);
83558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
83568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 4: case 5: /* 32-bit multiply.  Sum of absolute differences.  */
83578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            op = (insn >> 4) & 0xf;
83588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tmp = load_reg(s, rn);
83598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tmp2 = load_reg(s, rm);
83608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            switch ((insn >> 20) & 7) {
83618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            case 0: /* 32 x 32 -> 32 */
83628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                tcg_gen_mul_i32(tmp, tmp, tmp2);
83635285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_temp_free_i32(tmp2);
83648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (rs != 15) {
83658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    tmp2 = load_reg(s, rs);
83668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if (op)
83678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        tcg_gen_sub_i32(tmp, tmp2, tmp);
83688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    else
83698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        tcg_gen_add_i32(tmp, tmp, tmp2);
83705285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tcg_temp_free_i32(tmp2);
83718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
83728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                break;
83738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            case 1: /* 16 x 16 -> 32 */
83748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                gen_mulxy(tmp, tmp2, op & 2, op & 1);
83755285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_temp_free_i32(tmp2);
83768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (rs != 15) {
83778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    tmp2 = load_reg(s, rs);
83780b4c9e8457959b01cd26f60ef214e9b5b7a297d4David 'Digit' Turner                    gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
83795285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tcg_temp_free_i32(tmp2);
83808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
83818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                break;
83828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            case 2: /* Dual multiply add.  */
83838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            case 4: /* Dual multiply subtract.  */
83848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (op)
83858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    gen_swap_half(tmp2);
83868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                gen_smul_dual(tmp, tmp2);
83878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (insn & (1 << 22)) {
83885285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    /* This subtraction cannot overflow. */
83898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    tcg_gen_sub_i32(tmp, tmp, tmp2);
83908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                } else {
83915285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    /* This addition cannot overflow 32 bits;
83925285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                     * however it may overflow considered as a signed
83935285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                     * operation, in which case we must set the Q flag.
83945285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                     */
83950b4c9e8457959b01cd26f60ef214e9b5b7a297d4David 'Digit' Turner                    gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
83968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
83975285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_temp_free_i32(tmp2);
83988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (rs != 15)
83998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                  {
84008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    tmp2 = load_reg(s, rs);
84010b4c9e8457959b01cd26f60ef214e9b5b7a297d4David 'Digit' Turner                    gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
84025285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tcg_temp_free_i32(tmp2);
84038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                  }
84048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                break;
84058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            case 3: /* 32 * 16 -> 32msb */
84068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (op)
84078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    tcg_gen_sari_i32(tmp2, tmp2, 16);
84088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                else
84098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    gen_sxth(tmp2);
84105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                tmp64 = gen_muls_i64_i32(tmp, tmp2);
84115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                tcg_gen_shri_i64(tmp64, tmp64, 16);
84125285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tmp = tcg_temp_new_i32();
84135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                tcg_gen_trunc_i64_i32(tmp, tmp64);
84145285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_temp_free_i64(tmp64);
84158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (rs != 15)
84168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                  {
84178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    tmp2 = load_reg(s, rs);
84180b4c9e8457959b01cd26f60ef214e9b5b7a297d4David 'Digit' Turner                    gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
84195285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tcg_temp_free_i32(tmp2);
84208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                  }
84218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                break;
84225285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            case 5: case 6: /* 32 * 32 -> 32msb (SMMUL, SMMLA, SMMLS) */
84235285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tmp64 = gen_muls_i64_i32(tmp, tmp2);
84248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (rs != 15) {
84255285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tmp = load_reg(s, rs);
84265285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    if (insn & (1 << 20)) {
84275285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tmp64 = gen_addq_msw(tmp64, tmp);
84288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    } else {
84295285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tmp64 = gen_subq_msw(tmp64, tmp);
84308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
84318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
84325285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                if (insn & (1 << 4)) {
84335285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tcg_gen_addi_i64(tmp64, tmp64, 0x80000000u);
84345285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                }
84355285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_gen_shri_i64(tmp64, tmp64, 32);
84365285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tmp = tcg_temp_new_i32();
84375285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_gen_trunc_i64_i32(tmp, tmp64);
84385285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_temp_free_i64(tmp64);
84398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                break;
84408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            case 7: /* Unsigned sum of absolute differences.  */
84418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                gen_helper_usad8(tmp, tmp, tmp2);
84425285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_temp_free_i32(tmp2);
84438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (rs != 15) {
84448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    tmp2 = load_reg(s, rs);
84458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    tcg_gen_add_i32(tmp, tmp, tmp2);
84465285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tcg_temp_free_i32(tmp2);
84478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
84488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                break;
84498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
84508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            store_reg(s, rd, tmp);
84518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
84528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 6: case 7: /* 64-bit multiply, Divide.  */
84538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            op = ((insn >> 4) & 0xf) | ((insn >> 16) & 0x70);
84548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tmp = load_reg(s, rn);
84558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tmp2 = load_reg(s, rm);
84568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if ((op & 0x50) == 0x10) {
84578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* sdiv, udiv */
84588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (!arm_feature(env, ARM_FEATURE_DIV))
84598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    goto illegal_op;
84608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (op & 0x20)
84618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    gen_helper_udiv(tmp, tmp, tmp2);
84628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                else
84638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    gen_helper_sdiv(tmp, tmp, tmp2);
84645285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_temp_free_i32(tmp2);
84658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                store_reg(s, rd, tmp);
84668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            } else if ((op & 0xe) == 0xc) {
84678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* Dual multiply accumulate long.  */
84688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (op & 1)
84698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    gen_swap_half(tmp2);
84708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                gen_smul_dual(tmp, tmp2);
84718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (op & 0x10) {
84728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    tcg_gen_sub_i32(tmp, tmp, tmp2);
84738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                } else {
84748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    tcg_gen_add_i32(tmp, tmp, tmp2);
84758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
84765285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_temp_free_i32(tmp2);
84775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                /* BUGFIX */
84785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                tmp64 = tcg_temp_new_i64();
84795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                tcg_gen_ext_i32_i64(tmp64, tmp);
84805285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_temp_free_i32(tmp);
84815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                gen_addq(s, tmp64, rs, rd);
84825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                gen_storeq_reg(s, rs, rd, tmp64);
84835285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_temp_free_i64(tmp64);
84848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            } else {
84858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (op & 0x20) {
84868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    /* Unsigned 64-bit multiply  */
84875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                    tmp64 = gen_mulu_i64_i32(tmp, tmp2);
84888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                } else {
84898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if (op & 8) {
84908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        /* smlalxy */
84918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        gen_mulxy(tmp, tmp2, op & 2, op & 1);
84925285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tcg_temp_free_i32(tmp2);
84935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                        tmp64 = tcg_temp_new_i64();
84945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                        tcg_gen_ext_i32_i64(tmp64, tmp);
84955285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tcg_temp_free_i32(tmp);
84968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    } else {
84978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        /* Signed 64-bit multiply  */
84985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                        tmp64 = gen_muls_i64_i32(tmp, tmp2);
84998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
85008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
85018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (op & 4) {
85028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    /* umaal */
85035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                    gen_addq_lo(s, tmp64, rs);
85045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                    gen_addq_lo(s, tmp64, rd);
85058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                } else if (op & 0x40) {
85068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    /* 64-bit accumulate.  */
85075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                    gen_addq(s, tmp64, rs, rd);
85088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
85095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                gen_storeq_reg(s, rs, rd, tmp64);
85105285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_temp_free_i64(tmp64);
85118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
85128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
85138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
85148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
85158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 6: case 7: case 14: case 15:
85168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* Coprocessor.  */
85178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (((insn >> 24) & 3) == 3) {
85188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* Translate into the equivalent ARM encoding.  */
85195285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            insn = (insn & 0xe2ffffff) | ((insn & (1 << 28)) >> 4) | (1 << 28);
85208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (disas_neon_data_insn(env, s, insn))
85218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                goto illegal_op;
85228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        } else {
85238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (insn & (1 << 28))
85248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                goto illegal_op;
85258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (disas_coproc_insn (env, s, insn))
85268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                goto illegal_op;
85278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
85288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
85298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 8: case 9: case 10: case 11:
85308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (insn & (1 << 15)) {
85318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* Branches, misc control.  */
85328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (insn & 0x5000) {
85338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* Unconditional branch.  */
85348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* signextend(hw1[10:0]) -> offset[:12].  */
85358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                offset = ((int32_t)insn << 5) >> 9 & ~(int32_t)0xfff;
85368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* hw1[10:0] -> offset[11:1].  */
85378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                offset |= (insn & 0x7ff) << 1;
85388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* (~hw2[13, 11] ^ offset[24]) -> offset[23,22]
85398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                   offset[24:22] already have the same value because of the
85408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                   sign extension above.  */
85418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                offset ^= ((~insn) & (1 << 13)) << 10;
85428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                offset ^= ((~insn) & (1 << 11)) << 11;
85438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
85448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (insn & (1 << 14)) {
85458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    /* Branch and link.  */
85465285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tcg_gen_movi_i32(cpu_R[14], s->pc | 1);
85478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
85488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
85498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                offset += s->pc;
85508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (insn & (1 << 12)) {
85518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    /* b/bl */
85528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    gen_jmp(s, offset);
85538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                } else {
85548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    /* blx */
85558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    offset &= ~(uint32_t)2;
85565285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    /* thumb2 bx, no need to check */
85578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    gen_bx_im(s, offset);
85588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
85598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            } else if (((insn >> 23) & 7) == 7) {
85608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* Misc control */
85618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (insn & (1 << 13))
85628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    goto illegal_op;
85638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
85648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (insn & (1 << 26)) {
85655285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    /* Secure monitor call / smc (v6Z) */
85665285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    if (!(env->cp15.c0_c2[4] & 0xf000) || IS_USER(s)) {
85675285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        goto illegal_op;
85685285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    }
85695285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    gen_smc(env, s);
85708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                } else {
85718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    op = (insn >> 20) & 7;
85728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    switch (op) {
85738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    case 0: /* msr cpsr.  */
85748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        if (IS_M(env)) {
85758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            tmp = load_reg(s, rn);
85768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            addr = tcg_const_i32(insn & 0xff);
85778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            gen_helper_v7m_msr(cpu_env, addr, tmp);
85785285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            tcg_temp_free_i32(addr);
85795285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            tcg_temp_free_i32(tmp);
85808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            gen_lookup_tb(s);
85818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            break;
85828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        }
85838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        /* fall through */
85848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    case 1: /* msr spsr.  */
85858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        if (IS_M(env))
85868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            goto illegal_op;
85875285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tmp = load_reg(s, rn);
85885285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        if (gen_set_psr(s,
85898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                              msr_mask(env, s, (insn >> 8) & 0xf, op == 1),
85905285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                              op == 1, tmp))
85918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            goto illegal_op;
85928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        break;
85938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    case 2: /* cps, nop-hint.  */
85948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        if (((insn >> 8) & 7) == 0) {
85958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            gen_nop_hint(s, insn & 0xff);
85968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        }
85978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        /* Implemented as NOP in user mode.  */
85988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        if (IS_USER(s))
85998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            break;
86008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        offset = 0;
86018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        imm = 0;
86028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        if (insn & (1 << 10)) {
86038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            if (insn & (1 << 7))
86048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                offset |= CPSR_A;
86058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            if (insn & (1 << 6))
86068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                offset |= CPSR_I;
86078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            if (insn & (1 << 5))
86088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                offset |= CPSR_F;
86098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            if (insn & (1 << 9))
86108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                imm = CPSR_A | CPSR_I | CPSR_F;
86118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        }
86128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        if (insn & (1 << 8)) {
86138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            offset |= 0x1f;
86148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            imm |= (insn & 0x1f);
86158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        }
86168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        if (offset) {
86175285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            gen_set_psr_im(s, offset, 0, imm);
86188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        }
86198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        break;
86208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    case 3: /* Special control operations.  */
86215285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        ARCH(7);
86228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        op = (insn >> 4) & 0xf;
86238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        switch (op) {
86248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        case 2: /* clrex */
86255285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            gen_clrex(s);
86268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            break;
86278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        case 4: /* dsb */
86288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        case 5: /* dmb */
86298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        case 6: /* isb */
86308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            /* These execute as NOPs.  */
86318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            break;
86328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        default:
86338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            goto illegal_op;
86348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        }
86358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        break;
86368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    case 4: /* bxj */
86378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        /* Trivial implementation equivalent to bx.  */
86388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        tmp = load_reg(s, rn);
86398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        gen_bx(s, tmp);
86408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        break;
86418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    case 5: /* Exception return.  */
86425285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        if (IS_USER(s)) {
86435285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            goto illegal_op;
86445285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        }
86455285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        if (rn != 14 || rd != 15) {
86465285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            goto illegal_op;
86475285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        }
86485285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tmp = load_reg(s, rn);
86495285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tcg_gen_subi_i32(tmp, tmp, insn & 0xff);
86505285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        gen_exception_return(s, tmp);
86515285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        break;
86528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    case 6: /* mrs cpsr.  */
86535285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tmp = tcg_temp_new_i32();
86548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        if (IS_M(env)) {
86558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            addr = tcg_const_i32(insn & 0xff);
86568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            gen_helper_v7m_mrs(tmp, cpu_env, addr);
86575285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            tcg_temp_free_i32(addr);
86588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        } else {
86590b4c9e8457959b01cd26f60ef214e9b5b7a297d4David 'Digit' Turner                            gen_helper_cpsr_read(tmp, cpu_env);
86608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        }
86618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        store_reg(s, rd, tmp);
86628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        break;
86638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    case 7: /* mrs spsr.  */
86648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        /* Not accessible in user mode.  */
86658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        if (IS_USER(s) || IS_M(env))
86668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            goto illegal_op;
86678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        tmp = load_cpu_field(spsr);
86688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        store_reg(s, rd, tmp);
86698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        break;
86708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
86718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
86728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            } else {
86738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* Conditional branch.  */
86748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                op = (insn >> 22) & 0xf;
86758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* Generate a conditional jump to next instruction.  */
86768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                s->condlabel = gen_new_label();
86778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                gen_test_cc(op ^ 1, s->condlabel);
86788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                s->condjmp = 1;
86798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
86808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* offset[11:1] = insn[10:0] */
86818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                offset = (insn & 0x7ff) << 1;
86828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* offset[17:12] = insn[21:16].  */
86838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                offset |= (insn & 0x003f0000) >> 4;
86848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* offset[31:20] = insn[26].  */
86858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                offset |= ((int32_t)((insn << 5) & 0x80000000)) >> 11;
86868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* offset[18] = insn[13].  */
86878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                offset |= (insn & (1 << 13)) << 5;
86888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* offset[19] = insn[11].  */
86898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                offset |= (insn & (1 << 11)) << 8;
86908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
86918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* jump to the offset */
86928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                gen_jmp(s, s->pc + offset);
86938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
86948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        } else {
86958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* Data processing immediate.  */
86968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (insn & (1 << 25)) {
86978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (insn & (1 << 24)) {
86988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if (insn & (1 << 20))
86998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        goto illegal_op;
87008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    /* Bitfield/Saturate.  */
87018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    op = (insn >> 21) & 7;
87028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    imm = insn & 0x1f;
87038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    shift = ((insn >> 6) & 3) | ((insn >> 10) & 0x1c);
87048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if (rn == 15) {
87055285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tmp = tcg_temp_new_i32();
87068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        tcg_gen_movi_i32(tmp, 0);
87078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    } else {
87088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        tmp = load_reg(s, rn);
87098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
87108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    switch (op) {
87118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    case 2: /* Signed bitfield extract.  */
87128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        imm++;
87138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        if (shift + imm > 32)
87148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            goto illegal_op;
87158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        if (imm < 32)
87168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            gen_sbfx(tmp, shift, imm);
87178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        break;
87188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    case 6: /* Unsigned bitfield extract.  */
87198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        imm++;
87208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        if (shift + imm > 32)
87218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            goto illegal_op;
87228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        if (imm < 32)
87238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            gen_ubfx(tmp, shift, (1u << imm) - 1);
87248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        break;
87258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    case 3: /* Bitfield insert/clear.  */
87268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        if (imm < shift)
87278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            goto illegal_op;
87288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        imm = imm + 1 - shift;
87298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        if (imm != 32) {
87308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            tmp2 = load_reg(s, rd);
87318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            gen_bfi(tmp, tmp2, tmp, shift, (1u << imm) - 1);
87325285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            tcg_temp_free_i32(tmp2);
87338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        }
87348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        break;
87358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    case 7:
87368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        goto illegal_op;
87378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    default: /* Saturate.  */
87388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        if (shift) {
87398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            if (op & 1)
87408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                tcg_gen_sari_i32(tmp, tmp, shift);
87418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            else
87428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                tcg_gen_shli_i32(tmp, tmp, shift);
87438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        }
87448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        tmp2 = tcg_const_i32(imm);
87458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        if (op & 4) {
87468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            /* Unsigned.  */
87478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            if ((op & 1) && shift == 0)
87480b4c9e8457959b01cd26f60ef214e9b5b7a297d4David 'Digit' Turner                                gen_helper_usat16(tmp, cpu_env, tmp, tmp2);
87498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            else
87500b4c9e8457959b01cd26f60ef214e9b5b7a297d4David 'Digit' Turner                                gen_helper_usat(tmp, cpu_env, tmp, tmp2);
87518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        } else {
87528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            /* Signed.  */
87538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            if ((op & 1) && shift == 0)
87540b4c9e8457959b01cd26f60ef214e9b5b7a297d4David 'Digit' Turner                                gen_helper_ssat16(tmp, cpu_env, tmp, tmp2);
87558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            else
87560b4c9e8457959b01cd26f60ef214e9b5b7a297d4David 'Digit' Turner                                gen_helper_ssat(tmp, cpu_env, tmp, tmp2);
87578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        }
87585285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tcg_temp_free_i32(tmp2);
87598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        break;
87608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
87618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    store_reg(s, rd, tmp);
87628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                } else {
87638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    imm = ((insn & 0x04000000) >> 15)
87648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                          | ((insn & 0x7000) >> 4) | (insn & 0xff);
87658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if (insn & (1 << 22)) {
87668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        /* 16-bit immediate.  */
87678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        imm |= (insn >> 4) & 0xf000;
87688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        if (insn & (1 << 23)) {
87698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            /* movt */
87708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            tmp = load_reg(s, rd);
87718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            tcg_gen_ext16u_i32(tmp, tmp);
87728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            tcg_gen_ori_i32(tmp, tmp, imm << 16);
87738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        } else {
87748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            /* movw */
87755285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            tmp = tcg_temp_new_i32();
87768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            tcg_gen_movi_i32(tmp, imm);
87778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        }
87788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    } else {
87798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        /* Add/sub 12-bit immediate.  */
87808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        if (rn == 15) {
87818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            offset = s->pc & ~(uint32_t)3;
87828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            if (insn & (1 << 23))
87838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                offset -= imm;
87848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            else
87858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                offset += imm;
87865285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            tmp = tcg_temp_new_i32();
87878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            tcg_gen_movi_i32(tmp, offset);
87888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        } else {
87898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            tmp = load_reg(s, rn);
87908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            if (insn & (1 << 23))
87918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                tcg_gen_subi_i32(tmp, tmp, imm);
87928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            else
87938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                tcg_gen_addi_i32(tmp, tmp, imm);
87948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        }
87958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
87968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    store_reg(s, rd, tmp);
87978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
87988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            } else {
87998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                int shifter_out = 0;
88008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* modified 12-bit immediate.  */
88018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                shift = ((insn & 0x04000000) >> 23) | ((insn & 0x7000) >> 12);
88028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                imm = (insn & 0xff);
88038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                switch (shift) {
88048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                case 0: /* XY */
88058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    /* Nothing to do.  */
88068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    break;
88078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                case 1: /* 00XY00XY */
88088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    imm |= imm << 16;
88098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    break;
88108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                case 2: /* XY00XY00 */
88118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    imm |= imm << 16;
88128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    imm <<= 8;
88138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    break;
88148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                case 3: /* XYXYXYXY */
88158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    imm |= imm << 16;
88168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    imm |= imm << 8;
88178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    break;
88188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                default: /* Rotated constant.  */
88198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    shift = (shift << 1) | (imm >> 7);
88208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    imm |= 0x80;
88218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    imm = imm << (32 - shift);
88228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    shifter_out = 1;
88238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    break;
88248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
88255285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tmp2 = tcg_temp_new_i32();
88265285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_gen_movi_i32(tmp2, imm);
88278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                rn = (insn >> 16) & 0xf;
88285285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                if (rn == 15) {
88295285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tmp = tcg_temp_new_i32();
88305285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tcg_gen_movi_i32(tmp, 0);
88315285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                } else {
88325285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tmp = load_reg(s, rn);
88335285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                }
88348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                op = (insn >> 21) & 0xf;
88358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (gen_thumb2_data_op(s, op, (insn & (1 << 20)) != 0,
88365285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                                       shifter_out, tmp, tmp2))
88378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    goto illegal_op;
88385285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_temp_free_i32(tmp2);
88398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                rd = (insn >> 8) & 0xf;
88408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (rd != 15) {
88415285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    store_reg(s, rd, tmp);
88425285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                } else {
88435285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tcg_temp_free_i32(tmp);
88448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
88458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
88468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
88478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
88488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 12: /* Load/store single data item.  */
88498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        {
88508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        int postinc = 0;
88518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        int writeback = 0;
88528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        int user;
88538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if ((insn & 0x01100000) == 0x01000000) {
88548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (disas_neon_ls_insn(env, s, insn))
88558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                goto illegal_op;
88568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
88578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
88585285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        op = ((insn >> 21) & 3) | ((insn >> 22) & 4);
88595285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        if (rs == 15) {
88605285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            if (!(insn & (1 << 20))) {
88615285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                goto illegal_op;
88625285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            }
88635285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            if (op != 2) {
88645285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                /* Byte or halfword load space with dest == r15 : memory hints.
88655285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                 * Catch them early so we don't emit pointless addressing code.
88665285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                 * This space is a mix of:
88675285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                 *  PLD/PLDW/PLI,  which we implement as NOPs (note that unlike
88685285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                 *     the ARM encodings, PLDW space doesn't UNDEF for non-v7MP
88695285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                 *     cores)
88705285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                 *  unallocated hints, which must be treated as NOPs
88715285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                 *  UNPREDICTABLE space, which we NOP or UNDEF depending on
88725285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                 *     which is easiest for the decoding logic
88735285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                 *  Some space which must UNDEF
88745285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                 */
88755285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                int op1 = (insn >> 23) & 3;
88765285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                int op2 = (insn >> 6) & 0x3f;
88775285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                if (op & 2) {
88785285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    goto illegal_op;
88795285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                }
88805285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                if (rn == 15) {
88815285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    /* UNPREDICTABLE or unallocated hint */
88825285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    return 0;
88835285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                }
88845285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                if (op1 & 1) {
88855285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    return 0; /* PLD* or unallocated hint */
88865285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                }
88875285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                if ((op2 == 0) || ((op2 & 0x3c) == 0x30)) {
88885285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    return 0; /* PLD* or unallocated hint */
88895285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                }
88905285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                /* UNDEF space, or an UNPREDICTABLE */
88915285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                return 1;
88925285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            }
88935285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        }
88948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        user = IS_USER(s);
88958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (rn == 15) {
88965285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            addr = tcg_temp_new_i32();
88978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* PC relative.  */
88988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* s->pc has already been incremented by 4.  */
88998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            imm = s->pc & 0xfffffffc;
89008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (insn & (1 << 23))
89018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                imm += insn & 0xfff;
89028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            else
89038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                imm -= insn & 0xfff;
89048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tcg_gen_movi_i32(addr, imm);
89058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        } else {
89068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            addr = load_reg(s, rn);
89078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (insn & (1 << 23)) {
89088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* Positive offset.  */
89098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                imm = insn & 0xfff;
89108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                tcg_gen_addi_i32(addr, addr, imm);
89118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            } else {
89128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                imm = insn & 0xff;
89135285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                switch ((insn >> 8) & 0xf) {
89145285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                case 0x0: /* Shifted Register.  */
89158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    shift = (insn >> 4) & 0xf;
89165285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    if (shift > 3) {
89175285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tcg_temp_free_i32(addr);
89188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        goto illegal_op;
89195285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    }
89208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    tmp = load_reg(s, rm);
89218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if (shift)
89228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        tcg_gen_shli_i32(tmp, tmp, shift);
89238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    tcg_gen_add_i32(addr, addr, tmp);
89245285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tcg_temp_free_i32(tmp);
89258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    break;
89265285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                case 0xc: /* Negative offset.  */
89278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    tcg_gen_addi_i32(addr, addr, -imm);
89288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    break;
89295285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                case 0xe: /* User privilege.  */
89308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    tcg_gen_addi_i32(addr, addr, imm);
89318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    user = 1;
89328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    break;
89335285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                case 0x9: /* Post-decrement.  */
89348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    imm = -imm;
89358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    /* Fall through.  */
89365285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                case 0xb: /* Post-increment.  */
89378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    postinc = 1;
89388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    writeback = 1;
89398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    break;
89405285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                case 0xd: /* Pre-decrement.  */
89418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    imm = -imm;
89428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    /* Fall through.  */
89435285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                case 0xf: /* Pre-increment.  */
89448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    tcg_gen_addi_i32(addr, addr, imm);
89458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    writeback = 1;
89468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    break;
89478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                default:
89485285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tcg_temp_free_i32(addr);
89498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    goto illegal_op;
89508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
89518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
89528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
89538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (insn & (1 << 20)) {
89548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* Load.  */
89555285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            switch (op) {
89565285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            case 0: tmp = gen_ld8u(addr, user); break;
89575285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            case 4: tmp = gen_ld8s(addr, user); break;
89585285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            case 1: tmp = gen_ld16u(addr, user); break;
89595285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            case 5: tmp = gen_ld16s(addr, user); break;
89605285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            case 2: tmp = gen_ld32(addr, user); break;
89615285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            default:
89625285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_temp_free_i32(addr);
89635285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                goto illegal_op;
89645285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            }
89655285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            if (rs == 15) {
89665285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                gen_bx(s, tmp);
89678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            } else {
89685285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                store_reg(s, rs, tmp);
89698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
89708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        } else {
89718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* Store.  */
89728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tmp = load_reg(s, rs);
89738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            switch (op) {
89748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            case 0: gen_st8(tmp, addr, user); break;
89758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            case 1: gen_st16(tmp, addr, user); break;
89768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            case 2: gen_st32(tmp, addr, user); break;
89775285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            default:
89785285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_temp_free_i32(addr);
89795285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                goto illegal_op;
89808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
89818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
89828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (postinc)
89838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tcg_gen_addi_i32(addr, addr, imm);
89848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (writeback) {
89858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            store_reg(s, rn, addr);
89868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        } else {
89875285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tcg_temp_free_i32(addr);
89888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
89898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
89908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
89918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    default:
89928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        goto illegal_op;
89938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
89948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
89958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectillegal_op:
89968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 1;
89978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
89988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8999e2678e116c8cdb0f36b247a5bd9cfacc849362fcDavid 'Digit' Turnerstatic void disas_thumb_insn(CPUARMState *env, DisasContext *s)
90008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
90018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    uint32_t val, insn, op, rm, rn, rd, shift, cond;
90028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int32_t offset;
90038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int i;
90048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    TCGv tmp;
90058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    TCGv tmp2;
90068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    TCGv addr;
90078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9008a1204591a52bf668ee72c86f98f53189621572a2Vladimir Chtchetkine    if (s->condexec_mask) {
9009a1204591a52bf668ee72c86f98f53189621572a2Vladimir Chtchetkine        cond = s->condexec_cond;
90105285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        if (cond != 0x0e) {     /* Skip conditional when condition is AL. */
90115285864985be9077e58e42235af6582dee72e841David 'Digit' Turner          s->condlabel = gen_new_label();
90125285864985be9077e58e42235af6582dee72e841David 'Digit' Turner          gen_test_cc(cond ^ 1, s->condlabel);
90135285864985be9077e58e42235af6582dee72e841David 'Digit' Turner          s->condjmp = 1;
90145285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        }
90158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
90168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9017eca7bc24e45fb6809582795ff88f13384b5ce7dfDavid 'Digit' Turner    insn = cpu_lduw_code(env, s->pc);
90185389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine
90198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    s->pc += 2;
90208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
90218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    switch (insn >> 12) {
90228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0: case 1:
90235285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
90248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        rd = insn & 7;
90258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        op = (insn >> 11) & 3;
90268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (op == 3) {
90278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* add/subtract */
90288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            rn = (insn >> 3) & 7;
90295285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tmp = load_reg(s, rn);
90308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (insn & (1 << 10)) {
90318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* immediate */
90325285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tmp2 = tcg_temp_new_i32();
90335285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_gen_movi_i32(tmp2, (insn >> 6) & 7);
90348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            } else {
90358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* reg */
90368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                rm = (insn >> 6) & 7;
90375285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tmp2 = load_reg(s, rm);
90388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
90398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (insn & (1 << 9)) {
90408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (s->condexec_mask)
90415285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tcg_gen_sub_i32(tmp, tmp, tmp2);
90428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                else
90430b4c9e8457959b01cd26f60ef214e9b5b7a297d4David 'Digit' Turner                    gen_helper_sub_cc(tmp, cpu_env, tmp, tmp2);
90448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            } else {
90458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (s->condexec_mask)
90465285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tcg_gen_add_i32(tmp, tmp, tmp2);
90478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                else
90480b4c9e8457959b01cd26f60ef214e9b5b7a297d4David 'Digit' Turner                    gen_helper_add_cc(tmp, cpu_env, tmp, tmp2);
90498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
90505285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tcg_temp_free_i32(tmp2);
90515285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            store_reg(s, rd, tmp);
90528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        } else {
90538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* shift immediate */
90548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            rm = (insn >> 3) & 7;
90558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            shift = (insn >> 6) & 0x1f;
90568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tmp = load_reg(s, rm);
90578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            gen_arm_shift_im(tmp, op, shift, s->condexec_mask == 0);
90588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (!s->condexec_mask)
90598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                gen_logic_CC(tmp);
90608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            store_reg(s, rd, tmp);
90618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
90628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
90638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 2: case 3:
90648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* arithmetic large immediate */
90658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        op = (insn >> 11) & 3;
90668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        rd = (insn >> 8) & 0x7;
90675285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        if (op == 0) { /* mov */
90685285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tmp = tcg_temp_new_i32();
90695285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tcg_gen_movi_i32(tmp, insn & 0xff);
90708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (!s->condexec_mask)
90715285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                gen_logic_CC(tmp);
90725285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            store_reg(s, rd, tmp);
90735285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        } else {
90745285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tmp = load_reg(s, rd);
90755285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tmp2 = tcg_temp_new_i32();
90765285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tcg_gen_movi_i32(tmp2, insn & 0xff);
90775285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            switch (op) {
90785285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            case 1: /* cmp */
90790b4c9e8457959b01cd26f60ef214e9b5b7a297d4David 'Digit' Turner                gen_helper_sub_cc(tmp, cpu_env, tmp, tmp2);
90805285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_temp_free_i32(tmp);
90815285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_temp_free_i32(tmp2);
90825285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                break;
90835285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            case 2: /* add */
90845285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                if (s->condexec_mask)
90855285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tcg_gen_add_i32(tmp, tmp, tmp2);
90865285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                else
90870b4c9e8457959b01cd26f60ef214e9b5b7a297d4David 'Digit' Turner                    gen_helper_add_cc(tmp, cpu_env, tmp, tmp2);
90885285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_temp_free_i32(tmp2);
90895285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                store_reg(s, rd, tmp);
90905285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                break;
90915285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            case 3: /* sub */
90925285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                if (s->condexec_mask)
90935285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tcg_gen_sub_i32(tmp, tmp, tmp2);
90945285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                else
90950b4c9e8457959b01cd26f60ef214e9b5b7a297d4David 'Digit' Turner                    gen_helper_sub_cc(tmp, cpu_env, tmp, tmp2);
90965285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_temp_free_i32(tmp2);
90975285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                store_reg(s, rd, tmp);
90985285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                break;
90995285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            }
91008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
91018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
91028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 4:
91038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (insn & (1 << 11)) {
91048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            rd = (insn >> 8) & 7;
91058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* load pc-relative.  Bit 1 of PC is ignored.  */
91068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            val = s->pc + 2 + ((insn & 0xff) * 4);
91078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            val &= ~(uint32_t)2;
91085285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            addr = tcg_temp_new_i32();
91098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tcg_gen_movi_i32(addr, val);
91108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tmp = gen_ld32(addr, IS_USER(s));
91115285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tcg_temp_free_i32(addr);
91128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            store_reg(s, rd, tmp);
91138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
91148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
91158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (insn & (1 << 10)) {
91168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* data processing extended or blx */
91178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            rd = (insn & 7) | ((insn >> 4) & 8);
91188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            rm = (insn >> 3) & 0xf;
91198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            op = (insn >> 8) & 3;
91208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            switch (op) {
91218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            case 0: /* add */
91225285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tmp = load_reg(s, rd);
91235285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tmp2 = load_reg(s, rm);
91245285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_gen_add_i32(tmp, tmp, tmp2);
91255285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_temp_free_i32(tmp2);
91265285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                store_reg(s, rd, tmp);
91278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                break;
91288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            case 1: /* cmp */
91295285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tmp = load_reg(s, rd);
91305285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tmp2 = load_reg(s, rm);
91310b4c9e8457959b01cd26f60ef214e9b5b7a297d4David 'Digit' Turner                gen_helper_sub_cc(tmp, cpu_env, tmp, tmp2);
91325285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_temp_free_i32(tmp2);
91335285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_temp_free_i32(tmp);
91348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                break;
91358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            case 2: /* mov/cpy */
91365285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tmp = load_reg(s, rm);
91375285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                store_reg(s, rd, tmp);
91388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                break;
91398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            case 3:/* branch [and link] exchange thumb register */
91408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                tmp = load_reg(s, rm);
91418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (insn & (1 << 7)) {
91425285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    ARCH(5);
91438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    val = (uint32_t)s->pc | 1;
91445285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tmp2 = tcg_temp_new_i32();
91458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    tcg_gen_movi_i32(tmp2, val);
91468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    store_reg(s, 14, tmp2);
91478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
91485285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                /* already thumb, no need to check */
91498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                gen_bx(s, tmp);
91508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                break;
91518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
91528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
91538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
91548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
91558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* data processing register */
91568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        rd = insn & 7;
91578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        rm = (insn >> 3) & 7;
91588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        op = (insn >> 6) & 0xf;
91598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (op == 2 || op == 3 || op == 4 || op == 7) {
91608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* the shift/rotate ops want the operands backwards */
91618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            val = rm;
91628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            rm = rd;
91638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            rd = val;
91648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            val = 1;
91658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        } else {
91668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            val = 0;
91678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
91688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
91695285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        if (op == 9) { /* neg */
91705285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tmp = tcg_temp_new_i32();
91715285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tcg_gen_movi_i32(tmp, 0);
91725285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        } else if (op != 0xf) { /* mvn doesn't read its first operand */
91735285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tmp = load_reg(s, rd);
91745285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        } else {
91755285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            TCGV_UNUSED(tmp);
91765285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        }
91778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
91785285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tmp2 = load_reg(s, rm);
91798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        switch (op) {
91808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0x0: /* and */
91815285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tcg_gen_and_i32(tmp, tmp, tmp2);
91828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (!s->condexec_mask)
91835285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                gen_logic_CC(tmp);
91848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
91858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0x1: /* eor */
91865285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tcg_gen_xor_i32(tmp, tmp, tmp2);
91878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (!s->condexec_mask)
91885285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                gen_logic_CC(tmp);
91898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
91908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0x2: /* lsl */
91918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (s->condexec_mask) {
91925285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                gen_helper_shl(tmp2, tmp2, tmp);
91938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            } else {
91940b4c9e8457959b01cd26f60ef214e9b5b7a297d4David 'Digit' Turner                gen_helper_shl_cc(tmp2, cpu_env, tmp2, tmp);
91955285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                gen_logic_CC(tmp2);
91968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
91978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
91988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0x3: /* lsr */
91998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (s->condexec_mask) {
92005285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                gen_helper_shr(tmp2, tmp2, tmp);
92018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            } else {
92020b4c9e8457959b01cd26f60ef214e9b5b7a297d4David 'Digit' Turner                gen_helper_shr_cc(tmp2, cpu_env, tmp2, tmp);
92035285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                gen_logic_CC(tmp2);
92048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
92058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
92068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0x4: /* asr */
92078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (s->condexec_mask) {
92085285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                gen_helper_sar(tmp2, tmp2, tmp);
92098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            } else {
92100b4c9e8457959b01cd26f60ef214e9b5b7a297d4David 'Digit' Turner                gen_helper_sar_cc(tmp2, cpu_env, tmp2, tmp);
92115285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                gen_logic_CC(tmp2);
92128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
92138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
92148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0x5: /* adc */
92158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (s->condexec_mask)
92165285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                gen_adc(tmp, tmp2);
92178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            else
92180b4c9e8457959b01cd26f60ef214e9b5b7a297d4David 'Digit' Turner                gen_helper_adc_cc(tmp, cpu_env, tmp, tmp2);
92198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
92208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0x6: /* sbc */
92218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (s->condexec_mask)
92225285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                gen_sub_carry(tmp, tmp, tmp2);
92238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            else
92240b4c9e8457959b01cd26f60ef214e9b5b7a297d4David 'Digit' Turner                gen_helper_sbc_cc(tmp, cpu_env, tmp, tmp2);
92258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
92268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0x7: /* ror */
92278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (s->condexec_mask) {
92285285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_gen_andi_i32(tmp, tmp, 0x1f);
92295285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_gen_rotr_i32(tmp2, tmp2, tmp);
92308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            } else {
92310b4c9e8457959b01cd26f60ef214e9b5b7a297d4David 'Digit' Turner                gen_helper_ror_cc(tmp2, cpu_env, tmp2, tmp);
92325285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                gen_logic_CC(tmp2);
92338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
92348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
92358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0x8: /* tst */
92365285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tcg_gen_and_i32(tmp, tmp, tmp2);
92375285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            gen_logic_CC(tmp);
92388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            rd = 16;
92398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
92408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0x9: /* neg */
92418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (s->condexec_mask)
92425285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_gen_neg_i32(tmp, tmp2);
92438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            else
92440b4c9e8457959b01cd26f60ef214e9b5b7a297d4David 'Digit' Turner                gen_helper_sub_cc(tmp, cpu_env, tmp, tmp2);
92458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
92468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0xa: /* cmp */
92470b4c9e8457959b01cd26f60ef214e9b5b7a297d4David 'Digit' Turner            gen_helper_sub_cc(tmp, cpu_env, tmp, tmp2);
92488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            rd = 16;
92498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
92508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0xb: /* cmn */
92510b4c9e8457959b01cd26f60ef214e9b5b7a297d4David 'Digit' Turner            gen_helper_add_cc(tmp, cpu_env, tmp, tmp2);
92528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            rd = 16;
92538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
92548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0xc: /* orr */
92555285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tcg_gen_or_i32(tmp, tmp, tmp2);
92568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (!s->condexec_mask)
92575285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                gen_logic_CC(tmp);
92588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
92598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0xd: /* mul */
92605285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tcg_gen_mul_i32(tmp, tmp, tmp2);
92618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (!s->condexec_mask)
92625285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                gen_logic_CC(tmp);
92638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
92648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0xe: /* bic */
92655285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tcg_gen_andc_i32(tmp, tmp, tmp2);
92668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (!s->condexec_mask)
92675285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                gen_logic_CC(tmp);
92688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
92698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0xf: /* mvn */
92705285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tcg_gen_not_i32(tmp2, tmp2);
92718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (!s->condexec_mask)
92725285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                gen_logic_CC(tmp2);
92738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            val = 1;
92748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            rm = rd;
92758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
92768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
92778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (rd != 16) {
92785285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            if (val) {
92795285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                store_reg(s, rm, tmp2);
92805285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                if (op != 0xf)
92815285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tcg_temp_free_i32(tmp);
92825285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            } else {
92835285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                store_reg(s, rd, tmp);
92845285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_temp_free_i32(tmp2);
92855285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            }
92865285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        } else {
92875285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tcg_temp_free_i32(tmp);
92885285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tcg_temp_free_i32(tmp2);
92898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
92908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
92918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
92928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 5:
92938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* load/store register offset.  */
92948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        rd = insn & 7;
92958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        rn = (insn >> 3) & 7;
92968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        rm = (insn >> 6) & 7;
92978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        op = (insn >> 9) & 7;
92988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        addr = load_reg(s, rn);
92998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tmp = load_reg(s, rm);
93008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tcg_gen_add_i32(addr, addr, tmp);
93015285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tcg_temp_free_i32(tmp);
93028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
93038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (op < 3) /* store */
93048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tmp = load_reg(s, rd);
93058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
93068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        switch (op) {
93078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0: /* str */
93088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            gen_st32(tmp, addr, IS_USER(s));
93098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
93108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 1: /* strh */
93118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            gen_st16(tmp, addr, IS_USER(s));
93128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
93138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 2: /* strb */
93148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            gen_st8(tmp, addr, IS_USER(s));
93158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
93168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 3: /* ldrsb */
93178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tmp = gen_ld8s(addr, IS_USER(s));
93188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
93198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 4: /* ldr */
93208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tmp = gen_ld32(addr, IS_USER(s));
93218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
93228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 5: /* ldrh */
93238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tmp = gen_ld16u(addr, IS_USER(s));
93248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
93258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 6: /* ldrb */
93268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tmp = gen_ld8u(addr, IS_USER(s));
93278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
93288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 7: /* ldrsh */
93298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tmp = gen_ld16s(addr, IS_USER(s));
93308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
93318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
93328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (op >= 3) /* load */
93338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            store_reg(s, rd, tmp);
93345285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tcg_temp_free_i32(addr);
93358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
93368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
93378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 6:
93388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* load/store word immediate offset */
93398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        rd = insn & 7;
93408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        rn = (insn >> 3) & 7;
93418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        addr = load_reg(s, rn);
93428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        val = (insn >> 4) & 0x7c;
93438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tcg_gen_addi_i32(addr, addr, val);
93448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
93458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (insn & (1 << 11)) {
93468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* load */
93478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tmp = gen_ld32(addr, IS_USER(s));
93488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            store_reg(s, rd, tmp);
93498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        } else {
93508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* store */
93518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tmp = load_reg(s, rd);
93528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            gen_st32(tmp, addr, IS_USER(s));
93538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
93545285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tcg_temp_free_i32(addr);
93558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
93568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
93578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 7:
93588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* load/store byte immediate offset */
93598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        rd = insn & 7;
93608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        rn = (insn >> 3) & 7;
93618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        addr = load_reg(s, rn);
93628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        val = (insn >> 6) & 0x1f;
93638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tcg_gen_addi_i32(addr, addr, val);
93648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
93658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (insn & (1 << 11)) {
93668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* load */
93678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tmp = gen_ld8u(addr, IS_USER(s));
93688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            store_reg(s, rd, tmp);
93698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        } else {
93708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* store */
93718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tmp = load_reg(s, rd);
93728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            gen_st8(tmp, addr, IS_USER(s));
93738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
93745285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tcg_temp_free_i32(addr);
93758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
93768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
93778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 8:
93788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* load/store halfword immediate offset */
93798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        rd = insn & 7;
93808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        rn = (insn >> 3) & 7;
93818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        addr = load_reg(s, rn);
93828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        val = (insn >> 5) & 0x3e;
93838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tcg_gen_addi_i32(addr, addr, val);
93848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
93858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (insn & (1 << 11)) {
93868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* load */
93878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tmp = gen_ld16u(addr, IS_USER(s));
93888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            store_reg(s, rd, tmp);
93898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        } else {
93908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* store */
93918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tmp = load_reg(s, rd);
93928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            gen_st16(tmp, addr, IS_USER(s));
93938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
93945285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tcg_temp_free_i32(addr);
93958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
93968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
93978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 9:
93988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* load/store from stack */
93998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        rd = (insn >> 8) & 7;
94008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        addr = load_reg(s, 13);
94018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        val = (insn & 0xff) * 4;
94028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tcg_gen_addi_i32(addr, addr, val);
94038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
94048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (insn & (1 << 11)) {
94058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* load */
94068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tmp = gen_ld32(addr, IS_USER(s));
94078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            store_reg(s, rd, tmp);
94088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        } else {
94098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* store */
94108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tmp = load_reg(s, rd);
94118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            gen_st32(tmp, addr, IS_USER(s));
94128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
94135285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tcg_temp_free_i32(addr);
94148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
94158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
94168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 10:
94178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* add to high reg */
94188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        rd = (insn >> 8) & 7;
94198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (insn & (1 << 11)) {
94208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* SP */
94218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tmp = load_reg(s, 13);
94228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        } else {
94238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* PC. bit 1 is ignored.  */
94245285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tmp = tcg_temp_new_i32();
94258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tcg_gen_movi_i32(tmp, (s->pc + 2) & ~(uint32_t)2);
94268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
94278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        val = (insn & 0xff) * 4;
94288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tcg_gen_addi_i32(tmp, tmp, val);
94298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        store_reg(s, rd, tmp);
94308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
94318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
94328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 11:
94338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* misc */
94348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        op = (insn >> 8) & 0xf;
94358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        switch (op) {
94368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0:
94378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* adjust stack pointer */
94388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tmp = load_reg(s, 13);
94398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            val = (insn & 0x7f) * 4;
94408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (insn & (1 << 7))
94418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                val = -(int32_t)val;
94428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tcg_gen_addi_i32(tmp, tmp, val);
94438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            store_reg(s, 13, tmp);
94448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
94458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
94468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 2: /* sign/zero extend.  */
94478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            ARCH(6);
94488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            rd = insn & 7;
94498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            rm = (insn >> 3) & 7;
94508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tmp = load_reg(s, rm);
94518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            switch ((insn >> 6) & 3) {
94528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            case 0: gen_sxth(tmp); break;
94538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            case 1: gen_sxtb(tmp); break;
94548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            case 2: gen_uxth(tmp); break;
94558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            case 3: gen_uxtb(tmp); break;
94568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
94578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            store_reg(s, rd, tmp);
94588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
94598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 4: case 5: case 0xc: case 0xd:
94608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* push/pop */
94618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            addr = load_reg(s, 13);
94628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (insn & (1 << 8))
94638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                offset = 4;
94648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            else
94658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                offset = 0;
94668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            for (i = 0; i < 8; i++) {
94678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (insn & (1 << i))
94688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    offset += 4;
94698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
94708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if ((insn & (1 << 11)) == 0) {
94718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                tcg_gen_addi_i32(addr, addr, -offset);
94728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
94735285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tmp2 = tcg_const_i32(4);
94748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            for (i = 0; i < 8; i++) {
94758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (insn & (1 << i)) {
94768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if (insn & (1 << 11)) {
94778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        /* pop */
94788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        tmp = gen_ld32(addr, IS_USER(s));
94798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        store_reg(s, i, tmp);
94808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    } else {
94818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        /* push */
94828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        tmp = load_reg(s, i);
94838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        gen_st32(tmp, addr, IS_USER(s));
94848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
94858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    /* advance to the next address.  */
94865285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tcg_gen_add_i32(addr, addr, tmp2);
94878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
94888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
94898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            TCGV_UNUSED(tmp);
94908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (insn & (1 << 8)) {
94918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (insn & (1 << 11)) {
94928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    /* pop pc */
94938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    tmp = gen_ld32(addr, IS_USER(s));
94948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    /* don't set the pc until the rest of the instruction
94958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                       has completed */
94968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                } else {
94978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    /* push lr */
94988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    tmp = load_reg(s, 14);
94998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    gen_st32(tmp, addr, IS_USER(s));
95008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
95015285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_gen_add_i32(addr, addr, tmp2);
95028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
95035285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tcg_temp_free_i32(tmp2);
95048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if ((insn & (1 << 11)) == 0) {
95058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                tcg_gen_addi_i32(addr, addr, -offset);
95068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
95078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* write back the new stack pointer */
95088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            store_reg(s, 13, addr);
95098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* set the new PC value */
95105285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            if ((insn & 0x0900) == 0x0900) {
95115285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                store_reg_from_load(env, s, 15, tmp);
95125285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            }
95138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
95148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
95158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 1: case 3: case 9: case 11: /* czb */
95168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            rm = insn & 7;
95178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tmp = load_reg(s, rm);
95188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            s->condlabel = gen_new_label();
95198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            s->condjmp = 1;
95208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (insn & (1 << 11))
95218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, s->condlabel);
95228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            else
95238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, s->condlabel);
95245285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tcg_temp_free_i32(tmp);
95258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            offset = ((insn & 0xf8) >> 2) | (insn & 0x200) >> 3;
95268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            val = (uint32_t)s->pc + 2;
95278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            val += offset;
95288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            gen_jmp(s, val);
95298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
95308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
95318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 15: /* IT, nop-hint.  */
95328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if ((insn & 0xf) == 0) {
95338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                gen_nop_hint(s, (insn >> 4) & 0xf);
95348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                break;
95358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
95368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* If Then.  */
9537a1204591a52bf668ee72c86f98f53189621572a2Vladimir Chtchetkine            s->condexec_cond = (insn >> 4) & 0xe;
9538a1204591a52bf668ee72c86f98f53189621572a2Vladimir Chtchetkine            s->condexec_mask = insn & 0x1f;
95398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* No actual code generated for this insn, just setup state.  */
95408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
95418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
95428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0xe: /* bkpt */
95435285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            ARCH(5);
95445285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            gen_exception_insn(s, 2, EXCP_BKPT);
95458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
95468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
95478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0xa: /* rev */
95488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            ARCH(6);
95498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            rn = (insn >> 3) & 0x7;
95508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            rd = insn & 0x7;
95518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tmp = load_reg(s, rn);
95528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            switch ((insn >> 6) & 3) {
95535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            case 0: tcg_gen_bswap32_i32(tmp, tmp); break;
95548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            case 1: gen_rev16(tmp); break;
95558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            case 3: gen_revsh(tmp); break;
95568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            default: goto illegal_op;
95578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
95588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            store_reg(s, rd, tmp);
95598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
95608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
95618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 6: /* cps */
95628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            ARCH(6);
95638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (IS_USER(s))
95648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                break;
95658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (IS_M(env)) {
95668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                tmp = tcg_const_i32((insn & (1 << 4)) != 0);
95678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* PRIMASK */
95688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (insn & 1) {
95698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    addr = tcg_const_i32(16);
95708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    gen_helper_v7m_msr(cpu_env, addr, tmp);
95715285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tcg_temp_free_i32(addr);
95728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
95738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* FAULTMASK */
95748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (insn & 2) {
95758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    addr = tcg_const_i32(17);
95768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    gen_helper_v7m_msr(cpu_env, addr, tmp);
95775285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tcg_temp_free_i32(addr);
95788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
95795285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_temp_free_i32(tmp);
95808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                gen_lookup_tb(s);
95818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            } else {
95828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (insn & (1 << 4))
95838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    shift = CPSR_A | CPSR_I | CPSR_F;
95848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                else
95858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    shift = 0;
95865285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                gen_set_psr_im(s, ((insn & 7) << 6), 0, shift);
95878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
95888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
95898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
95908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        default:
95918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            goto undef;
95928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
95938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
95948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
95958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 12:
95965285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    {
95978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* load/store multiple */
95985285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        TCGv loaded_var;
95995285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        TCGV_UNUSED(loaded_var);
96008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        rn = (insn >> 8) & 0x7;
96018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        addr = load_reg(s, rn);
96028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        for (i = 0; i < 8; i++) {
96038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (insn & (1 << i)) {
96048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (insn & (1 << 11)) {
96058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    /* load */
96068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    tmp = gen_ld32(addr, IS_USER(s));
96075285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    if (i == rn) {
96085285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        loaded_var = tmp;
96095285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    } else {
96105285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        store_reg(s, i, tmp);
96115285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    }
96128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                } else {
96138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    /* store */
96148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    tmp = load_reg(s, i);
96158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    gen_st32(tmp, addr, IS_USER(s));
96168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
96178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* advance to the next address */
96188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                tcg_gen_addi_i32(addr, addr, 4);
96198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
96208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
96218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if ((insn & (1 << rn)) == 0) {
96225285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            /* base reg not in list: base register writeback */
96238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            store_reg(s, rn, addr);
96248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        } else {
96255285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            /* base reg in list: if load, complete it now */
96265285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            if (insn & (1 << 11)) {
96275285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                store_reg(s, rn, loaded_var);
96285285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            }
96295285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tcg_temp_free_i32(addr);
96308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
96318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
96325285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    }
96338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 13:
96348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* conditional branch or swi */
96358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        cond = (insn >> 8) & 0xf;
96368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (cond == 0xe)
96378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            goto undef;
96388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
96398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (cond == 0xf) {
96408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* swi */
96418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            gen_set_pc_im(s->pc);
96428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            s->is_jmp = DISAS_SWI;
96438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
96448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
96458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* generate a conditional jump to next instruction */
96468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        s->condlabel = gen_new_label();
96478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_test_cc(cond ^ 1, s->condlabel);
96488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        s->condjmp = 1;
96498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
96508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* jump to the offset */
96518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        val = (uint32_t)s->pc + 2;
96528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        offset = ((int32_t)insn << 24) >> 24;
96538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        val += offset << 1;
96548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_jmp(s, val);
96558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
96568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
96578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 14:
96588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (insn & (1 << 11)) {
96598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (disas_thumb2_insn(env, s, insn))
96608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project              goto undef32;
96618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
96628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
96638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* unconditional branch */
96648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        val = (uint32_t)s->pc;
96658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        offset = ((int32_t)insn << 21) >> 21;
96668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        val += (offset << 1) + 2;
96678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_jmp(s, val);
96688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
96698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
96708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 15:
96718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (disas_thumb2_insn(env, s, insn))
96728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            goto undef32;
96738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
96748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
96758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return;
96768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectundef32:
96775285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    gen_exception_insn(s, 4, EXCP_UDEF);
96788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return;
96798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectillegal_op:
96808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectundef:
96815285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    gen_exception_insn(s, 2, EXCP_UDEF);
96828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
96838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
96848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* generate intermediate code in gen_opc_buf and gen_opparam_buf for
96858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   basic block 'tb'. If search_pc is TRUE, also generate PC
96868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   information for each intermediate instruction. */
9687e2678e116c8cdb0f36b247a5bd9cfacc849362fcDavid 'Digit' Turnerstatic inline void gen_intermediate_code_internal(CPUARMState *env,
96888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                                  TranslationBlock *tb,
96898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                                  int search_pc)
96908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
96918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    DisasContext dc1, *dc = &dc1;
96925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    CPUBreakpoint *bp;
96938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    uint16_t *gen_opc_end;
96948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int j, lj;
96958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    target_ulong pc_start;
96968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    uint32_t next_page_start;
96978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int num_insns;
96988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int max_insns;
96998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
97008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* generate intermediate code */
97018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    pc_start = tb->pc;
97028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
97038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    dc->tb = tb;
97048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9705975bba804aed54452f774cdbf79a7b4732fc7696David 'Digit' Turner    gen_opc_end = tcg_ctx.gen_opc_buf + OPC_MAX_SIZE;
97068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
97078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    dc->is_jmp = DISAS_NEXT;
97088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    dc->pc = pc_start;
9709fed223d2bab55eda155e3463b9cb6966e69dd73cDavid 'Digit' Turner    dc->singlestep_enabled = ENV_GET_CPU(env)->singlestep_enabled;
97108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    dc->condjmp = 0;
97115285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    dc->thumb = ARM_TBFLAG_THUMB(tb->flags);
97125285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    dc->condexec_mask = (ARM_TBFLAG_CONDEXEC(tb->flags) & 0xf) << 1;
97135285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    dc->condexec_cond = ARM_TBFLAG_CONDEXEC(tb->flags) >> 4;
97148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if !defined(CONFIG_USER_ONLY)
97155285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    dc->user = (ARM_TBFLAG_PRIV(tb->flags) == 0);
97168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
97175285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    dc->vfp_enabled = ARM_TBFLAG_VFPEN(tb->flags);
97185285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    dc->vec_len = ARM_TBFLAG_VECLEN(tb->flags);
97195285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    dc->vec_stride = ARM_TBFLAG_VECSTRIDE(tb->flags);
97205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    cpu_F0s = tcg_temp_new_i32();
97215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    cpu_F1s = tcg_temp_new_i32();
97225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    cpu_F0d = tcg_temp_new_i64();
97235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    cpu_F1d = tcg_temp_new_i64();
97248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    cpu_V0 = cpu_F0d;
97258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    cpu_V1 = cpu_F1d;
97268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* FIXME: cpu_M0 can probably be the same as cpu_V0.  */
97275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    cpu_M0 = tcg_temp_new_i64();
97288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
97298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    lj = -1;
97308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    num_insns = 0;
97318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    max_insns = tb->cflags & CF_COUNT_MASK;
97328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (max_insns == 0)
97338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        max_insns = CF_COUNT_MASK;
97348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
97358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    gen_icount_start();
97368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
97375285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_clear_temp_count();
97385285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
97395285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    /* A note on handling of the condexec (IT) bits:
97405285864985be9077e58e42235af6582dee72e841David 'Digit' Turner     *
97415285864985be9077e58e42235af6582dee72e841David 'Digit' Turner     * We want to avoid the overhead of having to write the updated condexec
9742e2678e116c8cdb0f36b247a5bd9cfacc849362fcDavid 'Digit' Turner     * bits back to the CPUARMState for every instruction in an IT block. So:
97435285864985be9077e58e42235af6582dee72e841David 'Digit' Turner     * (1) if the condexec bits are not already zero then we write
9744e2678e116c8cdb0f36b247a5bd9cfacc849362fcDavid 'Digit' Turner     * zero back into the CPUARMState now. This avoids complications trying
97455285864985be9077e58e42235af6582dee72e841David 'Digit' Turner     * to do it at the end of the block. (For example if we don't do this
97465285864985be9077e58e42235af6582dee72e841David 'Digit' Turner     * it's hard to identify whether we can safely skip writing condexec
97475285864985be9077e58e42235af6582dee72e841David 'Digit' Turner     * at the end of the TB, which we definitely want to do for the case
97485285864985be9077e58e42235af6582dee72e841David 'Digit' Turner     * where a TB doesn't do anything with the IT state at all.)
97495285864985be9077e58e42235af6582dee72e841David 'Digit' Turner     * (2) if we are going to leave the TB then we call gen_set_condexec()
9750e2678e116c8cdb0f36b247a5bd9cfacc849362fcDavid 'Digit' Turner     * which will write the correct value into CPUARMState if zero is wrong.
97515285864985be9077e58e42235af6582dee72e841David 'Digit' Turner     * This is done both for leaving the TB at the end, and for leaving
97525285864985be9077e58e42235af6582dee72e841David 'Digit' Turner     * it because of an exception we know will happen, which is done in
97535285864985be9077e58e42235af6582dee72e841David 'Digit' Turner     * gen_exception_insn(). The latter is necessary because we need to
97545285864985be9077e58e42235af6582dee72e841David 'Digit' Turner     * leave the TB with the PC/IT state just prior to execution of the
97555285864985be9077e58e42235af6582dee72e841David 'Digit' Turner     * instruction which caused the exception.
97565285864985be9077e58e42235af6582dee72e841David 'Digit' Turner     * (3) if we leave the TB unexpectedly (eg a data abort on a load)
9757e2678e116c8cdb0f36b247a5bd9cfacc849362fcDavid 'Digit' Turner     * then the CPUARMState will be wrong and we need to reset it.
97585285864985be9077e58e42235af6582dee72e841David 'Digit' Turner     * This is handled in the same way as restoration of the
97595285864985be9077e58e42235af6582dee72e841David 'Digit' Turner     * PC in these situations: we will be called again with search_pc=1
97605285864985be9077e58e42235af6582dee72e841David 'Digit' Turner     * and generate a mapping of the condexec bits for each PC in
97615285864985be9077e58e42235af6582dee72e841David 'Digit' Turner     * gen_opc_condexec_bits[]. restore_state_to_opc() then uses
97625285864985be9077e58e42235af6582dee72e841David 'Digit' Turner     * this to restore the condexec bits.
97635285864985be9077e58e42235af6582dee72e841David 'Digit' Turner     *
97645285864985be9077e58e42235af6582dee72e841David 'Digit' Turner     * Note that there are no instructions which can read the condexec
97655285864985be9077e58e42235af6582dee72e841David 'Digit' Turner     * bits, and none which can write non-static values to them, so
9766e2678e116c8cdb0f36b247a5bd9cfacc849362fcDavid 'Digit' Turner     * we don't need to care about whether CPUARMState is correct in the
97675285864985be9077e58e42235af6582dee72e841David 'Digit' Turner     * middle of a TB.
97685285864985be9077e58e42235af6582dee72e841David 'Digit' Turner     */
97695285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
97705285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    /* Reset the conditional execution bits immediately. This avoids
97715285864985be9077e58e42235af6582dee72e841David 'Digit' Turner       complications trying to do it at the end of the block.  */
97725285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    if (dc->condexec_mask || dc->condexec_cond)
97735285864985be9077e58e42235af6582dee72e841David 'Digit' Turner      {
97745285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        TCGv tmp = tcg_temp_new_i32();
97755285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tcg_gen_movi_i32(tmp, 0);
97765285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        store_cpu_field(tmp, condexec_bits);
97775285864985be9077e58e42235af6582dee72e841David 'Digit' Turner      }
97788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    do {
97798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef CONFIG_USER_ONLY
97808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* Intercept jump to the magic kernel page.  */
97818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (dc->pc >= 0xffff0000) {
97828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* We always get here via a jump, so know we are not in a
97838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project               conditional execution block.  */
97848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            gen_exception(EXCP_KERNEL_TRAP);
97858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            dc->is_jmp = DISAS_UPDATE;
97868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
97878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
97888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else
97898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (dc->pc >= 0xfffffff0 && IS_M(env)) {
97908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* We always get here via a jump, so know we are not in a
97918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project               conditional execution block.  */
97928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            gen_exception(EXCP_EXCEPTION_EXIT);
97938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            dc->is_jmp = DISAS_UPDATE;
97948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
97958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
97968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
97978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9798a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner        if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
9799a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner            QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
98005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                if (bp->pc == dc->pc) {
98015285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    gen_exception_insn(dc, 0, EXCP_DEBUG);
98028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    /* Advance PC so that clearing the breakpoint will
98038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                       invalidate this TB.  */
98048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    dc->pc += 2;
98058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    goto done_generating;
98068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    break;
98078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
98088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
98098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
98105389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine
9811c3b504f4c434a24513336fba2c6dff2d9ff43f28David 'Digit' Turner        if (search_pc) {
9812c3b504f4c434a24513336fba2c6dff2d9ff43f28David 'Digit' Turner            j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
9813c3b504f4c434a24513336fba2c6dff2d9ff43f28David 'Digit' Turner            if (lj < j) {
9814c3b504f4c434a24513336fba2c6dff2d9ff43f28David 'Digit' Turner                lj++;
9815c3b504f4c434a24513336fba2c6dff2d9ff43f28David 'Digit' Turner                while (lj < j)
9816c3b504f4c434a24513336fba2c6dff2d9ff43f28David 'Digit' Turner                    tcg_ctx.gen_opc_instr_start[lj++] = 0;
9817c3b504f4c434a24513336fba2c6dff2d9ff43f28David 'Digit' Turner            }
9818c3b504f4c434a24513336fba2c6dff2d9ff43f28David 'Digit' Turner            tcg_ctx.gen_opc_pc[lj] = dc->pc;
9819c3b504f4c434a24513336fba2c6dff2d9ff43f28David 'Digit' Turner            gen_opc_condexec_bits[lj] = (dc->condexec_cond << 4) | (dc->condexec_mask >> 1);
9820c3b504f4c434a24513336fba2c6dff2d9ff43f28David 'Digit' Turner            tcg_ctx.gen_opc_instr_start[lj] = 1;
9821c3b504f4c434a24513336fba2c6dff2d9ff43f28David 'Digit' Turner            tcg_ctx.gen_opc_icount[lj] = num_insns;
9822c3b504f4c434a24513336fba2c6dff2d9ff43f28David 'Digit' Turner        }
9823c3b504f4c434a24513336fba2c6dff2d9ff43f28David 'Digit' Turner
98248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
98258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            gen_io_start();
98268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
98275285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP))) {
98285285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tcg_gen_debug_insn_start(dc->pc);
98295285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        }
98305285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
98315285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        if (dc->thumb) {
98328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            disas_thumb_insn(env, dc);
98338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (dc->condexec_mask) {
9834a1204591a52bf668ee72c86f98f53189621572a2Vladimir Chtchetkine                dc->condexec_cond = (dc->condexec_cond & 0xe)
9835a1204591a52bf668ee72c86f98f53189621572a2Vladimir Chtchetkine                                   | ((dc->condexec_mask >> 4) & 1);
9836a1204591a52bf668ee72c86f98f53189621572a2Vladimir Chtchetkine                dc->condexec_mask = (dc->condexec_mask << 1) & 0x1f;
9837a1204591a52bf668ee72c86f98f53189621572a2Vladimir Chtchetkine                if (dc->condexec_mask == 0) {
9838a1204591a52bf668ee72c86f98f53189621572a2Vladimir Chtchetkine                    dc->condexec_cond = 0;
98398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
98408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
98418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        } else {
98428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            disas_arm_insn(env, dc);
98438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
98448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
98458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (dc->condjmp && !dc->is_jmp) {
98468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            gen_set_label(dc->condlabel);
98478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            dc->condjmp = 0;
98488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
98495285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
98505285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        if (tcg_check_temp_count()) {
98515285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            fprintf(stderr, "TCG temporary leak before %08x\n", dc->pc);
98525285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        }
98535285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
98545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        /* Translation stops when a conditional branch is encountered.
98558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         * Otherwise the subsequent code could get translated several times.
98568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         * Also stop translation when a page boundary is reached.  This
98578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         * ensures prefetch aborts occur at the right place.  */
98588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        num_insns ++;
9859975bba804aed54452f774cdbf79a7b4732fc7696David 'Digit' Turner    } while (!dc->is_jmp && tcg_ctx.gen_opc_ptr < gen_opc_end &&
9860fed223d2bab55eda155e3463b9cb6966e69dd73cDavid 'Digit' Turner             !ENV_GET_CPU(env)->singlestep_enabled &&
98615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner             !singlestep &&
98628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project             dc->pc < next_page_start &&
98638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project             num_insns < max_insns);
98648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
98658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (tb->cflags & CF_LAST_IO) {
98668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (dc->condjmp) {
98678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* FIXME:  This can theoretically happen with self-modifying
98688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project               code.  */
98698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            cpu_abort(env, "IO on conditional branch instruction");
98708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
98718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_io_end();
98728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
98738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
98748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* At this stage dc->condjmp will only be set when the skipped
98758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project       instruction was a conditional branch or trap, and the PC has
98768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project       already been written.  */
9877fed223d2bab55eda155e3463b9cb6966e69dd73cDavid 'Digit' Turner    if (unlikely(ENV_GET_CPU(env)->singlestep_enabled)) {
98788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* Make sure the pc is updated, and raise a debug exception.  */
98798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (dc->condjmp) {
98808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            gen_set_condexec(dc);
98818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (dc->is_jmp == DISAS_SWI) {
98828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                gen_exception(EXCP_SWI);
98835285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            } else if (dc->is_jmp == DISAS_SMC) {
98845285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                gen_exception(EXCP_SMC);
98858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            } else {
98868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                gen_exception(EXCP_DEBUG);
98878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
98888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            gen_set_label(dc->condlabel);
98898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
98908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (dc->condjmp || !dc->is_jmp) {
98918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            gen_set_pc_im(dc->pc);
98928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            dc->condjmp = 0;
98938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
98948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_set_condexec(dc);
98958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (dc->is_jmp == DISAS_SWI && !dc->condjmp) {
98968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            gen_exception(EXCP_SWI);
98975285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        } else if (dc->is_jmp == DISAS_SMC && !dc->condjmp) {
98985285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            gen_exception(EXCP_SMC);
98998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        } else {
99008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* FIXME: Single stepping a WFI insn will not halt
99018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project               the CPU.  */
99028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            gen_exception(EXCP_DEBUG);
99038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
99048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } else {
99058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* While branches must always occur at the end of an IT block,
99068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project           there are a few other things that can cause us to terminate
99078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project           the TB in the middel of an IT block:
99088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            - Exception generating instructions (bkpt, swi, undefined).
99098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            - Page boundaries.
99108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            - Hardware watchpoints.
99118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project           Hardware breakpoints have already been handled and skip this code.
99128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         */
99138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_set_condexec(dc);
99148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        switch(dc->is_jmp) {
99158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case DISAS_NEXT:
99168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            gen_goto_tb(dc, 1, dc->pc);
99178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
99188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        default:
99198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case DISAS_JUMP:
99208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case DISAS_UPDATE:
99218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* indicate that the hash table must be used to find the next TB */
99228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tcg_gen_exit_tb(0);
99238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
99248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case DISAS_TB_JUMP:
99258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* nothing more to generate */
99268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
99278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case DISAS_WFI:
99280b4c9e8457959b01cd26f60ef214e9b5b7a297d4David 'Digit' Turner            gen_helper_wfi(cpu_env);
99298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
99308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case DISAS_SWI:
99318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            gen_exception(EXCP_SWI);
99328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
99335285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        case DISAS_SMC:
99345285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            gen_exception(EXCP_SMC);
99355285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            break;
99368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
99378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (dc->condjmp) {
99388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            gen_set_label(dc->condlabel);
99398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            gen_set_condexec(dc);
99408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            gen_goto_tb(dc, 1, dc->pc);
99418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            dc->condjmp = 0;
99428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
99438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
99448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
99458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdone_generating:
99468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    gen_icount_end(tb, num_insns);
9947975bba804aed54452f774cdbf79a7b4732fc7696David 'Digit' Turner    *tcg_ctx.gen_opc_ptr = INDEX_op_end;
99488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
99498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef DEBUG_DISAS
99505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
99515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        qemu_log("----------------\n");
99525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        qemu_log("IN: %s\n", lookup_symbol(pc_start));
99530dc43a9a7d4ed798d2c53792fe30a907f81d7615David 'Digit' Turner        log_target_disas(env, pc_start, dc->pc - pc_start, dc->thumb);
99545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        qemu_log("\n");
99558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
99568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
99578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (search_pc) {
9958975bba804aed54452f774cdbf79a7b4732fc7696David 'Digit' Turner        j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
99598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        lj++;
99608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        while (lj <= j)
9961975bba804aed54452f774cdbf79a7b4732fc7696David 'Digit' Turner            tcg_ctx.gen_opc_instr_start[lj++] = 0;
99628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } else {
99638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tb->size = dc->pc - pc_start;
99648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tb->icount = num_insns;
99658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
99668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
99678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9968e2678e116c8cdb0f36b247a5bd9cfacc849362fcDavid 'Digit' Turnervoid gen_intermediate_code(CPUARMState *env, TranslationBlock *tb)
99698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
99708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    gen_intermediate_code_internal(env, tb, 0);
99718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
99728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9973e2678e116c8cdb0f36b247a5bd9cfacc849362fcDavid 'Digit' Turnervoid gen_intermediate_code_pc(CPUARMState *env, TranslationBlock *tb)
99748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
99758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    gen_intermediate_code_internal(env, tb, 1);
99768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
99778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
99788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic const char *cpu_mode_names[16] = {
99798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project  "usr", "fiq", "irq", "svc", "???", "???", "???", "abt",
99808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project  "???", "???", "???", "und", "???", "???", "???", "sys"
99818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project};
99828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9983bf7a22f3a6c38d359d2e933dec4706d1c7375f0aDavid 'Digit' Turnervoid cpu_dump_state(CPUState *cpu, FILE *f, fprintf_function cpu_fprintf,
99848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    int flags)
99858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
9986bf7a22f3a6c38d359d2e933dec4706d1c7375f0aDavid 'Digit' Turner    CPUARMState *env = cpu->env_ptr;
99878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int i;
99888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if 0
99898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    union {
99908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        uint32_t i;
99918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        float s;
99928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } s0, s1;
99938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    CPU_DoubleU d;
99948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* ??? This assumes float64 and double have the same layout.
99958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project       Oh well, it's only debug dumps.  */
99968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    union {
99978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        float64 f64;
99988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        double d;
99998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } d0;
100008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
100018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    uint32_t psr;
100028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
100038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for(i=0;i<16;i++) {
100048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        cpu_fprintf(f, "R%02d=%08x", i, env->regs[i]);
100058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if ((i % 4) == 3)
100068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            cpu_fprintf(f, "\n");
100078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        else
100088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            cpu_fprintf(f, " ");
100098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
100108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    psr = cpsr_read(env);
100118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    cpu_fprintf(f, "PSR=%08x %c%c%c%c %c %s%d\n",
100128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                psr,
100138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                psr & (1 << 31) ? 'N' : '-',
100148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                psr & (1 << 30) ? 'Z' : '-',
100158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                psr & (1 << 29) ? 'C' : '-',
100168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                psr & (1 << 28) ? 'V' : '-',
100178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                psr & CPSR_T ? 'T' : 'A',
100188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                cpu_mode_names[psr & 0xf], (psr & 0x10) ? 32 : 26);
100198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
100208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if 0
100218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for (i = 0; i < 16; i++) {
100228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        d.d = env->vfp.regs[i];
100238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        s0.i = d.l.lower;
100248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        s1.i = d.l.upper;
100258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        d0.f64 = d.d;
100268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        cpu_fprintf(f, "s%02d=%08x(%8g) s%02d=%08x(%8g) d%02d=%08x%08x(%8g)\n",
100278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    i * 2, (int)s0.i, s0.s,
100288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    i * 2 + 1, (int)s1.i, s1.s,
100298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    i, (int)(uint32_t)d.l.upper, (int)(uint32_t)d.l.lower,
100308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    d0.d);
100318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
100328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    cpu_fprintf(f, "FPSCR: %08x\n", (int)env->vfp.xregs[ARM_VFP_FPSCR]);
100338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
100348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
100358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10036e2678e116c8cdb0f36b247a5bd9cfacc849362fcDavid 'Digit' Turnervoid restore_state_to_opc(CPUARMState *env, TranslationBlock *tb, int pc_pos)
100378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
10038975bba804aed54452f774cdbf79a7b4732fc7696David 'Digit' Turner    env->regs[15] = tcg_ctx.gen_opc_pc[pc_pos];
1003986b1fb06ee6ef53d8961ce96343ba4aa37518840David 'Digit' Turner    env->condexec_bits = gen_opc_condexec_bits[pc_pos];
100408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
10041