18b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*
28b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *  ARM translation
38b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *
48b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *  Copyright (c) 2003 Fabrice Bellard
58b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *  Copyright (c) 2005-2007 CodeSourcery
68b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *  Copyright (c) 2007 OpenedHand, Ltd.
78b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *
88b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * This library is free software; you can redistribute it and/or
98b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * modify it under the terms of the GNU Lesser General Public
108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * License as published by the Free Software Foundation; either
118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * version 2 of the License, or (at your option) any later version.
128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *
138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * This library is distributed in the hope that it will be useful,
148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * but WITHOUT ANY WARRANTY; without even the implied warranty of
158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Lesser General Public License for more details.
178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *
188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * You should have received a copy of the GNU Lesser General Public
19a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner * License along with this library; if not, see <http://www.gnu.org/licenses/>.
208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */
218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include <stdarg.h>
228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include <stdlib.h>
238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include <stdio.h>
248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include <string.h>
258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include <inttypes.h>
268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "cpu.h"
288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "exec-all.h"
298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "disas.h"
308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "tcg-op.h"
318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "qemu-log.h"
328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
335285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#include "helper.h"
348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define GEN_HELPER 1
355285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#include "helper.h"
368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
375285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define ENABLE_ARCH_4T    arm_feature(env, ARM_FEATURE_V4T)
385285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define ENABLE_ARCH_5     arm_feature(env, ARM_FEATURE_V5)
395285864985be9077e58e42235af6582dee72e841David 'Digit' Turner/* currently all emulated v5 cores are also v5TE, so don't bother */
405285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define ENABLE_ARCH_5TE   arm_feature(env, ARM_FEATURE_V5)
418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define ENABLE_ARCH_5J    0
428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define ENABLE_ARCH_6     arm_feature(env, ARM_FEATURE_V6)
438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define ENABLE_ARCH_6K   arm_feature(env, ARM_FEATURE_V6K)
448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define ENABLE_ARCH_6T2   arm_feature(env, ARM_FEATURE_THUMB2)
458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define ENABLE_ARCH_7     arm_feature(env, ARM_FEATURE_V7)
468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#define ARCH(x) do { if (!ENABLE_ARCH_##x) goto illegal_op; } while(0)
488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* internal defines */
508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projecttypedef struct DisasContext {
518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    target_ulong pc;
528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int is_jmp;
538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* Nonzero if this instruction has been conditionally skipped.  */
548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int condjmp;
558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* The label that will be jumped to when the instruction is skipped.  */
568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int condlabel;
578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* Thumb-2 condtional execution bits.  */
588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int condexec_mask;
59a1204591a52bf668ee72c86f98f53189621572a2Vladimir Chtchetkine    int condexec_cond;
608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    struct TranslationBlock *tb;
618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int singlestep_enabled;
628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int thumb;
638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if !defined(CONFIG_USER_ONLY)
648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int user;
658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
665285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    int vfp_enabled;
675285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    int vec_len;
685285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    int vec_stride;
695389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine#ifdef CONFIG_MEMCHECK
705389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine    int search_pc;
71288208c386810fef725aa448a9f46bd2772bec8cDavid 'Digit' Turner#endif
728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} DisasContext;
738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
74288208c386810fef725aa448a9f46bd2772bec8cDavid 'Digit' Turner#include "translate-android.h"
75288208c386810fef725aa448a9f46bd2772bec8cDavid 'Digit' Turner
765285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic uint32_t gen_opc_condexec_bits[OPC_BUF_SIZE];
775285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if defined(CONFIG_USER_ONLY)
798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define IS_USER(s) 1
808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else
818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define IS_USER(s) (s->user)
828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* These instructions trap after executing, so defer them until after the
858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   conditional executions state has been updated.  */
868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define DISAS_WFI 4
878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define DISAS_SWI 5
885285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define DISAS_SMC 6
898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic TCGv_ptr cpu_env;
918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* We reuse the same 64-bit temporaries for efficiency.  */
925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic TCGv_i64 cpu_V0, cpu_V1, cpu_M0;
935285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic TCGv_i32 cpu_R[16];
945285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic TCGv_i32 cpu_exclusive_addr;
955285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic TCGv_i32 cpu_exclusive_val;
965285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic TCGv_i32 cpu_exclusive_high;
975285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#ifdef CONFIG_USER_ONLY
985285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic TCGv_i32 cpu_exclusive_test;
995285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic TCGv_i32 cpu_exclusive_info;
1005285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#endif
1018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* FIXME:  These should be removed.  */
1035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic TCGv cpu_F0s, cpu_F1s;
1045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic TCGv_i64 cpu_F0d, cpu_F1d;
1058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "gen-icount.h"
1078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1085285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic const char *regnames[] =
1095285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    { "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
1105285864985be9077e58e42235af6582dee72e841David 'Digit' Turner      "r8", "r9", "r10", "r11", "r12", "r13", "r14", "pc" };
1115285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
1128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* initialize TCG globals.  */
1138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid arm_translate_init(void)
1148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1155285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    int i;
1165285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
1175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
1185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
1195285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    for (i = 0; i < 16; i++) {
1205285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        cpu_R[i] = tcg_global_mem_new_i32(TCG_AREG0,
1215285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                                          offsetof(CPUState, regs[i]),
1225285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                                          regnames[i]);
1235285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    }
1245285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    cpu_exclusive_addr = tcg_global_mem_new_i32(TCG_AREG0,
1255285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        offsetof(CPUState, exclusive_addr), "exclusive_addr");
1265285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    cpu_exclusive_val = tcg_global_mem_new_i32(TCG_AREG0,
1275285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        offsetof(CPUState, exclusive_val), "exclusive_val");
1285285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    cpu_exclusive_high = tcg_global_mem_new_i32(TCG_AREG0,
1295285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        offsetof(CPUState, exclusive_high), "exclusive_high");
1305285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#ifdef CONFIG_USER_ONLY
1315285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    cpu_exclusive_test = tcg_global_mem_new_i32(TCG_AREG0,
1325285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        offsetof(CPUState, exclusive_test), "exclusive_test");
1335285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    cpu_exclusive_info = tcg_global_mem_new_i32(TCG_AREG0,
1345285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        offsetof(CPUState, exclusive_info), "exclusive_info");
1355285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#endif
1368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#define GEN_HELPER 2
1385285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#include "helper.h"
1398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
1408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline TCGv load_cpu_offset(int offset)
1428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1435285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    TCGv tmp = tcg_temp_new_i32();
1448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_gen_ld_i32(tmp, cpu_env, offset);
1458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return tmp;
1468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
1478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define load_cpu_field(name) load_cpu_offset(offsetof(CPUState, name))
1498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline void store_cpu_offset(TCGv var, int offset)
1518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_gen_st_i32(var, cpu_env, offset);
1535285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_temp_free_i32(var);
1548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
1558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define store_cpu_field(var, name) \
1578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    store_cpu_offset(var, offsetof(CPUState, name))
1588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Set a variable to the value of a CPU register.  */
1608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void load_reg_var(DisasContext *s, TCGv var, int reg)
1618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (reg == 15) {
1638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        uint32_t addr;
1648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* normaly, since we updated PC, we need only to add one insn */
1658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (s->thumb)
1668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            addr = (long)s->pc + 2;
1678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        else
1688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            addr = (long)s->pc + 4;
1698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tcg_gen_movi_i32(var, addr);
1708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } else {
1715285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tcg_gen_mov_i32(var, cpu_R[reg]);
1728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
1738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
1748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Create a new temporary and set it to the value of a CPU register.  */
1768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline TCGv load_reg(DisasContext *s, int reg)
1778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1785285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    TCGv tmp = tcg_temp_new_i32();
1798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    load_reg_var(s, tmp, reg);
1808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return tmp;
1818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
1828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Set a CPU register.  The source must be a temporary and will be
1848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   marked as dead.  */
1858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void store_reg(DisasContext *s, int reg, TCGv var)
1868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (reg == 15) {
1888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tcg_gen_andi_i32(var, var, ~1);
1898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        s->is_jmp = DISAS_JUMP;
1908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
1915285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_gen_mov_i32(cpu_R[reg], var);
1925285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_temp_free_i32(var);
1938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
1948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Value extensions.  */
1968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define gen_uxtb(var) tcg_gen_ext8u_i32(var, var)
1978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define gen_uxth(var) tcg_gen_ext16u_i32(var, var)
1988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define gen_sxtb(var) tcg_gen_ext8s_i32(var, var)
1998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define gen_sxth(var) tcg_gen_ext16s_i32(var, var)
2008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define gen_sxtb16(var) gen_helper_sxtb16(var, var)
2028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define gen_uxtb16(var) gen_helper_uxtb16(var, var)
2038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2055285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic inline void gen_set_cpsr(TCGv var, uint32_t mask)
2065285864985be9077e58e42235af6582dee72e841David 'Digit' Turner{
2075285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    TCGv tmp_mask = tcg_const_i32(mask);
2085285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    gen_helper_cpsr_write(var, tmp_mask);
2095285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_temp_free_i32(tmp_mask);
2105285864985be9077e58e42235af6582dee72e841David 'Digit' Turner}
2118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Set NZCV flags from the high 4 bits of var.  */
2128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define gen_set_nzcv(var) gen_set_cpsr(var, CPSR_NZCV)
2138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void gen_exception(int excp)
2158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
2165285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    TCGv tmp = tcg_temp_new_i32();
2178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_gen_movi_i32(tmp, excp);
2188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    gen_helper_exception(tmp);
2195285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_temp_free_i32(tmp);
2208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
2218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void gen_smul_dual(TCGv a, TCGv b)
2238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
2245285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    TCGv tmp1 = tcg_temp_new_i32();
2255285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    TCGv tmp2 = tcg_temp_new_i32();
2268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_gen_ext16s_i32(tmp1, a);
2278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_gen_ext16s_i32(tmp2, b);
2288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_gen_mul_i32(tmp1, tmp1, tmp2);
2295285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_temp_free_i32(tmp2);
2308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_gen_sari_i32(a, a, 16);
2318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_gen_sari_i32(b, b, 16);
2328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_gen_mul_i32(b, b, a);
2338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_gen_mov_i32(a, tmp1);
2345285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_temp_free_i32(tmp1);
2358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
2368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Byteswap each halfword.  */
2388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void gen_rev16(TCGv var)
2398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
2405285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    TCGv tmp = tcg_temp_new_i32();
2418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_gen_shri_i32(tmp, var, 8);
2428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_gen_andi_i32(tmp, tmp, 0x00ff00ff);
2438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_gen_shli_i32(var, var, 8);
2448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_gen_andi_i32(var, var, 0xff00ff00);
2458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_gen_or_i32(var, var, tmp);
2465285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_temp_free_i32(tmp);
2478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
2488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Byteswap low halfword and sign extend.  */
2508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void gen_revsh(TCGv var)
2518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
2525285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_gen_ext16u_i32(var, var);
2535285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_gen_bswap16_i32(var, var);
2545285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_gen_ext16s_i32(var, var);
2558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
2568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Unsigned bitfield extract.  */
2588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void gen_ubfx(TCGv var, int shift, uint32_t mask)
2598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
2608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (shift)
2618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tcg_gen_shri_i32(var, var, shift);
2628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_gen_andi_i32(var, var, mask);
2638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
2648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Signed bitfield extract.  */
2668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void gen_sbfx(TCGv var, int shift, int width)
2678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
2688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    uint32_t signbit;
2698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (shift)
2718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tcg_gen_sari_i32(var, var, shift);
2728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (shift + width < 32) {
2738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        signbit = 1u << (width - 1);
2748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tcg_gen_andi_i32(var, var, (1u << width) - 1);
2758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tcg_gen_xori_i32(var, var, signbit);
2768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tcg_gen_subi_i32(var, var, signbit);
2778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
2788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
2798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Bitfield insertion.  Insert val into base.  Clobbers base and val.  */
2818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void gen_bfi(TCGv dest, TCGv base, TCGv val, int shift, uint32_t mask)
2828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
2838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_gen_andi_i32(val, val, mask);
2848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_gen_shli_i32(val, val, shift);
2858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_gen_andi_i32(base, base, ~(mask << shift));
2868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_gen_or_i32(dest, base, val);
2878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
2888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2895285864985be9077e58e42235af6582dee72e841David 'Digit' Turner/* Return (b << 32) + a. Mark inputs as dead */
2905285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic TCGv_i64 gen_addq_msw(TCGv_i64 a, TCGv b)
2915285864985be9077e58e42235af6582dee72e841David 'Digit' Turner{
2925285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    TCGv_i64 tmp64 = tcg_temp_new_i64();
2935285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
2945285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_gen_extu_i32_i64(tmp64, b);
2955285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_temp_free_i32(b);
2965285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_gen_shli_i64(tmp64, tmp64, 32);
2975285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_gen_add_i64(a, tmp64, a);
2985285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
2995285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_temp_free_i64(tmp64);
3005285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    return a;
3015285864985be9077e58e42235af6582dee72e841David 'Digit' Turner}
3025285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
3035285864985be9077e58e42235af6582dee72e841David 'Digit' Turner/* Return (b << 32) - a. Mark inputs as dead. */
3045285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic TCGv_i64 gen_subq_msw(TCGv_i64 a, TCGv b)
3058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
3065285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    TCGv_i64 tmp64 = tcg_temp_new_i64();
3075285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
3085285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_gen_extu_i32_i64(tmp64, b);
3095285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_temp_free_i32(b);
3105285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_gen_shli_i64(tmp64, tmp64, 32);
3115285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_gen_sub_i64(a, tmp64, a);
3125285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
3135285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_temp_free_i64(tmp64);
3145285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    return a;
3158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
3168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* FIXME: Most targets have native widening multiplication.
3188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   It would be good to use that instead of a full wide multiply.  */
3198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* 32x32->64 multiply.  Marks inputs as dead.  */
3205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic TCGv_i64 gen_mulu_i64_i32(TCGv a, TCGv b)
3218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
3225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    TCGv_i64 tmp1 = tcg_temp_new_i64();
3235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    TCGv_i64 tmp2 = tcg_temp_new_i64();
3248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_gen_extu_i32_i64(tmp1, a);
3265285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_temp_free_i32(a);
3278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_gen_extu_i32_i64(tmp2, b);
3285285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_temp_free_i32(b);
3298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_gen_mul_i64(tmp1, tmp1, tmp2);
3305285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_temp_free_i64(tmp2);
3318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return tmp1;
3328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
3338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic TCGv_i64 gen_muls_i64_i32(TCGv a, TCGv b)
3358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
3365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    TCGv_i64 tmp1 = tcg_temp_new_i64();
3375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    TCGv_i64 tmp2 = tcg_temp_new_i64();
3388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_gen_ext_i32_i64(tmp1, a);
3405285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_temp_free_i32(a);
3418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_gen_ext_i32_i64(tmp2, b);
3425285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_temp_free_i32(b);
3438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_gen_mul_i64(tmp1, tmp1, tmp2);
3445285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_temp_free_i64(tmp2);
3458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return tmp1;
3468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
3478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Swap low and high halfwords.  */
3498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void gen_swap_half(TCGv var)
3508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
3515285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    TCGv tmp = tcg_temp_new_i32();
3528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_gen_shri_i32(tmp, var, 16);
3538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_gen_shli_i32(var, var, 16);
3548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_gen_or_i32(var, var, tmp);
3555285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_temp_free_i32(tmp);
3568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
3578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Dual 16-bit add.  Result placed in t0 and t1 is marked as dead.
3598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tmp = (t0 ^ t1) & 0x8000;
3608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    t0 &= ~0x8000;
3618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    t1 &= ~0x8000;
3628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    t0 = (t0 + t1) ^ tmp;
3638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */
3648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void gen_add16(TCGv t0, TCGv t1)
3668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
3675285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    TCGv tmp = tcg_temp_new_i32();
3688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_gen_xor_i32(tmp, t0, t1);
3698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_gen_andi_i32(tmp, tmp, 0x8000);
3708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_gen_andi_i32(t0, t0, ~0x8000);
3718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_gen_andi_i32(t1, t1, ~0x8000);
3728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_gen_add_i32(t0, t0, t1);
3738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_gen_xor_i32(t0, t0, tmp);
3745285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_temp_free_i32(tmp);
3755285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_temp_free_i32(t1);
3768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
3778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define gen_set_CF(var) tcg_gen_st_i32(var, cpu_env, offsetof(CPUState, CF))
3798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Set CF to the top bit of var.  */
3818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void gen_set_CF_bit31(TCGv var)
3828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
3835285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    TCGv tmp = tcg_temp_new_i32();
3848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_gen_shri_i32(tmp, var, 31);
3855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    gen_set_CF(tmp);
3865285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_temp_free_i32(tmp);
3878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
3888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Set N and Z flags from var.  */
3908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline void gen_logic_CC(TCGv var)
3918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
3928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_gen_st_i32(var, cpu_env, offsetof(CPUState, NF));
3938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_gen_st_i32(var, cpu_env, offsetof(CPUState, ZF));
3948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
3958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* T0 += T1 + CF.  */
3975285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic void gen_adc(TCGv t0, TCGv t1)
3988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
3998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    TCGv tmp;
4005285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_gen_add_i32(t0, t0, t1);
4018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tmp = load_cpu_field(CF);
4025285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_gen_add_i32(t0, t0, tmp);
4035285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_temp_free_i32(tmp);
4048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
4058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner/* dest = T0 + T1 + CF. */
4075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void gen_add_carry(TCGv dest, TCGv t0, TCGv t1)
4085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
4095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    TCGv tmp;
4105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    tcg_gen_add_i32(dest, t0, t1);
4115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    tmp = load_cpu_field(CF);
4125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    tcg_gen_add_i32(dest, dest, tmp);
4135285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_temp_free_i32(tmp);
4145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
4155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
4168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* dest = T0 - T1 + CF - 1.  */
4178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void gen_sub_carry(TCGv dest, TCGv t0, TCGv t1)
4188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
4198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    TCGv tmp;
4208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_gen_sub_i32(dest, t0, t1);
4218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tmp = load_cpu_field(CF);
4228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_gen_add_i32(dest, dest, tmp);
4238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_gen_subi_i32(dest, dest, 1);
4245285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_temp_free_i32(tmp);
4258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
4268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* FIXME:  Implement this natively.  */
4288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define tcg_gen_abs_i32(t0, t1) gen_helper_abs(t0, t1)
4298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void shifter_out_im(TCGv var, int shift)
4318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
4325285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    TCGv tmp = tcg_temp_new_i32();
4338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (shift == 0) {
4348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tcg_gen_andi_i32(tmp, var, 1);
4358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } else {
4368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tcg_gen_shri_i32(tmp, var, shift);
4375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (shift != 31)
4388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tcg_gen_andi_i32(tmp, tmp, 1);
4398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
4408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    gen_set_CF(tmp);
4415285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_temp_free_i32(tmp);
4428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
4438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Shift by immediate.  Includes special handling for shift == 0.  */
4458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline void gen_arm_shift_im(TCGv var, int shiftop, int shift, int flags)
4468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
4478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    switch (shiftop) {
4488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0: /* LSL */
4498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (shift != 0) {
4508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (flags)
4518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                shifter_out_im(var, 32 - shift);
4528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tcg_gen_shli_i32(var, var, shift);
4538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
4548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
4558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 1: /* LSR */
4568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (shift == 0) {
4578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (flags) {
4588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                tcg_gen_shri_i32(var, var, 31);
4598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                gen_set_CF(var);
4608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
4618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tcg_gen_movi_i32(var, 0);
4628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        } else {
4638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (flags)
4648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                shifter_out_im(var, shift - 1);
4658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tcg_gen_shri_i32(var, var, shift);
4668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
4678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
4688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 2: /* ASR */
4698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (shift == 0)
4708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            shift = 32;
4718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (flags)
4728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            shifter_out_im(var, shift - 1);
4738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (shift == 32)
4748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project          shift = 31;
4758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tcg_gen_sari_i32(var, var, shift);
4768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
4778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 3: /* ROR/RRX */
4788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (shift != 0) {
4798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (flags)
4808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                shifter_out_im(var, shift - 1);
4815285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tcg_gen_rotri_i32(var, var, shift); break;
4828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        } else {
4838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            TCGv tmp = load_cpu_field(CF);
4848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (flags)
4858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                shifter_out_im(var, 0);
4868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tcg_gen_shri_i32(var, var, 1);
4878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tcg_gen_shli_i32(tmp, tmp, 31);
4888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tcg_gen_or_i32(var, var, tmp);
4895285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tcg_temp_free_i32(tmp);
4908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
4918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
4928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project};
4938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline void gen_arm_shift_reg(TCGv var, int shiftop,
4958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                     TCGv shift, int flags)
4968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
4978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (flags) {
4988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        switch (shiftop) {
4998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0: gen_helper_shl_cc(var, var, shift); break;
5008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 1: gen_helper_shr_cc(var, var, shift); break;
5018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 2: gen_helper_sar_cc(var, var, shift); break;
5028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 3: gen_helper_ror_cc(var, var, shift); break;
5038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
5048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } else {
5058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        switch (shiftop) {
5068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0: gen_helper_shl(var, var, shift); break;
5078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 1: gen_helper_shr(var, var, shift); break;
5088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 2: gen_helper_sar(var, var, shift); break;
5095285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        case 3: tcg_gen_andi_i32(shift, shift, 0x1f);
5105285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_gen_rotr_i32(var, var, shift); break;
5118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
5128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
5135285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_temp_free_i32(shift);
5148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
5158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define PAS_OP(pfx) \
5178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    switch (op2) {  \
5188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0: gen_pas_helper(glue(pfx,add16)); break; \
5198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 1: gen_pas_helper(glue(pfx,addsubx)); break; \
5208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 2: gen_pas_helper(glue(pfx,subaddx)); break; \
5218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 3: gen_pas_helper(glue(pfx,sub16)); break; \
5228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 4: gen_pas_helper(glue(pfx,add8)); break; \
5238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 7: gen_pas_helper(glue(pfx,sub8)); break; \
5248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
5258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void gen_arm_parallel_addsub(int op1, int op2, TCGv a, TCGv b)
5268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
5275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    TCGv_ptr tmp;
5288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    switch (op1) {
5308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b, tmp)
5318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 1:
5325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        tmp = tcg_temp_new_ptr();
5338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUState, GE));
5348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        PAS_OP(s)
5355285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tcg_temp_free_ptr(tmp);
5368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
5378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 5:
5385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        tmp = tcg_temp_new_ptr();
5398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUState, GE));
5408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        PAS_OP(u)
5415285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tcg_temp_free_ptr(tmp);
5428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
5438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#undef gen_pas_helper
5448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b)
5458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 2:
5468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        PAS_OP(q);
5478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
5488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 3:
5498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        PAS_OP(sh);
5508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
5518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 6:
5528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        PAS_OP(uq);
5538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
5548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 7:
5558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        PAS_OP(uh);
5568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
5578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#undef gen_pas_helper
5588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
5598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
5608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#undef PAS_OP
5618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* For unknown reasons Arm and Thumb-2 use arbitrarily different encodings.  */
5638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define PAS_OP(pfx) \
5645285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    switch (op1) {  \
5658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0: gen_pas_helper(glue(pfx,add8)); break; \
5668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 1: gen_pas_helper(glue(pfx,add16)); break; \
5678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 2: gen_pas_helper(glue(pfx,addsubx)); break; \
5688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 4: gen_pas_helper(glue(pfx,sub8)); break; \
5698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 5: gen_pas_helper(glue(pfx,sub16)); break; \
5708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 6: gen_pas_helper(glue(pfx,subaddx)); break; \
5718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
5728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void gen_thumb2_parallel_addsub(int op1, int op2, TCGv a, TCGv b)
5738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
5745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    TCGv_ptr tmp;
5758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5765285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    switch (op2) {
5778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b, tmp)
5788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0:
5795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        tmp = tcg_temp_new_ptr();
5808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUState, GE));
5818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        PAS_OP(s)
5825285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tcg_temp_free_ptr(tmp);
5838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
5848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 4:
5855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        tmp = tcg_temp_new_ptr();
5868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUState, GE));
5878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        PAS_OP(u)
5885285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tcg_temp_free_ptr(tmp);
5898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
5908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#undef gen_pas_helper
5918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b)
5928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 1:
5938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        PAS_OP(q);
5948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
5958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 2:
5968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        PAS_OP(sh);
5978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
5988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 5:
5998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        PAS_OP(uq);
6008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
6018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 6:
6028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        PAS_OP(uh);
6038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
6048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#undef gen_pas_helper
6058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
6068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
6078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#undef PAS_OP
6088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void gen_test_cc(int cc, int label)
6108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
6118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    TCGv tmp;
6128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    TCGv tmp2;
6138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int inv;
6148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    switch (cc) {
6168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0: /* eq: Z */
6178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tmp = load_cpu_field(ZF);
6188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, label);
6198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
6208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 1: /* ne: !Z */
6218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tmp = load_cpu_field(ZF);
6228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, label);
6238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
6248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 2: /* cs: C */
6258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tmp = load_cpu_field(CF);
6268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, label);
6278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
6288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 3: /* cc: !C */
6298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tmp = load_cpu_field(CF);
6308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, label);
6318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
6328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 4: /* mi: N */
6338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tmp = load_cpu_field(NF);
6348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tcg_gen_brcondi_i32(TCG_COND_LT, tmp, 0, label);
6358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
6368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 5: /* pl: !N */
6378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tmp = load_cpu_field(NF);
6388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tcg_gen_brcondi_i32(TCG_COND_GE, tmp, 0, label);
6398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
6408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 6: /* vs: V */
6418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tmp = load_cpu_field(VF);
6428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tcg_gen_brcondi_i32(TCG_COND_LT, tmp, 0, label);
6438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
6448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 7: /* vc: !V */
6458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tmp = load_cpu_field(VF);
6468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tcg_gen_brcondi_i32(TCG_COND_GE, tmp, 0, label);
6478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
6488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 8: /* hi: C && !Z */
6498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        inv = gen_new_label();
6508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tmp = load_cpu_field(CF);
6518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, inv);
6525285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tcg_temp_free_i32(tmp);
6538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tmp = load_cpu_field(ZF);
6548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, label);
6558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_set_label(inv);
6568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
6578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 9: /* ls: !C || Z */
6588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tmp = load_cpu_field(CF);
6598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, label);
6605285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tcg_temp_free_i32(tmp);
6618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tmp = load_cpu_field(ZF);
6628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, label);
6638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
6648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 10: /* ge: N == V -> N ^ V == 0 */
6658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tmp = load_cpu_field(VF);
6668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tmp2 = load_cpu_field(NF);
6678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tcg_gen_xor_i32(tmp, tmp, tmp2);
6685285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tcg_temp_free_i32(tmp2);
6698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tcg_gen_brcondi_i32(TCG_COND_GE, tmp, 0, label);
6708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
6718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 11: /* lt: N != V -> N ^ V != 0 */
6728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tmp = load_cpu_field(VF);
6738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tmp2 = load_cpu_field(NF);
6748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tcg_gen_xor_i32(tmp, tmp, tmp2);
6755285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tcg_temp_free_i32(tmp2);
6768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tcg_gen_brcondi_i32(TCG_COND_LT, tmp, 0, label);
6778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
6788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 12: /* gt: !Z && N == V */
6798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        inv = gen_new_label();
6808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tmp = load_cpu_field(ZF);
6818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, inv);
6825285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tcg_temp_free_i32(tmp);
6838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tmp = load_cpu_field(VF);
6848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tmp2 = load_cpu_field(NF);
6858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tcg_gen_xor_i32(tmp, tmp, tmp2);
6865285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tcg_temp_free_i32(tmp2);
6878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tcg_gen_brcondi_i32(TCG_COND_GE, tmp, 0, label);
6888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_set_label(inv);
6898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
6908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 13: /* le: Z || N != V */
6918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tmp = load_cpu_field(ZF);
6928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, label);
6935285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tcg_temp_free_i32(tmp);
6948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tmp = load_cpu_field(VF);
6958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tmp2 = load_cpu_field(NF);
6968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tcg_gen_xor_i32(tmp, tmp, tmp2);
6975285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tcg_temp_free_i32(tmp2);
6988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tcg_gen_brcondi_i32(TCG_COND_LT, tmp, 0, label);
6998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
7008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    default:
7018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        fprintf(stderr, "Bad condition code 0x%x\n", cc);
7028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        abort();
7038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
7045285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_temp_free_i32(tmp);
7058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
7068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic const uint8_t table_logic_cc[16] = {
7088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    1, /* and */
7098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    1, /* xor */
7108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    0, /* sub */
7118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    0, /* rsb */
7128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    0, /* add */
7138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    0, /* adc */
7148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    0, /* sbc */
7158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    0, /* rsc */
7168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    1, /* andl */
7178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    1, /* xorl */
7188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    0, /* cmp */
7198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    0, /* cmn */
7208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    1, /* orr */
7218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    1, /* mov */
7228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    1, /* bic */
7238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    1, /* mvn */
7248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project};
7258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Set PC and Thumb state from an immediate address.  */
7278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline void gen_bx_im(DisasContext *s, uint32_t addr)
7288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
7298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    TCGv tmp;
7308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    s->is_jmp = DISAS_UPDATE;
7328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (s->thumb != (addr & 1)) {
7335285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tmp = tcg_temp_new_i32();
7348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tcg_gen_movi_i32(tmp, addr & 1);
7358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tcg_gen_st_i32(tmp, cpu_env, offsetof(CPUState, thumb));
7365285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tcg_temp_free_i32(tmp);
7378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
7385285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_gen_movi_i32(cpu_R[15], addr & ~1);
7398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
7408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Set PC and Thumb state from var.  var is marked as dead.  */
7428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline void gen_bx(DisasContext *s, TCGv var)
7438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
7448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    s->is_jmp = DISAS_UPDATE;
7455285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_gen_andi_i32(cpu_R[15], var, ~1);
7465285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_gen_andi_i32(var, var, 1);
7475285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    store_cpu_field(var, thumb);
7488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
7498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner/* Variant of store_reg which uses branch&exchange logic when storing
7515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner   to r15 in ARM architecture v7 and above. The source must be a temporary
7525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner   and will be marked as dead. */
7535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic inline void store_reg_bx(CPUState *env, DisasContext *s,
7545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                                int reg, TCGv var)
7555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
7565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (reg == 15 && ENABLE_ARCH_7) {
7575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        gen_bx(s, var);
7585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    } else {
7595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        store_reg(s, reg, var);
7605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
7615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
7625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
7635285864985be9077e58e42235af6582dee72e841David 'Digit' Turner/* Variant of store_reg which uses branch&exchange logic when storing
7645285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * to r15 in ARM architecture v5T and above. This is used for storing
7655285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * the results of a LDR/LDM/POP into r15, and corresponds to the cases
7665285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * in the ARM ARM which use the LoadWritePC() pseudocode function. */
7675285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic inline void store_reg_from_load(CPUState *env, DisasContext *s,
7685285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                                int reg, TCGv var)
7695285864985be9077e58e42235af6582dee72e841David 'Digit' Turner{
7705285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    if (reg == 15 && ENABLE_ARCH_5) {
7715285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        gen_bx(s, var);
7725285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    } else {
7735285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        store_reg(s, reg, var);
7745285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    }
7755285864985be9077e58e42235af6582dee72e841David 'Digit' Turner}
7765285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
7775285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic inline void gen_smc(CPUState *env, DisasContext *s)
7785285864985be9077e58e42235af6582dee72e841David 'Digit' Turner{
7795285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_gen_movi_i32(cpu_R[15], s->pc);
7805285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    s->is_jmp = DISAS_SMC;
7815285864985be9077e58e42235af6582dee72e841David 'Digit' Turner}
7825285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
7838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline TCGv gen_ld8s(TCGv addr, int index)
7848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
7855285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    TCGv tmp = tcg_temp_new_i32();
7868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_gen_qemu_ld8s(tmp, addr, index);
7878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return tmp;
7888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
7898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline TCGv gen_ld8u(TCGv addr, int index)
7908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
7915285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    TCGv tmp = tcg_temp_new_i32();
7928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_gen_qemu_ld8u(tmp, addr, index);
7938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return tmp;
7948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
7958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline TCGv gen_ld16s(TCGv addr, int index)
7968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
7975285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    TCGv tmp = tcg_temp_new_i32();
7988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_gen_qemu_ld16s(tmp, addr, index);
7998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return tmp;
8008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
8018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline TCGv gen_ld16u(TCGv addr, int index)
8028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
8035285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    TCGv tmp = tcg_temp_new_i32();
8048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_gen_qemu_ld16u(tmp, addr, index);
8058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return tmp;
8068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
8078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline TCGv gen_ld32(TCGv addr, int index)
8088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
8095285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    TCGv tmp = tcg_temp_new_i32();
8108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_gen_qemu_ld32u(tmp, addr, index);
8118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return tmp;
8128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
8135285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic inline TCGv_i64 gen_ld64(TCGv addr, int index)
8145285864985be9077e58e42235af6582dee72e841David 'Digit' Turner{
8155285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    TCGv_i64 tmp = tcg_temp_new_i64();
8165285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_gen_qemu_ld64(tmp, addr, index);
8175285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    return tmp;
8185285864985be9077e58e42235af6582dee72e841David 'Digit' Turner}
8198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline void gen_st8(TCGv val, TCGv addr, int index)
8208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
8218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_gen_qemu_st8(val, addr, index);
8225285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_temp_free_i32(val);
8238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
8248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline void gen_st16(TCGv val, TCGv addr, int index)
8258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
8268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_gen_qemu_st16(val, addr, index);
8275285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_temp_free_i32(val);
8288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
8298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline void gen_st32(TCGv val, TCGv addr, int index)
8308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
8318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_gen_qemu_st32(val, addr, index);
8325285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_temp_free_i32(val);
8338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
8345285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic inline void gen_st64(TCGv_i64 val, TCGv addr, int index)
8358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
8365285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_gen_qemu_st64(val, addr, index);
8375285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_temp_free_i64(val);
8388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
8398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline void gen_set_pc_im(uint32_t val)
8418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
8425285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_gen_movi_i32(cpu_R[15], val);
8438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
8448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Force a TB lookup after an instruction that changes the CPU state.  */
8468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline void gen_lookup_tb(DisasContext *s)
8478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
8485285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_gen_movi_i32(cpu_R[15], s->pc & ~1);
8498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    s->is_jmp = DISAS_UPDATE;
8508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
8518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline void gen_add_data_offset(DisasContext *s, unsigned int insn,
8538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                       TCGv var)
8548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
8558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int val, rm, shift, shiftop;
8568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    TCGv offset;
8578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!(insn & (1 << 25))) {
8598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* immediate */
8608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        val = insn & 0xfff;
8618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (!(insn & (1 << 23)))
8628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            val = -val;
8638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (val != 0)
8648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tcg_gen_addi_i32(var, var, val);
8658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } else {
8668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* shift/register */
8678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        rm = (insn) & 0xf;
8688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        shift = (insn >> 7) & 0x1f;
8698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        shiftop = (insn >> 5) & 3;
8708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        offset = load_reg(s, rm);
8718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_arm_shift_im(offset, shiftop, shift, 0);
8728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (!(insn & (1 << 23)))
8738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tcg_gen_sub_i32(var, var, offset);
8748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        else
8758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tcg_gen_add_i32(var, var, offset);
8765285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tcg_temp_free_i32(offset);
8778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
8788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
8798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline void gen_add_datah_offset(DisasContext *s, unsigned int insn,
8818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                        int extra, TCGv var)
8828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
8838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int val, rm;
8848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    TCGv offset;
8858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (insn & (1 << 22)) {
8878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* immediate */
8888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        val = (insn & 0xf) | ((insn >> 4) & 0xf0);
8898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (!(insn & (1 << 23)))
8908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            val = -val;
8918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        val += extra;
8928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (val != 0)
8938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tcg_gen_addi_i32(var, var, val);
8948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } else {
8958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* register */
8968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (extra)
8978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tcg_gen_addi_i32(var, var, extra);
8988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        rm = (insn) & 0xf;
8998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        offset = load_reg(s, rm);
9008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (!(insn & (1 << 23)))
9018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tcg_gen_sub_i32(var, var, offset);
9028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        else
9038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tcg_gen_add_i32(var, var, offset);
9045285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tcg_temp_free_i32(offset);
9058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
9068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
9078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define VFP_OP2(name)                                                 \
9098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline void gen_vfp_##name(int dp)                             \
9108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{                                                                     \
9118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (dp)                                                           \
9128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_helper_vfp_##name##d(cpu_F0d, cpu_F0d, cpu_F1d, cpu_env); \
9138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    else                                                              \
9148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, cpu_F1s, cpu_env); \
9158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
9168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectVFP_OP2(add)
9188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectVFP_OP2(sub)
9198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectVFP_OP2(mul)
9208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectVFP_OP2(div)
9218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#undef VFP_OP2
9238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9245285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic inline void gen_vfp_F1_mul(int dp)
9255285864985be9077e58e42235af6582dee72e841David 'Digit' Turner{
9265285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    /* Like gen_vfp_mul() but put result in F1 */
9275285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    if (dp) {
9285285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        gen_helper_vfp_muld(cpu_F1d, cpu_F0d, cpu_F1d, cpu_env);
9295285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    } else {
9305285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        gen_helper_vfp_muls(cpu_F1s, cpu_F0s, cpu_F1s, cpu_env);
9315285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    }
9325285864985be9077e58e42235af6582dee72e841David 'Digit' Turner}
9335285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
9345285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic inline void gen_vfp_F1_neg(int dp)
9355285864985be9077e58e42235af6582dee72e841David 'Digit' Turner{
9365285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    /* Like gen_vfp_neg() but put result in F1 */
9375285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    if (dp) {
9385285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        gen_helper_vfp_negd(cpu_F1d, cpu_F0d);
9395285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    } else {
9405285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        gen_helper_vfp_negs(cpu_F1s, cpu_F0s);
9415285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    }
9425285864985be9077e58e42235af6582dee72e841David 'Digit' Turner}
9435285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
9448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline void gen_vfp_abs(int dp)
9458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
9468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (dp)
9478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_helper_vfp_absd(cpu_F0d, cpu_F0d);
9488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    else
9498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_helper_vfp_abss(cpu_F0s, cpu_F0s);
9508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
9518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline void gen_vfp_neg(int dp)
9538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
9548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (dp)
9558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_helper_vfp_negd(cpu_F0d, cpu_F0d);
9568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    else
9578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_helper_vfp_negs(cpu_F0s, cpu_F0s);
9588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
9598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline void gen_vfp_sqrt(int dp)
9618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
9628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (dp)
9638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_helper_vfp_sqrtd(cpu_F0d, cpu_F0d, cpu_env);
9648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    else
9658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_helper_vfp_sqrts(cpu_F0s, cpu_F0s, cpu_env);
9668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
9678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline void gen_vfp_cmp(int dp)
9698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
9708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (dp)
9718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_helper_vfp_cmpd(cpu_F0d, cpu_F1d, cpu_env);
9728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    else
9738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_helper_vfp_cmps(cpu_F0s, cpu_F1s, cpu_env);
9748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
9758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline void gen_vfp_cmpe(int dp)
9778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
9788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (dp)
9798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_helper_vfp_cmped(cpu_F0d, cpu_F1d, cpu_env);
9808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    else
9818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_helper_vfp_cmpes(cpu_F0s, cpu_F1s, cpu_env);
9828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
9838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline void gen_vfp_F1_ld0(int dp)
9858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
9868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (dp)
9878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tcg_gen_movi_i64(cpu_F1d, 0);
9888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    else
9898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tcg_gen_movi_i32(cpu_F1s, 0);
9908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
9918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9925285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define VFP_GEN_ITOF(name) \
9935285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic inline void gen_vfp_##name(int dp, int neon) \
9945285864985be9077e58e42235af6582dee72e841David 'Digit' Turner{ \
9955285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    TCGv_ptr statusptr = tcg_temp_new_ptr(); \
9965285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    int offset; \
9975285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    if (neon) { \
9985285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        offset = offsetof(CPUState, vfp.standard_fp_status); \
9995285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    } else { \
10005285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        offset = offsetof(CPUState, vfp.fp_status); \
10015285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    } \
10025285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_gen_addi_ptr(statusptr, cpu_env, offset); \
10035285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    if (dp) { \
10045285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        gen_helper_vfp_##name##d(cpu_F0d, cpu_F0s, statusptr); \
10055285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    } else { \
10065285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, statusptr); \
10075285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    } \
10085285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_temp_free_ptr(statusptr); \
10098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
10108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10115285864985be9077e58e42235af6582dee72e841David 'Digit' TurnerVFP_GEN_ITOF(uito)
10125285864985be9077e58e42235af6582dee72e841David 'Digit' TurnerVFP_GEN_ITOF(sito)
10135285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#undef VFP_GEN_ITOF
10148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10155285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define VFP_GEN_FTOI(name) \
10165285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic inline void gen_vfp_##name(int dp, int neon) \
10175285864985be9077e58e42235af6582dee72e841David 'Digit' Turner{ \
10185285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    TCGv_ptr statusptr = tcg_temp_new_ptr(); \
10195285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    int offset; \
10205285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    if (neon) { \
10215285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        offset = offsetof(CPUState, vfp.standard_fp_status); \
10225285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    } else { \
10235285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        offset = offsetof(CPUState, vfp.fp_status); \
10245285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    } \
10255285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_gen_addi_ptr(statusptr, cpu_env, offset); \
10265285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    if (dp) { \
10275285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        gen_helper_vfp_##name##d(cpu_F0s, cpu_F0d, statusptr); \
10285285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    } else { \
10295285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, statusptr); \
10305285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    } \
10315285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_temp_free_ptr(statusptr); \
10328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
10338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10345285864985be9077e58e42235af6582dee72e841David 'Digit' TurnerVFP_GEN_FTOI(toui)
10355285864985be9077e58e42235af6582dee72e841David 'Digit' TurnerVFP_GEN_FTOI(touiz)
10365285864985be9077e58e42235af6582dee72e841David 'Digit' TurnerVFP_GEN_FTOI(tosi)
10375285864985be9077e58e42235af6582dee72e841David 'Digit' TurnerVFP_GEN_FTOI(tosiz)
10385285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#undef VFP_GEN_FTOI
10398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define VFP_GEN_FIX(name) \
10415285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic inline void gen_vfp_##name(int dp, int shift, int neon) \
10428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ \
10435285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    TCGv tmp_shift = tcg_const_i32(shift); \
10445285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    TCGv_ptr statusptr = tcg_temp_new_ptr(); \
10455285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    int offset; \
10465285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    if (neon) { \
10475285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        offset = offsetof(CPUState, vfp.standard_fp_status); \
10485285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    } else { \
10495285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        offset = offsetof(CPUState, vfp.fp_status); \
10505285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    } \
10515285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_gen_addi_ptr(statusptr, cpu_env, offset); \
10525285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    if (dp) { \
10535285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        gen_helper_vfp_##name##d(cpu_F0d, cpu_F0d, tmp_shift, statusptr); \
10545285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    } else { \
10555285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, tmp_shift, statusptr); \
10565285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    } \
10575285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_temp_free_i32(tmp_shift); \
10585285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_temp_free_ptr(statusptr); \
10598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
10608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectVFP_GEN_FIX(tosh)
10618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectVFP_GEN_FIX(tosl)
10628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectVFP_GEN_FIX(touh)
10638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectVFP_GEN_FIX(toul)
10648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectVFP_GEN_FIX(shto)
10658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectVFP_GEN_FIX(slto)
10668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectVFP_GEN_FIX(uhto)
10678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectVFP_GEN_FIX(ulto)
10688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#undef VFP_GEN_FIX
10698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10705285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic inline void gen_vfp_ld(DisasContext *s, int dp, TCGv addr)
10718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
10728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (dp)
10735285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tcg_gen_qemu_ld64(cpu_F0d, addr, IS_USER(s));
10748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    else
10755285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tcg_gen_qemu_ld32u(cpu_F0s, addr, IS_USER(s));
10768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
10778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10785285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic inline void gen_vfp_st(DisasContext *s, int dp, TCGv addr)
10798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
10808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (dp)
10815285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tcg_gen_qemu_st64(cpu_F0d, addr, IS_USER(s));
10828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    else
10835285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tcg_gen_qemu_st32(cpu_F0s, addr, IS_USER(s));
10848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
10858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline long
10878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvfp_reg_offset (int dp, int reg)
10888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
10898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (dp)
10908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return offsetof(CPUARMState, vfp.regs[reg]);
10918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    else if (reg & 1) {
10928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return offsetof(CPUARMState, vfp.regs[reg >> 1])
10938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project          + offsetof(CPU_DoubleU, l.upper);
10948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } else {
10958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return offsetof(CPUARMState, vfp.regs[reg >> 1])
10968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project          + offsetof(CPU_DoubleU, l.lower);
10978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
10988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
10998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Return the offset of a 32-bit piece of a NEON register.
11018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   zero is the least significant end of the register.  */
11028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline long
11038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectneon_reg_offset (int reg, int n)
11048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
11058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int sreg;
11068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    sreg = reg * 2 + n;
11078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return vfp_reg_offset(0, sreg);
11088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
11098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic TCGv neon_load_reg(int reg, int pass)
11118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
11125285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    TCGv tmp = tcg_temp_new_i32();
11138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_gen_ld_i32(tmp, cpu_env, neon_reg_offset(reg, pass));
11148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return tmp;
11158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
11168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void neon_store_reg(int reg, int pass, TCGv var)
11188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
11198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_gen_st_i32(var, cpu_env, neon_reg_offset(reg, pass));
11205285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_temp_free_i32(var);
11218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
11228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic inline void neon_load_reg64(TCGv_i64 var, int reg)
11248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
11258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_gen_ld_i64(var, cpu_env, vfp_reg_offset(1, reg));
11268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
11278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic inline void neon_store_reg64(TCGv_i64 var, int reg)
11298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
11308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_gen_st_i64(var, cpu_env, vfp_reg_offset(1, reg));
11318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
11328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define tcg_gen_ld_f32 tcg_gen_ld_i32
11348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define tcg_gen_ld_f64 tcg_gen_ld_i64
11358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define tcg_gen_st_f32 tcg_gen_st_i32
11368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define tcg_gen_st_f64 tcg_gen_st_i64
11378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline void gen_mov_F0_vreg(int dp, int reg)
11398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
11408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (dp)
11418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tcg_gen_ld_f64(cpu_F0d, cpu_env, vfp_reg_offset(dp, reg));
11428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    else
11438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tcg_gen_ld_f32(cpu_F0s, cpu_env, vfp_reg_offset(dp, reg));
11448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
11458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline void gen_mov_F1_vreg(int dp, int reg)
11478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
11488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (dp)
11498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tcg_gen_ld_f64(cpu_F1d, cpu_env, vfp_reg_offset(dp, reg));
11508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    else
11518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tcg_gen_ld_f32(cpu_F1s, cpu_env, vfp_reg_offset(dp, reg));
11528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
11538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline void gen_mov_vreg_F0(int dp, int reg)
11558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
11568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (dp)
11578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tcg_gen_st_f64(cpu_F0d, cpu_env, vfp_reg_offset(dp, reg));
11588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    else
11598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tcg_gen_st_f32(cpu_F0s, cpu_env, vfp_reg_offset(dp, reg));
11608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
11618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define ARM_CP_RW_BIT	(1 << 20)
11638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic inline void iwmmxt_load_reg(TCGv_i64 var, int reg)
11658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
11668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_gen_ld_i64(var, cpu_env, offsetof(CPUState, iwmmxt.regs[reg]));
11678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
11688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic inline void iwmmxt_store_reg(TCGv_i64 var, int reg)
11708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
11718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_gen_st_i64(var, cpu_env, offsetof(CPUState, iwmmxt.regs[reg]));
11728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
11738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11745285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic inline TCGv iwmmxt_load_creg(int reg)
11758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
11765285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    TCGv var = tcg_temp_new_i32();
11775285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_gen_ld_i32(var, cpu_env, offsetof(CPUState, iwmmxt.cregs[reg]));
11785285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    return var;
11798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
11808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11815285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic inline void iwmmxt_store_creg(int reg, TCGv var)
11828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
11835285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_gen_st_i32(var, cpu_env, offsetof(CPUState, iwmmxt.cregs[reg]));
11845285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_temp_free_i32(var);
11858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
11868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline void gen_op_iwmmxt_movq_wRn_M0(int rn)
11888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
11898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    iwmmxt_store_reg(cpu_M0, rn);
11908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
11918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline void gen_op_iwmmxt_movq_M0_wRn(int rn)
11938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
11948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    iwmmxt_load_reg(cpu_M0, rn);
11958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
11968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline void gen_op_iwmmxt_orq_M0_wRn(int rn)
11988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
11998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    iwmmxt_load_reg(cpu_V1, rn);
12008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_gen_or_i64(cpu_M0, cpu_M0, cpu_V1);
12018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
12028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline void gen_op_iwmmxt_andq_M0_wRn(int rn)
12048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
12058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    iwmmxt_load_reg(cpu_V1, rn);
12068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_gen_and_i64(cpu_M0, cpu_M0, cpu_V1);
12078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
12088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline void gen_op_iwmmxt_xorq_M0_wRn(int rn)
12108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
12118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    iwmmxt_load_reg(cpu_V1, rn);
12128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_gen_xor_i64(cpu_M0, cpu_M0, cpu_V1);
12138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
12148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define IWMMXT_OP(name) \
12168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline void gen_op_iwmmxt_##name##_M0_wRn(int rn) \
12178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ \
12188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    iwmmxt_load_reg(cpu_V1, rn); \
12198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    gen_helper_iwmmxt_##name(cpu_M0, cpu_M0, cpu_V1); \
12208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
12218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12225285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define IWMMXT_OP_SIZE(name) \
12235285864985be9077e58e42235af6582dee72e841David 'Digit' TurnerIWMMXT_OP(name##b) \
12245285864985be9077e58e42235af6582dee72e841David 'Digit' TurnerIWMMXT_OP(name##w) \
12255285864985be9077e58e42235af6582dee72e841David 'Digit' TurnerIWMMXT_OP(name##l)
12268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12275285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define IWMMXT_OP_1(name) \
12288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline void gen_op_iwmmxt_##name##_M0(void) \
12298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ \
12305285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    gen_helper_iwmmxt_##name(cpu_M0, cpu_M0); \
12318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
12328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectIWMMXT_OP(maddsq)
12348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectIWMMXT_OP(madduq)
12358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectIWMMXT_OP(sadb)
12368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectIWMMXT_OP(sadw)
12378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectIWMMXT_OP(mulslw)
12388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectIWMMXT_OP(mulshw)
12398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectIWMMXT_OP(mululw)
12408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectIWMMXT_OP(muluhw)
12418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectIWMMXT_OP(macsw)
12428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectIWMMXT_OP(macuw)
12438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12445285864985be9077e58e42235af6582dee72e841David 'Digit' TurnerIWMMXT_OP_SIZE(unpackl)
12455285864985be9077e58e42235af6582dee72e841David 'Digit' TurnerIWMMXT_OP_SIZE(unpackh)
12465285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
12475285864985be9077e58e42235af6582dee72e841David 'Digit' TurnerIWMMXT_OP_1(unpacklub)
12485285864985be9077e58e42235af6582dee72e841David 'Digit' TurnerIWMMXT_OP_1(unpackluw)
12495285864985be9077e58e42235af6582dee72e841David 'Digit' TurnerIWMMXT_OP_1(unpacklul)
12505285864985be9077e58e42235af6582dee72e841David 'Digit' TurnerIWMMXT_OP_1(unpackhub)
12515285864985be9077e58e42235af6582dee72e841David 'Digit' TurnerIWMMXT_OP_1(unpackhuw)
12525285864985be9077e58e42235af6582dee72e841David 'Digit' TurnerIWMMXT_OP_1(unpackhul)
12535285864985be9077e58e42235af6582dee72e841David 'Digit' TurnerIWMMXT_OP_1(unpacklsb)
12545285864985be9077e58e42235af6582dee72e841David 'Digit' TurnerIWMMXT_OP_1(unpacklsw)
12555285864985be9077e58e42235af6582dee72e841David 'Digit' TurnerIWMMXT_OP_1(unpacklsl)
12565285864985be9077e58e42235af6582dee72e841David 'Digit' TurnerIWMMXT_OP_1(unpackhsb)
12575285864985be9077e58e42235af6582dee72e841David 'Digit' TurnerIWMMXT_OP_1(unpackhsw)
12585285864985be9077e58e42235af6582dee72e841David 'Digit' TurnerIWMMXT_OP_1(unpackhsl)
12595285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
12605285864985be9077e58e42235af6582dee72e841David 'Digit' TurnerIWMMXT_OP_SIZE(cmpeq)
12615285864985be9077e58e42235af6582dee72e841David 'Digit' TurnerIWMMXT_OP_SIZE(cmpgtu)
12625285864985be9077e58e42235af6582dee72e841David 'Digit' TurnerIWMMXT_OP_SIZE(cmpgts)
12635285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
12645285864985be9077e58e42235af6582dee72e841David 'Digit' TurnerIWMMXT_OP_SIZE(mins)
12655285864985be9077e58e42235af6582dee72e841David 'Digit' TurnerIWMMXT_OP_SIZE(minu)
12665285864985be9077e58e42235af6582dee72e841David 'Digit' TurnerIWMMXT_OP_SIZE(maxs)
12675285864985be9077e58e42235af6582dee72e841David 'Digit' TurnerIWMMXT_OP_SIZE(maxu)
12685285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
12695285864985be9077e58e42235af6582dee72e841David 'Digit' TurnerIWMMXT_OP_SIZE(subn)
12705285864985be9077e58e42235af6582dee72e841David 'Digit' TurnerIWMMXT_OP_SIZE(addn)
12715285864985be9077e58e42235af6582dee72e841David 'Digit' TurnerIWMMXT_OP_SIZE(subu)
12725285864985be9077e58e42235af6582dee72e841David 'Digit' TurnerIWMMXT_OP_SIZE(addu)
12735285864985be9077e58e42235af6582dee72e841David 'Digit' TurnerIWMMXT_OP_SIZE(subs)
12745285864985be9077e58e42235af6582dee72e841David 'Digit' TurnerIWMMXT_OP_SIZE(adds)
12755285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
12765285864985be9077e58e42235af6582dee72e841David 'Digit' TurnerIWMMXT_OP(avgb0)
12775285864985be9077e58e42235af6582dee72e841David 'Digit' TurnerIWMMXT_OP(avgb1)
12785285864985be9077e58e42235af6582dee72e841David 'Digit' TurnerIWMMXT_OP(avgw0)
12795285864985be9077e58e42235af6582dee72e841David 'Digit' TurnerIWMMXT_OP(avgw1)
12808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectIWMMXT_OP(msadb)
12828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12835285864985be9077e58e42235af6582dee72e841David 'Digit' TurnerIWMMXT_OP(packuw)
12845285864985be9077e58e42235af6582dee72e841David 'Digit' TurnerIWMMXT_OP(packul)
12855285864985be9077e58e42235af6582dee72e841David 'Digit' TurnerIWMMXT_OP(packuq)
12865285864985be9077e58e42235af6582dee72e841David 'Digit' TurnerIWMMXT_OP(packsw)
12875285864985be9077e58e42235af6582dee72e841David 'Digit' TurnerIWMMXT_OP(packsl)
12885285864985be9077e58e42235af6582dee72e841David 'Digit' TurnerIWMMXT_OP(packsq)
12898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void gen_op_iwmmxt_set_mup(void)
12918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
12928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    TCGv tmp;
12938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tmp = load_cpu_field(iwmmxt.cregs[ARM_IWMMXT_wCon]);
12948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_gen_ori_i32(tmp, tmp, 2);
12958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    store_cpu_field(tmp, iwmmxt.cregs[ARM_IWMMXT_wCon]);
12968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
12978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void gen_op_iwmmxt_set_cup(void)
12998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
13008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    TCGv tmp;
13018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tmp = load_cpu_field(iwmmxt.cregs[ARM_IWMMXT_wCon]);
13028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_gen_ori_i32(tmp, tmp, 1);
13038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    store_cpu_field(tmp, iwmmxt.cregs[ARM_IWMMXT_wCon]);
13048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
13058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void gen_op_iwmmxt_setpsr_nz(void)
13078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
13085285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    TCGv tmp = tcg_temp_new_i32();
13098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    gen_helper_iwmmxt_setpsr_nz(tmp, cpu_M0);
13108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    store_cpu_field(tmp, iwmmxt.cregs[ARM_IWMMXT_wCASF]);
13118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
13128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline void gen_op_iwmmxt_addl_M0_wRn(int rn)
13148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
13158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    iwmmxt_load_reg(cpu_V1, rn);
13168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_gen_ext32u_i64(cpu_V1, cpu_V1);
13178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_gen_add_i64(cpu_M0, cpu_M0, cpu_V1);
13188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
13198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13205285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic inline int gen_iwmmxt_address(DisasContext *s, uint32_t insn, TCGv dest)
13218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
13228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int rd;
13238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    uint32_t offset;
13245285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    TCGv tmp;
13258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    rd = (insn >> 16) & 0xf;
13275285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tmp = load_reg(s, rd);
13288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    offset = (insn & 0xff) << ((insn >> 7) & 2);
13308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (insn & (1 << 24)) {
13318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* Pre indexed */
13328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (insn & (1 << 23))
13335285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tcg_gen_addi_i32(tmp, tmp, offset);
13348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        else
13355285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tcg_gen_addi_i32(tmp, tmp, -offset);
13365285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tcg_gen_mov_i32(dest, tmp);
13378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (insn & (1 << 21))
13385285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            store_reg(s, rd, tmp);
13395285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        else
13405285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tcg_temp_free_i32(tmp);
13418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } else if (insn & (1 << 21)) {
13428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* Post indexed */
13435285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tcg_gen_mov_i32(dest, tmp);
13448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (insn & (1 << 23))
13455285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tcg_gen_addi_i32(tmp, tmp, offset);
13468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        else
13475285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tcg_gen_addi_i32(tmp, tmp, -offset);
13485285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        store_reg(s, rd, tmp);
13498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } else if (!(insn & (1 << 23)))
13508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return 1;
13518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
13528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
13538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13545285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic inline int gen_iwmmxt_shift(uint32_t insn, uint32_t mask, TCGv dest)
13558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
13568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int rd = (insn >> 0) & 0xf;
13575285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    TCGv tmp;
13588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13595285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    if (insn & (1 << 8)) {
13605285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        if (rd < ARM_IWMMXT_wCGR0 || rd > ARM_IWMMXT_wCGR3) {
13618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 1;
13625285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        } else {
13635285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tmp = iwmmxt_load_creg(rd);
13645285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        }
13655285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    } else {
13665285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tmp = tcg_temp_new_i32();
13675285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        iwmmxt_load_reg(cpu_V0, rd);
13685285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tcg_gen_trunc_i64_i32(tmp, cpu_V0);
13695285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    }
13705285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_gen_andi_i32(tmp, tmp, mask);
13715285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_gen_mov_i32(dest, tmp);
13725285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_temp_free_i32(tmp);
13738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
13748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
13758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13765285864985be9077e58e42235af6582dee72e841David 'Digit' Turner/* Disassemble an iwMMXt instruction.  Returns nonzero if an error occurred
13778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   (ie. an undefined instruction).  */
13788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int disas_iwmmxt_insn(CPUState *env, DisasContext *s, uint32_t insn)
13798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
13808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int rd, wrd;
13818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int rdhi, rdlo, rd0, rd1, i;
13825285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    TCGv addr;
13835285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    TCGv tmp, tmp2, tmp3;
13848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if ((insn & 0x0e000e00) == 0x0c000000) {
13868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if ((insn & 0x0fe00ff0) == 0x0c400000) {
13878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            wrd = insn & 0xf;
13888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            rdlo = (insn >> 12) & 0xf;
13898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            rdhi = (insn >> 16) & 0xf;
13908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (insn & ARM_CP_RW_BIT) {			/* TMRRC */
13915285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                iwmmxt_load_reg(cpu_V0, wrd);
13925285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_gen_trunc_i64_i32(cpu_R[rdlo], cpu_V0);
13935285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_gen_shri_i64(cpu_V0, cpu_V0, 32);
13945285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_gen_trunc_i64_i32(cpu_R[rdhi], cpu_V0);
13958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            } else {					/* TMCRR */
13965285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_gen_concat_i32_i64(cpu_V0, cpu_R[rdlo], cpu_R[rdhi]);
13975285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                iwmmxt_store_reg(cpu_V0, wrd);
13988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                gen_op_iwmmxt_set_mup();
13998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
14008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 0;
14018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
14028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
14038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        wrd = (insn >> 12) & 0xf;
14045285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        addr = tcg_temp_new_i32();
14055285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        if (gen_iwmmxt_address(s, insn, addr)) {
14065285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tcg_temp_free_i32(addr);
14078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 1;
14085285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        }
14098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (insn & ARM_CP_RW_BIT) {
14108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if ((insn >> 28) == 0xf) {			/* WLDRW wCx */
14115285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tmp = tcg_temp_new_i32();
14125285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_gen_qemu_ld32u(tmp, addr, IS_USER(s));
14135285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                iwmmxt_store_creg(wrd, tmp);
14148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            } else {
14158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                i = 1;
14168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (insn & (1 << 8)) {
14178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if (insn & (1 << 22)) {		/* WLDRD */
14185285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tcg_gen_qemu_ld64(cpu_M0, addr, IS_USER(s));
14198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        i = 0;
14208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    } else {				/* WLDRW wRd */
14215285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tmp = gen_ld32(addr, IS_USER(s));
14228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
14238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                } else {
14248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if (insn & (1 << 22)) {		/* WLDRH */
14255285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tmp = gen_ld16u(addr, IS_USER(s));
14268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    } else {				/* WLDRB */
14275285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tmp = gen_ld8u(addr, IS_USER(s));
14288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
14298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
14308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (i) {
14318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    tcg_gen_extu_i32_i64(cpu_M0, tmp);
14325285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tcg_temp_free_i32(tmp);
14338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
14348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                gen_op_iwmmxt_movq_wRn_M0(wrd);
14358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
14368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        } else {
14378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if ((insn >> 28) == 0xf) {			/* WSTRW wCx */
14385285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tmp = iwmmxt_load_creg(wrd);
14395285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                gen_st32(tmp, addr, IS_USER(s));
14408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            } else {
14418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                gen_op_iwmmxt_movq_M0_wRn(wrd);
14425285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tmp = tcg_temp_new_i32();
14438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (insn & (1 << 8)) {
14448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if (insn & (1 << 22)) {		/* WSTRD */
14455285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tcg_temp_free_i32(tmp);
14465285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tcg_gen_qemu_st64(cpu_M0, addr, IS_USER(s));
14478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    } else {				/* WSTRW wRd */
14488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        tcg_gen_trunc_i64_i32(tmp, cpu_M0);
14495285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        gen_st32(tmp, addr, IS_USER(s));
14508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
14518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                } else {
14528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if (insn & (1 << 22)) {		/* WSTRH */
14538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        tcg_gen_trunc_i64_i32(tmp, cpu_M0);
14545285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        gen_st16(tmp, addr, IS_USER(s));
14558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    } else {				/* WSTRB */
14568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        tcg_gen_trunc_i64_i32(tmp, cpu_M0);
14575285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        gen_st8(tmp, addr, IS_USER(s));
14588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
14598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
14608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
14618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
14625285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tcg_temp_free_i32(addr);
14638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return 0;
14648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
14658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
14668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if ((insn & 0x0f000000) != 0x0e000000)
14678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return 1;
14688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
14698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    switch (((insn >> 12) & 0xf00) | ((insn >> 4) & 0xff)) {
14708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0x000:						/* WOR */
14718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        wrd = (insn >> 12) & 0xf;
14728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        rd0 = (insn >> 0) & 0xf;
14738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        rd1 = (insn >> 16) & 0xf;
14748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_movq_M0_wRn(rd0);
14758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_orq_M0_wRn(rd1);
14768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_setpsr_nz();
14778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_movq_wRn_M0(wrd);
14788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_set_mup();
14798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_set_cup();
14808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
14818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0x011:						/* TMCR */
14828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (insn & 0xf)
14838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 1;
14848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        rd = (insn >> 12) & 0xf;
14858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        wrd = (insn >> 16) & 0xf;
14868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        switch (wrd) {
14878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case ARM_IWMMXT_wCID:
14888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case ARM_IWMMXT_wCASF:
14898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
14908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case ARM_IWMMXT_wCon:
14918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            gen_op_iwmmxt_set_cup();
14928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* Fall through.  */
14938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case ARM_IWMMXT_wCSSF:
14945285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tmp = iwmmxt_load_creg(wrd);
14955285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tmp2 = load_reg(s, rd);
14965285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tcg_gen_andc_i32(tmp, tmp, tmp2);
14975285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tcg_temp_free_i32(tmp2);
14985285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            iwmmxt_store_creg(wrd, tmp);
14998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
15008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case ARM_IWMMXT_wCGR0:
15018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case ARM_IWMMXT_wCGR1:
15028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case ARM_IWMMXT_wCGR2:
15038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case ARM_IWMMXT_wCGR3:
15048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            gen_op_iwmmxt_set_cup();
15055285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tmp = load_reg(s, rd);
15065285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            iwmmxt_store_creg(wrd, tmp);
15078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
15088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        default:
15098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 1;
15108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
15118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
15128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0x100:						/* WXOR */
15138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        wrd = (insn >> 12) & 0xf;
15148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        rd0 = (insn >> 0) & 0xf;
15158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        rd1 = (insn >> 16) & 0xf;
15168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_movq_M0_wRn(rd0);
15178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_xorq_M0_wRn(rd1);
15188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_setpsr_nz();
15198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_movq_wRn_M0(wrd);
15208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_set_mup();
15218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_set_cup();
15228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
15238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0x111:						/* TMRC */
15248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (insn & 0xf)
15258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 1;
15268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        rd = (insn >> 12) & 0xf;
15278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        wrd = (insn >> 16) & 0xf;
15285285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tmp = iwmmxt_load_creg(wrd);
15295285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        store_reg(s, rd, tmp);
15308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
15318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0x300:						/* WANDN */
15328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        wrd = (insn >> 12) & 0xf;
15338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        rd0 = (insn >> 0) & 0xf;
15348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        rd1 = (insn >> 16) & 0xf;
15358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_movq_M0_wRn(rd0);
15368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tcg_gen_neg_i64(cpu_M0, cpu_M0);
15378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_andq_M0_wRn(rd1);
15388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_setpsr_nz();
15398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_movq_wRn_M0(wrd);
15408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_set_mup();
15418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_set_cup();
15428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
15438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0x200:						/* WAND */
15448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        wrd = (insn >> 12) & 0xf;
15458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        rd0 = (insn >> 0) & 0xf;
15468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        rd1 = (insn >> 16) & 0xf;
15478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_movq_M0_wRn(rd0);
15488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_andq_M0_wRn(rd1);
15498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_setpsr_nz();
15508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_movq_wRn_M0(wrd);
15518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_set_mup();
15528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_set_cup();
15538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
15548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0x810: case 0xa10:				/* WMADD */
15558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        wrd = (insn >> 12) & 0xf;
15568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        rd0 = (insn >> 0) & 0xf;
15578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        rd1 = (insn >> 16) & 0xf;
15588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_movq_M0_wRn(rd0);
15598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (insn & (1 << 21))
15608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            gen_op_iwmmxt_maddsq_M0_wRn(rd1);
15618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        else
15628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            gen_op_iwmmxt_madduq_M0_wRn(rd1);
15638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_movq_wRn_M0(wrd);
15648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_set_mup();
15658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
15668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0x10e: case 0x50e: case 0x90e: case 0xd0e:	/* WUNPCKIL */
15678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        wrd = (insn >> 12) & 0xf;
15688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        rd0 = (insn >> 16) & 0xf;
15698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        rd1 = (insn >> 0) & 0xf;
15708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_movq_M0_wRn(rd0);
15718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        switch ((insn >> 22) & 3) {
15728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0:
15738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            gen_op_iwmmxt_unpacklb_M0_wRn(rd1);
15748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
15758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 1:
15768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            gen_op_iwmmxt_unpacklw_M0_wRn(rd1);
15778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
15788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 2:
15798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            gen_op_iwmmxt_unpackll_M0_wRn(rd1);
15808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
15818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 3:
15828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 1;
15838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
15848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_movq_wRn_M0(wrd);
15858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_set_mup();
15868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_set_cup();
15878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
15888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0x10c: case 0x50c: case 0x90c: case 0xd0c:	/* WUNPCKIH */
15898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        wrd = (insn >> 12) & 0xf;
15908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        rd0 = (insn >> 16) & 0xf;
15918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        rd1 = (insn >> 0) & 0xf;
15928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_movq_M0_wRn(rd0);
15938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        switch ((insn >> 22) & 3) {
15948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0:
15958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            gen_op_iwmmxt_unpackhb_M0_wRn(rd1);
15968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
15978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 1:
15988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            gen_op_iwmmxt_unpackhw_M0_wRn(rd1);
15998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
16008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 2:
16018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            gen_op_iwmmxt_unpackhl_M0_wRn(rd1);
16028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
16038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 3:
16048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 1;
16058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
16068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_movq_wRn_M0(wrd);
16078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_set_mup();
16088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_set_cup();
16098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
16108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0x012: case 0x112: case 0x412: case 0x512:	/* WSAD */
16118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        wrd = (insn >> 12) & 0xf;
16128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        rd0 = (insn >> 16) & 0xf;
16138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        rd1 = (insn >> 0) & 0xf;
16148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_movq_M0_wRn(rd0);
16158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (insn & (1 << 22))
16168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            gen_op_iwmmxt_sadw_M0_wRn(rd1);
16178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        else
16188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            gen_op_iwmmxt_sadb_M0_wRn(rd1);
16198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (!(insn & (1 << 20)))
16208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            gen_op_iwmmxt_addl_M0_wRn(wrd);
16218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_movq_wRn_M0(wrd);
16228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_set_mup();
16238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
16248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0x010: case 0x110: case 0x210: case 0x310:	/* WMUL */
16258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        wrd = (insn >> 12) & 0xf;
16268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        rd0 = (insn >> 16) & 0xf;
16278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        rd1 = (insn >> 0) & 0xf;
16288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_movq_M0_wRn(rd0);
16298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (insn & (1 << 21)) {
16308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (insn & (1 << 20))
16318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                gen_op_iwmmxt_mulshw_M0_wRn(rd1);
16328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            else
16338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                gen_op_iwmmxt_mulslw_M0_wRn(rd1);
16348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        } else {
16358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (insn & (1 << 20))
16368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                gen_op_iwmmxt_muluhw_M0_wRn(rd1);
16378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            else
16388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                gen_op_iwmmxt_mululw_M0_wRn(rd1);
16398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
16408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_movq_wRn_M0(wrd);
16418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_set_mup();
16428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
16438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0x410: case 0x510: case 0x610: case 0x710:	/* WMAC */
16448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        wrd = (insn >> 12) & 0xf;
16458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        rd0 = (insn >> 16) & 0xf;
16468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        rd1 = (insn >> 0) & 0xf;
16478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_movq_M0_wRn(rd0);
16488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (insn & (1 << 21))
16498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            gen_op_iwmmxt_macsw_M0_wRn(rd1);
16508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        else
16518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            gen_op_iwmmxt_macuw_M0_wRn(rd1);
16528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (!(insn & (1 << 20))) {
16538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            iwmmxt_load_reg(cpu_V1, wrd);
16548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tcg_gen_add_i64(cpu_M0, cpu_M0, cpu_V1);
16558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
16568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_movq_wRn_M0(wrd);
16578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_set_mup();
16588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
16598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0x006: case 0x406: case 0x806: case 0xc06:	/* WCMPEQ */
16608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        wrd = (insn >> 12) & 0xf;
16618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        rd0 = (insn >> 16) & 0xf;
16628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        rd1 = (insn >> 0) & 0xf;
16638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_movq_M0_wRn(rd0);
16648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        switch ((insn >> 22) & 3) {
16658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0:
16668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            gen_op_iwmmxt_cmpeqb_M0_wRn(rd1);
16678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
16688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 1:
16698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            gen_op_iwmmxt_cmpeqw_M0_wRn(rd1);
16708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
16718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 2:
16728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            gen_op_iwmmxt_cmpeql_M0_wRn(rd1);
16738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
16748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 3:
16758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 1;
16768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
16778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_movq_wRn_M0(wrd);
16788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_set_mup();
16798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_set_cup();
16808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
16818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0x800: case 0x900: case 0xc00: case 0xd00:	/* WAVG2 */
16828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        wrd = (insn >> 12) & 0xf;
16838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        rd0 = (insn >> 16) & 0xf;
16848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        rd1 = (insn >> 0) & 0xf;
16858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_movq_M0_wRn(rd0);
16868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (insn & (1 << 22)) {
16878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (insn & (1 << 20))
16888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                gen_op_iwmmxt_avgw1_M0_wRn(rd1);
16898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            else
16908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                gen_op_iwmmxt_avgw0_M0_wRn(rd1);
16918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        } else {
16928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (insn & (1 << 20))
16938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                gen_op_iwmmxt_avgb1_M0_wRn(rd1);
16948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            else
16958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                gen_op_iwmmxt_avgb0_M0_wRn(rd1);
16968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
16978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_movq_wRn_M0(wrd);
16988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_set_mup();
16998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_set_cup();
17008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
17018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0x802: case 0x902: case 0xa02: case 0xb02:	/* WALIGNR */
17028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        wrd = (insn >> 12) & 0xf;
17038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        rd0 = (insn >> 16) & 0xf;
17048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        rd1 = (insn >> 0) & 0xf;
17058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_movq_M0_wRn(rd0);
17065285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tmp = iwmmxt_load_creg(ARM_IWMMXT_wCGR0 + ((insn >> 20) & 3));
17075285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tcg_gen_andi_i32(tmp, tmp, 7);
17085285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        iwmmxt_load_reg(cpu_V1, rd1);
17095285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        gen_helper_iwmmxt_align(cpu_M0, cpu_M0, cpu_V1, tmp);
17105285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tcg_temp_free_i32(tmp);
17118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_movq_wRn_M0(wrd);
17128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_set_mup();
17138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
17148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0x601: case 0x605: case 0x609: case 0x60d:	/* TINSR */
17155285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        if (((insn >> 6) & 3) == 3)
17165285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            return 1;
17178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        rd = (insn >> 12) & 0xf;
17188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        wrd = (insn >> 16) & 0xf;
17195285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tmp = load_reg(s, rd);
17208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_movq_M0_wRn(wrd);
17218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        switch ((insn >> 6) & 3) {
17228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0:
17235285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tmp2 = tcg_const_i32(0xff);
17245285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tmp3 = tcg_const_i32((insn & 7) << 3);
17258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
17268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 1:
17275285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tmp2 = tcg_const_i32(0xffff);
17285285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tmp3 = tcg_const_i32((insn & 3) << 4);
17298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
17308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 2:
17315285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tmp2 = tcg_const_i32(0xffffffff);
17325285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tmp3 = tcg_const_i32((insn & 1) << 5);
17338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
17345285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        default:
17355285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            TCGV_UNUSED(tmp2);
17365285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            TCGV_UNUSED(tmp3);
17378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
17385285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        gen_helper_iwmmxt_insr(cpu_M0, cpu_M0, tmp, tmp2, tmp3);
17395285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tcg_temp_free(tmp3);
17405285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tcg_temp_free(tmp2);
17415285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tcg_temp_free_i32(tmp);
17428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_movq_wRn_M0(wrd);
17438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_set_mup();
17448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
17458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0x107: case 0x507: case 0x907: case 0xd07:	/* TEXTRM */
17468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        rd = (insn >> 12) & 0xf;
17478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        wrd = (insn >> 16) & 0xf;
17485285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        if (rd == 15 || ((insn >> 22) & 3) == 3)
17498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 1;
17508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_movq_M0_wRn(wrd);
17515285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tmp = tcg_temp_new_i32();
17528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        switch ((insn >> 22) & 3) {
17538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0:
17545285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tcg_gen_shri_i64(cpu_M0, cpu_M0, (insn & 7) << 3);
17555285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tcg_gen_trunc_i64_i32(tmp, cpu_M0);
17565285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            if (insn & 8) {
17575285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_gen_ext8s_i32(tmp, tmp);
17585285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            } else {
17595285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_gen_andi_i32(tmp, tmp, 0xff);
17608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
17618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
17628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 1:
17635285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tcg_gen_shri_i64(cpu_M0, cpu_M0, (insn & 3) << 4);
17645285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tcg_gen_trunc_i64_i32(tmp, cpu_M0);
17655285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            if (insn & 8) {
17665285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_gen_ext16s_i32(tmp, tmp);
17675285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            } else {
17685285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_gen_andi_i32(tmp, tmp, 0xffff);
17698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
17708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
17718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 2:
17725285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tcg_gen_shri_i64(cpu_M0, cpu_M0, (insn & 1) << 5);
17735285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tcg_gen_trunc_i64_i32(tmp, cpu_M0);
17748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
17758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
17765285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        store_reg(s, rd, tmp);
17778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
17788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0x117: case 0x517: case 0x917: case 0xd17:	/* TEXTRC */
17795285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        if ((insn & 0x000ff008) != 0x0003f000 || ((insn >> 22) & 3) == 3)
17808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 1;
17815285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tmp = iwmmxt_load_creg(ARM_IWMMXT_wCASF);
17828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        switch ((insn >> 22) & 3) {
17838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0:
17845285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tcg_gen_shri_i32(tmp, tmp, ((insn & 7) << 2) + 0);
17858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
17868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 1:
17875285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tcg_gen_shri_i32(tmp, tmp, ((insn & 3) << 3) + 4);
17888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
17898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 2:
17905285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tcg_gen_shri_i32(tmp, tmp, ((insn & 1) << 4) + 12);
17918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
17928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
17935285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tcg_gen_shli_i32(tmp, tmp, 28);
17945285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        gen_set_nzcv(tmp);
17955285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tcg_temp_free_i32(tmp);
17968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
17978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0x401: case 0x405: case 0x409: case 0x40d:	/* TBCST */
17985285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        if (((insn >> 6) & 3) == 3)
17995285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            return 1;
18008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        rd = (insn >> 12) & 0xf;
18018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        wrd = (insn >> 16) & 0xf;
18025285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tmp = load_reg(s, rd);
18038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        switch ((insn >> 6) & 3) {
18048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0:
18055285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            gen_helper_iwmmxt_bcstb(cpu_M0, tmp);
18068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
18078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 1:
18085285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            gen_helper_iwmmxt_bcstw(cpu_M0, tmp);
18098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
18108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 2:
18115285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            gen_helper_iwmmxt_bcstl(cpu_M0, tmp);
18128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
18138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
18145285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tcg_temp_free_i32(tmp);
18158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_movq_wRn_M0(wrd);
18168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_set_mup();
18178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
18188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0x113: case 0x513: case 0x913: case 0xd13:	/* TANDC */
18195285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        if ((insn & 0x000ff00f) != 0x0003f000 || ((insn >> 22) & 3) == 3)
18208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 1;
18215285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tmp = iwmmxt_load_creg(ARM_IWMMXT_wCASF);
18225285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tmp2 = tcg_temp_new_i32();
18235285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tcg_gen_mov_i32(tmp2, tmp);
18248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        switch ((insn >> 22) & 3) {
18258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0:
18268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            for (i = 0; i < 7; i ++) {
18275285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_gen_shli_i32(tmp2, tmp2, 4);
18285285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_gen_and_i32(tmp, tmp, tmp2);
18298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
18308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
18318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 1:
18328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            for (i = 0; i < 3; i ++) {
18335285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_gen_shli_i32(tmp2, tmp2, 8);
18345285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_gen_and_i32(tmp, tmp, tmp2);
18358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
18368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
18378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 2:
18385285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tcg_gen_shli_i32(tmp2, tmp2, 16);
18395285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tcg_gen_and_i32(tmp, tmp, tmp2);
18408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
18418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
18425285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        gen_set_nzcv(tmp);
18435285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tcg_temp_free_i32(tmp2);
18445285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tcg_temp_free_i32(tmp);
18458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
18468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0x01c: case 0x41c: case 0x81c: case 0xc1c:	/* WACC */
18478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        wrd = (insn >> 12) & 0xf;
18488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        rd0 = (insn >> 16) & 0xf;
18498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_movq_M0_wRn(rd0);
18508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        switch ((insn >> 22) & 3) {
18518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0:
18528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            gen_helper_iwmmxt_addcb(cpu_M0, cpu_M0);
18538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
18548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 1:
18558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            gen_helper_iwmmxt_addcw(cpu_M0, cpu_M0);
18568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
18578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 2:
18588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            gen_helper_iwmmxt_addcl(cpu_M0, cpu_M0);
18598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
18608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 3:
18618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 1;
18628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
18638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_movq_wRn_M0(wrd);
18648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_set_mup();
18658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
18668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0x115: case 0x515: case 0x915: case 0xd15:	/* TORC */
18675285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        if ((insn & 0x000ff00f) != 0x0003f000 || ((insn >> 22) & 3) == 3)
18688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 1;
18695285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tmp = iwmmxt_load_creg(ARM_IWMMXT_wCASF);
18705285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tmp2 = tcg_temp_new_i32();
18715285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tcg_gen_mov_i32(tmp2, tmp);
18728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        switch ((insn >> 22) & 3) {
18738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0:
18748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            for (i = 0; i < 7; i ++) {
18755285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_gen_shli_i32(tmp2, tmp2, 4);
18765285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_gen_or_i32(tmp, tmp, tmp2);
18778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
18788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
18798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 1:
18808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            for (i = 0; i < 3; i ++) {
18815285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_gen_shli_i32(tmp2, tmp2, 8);
18825285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_gen_or_i32(tmp, tmp, tmp2);
18838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
18848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
18858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 2:
18865285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tcg_gen_shli_i32(tmp2, tmp2, 16);
18875285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tcg_gen_or_i32(tmp, tmp, tmp2);
18888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
18898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
18905285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        gen_set_nzcv(tmp);
18915285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tcg_temp_free_i32(tmp2);
18925285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tcg_temp_free_i32(tmp);
18938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
18948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0x103: case 0x503: case 0x903: case 0xd03:	/* TMOVMSK */
18958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        rd = (insn >> 12) & 0xf;
18968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        rd0 = (insn >> 16) & 0xf;
18975285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        if ((insn & 0xf) != 0 || ((insn >> 22) & 3) == 3)
18988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 1;
18998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_movq_M0_wRn(rd0);
19005285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tmp = tcg_temp_new_i32();
19018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        switch ((insn >> 22) & 3) {
19028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0:
19035285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            gen_helper_iwmmxt_msbb(tmp, cpu_M0);
19048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
19058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 1:
19065285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            gen_helper_iwmmxt_msbw(tmp, cpu_M0);
19078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
19088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 2:
19095285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            gen_helper_iwmmxt_msbl(tmp, cpu_M0);
19108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
19118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
19125285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        store_reg(s, rd, tmp);
19138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
19148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0x106: case 0x306: case 0x506: case 0x706:	/* WCMPGT */
19158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0x906: case 0xb06: case 0xd06: case 0xf06:
19168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        wrd = (insn >> 12) & 0xf;
19178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        rd0 = (insn >> 16) & 0xf;
19188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        rd1 = (insn >> 0) & 0xf;
19198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_movq_M0_wRn(rd0);
19208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        switch ((insn >> 22) & 3) {
19218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0:
19228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (insn & (1 << 21))
19238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                gen_op_iwmmxt_cmpgtsb_M0_wRn(rd1);
19248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            else
19258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                gen_op_iwmmxt_cmpgtub_M0_wRn(rd1);
19268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
19278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 1:
19288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (insn & (1 << 21))
19298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                gen_op_iwmmxt_cmpgtsw_M0_wRn(rd1);
19308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            else
19318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                gen_op_iwmmxt_cmpgtuw_M0_wRn(rd1);
19328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
19338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 2:
19348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (insn & (1 << 21))
19358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                gen_op_iwmmxt_cmpgtsl_M0_wRn(rd1);
19368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            else
19378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                gen_op_iwmmxt_cmpgtul_M0_wRn(rd1);
19388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
19398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 3:
19408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 1;
19418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
19428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_movq_wRn_M0(wrd);
19438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_set_mup();
19448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_set_cup();
19458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
19468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0x00e: case 0x20e: case 0x40e: case 0x60e:	/* WUNPCKEL */
19478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0x80e: case 0xa0e: case 0xc0e: case 0xe0e:
19488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        wrd = (insn >> 12) & 0xf;
19498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        rd0 = (insn >> 16) & 0xf;
19508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_movq_M0_wRn(rd0);
19518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        switch ((insn >> 22) & 3) {
19528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0:
19538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (insn & (1 << 21))
19548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                gen_op_iwmmxt_unpacklsb_M0();
19558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            else
19568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                gen_op_iwmmxt_unpacklub_M0();
19578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
19588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 1:
19598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (insn & (1 << 21))
19608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                gen_op_iwmmxt_unpacklsw_M0();
19618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            else
19628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                gen_op_iwmmxt_unpackluw_M0();
19638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
19648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 2:
19658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (insn & (1 << 21))
19668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                gen_op_iwmmxt_unpacklsl_M0();
19678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            else
19688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                gen_op_iwmmxt_unpacklul_M0();
19698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
19708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 3:
19718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 1;
19728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
19738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_movq_wRn_M0(wrd);
19748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_set_mup();
19758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_set_cup();
19768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
19778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0x00c: case 0x20c: case 0x40c: case 0x60c:	/* WUNPCKEH */
19788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0x80c: case 0xa0c: case 0xc0c: case 0xe0c:
19798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        wrd = (insn >> 12) & 0xf;
19808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        rd0 = (insn >> 16) & 0xf;
19818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_movq_M0_wRn(rd0);
19828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        switch ((insn >> 22) & 3) {
19838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0:
19848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (insn & (1 << 21))
19858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                gen_op_iwmmxt_unpackhsb_M0();
19868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            else
19878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                gen_op_iwmmxt_unpackhub_M0();
19888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
19898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 1:
19908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (insn & (1 << 21))
19918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                gen_op_iwmmxt_unpackhsw_M0();
19928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            else
19938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                gen_op_iwmmxt_unpackhuw_M0();
19948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
19958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 2:
19968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (insn & (1 << 21))
19978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                gen_op_iwmmxt_unpackhsl_M0();
19988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            else
19998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                gen_op_iwmmxt_unpackhul_M0();
20008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
20018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 3:
20028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 1;
20038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
20048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_movq_wRn_M0(wrd);
20058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_set_mup();
20068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_set_cup();
20078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
20088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0x204: case 0x604: case 0xa04: case 0xe04:	/* WSRL */
20098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0x214: case 0x614: case 0xa14: case 0xe14:
20105285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        if (((insn >> 22) & 3) == 0)
20115285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            return 1;
20128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        wrd = (insn >> 12) & 0xf;
20138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        rd0 = (insn >> 16) & 0xf;
20148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_movq_M0_wRn(rd0);
20155285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tmp = tcg_temp_new_i32();
20165285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        if (gen_iwmmxt_shift(insn, 0xff, tmp)) {
20175285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tcg_temp_free_i32(tmp);
20188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 1;
20195285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        }
20208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        switch ((insn >> 22) & 3) {
20218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 1:
20225285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            gen_helper_iwmmxt_srlw(cpu_M0, cpu_M0, tmp);
20238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
20248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 2:
20255285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            gen_helper_iwmmxt_srll(cpu_M0, cpu_M0, tmp);
20268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
20278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 3:
20285285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            gen_helper_iwmmxt_srlq(cpu_M0, cpu_M0, tmp);
20298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
20308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
20315285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tcg_temp_free_i32(tmp);
20328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_movq_wRn_M0(wrd);
20338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_set_mup();
20348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_set_cup();
20358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
20368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0x004: case 0x404: case 0x804: case 0xc04:	/* WSRA */
20378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0x014: case 0x414: case 0x814: case 0xc14:
20385285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        if (((insn >> 22) & 3) == 0)
20395285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            return 1;
20408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        wrd = (insn >> 12) & 0xf;
20418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        rd0 = (insn >> 16) & 0xf;
20428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_movq_M0_wRn(rd0);
20435285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tmp = tcg_temp_new_i32();
20445285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        if (gen_iwmmxt_shift(insn, 0xff, tmp)) {
20455285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tcg_temp_free_i32(tmp);
20468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 1;
20475285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        }
20488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        switch ((insn >> 22) & 3) {
20498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 1:
20505285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            gen_helper_iwmmxt_sraw(cpu_M0, cpu_M0, tmp);
20518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
20528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 2:
20535285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            gen_helper_iwmmxt_sral(cpu_M0, cpu_M0, tmp);
20548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
20558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 3:
20565285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            gen_helper_iwmmxt_sraq(cpu_M0, cpu_M0, tmp);
20578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
20588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
20595285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tcg_temp_free_i32(tmp);
20608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_movq_wRn_M0(wrd);
20618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_set_mup();
20628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_set_cup();
20638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
20648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0x104: case 0x504: case 0x904: case 0xd04:	/* WSLL */
20658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0x114: case 0x514: case 0x914: case 0xd14:
20665285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        if (((insn >> 22) & 3) == 0)
20675285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            return 1;
20688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        wrd = (insn >> 12) & 0xf;
20698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        rd0 = (insn >> 16) & 0xf;
20708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_movq_M0_wRn(rd0);
20715285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tmp = tcg_temp_new_i32();
20725285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        if (gen_iwmmxt_shift(insn, 0xff, tmp)) {
20735285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tcg_temp_free_i32(tmp);
20748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 1;
20755285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        }
20768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        switch ((insn >> 22) & 3) {
20778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 1:
20785285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            gen_helper_iwmmxt_sllw(cpu_M0, cpu_M0, tmp);
20798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
20808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 2:
20815285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            gen_helper_iwmmxt_slll(cpu_M0, cpu_M0, tmp);
20828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
20838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 3:
20845285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            gen_helper_iwmmxt_sllq(cpu_M0, cpu_M0, tmp);
20858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
20868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
20875285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tcg_temp_free_i32(tmp);
20888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_movq_wRn_M0(wrd);
20898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_set_mup();
20908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_set_cup();
20918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
20928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0x304: case 0x704: case 0xb04: case 0xf04:	/* WROR */
20938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0x314: case 0x714: case 0xb14: case 0xf14:
20945285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        if (((insn >> 22) & 3) == 0)
20955285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            return 1;
20968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        wrd = (insn >> 12) & 0xf;
20978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        rd0 = (insn >> 16) & 0xf;
20988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_movq_M0_wRn(rd0);
20995285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tmp = tcg_temp_new_i32();
21008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        switch ((insn >> 22) & 3) {
21018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 1:
21025285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            if (gen_iwmmxt_shift(insn, 0xf, tmp)) {
21035285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_temp_free_i32(tmp);
21048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                return 1;
21055285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            }
21065285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            gen_helper_iwmmxt_rorw(cpu_M0, cpu_M0, tmp);
21078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
21088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 2:
21095285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            if (gen_iwmmxt_shift(insn, 0x1f, tmp)) {
21105285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_temp_free_i32(tmp);
21118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                return 1;
21125285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            }
21135285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            gen_helper_iwmmxt_rorl(cpu_M0, cpu_M0, tmp);
21148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
21158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 3:
21165285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            if (gen_iwmmxt_shift(insn, 0x3f, tmp)) {
21175285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_temp_free_i32(tmp);
21188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                return 1;
21195285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            }
21205285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            gen_helper_iwmmxt_rorq(cpu_M0, cpu_M0, tmp);
21218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
21228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
21235285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tcg_temp_free_i32(tmp);
21248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_movq_wRn_M0(wrd);
21258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_set_mup();
21268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_set_cup();
21278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
21288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0x116: case 0x316: case 0x516: case 0x716:	/* WMIN */
21298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0x916: case 0xb16: case 0xd16: case 0xf16:
21308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        wrd = (insn >> 12) & 0xf;
21318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        rd0 = (insn >> 16) & 0xf;
21328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        rd1 = (insn >> 0) & 0xf;
21338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_movq_M0_wRn(rd0);
21348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        switch ((insn >> 22) & 3) {
21358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0:
21368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (insn & (1 << 21))
21378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                gen_op_iwmmxt_minsb_M0_wRn(rd1);
21388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            else
21398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                gen_op_iwmmxt_minub_M0_wRn(rd1);
21408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
21418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 1:
21428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (insn & (1 << 21))
21438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                gen_op_iwmmxt_minsw_M0_wRn(rd1);
21448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            else
21458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                gen_op_iwmmxt_minuw_M0_wRn(rd1);
21468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
21478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 2:
21488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (insn & (1 << 21))
21498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                gen_op_iwmmxt_minsl_M0_wRn(rd1);
21508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            else
21518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                gen_op_iwmmxt_minul_M0_wRn(rd1);
21528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
21538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 3:
21548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 1;
21558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
21568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_movq_wRn_M0(wrd);
21578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_set_mup();
21588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
21598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0x016: case 0x216: case 0x416: case 0x616:	/* WMAX */
21608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0x816: case 0xa16: case 0xc16: case 0xe16:
21618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        wrd = (insn >> 12) & 0xf;
21628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        rd0 = (insn >> 16) & 0xf;
21638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        rd1 = (insn >> 0) & 0xf;
21648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_movq_M0_wRn(rd0);
21658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        switch ((insn >> 22) & 3) {
21668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0:
21678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (insn & (1 << 21))
21688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                gen_op_iwmmxt_maxsb_M0_wRn(rd1);
21698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            else
21708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                gen_op_iwmmxt_maxub_M0_wRn(rd1);
21718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
21728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 1:
21738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (insn & (1 << 21))
21748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                gen_op_iwmmxt_maxsw_M0_wRn(rd1);
21758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            else
21768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                gen_op_iwmmxt_maxuw_M0_wRn(rd1);
21778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
21788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 2:
21798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (insn & (1 << 21))
21808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                gen_op_iwmmxt_maxsl_M0_wRn(rd1);
21818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            else
21828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                gen_op_iwmmxt_maxul_M0_wRn(rd1);
21838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
21848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 3:
21858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 1;
21868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
21878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_movq_wRn_M0(wrd);
21888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_set_mup();
21898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
21908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0x002: case 0x102: case 0x202: case 0x302:	/* WALIGNI */
21918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0x402: case 0x502: case 0x602: case 0x702:
21928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        wrd = (insn >> 12) & 0xf;
21938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        rd0 = (insn >> 16) & 0xf;
21948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        rd1 = (insn >> 0) & 0xf;
21958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_movq_M0_wRn(rd0);
21965285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tmp = tcg_const_i32((insn >> 20) & 3);
21975285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        iwmmxt_load_reg(cpu_V1, rd1);
21985285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        gen_helper_iwmmxt_align(cpu_M0, cpu_M0, cpu_V1, tmp);
21995285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tcg_temp_free(tmp);
22008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_movq_wRn_M0(wrd);
22018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_set_mup();
22028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
22038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0x01a: case 0x11a: case 0x21a: case 0x31a:	/* WSUB */
22048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0x41a: case 0x51a: case 0x61a: case 0x71a:
22058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0x81a: case 0x91a: case 0xa1a: case 0xb1a:
22068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0xc1a: case 0xd1a: case 0xe1a: case 0xf1a:
22078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        wrd = (insn >> 12) & 0xf;
22088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        rd0 = (insn >> 16) & 0xf;
22098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        rd1 = (insn >> 0) & 0xf;
22108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_movq_M0_wRn(rd0);
22118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        switch ((insn >> 20) & 0xf) {
22128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0x0:
22138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            gen_op_iwmmxt_subnb_M0_wRn(rd1);
22148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
22158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0x1:
22168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            gen_op_iwmmxt_subub_M0_wRn(rd1);
22178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
22188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0x3:
22198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            gen_op_iwmmxt_subsb_M0_wRn(rd1);
22208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
22218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0x4:
22228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            gen_op_iwmmxt_subnw_M0_wRn(rd1);
22238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
22248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0x5:
22258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            gen_op_iwmmxt_subuw_M0_wRn(rd1);
22268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
22278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0x7:
22288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            gen_op_iwmmxt_subsw_M0_wRn(rd1);
22298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
22308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0x8:
22318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            gen_op_iwmmxt_subnl_M0_wRn(rd1);
22328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
22338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0x9:
22348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            gen_op_iwmmxt_subul_M0_wRn(rd1);
22358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
22368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0xb:
22378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            gen_op_iwmmxt_subsl_M0_wRn(rd1);
22388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
22398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        default:
22408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 1;
22418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
22428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_movq_wRn_M0(wrd);
22438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_set_mup();
22448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_set_cup();
22458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
22468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0x01e: case 0x11e: case 0x21e: case 0x31e:	/* WSHUFH */
22478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0x41e: case 0x51e: case 0x61e: case 0x71e:
22488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0x81e: case 0x91e: case 0xa1e: case 0xb1e:
22498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0xc1e: case 0xd1e: case 0xe1e: case 0xf1e:
22508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        wrd = (insn >> 12) & 0xf;
22518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        rd0 = (insn >> 16) & 0xf;
22528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_movq_M0_wRn(rd0);
22535285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tmp = tcg_const_i32(((insn >> 16) & 0xf0) | (insn & 0x0f));
22545285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        gen_helper_iwmmxt_shufh(cpu_M0, cpu_M0, tmp);
22555285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tcg_temp_free(tmp);
22568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_movq_wRn_M0(wrd);
22578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_set_mup();
22588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_set_cup();
22598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
22608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0x018: case 0x118: case 0x218: case 0x318:	/* WADD */
22618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0x418: case 0x518: case 0x618: case 0x718:
22628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0x818: case 0x918: case 0xa18: case 0xb18:
22638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0xc18: case 0xd18: case 0xe18: case 0xf18:
22648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        wrd = (insn >> 12) & 0xf;
22658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        rd0 = (insn >> 16) & 0xf;
22668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        rd1 = (insn >> 0) & 0xf;
22678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_movq_M0_wRn(rd0);
22688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        switch ((insn >> 20) & 0xf) {
22698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0x0:
22708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            gen_op_iwmmxt_addnb_M0_wRn(rd1);
22718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
22728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0x1:
22738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            gen_op_iwmmxt_addub_M0_wRn(rd1);
22748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
22758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0x3:
22768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            gen_op_iwmmxt_addsb_M0_wRn(rd1);
22778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
22788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0x4:
22798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            gen_op_iwmmxt_addnw_M0_wRn(rd1);
22808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
22818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0x5:
22828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            gen_op_iwmmxt_adduw_M0_wRn(rd1);
22838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
22848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0x7:
22858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            gen_op_iwmmxt_addsw_M0_wRn(rd1);
22868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
22878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0x8:
22888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            gen_op_iwmmxt_addnl_M0_wRn(rd1);
22898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
22908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0x9:
22918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            gen_op_iwmmxt_addul_M0_wRn(rd1);
22928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
22938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0xb:
22948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            gen_op_iwmmxt_addsl_M0_wRn(rd1);
22958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
22968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        default:
22978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 1;
22988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
22998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_movq_wRn_M0(wrd);
23008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_set_mup();
23018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_set_cup();
23028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
23038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0x008: case 0x108: case 0x208: case 0x308:	/* WPACK */
23048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0x408: case 0x508: case 0x608: case 0x708:
23058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0x808: case 0x908: case 0xa08: case 0xb08:
23068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0xc08: case 0xd08: case 0xe08: case 0xf08:
23075285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        if (!(insn & (1 << 20)) || ((insn >> 22) & 3) == 0)
23085285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            return 1;
23098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        wrd = (insn >> 12) & 0xf;
23108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        rd0 = (insn >> 16) & 0xf;
23118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        rd1 = (insn >> 0) & 0xf;
23128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_movq_M0_wRn(rd0);
23138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        switch ((insn >> 22) & 3) {
23148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 1:
23158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (insn & (1 << 21))
23168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                gen_op_iwmmxt_packsw_M0_wRn(rd1);
23178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            else
23188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                gen_op_iwmmxt_packuw_M0_wRn(rd1);
23198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
23208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 2:
23218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (insn & (1 << 21))
23228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                gen_op_iwmmxt_packsl_M0_wRn(rd1);
23238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            else
23248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                gen_op_iwmmxt_packul_M0_wRn(rd1);
23258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
23268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 3:
23278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (insn & (1 << 21))
23288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                gen_op_iwmmxt_packsq_M0_wRn(rd1);
23298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            else
23308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                gen_op_iwmmxt_packuq_M0_wRn(rd1);
23318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
23328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
23338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_movq_wRn_M0(wrd);
23348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_set_mup();
23358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_set_cup();
23368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
23378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0x201: case 0x203: case 0x205: case 0x207:
23388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0x209: case 0x20b: case 0x20d: case 0x20f:
23398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0x211: case 0x213: case 0x215: case 0x217:
23408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0x219: case 0x21b: case 0x21d: case 0x21f:
23418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        wrd = (insn >> 5) & 0xf;
23428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        rd0 = (insn >> 12) & 0xf;
23438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        rd1 = (insn >> 0) & 0xf;
23448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (rd0 == 0xf || rd1 == 0xf)
23458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 1;
23468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_movq_M0_wRn(wrd);
23475285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tmp = load_reg(s, rd0);
23485285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tmp2 = load_reg(s, rd1);
23498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        switch ((insn >> 16) & 0xf) {
23508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0x0:					/* TMIA */
23515285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            gen_helper_iwmmxt_muladdsl(cpu_M0, cpu_M0, tmp, tmp2);
23528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
23538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0x8:					/* TMIAPH */
23545285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            gen_helper_iwmmxt_muladdsw(cpu_M0, cpu_M0, tmp, tmp2);
23558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
23568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0xc: case 0xd: case 0xe: case 0xf:		/* TMIAxy */
23578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (insn & (1 << 16))
23585285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_gen_shri_i32(tmp, tmp, 16);
23598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (insn & (1 << 17))
23605285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_gen_shri_i32(tmp2, tmp2, 16);
23615285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            gen_helper_iwmmxt_muladdswl(cpu_M0, cpu_M0, tmp, tmp2);
23628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
23638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        default:
23645285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tcg_temp_free_i32(tmp2);
23655285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tcg_temp_free_i32(tmp);
23668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 1;
23678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
23685285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tcg_temp_free_i32(tmp2);
23695285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tcg_temp_free_i32(tmp);
23708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_movq_wRn_M0(wrd);
23718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_set_mup();
23728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
23738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    default:
23748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return 1;
23758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
23768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
23778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
23788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
23798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
23805285864985be9077e58e42235af6582dee72e841David 'Digit' Turner/* Disassemble an XScale DSP instruction.  Returns nonzero if an error occurred
23818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   (ie. an undefined instruction).  */
23828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int disas_dsp_insn(CPUState *env, DisasContext *s, uint32_t insn)
23838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
23848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int acc, rd0, rd1, rdhi, rdlo;
23855285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    TCGv tmp, tmp2;
23868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
23878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if ((insn & 0x0ff00f10) == 0x0e200010) {
23888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* Multiply with Internal Accumulate Format */
23898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        rd0 = (insn >> 12) & 0xf;
23908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        rd1 = insn & 0xf;
23918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        acc = (insn >> 5) & 7;
23928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
23938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (acc != 0)
23948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 1;
23958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
23965285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tmp = load_reg(s, rd0);
23975285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tmp2 = load_reg(s, rd1);
23988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        switch ((insn >> 16) & 0xf) {
23998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0x0:					/* MIA */
24005285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            gen_helper_iwmmxt_muladdsl(cpu_M0, cpu_M0, tmp, tmp2);
24018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
24028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0x8:					/* MIAPH */
24035285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            gen_helper_iwmmxt_muladdsw(cpu_M0, cpu_M0, tmp, tmp2);
24048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
24058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0xc:					/* MIABB */
24068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0xd:					/* MIABT */
24078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0xe:					/* MIATB */
24088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0xf:					/* MIATT */
24098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (insn & (1 << 16))
24105285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_gen_shri_i32(tmp, tmp, 16);
24118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (insn & (1 << 17))
24125285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_gen_shri_i32(tmp2, tmp2, 16);
24135285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            gen_helper_iwmmxt_muladdswl(cpu_M0, cpu_M0, tmp, tmp2);
24148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
24158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        default:
24168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 1;
24178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
24185285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tcg_temp_free_i32(tmp2);
24195285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tcg_temp_free_i32(tmp);
24208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
24218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_op_iwmmxt_movq_wRn_M0(acc);
24228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return 0;
24238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
24248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
24258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if ((insn & 0x0fe00ff8) == 0x0c400000) {
24268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* Internal Accumulator Access Format */
24278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        rdhi = (insn >> 16) & 0xf;
24288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        rdlo = (insn >> 12) & 0xf;
24298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        acc = insn & 7;
24308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
24318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (acc != 0)
24328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 1;
24338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
24348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (insn & ARM_CP_RW_BIT) {			/* MRA */
24355285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            iwmmxt_load_reg(cpu_V0, acc);
24365285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tcg_gen_trunc_i64_i32(cpu_R[rdlo], cpu_V0);
24375285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tcg_gen_shri_i64(cpu_V0, cpu_V0, 32);
24385285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tcg_gen_trunc_i64_i32(cpu_R[rdhi], cpu_V0);
24395285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tcg_gen_andi_i32(cpu_R[rdhi], cpu_R[rdhi], (1 << (40 - 32)) - 1);
24408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        } else {					/* MAR */
24415285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tcg_gen_concat_i32_i64(cpu_V0, cpu_R[rdlo], cpu_R[rdhi]);
24425285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            iwmmxt_store_reg(cpu_V0, acc);
24438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
24448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return 0;
24458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
24468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
24478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 1;
24488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
24498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
24508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Disassemble system coprocessor instruction.  Return nonzero if
24518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   instruction is not defined.  */
24528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int disas_cp_insn(CPUState *env, DisasContext *s, uint32_t insn)
24538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
24545285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    TCGv tmp, tmp2;
24558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    uint32_t rd = (insn >> 12) & 0xf;
24568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    uint32_t cp = (insn >> 8) & 0xf;
24578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
24588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (insn & ARM_CP_RW_BIT) {
24598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (!env->cp[cp].cp_read)
24608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 1;
24618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_set_pc_im(s->pc);
24625285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tmp = tcg_temp_new_i32();
24635285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tmp2 = tcg_const_i32(insn);
24645285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        gen_helper_get_cp(tmp, cpu_env, tmp2);
24655285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tcg_temp_free(tmp2);
24668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        store_reg(s, rd, tmp);
24678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } else {
24688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (!env->cp[cp].cp_write)
24698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 1;
24708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_set_pc_im(s->pc);
24718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tmp = load_reg(s, rd);
24725285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tmp2 = tcg_const_i32(insn);
24735285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        gen_helper_set_cp(cpu_env, tmp2, tmp);
24745285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tcg_temp_free(tmp2);
24755285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tcg_temp_free_i32(tmp);
24768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
24778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
24788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
24798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
24808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int cp15_user_ok(uint32_t insn)
24818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
24828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int cpn = (insn >> 16) & 0xf;
24838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int cpm = insn & 0xf;
24848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int op = ((insn >> 5) & 7) | ((insn >> 18) & 0x38);
24858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
24868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (cpn == 13 && cpm == 0) {
24878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* TLS register.  */
24888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (op == 2 || (op == 3 && (insn & ARM_CP_RW_BIT)))
24898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 1;
24908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
24918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (cpn == 7) {
24928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* ISB, DSB, DMB.  */
24938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if ((cpm == 5 && op == 4)
24948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                || (cpm == 10 && (op == 4 || op == 5)))
24958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 1;
24968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
24978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
24988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
24998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
25005285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic int cp15_tls_load_store(CPUState *env, DisasContext *s, uint32_t insn, uint32_t rd)
25015285864985be9077e58e42235af6582dee72e841David 'Digit' Turner{
25025285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    TCGv tmp;
25035285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    int cpn = (insn >> 16) & 0xf;
25045285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    int cpm = insn & 0xf;
25055285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    int op = ((insn >> 5) & 7) | ((insn >> 18) & 0x38);
25065285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
25075285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    if (!arm_feature(env, ARM_FEATURE_V6K))
25085285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        return 0;
25095285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
25105285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    if (!(cpn == 13 && cpm == 0))
25115285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        return 0;
25125285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
25135285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    if (insn & ARM_CP_RW_BIT) {
25145285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        switch (op) {
25155285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        case 2:
25165285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tmp = load_cpu_field(cp15.c13_tls1);
25175285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            break;
25185285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        case 3:
25195285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tmp = load_cpu_field(cp15.c13_tls2);
25205285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            break;
25215285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        case 4:
25225285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tmp = load_cpu_field(cp15.c13_tls3);
25235285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            break;
25245285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        default:
25255285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            return 0;
25265285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        }
25275285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        store_reg(s, rd, tmp);
25285285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
25295285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    } else {
25305285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tmp = load_reg(s, rd);
25315285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        switch (op) {
25325285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        case 2:
25335285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            store_cpu_field(tmp, cp15.c13_tls1);
25345285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            break;
25355285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        case 3:
25365285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            store_cpu_field(tmp, cp15.c13_tls2);
25375285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            break;
25385285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        case 4:
25395285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            store_cpu_field(tmp, cp15.c13_tls3);
25405285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            break;
25415285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        default:
25425285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tcg_temp_free_i32(tmp);
25435285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            return 0;
25445285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        }
25455285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    }
25465285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    return 1;
25475285864985be9077e58e42235af6582dee72e841David 'Digit' Turner}
25485285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
25498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Disassemble system coprocessor (cp15) instruction.  Return nonzero if
25508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   instruction is not defined.  */
25518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int disas_cp15_insn(CPUState *env, DisasContext *s, uint32_t insn)
25528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
25538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    uint32_t rd;
25545285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    TCGv tmp, tmp2;
25558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
25568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* M profile cores use memory mapped registers instead of cp15.  */
25578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (arm_feature(env, ARM_FEATURE_M))
25588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	return 1;
25598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
25608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if ((insn & (1 << 25)) == 0) {
25618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (insn & (1 << 20)) {
25628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* mrrc */
25638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 1;
25648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
25658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* mcrr.  Used for block cache operations, so implement as no-op.  */
25668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return 0;
25678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
25688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if ((insn & (1 << 4)) == 0) {
25698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* cdp */
25708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return 1;
25718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
25728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (IS_USER(s) && !cp15_user_ok(insn)) {
25738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return 1;
25748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
25755285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
25765285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    /* Pre-v7 versions of the architecture implemented WFI via coprocessor
25775285864985be9077e58e42235af6582dee72e841David 'Digit' Turner     * instructions rather than a separate instruction.
25785285864985be9077e58e42235af6582dee72e841David 'Digit' Turner     */
25795285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    if ((insn & 0x0fff0fff) == 0x0e070f90) {
25805285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        /* 0,c7,c0,4: Standard v6 WFI (also used in some pre-v6 cores).
25815285864985be9077e58e42235af6582dee72e841David 'Digit' Turner         * In v7, this must NOP.
25825285864985be9077e58e42235af6582dee72e841David 'Digit' Turner         */
25835285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        if (!arm_feature(env, ARM_FEATURE_V7)) {
25845285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            /* Wait for interrupt.  */
25855285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            gen_set_pc_im(s->pc);
25865285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            s->is_jmp = DISAS_WFI;
25875285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        }
25888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return 0;
25898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
25905285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
25915285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    if ((insn & 0x0fff0fff) == 0x0e070f58) {
25925285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        /* 0,c7,c8,2: Not all pre-v6 cores implemented this WFI,
25935285864985be9077e58e42235af6582dee72e841David 'Digit' Turner         * so this is slightly over-broad.
25945285864985be9077e58e42235af6582dee72e841David 'Digit' Turner         */
25955285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        if (!arm_feature(env, ARM_FEATURE_V6)) {
25965285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            /* Wait for interrupt.  */
25975285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            gen_set_pc_im(s->pc);
25985285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            s->is_jmp = DISAS_WFI;
25995285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            return 0;
26005285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        }
26015285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        /* Otherwise fall through to handle via helper function.
26025285864985be9077e58e42235af6582dee72e841David 'Digit' Turner         * In particular, on v7 and some v6 cores this is one of
26035285864985be9077e58e42235af6582dee72e841David 'Digit' Turner         * the VA-PA registers.
26045285864985be9077e58e42235af6582dee72e841David 'Digit' Turner         */
26055285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    }
26065285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
26078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    rd = (insn >> 12) & 0xf;
26085285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
26095285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    if (cp15_tls_load_store(env, s, insn, rd))
26105285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        return 0;
26115285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
26125285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tmp2 = tcg_const_i32(insn);
26138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (insn & ARM_CP_RW_BIT) {
26145285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tmp = tcg_temp_new_i32();
26155285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        gen_helper_get_cp15(tmp, cpu_env, tmp2);
26168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* If the destination register is r15 then sets condition codes.  */
26178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (rd != 15)
26188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            store_reg(s, rd, tmp);
26198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        else
26205285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tcg_temp_free_i32(tmp);
26218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } else {
26228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tmp = load_reg(s, rd);
26235285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        gen_helper_set_cp15(cpu_env, tmp2, tmp);
26245285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tcg_temp_free_i32(tmp);
26258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* Normally we would always end the TB here, but Linux
26268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         * arch/arm/mach-pxa/sleep.S expects two instructions following
26278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         * an MMU enable to execute from cache.  Imitate this behaviour.  */
26288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (!arm_feature(env, ARM_FEATURE_XSCALE) ||
26298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                (insn & 0x0fff0fff) != 0x0e010f10)
26308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            gen_lookup_tb(s);
26318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
26325285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_temp_free_i32(tmp2);
26338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
26348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
26358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
26368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define VFP_REG_SHR(x, n) (((n) > 0) ? (x) >> (n) : (x) << -(n))
26378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define VFP_SREG(insn, bigbit, smallbit) \
26388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project  ((VFP_REG_SHR(insn, bigbit - 1) & 0x1e) | (((insn) >> (smallbit)) & 1))
26398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define VFP_DREG(reg, insn, bigbit, smallbit) do { \
26408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (arm_feature(env, ARM_FEATURE_VFP3)) { \
26418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        reg = (((insn) >> (bigbit)) & 0x0f) \
26428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project              | (((insn) >> ((smallbit) - 4)) & 0x10); \
26438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } else { \
26448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (insn & (1 << (smallbit))) \
26458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 1; \
26468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        reg = ((insn) >> (bigbit)) & 0x0f; \
26478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }} while (0)
26488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
26498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define VFP_SREG_D(insn) VFP_SREG(insn, 12, 22)
26508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define VFP_DREG_D(reg, insn) VFP_DREG(reg, insn, 12, 22)
26518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define VFP_SREG_N(insn) VFP_SREG(insn, 16,  7)
26528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define VFP_DREG_N(reg, insn) VFP_DREG(reg, insn, 16,  7)
26538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define VFP_SREG_M(insn) VFP_SREG(insn,  0,  5)
26548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define VFP_DREG_M(reg, insn) VFP_DREG(reg, insn,  0,  5)
26558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
26568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Move between integer and VFP cores.  */
26578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic TCGv gen_vfp_mrs(void)
26588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
26595285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    TCGv tmp = tcg_temp_new_i32();
26608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_gen_mov_i32(tmp, cpu_F0s);
26618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return tmp;
26628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
26638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
26648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void gen_vfp_msr(TCGv tmp)
26658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
26668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_gen_mov_i32(cpu_F0s, tmp);
26675285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_temp_free_i32(tmp);
26688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
26698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
26708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void gen_neon_dup_u8(TCGv var, int shift)
26718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
26725285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    TCGv tmp = tcg_temp_new_i32();
26738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (shift)
26748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tcg_gen_shri_i32(var, var, shift);
26758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_gen_ext8u_i32(var, var);
26768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_gen_shli_i32(tmp, var, 8);
26778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_gen_or_i32(var, var, tmp);
26788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_gen_shli_i32(tmp, var, 16);
26798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_gen_or_i32(var, var, tmp);
26805285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_temp_free_i32(tmp);
26818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
26828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
26838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void gen_neon_dup_low16(TCGv var)
26848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
26855285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    TCGv tmp = tcg_temp_new_i32();
26868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_gen_ext16u_i32(var, var);
26878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_gen_shli_i32(tmp, var, 16);
26888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_gen_or_i32(var, var, tmp);
26895285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_temp_free_i32(tmp);
26908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
26918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
26928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void gen_neon_dup_high16(TCGv var)
26938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
26945285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    TCGv tmp = tcg_temp_new_i32();
26958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_gen_andi_i32(var, var, 0xffff0000);
26968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_gen_shri_i32(tmp, var, 16);
26978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_gen_or_i32(var, var, tmp);
26985285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_temp_free_i32(tmp);
26995285864985be9077e58e42235af6582dee72e841David 'Digit' Turner}
27005285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
27015285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic TCGv gen_load_and_replicate(DisasContext *s, TCGv addr, int size)
27025285864985be9077e58e42235af6582dee72e841David 'Digit' Turner{
27035285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    /* Load a single Neon element and replicate into a 32 bit TCG reg */
27045285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    TCGv tmp;
27055285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    switch (size) {
27065285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    case 0:
27075285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tmp = gen_ld8u(addr, IS_USER(s));
27085285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        gen_neon_dup_u8(tmp, 0);
27095285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        break;
27105285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    case 1:
27115285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tmp = gen_ld16u(addr, IS_USER(s));
27125285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        gen_neon_dup_low16(tmp);
27135285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        break;
27145285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    case 2:
27155285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tmp = gen_ld32(addr, IS_USER(s));
27165285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        break;
27175285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    default: /* Avoid compiler warnings.  */
27185285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        abort();
27195285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    }
27205285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    return tmp;
27218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
27228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
27235285864985be9077e58e42235af6582dee72e841David 'Digit' Turner/* Disassemble a VFP instruction.  Returns nonzero if an error occurred
27248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   (ie. an undefined instruction).  */
27258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int disas_vfp_insn(CPUState * env, DisasContext *s, uint32_t insn)
27268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
27278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    uint32_t rd, rn, rm, op, i, n, offset, delta_d, delta_m, bank_mask;
27288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int dp, veclen;
27295285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    TCGv addr;
27308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    TCGv tmp;
27318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    TCGv tmp2;
27328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
27338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!arm_feature(env, ARM_FEATURE_VFP))
27348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return 1;
27358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
27365285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    if (!s->vfp_enabled) {
27378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* VFP disabled.  Only allow fmxr/fmrx to/from some control regs.  */
27388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if ((insn & 0x0fe00fff) != 0x0ee00a10)
27398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 1;
27408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        rn = (insn >> 16) & 0xf;
27418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (rn != ARM_VFP_FPSID && rn != ARM_VFP_FPEXC
27428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            && rn != ARM_VFP_MVFR1 && rn != ARM_VFP_MVFR0)
27438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 1;
27448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
27458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    dp = ((insn & 0xf00) == 0xb00);
27468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    switch ((insn >> 24) & 0xf) {
27478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0xe:
27488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (insn & (1 << 4)) {
27498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* single register transfer */
27508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            rd = (insn >> 12) & 0xf;
27518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (dp) {
27528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                int size;
27538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                int pass;
27548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
27558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                VFP_DREG_N(rn, insn);
27568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (insn & 0xf)
27578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    return 1;
27588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (insn & 0x00c00060
27598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    && !arm_feature(env, ARM_FEATURE_NEON))
27608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    return 1;
27618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
27628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                pass = (insn >> 21) & 1;
27638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (insn & (1 << 22)) {
27648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    size = 0;
27658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    offset = ((insn >> 5) & 3) * 8;
27668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                } else if (insn & (1 << 5)) {
27678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    size = 1;
27688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    offset = (insn & (1 << 6)) ? 16 : 0;
27698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                } else {
27708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    size = 2;
27718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    offset = 0;
27728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
27738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (insn & ARM_CP_RW_BIT) {
27748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    /* vfp->arm */
27758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    tmp = neon_load_reg(rn, pass);
27768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    switch (size) {
27778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    case 0:
27788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        if (offset)
27798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            tcg_gen_shri_i32(tmp, tmp, offset);
27808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        if (insn & (1 << 23))
27818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            gen_uxtb(tmp);
27828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        else
27838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            gen_sxtb(tmp);
27848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        break;
27858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    case 1:
27868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        if (insn & (1 << 23)) {
27878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            if (offset) {
27888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                tcg_gen_shri_i32(tmp, tmp, 16);
27898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            } else {
27908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                gen_uxth(tmp);
27918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            }
27928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        } else {
27938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            if (offset) {
27948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                tcg_gen_sari_i32(tmp, tmp, 16);
27958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            } else {
27968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                gen_sxth(tmp);
27978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            }
27988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        }
27998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        break;
28008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    case 2:
28018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        break;
28028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
28038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    store_reg(s, rd, tmp);
28048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                } else {
28058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    /* arm->vfp */
28068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    tmp = load_reg(s, rd);
28078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if (insn & (1 << 23)) {
28088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        /* VDUP */
28098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        if (size == 0) {
28108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            gen_neon_dup_u8(tmp, 0);
28118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        } else if (size == 1) {
28128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            gen_neon_dup_low16(tmp);
28138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        }
28145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                        for (n = 0; n <= pass * 2; n++) {
28155285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            tmp2 = tcg_temp_new_i32();
28165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                            tcg_gen_mov_i32(tmp2, tmp);
28175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                            neon_store_reg(rn, n, tmp2);
28185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                        }
28195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                        neon_store_reg(rn, n, tmp);
28208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    } else {
28218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        /* VMOV */
28228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        switch (size) {
28238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        case 0:
28248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            tmp2 = neon_load_reg(rn, pass);
28258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            gen_bfi(tmp, tmp2, tmp, offset, 0xff);
28265285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            tcg_temp_free_i32(tmp2);
28278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            break;
28288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        case 1:
28298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            tmp2 = neon_load_reg(rn, pass);
28308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            gen_bfi(tmp, tmp2, tmp, offset, 0xffff);
28315285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            tcg_temp_free_i32(tmp2);
28328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            break;
28338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        case 2:
28348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            break;
28358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        }
28368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        neon_store_reg(rn, pass, tmp);
28378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
28388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
28398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            } else { /* !dp */
28408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if ((insn & 0x6f) != 0x00)
28418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    return 1;
28428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                rn = VFP_SREG_N(insn);
28438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (insn & ARM_CP_RW_BIT) {
28448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    /* vfp->arm */
28458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if (insn & (1 << 21)) {
28468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        /* system register */
28478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        rn >>= 1;
28488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
28498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        switch (rn) {
28508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        case ARM_VFP_FPSID:
28518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            /* VFP2 allows access to FSID from userspace.
28528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                               VFP3 restricts all id registers to privileged
28538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                               accesses.  */
28548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            if (IS_USER(s)
28558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                && arm_feature(env, ARM_FEATURE_VFP3))
28568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                return 1;
28578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            tmp = load_cpu_field(vfp.xregs[rn]);
28588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            break;
28598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        case ARM_VFP_FPEXC:
28608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            if (IS_USER(s))
28618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                return 1;
28628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            tmp = load_cpu_field(vfp.xregs[rn]);
28638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            break;
28648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        case ARM_VFP_FPINST:
28658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        case ARM_VFP_FPINST2:
28668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            /* Not present in VFP3.  */
28678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            if (IS_USER(s)
28688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                || arm_feature(env, ARM_FEATURE_VFP3))
28698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                return 1;
28708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            tmp = load_cpu_field(vfp.xregs[rn]);
28718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            break;
28728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        case ARM_VFP_FPSCR:
28738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            if (rd == 15) {
28748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                tmp = load_cpu_field(vfp.xregs[ARM_VFP_FPSCR]);
28758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                tcg_gen_andi_i32(tmp, tmp, 0xf0000000);
28768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            } else {
28775285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                                tmp = tcg_temp_new_i32();
28788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                gen_helper_vfp_get_fpscr(tmp, cpu_env);
28798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            }
28808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            break;
28818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        case ARM_VFP_MVFR0:
28828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        case ARM_VFP_MVFR1:
28838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            if (IS_USER(s)
28848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                || !arm_feature(env, ARM_FEATURE_VFP3))
28858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                return 1;
28868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            tmp = load_cpu_field(vfp.xregs[rn]);
28878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            break;
28888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        default:
28898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            return 1;
28908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        }
28918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    } else {
28928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        gen_mov_F0_vreg(0, rn);
28938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        tmp = gen_vfp_mrs();
28948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
28958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if (rd == 15) {
28968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        /* Set the 4 flag bits in the CPSR.  */
28978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        gen_set_nzcv(tmp);
28985285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tcg_temp_free_i32(tmp);
28998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    } else {
29008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        store_reg(s, rd, tmp);
29018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
29028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                } else {
29038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    /* arm->vfp */
29048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    tmp = load_reg(s, rd);
29058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if (insn & (1 << 21)) {
29068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        rn >>= 1;
29078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        /* system register */
29088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        switch (rn) {
29098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        case ARM_VFP_FPSID:
29108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        case ARM_VFP_MVFR0:
29118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        case ARM_VFP_MVFR1:
29128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            /* Writes are ignored.  */
29138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            break;
29148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        case ARM_VFP_FPSCR:
29158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            gen_helper_vfp_set_fpscr(cpu_env, tmp);
29165285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            tcg_temp_free_i32(tmp);
29178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            gen_lookup_tb(s);
29188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            break;
29198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        case ARM_VFP_FPEXC:
29208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            if (IS_USER(s))
29218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                return 1;
29225285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            /* TODO: VFP subarchitecture support.
29235285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                             * For now, keep the EN bit only */
29245285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            tcg_gen_andi_i32(tmp, tmp, 1 << 30);
29258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            store_cpu_field(tmp, vfp.xregs[rn]);
29268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            gen_lookup_tb(s);
29278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            break;
29288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        case ARM_VFP_FPINST:
29298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        case ARM_VFP_FPINST2:
29308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            store_cpu_field(tmp, vfp.xregs[rn]);
29318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            break;
29328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        default:
29338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            return 1;
29348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        }
29358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    } else {
29368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        gen_vfp_msr(tmp);
29378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        gen_mov_vreg_F0(0, rn);
29388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
29398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
29408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
29418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        } else {
29428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* data processing */
29438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* The opcode is in bits 23, 21, 20 and 6.  */
29448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            op = ((insn >> 20) & 8) | ((insn >> 19) & 6) | ((insn >> 6) & 1);
29458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (dp) {
29468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (op == 15) {
29478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    /* rn is opcode */
29488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    rn = ((insn >> 15) & 0x1e) | ((insn >> 7) & 1);
29498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                } else {
29508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    /* rn is register number */
29518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    VFP_DREG_N(rn, insn);
29528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
29538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
29545285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                if (op == 15 && (rn == 15 || ((rn & 0x1c) == 0x18))) {
29558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    /* Integer or single precision destination.  */
29568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    rd = VFP_SREG_D(insn);
29578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                } else {
29588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    VFP_DREG_D(rd, insn);
29598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
29605285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                if (op == 15 &&
29615285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    (((rn & 0x1c) == 0x10) || ((rn & 0x14) == 0x14))) {
29625285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    /* VCVT from int is always from S reg regardless of dp bit.
29635285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                     * VCVT with immediate frac_bits has same format as SREG_M
29645285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                     */
29655285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    rm = VFP_SREG_M(insn);
29668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                } else {
29678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    VFP_DREG_M(rm, insn);
29688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
29698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            } else {
29708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                rn = VFP_SREG_N(insn);
29718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (op == 15 && rn == 15) {
29728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    /* Double precision destination.  */
29738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    VFP_DREG_D(rd, insn);
29748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                } else {
29758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    rd = VFP_SREG_D(insn);
29768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
29775285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                /* NB that we implicitly rely on the encoding for the frac_bits
29785285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                 * in VCVT of fixed to float being the same as that of an SREG_M
29795285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                 */
29808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                rm = VFP_SREG_M(insn);
29818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
29828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
29835285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            veclen = s->vec_len;
29848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (op == 15 && rn > 3)
29858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                veclen = 0;
29868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
29878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* Shut up compiler warnings.  */
29888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            delta_m = 0;
29898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            delta_d = 0;
29908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            bank_mask = 0;
29918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
29928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (veclen > 0) {
29938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (dp)
29948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    bank_mask = 0xc;
29958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                else
29968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    bank_mask = 0x18;
29978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
29988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* Figure out what type of vector operation this is.  */
29998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if ((rd & bank_mask) == 0) {
30008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    /* scalar */
30018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    veclen = 0;
30028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                } else {
30038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if (dp)
30045285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        delta_d = (s->vec_stride >> 1) + 1;
30058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    else
30065285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        delta_d = s->vec_stride + 1;
30078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
30088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if ((rm & bank_mask) == 0) {
30098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        /* mixed scalar/vector */
30108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        delta_m = 0;
30118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    } else {
30128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        /* vector */
30138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        delta_m = delta_d;
30148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
30158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
30168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
30178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
30188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* Load the initial operands.  */
30198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (op == 15) {
30208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                switch (rn) {
30218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                case 16:
30228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                case 17:
30238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    /* Integer source */
30248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    gen_mov_F0_vreg(0, rm);
30258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    break;
30268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                case 8:
30278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                case 9:
30288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    /* Compare */
30298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    gen_mov_F0_vreg(dp, rd);
30308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    gen_mov_F1_vreg(dp, rm);
30318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    break;
30328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                case 10:
30338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                case 11:
30348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    /* Compare with zero */
30358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    gen_mov_F0_vreg(dp, rd);
30368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    gen_vfp_F1_ld0(dp);
30378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    break;
30388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                case 20:
30398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                case 21:
30408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                case 22:
30418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                case 23:
30425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                case 28:
30435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                case 29:
30445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                case 30:
30455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                case 31:
30468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    /* Source and destination the same.  */
30478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    gen_mov_F0_vreg(dp, rd);
30488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    break;
30498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                default:
30508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    /* One source operand.  */
30518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    gen_mov_F0_vreg(dp, rm);
30528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    break;
30538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
30548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            } else {
30558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* Two source operands.  */
30568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                gen_mov_F0_vreg(dp, rn);
30578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                gen_mov_F1_vreg(dp, rm);
30588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
30598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
30608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            for (;;) {
30618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* Perform the calculation.  */
30628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                switch (op) {
30635285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                case 0: /* VMLA: fd + (fn * fm) */
30645285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    /* Note that order of inputs to the add matters for NaNs */
30655285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    gen_vfp_F1_mul(dp);
30665285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    gen_mov_F0_vreg(dp, rd);
30678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    gen_vfp_add(dp);
30688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    break;
30695285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                case 1: /* VMLS: fd + -(fn * fm) */
30708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    gen_vfp_mul(dp);
30715285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    gen_vfp_F1_neg(dp);
30725285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    gen_mov_F0_vreg(dp, rd);
30738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    gen_vfp_add(dp);
30748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    break;
30755285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                case 2: /* VNMLS: -fd + (fn * fm) */
30765285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    /* Note that it isn't valid to replace (-A + B) with (B - A)
30775285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                     * or similar plausible looking simplifications
30785285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                     * because this will give wrong results for NaNs.
30795285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                     */
30805285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    gen_vfp_F1_mul(dp);
30815285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    gen_mov_F0_vreg(dp, rd);
30825285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    gen_vfp_neg(dp);
30835285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    gen_vfp_add(dp);
30848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    break;
30855285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                case 3: /* VNMLA: -fd + -(fn * fm) */
30868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    gen_vfp_mul(dp);
30875285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    gen_vfp_F1_neg(dp);
30885285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    gen_mov_F0_vreg(dp, rd);
30898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    gen_vfp_neg(dp);
30905285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    gen_vfp_add(dp);
30918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    break;
30928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                case 4: /* mul: fn * fm */
30938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    gen_vfp_mul(dp);
30948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    break;
30958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                case 5: /* nmul: -(fn * fm) */
30968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    gen_vfp_mul(dp);
30978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    gen_vfp_neg(dp);
30988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    break;
30998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                case 6: /* add: fn + fm */
31008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    gen_vfp_add(dp);
31018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    break;
31028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                case 7: /* sub: fn - fm */
31038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    gen_vfp_sub(dp);
31048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    break;
31058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                case 8: /* div: fn / fm */
31068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    gen_vfp_div(dp);
31078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    break;
31088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                case 14: /* fconst */
31098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if (!arm_feature(env, ARM_FEATURE_VFP3))
31108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                      return 1;
31118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
31128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    n = (insn << 12) & 0x80000000;
31138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    i = ((insn >> 12) & 0x70) | (insn & 0xf);
31148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if (dp) {
31158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        if (i & 0x40)
31168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            i |= 0x3f80;
31178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        else
31188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            i |= 0x4000;
31198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        n |= i << 16;
31208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        tcg_gen_movi_i64(cpu_F0d, ((uint64_t)n) << 32);
31218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    } else {
31228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        if (i & 0x40)
31238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            i |= 0x780;
31248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        else
31258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            i |= 0x800;
31268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        n |= i << 19;
31278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        tcg_gen_movi_i32(cpu_F0s, n);
31288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
31298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    break;
31308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                case 15: /* extension space */
31318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    switch (rn) {
31328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    case 0: /* cpy */
31338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        /* no-op */
31348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        break;
31358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    case 1: /* abs */
31368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        gen_vfp_abs(dp);
31378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        break;
31388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    case 2: /* neg */
31398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        gen_vfp_neg(dp);
31408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        break;
31418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    case 3: /* sqrt */
31428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        gen_vfp_sqrt(dp);
31438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        break;
31445285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    case 4: /* vcvtb.f32.f16 */
31455285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        if (!arm_feature(env, ARM_FEATURE_VFP_FP16))
31465285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                          return 1;
31475285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tmp = gen_vfp_mrs();
31485285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tcg_gen_ext16u_i32(tmp, tmp);
31495285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s, tmp, cpu_env);
31505285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tcg_temp_free_i32(tmp);
31515285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        break;
31525285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    case 5: /* vcvtt.f32.f16 */
31535285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        if (!arm_feature(env, ARM_FEATURE_VFP_FP16))
31545285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                          return 1;
31555285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tmp = gen_vfp_mrs();
31565285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tcg_gen_shri_i32(tmp, tmp, 16);
31575285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s, tmp, cpu_env);
31585285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tcg_temp_free_i32(tmp);
31595285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        break;
31605285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    case 6: /* vcvtb.f16.f32 */
31615285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        if (!arm_feature(env, ARM_FEATURE_VFP_FP16))
31625285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                          return 1;
31635285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tmp = tcg_temp_new_i32();
31645285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        gen_helper_vfp_fcvt_f32_to_f16(tmp, cpu_F0s, cpu_env);
31655285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        gen_mov_F0_vreg(0, rd);
31665285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tmp2 = gen_vfp_mrs();
31675285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tcg_gen_andi_i32(tmp2, tmp2, 0xffff0000);
31685285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tcg_gen_or_i32(tmp, tmp, tmp2);
31695285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tcg_temp_free_i32(tmp2);
31705285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        gen_vfp_msr(tmp);
31715285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        break;
31725285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    case 7: /* vcvtt.f16.f32 */
31735285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        if (!arm_feature(env, ARM_FEATURE_VFP_FP16))
31745285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                          return 1;
31755285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tmp = tcg_temp_new_i32();
31765285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        gen_helper_vfp_fcvt_f32_to_f16(tmp, cpu_F0s, cpu_env);
31775285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tcg_gen_shli_i32(tmp, tmp, 16);
31785285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        gen_mov_F0_vreg(0, rd);
31795285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tmp2 = gen_vfp_mrs();
31805285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tcg_gen_ext16u_i32(tmp2, tmp2);
31815285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tcg_gen_or_i32(tmp, tmp, tmp2);
31825285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tcg_temp_free_i32(tmp2);
31835285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        gen_vfp_msr(tmp);
31845285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        break;
31858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    case 8: /* cmp */
31868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        gen_vfp_cmp(dp);
31878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        break;
31888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    case 9: /* cmpe */
31898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        gen_vfp_cmpe(dp);
31908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        break;
31918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    case 10: /* cmpz */
31928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        gen_vfp_cmp(dp);
31938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        break;
31948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    case 11: /* cmpez */
31958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        gen_vfp_F1_ld0(dp);
31968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        gen_vfp_cmpe(dp);
31978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        break;
31988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    case 15: /* single<->double conversion */
31998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        if (dp)
32008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            gen_helper_vfp_fcvtsd(cpu_F0s, cpu_F0d, cpu_env);
32018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        else
32028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            gen_helper_vfp_fcvtds(cpu_F0d, cpu_F0s, cpu_env);
32038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        break;
32048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    case 16: /* fuito */
32055285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        gen_vfp_uito(dp, 0);
32068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        break;
32078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    case 17: /* fsito */
32085285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        gen_vfp_sito(dp, 0);
32098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        break;
32108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    case 20: /* fshto */
32118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        if (!arm_feature(env, ARM_FEATURE_VFP3))
32128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                          return 1;
32135285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        gen_vfp_shto(dp, 16 - rm, 0);
32148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        break;
32158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    case 21: /* fslto */
32168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        if (!arm_feature(env, ARM_FEATURE_VFP3))
32178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                          return 1;
32185285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        gen_vfp_slto(dp, 32 - rm, 0);
32198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        break;
32208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    case 22: /* fuhto */
32218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        if (!arm_feature(env, ARM_FEATURE_VFP3))
32228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                          return 1;
32235285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        gen_vfp_uhto(dp, 16 - rm, 0);
32248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        break;
32258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    case 23: /* fulto */
32268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        if (!arm_feature(env, ARM_FEATURE_VFP3))
32278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                          return 1;
32285285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        gen_vfp_ulto(dp, 32 - rm, 0);
32298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        break;
32308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    case 24: /* ftoui */
32315285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        gen_vfp_toui(dp, 0);
32328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        break;
32338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    case 25: /* ftouiz */
32345285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        gen_vfp_touiz(dp, 0);
32358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        break;
32368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    case 26: /* ftosi */
32375285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        gen_vfp_tosi(dp, 0);
32388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        break;
32398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    case 27: /* ftosiz */
32405285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        gen_vfp_tosiz(dp, 0);
32418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        break;
32428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    case 28: /* ftosh */
32438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        if (!arm_feature(env, ARM_FEATURE_VFP3))
32448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                          return 1;
32455285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        gen_vfp_tosh(dp, 16 - rm, 0);
32468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        break;
32478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    case 29: /* ftosl */
32488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        if (!arm_feature(env, ARM_FEATURE_VFP3))
32498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                          return 1;
32505285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        gen_vfp_tosl(dp, 32 - rm, 0);
32518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        break;
32528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    case 30: /* ftouh */
32538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        if (!arm_feature(env, ARM_FEATURE_VFP3))
32548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                          return 1;
32555285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        gen_vfp_touh(dp, 16 - rm, 0);
32568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        break;
32578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    case 31: /* ftoul */
32588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        if (!arm_feature(env, ARM_FEATURE_VFP3))
32598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                          return 1;
32605285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        gen_vfp_toul(dp, 32 - rm, 0);
32618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        break;
32628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    default: /* undefined */
32638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        printf ("rn:%d\n", rn);
32648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        return 1;
32658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
32668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    break;
32678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                default: /* undefined */
32688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    printf ("op:%d\n", op);
32698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    return 1;
32708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
32718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
32728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* Write back the result.  */
32738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (op == 15 && (rn >= 8 && rn <= 11))
32748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    ; /* Comparison, do nothing.  */
32755285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                else if (op == 15 && dp && ((rn & 0x1c) == 0x18))
32765285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    /* VCVT double to int: always integer result. */
32778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    gen_mov_vreg_F0(0, rd);
32788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                else if (op == 15 && rn == 15)
32798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    /* conversion */
32808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    gen_mov_vreg_F0(!dp, rd);
32818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                else
32828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    gen_mov_vreg_F0(dp, rd);
32838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
32848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* break out of the loop if we have finished  */
32858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (veclen == 0)
32868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    break;
32878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
32888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (op == 15 && delta_m == 0) {
32898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    /* single source one-many */
32908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    while (veclen--) {
32918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        rd = ((rd + delta_d) & (bank_mask - 1))
32928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                             | (rd & bank_mask);
32938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        gen_mov_vreg_F0(dp, rd);
32948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
32958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    break;
32968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
32978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* Setup the next operands.  */
32988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                veclen--;
32998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                rd = ((rd + delta_d) & (bank_mask - 1))
33008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                     | (rd & bank_mask);
33018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
33028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (op == 15) {
33038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    /* One source operand.  */
33048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    rm = ((rm + delta_m) & (bank_mask - 1))
33058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                         | (rm & bank_mask);
33068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    gen_mov_F0_vreg(dp, rm);
33078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                } else {
33088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    /* Two source operands.  */
33098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    rn = ((rn + delta_d) & (bank_mask - 1))
33108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                         | (rn & bank_mask);
33118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    gen_mov_F0_vreg(dp, rn);
33128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if (delta_m) {
33138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        rm = ((rm + delta_m) & (bank_mask - 1))
33148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                             | (rm & bank_mask);
33158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        gen_mov_F1_vreg(dp, rm);
33168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
33178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
33188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
33198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
33208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
33218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0xc:
33228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0xd:
33235285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        if ((insn & 0x03e00000) == 0x00400000) {
33248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* two-register transfer */
33258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            rn = (insn >> 16) & 0xf;
33268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            rd = (insn >> 12) & 0xf;
33278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (dp) {
33288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                VFP_DREG_M(rm, insn);
33298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            } else {
33308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                rm = VFP_SREG_M(insn);
33318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
33328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
33338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (insn & ARM_CP_RW_BIT) {
33348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* vfp->arm */
33358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (dp) {
33368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    gen_mov_F0_vreg(0, rm * 2);
33378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    tmp = gen_vfp_mrs();
33388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    store_reg(s, rd, tmp);
33398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    gen_mov_F0_vreg(0, rm * 2 + 1);
33408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    tmp = gen_vfp_mrs();
33418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    store_reg(s, rn, tmp);
33428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                } else {
33438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    gen_mov_F0_vreg(0, rm);
33448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    tmp = gen_vfp_mrs();
33455285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    store_reg(s, rd, tmp);
33468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    gen_mov_F0_vreg(0, rm + 1);
33478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    tmp = gen_vfp_mrs();
33485285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    store_reg(s, rn, tmp);
33498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
33508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            } else {
33518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* arm->vfp */
33528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (dp) {
33538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    tmp = load_reg(s, rd);
33548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    gen_vfp_msr(tmp);
33558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    gen_mov_vreg_F0(0, rm * 2);
33568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    tmp = load_reg(s, rn);
33578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    gen_vfp_msr(tmp);
33588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    gen_mov_vreg_F0(0, rm * 2 + 1);
33598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                } else {
33605285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tmp = load_reg(s, rd);
33618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    gen_vfp_msr(tmp);
33628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    gen_mov_vreg_F0(0, rm);
33635285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tmp = load_reg(s, rn);
33648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    gen_vfp_msr(tmp);
33658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    gen_mov_vreg_F0(0, rm + 1);
33668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
33678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
33688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        } else {
33698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* Load/store */
33708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            rn = (insn >> 16) & 0xf;
33718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (dp)
33728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                VFP_DREG_D(rd, insn);
33738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            else
33748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                rd = VFP_SREG_D(insn);
33758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (s->thumb && rn == 15) {
33765285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                addr = tcg_temp_new_i32();
33775285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_gen_movi_i32(addr, s->pc & ~2);
33788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            } else {
33795285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                addr = load_reg(s, rn);
33808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
33818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if ((insn & 0x01200000) == 0x01000000) {
33828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* Single load/store */
33838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                offset = (insn & 0xff) << 2;
33848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if ((insn & (1 << 23)) == 0)
33858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    offset = -offset;
33865285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_gen_addi_i32(addr, addr, offset);
33878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (insn & (1 << 20)) {
33885285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    gen_vfp_ld(s, dp, addr);
33898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    gen_mov_vreg_F0(dp, rd);
33908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                } else {
33918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    gen_mov_F0_vreg(dp, rd);
33925285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    gen_vfp_st(s, dp, addr);
33938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
33945285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_temp_free_i32(addr);
33958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            } else {
33968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* load/store multiple */
33978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (dp)
33988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    n = (insn >> 1) & 0x7f;
33998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                else
34008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    n = insn & 0xff;
34018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
34028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (insn & (1 << 24)) /* pre-decrement */
34035285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tcg_gen_addi_i32(addr, addr, -((insn & 0xff) << 2));
34048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
34058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (dp)
34068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    offset = 8;
34078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                else
34088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    offset = 4;
34095285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tmp = tcg_const_i32(offset);
34108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                for (i = 0; i < n; i++) {
34118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if (insn & ARM_CP_RW_BIT) {
34128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        /* load */
34135285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        gen_vfp_ld(s, dp, addr);
34148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        gen_mov_vreg_F0(dp, rd + i);
34158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    } else {
34168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        /* store */
34178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        gen_mov_F0_vreg(dp, rd + i);
34185285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        gen_vfp_st(s, dp, addr);
34198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
34205285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tcg_gen_add_i32(addr, addr, tmp);
34218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
34225285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_temp_free_i32(tmp);
34238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (insn & (1 << 21)) {
34248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    /* writeback */
34258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if (insn & (1 << 24))
34268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        offset = -offset * n;
34278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    else if (dp && (insn & 1))
34288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        offset = 4;
34298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    else
34308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        offset = 0;
34318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
34328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if (offset != 0)
34335285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tcg_gen_addi_i32(addr, addr, offset);
34345285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    store_reg(s, rn, addr);
34355285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                } else {
34365285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tcg_temp_free_i32(addr);
34378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
34388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
34398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
34408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
34418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    default:
34428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* Should never happen.  */
34438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return 1;
34448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
34458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
34468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
34478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
34488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline void gen_goto_tb(DisasContext *s, int n, uint32_t dest)
34498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
34508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    TranslationBlock *tb;
34518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
34528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tb = s->tb;
34538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)) {
34548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tcg_gen_goto_tb(n);
34558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_set_pc_im(dest);
34565285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tcg_gen_exit_tb((tcg_target_long)tb + n);
34578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } else {
34588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_set_pc_im(dest);
34598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tcg_gen_exit_tb(0);
34608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
34618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
34628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
34638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline void gen_jmp (DisasContext *s, uint32_t dest)
34648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
34658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (unlikely(s->singlestep_enabled)) {
34668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* An indirect jump so that we still trigger the debug exception.  */
34678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (s->thumb)
34688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            dest |= 1;
34698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_bx_im(s, dest);
34708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } else {
34718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_goto_tb(s, 0, dest);
34728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        s->is_jmp = DISAS_TB_JUMP;
34738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
34748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
34758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
34768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline void gen_mulxy(TCGv t0, TCGv t1, int x, int y)
34778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
34788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (x)
34798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tcg_gen_sari_i32(t0, t0, 16);
34808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    else
34818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_sxth(t0);
34828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (y)
34838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tcg_gen_sari_i32(t1, t1, 16);
34848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    else
34858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_sxth(t1);
34868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_gen_mul_i32(t0, t0, t1);
34878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
34888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
34898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Return the mask of PSR bits set by a MSR instruction.  */
34908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic uint32_t msr_mask(CPUState *env, DisasContext *s, int flags, int spsr) {
34918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    uint32_t mask;
34928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
34938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    mask = 0;
34948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (flags & (1 << 0))
34958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        mask |= 0xff;
34968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (flags & (1 << 1))
34978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        mask |= 0xff00;
34988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (flags & (1 << 2))
34998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        mask |= 0xff0000;
35008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (flags & (1 << 3))
35018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        mask |= 0xff000000;
35028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
35038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* Mask out undefined bits.  */
35048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    mask &= ~CPSR_RESERVED;
35055285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    if (!arm_feature(env, ARM_FEATURE_V4T))
35065285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        mask &= ~CPSR_T;
35075285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    if (!arm_feature(env, ARM_FEATURE_V5))
35085285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        mask &= ~CPSR_Q; /* V5TE in reality*/
35098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!arm_feature(env, ARM_FEATURE_V6))
35108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        mask &= ~(CPSR_E | CPSR_GE);
35118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!arm_feature(env, ARM_FEATURE_THUMB2))
35128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        mask &= ~CPSR_IT;
35138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* Mask out execution state bits.  */
35148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!spsr)
35158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        mask &= ~CPSR_EXEC;
35168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* Mask out privileged bits.  */
35178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (IS_USER(s))
35188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        mask &= CPSR_USER;
35198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return mask;
35208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
35218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
35225285864985be9077e58e42235af6582dee72e841David 'Digit' Turner/* Returns nonzero if access to the PSR is not permitted. Marks t0 as dead. */
35235285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic int gen_set_psr(DisasContext *s, uint32_t mask, int spsr, TCGv t0)
35248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
35258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    TCGv tmp;
35268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (spsr) {
35278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* ??? This is also undefined in system mode.  */
35288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (IS_USER(s))
35298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 1;
35308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
35318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tmp = load_cpu_field(spsr);
35328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tcg_gen_andi_i32(tmp, tmp, ~mask);
35335285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tcg_gen_andi_i32(t0, t0, mask);
35345285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tcg_gen_or_i32(tmp, tmp, t0);
35358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        store_cpu_field(tmp, spsr);
35368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } else {
35375285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        gen_set_cpsr(t0, mask);
35388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
35395285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_temp_free_i32(t0);
35408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    gen_lookup_tb(s);
35418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
35428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
35438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
35445285864985be9077e58e42235af6582dee72e841David 'Digit' Turner/* Returns nonzero if access to the PSR is not permitted.  */
35455285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic int gen_set_psr_im(DisasContext *s, uint32_t mask, int spsr, uint32_t val)
35465285864985be9077e58e42235af6582dee72e841David 'Digit' Turner{
35475285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    TCGv tmp;
35485285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tmp = tcg_temp_new_i32();
35495285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_gen_movi_i32(tmp, val);
35505285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    return gen_set_psr(s, mask, spsr, tmp);
35515285864985be9077e58e42235af6582dee72e841David 'Digit' Turner}
35525285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
35535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner/* Generate an old-style exception return. Marks pc as dead. */
35545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void gen_exception_return(DisasContext *s, TCGv pc)
35558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
35568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    TCGv tmp;
35575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    store_reg(s, 15, pc);
35588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tmp = load_cpu_field(spsr);
35598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    gen_set_cpsr(tmp, 0xffffffff);
35605285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_temp_free_i32(tmp);
35618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    s->is_jmp = DISAS_UPDATE;
35628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
35638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
35648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Generate a v6 exception return.  Marks both values as dead.  */
35658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void gen_rfe(DisasContext *s, TCGv pc, TCGv cpsr)
35668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
35678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    gen_set_cpsr(cpsr, 0xffffffff);
35685285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_temp_free_i32(cpsr);
35698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    store_reg(s, 15, pc);
35708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    s->is_jmp = DISAS_UPDATE;
35718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
35728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
35738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline void
35748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectgen_set_condexec (DisasContext *s)
35758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
3576a1204591a52bf668ee72c86f98f53189621572a2Vladimir Chtchetkine    if (s->condexec_mask) {
3577a1204591a52bf668ee72c86f98f53189621572a2Vladimir Chtchetkine        uint32_t val = (s->condexec_cond << 4) | (s->condexec_mask >> 1);
35785285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        TCGv tmp = tcg_temp_new_i32();
3579a1204591a52bf668ee72c86f98f53189621572a2Vladimir Chtchetkine        tcg_gen_movi_i32(tmp, val);
3580a1204591a52bf668ee72c86f98f53189621572a2Vladimir Chtchetkine        store_cpu_field(tmp, condexec_bits);
3581a1204591a52bf668ee72c86f98f53189621572a2Vladimir Chtchetkine    }
35825285864985be9077e58e42235af6582dee72e841David 'Digit' Turner}
35835285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
35845285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic void gen_exception_insn(DisasContext *s, int offset, int excp)
35855285864985be9077e58e42235af6582dee72e841David 'Digit' Turner{
35865285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    gen_set_condexec(s);
35875285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    gen_set_pc_im(s->pc - offset);
35885285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    gen_exception(excp);
35895285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    s->is_jmp = DISAS_JUMP;
35908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
35918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
35928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void gen_nop_hint(DisasContext *s, int val)
35938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
35948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    switch (val) {
35958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 3: /* wfi */
35968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_set_pc_im(s->pc);
35978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        s->is_jmp = DISAS_WFI;
35988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
35998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 2: /* wfe */
36008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 4: /* sev */
36018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* TODO: Implement SEV and WFE.  May help SMP performance.  */
36028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    default: /* nop */
36038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
36048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
36058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
36068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
36078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define CPU_V001 cpu_V0, cpu_V0, cpu_V1
36088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
36095285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic inline void gen_neon_add(int size, TCGv t0, TCGv t1)
36108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
36118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    switch (size) {
36125285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    case 0: gen_helper_neon_add_u8(t0, t0, t1); break;
36135285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    case 1: gen_helper_neon_add_u16(t0, t0, t1); break;
36145285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    case 2: tcg_gen_add_i32(t0, t0, t1); break;
36155285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    default: abort();
36168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
36178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
36188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
36195285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic inline void gen_neon_rsb(int size, TCGv t0, TCGv t1)
36208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
36218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    switch (size) {
36225285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    case 0: gen_helper_neon_sub_u8(t0, t1, t0); break;
36235285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    case 1: gen_helper_neon_sub_u16(t0, t1, t0); break;
36245285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    case 2: tcg_gen_sub_i32(t0, t1, t0); break;
36258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    default: return;
36268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
36278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
36288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
36298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* 32-bit pairwise ops end up the same as the elementwise versions.  */
36308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define gen_helper_neon_pmax_s32  gen_helper_neon_max_s32
36318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define gen_helper_neon_pmax_u32  gen_helper_neon_max_u32
36328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define gen_helper_neon_pmin_s32  gen_helper_neon_min_s32
36338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define gen_helper_neon_pmin_u32  gen_helper_neon_min_u32
36348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
36358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define GEN_NEON_INTEGER_OP(name) do { \
36368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    switch ((size << 1) | u) { \
36378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0: \
36385285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        gen_helper_neon_##name##_s8(tmp, tmp, tmp2); \
36398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break; \
36408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 1: \
36415285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        gen_helper_neon_##name##_u8(tmp, tmp, tmp2); \
36428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break; \
36438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 2: \
36445285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        gen_helper_neon_##name##_s16(tmp, tmp, tmp2); \
36458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break; \
36468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 3: \
36475285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        gen_helper_neon_##name##_u16(tmp, tmp, tmp2); \
36488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break; \
36498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 4: \
36505285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        gen_helper_neon_##name##_s32(tmp, tmp, tmp2); \
36518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break; \
36528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 5: \
36535285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        gen_helper_neon_##name##_u32(tmp, tmp, tmp2); \
36548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break; \
36558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    default: return 1; \
36568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }} while (0)
36578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
36585285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic TCGv neon_load_scratch(int scratch)
36598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
36605285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    TCGv tmp = tcg_temp_new_i32();
36615285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_gen_ld_i32(tmp, cpu_env, offsetof(CPUARMState, vfp.scratch[scratch]));
36625285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    return tmp;
36638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
36648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
36655285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic void neon_store_scratch(int scratch, TCGv var)
36668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
36675285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_gen_st_i32(var, cpu_env, offsetof(CPUARMState, vfp.scratch[scratch]));
36685285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_temp_free_i32(var);
36698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
36708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
36715285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic inline TCGv neon_get_scalar(int size, int reg)
36728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
36735285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    TCGv tmp;
36745285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    if (size == 1) {
36755285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tmp = neon_load_reg(reg & 7, reg >> 4);
36765285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        if (reg & 8) {
36775285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            gen_neon_dup_high16(tmp);
36785285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        } else {
36795285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            gen_neon_dup_low16(tmp);
36805285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        }
36815285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    } else {
36825285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tmp = neon_load_reg(reg & 15, reg >> 4);
36835285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    }
36845285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    return tmp;
36858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
36868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
36875285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic int gen_neon_unzip(int rd, int rm, int size, int q)
36888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
36895285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    TCGv tmp, tmp2;
36905285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    if (!q && size == 2) {
36915285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        return 1;
36925285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    }
36935285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tmp = tcg_const_i32(rd);
36945285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tmp2 = tcg_const_i32(rm);
36955285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    if (q) {
36965285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        switch (size) {
36975285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        case 0:
36985285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            gen_helper_neon_qunzip8(tmp, tmp2);
36995285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            break;
37005285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        case 1:
37015285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            gen_helper_neon_qunzip16(tmp, tmp2);
37025285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            break;
37035285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        case 2:
37045285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            gen_helper_neon_qunzip32(tmp, tmp2);
37055285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            break;
37065285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        default:
37075285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            abort();
37085285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        }
37095285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    } else {
37105285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        switch (size) {
37115285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        case 0:
37125285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            gen_helper_neon_unzip8(tmp, tmp2);
37135285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            break;
37145285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        case 1:
37155285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            gen_helper_neon_unzip16(tmp, tmp2);
37165285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            break;
37175285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        default:
37185285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            abort();
37195285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        }
37205285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    }
37215285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_temp_free_i32(tmp);
37225285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_temp_free_i32(tmp2);
37235285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    return 0;
37248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
37258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
37265285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic int gen_neon_zip(int rd, int rm, int size, int q)
37278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
37285285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    TCGv tmp, tmp2;
37295285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    if (!q && size == 2) {
37305285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        return 1;
37315285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    }
37325285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tmp = tcg_const_i32(rd);
37335285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tmp2 = tcg_const_i32(rm);
37345285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    if (q) {
37355285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        switch (size) {
37365285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        case 0:
37375285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            gen_helper_neon_qzip8(tmp, tmp2);
37385285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            break;
37395285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        case 1:
37405285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            gen_helper_neon_qzip16(tmp, tmp2);
37415285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            break;
37425285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        case 2:
37435285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            gen_helper_neon_qzip32(tmp, tmp2);
37445285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            break;
37455285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        default:
37465285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            abort();
37475285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        }
37488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } else {
37495285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        switch (size) {
37505285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        case 0:
37515285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            gen_helper_neon_zip8(tmp, tmp2);
37525285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            break;
37535285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        case 1:
37545285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            gen_helper_neon_zip16(tmp, tmp2);
37555285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            break;
37565285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        default:
37575285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            abort();
37585285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        }
37598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
37605285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_temp_free_i32(tmp);
37615285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_temp_free_i32(tmp2);
37625285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    return 0;
37638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
37648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
37655285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic void gen_neon_trn_u8(TCGv t0, TCGv t1)
37668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
37675285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    TCGv rd, tmp;
37688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
37695285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    rd = tcg_temp_new_i32();
37705285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tmp = tcg_temp_new_i32();
37715285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
37725285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_gen_shli_i32(rd, t0, 8);
37735285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_gen_andi_i32(rd, rd, 0xff00ff00);
37745285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_gen_andi_i32(tmp, t1, 0x00ff00ff);
37755285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_gen_or_i32(rd, rd, tmp);
37765285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
37775285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_gen_shri_i32(t1, t1, 8);
37785285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_gen_andi_i32(t1, t1, 0x00ff00ff);
37795285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_gen_andi_i32(tmp, t0, 0xff00ff00);
37805285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_gen_or_i32(t1, t1, tmp);
37815285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_gen_mov_i32(t0, rd);
37825285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
37835285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_temp_free_i32(tmp);
37845285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_temp_free_i32(rd);
37858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
37868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
37875285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic void gen_neon_trn_u16(TCGv t0, TCGv t1)
37885285864985be9077e58e42235af6582dee72e841David 'Digit' Turner{
37895285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    TCGv rd, tmp;
37905285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
37915285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    rd = tcg_temp_new_i32();
37925285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tmp = tcg_temp_new_i32();
37935285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
37945285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_gen_shli_i32(rd, t0, 16);
37955285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_gen_andi_i32(tmp, t1, 0xffff);
37965285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_gen_or_i32(rd, rd, tmp);
37975285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_gen_shri_i32(t1, t1, 16);
37985285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_gen_andi_i32(tmp, t0, 0xffff0000);
37995285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_gen_or_i32(t1, t1, tmp);
38005285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_gen_mov_i32(t0, rd);
38015285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
38025285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_temp_free_i32(tmp);
38035285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_temp_free_i32(rd);
38045285864985be9077e58e42235af6582dee72e841David 'Digit' Turner}
38055285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
38065285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
38075285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic struct {
38085285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    int nregs;
38095285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    int interleave;
38105285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    int spacing;
38115285864985be9077e58e42235af6582dee72e841David 'Digit' Turner} neon_ls_element_type[11] = {
38125285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    {4, 4, 1},
38135285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    {4, 4, 2},
38148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    {4, 1, 1},
38158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    {4, 2, 1},
38168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    {3, 3, 1},
38178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    {3, 3, 2},
38188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    {3, 1, 1},
38198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    {1, 1, 1},
38208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    {2, 2, 1},
38218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    {2, 2, 2},
38228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    {2, 1, 1}
38238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project};
38248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
38258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Translate a NEON load/store element instruction.  Return nonzero if the
38268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   instruction is invalid.  */
38278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int disas_neon_ls_insn(CPUState * env, DisasContext *s, uint32_t insn)
38288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
38298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int rd, rn, rm;
38308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int op;
38318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int nregs;
38328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int interleave;
38335285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    int spacing;
38348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int stride;
38358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int size;
38368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int reg;
38378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int pass;
38388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int load;
38398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int shift;
38405285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    TCGv addr;
38418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    TCGv tmp;
38428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    TCGv tmp2;
38438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
38445285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    if (!s->vfp_enabled)
38458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      return 1;
38468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    VFP_DREG_D(rd, insn);
38478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    rn = (insn >> 16) & 0xf;
38488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    rm = insn & 0xf;
38498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    load = (insn & (1 << 21)) != 0;
38508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if ((insn & (1 << 23)) == 0) {
38518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* Load store all elements.  */
38528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        op = (insn >> 8) & 0xf;
38538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        size = (insn >> 6) & 3;
38545285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        if (op > 10)
38558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 1;
38565285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        /* Catch UNDEF cases for bad values of align field */
38575285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        switch (op & 0xc) {
38585285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        case 4:
38595285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            if (((insn >> 5) & 1) == 1) {
38605285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                return 1;
38615285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            }
38625285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            break;
38635285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        case 8:
38645285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            if (((insn >> 4) & 3) == 3) {
38655285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                return 1;
38665285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            }
38675285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            break;
38685285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        default:
38695285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            break;
38705285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        }
38718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        nregs = neon_ls_element_type[op].nregs;
38728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        interleave = neon_ls_element_type[op].interleave;
38735285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        spacing = neon_ls_element_type[op].spacing;
38745285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        if (size == 3 && (interleave | spacing) != 1) {
38755285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            return 1;
38768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
38775285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        addr = tcg_const_i32(insn);
38785285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        gen_helper_neon_vldst_all(addr);
38795285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tcg_temp_free_i32(addr);
38808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        stride = nregs * 8;
38818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } else {
38828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        size = (insn >> 10) & 3;
38838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (size == 3) {
38848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* Load single element to all lanes.  */
38855285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            int a = (insn >> 4) & 1;
38865285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            if (!load) {
38878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                return 1;
38885285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            }
38898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            size = (insn >> 6) & 3;
38908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            nregs = ((insn >> 8) & 3) + 1;
38915285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
38925285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            if (size == 3) {
38935285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                if (nregs != 4 || a == 0) {
38948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    return 1;
38958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
38965285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                /* For VLD4 size==3 a == 1 means 32 bits at 16 byte alignment */
38975285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                size = 2;
38985285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            }
38995285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            if (nregs == 1 && a == 1 && size == 0) {
39005285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                return 1;
39015285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            }
39025285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            if (nregs == 3 && a == 1) {
39035285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                return 1;
39045285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            }
39055285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            addr = tcg_temp_new_i32();
39065285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            load_reg_var(s, addr, rn);
39075285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            if (nregs == 1) {
39085285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                /* VLD1 to all lanes: bit 5 indicates how many Dregs to write */
39095285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tmp = gen_load_and_replicate(s, addr, size);
39105285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_gen_st_i32(tmp, cpu_env, neon_reg_offset(rd, 0));
39115285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_gen_st_i32(tmp, cpu_env, neon_reg_offset(rd, 1));
39125285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                if (insn & (1 << 5)) {
39135285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tcg_gen_st_i32(tmp, cpu_env, neon_reg_offset(rd + 1, 0));
39145285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tcg_gen_st_i32(tmp, cpu_env, neon_reg_offset(rd + 1, 1));
39155285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                }
39165285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_temp_free_i32(tmp);
39175285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            } else {
39185285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                /* VLD2/3/4 to all lanes: bit 5 indicates register stride */
39195285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                stride = (insn & (1 << 5)) ? 2 : 1;
39205285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                for (reg = 0; reg < nregs; reg++) {
39215285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tmp = gen_load_and_replicate(s, addr, size);
39225285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tcg_gen_st_i32(tmp, cpu_env, neon_reg_offset(rd, 0));
39235285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tcg_gen_st_i32(tmp, cpu_env, neon_reg_offset(rd, 1));
39245285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tcg_temp_free_i32(tmp);
39255285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tcg_gen_addi_i32(addr, addr, 1 << size);
39265285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    rd += stride;
39275285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                }
39288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
39295285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tcg_temp_free_i32(addr);
39308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            stride = (1 << size) * nregs;
39318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        } else {
39328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* Single element.  */
39335285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            int idx = (insn >> 4) & 0xf;
39348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            pass = (insn >> 7) & 1;
39358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            switch (size) {
39368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            case 0:
39378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                shift = ((insn >> 5) & 3) * 8;
39388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                stride = 1;
39398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                break;
39408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            case 1:
39418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                shift = ((insn >> 6) & 1) * 16;
39428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                stride = (insn & (1 << 5)) ? 2 : 1;
39438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                break;
39448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            case 2:
39458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                shift = 0;
39468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                stride = (insn & (1 << 6)) ? 2 : 1;
39478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                break;
39488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            default:
39498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                abort();
39508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
39518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            nregs = ((insn >> 8) & 3) + 1;
39525285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            /* Catch the UNDEF cases. This is unavoidably a bit messy. */
39535285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            switch (nregs) {
39545285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            case 1:
39555285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                if (((idx & (1 << size)) != 0) ||
39565285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    (size == 2 && ((idx & 3) == 1 || (idx & 3) == 2))) {
39575285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    return 1;
39585285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                }
39595285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                break;
39605285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            case 3:
39615285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                if ((idx & 1) != 0) {
39625285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    return 1;
39635285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                }
39645285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                /* fall through */
39655285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            case 2:
39665285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                if (size == 2 && (idx & 2) != 0) {
39675285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    return 1;
39685285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                }
39695285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                break;
39705285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            case 4:
39715285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                if ((size == 2) && ((idx & 3) == 3)) {
39725285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    return 1;
39735285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                }
39745285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                break;
39755285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            default:
39765285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                abort();
39775285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            }
39785285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            if ((rd + stride * (nregs - 1)) > 31) {
39795285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                /* Attempts to write off the end of the register file
39805285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                 * are UNPREDICTABLE; we choose to UNDEF because otherwise
39815285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                 * the neon_load_reg() would write off the end of the array.
39825285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                 */
39835285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                return 1;
39845285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            }
39855285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            addr = tcg_temp_new_i32();
39865285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            load_reg_var(s, addr, rn);
39878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            for (reg = 0; reg < nregs; reg++) {
39888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (load) {
39898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    switch (size) {
39908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    case 0:
39915285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tmp = gen_ld8u(addr, IS_USER(s));
39928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        break;
39938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    case 1:
39945285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tmp = gen_ld16u(addr, IS_USER(s));
39958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        break;
39968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    case 2:
39975285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tmp = gen_ld32(addr, IS_USER(s));
39988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        break;
39998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    default: /* Avoid compiler warnings.  */
40008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        abort();
40018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
40028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if (size != 2) {
40038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        tmp2 = neon_load_reg(rd, pass);
40048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        gen_bfi(tmp, tmp2, tmp, shift, size ? 0xffff : 0xff);
40055285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tcg_temp_free_i32(tmp2);
40068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
40078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    neon_store_reg(rd, pass, tmp);
40088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                } else { /* Store */
40098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    tmp = neon_load_reg(rd, pass);
40108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if (shift)
40118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        tcg_gen_shri_i32(tmp, tmp, shift);
40128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    switch (size) {
40138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    case 0:
40145285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        gen_st8(tmp, addr, IS_USER(s));
40158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        break;
40168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    case 1:
40175285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        gen_st16(tmp, addr, IS_USER(s));
40188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        break;
40198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    case 2:
40205285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        gen_st32(tmp, addr, IS_USER(s));
40218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        break;
40228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
40238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
40248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                rd += stride;
40255285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_gen_addi_i32(addr, addr, 1 << size);
40268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
40275285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tcg_temp_free_i32(addr);
40288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            stride = nregs * (1 << size);
40298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
40308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
40318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (rm != 15) {
40328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        TCGv base;
40338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
40348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        base = load_reg(s, rn);
40358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (rm == 13) {
40368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tcg_gen_addi_i32(base, base, stride);
40378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        } else {
40388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            TCGv index;
40398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            index = load_reg(s, rm);
40408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tcg_gen_add_i32(base, base, index);
40415285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tcg_temp_free_i32(index);
40428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
40438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        store_reg(s, rn, base);
40448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
40458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
40468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
40478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
40488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Bitwise select.  dest = c ? t : f.  Clobbers T and F.  */
40498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void gen_neon_bsl(TCGv dest, TCGv t, TCGv f, TCGv c)
40508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
40518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_gen_and_i32(t, t, c);
40525285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_gen_andc_i32(f, f, c);
40538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_gen_or_i32(dest, t, f);
40548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
40558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
40565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic inline void gen_neon_narrow(int size, TCGv dest, TCGv_i64 src)
40578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
40588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    switch (size) {
40598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0: gen_helper_neon_narrow_u8(dest, src); break;
40608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 1: gen_helper_neon_narrow_u16(dest, src); break;
40618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 2: tcg_gen_trunc_i64_i32(dest, src); break;
40628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    default: abort();
40638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
40648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
40658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
40665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic inline void gen_neon_narrow_sats(int size, TCGv dest, TCGv_i64 src)
40678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
40688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    switch (size) {
40695285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    case 0: gen_helper_neon_narrow_sat_s8(dest, src); break;
40705285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    case 1: gen_helper_neon_narrow_sat_s16(dest, src); break;
40715285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    case 2: gen_helper_neon_narrow_sat_s32(dest, src); break;
40728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    default: abort();
40738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
40748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
40758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
40765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic inline void gen_neon_narrow_satu(int size, TCGv dest, TCGv_i64 src)
40778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
40788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    switch (size) {
40795285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    case 0: gen_helper_neon_narrow_sat_u8(dest, src); break;
40805285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    case 1: gen_helper_neon_narrow_sat_u16(dest, src); break;
40815285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    case 2: gen_helper_neon_narrow_sat_u32(dest, src); break;
40825285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    default: abort();
40835285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    }
40845285864985be9077e58e42235af6582dee72e841David 'Digit' Turner}
40855285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
40865285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic inline void gen_neon_unarrow_sats(int size, TCGv dest, TCGv_i64 src)
40875285864985be9077e58e42235af6582dee72e841David 'Digit' Turner{
40885285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    switch (size) {
40895285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    case 0: gen_helper_neon_unarrow_sat8(dest, src); break;
40905285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    case 1: gen_helper_neon_unarrow_sat16(dest, src); break;
40915285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    case 2: gen_helper_neon_unarrow_sat32(dest, src); break;
40928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    default: abort();
40938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
40948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
40958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
40968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline void gen_neon_shift_narrow(int size, TCGv var, TCGv shift,
40978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                         int q, int u)
40988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
40998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (q) {
41008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (u) {
41018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            switch (size) {
41028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            case 1: gen_helper_neon_rshl_u16(var, var, shift); break;
41038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            case 2: gen_helper_neon_rshl_u32(var, var, shift); break;
41048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            default: abort();
41058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
41068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        } else {
41078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            switch (size) {
41088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            case 1: gen_helper_neon_rshl_s16(var, var, shift); break;
41098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            case 2: gen_helper_neon_rshl_s32(var, var, shift); break;
41108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            default: abort();
41118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
41128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
41138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } else {
41148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (u) {
41158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            switch (size) {
41165285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            case 1: gen_helper_neon_shl_u16(var, var, shift); break;
41175285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            case 2: gen_helper_neon_shl_u32(var, var, shift); break;
41188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            default: abort();
41198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
41208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        } else {
41218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            switch (size) {
41228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            case 1: gen_helper_neon_shl_s16(var, var, shift); break;
41238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            case 2: gen_helper_neon_shl_s32(var, var, shift); break;
41248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            default: abort();
41258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
41268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
41278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
41288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
41298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
41305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic inline void gen_neon_widen(TCGv_i64 dest, TCGv src, int size, int u)
41318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
41328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (u) {
41338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        switch (size) {
41348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0: gen_helper_neon_widen_u8(dest, src); break;
41358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 1: gen_helper_neon_widen_u16(dest, src); break;
41368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 2: tcg_gen_extu_i32_i64(dest, src); break;
41378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        default: abort();
41388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
41398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } else {
41408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        switch (size) {
41418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0: gen_helper_neon_widen_s8(dest, src); break;
41428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 1: gen_helper_neon_widen_s16(dest, src); break;
41438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 2: tcg_gen_ext_i32_i64(dest, src); break;
41448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        default: abort();
41458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
41468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
41475285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_temp_free_i32(src);
41488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
41498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
41508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline void gen_neon_addl(int size)
41518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
41528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    switch (size) {
41538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0: gen_helper_neon_addl_u16(CPU_V001); break;
41548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 1: gen_helper_neon_addl_u32(CPU_V001); break;
41558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 2: tcg_gen_add_i64(CPU_V001); break;
41568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    default: abort();
41578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
41588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
41598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
41608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline void gen_neon_subl(int size)
41618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
41628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    switch (size) {
41638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0: gen_helper_neon_subl_u16(CPU_V001); break;
41648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 1: gen_helper_neon_subl_u32(CPU_V001); break;
41658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 2: tcg_gen_sub_i64(CPU_V001); break;
41668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    default: abort();
41678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
41688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
41698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
41705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic inline void gen_neon_negl(TCGv_i64 var, int size)
41718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
41728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    switch (size) {
41738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0: gen_helper_neon_negl_u16(var, var); break;
41748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 1: gen_helper_neon_negl_u32(var, var); break;
41758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 2: gen_helper_neon_negl_u64(var, var); break;
41768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    default: abort();
41778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
41788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
41798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
41805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic inline void gen_neon_addl_saturate(TCGv_i64 op0, TCGv_i64 op1, int size)
41818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
41828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    switch (size) {
41835285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    case 1: gen_helper_neon_addl_saturate_s32(op0, op0, op1); break;
41845285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    case 2: gen_helper_neon_addl_saturate_s64(op0, op0, op1); break;
41858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    default: abort();
41868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
41878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
41888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
41895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic inline void gen_neon_mull(TCGv_i64 dest, TCGv a, TCGv b, int size, int u)
41908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
41915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    TCGv_i64 tmp;
41928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
41938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    switch ((size << 1) | u) {
41948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0: gen_helper_neon_mull_s8(dest, a, b); break;
41958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 1: gen_helper_neon_mull_u8(dest, a, b); break;
41968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 2: gen_helper_neon_mull_s16(dest, a, b); break;
41978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 3: gen_helper_neon_mull_u16(dest, a, b); break;
41988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 4:
41998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tmp = gen_muls_i64_i32(a, b);
42008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tcg_gen_mov_i64(dest, tmp);
42015285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tcg_temp_free_i64(tmp);
42028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
42038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 5:
42048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tmp = gen_mulu_i64_i32(a, b);
42058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tcg_gen_mov_i64(dest, tmp);
42065285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tcg_temp_free_i64(tmp);
42078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
42088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    default: abort();
42098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
42105285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
42115285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    /* gen_helper_neon_mull_[su]{8|16} do not free their parameters.
42125285864985be9077e58e42235af6582dee72e841David 'Digit' Turner       Don't forget to clean them now.  */
42138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (size < 2) {
42145285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tcg_temp_free_i32(a);
42155285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tcg_temp_free_i32(b);
42168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
42178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
42188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
42195285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic void gen_neon_narrow_op(int op, int u, int size, TCGv dest, TCGv_i64 src)
42205285864985be9077e58e42235af6582dee72e841David 'Digit' Turner{
42215285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    if (op) {
42225285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        if (u) {
42235285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            gen_neon_unarrow_sats(size, dest, src);
42245285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        } else {
42255285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            gen_neon_narrow(size, dest, src);
42265285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        }
42275285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    } else {
42285285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        if (u) {
42295285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            gen_neon_narrow_satu(size, dest, src);
42305285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        } else {
42315285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            gen_neon_narrow_sats(size, dest, src);
42325285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        }
42335285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    }
42345285864985be9077e58e42235af6582dee72e841David 'Digit' Turner}
42355285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
42365285864985be9077e58e42235af6582dee72e841David 'Digit' Turner/* Symbolic constants for op fields for Neon 3-register same-length.
42375285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * The values correspond to bits [11:8,4]; see the ARM ARM DDI0406B
42385285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * table A7-9.
42395285864985be9077e58e42235af6582dee72e841David 'Digit' Turner */
42405285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_3R_VHADD 0
42415285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_3R_VQADD 1
42425285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_3R_VRHADD 2
42435285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_3R_LOGIC 3 /* VAND,VBIC,VORR,VMOV,VORN,VEOR,VBIF,VBIT,VBSL */
42445285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_3R_VHSUB 4
42455285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_3R_VQSUB 5
42465285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_3R_VCGT 6
42475285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_3R_VCGE 7
42485285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_3R_VSHL 8
42495285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_3R_VQSHL 9
42505285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_3R_VRSHL 10
42515285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_3R_VQRSHL 11
42525285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_3R_VMAX 12
42535285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_3R_VMIN 13
42545285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_3R_VABD 14
42555285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_3R_VABA 15
42565285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_3R_VADD_VSUB 16
42575285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_3R_VTST_VCEQ 17
42585285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_3R_VML 18 /* VMLA, VMLAL, VMLS, VMLSL */
42595285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_3R_VMUL 19
42605285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_3R_VPMAX 20
42615285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_3R_VPMIN 21
42625285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_3R_VQDMULH_VQRDMULH 22
42635285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_3R_VPADD 23
42645285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_3R_FLOAT_ARITH 26 /* float VADD, VSUB, VPADD, VABD */
42655285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_3R_FLOAT_MULTIPLY 27 /* float VMLA, VMLS, VMUL */
42665285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_3R_FLOAT_CMP 28 /* float VCEQ, VCGE, VCGT */
42675285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_3R_FLOAT_ACMP 29 /* float VACGE, VACGT, VACLE, VACLT */
42685285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_3R_FLOAT_MINMAX 30 /* float VMIN, VMAX */
42695285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_3R_VRECPS_VRSQRTS 31 /* float VRECPS, VRSQRTS */
42705285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
42715285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic const uint8_t neon_3r_sizes[] = {
42725285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    [NEON_3R_VHADD] = 0x7,
42735285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    [NEON_3R_VQADD] = 0xf,
42745285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    [NEON_3R_VRHADD] = 0x7,
42755285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    [NEON_3R_LOGIC] = 0xf, /* size field encodes op type */
42765285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    [NEON_3R_VHSUB] = 0x7,
42775285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    [NEON_3R_VQSUB] = 0xf,
42785285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    [NEON_3R_VCGT] = 0x7,
42795285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    [NEON_3R_VCGE] = 0x7,
42805285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    [NEON_3R_VSHL] = 0xf,
42815285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    [NEON_3R_VQSHL] = 0xf,
42825285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    [NEON_3R_VRSHL] = 0xf,
42835285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    [NEON_3R_VQRSHL] = 0xf,
42845285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    [NEON_3R_VMAX] = 0x7,
42855285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    [NEON_3R_VMIN] = 0x7,
42865285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    [NEON_3R_VABD] = 0x7,
42875285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    [NEON_3R_VABA] = 0x7,
42885285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    [NEON_3R_VADD_VSUB] = 0xf,
42895285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    [NEON_3R_VTST_VCEQ] = 0x7,
42905285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    [NEON_3R_VML] = 0x7,
42915285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    [NEON_3R_VMUL] = 0x7,
42925285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    [NEON_3R_VPMAX] = 0x7,
42935285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    [NEON_3R_VPMIN] = 0x7,
42945285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    [NEON_3R_VQDMULH_VQRDMULH] = 0x6,
42955285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    [NEON_3R_VPADD] = 0x7,
42965285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    [NEON_3R_FLOAT_ARITH] = 0x5, /* size bit 1 encodes op */
42975285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    [NEON_3R_FLOAT_MULTIPLY] = 0x5, /* size bit 1 encodes op */
42985285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    [NEON_3R_FLOAT_CMP] = 0x5, /* size bit 1 encodes op */
42995285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    [NEON_3R_FLOAT_ACMP] = 0x5, /* size bit 1 encodes op */
43005285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    [NEON_3R_FLOAT_MINMAX] = 0x5, /* size bit 1 encodes op */
43015285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    [NEON_3R_VRECPS_VRSQRTS] = 0x5, /* size bit 1 encodes op */
43025285864985be9077e58e42235af6582dee72e841David 'Digit' Turner};
43035285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
43045285864985be9077e58e42235af6582dee72e841David 'Digit' Turner/* Symbolic constants for op fields for Neon 2-register miscellaneous.
43055285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * The values correspond to bits [17:16,10:7]; see the ARM ARM DDI0406B
43065285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * table A7-13.
43075285864985be9077e58e42235af6582dee72e841David 'Digit' Turner */
43085285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VREV64 0
43095285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VREV32 1
43105285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VREV16 2
43115285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VPADDL 4
43125285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VPADDL_U 5
43135285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VCLS 8
43145285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VCLZ 9
43155285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VCNT 10
43165285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VMVN 11
43175285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VPADAL 12
43185285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VPADAL_U 13
43195285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VQABS 14
43205285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VQNEG 15
43215285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VCGT0 16
43225285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VCGE0 17
43235285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VCEQ0 18
43245285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VCLE0 19
43255285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VCLT0 20
43265285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VABS 22
43275285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VNEG 23
43285285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VCGT0_F 24
43295285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VCGE0_F 25
43305285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VCEQ0_F 26
43315285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VCLE0_F 27
43325285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VCLT0_F 28
43335285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VABS_F 30
43345285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VNEG_F 31
43355285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VSWP 32
43365285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VTRN 33
43375285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VUZP 34
43385285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VZIP 35
43395285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VMOVN 36 /* Includes VQMOVN, VQMOVUN */
43405285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VQMOVN 37 /* Includes VQMOVUN */
43415285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VSHLL 38
43425285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VCVT_F16_F32 44
43435285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VCVT_F32_F16 46
43445285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VRECPE 56
43455285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VRSQRTE 57
43465285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VRECPE_F 58
43475285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VRSQRTE_F 59
43485285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VCVT_FS 60
43495285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VCVT_FU 61
43505285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VCVT_SF 62
43515285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define NEON_2RM_VCVT_UF 63
43525285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
43535285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic int neon_2rm_is_float_op(int op)
43545285864985be9077e58e42235af6582dee72e841David 'Digit' Turner{
43555285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    /* Return true if this neon 2reg-misc op is float-to-float */
43565285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    return (op == NEON_2RM_VABS_F || op == NEON_2RM_VNEG_F ||
43575285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            op >= NEON_2RM_VRECPE_F);
43585285864985be9077e58e42235af6582dee72e841David 'Digit' Turner}
43595285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
43605285864985be9077e58e42235af6582dee72e841David 'Digit' Turner/* Each entry in this array has bit n set if the insn allows
43615285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * size value n (otherwise it will UNDEF). Since unallocated
43625285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * op values will have no bits set they always UNDEF.
43635285864985be9077e58e42235af6582dee72e841David 'Digit' Turner */
43645285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic const uint8_t neon_2rm_sizes[] = {
43655285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    [NEON_2RM_VREV64] = 0x7,
43665285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    [NEON_2RM_VREV32] = 0x3,
43675285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    [NEON_2RM_VREV16] = 0x1,
43685285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    [NEON_2RM_VPADDL] = 0x7,
43695285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    [NEON_2RM_VPADDL_U] = 0x7,
43705285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    [NEON_2RM_VCLS] = 0x7,
43715285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    [NEON_2RM_VCLZ] = 0x7,
43725285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    [NEON_2RM_VCNT] = 0x1,
43735285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    [NEON_2RM_VMVN] = 0x1,
43745285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    [NEON_2RM_VPADAL] = 0x7,
43755285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    [NEON_2RM_VPADAL_U] = 0x7,
43765285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    [NEON_2RM_VQABS] = 0x7,
43775285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    [NEON_2RM_VQNEG] = 0x7,
43785285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    [NEON_2RM_VCGT0] = 0x7,
43795285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    [NEON_2RM_VCGE0] = 0x7,
43805285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    [NEON_2RM_VCEQ0] = 0x7,
43815285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    [NEON_2RM_VCLE0] = 0x7,
43825285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    [NEON_2RM_VCLT0] = 0x7,
43835285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    [NEON_2RM_VABS] = 0x7,
43845285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    [NEON_2RM_VNEG] = 0x7,
43855285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    [NEON_2RM_VCGT0_F] = 0x4,
43865285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    [NEON_2RM_VCGE0_F] = 0x4,
43875285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    [NEON_2RM_VCEQ0_F] = 0x4,
43885285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    [NEON_2RM_VCLE0_F] = 0x4,
43895285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    [NEON_2RM_VCLT0_F] = 0x4,
43905285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    [NEON_2RM_VABS_F] = 0x4,
43915285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    [NEON_2RM_VNEG_F] = 0x4,
43925285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    [NEON_2RM_VSWP] = 0x1,
43935285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    [NEON_2RM_VTRN] = 0x7,
43945285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    [NEON_2RM_VUZP] = 0x7,
43955285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    [NEON_2RM_VZIP] = 0x7,
43965285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    [NEON_2RM_VMOVN] = 0x7,
43975285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    [NEON_2RM_VQMOVN] = 0x7,
43985285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    [NEON_2RM_VSHLL] = 0x7,
43995285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    [NEON_2RM_VCVT_F16_F32] = 0x2,
44005285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    [NEON_2RM_VCVT_F32_F16] = 0x2,
44015285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    [NEON_2RM_VRECPE] = 0x4,
44025285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    [NEON_2RM_VRSQRTE] = 0x4,
44035285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    [NEON_2RM_VRECPE_F] = 0x4,
44045285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    [NEON_2RM_VRSQRTE_F] = 0x4,
44055285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    [NEON_2RM_VCVT_FS] = 0x4,
44065285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    [NEON_2RM_VCVT_FU] = 0x4,
44075285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    [NEON_2RM_VCVT_SF] = 0x4,
44085285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    [NEON_2RM_VCVT_UF] = 0x4,
44095285864985be9077e58e42235af6582dee72e841David 'Digit' Turner};
44105285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
44118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Translate a NEON data processing instruction.  Return nonzero if the
44128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   instruction is invalid.
44138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   We process data in a mixture of 32-bit and 64-bit chunks.
44148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   Mostly we use 32-bit chunks so we can use normal scalar instructions.  */
44158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
44168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
44178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
44188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int op;
44198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int q;
44208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int rd, rn, rm;
44218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int size;
44228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int shift;
44238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int pass;
44248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int count;
44258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int pairwise;
44268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int u;
44275285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    uint32_t imm, mask;
44285285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    TCGv tmp, tmp2, tmp3, tmp4, tmp5;
44295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    TCGv_i64 tmp64;
44308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
44315285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    if (!s->vfp_enabled)
44328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      return 1;
44338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    q = (insn & (1 << 6)) != 0;
44348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    u = (insn >> 24) & 1;
44358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    VFP_DREG_D(rd, insn);
44368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    VFP_DREG_N(rn, insn);
44378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    VFP_DREG_M(rm, insn);
44388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    size = (insn >> 20) & 3;
44398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if ((insn & (1 << 23)) == 0) {
44408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* Three register same length.  */
44418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        op = ((insn >> 7) & 0x1e) | ((insn >> 4) & 1);
44425285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        /* Catch invalid op and bad size combinations: UNDEF */
44435285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        if ((neon_3r_sizes[op] & (1 << size)) == 0) {
44445285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            return 1;
44455285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        }
44465285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        /* All insns of this form UNDEF for either this condition or the
44475285864985be9077e58e42235af6582dee72e841David 'Digit' Turner         * superset of cases "Q==1"; we catch the latter later.
44485285864985be9077e58e42235af6582dee72e841David 'Digit' Turner         */
44495285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        if (q && ((rd | rn | rm) & 1)) {
44505285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            return 1;
44515285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        }
44525285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        if (size == 3 && op != NEON_3R_LOGIC) {
44535285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            /* 64-bit element instructions. */
44548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            for (pass = 0; pass < (q ? 2 : 1); pass++) {
44558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                neon_load_reg64(cpu_V0, rn + pass);
44568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                neon_load_reg64(cpu_V1, rm + pass);
44578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                switch (op) {
44585285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                case NEON_3R_VQADD:
44598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if (u) {
44605285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        gen_helper_neon_qadd_u64(cpu_V0, cpu_V0, cpu_V1);
44618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    } else {
44625285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        gen_helper_neon_qadd_s64(cpu_V0, cpu_V0, cpu_V1);
44638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
44648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    break;
44655285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                case NEON_3R_VQSUB:
44668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if (u) {
44675285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        gen_helper_neon_qsub_u64(cpu_V0, cpu_V0, cpu_V1);
44688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    } else {
44695285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        gen_helper_neon_qsub_s64(cpu_V0, cpu_V0, cpu_V1);
44708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
44718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    break;
44725285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                case NEON_3R_VSHL:
44738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if (u) {
44748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        gen_helper_neon_shl_u64(cpu_V0, cpu_V1, cpu_V0);
44758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    } else {
44768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        gen_helper_neon_shl_s64(cpu_V0, cpu_V1, cpu_V0);
44778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
44788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    break;
44795285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                case NEON_3R_VQSHL:
44808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if (u) {
44815285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        gen_helper_neon_qshl_u64(cpu_V0, cpu_V1, cpu_V0);
44828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    } else {
44835285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        gen_helper_neon_qshl_s64(cpu_V0, cpu_V1, cpu_V0);
44848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
44858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    break;
44865285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                case NEON_3R_VRSHL:
44878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if (u) {
44888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        gen_helper_neon_rshl_u64(cpu_V0, cpu_V1, cpu_V0);
44898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    } else {
44908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        gen_helper_neon_rshl_s64(cpu_V0, cpu_V1, cpu_V0);
44918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
44928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    break;
44935285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                case NEON_3R_VQRSHL:
44948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if (u) {
44955285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        gen_helper_neon_qrshl_u64(cpu_V0, cpu_V1, cpu_V0);
44968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    } else {
44975285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        gen_helper_neon_qrshl_s64(cpu_V0, cpu_V1, cpu_V0);
44988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
44998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    break;
45005285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                case NEON_3R_VADD_VSUB:
45018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if (u) {
45028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        tcg_gen_sub_i64(CPU_V001);
45038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    } else {
45048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        tcg_gen_add_i64(CPU_V001);
45058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
45068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    break;
45078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                default:
45088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    abort();
45098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
45108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                neon_store_reg64(cpu_V0, rd + pass);
45118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
45128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 0;
45138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
45145285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        pairwise = 0;
45158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        switch (op) {
45165285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        case NEON_3R_VSHL:
45175285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        case NEON_3R_VQSHL:
45185285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        case NEON_3R_VRSHL:
45195285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        case NEON_3R_VQRSHL:
45208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            {
45218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                int rtmp;
45228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* Shift instruction operands are reversed.  */
45238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                rtmp = rn;
45248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                rn = rm;
45258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                rm = rtmp;
45268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
45278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
45285285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        case NEON_3R_VPADD:
45295285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            if (u) {
45305285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                return 1;
45315285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            }
45325285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            /* Fall through */
45335285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        case NEON_3R_VPMAX:
45345285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        case NEON_3R_VPMIN:
45358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            pairwise = 1;
45368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
45375285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        case NEON_3R_FLOAT_ARITH:
45385285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            pairwise = (u && size < 2); /* if VPADD (float) */
45398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
45405285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        case NEON_3R_FLOAT_MINMAX:
45415285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            pairwise = u; /* if VPMIN/VPMAX (float) */
45425285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            break;
45435285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        case NEON_3R_FLOAT_CMP:
45445285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            if (!u && size) {
45455285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                /* no encoding for U=0 C=1x */
45465285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                return 1;
45475285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            }
45485285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            break;
45495285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        case NEON_3R_FLOAT_ACMP:
45505285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            if (!u) {
45515285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                return 1;
45525285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            }
45535285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            break;
45545285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        case NEON_3R_VRECPS_VRSQRTS:
45555285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            if (u) {
45565285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                return 1;
45575285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            }
45585285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            break;
45595285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        case NEON_3R_VMUL:
45605285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            if (u && (size != 0)) {
45615285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                /* UNDEF on invalid size for polynomial subcase */
45625285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                return 1;
45635285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            }
45648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
45658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        default:
45668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
45678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
45685285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
45695285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        if (pairwise && q) {
45705285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            /* All the pairwise insns UNDEF if Q is set */
45715285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            return 1;
45725285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        }
45735285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
45748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        for (pass = 0; pass < (q ? 4 : 2); pass++) {
45758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
45768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (pairwise) {
45778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* Pairwise.  */
45785285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            if (pass < 1) {
45795285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tmp = neon_load_reg(rn, 0);
45805285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tmp2 = neon_load_reg(rn, 1);
45818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            } else {
45825285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tmp = neon_load_reg(rm, 0);
45835285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tmp2 = neon_load_reg(rm, 1);
45848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
45858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        } else {
45868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* Elementwise.  */
45875285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tmp = neon_load_reg(rn, pass);
45885285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tmp2 = neon_load_reg(rm, pass);
45898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
45908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        switch (op) {
45915285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        case NEON_3R_VHADD:
45928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            GEN_NEON_INTEGER_OP(hadd);
45938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
45945285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        case NEON_3R_VQADD:
45955285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            GEN_NEON_INTEGER_OP(qadd);
45968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
45975285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        case NEON_3R_VRHADD:
45988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            GEN_NEON_INTEGER_OP(rhadd);
45998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
46005285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        case NEON_3R_LOGIC: /* Logic ops.  */
46018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            switch ((u << 2) | size) {
46028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            case 0: /* VAND */
46035285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_gen_and_i32(tmp, tmp, tmp2);
46048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                break;
46058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            case 1: /* BIC */
46065285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_gen_andc_i32(tmp, tmp, tmp2);
46078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                break;
46088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            case 2: /* VORR */
46095285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_gen_or_i32(tmp, tmp, tmp2);
46108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                break;
46118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            case 3: /* VORN */
46125285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_gen_orc_i32(tmp, tmp, tmp2);
46138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                break;
46148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            case 4: /* VEOR */
46155285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_gen_xor_i32(tmp, tmp, tmp2);
46168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                break;
46178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            case 5: /* VBSL */
46185285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tmp3 = neon_load_reg(rd, pass);
46195285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                gen_neon_bsl(tmp, tmp, tmp2, tmp3);
46205285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_temp_free_i32(tmp3);
46218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                break;
46228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            case 6: /* VBIT */
46235285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tmp3 = neon_load_reg(rd, pass);
46245285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                gen_neon_bsl(tmp, tmp, tmp3, tmp2);
46255285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_temp_free_i32(tmp3);
46268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                break;
46278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            case 7: /* VBIF */
46285285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tmp3 = neon_load_reg(rd, pass);
46295285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                gen_neon_bsl(tmp, tmp3, tmp, tmp2);
46305285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_temp_free_i32(tmp3);
46318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                break;
46328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
46338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
46345285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        case NEON_3R_VHSUB:
46358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            GEN_NEON_INTEGER_OP(hsub);
46368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
46375285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        case NEON_3R_VQSUB:
46385285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            GEN_NEON_INTEGER_OP(qsub);
46398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
46405285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        case NEON_3R_VCGT:
46418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            GEN_NEON_INTEGER_OP(cgt);
46428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
46435285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        case NEON_3R_VCGE:
46448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            GEN_NEON_INTEGER_OP(cge);
46458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
46465285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        case NEON_3R_VSHL:
46478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            GEN_NEON_INTEGER_OP(shl);
46488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
46495285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        case NEON_3R_VQSHL:
46505285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            GEN_NEON_INTEGER_OP(qshl);
46518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
46525285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        case NEON_3R_VRSHL:
46538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            GEN_NEON_INTEGER_OP(rshl);
46548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
46555285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        case NEON_3R_VQRSHL:
46565285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            GEN_NEON_INTEGER_OP(qrshl);
46578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
46585285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        case NEON_3R_VMAX:
46598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            GEN_NEON_INTEGER_OP(max);
46608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
46615285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        case NEON_3R_VMIN:
46628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            GEN_NEON_INTEGER_OP(min);
46638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
46645285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        case NEON_3R_VABD:
46658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            GEN_NEON_INTEGER_OP(abd);
46668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
46675285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        case NEON_3R_VABA:
46688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            GEN_NEON_INTEGER_OP(abd);
46695285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tcg_temp_free_i32(tmp2);
46705285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tmp2 = neon_load_reg(rd, pass);
46715285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            gen_neon_add(size, tmp, tmp2);
46728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
46735285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        case NEON_3R_VADD_VSUB:
46748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (!u) { /* VADD */
46755285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                gen_neon_add(size, tmp, tmp2);
46768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            } else { /* VSUB */
46778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                switch (size) {
46785285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                case 0: gen_helper_neon_sub_u8(tmp, tmp, tmp2); break;
46795285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                case 1: gen_helper_neon_sub_u16(tmp, tmp, tmp2); break;
46805285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                case 2: tcg_gen_sub_i32(tmp, tmp, tmp2); break;
46815285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                default: abort();
46828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
46838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
46848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
46855285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        case NEON_3R_VTST_VCEQ:
46868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (!u) { /* VTST */
46878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                switch (size) {
46885285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                case 0: gen_helper_neon_tst_u8(tmp, tmp, tmp2); break;
46895285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                case 1: gen_helper_neon_tst_u16(tmp, tmp, tmp2); break;
46905285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                case 2: gen_helper_neon_tst_u32(tmp, tmp, tmp2); break;
46915285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                default: abort();
46928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
46938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            } else { /* VCEQ */
46948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                switch (size) {
46955285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                case 0: gen_helper_neon_ceq_u8(tmp, tmp, tmp2); break;
46965285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                case 1: gen_helper_neon_ceq_u16(tmp, tmp, tmp2); break;
46975285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                case 2: gen_helper_neon_ceq_u32(tmp, tmp, tmp2); break;
46985285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                default: abort();
46998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
47008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
47018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
47025285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        case NEON_3R_VML: /* VMLA, VMLAL, VMLS,VMLSL */
47038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            switch (size) {
47045285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            case 0: gen_helper_neon_mul_u8(tmp, tmp, tmp2); break;
47055285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            case 1: gen_helper_neon_mul_u16(tmp, tmp, tmp2); break;
47065285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            case 2: tcg_gen_mul_i32(tmp, tmp, tmp2); break;
47075285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            default: abort();
47088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
47095285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tcg_temp_free_i32(tmp2);
47105285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tmp2 = neon_load_reg(rd, pass);
47118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (u) { /* VMLS */
47125285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                gen_neon_rsb(size, tmp, tmp2);
47138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            } else { /* VMLA */
47145285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                gen_neon_add(size, tmp, tmp2);
47158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
47168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
47175285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        case NEON_3R_VMUL:
47188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (u) { /* polynomial */
47195285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                gen_helper_neon_mul_p8(tmp, tmp, tmp2);
47208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            } else { /* Integer */
47218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                switch (size) {
47225285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                case 0: gen_helper_neon_mul_u8(tmp, tmp, tmp2); break;
47235285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                case 1: gen_helper_neon_mul_u16(tmp, tmp, tmp2); break;
47245285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                case 2: tcg_gen_mul_i32(tmp, tmp, tmp2); break;
47255285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                default: abort();
47268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
47278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
47288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
47295285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        case NEON_3R_VPMAX:
47308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            GEN_NEON_INTEGER_OP(pmax);
47318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
47325285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        case NEON_3R_VPMIN:
47338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            GEN_NEON_INTEGER_OP(pmin);
47348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
47355285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        case NEON_3R_VQDMULH_VQRDMULH: /* Multiply high.  */
47368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (!u) { /* VQDMULH */
47378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                switch (size) {
47385285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                case 1: gen_helper_neon_qdmulh_s16(tmp, tmp, tmp2); break;
47395285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                case 2: gen_helper_neon_qdmulh_s32(tmp, tmp, tmp2); break;
47405285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                default: abort();
47418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
47425285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            } else { /* VQRDMULH */
47438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                switch (size) {
47445285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                case 1: gen_helper_neon_qrdmulh_s16(tmp, tmp, tmp2); break;
47455285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                case 2: gen_helper_neon_qrdmulh_s32(tmp, tmp, tmp2); break;
47465285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                default: abort();
47478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
47488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
47498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
47505285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        case NEON_3R_VPADD:
47518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            switch (size) {
47525285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            case 0: gen_helper_neon_padd_u8(tmp, tmp, tmp2); break;
47535285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            case 1: gen_helper_neon_padd_u16(tmp, tmp, tmp2); break;
47545285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            case 2: tcg_gen_add_i32(tmp, tmp, tmp2); break;
47555285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            default: abort();
47568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
47578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
47585285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        case NEON_3R_FLOAT_ARITH: /* Floating point arithmetic. */
47598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            switch ((u << 2) | size) {
47608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            case 0: /* VADD */
47615285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                gen_helper_neon_add_f32(tmp, tmp, tmp2);
47628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                break;
47638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            case 2: /* VSUB */
47645285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                gen_helper_neon_sub_f32(tmp, tmp, tmp2);
47658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                break;
47668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            case 4: /* VPADD */
47675285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                gen_helper_neon_add_f32(tmp, tmp, tmp2);
47688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                break;
47698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            case 6: /* VABD */
47705285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                gen_helper_neon_abd_f32(tmp, tmp, tmp2);
47718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                break;
47728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            default:
47735285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                abort();
47748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
47758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
47765285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        case NEON_3R_FLOAT_MULTIPLY:
47775285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            gen_helper_neon_mul_f32(tmp, tmp, tmp2);
47788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (!u) {
47795285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_temp_free_i32(tmp2);
47805285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tmp2 = neon_load_reg(rd, pass);
47818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (size == 0) {
47825285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    gen_helper_neon_add_f32(tmp, tmp, tmp2);
47838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                } else {
47845285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    gen_helper_neon_sub_f32(tmp, tmp2, tmp);
47858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
47868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
47878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
47885285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        case NEON_3R_FLOAT_CMP:
47898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (!u) {
47905285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                gen_helper_neon_ceq_f32(tmp, tmp, tmp2);
47918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            } else {
47928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (size == 0)
47935285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    gen_helper_neon_cge_f32(tmp, tmp, tmp2);
47948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                else
47955285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    gen_helper_neon_cgt_f32(tmp, tmp, tmp2);
47968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
47978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
47985285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        case NEON_3R_FLOAT_ACMP:
47998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (size == 0)
48005285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                gen_helper_neon_acge_f32(tmp, tmp, tmp2);
48018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            else
48025285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                gen_helper_neon_acgt_f32(tmp, tmp, tmp2);
48038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
48045285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        case NEON_3R_FLOAT_MINMAX:
48058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (size == 0)
48065285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                gen_helper_neon_max_f32(tmp, tmp, tmp2);
48078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            else
48085285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                gen_helper_neon_min_f32(tmp, tmp, tmp2);
48098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
48105285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        case NEON_3R_VRECPS_VRSQRTS:
48118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (size == 0)
48125285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                gen_helper_recps_f32(tmp, tmp, tmp2, cpu_env);
48138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            else
48145285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                gen_helper_rsqrts_f32(tmp, tmp, tmp2, cpu_env);
48158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
48168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        default:
48178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            abort();
48188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
48195285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tcg_temp_free_i32(tmp2);
48205285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
48218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* Save the result.  For elementwise operations we can put it
48228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project           straight into the destination register.  For pairwise operations
48238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project           we have to be careful to avoid clobbering the source operands.  */
48248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (pairwise && rd == rm) {
48255285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            neon_store_scratch(pass, tmp);
48268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        } else {
48275285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            neon_store_reg(rd, pass, tmp);
48288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
48298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
48308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        } /* for pass */
48318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (pairwise && rd == rm) {
48328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            for (pass = 0; pass < (q ? 4 : 2); pass++) {
48335285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tmp = neon_load_scratch(pass);
48345285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                neon_store_reg(rd, pass, tmp);
48358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
48368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
48378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* End of 3 register same size operations.  */
48388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } else if (insn & (1 << 4)) {
48398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if ((insn & 0x00380080) != 0) {
48408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* Two registers and shift.  */
48418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            op = (insn >> 8) & 0xf;
48428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (insn & (1 << 7)) {
48435285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                /* 64-bit shift. */
48445285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                if (op > 7) {
48455285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    return 1;
48465285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                }
48478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                size = 3;
48488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            } else {
48498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                size = 2;
48508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                while ((insn & (1 << (size + 19))) == 0)
48518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    size--;
48528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
48538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            shift = (insn >> 16) & ((1 << (3 + size)) - 1);
48548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* To avoid excessive dumplication of ops we implement shift
48558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project               by immediate using the variable shift operations.  */
48568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (op < 8) {
48578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* Shift by immediate:
48588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                   VSHR, VSRA, VRSHR, VRSRA, VSRI, VSHL, VQSHL, VQSHLU.  */
48595285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                if (q && ((rd | rm) & 1)) {
48605285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    return 1;
48615285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                }
48625285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                if (!u && (op == 4 || op == 6)) {
48635285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    return 1;
48645285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                }
48658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* Right shifts are encoded as N - shift, where N is the
48668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                   element size in bits.  */
48678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (op <= 4)
48688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    shift = shift - (1 << (size + 3));
48698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (size == 3) {
48708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    count = q + 1;
48718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                } else {
48728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    count = q ? 4: 2;
48738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
48748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                switch (size) {
48758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                case 0:
48768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    imm = (uint8_t) shift;
48778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    imm |= imm << 8;
48788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    imm |= imm << 16;
48798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    break;
48808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                case 1:
48818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    imm = (uint16_t) shift;
48828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    imm |= imm << 16;
48838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    break;
48848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                case 2:
48858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                case 3:
48868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    imm = shift;
48878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    break;
48888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                default:
48898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    abort();
48908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
48918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
48928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                for (pass = 0; pass < count; pass++) {
48938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if (size == 3) {
48948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        neon_load_reg64(cpu_V0, rm + pass);
48958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        tcg_gen_movi_i64(cpu_V1, imm);
48968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        switch (op) {
48978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        case 0:  /* VSHR */
48988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        case 1:  /* VSRA */
48998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            if (u)
49008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                gen_helper_neon_shl_u64(cpu_V0, cpu_V0, cpu_V1);
49018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            else
49028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                gen_helper_neon_shl_s64(cpu_V0, cpu_V0, cpu_V1);
49038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            break;
49048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        case 2: /* VRSHR */
49058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        case 3: /* VRSRA */
49068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            if (u)
49078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                gen_helper_neon_rshl_u64(cpu_V0, cpu_V0, cpu_V1);
49088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            else
49098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                gen_helper_neon_rshl_s64(cpu_V0, cpu_V0, cpu_V1);
49108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            break;
49118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        case 4: /* VSRI */
49128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        case 5: /* VSHL, VSLI */
49138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            gen_helper_neon_shl_u64(cpu_V0, cpu_V0, cpu_V1);
49148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            break;
49155285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        case 6: /* VQSHLU */
49165285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            gen_helper_neon_qshlu_s64(cpu_V0, cpu_V0, cpu_V1);
49178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            break;
49185285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        case 7: /* VQSHL */
49195285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            if (u) {
49205285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                                gen_helper_neon_qshl_u64(cpu_V0,
49215285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                                                         cpu_V0, cpu_V1);
49225285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            } else {
49235285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                                gen_helper_neon_qshl_s64(cpu_V0,
49245285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                                                         cpu_V0, cpu_V1);
49255285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            }
49268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            break;
49278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        }
49288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        if (op == 1 || op == 3) {
49298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            /* Accumulate.  */
49305285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            neon_load_reg64(cpu_V1, rd + pass);
49318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            tcg_gen_add_i64(cpu_V0, cpu_V0, cpu_V1);
49328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        } else if (op == 4 || (op == 5 && u)) {
49338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            /* Insert */
49345285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            neon_load_reg64(cpu_V1, rd + pass);
49355285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            uint64_t mask;
49365285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            if (shift < -63 || shift > 63) {
49375285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                                mask = 0;
49385285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            } else {
49395285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                                if (op == 4) {
49405285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                                    mask = 0xffffffffffffffffull >> -shift;
49415285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                                } else {
49425285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                                    mask = 0xffffffffffffffffull << shift;
49435285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                                }
49445285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            }
49455285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            tcg_gen_andi_i64(cpu_V1, cpu_V1, ~mask);
49465285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            tcg_gen_or_i64(cpu_V0, cpu_V0, cpu_V1);
49478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        }
49488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        neon_store_reg64(cpu_V0, rd + pass);
49498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    } else { /* size < 3 */
49508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        /* Operands in T0 and T1.  */
49515285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tmp = neon_load_reg(rm, pass);
49525285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tmp2 = tcg_const_i32(imm);
49538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        switch (op) {
49548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        case 0:  /* VSHR */
49558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        case 1:  /* VSRA */
49568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            GEN_NEON_INTEGER_OP(shl);
49578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            break;
49588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        case 2: /* VRSHR */
49598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        case 3: /* VRSRA */
49608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            GEN_NEON_INTEGER_OP(rshl);
49618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            break;
49628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        case 4: /* VSRI */
49638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        case 5: /* VSHL, VSLI */
49648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            switch (size) {
49655285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            case 0: gen_helper_neon_shl_u8(tmp, tmp, tmp2); break;
49665285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            case 1: gen_helper_neon_shl_u16(tmp, tmp, tmp2); break;
49675285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            case 2: gen_helper_neon_shl_u32(tmp, tmp, tmp2); break;
49685285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            default: abort();
49698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            }
49708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            break;
49715285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        case 6: /* VQSHLU */
49728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            switch (size) {
49735285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            case 0:
49745285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                                gen_helper_neon_qshlu_s8(tmp, tmp, tmp2);
49755285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                                break;
49765285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            case 1:
49775285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                                gen_helper_neon_qshlu_s16(tmp, tmp, tmp2);
49785285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                                break;
49795285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            case 2:
49805285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                                gen_helper_neon_qshlu_s32(tmp, tmp, tmp2);
49815285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                                break;
49825285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            default:
49835285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                                abort();
49848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            }
49858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            break;
49865285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        case 7: /* VQSHL */
49875285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            GEN_NEON_INTEGER_OP(qshl);
49885285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            break;
49898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        }
49905285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tcg_temp_free_i32(tmp2);
49918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
49928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        if (op == 1 || op == 3) {
49938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            /* Accumulate.  */
49945285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            tmp2 = neon_load_reg(rd, pass);
49955285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            gen_neon_add(size, tmp, tmp2);
49965285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            tcg_temp_free_i32(tmp2);
49978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        } else if (op == 4 || (op == 5 && u)) {
49988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            /* Insert */
49998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            switch (size) {
50008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            case 0:
50018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                if (op == 4)
50025285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                                    mask = 0xff >> -shift;
50038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                else
50045285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                                    mask = (uint8_t)(0xff << shift);
50055285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                                mask |= mask << 8;
50065285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                                mask |= mask << 16;
50078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                break;
50088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            case 1:
50098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                if (op == 4)
50105285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                                    mask = 0xffff >> -shift;
50118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                else
50125285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                                    mask = (uint16_t)(0xffff << shift);
50135285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                                mask |= mask << 16;
50148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                break;
50158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            case 2:
50165285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                                if (shift < -31 || shift > 31) {
50175285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                                    mask = 0;
50185285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                                } else {
50195285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                                    if (op == 4)
50205285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                                        mask = 0xffffffffu >> -shift;
50215285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                                    else
50225285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                                        mask = 0xffffffffu << shift;
50235285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                                }
50248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                break;
50258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            default:
50268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                abort();
50278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            }
50285285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            tmp2 = neon_load_reg(rd, pass);
50295285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            tcg_gen_andi_i32(tmp, tmp, mask);
50305285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            tcg_gen_andi_i32(tmp2, tmp2, ~mask);
50315285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            tcg_gen_or_i32(tmp, tmp, tmp2);
50325285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            tcg_temp_free_i32(tmp2);
50338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        }
50345285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        neon_store_reg(rd, pass, tmp);
50358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
50368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                } /* for pass */
50378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            } else if (op < 10) {
50388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* Shift by immediate and narrow:
50398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                   VSHRN, VRSHRN, VQSHRN, VQRSHRN.  */
50405285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                int input_unsigned = (op == 8) ? !u : u;
50415285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                if (rm & 1) {
50425285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    return 1;
50435285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                }
50448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                shift = shift - (1 << (size + 3));
50458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                size++;
50465285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                if (size == 3) {
50475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                    tmp64 = tcg_const_i64(shift);
50485285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    neon_load_reg64(cpu_V0, rm);
50495285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    neon_load_reg64(cpu_V1, rm + 1);
50505285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    for (pass = 0; pass < 2; pass++) {
50515285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        TCGv_i64 in;
50525285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        if (pass == 0) {
50535285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            in = cpu_V0;
50545285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        } else {
50555285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            in = cpu_V1;
50565285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        }
50578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        if (q) {
50585285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            if (input_unsigned) {
50595285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                                gen_helper_neon_rshl_u64(cpu_V0, in, tmp64);
50605285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            } else {
50615285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                                gen_helper_neon_rshl_s64(cpu_V0, in, tmp64);
50625285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            }
50638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        } else {
50645285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            if (input_unsigned) {
50655285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                                gen_helper_neon_shl_u64(cpu_V0, in, tmp64);
50665285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            } else {
50675285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                                gen_helper_neon_shl_s64(cpu_V0, in, tmp64);
50685285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            }
50698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        }
50705285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tmp = tcg_temp_new_i32();
50715285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        gen_neon_narrow_op(op == 8, u, size - 1, tmp, cpu_V0);
50725285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        neon_store_reg(rd, pass, tmp);
50735285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    } /* for pass */
50745285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tcg_temp_free_i64(tmp64);
50755285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                } else {
50765285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    if (size == 1) {
50775285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        imm = (uint16_t)shift;
50785285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        imm |= imm << 16;
50798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    } else {
50805285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        /* size == 2 */
50815285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        imm = (uint32_t)shift;
50828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
50835285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tmp2 = tcg_const_i32(imm);
50845285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tmp4 = neon_load_reg(rm + 1, 0);
50855285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tmp5 = neon_load_reg(rm + 1, 1);
50865285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    for (pass = 0; pass < 2; pass++) {
50875285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        if (pass == 0) {
50885285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            tmp = neon_load_reg(rm, 0);
50895285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        } else {
50905285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            tmp = tmp4;
50915285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        }
50925285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        gen_neon_shift_narrow(size, tmp, tmp2, q,
50935285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                                              input_unsigned);
50945285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        if (pass == 0) {
50955285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            tmp3 = neon_load_reg(rm, 1);
50965285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        } else {
50975285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            tmp3 = tmp5;
50985285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        }
50995285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        gen_neon_shift_narrow(size, tmp3, tmp2, q,
51005285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                                              input_unsigned);
51015285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tcg_gen_concat_i32_i64(cpu_V0, tmp, tmp3);
51025285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tcg_temp_free_i32(tmp);
51035285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tcg_temp_free_i32(tmp3);
51045285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tmp = tcg_temp_new_i32();
51055285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        gen_neon_narrow_op(op == 8, u, size - 1, tmp, cpu_V0);
51065285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        neon_store_reg(rd, pass, tmp);
51075285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    } /* for pass */
51085285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tcg_temp_free_i32(tmp2);
51095285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                }
51108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            } else if (op == 10) {
51115285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                /* VSHLL, VMOVL */
51125285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                if (q || (rd & 1)) {
51138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    return 1;
51145285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                }
51158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                tmp = neon_load_reg(rm, 0);
51168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                tmp2 = neon_load_reg(rm, 1);
51178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                for (pass = 0; pass < 2; pass++) {
51188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if (pass == 1)
51198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        tmp = tmp2;
51208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
51218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    gen_neon_widen(cpu_V0, tmp, size, u);
51228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
51238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if (shift != 0) {
51248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        /* The shift is less than the width of the source
51258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                           type, so we can just shift the whole register.  */
51268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        tcg_gen_shli_i64(cpu_V0, cpu_V0, shift);
51275285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        /* Widen the result of shift: we need to clear
51285285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                         * the potential overflow bits resulting from
51295285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                         * left bits of the narrow input appearing as
51305285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                         * right bits of left the neighbour narrow
51315285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                         * input.  */
51328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        if (size < 2 || !u) {
51338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            uint64_t imm64;
51348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            if (size == 0) {
51358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                imm = (0xffu >> (8 - shift));
51368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                imm |= imm << 16;
51375285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            } else if (size == 1) {
51388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                imm = 0xffff >> (16 - shift);
51395285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            } else {
51405285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                                /* size == 2 */
51415285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                                imm = 0xffffffff >> (32 - shift);
51428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            }
51435285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            if (size < 2) {
51445285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                                imm64 = imm | (((uint64_t)imm) << 32);
51455285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            } else {
51465285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                                imm64 = imm;
51475285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            }
51485285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            tcg_gen_andi_i64(cpu_V0, cpu_V0, ~imm64);
51498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        }
51508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
51518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    neon_store_reg64(cpu_V0, rd + pass);
51528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
51535285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            } else if (op >= 14) {
51548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* VCVT fixed-point.  */
51555285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                if (!(insn & (1 << 21)) || (q && ((rd | rm) & 1))) {
51565285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    return 1;
51575285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                }
51585285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                /* We have already masked out the must-be-1 top bit of imm6,
51595285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                 * hence this 32-shift where the ARM ARM has 64-imm6.
51605285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                 */
51615285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                shift = 32 - shift;
51628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                for (pass = 0; pass < (q ? 4 : 2); pass++) {
51638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, pass));
51645285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    if (!(op & 1)) {
51658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        if (u)
51665285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            gen_vfp_ulto(0, shift, 1);
51678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        else
51685285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            gen_vfp_slto(0, shift, 1);
51698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    } else {
51708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        if (u)
51715285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            gen_vfp_toul(0, shift, 1);
51728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        else
51735285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            gen_vfp_tosl(0, shift, 1);
51748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
51758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, pass));
51768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
51778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            } else {
51788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                return 1;
51798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
51808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        } else { /* (insn & 0x00380080) == 0 */
51818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            int invert;
51825285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            if (q && (rd & 1)) {
51835285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                return 1;
51845285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            }
51858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
51868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            op = (insn >> 8) & 0xf;
51878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* One register and immediate.  */
51888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            imm = (u << 7) | ((insn >> 12) & 0x70) | (insn & 0xf);
51898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            invert = (insn & (1 << 5)) != 0;
51905285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            /* Note that op = 2,3,4,5,6,7,10,11,12,13 imm=0 is UNPREDICTABLE.
51915285864985be9077e58e42235af6582dee72e841David 'Digit' Turner             * We choose to not special-case this and will behave as if a
51925285864985be9077e58e42235af6582dee72e841David 'Digit' Turner             * valid constant encoding of 0 had been given.
51935285864985be9077e58e42235af6582dee72e841David 'Digit' Turner             */
51948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            switch (op) {
51958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            case 0: case 1:
51968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* no-op */
51978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                break;
51988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            case 2: case 3:
51998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                imm <<= 8;
52008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                break;
52018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            case 4: case 5:
52028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                imm <<= 16;
52038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                break;
52048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            case 6: case 7:
52058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                imm <<= 24;
52068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                break;
52078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            case 8: case 9:
52088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                imm |= imm << 16;
52098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                break;
52108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            case 10: case 11:
52118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                imm = (imm << 8) | (imm << 24);
52128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                break;
52138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            case 12:
52145285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                imm = (imm << 8) | 0xff;
52158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                break;
52168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            case 13:
52178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                imm = (imm << 16) | 0xffff;
52188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                break;
52198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            case 14:
52208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                imm |= (imm << 8) | (imm << 16) | (imm << 24);
52218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (invert)
52228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    imm = ~imm;
52238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                break;
52248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            case 15:
52255285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                if (invert) {
52265285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    return 1;
52275285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                }
52288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                imm = ((imm & 0x80) << 24) | ((imm & 0x3f) << 19)
52298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                      | ((imm & 0x40) ? (0x1f << 25) : (1 << 30));
52308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                break;
52318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
52328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (invert)
52338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                imm = ~imm;
52348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
52358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            for (pass = 0; pass < (q ? 4 : 2); pass++) {
52368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (op & 1 && op < 12) {
52378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    tmp = neon_load_reg(rd, pass);
52388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if (invert) {
52398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        /* The immediate value has already been inverted, so
52408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                           BIC becomes AND.  */
52418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        tcg_gen_andi_i32(tmp, tmp, imm);
52428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    } else {
52438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        tcg_gen_ori_i32(tmp, tmp, imm);
52448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
52458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                } else {
52468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    /* VMOV, VMVN.  */
52475285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tmp = tcg_temp_new_i32();
52488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if (op == 14 && invert) {
52495285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        int n;
52508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        uint32_t val;
52518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        val = 0;
52528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        for (n = 0; n < 4; n++) {
52538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            if (imm & (1 << (n + (pass & 1) * 4)))
52548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                val |= 0xff << (n * 8);
52558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        }
52568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        tcg_gen_movi_i32(tmp, val);
52578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    } else {
52588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        tcg_gen_movi_i32(tmp, imm);
52598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
52608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
52618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                neon_store_reg(rd, pass, tmp);
52628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
52638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
52645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    } else { /* (insn & 0x00800010 == 0x00800000) */
52658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (size != 3) {
52668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            op = (insn >> 8) & 0xf;
52678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if ((insn & (1 << 6)) == 0) {
52688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* Three registers of different lengths.  */
52698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                int src1_wide;
52708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                int src2_wide;
52718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                int prewiden;
52725285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                /* undefreq: bit 0 : UNDEF if size != 0
52735285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                 *           bit 1 : UNDEF if size == 0
52745285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                 *           bit 2 : UNDEF if U == 1
52755285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                 * Note that [1:0] set implies 'always UNDEF'
52765285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                 */
52775285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                int undefreq;
52785285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                /* prewiden, src1_wide, src2_wide, undefreq */
52795285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                static const int neon_3reg_wide[16][4] = {
52805285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    {1, 0, 0, 0}, /* VADDL */
52815285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    {1, 1, 0, 0}, /* VADDW */
52825285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    {1, 0, 0, 0}, /* VSUBL */
52835285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    {1, 1, 0, 0}, /* VSUBW */
52845285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    {0, 1, 1, 0}, /* VADDHN */
52855285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    {0, 0, 0, 0}, /* VABAL */
52865285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    {0, 1, 1, 0}, /* VSUBHN */
52875285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    {0, 0, 0, 0}, /* VABDL */
52885285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    {0, 0, 0, 0}, /* VMLAL */
52895285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    {0, 0, 0, 6}, /* VQDMLAL */
52905285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    {0, 0, 0, 0}, /* VMLSL */
52915285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    {0, 0, 0, 6}, /* VQDMLSL */
52925285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    {0, 0, 0, 0}, /* Integer VMULL */
52935285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    {0, 0, 0, 2}, /* VQDMULL */
52945285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    {0, 0, 0, 5}, /* Polynomial VMULL */
52955285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    {0, 0, 0, 3}, /* Reserved: always UNDEF */
52968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                };
52978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
52988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                prewiden = neon_3reg_wide[op][0];
52998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                src1_wide = neon_3reg_wide[op][1];
53008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                src2_wide = neon_3reg_wide[op][2];
53015285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                undefreq = neon_3reg_wide[op][3];
53028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
53035285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                if (((undefreq & 1) && (size != 0)) ||
53045285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    ((undefreq & 2) && (size == 0)) ||
53055285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    ((undefreq & 4) && u)) {
53065285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    return 1;
53075285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                }
53085285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                if ((src1_wide && (rn & 1)) ||
53095285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    (src2_wide && (rm & 1)) ||
53105285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    (!src2_wide && (rd & 1))) {
53118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    return 1;
53125285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                }
53138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
53148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* Avoid overlapping operands.  Wide source operands are
53158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                   always aligned so will never overlap with wide
53168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                   destinations in problematic ways.  */
53178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (rd == rm && !src2_wide) {
53185285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tmp = neon_load_reg(rm, 1);
53195285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    neon_store_scratch(2, tmp);
53208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                } else if (rd == rn && !src1_wide) {
53215285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tmp = neon_load_reg(rn, 1);
53225285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    neon_store_scratch(2, tmp);
53238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
53248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                TCGV_UNUSED(tmp3);
53258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                for (pass = 0; pass < 2; pass++) {
53268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if (src1_wide) {
53278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        neon_load_reg64(cpu_V0, rn + pass);
53288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        TCGV_UNUSED(tmp);
53298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    } else {
53308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        if (pass == 1 && rd == rn) {
53315285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            tmp = neon_load_scratch(2);
53328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        } else {
53338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            tmp = neon_load_reg(rn, pass);
53348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        }
53358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        if (prewiden) {
53368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            gen_neon_widen(cpu_V0, tmp, size, u);
53378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        }
53388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
53398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if (src2_wide) {
53408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        neon_load_reg64(cpu_V1, rm + pass);
53418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        TCGV_UNUSED(tmp2);
53428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    } else {
53438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        if (pass == 1 && rd == rm) {
53445285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            tmp2 = neon_load_scratch(2);
53458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        } else {
53468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            tmp2 = neon_load_reg(rm, pass);
53478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        }
53488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        if (prewiden) {
53498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            gen_neon_widen(cpu_V1, tmp2, size, u);
53508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        }
53518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
53528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    switch (op) {
53538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    case 0: case 1: case 4: /* VADDL, VADDW, VADDHN, VRADDHN */
53548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        gen_neon_addl(size);
53558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        break;
53565285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    case 2: case 3: case 6: /* VSUBL, VSUBW, VSUBHN, VRSUBHN */
53578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        gen_neon_subl(size);
53588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        break;
53598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    case 5: case 7: /* VABAL, VABDL */
53608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        switch ((size << 1) | u) {
53618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        case 0:
53628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            gen_helper_neon_abdl_s16(cpu_V0, tmp, tmp2);
53638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            break;
53648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        case 1:
53658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            gen_helper_neon_abdl_u16(cpu_V0, tmp, tmp2);
53668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            break;
53678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        case 2:
53688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            gen_helper_neon_abdl_s32(cpu_V0, tmp, tmp2);
53698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            break;
53708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        case 3:
53718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            gen_helper_neon_abdl_u32(cpu_V0, tmp, tmp2);
53728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            break;
53738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        case 4:
53748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            gen_helper_neon_abdl_s64(cpu_V0, tmp, tmp2);
53758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            break;
53768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        case 5:
53778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            gen_helper_neon_abdl_u64(cpu_V0, tmp, tmp2);
53788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            break;
53798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        default: abort();
53808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        }
53815285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tcg_temp_free_i32(tmp2);
53825285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tcg_temp_free_i32(tmp);
53838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        break;
53848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    case 8: case 9: case 10: case 11: case 12: case 13:
53858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        /* VMLAL, VQDMLAL, VMLSL, VQDMLSL, VMULL, VQDMULL */
53868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        gen_neon_mull(cpu_V0, tmp, tmp2, size, u);
53878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        break;
53888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    case 14: /* Polynomial VMULL */
53895285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        gen_helper_neon_mull_p8(cpu_V0, tmp, tmp2);
53905285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tcg_temp_free_i32(tmp2);
53915285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tcg_temp_free_i32(tmp);
53925285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        break;
53935285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    default: /* 15 is RESERVED: caught earlier  */
53945285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        abort();
53955285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    }
53965285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    if (op == 13) {
53975285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        /* VQDMULL */
53985285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
53995285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        neon_store_reg64(cpu_V0, rd + pass);
54005285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    } else if (op == 5 || (op >= 8 && op <= 11)) {
54015285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        /* Accumulate.  */
54025285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        neon_load_reg64(cpu_V1, rd + pass);
54038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        switch (op) {
54045285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        case 10: /* VMLSL */
54055285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            gen_neon_negl(cpu_V0, size);
54065285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            /* Fall through */
54075285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        case 5: case 8: /* VABAL, VMLAL */
54088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            gen_neon_addl(size);
54098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            break;
54108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        case 9: case 11: /* VQDMLAL, VQDMLSL */
54118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
54125285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            if (op == 11) {
54135285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                                gen_neon_negl(cpu_V0, size);
54145285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            }
54158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            gen_neon_addl_saturate(cpu_V0, cpu_V1, size);
54168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            break;
54178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        default:
54188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            abort();
54198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        }
54208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        neon_store_reg64(cpu_V0, rd + pass);
54218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    } else if (op == 4 || op == 6) {
54228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        /* Narrowing operation.  */
54235285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tmp = tcg_temp_new_i32();
54245285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        if (!u) {
54258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            switch (size) {
54268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            case 0:
54278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                gen_helper_neon_narrow_high_u8(tmp, cpu_V0);
54288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                break;
54298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            case 1:
54308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                gen_helper_neon_narrow_high_u16(tmp, cpu_V0);
54318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                break;
54328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            case 2:
54338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                tcg_gen_shri_i64(cpu_V0, cpu_V0, 32);
54348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                tcg_gen_trunc_i64_i32(tmp, cpu_V0);
54358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                break;
54368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            default: abort();
54378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            }
54388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        } else {
54398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            switch (size) {
54408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            case 0:
54418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                gen_helper_neon_narrow_round_high_u8(tmp, cpu_V0);
54428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                break;
54438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            case 1:
54448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                gen_helper_neon_narrow_round_high_u16(tmp, cpu_V0);
54458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                break;
54468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            case 2:
54478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                tcg_gen_addi_i64(cpu_V0, cpu_V0, 1u << 31);
54488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                tcg_gen_shri_i64(cpu_V0, cpu_V0, 32);
54498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                tcg_gen_trunc_i64_i32(tmp, cpu_V0);
54508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                break;
54518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            default: abort();
54528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            }
54538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        }
54548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        if (pass == 0) {
54558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            tmp3 = tmp;
54568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        } else {
54578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            neon_store_reg(rd, 0, tmp3);
54588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            neon_store_reg(rd, 1, tmp);
54598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        }
54608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    } else {
54618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        /* Write back the result.  */
54628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        neon_store_reg64(cpu_V0, rd + pass);
54638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
54648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
54658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            } else {
54665285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                /* Two registers and a scalar. NB that for ops of this form
54675285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                 * the ARM ARM labels bit 24 as Q, but it is in our variable
54685285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                 * 'u', not 'q'.
54695285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                 */
54705285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                if (size == 0) {
54715285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    return 1;
54725285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                }
54738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                switch (op) {
54748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                case 1: /* Float VMLA scalar */
54758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                case 5: /* Floating point VMLS scalar */
54768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                case 9: /* Floating point VMUL scalar */
54775285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    if (size == 1) {
54785285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        return 1;
54795285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    }
54805285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    /* fall through */
54815285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                case 0: /* Integer VMLA scalar */
54825285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                case 4: /* Integer VMLS scalar */
54835285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                case 8: /* Integer VMUL scalar */
54848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                case 12: /* VQDMULH scalar */
54858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                case 13: /* VQRDMULH scalar */
54865285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    if (u && ((rd | rn) & 1)) {
54875285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        return 1;
54885285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    }
54895285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tmp = neon_get_scalar(size, rm);
54905285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    neon_store_scratch(0, tmp);
54918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    for (pass = 0; pass < (u ? 4 : 2); pass++) {
54925285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tmp = neon_load_scratch(0);
54935285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tmp2 = neon_load_reg(rn, pass);
54948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        if (op == 12) {
54958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            if (size == 1) {
54965285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                                gen_helper_neon_qdmulh_s16(tmp, tmp, tmp2);
54978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            } else {
54985285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                                gen_helper_neon_qdmulh_s32(tmp, tmp, tmp2);
54998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            }
55008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        } else if (op == 13) {
55018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            if (size == 1) {
55025285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                                gen_helper_neon_qrdmulh_s16(tmp, tmp, tmp2);
55038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            } else {
55045285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                                gen_helper_neon_qrdmulh_s32(tmp, tmp, tmp2);
55058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            }
55068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        } else if (op & 1) {
55075285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            gen_helper_neon_mul_f32(tmp, tmp, tmp2);
55088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        } else {
55098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            switch (size) {
55105285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            case 0: gen_helper_neon_mul_u8(tmp, tmp, tmp2); break;
55115285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            case 1: gen_helper_neon_mul_u16(tmp, tmp, tmp2); break;
55125285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            case 2: tcg_gen_mul_i32(tmp, tmp, tmp2); break;
55135285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            default: abort();
55148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            }
55158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        }
55165285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tcg_temp_free_i32(tmp2);
55178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        if (op < 8) {
55188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            /* Accumulate.  */
55195285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            tmp2 = neon_load_reg(rd, pass);
55208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            switch (op) {
55218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            case 0:
55225285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                                gen_neon_add(size, tmp, tmp2);
55238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                break;
55248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            case 1:
55255285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                                gen_helper_neon_add_f32(tmp, tmp, tmp2);
55268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                break;
55278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            case 4:
55285285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                                gen_neon_rsb(size, tmp, tmp2);
55298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                break;
55308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            case 5:
55315285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                                gen_helper_neon_sub_f32(tmp, tmp2, tmp);
55328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                break;
55338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            default:
55348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                abort();
55358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            }
55365285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            tcg_temp_free_i32(tmp2);
55378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        }
55385285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        neon_store_reg(rd, pass, tmp);
55398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
55408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    break;
55418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                case 3: /* VQDMLAL scalar */
55428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                case 7: /* VQDMLSL scalar */
55438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                case 11: /* VQDMULL scalar */
55445285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    if (u == 1) {
55458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        return 1;
55465285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    }
55475285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    /* fall through */
55485285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                case 2: /* VMLAL sclar */
55495285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                case 6: /* VMLSL scalar */
55505285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                case 10: /* VMULL scalar */
55515285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    if (rd & 1) {
55525285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        return 1;
55535285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    }
55545285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tmp2 = neon_get_scalar(size, rm);
55555285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    /* We need a copy of tmp2 because gen_neon_mull
55565285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                     * deletes it during pass 0.  */
55575285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tmp4 = tcg_temp_new_i32();
55585285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tcg_gen_mov_i32(tmp4, tmp2);
55595285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tmp3 = neon_load_reg(rn, 1);
55608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
55618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    for (pass = 0; pass < 2; pass++) {
55628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        if (pass == 0) {
55638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            tmp = neon_load_reg(rn, 0);
55648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        } else {
55655285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            tmp = tmp3;
55665285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            tmp2 = tmp4;
55678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        }
55688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        gen_neon_mull(cpu_V0, tmp, tmp2, size, u);
55698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        if (op != 11) {
55708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            neon_load_reg64(cpu_V1, rd + pass);
55718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        }
55728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        switch (op) {
55735285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        case 6:
55745285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            gen_neon_negl(cpu_V0, size);
55755285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            /* Fall through */
55765285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        case 2:
55778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            gen_neon_addl(size);
55788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            break;
55798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        case 3: case 7:
55808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
55815285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            if (op == 7) {
55825285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                                gen_neon_negl(cpu_V0, size);
55835285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            }
55848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            gen_neon_addl_saturate(cpu_V0, cpu_V1, size);
55858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            break;
55868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        case 10:
55878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            /* no-op */
55888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            break;
55898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        case 11:
55908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
55918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            break;
55928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        default:
55938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            abort();
55948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        }
55958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        neon_store_reg64(cpu_V0, rd + pass);
55968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
55975285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
55985285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
55998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    break;
56008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                default: /* 14 and 15 are RESERVED */
56018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    return 1;
56028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
56038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
56048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        } else { /* size == 3 */
56058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (!u) {
56068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* Extract.  */
56078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                imm = (insn >> 8) & 0xf;
56088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
56098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (imm > 7 && !q)
56108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    return 1;
56118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
56125285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                if (q && ((rd | rn | rm) & 1)) {
56135285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    return 1;
56145285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                }
56155285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
56168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (imm == 0) {
56178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    neon_load_reg64(cpu_V0, rn);
56188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if (q) {
56198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        neon_load_reg64(cpu_V1, rn + 1);
56208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
56218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                } else if (imm == 8) {
56228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    neon_load_reg64(cpu_V0, rn + 1);
56238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if (q) {
56248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        neon_load_reg64(cpu_V1, rm);
56258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
56268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                } else if (q) {
56275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                    tmp64 = tcg_temp_new_i64();
56288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if (imm < 8) {
56298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        neon_load_reg64(cpu_V0, rn);
56305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                        neon_load_reg64(tmp64, rn + 1);
56318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    } else {
56328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        neon_load_reg64(cpu_V0, rn + 1);
56335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                        neon_load_reg64(tmp64, rm);
56348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
56358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    tcg_gen_shri_i64(cpu_V0, cpu_V0, (imm & 7) * 8);
56365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                    tcg_gen_shli_i64(cpu_V1, tmp64, 64 - ((imm & 7) * 8));
56378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    tcg_gen_or_i64(cpu_V0, cpu_V0, cpu_V1);
56388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if (imm < 8) {
56398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        neon_load_reg64(cpu_V1, rm);
56408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    } else {
56418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        neon_load_reg64(cpu_V1, rm + 1);
56428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        imm -= 8;
56438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
56448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    tcg_gen_shli_i64(cpu_V1, cpu_V1, 64 - (imm * 8));
56455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                    tcg_gen_shri_i64(tmp64, tmp64, imm * 8);
56465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                    tcg_gen_or_i64(cpu_V1, cpu_V1, tmp64);
56475285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tcg_temp_free_i64(tmp64);
56488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                } else {
56495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                    /* BUGFIX */
56508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    neon_load_reg64(cpu_V0, rn);
56515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                    tcg_gen_shri_i64(cpu_V0, cpu_V0, imm * 8);
56528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    neon_load_reg64(cpu_V1, rm);
56535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                    tcg_gen_shli_i64(cpu_V1, cpu_V1, 64 - (imm * 8));
56548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    tcg_gen_or_i64(cpu_V0, cpu_V0, cpu_V1);
56558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
56568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                neon_store_reg64(cpu_V0, rd);
56578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (q) {
56588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    neon_store_reg64(cpu_V1, rd + 1);
56598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
56608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            } else if ((insn & (1 << 11)) == 0) {
56618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* Two register misc.  */
56628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                op = ((insn >> 12) & 0x30) | ((insn >> 7) & 0xf);
56638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                size = (insn >> 18) & 3;
56645285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                /* UNDEF for unknown op values and bad op-size combinations */
56655285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                if ((neon_2rm_sizes[op] & (1 << size)) == 0) {
56665285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    return 1;
56675285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                }
56685285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                if ((op != NEON_2RM_VMOVN && op != NEON_2RM_VQMOVN) &&
56695285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    q && ((rm | rd) & 1)) {
56705285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    return 1;
56715285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                }
56728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                switch (op) {
56735285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                case NEON_2RM_VREV64:
56748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    for (pass = 0; pass < (q ? 2 : 1); pass++) {
56755285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tmp = neon_load_reg(rm, pass * 2);
56765285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tmp2 = neon_load_reg(rm, pass * 2 + 1);
56778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        switch (size) {
56785285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        case 0: tcg_gen_bswap32_i32(tmp, tmp); break;
56795285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        case 1: gen_swap_half(tmp); break;
56808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        case 2: /* no-op */ break;
56818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        default: abort();
56828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        }
56835285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        neon_store_reg(rd, pass * 2 + 1, tmp);
56848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        if (size == 2) {
56855285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            neon_store_reg(rd, pass * 2, tmp2);
56868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        } else {
56878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            switch (size) {
56885285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            case 0: tcg_gen_bswap32_i32(tmp2, tmp2); break;
56895285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            case 1: gen_swap_half(tmp2); break;
56908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            default: abort();
56918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            }
56925285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            neon_store_reg(rd, pass * 2, tmp2);
56938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        }
56948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
56958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    break;
56965285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                case NEON_2RM_VPADDL: case NEON_2RM_VPADDL_U:
56975285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                case NEON_2RM_VPADAL: case NEON_2RM_VPADAL_U:
56988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    for (pass = 0; pass < q + 1; pass++) {
56998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        tmp = neon_load_reg(rm, pass * 2);
57008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        gen_neon_widen(cpu_V0, tmp, size, op & 1);
57018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        tmp = neon_load_reg(rm, pass * 2 + 1);
57028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        gen_neon_widen(cpu_V1, tmp, size, op & 1);
57038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        switch (size) {
57048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        case 0: gen_helper_neon_paddl_u16(CPU_V001); break;
57058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        case 1: gen_helper_neon_paddl_u32(CPU_V001); break;
57068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        case 2: tcg_gen_add_i64(CPU_V001); break;
57078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        default: abort();
57088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        }
57095285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        if (op >= NEON_2RM_VPADAL) {
57108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            /* Accumulate.  */
57118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            neon_load_reg64(cpu_V1, rd + pass);
57128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            gen_neon_addl(size);
57138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        }
57148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        neon_store_reg64(cpu_V0, rd + pass);
57158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
57168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    break;
57175285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                case NEON_2RM_VTRN:
57188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if (size == 2) {
57195285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        int n;
57208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        for (n = 0; n < (q ? 4 : 2); n += 2) {
57215285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            tmp = neon_load_reg(rm, n);
57225285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            tmp2 = neon_load_reg(rd, n + 1);
57235285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            neon_store_reg(rm, n, tmp2);
57245285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            neon_store_reg(rd, n + 1, tmp);
57258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        }
57268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    } else {
57278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        goto elementwise;
57288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
57298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    break;
57305285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                case NEON_2RM_VUZP:
57315285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    if (gen_neon_unzip(rd, rm, size, q)) {
57328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        return 1;
57338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
57348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    break;
57355285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                case NEON_2RM_VZIP:
57365285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    if (gen_neon_zip(rd, rm, size, q)) {
57378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        return 1;
57388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
57398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    break;
57405285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                case NEON_2RM_VMOVN: case NEON_2RM_VQMOVN:
57415285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    /* also VQMOVUN; op field and mnemonics don't line up */
57425285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    if (rm & 1) {
57438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        return 1;
57445285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    }
57458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    TCGV_UNUSED(tmp2);
57468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    for (pass = 0; pass < 2; pass++) {
57478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        neon_load_reg64(cpu_V0, rm + pass);
57485285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tmp = tcg_temp_new_i32();
57495285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        gen_neon_narrow_op(op == NEON_2RM_VMOVN, q, size,
57505285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                                           tmp, cpu_V0);
57518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        if (pass == 0) {
57528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            tmp2 = tmp;
57538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        } else {
57548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            neon_store_reg(rd, 0, tmp2);
57558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            neon_store_reg(rd, 1, tmp);
57568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        }
57578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
57588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    break;
57595285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                case NEON_2RM_VSHLL:
57605285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    if (q || (rd & 1)) {
57618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        return 1;
57625285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    }
57638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    tmp = neon_load_reg(rm, 0);
57648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    tmp2 = neon_load_reg(rm, 1);
57658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    for (pass = 0; pass < 2; pass++) {
57668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        if (pass == 1)
57678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            tmp = tmp2;
57688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        gen_neon_widen(cpu_V0, tmp, size, 1);
57695285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tcg_gen_shli_i64(cpu_V0, cpu_V0, 8 << size);
57708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        neon_store_reg64(cpu_V0, rd + pass);
57718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
57728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    break;
57735285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                case NEON_2RM_VCVT_F16_F32:
57745285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    if (!arm_feature(env, ARM_FEATURE_VFP_FP16) ||
57755285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        q || (rm & 1)) {
57765285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        return 1;
57775285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    }
57785285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tmp = tcg_temp_new_i32();
57795285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tmp2 = tcg_temp_new_i32();
57805285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, 0));
57815285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    gen_helper_neon_fcvt_f32_to_f16(tmp, cpu_F0s, cpu_env);
57825285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, 1));
57835285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    gen_helper_neon_fcvt_f32_to_f16(tmp2, cpu_F0s, cpu_env);
57845285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tcg_gen_shli_i32(tmp2, tmp2, 16);
57855285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tcg_gen_or_i32(tmp2, tmp2, tmp);
57865285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, 2));
57875285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    gen_helper_neon_fcvt_f32_to_f16(tmp, cpu_F0s, cpu_env);
57885285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, 3));
57895285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    neon_store_reg(rd, 0, tmp2);
57905285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tmp2 = tcg_temp_new_i32();
57915285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    gen_helper_neon_fcvt_f32_to_f16(tmp2, cpu_F0s, cpu_env);
57925285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tcg_gen_shli_i32(tmp2, tmp2, 16);
57935285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tcg_gen_or_i32(tmp2, tmp2, tmp);
57945285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    neon_store_reg(rd, 1, tmp2);
57955285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tcg_temp_free_i32(tmp);
57965285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    break;
57975285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                case NEON_2RM_VCVT_F32_F16:
57985285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    if (!arm_feature(env, ARM_FEATURE_VFP_FP16) ||
57995285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        q || (rd & 1)) {
58005285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        return 1;
58015285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    }
58025285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tmp3 = tcg_temp_new_i32();
58035285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tmp = neon_load_reg(rm, 0);
58045285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tmp2 = neon_load_reg(rm, 1);
58055285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tcg_gen_ext16u_i32(tmp3, tmp);
58065285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    gen_helper_neon_fcvt_f16_to_f32(cpu_F0s, tmp3, cpu_env);
58075285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, 0));
58085285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tcg_gen_shri_i32(tmp3, tmp, 16);
58095285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    gen_helper_neon_fcvt_f16_to_f32(cpu_F0s, tmp3, cpu_env);
58105285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, 1));
58115285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tcg_temp_free_i32(tmp);
58125285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tcg_gen_ext16u_i32(tmp3, tmp2);
58135285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    gen_helper_neon_fcvt_f16_to_f32(cpu_F0s, tmp3, cpu_env);
58145285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, 2));
58155285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tcg_gen_shri_i32(tmp3, tmp2, 16);
58165285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    gen_helper_neon_fcvt_f16_to_f32(cpu_F0s, tmp3, cpu_env);
58175285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, 3));
58185285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tcg_temp_free_i32(tmp2);
58195285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tcg_temp_free_i32(tmp3);
58205285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    break;
58218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                default:
58228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                elementwise:
58238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    for (pass = 0; pass < (q ? 4 : 2); pass++) {
58245285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        if (neon_2rm_is_float_op(op)) {
58258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            tcg_gen_ld_f32(cpu_F0s, cpu_env,
58268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                           neon_reg_offset(rm, pass));
58275285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            TCGV_UNUSED(tmp);
58288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        } else {
58295285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            tmp = neon_load_reg(rm, pass);
58308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        }
58318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        switch (op) {
58325285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        case NEON_2RM_VREV32:
58338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            switch (size) {
58345285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            case 0: tcg_gen_bswap32_i32(tmp, tmp); break;
58355285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            case 1: gen_swap_half(tmp); break;
58365285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            default: abort();
58378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            }
58388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            break;
58395285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        case NEON_2RM_VREV16:
58405285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            gen_rev16(tmp);
58418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            break;
58425285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        case NEON_2RM_VCLS:
58438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            switch (size) {
58445285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            case 0: gen_helper_neon_cls_s8(tmp, tmp); break;
58455285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            case 1: gen_helper_neon_cls_s16(tmp, tmp); break;
58465285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            case 2: gen_helper_neon_cls_s32(tmp, tmp); break;
58475285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            default: abort();
58488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            }
58498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            break;
58505285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        case NEON_2RM_VCLZ:
58518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            switch (size) {
58525285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            case 0: gen_helper_neon_clz_u8(tmp, tmp); break;
58535285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            case 1: gen_helper_neon_clz_u16(tmp, tmp); break;
58545285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            case 2: gen_helper_clz(tmp, tmp); break;
58555285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            default: abort();
58568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            }
58578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            break;
58585285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        case NEON_2RM_VCNT:
58595285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            gen_helper_neon_cnt_u8(tmp, tmp);
58608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            break;
58615285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        case NEON_2RM_VMVN:
58625285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            tcg_gen_not_i32(tmp, tmp);
58638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            break;
58645285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        case NEON_2RM_VQABS:
58658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            switch (size) {
58665285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            case 0: gen_helper_neon_qabs_s8(tmp, tmp); break;
58675285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            case 1: gen_helper_neon_qabs_s16(tmp, tmp); break;
58685285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            case 2: gen_helper_neon_qabs_s32(tmp, tmp); break;
58695285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            default: abort();
58708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            }
58718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            break;
58725285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        case NEON_2RM_VQNEG:
58738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            switch (size) {
58745285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            case 0: gen_helper_neon_qneg_s8(tmp, tmp); break;
58755285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            case 1: gen_helper_neon_qneg_s16(tmp, tmp); break;
58765285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            case 2: gen_helper_neon_qneg_s32(tmp, tmp); break;
58775285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            default: abort();
58788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            }
58798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            break;
58805285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        case NEON_2RM_VCGT0: case NEON_2RM_VCLE0:
58815285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            tmp2 = tcg_const_i32(0);
58828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            switch(size) {
58835285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            case 0: gen_helper_neon_cgt_s8(tmp, tmp, tmp2); break;
58845285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            case 1: gen_helper_neon_cgt_s16(tmp, tmp, tmp2); break;
58855285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            case 2: gen_helper_neon_cgt_s32(tmp, tmp, tmp2); break;
58865285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            default: abort();
58875285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            }
58885285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            tcg_temp_free(tmp2);
58895285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            if (op == NEON_2RM_VCLE0) {
58905285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                                tcg_gen_not_i32(tmp, tmp);
58918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            }
58928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            break;
58935285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        case NEON_2RM_VCGE0: case NEON_2RM_VCLT0:
58945285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            tmp2 = tcg_const_i32(0);
58958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            switch(size) {
58965285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            case 0: gen_helper_neon_cge_s8(tmp, tmp, tmp2); break;
58975285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            case 1: gen_helper_neon_cge_s16(tmp, tmp, tmp2); break;
58985285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            case 2: gen_helper_neon_cge_s32(tmp, tmp, tmp2); break;
58995285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            default: abort();
59005285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            }
59015285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            tcg_temp_free(tmp2);
59025285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            if (op == NEON_2RM_VCLT0) {
59035285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                                tcg_gen_not_i32(tmp, tmp);
59048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            }
59058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            break;
59065285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        case NEON_2RM_VCEQ0:
59075285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            tmp2 = tcg_const_i32(0);
59088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            switch(size) {
59095285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            case 0: gen_helper_neon_ceq_u8(tmp, tmp, tmp2); break;
59105285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            case 1: gen_helper_neon_ceq_u16(tmp, tmp, tmp2); break;
59115285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            case 2: gen_helper_neon_ceq_u32(tmp, tmp, tmp2); break;
59125285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            default: abort();
59138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            }
59145285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            tcg_temp_free(tmp2);
59158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            break;
59165285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        case NEON_2RM_VABS:
59178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            switch(size) {
59185285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            case 0: gen_helper_neon_abs_s8(tmp, tmp); break;
59195285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            case 1: gen_helper_neon_abs_s16(tmp, tmp); break;
59205285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            case 2: tcg_gen_abs_i32(tmp, tmp); break;
59215285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            default: abort();
59228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            }
59238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            break;
59245285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        case NEON_2RM_VNEG:
59255285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            tmp2 = tcg_const_i32(0);
59265285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            gen_neon_rsb(size, tmp, tmp2);
59275285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            tcg_temp_free(tmp2);
59288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            break;
59295285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        case NEON_2RM_VCGT0_F:
59305285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            tmp2 = tcg_const_i32(0);
59315285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            gen_helper_neon_cgt_f32(tmp, tmp, tmp2);
59325285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            tcg_temp_free(tmp2);
59338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            break;
59345285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        case NEON_2RM_VCGE0_F:
59355285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            tmp2 = tcg_const_i32(0);
59365285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            gen_helper_neon_cge_f32(tmp, tmp, tmp2);
59375285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            tcg_temp_free(tmp2);
59388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            break;
59395285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        case NEON_2RM_VCEQ0_F:
59405285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            tmp2 = tcg_const_i32(0);
59415285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            gen_helper_neon_ceq_f32(tmp, tmp, tmp2);
59425285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            tcg_temp_free(tmp2);
59438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            break;
59445285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        case NEON_2RM_VCLE0_F:
59455285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            tmp2 = tcg_const_i32(0);
59465285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            gen_helper_neon_cge_f32(tmp, tmp2, tmp);
59475285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            tcg_temp_free(tmp2);
59485285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            break;
59495285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        case NEON_2RM_VCLT0_F:
59505285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            tmp2 = tcg_const_i32(0);
59515285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            gen_helper_neon_cgt_f32(tmp, tmp2, tmp);
59525285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            tcg_temp_free(tmp2);
59535285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            break;
59545285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        case NEON_2RM_VABS_F:
59558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            gen_vfp_abs(0);
59568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            break;
59575285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        case NEON_2RM_VNEG_F:
59588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            gen_vfp_neg(0);
59598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            break;
59605285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        case NEON_2RM_VSWP:
59615285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            tmp2 = neon_load_reg(rd, pass);
59625285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            neon_store_reg(rm, pass, tmp2);
59638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            break;
59645285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        case NEON_2RM_VTRN:
59655285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            tmp2 = neon_load_reg(rd, pass);
59668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            switch (size) {
59675285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            case 0: gen_neon_trn_u8(tmp, tmp2); break;
59685285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            case 1: gen_neon_trn_u16(tmp, tmp2); break;
59695285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            default: abort();
59708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            }
59715285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            neon_store_reg(rm, pass, tmp2);
59728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            break;
59735285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        case NEON_2RM_VRECPE:
59745285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            gen_helper_recpe_u32(tmp, tmp, cpu_env);
59758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            break;
59765285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        case NEON_2RM_VRSQRTE:
59775285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            gen_helper_rsqrte_u32(tmp, tmp, cpu_env);
59788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            break;
59795285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        case NEON_2RM_VRECPE_F:
59808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            gen_helper_recpe_f32(cpu_F0s, cpu_F0s, cpu_env);
59818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            break;
59825285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        case NEON_2RM_VRSQRTE_F:
59838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            gen_helper_rsqrte_f32(cpu_F0s, cpu_F0s, cpu_env);
59848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            break;
59855285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        case NEON_2RM_VCVT_FS: /* VCVT.F32.S32 */
59865285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            gen_vfp_sito(0, 1);
59878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            break;
59885285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        case NEON_2RM_VCVT_FU: /* VCVT.F32.U32 */
59895285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            gen_vfp_uito(0, 1);
59908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            break;
59915285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        case NEON_2RM_VCVT_SF: /* VCVT.S32.F32 */
59925285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            gen_vfp_tosiz(0, 1);
59938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            break;
59945285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        case NEON_2RM_VCVT_UF: /* VCVT.U32.F32 */
59955285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            gen_vfp_touiz(0, 1);
59968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            break;
59978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        default:
59985285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            /* Reserved op values were caught by the
59995285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                             * neon_2rm_sizes[] check earlier.
60005285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                             */
60015285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            abort();
60028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        }
60035285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        if (neon_2rm_is_float_op(op)) {
60048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            tcg_gen_st_f32(cpu_F0s, cpu_env,
60058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                           neon_reg_offset(rd, pass));
60068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        } else {
60075285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            neon_store_reg(rd, pass, tmp);
60088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        }
60098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
60108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    break;
60118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
60128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            } else if ((insn & (1 << 10)) == 0) {
60138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* VTBL, VTBX.  */
60145285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                int n = ((insn >> 8) & 3) + 1;
60155285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                if ((rn + n) > 32) {
60165285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    /* This is UNPREDICTABLE; we choose to UNDEF to avoid the
60175285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                     * helper function running off the end of the register file.
60185285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                     */
60195285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    return 1;
60205285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                }
60215285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                n <<= 3;
60228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (insn & (1 << 6)) {
60238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    tmp = neon_load_reg(rd, 0);
60248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                } else {
60255285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tmp = tcg_temp_new_i32();
60268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    tcg_gen_movi_i32(tmp, 0);
60278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
60288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                tmp2 = neon_load_reg(rm, 0);
60295285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tmp4 = tcg_const_i32(rn);
60305285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tmp5 = tcg_const_i32(n);
60315285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                gen_helper_neon_tbl(tmp2, tmp2, tmp, tmp4, tmp5);
60325285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_temp_free_i32(tmp);
60338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (insn & (1 << 6)) {
60348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    tmp = neon_load_reg(rd, 1);
60358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                } else {
60365285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tmp = tcg_temp_new_i32();
60378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    tcg_gen_movi_i32(tmp, 0);
60388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
60398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                tmp3 = neon_load_reg(rm, 1);
60405285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                gen_helper_neon_tbl(tmp3, tmp3, tmp, tmp4, tmp5);
60415285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_temp_free_i32(tmp5);
60425285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_temp_free_i32(tmp4);
60438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                neon_store_reg(rd, 0, tmp2);
60445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                neon_store_reg(rd, 1, tmp3);
60455285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_temp_free_i32(tmp);
60468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            } else if ((insn & 0x380) == 0) {
60478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* VDUP */
60485285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                if ((insn & (7 << 16)) == 0 || (q && (rd & 1))) {
60495285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    return 1;
60505285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                }
60518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (insn & (1 << 19)) {
60525285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tmp = neon_load_reg(rm, 1);
60538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                } else {
60545285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tmp = neon_load_reg(rm, 0);
60558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
60568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (insn & (1 << 16)) {
60575285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    gen_neon_dup_u8(tmp, ((insn >> 17) & 3) * 8);
60588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                } else if (insn & (1 << 17)) {
60598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if ((insn >> 18) & 1)
60605285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        gen_neon_dup_high16(tmp);
60618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    else
60625285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        gen_neon_dup_low16(tmp);
60638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
60648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                for (pass = 0; pass < (q ? 4 : 2); pass++) {
60655285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tmp2 = tcg_temp_new_i32();
60665285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tcg_gen_mov_i32(tmp2, tmp);
60675285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    neon_store_reg(rd, pass, tmp2);
60688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
60695285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_temp_free_i32(tmp);
60708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            } else {
60718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                return 1;
60728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
60738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
60748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
60758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
60768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
60778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
60785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic int disas_cp14_read(CPUState * env, DisasContext *s, uint32_t insn)
60795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
60805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int crn = (insn >> 16) & 0xf;
60815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int crm = insn & 0xf;
60825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int op1 = (insn >> 21) & 7;
60835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int op2 = (insn >> 5) & 7;
60845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int rt = (insn >> 12) & 0xf;
60855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    TCGv tmp;
60865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
60875285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    /* Minimal set of debug registers, since we don't support debug */
60885285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    if (op1 == 0 && crn == 0 && op2 == 0) {
60895285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        switch (crm) {
60905285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        case 0:
60915285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            /* DBGDIDR: just RAZ. In particular this means the
60925285864985be9077e58e42235af6582dee72e841David 'Digit' Turner             * "debug architecture version" bits will read as
60935285864985be9077e58e42235af6582dee72e841David 'Digit' Turner             * a reserved value, which should cause Linux to
60945285864985be9077e58e42235af6582dee72e841David 'Digit' Turner             * not try to use the debug hardware.
60955285864985be9077e58e42235af6582dee72e841David 'Digit' Turner             */
60965285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tmp = tcg_const_i32(0);
60975285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            store_reg(s, rt, tmp);
60985285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            return 0;
60995285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        case 1:
61005285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        case 2:
61015285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            /* DBGDRAR and DBGDSAR: v7 only. Always RAZ since we
61025285864985be9077e58e42235af6582dee72e841David 'Digit' Turner             * don't implement memory mapped debug components
61035285864985be9077e58e42235af6582dee72e841David 'Digit' Turner             */
61045285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            if (ENABLE_ARCH_7) {
61055285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tmp = tcg_const_i32(0);
61065285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                store_reg(s, rt, tmp);
61075285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                return 0;
61085285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            }
61095285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            break;
61105285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        default:
61115285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            break;
61125285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        }
61135285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    }
61145285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
61155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (arm_feature(env, ARM_FEATURE_THUMB2EE)) {
61165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (op1 == 6 && crn == 0 && crm == 0 && op2 == 0) {
61175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            /* TEECR */
61185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            if (IS_USER(s))
61195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                return 1;
61205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            tmp = load_cpu_field(teecr);
61215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            store_reg(s, rt, tmp);
61225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            return 0;
61235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        }
61245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (op1 == 6 && crn == 1 && crm == 0 && op2 == 0) {
61255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            /* TEEHBR */
61265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            if (IS_USER(s) && (env->teecr & 1))
61275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                return 1;
61285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            tmp = load_cpu_field(teehbr);
61295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            store_reg(s, rt, tmp);
61305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            return 0;
61315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        }
61325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
61335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    fprintf(stderr, "Unknown cp14 read op1:%d crn:%d crm:%d op2:%d\n",
61345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            op1, crn, crm, op2);
61355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return 1;
61365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
61375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
61385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic int disas_cp14_write(CPUState * env, DisasContext *s, uint32_t insn)
61395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
61405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int crn = (insn >> 16) & 0xf;
61415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int crm = insn & 0xf;
61425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int op1 = (insn >> 21) & 7;
61435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int op2 = (insn >> 5) & 7;
61445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int rt = (insn >> 12) & 0xf;
61455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    TCGv tmp;
61465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
61475285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    /* Minimal set of debug registers, since we don't support debug */
61485285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    if (op1 == 0 && crn == 0 && op2 == 0) {
61495285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        switch (crm) {
61505285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        case 0:
61515285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            /* DBGDIDR */
61525285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tmp = load_cpu_field(cp14_dbgdidr);
61535285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            store_reg(s, rt, tmp);
61545285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            return 0;
61555285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        case 1:
61565285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        case 2:
61575285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            /* DBGDRAR and DBGDSAR: v7 only. Always RAZ since we
61585285864985be9077e58e42235af6582dee72e841David 'Digit' Turner             * don't implement memory mapped debug components
61595285864985be9077e58e42235af6582dee72e841David 'Digit' Turner             */
61605285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            if (ENABLE_ARCH_7) {
61615285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tmp = tcg_const_i32(0);
61625285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                store_reg(s, rt, tmp);
61635285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                return 0;
61645285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            }
61655285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            break;
61665285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        default:
61675285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            break;
61685285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        }
61695285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    }
61705285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
61715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (arm_feature(env, ARM_FEATURE_THUMB2EE)) {
61725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (op1 == 6 && crn == 0 && crm == 0 && op2 == 0) {
61735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            /* TEECR */
61745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            if (IS_USER(s))
61755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                return 1;
61765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            tmp = load_reg(s, rt);
61775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            gen_helper_set_teecr(cpu_env, tmp);
61785285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tcg_temp_free_i32(tmp);
61795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            return 0;
61805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        }
61815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (op1 == 6 && crn == 1 && crm == 0 && op2 == 0) {
61825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            /* TEEHBR */
61835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            if (IS_USER(s) && (env->teecr & 1))
61845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                return 1;
61855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            tmp = load_reg(s, rt);
61865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            store_cpu_field(tmp, teehbr);
61875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            return 0;
61885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        }
61895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    }
61905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    fprintf(stderr, "Unknown cp14 write op1:%d crn:%d crm:%d op2:%d\n",
61915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            op1, crn, crm, op2);
61925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return 1;
61935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
61945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
61958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int disas_coproc_insn(CPUState * env, DisasContext *s, uint32_t insn)
61968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
61978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int cpnum;
61988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
61998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    cpnum = (insn >> 8) & 0xf;
62008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (arm_feature(env, ARM_FEATURE_XSCALE)
62018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	    && ((env->cp15.c15_cpar ^ 0x3fff) & (1 << cpnum)))
62028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	return 1;
62038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
62048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    switch (cpnum) {
62058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      case 0:
62068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      case 1:
62078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
62088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	    return disas_iwmmxt_insn(env, s, insn);
62098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	} else if (arm_feature(env, ARM_FEATURE_XSCALE)) {
62108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	    return disas_dsp_insn(env, s, insn);
62118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	}
62125285864985be9077e58e42235af6582dee72e841David 'Digit' Turner	goto board;
62138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 10:
62148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 11:
62158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	return disas_vfp_insn (env, s, insn);
62165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    case 14:
62175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        /* Coprocessors 7-15 are architecturally reserved by ARM.
62185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner           Unfortunately Intel decided to ignore this.  */
62195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (arm_feature(env, ARM_FEATURE_XSCALE))
62205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            goto board;
62215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (insn & (1 << 20))
62225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            return disas_cp14_read(env, s, insn);
62235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        else
62245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            return disas_cp14_write(env, s, insn);
62258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 15:
62268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	return disas_cp15_insn (env, s, insn);
62278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    default:
62285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    board:
62298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	/* Unknown coprocessor.  See if the board has hooked it.  */
62308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	return disas_cp_insn (env, s, insn);
62318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
62328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
62338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
62348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
62358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Store a 64-bit value to a register pair.  Clobbers val.  */
62365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void gen_storeq_reg(DisasContext *s, int rlow, int rhigh, TCGv_i64 val)
62378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
62388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    TCGv tmp;
62395285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tmp = tcg_temp_new_i32();
62408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_gen_trunc_i64_i32(tmp, val);
62418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    store_reg(s, rlow, tmp);
62425285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tmp = tcg_temp_new_i32();
62438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_gen_shri_i64(val, val, 32);
62448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_gen_trunc_i64_i32(tmp, val);
62458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    store_reg(s, rhigh, tmp);
62468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
62478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
62488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* load a 32-bit value from a register and perform a 64-bit accumulate.  */
62495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void gen_addq_lo(DisasContext *s, TCGv_i64 val, int rlow)
62508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
62515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    TCGv_i64 tmp;
62528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    TCGv tmp2;
62538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
62545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    /* Load value and extend to 64 bits.  */
62555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    tmp = tcg_temp_new_i64();
62568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tmp2 = load_reg(s, rlow);
62578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_gen_extu_i32_i64(tmp, tmp2);
62585285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_temp_free_i32(tmp2);
62598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_gen_add_i64(val, val, tmp);
62605285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_temp_free_i64(tmp);
62618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
62628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
62638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* load and add a 64-bit value from a register pair.  */
62645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void gen_addq(DisasContext *s, TCGv_i64 val, int rlow, int rhigh)
62658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
62665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    TCGv_i64 tmp;
62675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    TCGv tmpl;
62685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    TCGv tmph;
62698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
62708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* Load 64-bit value rd:rn.  */
62715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    tmpl = load_reg(s, rlow);
62725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    tmph = load_reg(s, rhigh);
62735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    tmp = tcg_temp_new_i64();
62745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    tcg_gen_concat_i32_i64(tmp, tmpl, tmph);
62755285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_temp_free_i32(tmpl);
62765285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_temp_free_i32(tmph);
62778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcg_gen_add_i64(val, val, tmp);
62785285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_temp_free_i64(tmp);
62798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
62808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
62818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Set N and Z flags from a 64-bit value.  */
62825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void gen_logicq_cc(TCGv_i64 val)
62838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
62845285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    TCGv tmp = tcg_temp_new_i32();
62858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    gen_helper_logicq_cc(tmp, val);
62868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    gen_logic_CC(tmp);
62875285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_temp_free_i32(tmp);
62885285864985be9077e58e42235af6582dee72e841David 'Digit' Turner}
62895285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
62905285864985be9077e58e42235af6582dee72e841David 'Digit' Turner/* Load/Store exclusive instructions are implemented by remembering
62915285864985be9077e58e42235af6582dee72e841David 'Digit' Turner   the value/address loaded, and seeing if these are the same
62925285864985be9077e58e42235af6582dee72e841David 'Digit' Turner   when the store is performed. This should be is sufficient to implement
62935285864985be9077e58e42235af6582dee72e841David 'Digit' Turner   the architecturally mandated semantics, and avoids having to monitor
62945285864985be9077e58e42235af6582dee72e841David 'Digit' Turner   regular stores.
62955285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
62965285864985be9077e58e42235af6582dee72e841David 'Digit' Turner   In system emulation mode only one CPU will be running at once, so
62975285864985be9077e58e42235af6582dee72e841David 'Digit' Turner   this sequence is effectively atomic.  In user emulation mode we
62985285864985be9077e58e42235af6582dee72e841David 'Digit' Turner   throw an exception and handle the atomic operation elsewhere.  */
62995285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic void gen_load_exclusive(DisasContext *s, int rt, int rt2,
63005285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                               TCGv addr, int size)
63015285864985be9077e58e42235af6582dee72e841David 'Digit' Turner{
63025285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    TCGv tmp;
63035285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
63045285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    switch (size) {
63055285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    case 0:
63065285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tmp = gen_ld8u(addr, IS_USER(s));
63075285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        break;
63085285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    case 1:
63095285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tmp = gen_ld16u(addr, IS_USER(s));
63105285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        break;
63115285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    case 2:
63125285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    case 3:
63135285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tmp = gen_ld32(addr, IS_USER(s));
63145285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        break;
63155285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    default:
63165285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        abort();
63175285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    }
63185285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_gen_mov_i32(cpu_exclusive_val, tmp);
63195285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    store_reg(s, rt, tmp);
63205285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    if (size == 3) {
63215285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        TCGv tmp2 = tcg_temp_new_i32();
63225285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tcg_gen_addi_i32(tmp2, addr, 4);
63235285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tmp = gen_ld32(tmp2, IS_USER(s));
63245285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tcg_temp_free_i32(tmp2);
63255285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tcg_gen_mov_i32(cpu_exclusive_high, tmp);
63265285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        store_reg(s, rt2, tmp);
63275285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    }
63285285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_gen_mov_i32(cpu_exclusive_addr, addr);
63295285864985be9077e58e42235af6582dee72e841David 'Digit' Turner}
63305285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
63315285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic void gen_clrex(DisasContext *s)
63325285864985be9077e58e42235af6582dee72e841David 'Digit' Turner{
63335285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_gen_movi_i32(cpu_exclusive_addr, -1);
63348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
63358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
63365285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#ifdef CONFIG_USER_ONLY
63375285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic void gen_store_exclusive(DisasContext *s, int rd, int rt, int rt2,
63385285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                                TCGv addr, int size)
63395285864985be9077e58e42235af6582dee72e841David 'Digit' Turner{
63405285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_gen_mov_i32(cpu_exclusive_test, addr);
63415285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_gen_movi_i32(cpu_exclusive_info,
63425285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                     size | (rd << 4) | (rt << 8) | (rt2 << 12));
63435285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    gen_exception_insn(s, 4, EXCP_STREX);
63445285864985be9077e58e42235af6582dee72e841David 'Digit' Turner}
63455285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#else
63465285864985be9077e58e42235af6582dee72e841David 'Digit' Turnerstatic void gen_store_exclusive(DisasContext *s, int rd, int rt, int rt2,
63475285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                                TCGv addr, int size)
63485285864985be9077e58e42235af6582dee72e841David 'Digit' Turner{
63495285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    TCGv tmp;
63505285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    int done_label;
63515285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    int fail_label;
63525285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
63535285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    /* if (env->exclusive_addr == addr && env->exclusive_val == [addr]) {
63545285864985be9077e58e42235af6582dee72e841David 'Digit' Turner         [addr] = {Rt};
63555285864985be9077e58e42235af6582dee72e841David 'Digit' Turner         {Rd} = 0;
63565285864985be9077e58e42235af6582dee72e841David 'Digit' Turner       } else {
63575285864985be9077e58e42235af6582dee72e841David 'Digit' Turner         {Rd} = 1;
63585285864985be9077e58e42235af6582dee72e841David 'Digit' Turner       } */
63595285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    fail_label = gen_new_label();
63605285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    done_label = gen_new_label();
63615285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_gen_brcond_i32(TCG_COND_NE, addr, cpu_exclusive_addr, fail_label);
63625285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    switch (size) {
63635285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    case 0:
63645285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tmp = gen_ld8u(addr, IS_USER(s));
63655285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        break;
63665285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    case 1:
63675285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tmp = gen_ld16u(addr, IS_USER(s));
63685285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        break;
63695285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    case 2:
63705285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    case 3:
63715285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tmp = gen_ld32(addr, IS_USER(s));
63725285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        break;
63735285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    default:
63745285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        abort();
63755285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    }
63765285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_gen_brcond_i32(TCG_COND_NE, tmp, cpu_exclusive_val, fail_label);
63775285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_temp_free_i32(tmp);
63785285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    if (size == 3) {
63795285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        TCGv tmp2 = tcg_temp_new_i32();
63805285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tcg_gen_addi_i32(tmp2, addr, 4);
63815285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tmp = gen_ld32(tmp2, IS_USER(s));
63825285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tcg_temp_free_i32(tmp2);
63835285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tcg_gen_brcond_i32(TCG_COND_NE, tmp, cpu_exclusive_high, fail_label);
63845285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tcg_temp_free_i32(tmp);
63855285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    }
63865285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tmp = load_reg(s, rt);
63875285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    switch (size) {
63885285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    case 0:
63895285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        gen_st8(tmp, addr, IS_USER(s));
63905285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        break;
63915285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    case 1:
63925285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        gen_st16(tmp, addr, IS_USER(s));
63935285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        break;
63945285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    case 2:
63955285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    case 3:
63965285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        gen_st32(tmp, addr, IS_USER(s));
63975285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        break;
63985285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    default:
63995285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        abort();
64005285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    }
64015285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    if (size == 3) {
64025285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tcg_gen_addi_i32(addr, addr, 4);
64035285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tmp = load_reg(s, rt2);
64045285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        gen_st32(tmp, addr, IS_USER(s));
64055285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    }
64065285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_gen_movi_i32(cpu_R[rd], 0);
64075285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_gen_br(done_label);
64085285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    gen_set_label(fail_label);
64095285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_gen_movi_i32(cpu_R[rd], 1);
64105285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    gen_set_label(done_label);
64115285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_gen_movi_i32(cpu_exclusive_addr, -1);
64125285864985be9077e58e42235af6582dee72e841David 'Digit' Turner}
64135285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#endif
6414a577fcadc0b365ee629aec313f57a65d54fe5d89David 'Digit' Turner
64158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void disas_arm_insn(CPUState * env, DisasContext *s)
64168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
64178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    unsigned int cond, insn, val, op1, i, shift, rm, rs, rn, rd, sh;
6418288208c386810fef725aa448a9f46bd2772bec8cDavid 'Digit' Turner    ANDROID_TRACE_DECLS
64198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    TCGv tmp;
64208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    TCGv tmp2;
64218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    TCGv tmp3;
64228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    TCGv addr;
64235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    TCGv_i64 tmp64;
64245285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
64258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    insn = ldl_code(s->pc);
64265389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine
6427288208c386810fef725aa448a9f46bd2772bec8cDavid 'Digit' Turner    ANDROID_WATCH_CALLSTACK_ARM(s);
64285389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine
6429288208c386810fef725aa448a9f46bd2772bec8cDavid 'Digit' Turner    ANDROID_TRACE_START_ARM();
64305389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine
64318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    s->pc += 4;
64328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
64338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* M variants do not implement ARM mode.  */
64348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (IS_M(env))
64358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        goto illegal_op;
64368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    cond = insn >> 28;
64378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (cond == 0xf){
64385285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        /* In ARMv3 and v4 the NV condition is UNPREDICTABLE; we
64395285864985be9077e58e42235af6582dee72e841David 'Digit' Turner         * choose to UNDEF. In ARMv5 and above the space is used
64405285864985be9077e58e42235af6582dee72e841David 'Digit' Turner         * for miscellaneous unconditional instructions.
64415285864985be9077e58e42235af6582dee72e841David 'Digit' Turner         */
64425285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        ARCH(5);
64435285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
6444288208c386810fef725aa448a9f46bd2772bec8cDavid 'Digit' Turner        ANDROID_TRACE_GEN_TICKS();
64458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* Unconditional instructions.  */
64468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (((insn >> 25) & 7) == 1) {
64478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* NEON Data processing.  */
64488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (!arm_feature(env, ARM_FEATURE_NEON))
64498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                goto illegal_op;
64508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
64518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (disas_neon_data_insn(env, s, insn))
64528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                goto illegal_op;
64538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return;
64548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
64558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if ((insn & 0x0f100000) == 0x04000000) {
64568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* NEON load/store.  */
64578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (!arm_feature(env, ARM_FEATURE_NEON))
64588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                goto illegal_op;
64598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
64608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (disas_neon_ls_insn(env, s, insn))
64618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                goto illegal_op;
64628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return;
64638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
64645285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        if (((insn & 0x0f30f000) == 0x0510f000) ||
64655285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            ((insn & 0x0f30f010) == 0x0710f000)) {
64665285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            if ((insn & (1 << 22)) == 0) {
64675285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                /* PLDW; v7MP */
64685285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                if (!arm_feature(env, ARM_FEATURE_V7MP)) {
64695285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    goto illegal_op;
64705285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                }
64715285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            }
64725285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            /* Otherwise PLD; v5TE+ */
64735285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            ARCH(5TE);
64745285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            return;
64755285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        }
64765285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        if (((insn & 0x0f70f000) == 0x0450f000) ||
64775285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            ((insn & 0x0f70f010) == 0x0650f000)) {
64785285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            ARCH(7);
64795285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            return; /* PLI; V7 */
64805285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        }
64815285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        if (((insn & 0x0f700000) == 0x04100000) ||
64825285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            ((insn & 0x0f700010) == 0x06100000)) {
64835285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            if (!arm_feature(env, ARM_FEATURE_V7MP)) {
64845285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                goto illegal_op;
64855285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            }
64865285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            return; /* v7MP: Unallocated memory hint: must NOP */
64875285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        }
64885285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
64895285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        if ((insn & 0x0ffffdff) == 0x01010000) {
64908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            ARCH(6);
64918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* setend */
64928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (insn & (1 << 9)) {
64938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* BE8 mode not implemented.  */
64948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                goto illegal_op;
64958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
64968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return;
64978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        } else if ((insn & 0x0fffff00) == 0x057ff000) {
64988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            switch ((insn >> 4) & 0xf) {
64998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            case 1: /* clrex */
65008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                ARCH(6K);
65015285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                gen_clrex(s);
65028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                return;
65038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            case 4: /* dsb */
65048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            case 5: /* dmb */
65058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            case 6: /* isb */
65068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                ARCH(7);
65078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* We don't emulate caches so these are a no-op.  */
65088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                return;
65098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            default:
65108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                goto illegal_op;
65118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
65128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        } else if ((insn & 0x0e5fffe0) == 0x084d0500) {
65138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* srs */
65145285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            int32_t offset;
65158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (IS_USER(s))
65168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                goto illegal_op;
65178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            ARCH(6);
65188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            op1 = (insn & 0x1f);
65195285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            addr = tcg_temp_new_i32();
65205285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tmp = tcg_const_i32(op1);
65215285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            gen_helper_get_r13_banked(addr, cpu_env, tmp);
65225285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tcg_temp_free_i32(tmp);
65238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            i = (insn >> 23) & 3;
65248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            switch (i) {
65258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            case 0: offset = -4; break; /* DA */
65265285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            case 1: offset = 0; break; /* IA */
65275285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            case 2: offset = -8; break; /* DB */
65288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            case 3: offset = 4; break; /* IB */
65298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            default: abort();
65308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
65318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (offset)
65328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                tcg_gen_addi_i32(addr, addr, offset);
65338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tmp = load_reg(s, 14);
65348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            gen_st32(tmp, addr, 0);
65355285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tmp = load_cpu_field(spsr);
65368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tcg_gen_addi_i32(addr, addr, 4);
65378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            gen_st32(tmp, addr, 0);
65388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (insn & (1 << 21)) {
65398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* Base writeback.  */
65408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                switch (i) {
65418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                case 0: offset = -8; break;
65425285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                case 1: offset = 4; break;
65435285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                case 2: offset = -4; break;
65448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                case 3: offset = 0; break;
65458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                default: abort();
65468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
65478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (offset)
65485285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tcg_gen_addi_i32(addr, addr, offset);
65495285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tmp = tcg_const_i32(op1);
65505285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                gen_helper_set_r13_banked(cpu_env, tmp, addr);
65515285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_temp_free_i32(tmp);
65525285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_temp_free_i32(addr);
65538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            } else {
65545285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_temp_free_i32(addr);
65558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
65565285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            return;
65575285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        } else if ((insn & 0x0e50ffe0) == 0x08100a00) {
65588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* rfe */
65595285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            int32_t offset;
65608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (IS_USER(s))
65618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                goto illegal_op;
65628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            ARCH(6);
65638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            rn = (insn >> 16) & 0xf;
65648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            addr = load_reg(s, rn);
65658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            i = (insn >> 23) & 3;
65668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            switch (i) {
65678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            case 0: offset = -4; break; /* DA */
65685285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            case 1: offset = 0; break; /* IA */
65695285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            case 2: offset = -8; break; /* DB */
65708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            case 3: offset = 4; break; /* IB */
65718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            default: abort();
65728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
65738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (offset)
65748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                tcg_gen_addi_i32(addr, addr, offset);
65758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* Load PC into tmp and CPSR into tmp2.  */
65768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tmp = gen_ld32(addr, 0);
65778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tcg_gen_addi_i32(addr, addr, 4);
65788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tmp2 = gen_ld32(addr, 0);
65798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (insn & (1 << 21)) {
65808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* Base writeback.  */
65818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                switch (i) {
65828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                case 0: offset = -8; break;
65835285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                case 1: offset = 4; break;
65845285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                case 2: offset = -4; break;
65858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                case 3: offset = 0; break;
65868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                default: abort();
65878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
65888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (offset)
65898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    tcg_gen_addi_i32(addr, addr, offset);
65908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                store_reg(s, rn, addr);
65918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            } else {
65925285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_temp_free_i32(addr);
65938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
65948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            gen_rfe(s, tmp, tmp2);
65955285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            return;
65968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        } else if ((insn & 0x0e000000) == 0x0a000000) {
65978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* branch link and change to thumb (blx <offset>) */
65988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            int32_t offset;
65998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
66008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            val = (uint32_t)s->pc;
66015285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tmp = tcg_temp_new_i32();
66028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tcg_gen_movi_i32(tmp, val);
66038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            store_reg(s, 14, tmp);
66048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* Sign-extend the 24-bit offset */
66058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            offset = (((int32_t)insn) << 8) >> 8;
66068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* offset * 4 + bit24 * 2 + (thumb bit) */
66078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            val += (offset << 2) | ((insn >> 23) & 2) | 1;
66088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* pipeline offset */
66098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            val += 4;
66105285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            /* protected by ARCH(5); above, near the start of uncond block */
66118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            gen_bx_im(s, val);
66128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return;
66138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        } else if ((insn & 0x0e000f00) == 0x0c000100) {
66148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
66158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* iWMMXt register transfer.  */
66168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (env->cp15.c15_cpar & (1 << 1))
66178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if (!disas_iwmmxt_insn(env, s, insn))
66188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        return;
66198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
66208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        } else if ((insn & 0x0fe00000) == 0x0c400000) {
66218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* Coprocessor double register transfer.  */
66225285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            ARCH(5TE);
66238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        } else if ((insn & 0x0f000010) == 0x0e000010) {
66248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* Additional coprocessor register transfer.  */
66255285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            if (!disas_coproc_insn(env, s, insn)) {
66265285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                return;
66275285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            }
66288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        } else if ((insn & 0x0ff10020) == 0x01000000) {
66298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            uint32_t mask;
66308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            uint32_t val;
66318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* cps (privileged) */
66328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (IS_USER(s))
66338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                return;
66348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            mask = val = 0;
66358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (insn & (1 << 19)) {
66368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (insn & (1 << 8))
66378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    mask |= CPSR_A;
66388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (insn & (1 << 7))
66398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    mask |= CPSR_I;
66408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (insn & (1 << 6))
66418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    mask |= CPSR_F;
66428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (insn & (1 << 18))
66438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    val |= mask;
66448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
66458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (insn & (1 << 17)) {
66468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                mask |= CPSR_M;
66478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                val |= (insn & 0x1f);
66488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
66498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (mask) {
66505285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                gen_set_psr_im(s, mask, 0, val);
66518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
66528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return;
66538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
66548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        goto illegal_op;
66558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
66568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (cond != 0xe) {
6657288208c386810fef725aa448a9f46bd2772bec8cDavid 'Digit' Turner        ANDROID_TRACE_GEN_SINGLE_TICK();
66588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* if not always execute, we generate a conditional jump to
66598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project           next instruction */
66608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        s->condlabel = gen_new_label();
66618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_test_cc(cond ^ 1, s->condlabel);
66628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        s->condjmp = 1;
66638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
6664288208c386810fef725aa448a9f46bd2772bec8cDavid 'Digit' Turner    ANDROID_TRACE_GEN_OTHER_TICKS();
66658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if ((insn & 0x0f900000) == 0x03000000) {
66668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if ((insn & (1 << 21)) == 0) {
66678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            ARCH(6T2);
66688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            rd = (insn >> 12) & 0xf;
66698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            val = ((insn >> 4) & 0xf000) | (insn & 0xfff);
66708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if ((insn & (1 << 22)) == 0) {
66718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* MOVW */
66725285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tmp = tcg_temp_new_i32();
66738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                tcg_gen_movi_i32(tmp, val);
66748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            } else {
66758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* MOVT */
66768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                tmp = load_reg(s, rd);
66778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                tcg_gen_ext16u_i32(tmp, tmp);
66788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                tcg_gen_ori_i32(tmp, tmp, val << 16);
66798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
66808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            store_reg(s, rd, tmp);
66818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        } else {
66828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (((insn >> 12) & 0xf) != 0xf)
66838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                goto illegal_op;
66848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (((insn >> 16) & 0xf) == 0) {
66858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                gen_nop_hint(s, insn & 0xff);
66868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            } else {
66878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* CPSR = immediate */
66888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                val = insn & 0xff;
66898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                shift = ((insn >> 8) & 0xf) * 2;
66908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (shift)
66918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    val = (val >> shift) | (val << (32 - shift));
66928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                i = ((insn & (1 << 22)) != 0);
66935285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                if (gen_set_psr_im(s, msr_mask(env, s, (insn >> 16) & 0xf, i), i, val))
66948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    goto illegal_op;
66958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
66968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
66978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } else if ((insn & 0x0f900000) == 0x01000000
66988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project               && (insn & 0x00000090) != 0x00000090) {
66998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* miscellaneous instructions */
67008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        op1 = (insn >> 21) & 3;
67018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        sh = (insn >> 4) & 0xf;
67028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        rm = insn & 0xf;
67038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        switch (sh) {
67048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0x0: /* move program status register */
67058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (op1 & 1) {
67068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* PSR = reg */
67075285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tmp = load_reg(s, rm);
67088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                i = ((op1 & 2) != 0);
67095285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                if (gen_set_psr(s, msr_mask(env, s, (insn >> 16) & 0xf, i), i, tmp))
67108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    goto illegal_op;
67118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            } else {
67128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* reg = PSR */
67138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                rd = (insn >> 12) & 0xf;
67148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (op1 & 2) {
67158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if (IS_USER(s))
67168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        goto illegal_op;
67178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    tmp = load_cpu_field(spsr);
67188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                } else {
67195285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tmp = tcg_temp_new_i32();
67208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    gen_helper_cpsr_read(tmp);
67218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
67228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                store_reg(s, rd, tmp);
67238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
67248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
67258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0x1:
67268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (op1 == 1) {
67278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* branch/exchange thumb (bx).  */
67285285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                ARCH(4T);
67298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                tmp = load_reg(s, rm);
67308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                gen_bx(s, tmp);
67318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            } else if (op1 == 3) {
67328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* clz */
67335285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                ARCH(5);
67348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                rd = (insn >> 12) & 0xf;
67358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                tmp = load_reg(s, rm);
67368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                gen_helper_clz(tmp, tmp);
67378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                store_reg(s, rd, tmp);
67388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            } else {
67398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                goto illegal_op;
67408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
67418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
67428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0x2:
67438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (op1 == 1) {
67448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                ARCH(5J); /* bxj */
67458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* Trivial implementation equivalent to bx.  */
67468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                tmp = load_reg(s, rm);
67478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                gen_bx(s, tmp);
67488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            } else {
67498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                goto illegal_op;
67508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
67518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
67528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0x3:
67538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (op1 != 1)
67548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project              goto illegal_op;
67558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
67565285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            ARCH(5);
67578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* branch link/exchange thumb (blx) */
67588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tmp = load_reg(s, rm);
67595285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tmp2 = tcg_temp_new_i32();
67608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tcg_gen_movi_i32(tmp2, s->pc);
67618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            store_reg(s, 14, tmp2);
67628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            gen_bx(s, tmp);
67638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
67648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0x5: /* saturating add/subtract */
67655285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            ARCH(5TE);
67668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            rd = (insn >> 12) & 0xf;
67678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            rn = (insn >> 16) & 0xf;
676880562525ca945d9e921eb49f96d52f1b5a0e693dDavid 'Digit' Turner            tmp = load_reg(s, rm);
67698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tmp2 = load_reg(s, rn);
67708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (op1 & 2)
67718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                gen_helper_double_saturate(tmp2, tmp2);
67728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (op1 & 1)
67738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                gen_helper_sub_saturate(tmp, tmp, tmp2);
67748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            else
67758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                gen_helper_add_saturate(tmp, tmp, tmp2);
67765285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tcg_temp_free_i32(tmp2);
67778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            store_reg(s, rd, tmp);
67788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
67795285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        case 7:
67805285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            if (op1 == 1) {
67815285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                /* bkpt */
67825285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                ARCH(5);
67835285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                gen_exception_insn(s, 4, EXCP_BKPT);
67845285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            } else if (op1 == 3) {
67855285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                /* smi/smc */
67865285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                if (!(env->cp15.c0_c2[4] & 0xf000) || IS_USER(s)) {
67875285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    goto illegal_op;
67885285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                }
67895285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                gen_smc(env, s);
67905285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            } else {
67915285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                goto illegal_op;
67925285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            }
67938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
67948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0x8: /* signed multiply */
67958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0xa:
67968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0xc:
67978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0xe:
67985285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            ARCH(5TE);
67998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            rs = (insn >> 8) & 0xf;
68008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            rn = (insn >> 12) & 0xf;
68018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            rd = (insn >> 16) & 0xf;
68028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (op1 == 1) {
68038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* (32 * 16) >> 16 */
68048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                tmp = load_reg(s, rm);
68058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                tmp2 = load_reg(s, rs);
68068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (sh & 4)
68078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    tcg_gen_sari_i32(tmp2, tmp2, 16);
68088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                else
68098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    gen_sxth(tmp2);
68105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                tmp64 = gen_muls_i64_i32(tmp, tmp2);
68115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                tcg_gen_shri_i64(tmp64, tmp64, 16);
68125285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tmp = tcg_temp_new_i32();
68135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                tcg_gen_trunc_i64_i32(tmp, tmp64);
68145285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_temp_free_i64(tmp64);
68158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if ((sh & 2) == 0) {
68168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    tmp2 = load_reg(s, rn);
68178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    gen_helper_add_setq(tmp, tmp, tmp2);
68185285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tcg_temp_free_i32(tmp2);
68198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
68208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                store_reg(s, rd, tmp);
68218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            } else {
68228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* 16 * 16 */
68238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                tmp = load_reg(s, rm);
68248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                tmp2 = load_reg(s, rs);
68258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                gen_mulxy(tmp, tmp2, sh & 2, sh & 4);
68265285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_temp_free_i32(tmp2);
68278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (op1 == 2) {
68285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                    tmp64 = tcg_temp_new_i64();
68295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                    tcg_gen_ext_i32_i64(tmp64, tmp);
68305285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tcg_temp_free_i32(tmp);
68315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                    gen_addq(s, tmp64, rn, rd);
68325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                    gen_storeq_reg(s, rn, rd, tmp64);
68335285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tcg_temp_free_i64(tmp64);
68348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                } else {
68358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if (op1 == 0) {
68368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        tmp2 = load_reg(s, rn);
68378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        gen_helper_add_setq(tmp, tmp, tmp2);
68385285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tcg_temp_free_i32(tmp2);
68398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
68408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    store_reg(s, rd, tmp);
68418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
68428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
68438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
68448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        default:
68458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            goto illegal_op;
68468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
68478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } else if (((insn & 0x0e000000) == 0 &&
68488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                (insn & 0x00000090) != 0x90) ||
68498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project               ((insn & 0x0e000000) == (1 << 25))) {
68508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        int set_cc, logic_cc, shiftop;
68518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
68528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        op1 = (insn >> 21) & 0xf;
68538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        set_cc = (insn >> 20) & 1;
68548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        logic_cc = table_logic_cc[op1] & set_cc;
68558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
68568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* data processing instruction */
68578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (insn & (1 << 25)) {
68588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* immediate operand */
68598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            val = insn & 0xff;
68608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            shift = ((insn >> 8) & 0xf) * 2;
68615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            if (shift) {
68628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                val = (val >> shift) | (val << (32 - shift));
68635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            }
68645285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tmp2 = tcg_temp_new_i32();
68655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            tcg_gen_movi_i32(tmp2, val);
68665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            if (logic_cc && shift) {
68675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                gen_set_CF_bit31(tmp2);
68685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            }
68698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        } else {
68708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* register */
68718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            rm = (insn) & 0xf;
68725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            tmp2 = load_reg(s, rm);
68738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            shiftop = (insn >> 5) & 3;
68748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (!(insn & (1 << 4))) {
68758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                shift = (insn >> 7) & 0x1f;
68765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                gen_arm_shift_im(tmp2, shiftop, shift, logic_cc);
68778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            } else {
68788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                rs = (insn >> 8) & 0xf;
68798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                tmp = load_reg(s, rs);
68805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                gen_arm_shift_reg(tmp2, shiftop, tmp, logic_cc);
68818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
68828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
68838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (op1 != 0x0f && op1 != 0x0d) {
68848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            rn = (insn >> 16) & 0xf;
68855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            tmp = load_reg(s, rn);
68865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        } else {
68875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            TCGV_UNUSED(tmp);
68888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
68898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        rd = (insn >> 12) & 0xf;
68908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        switch(op1) {
68918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0x00:
68925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            tcg_gen_and_i32(tmp, tmp, tmp2);
68935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            if (logic_cc) {
68945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                gen_logic_CC(tmp);
68955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            }
68965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            store_reg_bx(env, s, rd, tmp);
68978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
68988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0x01:
68995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            tcg_gen_xor_i32(tmp, tmp, tmp2);
69005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            if (logic_cc) {
69015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                gen_logic_CC(tmp);
69025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            }
69035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            store_reg_bx(env, s, rd, tmp);
69048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
69058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0x02:
69068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (set_cc && rd == 15) {
69078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* SUBS r15, ... is used for exception return.  */
69085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                if (IS_USER(s)) {
69098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    goto illegal_op;
69105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                }
69115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                gen_helper_sub_cc(tmp, tmp, tmp2);
69125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                gen_exception_return(s, tmp);
69138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            } else {
69145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                if (set_cc) {
69155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                    gen_helper_sub_cc(tmp, tmp, tmp2);
69165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                } else {
69175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                    tcg_gen_sub_i32(tmp, tmp, tmp2);
69185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                }
69195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                store_reg_bx(env, s, rd, tmp);
69208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
69218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
69228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0x03:
69235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            if (set_cc) {
69245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                gen_helper_sub_cc(tmp, tmp2, tmp);
69255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            } else {
69265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                tcg_gen_sub_i32(tmp, tmp2, tmp);
69275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            }
69285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            store_reg_bx(env, s, rd, tmp);
69298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
69308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0x04:
69315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            if (set_cc) {
69325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                gen_helper_add_cc(tmp, tmp, tmp2);
69335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            } else {
69345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                tcg_gen_add_i32(tmp, tmp, tmp2);
69355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            }
69365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            store_reg_bx(env, s, rd, tmp);
69378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
69388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0x05:
69395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            if (set_cc) {
69405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                gen_helper_adc_cc(tmp, tmp, tmp2);
69415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            } else {
69425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                gen_add_carry(tmp, tmp, tmp2);
69435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            }
69445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            store_reg_bx(env, s, rd, tmp);
69458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
69468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0x06:
69475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            if (set_cc) {
69485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                gen_helper_sbc_cc(tmp, tmp, tmp2);
69495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            } else {
69505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                gen_sub_carry(tmp, tmp, tmp2);
69515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            }
69525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            store_reg_bx(env, s, rd, tmp);
69538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
69548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0x07:
69555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            if (set_cc) {
69565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                gen_helper_sbc_cc(tmp, tmp2, tmp);
69575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            } else {
69585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                gen_sub_carry(tmp, tmp2, tmp);
69595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            }
69605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            store_reg_bx(env, s, rd, tmp);
69618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
69628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0x08:
69638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (set_cc) {
69645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                tcg_gen_and_i32(tmp, tmp, tmp2);
69655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                gen_logic_CC(tmp);
69668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
69675285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tcg_temp_free_i32(tmp);
69688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
69698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0x09:
69708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (set_cc) {
69715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                tcg_gen_xor_i32(tmp, tmp, tmp2);
69725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                gen_logic_CC(tmp);
69738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
69745285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tcg_temp_free_i32(tmp);
69758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
69768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0x0a:
69778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (set_cc) {
69785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                gen_helper_sub_cc(tmp, tmp, tmp2);
69798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
69805285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tcg_temp_free_i32(tmp);
69818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
69828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0x0b:
69838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (set_cc) {
69845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                gen_helper_add_cc(tmp, tmp, tmp2);
69858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
69865285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tcg_temp_free_i32(tmp);
69878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
69888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0x0c:
69895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            tcg_gen_or_i32(tmp, tmp, tmp2);
69905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            if (logic_cc) {
69915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                gen_logic_CC(tmp);
69925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            }
69935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            store_reg_bx(env, s, rd, tmp);
69948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
69958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0x0d:
69968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (logic_cc && rd == 15) {
69978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* MOVS r15, ... is used for exception return.  */
69985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                if (IS_USER(s)) {
69998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    goto illegal_op;
70005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                }
70015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                gen_exception_return(s, tmp2);
70028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            } else {
70035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                if (logic_cc) {
70045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                    gen_logic_CC(tmp2);
70055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                }
70065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                store_reg_bx(env, s, rd, tmp2);
70078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
70088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
70098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0x0e:
70105285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tcg_gen_andc_i32(tmp, tmp, tmp2);
70115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            if (logic_cc) {
70125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                gen_logic_CC(tmp);
70135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            }
70145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            store_reg_bx(env, s, rd, tmp);
70158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
70168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        default:
70178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0x0f:
70185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            tcg_gen_not_i32(tmp2, tmp2);
70195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            if (logic_cc) {
70205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                gen_logic_CC(tmp2);
70215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            }
70225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            store_reg_bx(env, s, rd, tmp2);
70238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
70248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
70255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (op1 != 0x0f && op1 != 0x0d) {
70265285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tcg_temp_free_i32(tmp2);
70275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        }
70288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } else {
70298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* other instructions */
70308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        op1 = (insn >> 24) & 0xf;
70318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        switch(op1) {
70328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0x0:
70338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0x1:
70348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* multiplies, extra load/stores */
70358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            sh = (insn >> 5) & 3;
70368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (sh == 0) {
70378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (op1 == 0x0) {
70388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    rd = (insn >> 16) & 0xf;
70398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    rn = (insn >> 12) & 0xf;
70408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    rs = (insn >> 8) & 0xf;
70418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    rm = (insn) & 0xf;
70428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    op1 = (insn >> 20) & 0xf;
70438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    switch (op1) {
70448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    case 0: case 1: case 2: case 3: case 6:
70458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        /* 32 bit mul */
70468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        tmp = load_reg(s, rs);
70478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        tmp2 = load_reg(s, rm);
70488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        tcg_gen_mul_i32(tmp, tmp, tmp2);
70495285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tcg_temp_free_i32(tmp2);
70508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        if (insn & (1 << 22)) {
70518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            /* Subtract (mls) */
70528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            ARCH(6T2);
70538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            tmp2 = load_reg(s, rn);
70548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            tcg_gen_sub_i32(tmp, tmp2, tmp);
70555285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            tcg_temp_free_i32(tmp2);
70568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        } else if (insn & (1 << 21)) {
70578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            /* Add */
70588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            tmp2 = load_reg(s, rn);
70598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            tcg_gen_add_i32(tmp, tmp, tmp2);
70605285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            tcg_temp_free_i32(tmp2);
70618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        }
70628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        if (insn & (1 << 20))
70638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            gen_logic_CC(tmp);
70648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        store_reg(s, rd, tmp);
70658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        break;
70665285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    case 4:
70675285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        /* 64 bit mul double accumulate (UMAAL) */
70685285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        ARCH(6);
70698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        tmp = load_reg(s, rs);
70708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        tmp2 = load_reg(s, rm);
70715285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tmp64 = gen_mulu_i64_i32(tmp, tmp2);
70725285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        gen_addq_lo(s, tmp64, rn);
70735285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        gen_addq_lo(s, tmp64, rd);
70745285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        gen_storeq_reg(s, rn, rd, tmp64);
70755285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tcg_temp_free_i64(tmp64);
70765285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        break;
70775285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    case 8: case 9: case 10: case 11:
70785285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    case 12: case 13: case 14: case 15:
70795285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        /* 64 bit mul: UMULL, UMLAL, SMULL, SMLAL. */
70805285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tmp = load_reg(s, rs);
70815285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tmp2 = load_reg(s, rm);
70825285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        if (insn & (1 << 22)) {
70835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                            tmp64 = gen_muls_i64_i32(tmp, tmp2);
70845285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        } else {
70855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                            tmp64 = gen_mulu_i64_i32(tmp, tmp2);
70865285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        }
70875285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        if (insn & (1 << 21)) { /* mult accumulate */
70885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                            gen_addq(s, tmp64, rn, rd);
70898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        }
70905285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        if (insn & (1 << 20)) {
70915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                            gen_logicq_cc(tmp64);
70925285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        }
70935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                        gen_storeq_reg(s, rn, rd, tmp64);
70945285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tcg_temp_free_i64(tmp64);
70958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        break;
70965285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    default:
70975285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        goto illegal_op;
70988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
70998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                } else {
71008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    rn = (insn >> 16) & 0xf;
71018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    rd = (insn >> 12) & 0xf;
71028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if (insn & (1 << 23)) {
71038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        /* load/store exclusive */
71045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                        op1 = (insn >> 21) & 0x3;
71055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                        if (op1)
71065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                            ARCH(6K);
71075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                        else
71085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                            ARCH(6);
71095285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        addr = tcg_temp_local_new_i32();
71105285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        load_reg_var(s, addr, rn);
71118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        if (insn & (1 << 20)) {
71125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                            switch (op1) {
71135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                            case 0: /* ldrex */
71145285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                                gen_load_exclusive(s, rd, 15, addr, 2);
71155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                                break;
71165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                            case 1: /* ldrexd */
71175285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                                gen_load_exclusive(s, rd, rd + 1, addr, 3);
71185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                                break;
71195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                            case 2: /* ldrexb */
71205285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                                gen_load_exclusive(s, rd, 15, addr, 0);
71215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                                break;
71225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                            case 3: /* ldrexh */
71235285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                                gen_load_exclusive(s, rd, 15, addr, 1);
71245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                                break;
71255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                            default:
71265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                                abort();
71275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                            }
71288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        } else {
71298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            rm = insn & 0xf;
71305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                            switch (op1) {
71315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                            case 0:  /*  strex */
71325285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                                gen_store_exclusive(s, rd, rm, 15, addr, 2);
71335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                                break;
71345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                            case 1: /*  strexd */
71355285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                                gen_store_exclusive(s, rd, rm, rm + 1, addr, 3);
71365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                                break;
71375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                            case 2: /*  strexb */
71385285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                                gen_store_exclusive(s, rd, rm, 15, addr, 0);
71395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                                break;
71405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                            case 3: /* strexh */
71415285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                                gen_store_exclusive(s, rd, rm, 15, addr, 1);
71425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                                break;
71435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                            default:
71445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                                abort();
71455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                            }
71468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        }
71475285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tcg_temp_free(addr);
71488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    } else {
71498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        /* SWP instruction */
71508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        rm = (insn) & 0xf;
71518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
71528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        /* ??? This is not really atomic.  However we know
71538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                           we never have multiple CPUs running in parallel,
71548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                           so it is good enough.  */
71558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        addr = load_reg(s, rn);
71568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        tmp = load_reg(s, rm);
71578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        if (insn & (1 << 22)) {
71588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            tmp2 = gen_ld8u(addr, IS_USER(s));
71598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            gen_st8(tmp, addr, IS_USER(s));
71608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        } else {
71618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            tmp2 = gen_ld32(addr, IS_USER(s));
71628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            gen_st32(tmp, addr, IS_USER(s));
71638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        }
71645285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tcg_temp_free_i32(addr);
71658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        store_reg(s, rd, tmp2);
71668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
71678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
71688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            } else {
71698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                int address_offset;
71708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                int load;
71718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* Misc load/store */
71728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                rn = (insn >> 16) & 0xf;
71738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                rd = (insn >> 12) & 0xf;
71748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                addr = load_reg(s, rn);
71758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (insn & (1 << 24))
71768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    gen_add_datah_offset(s, insn, 0, addr);
71778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                address_offset = 0;
71788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (insn & (1 << 20)) {
71798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    /* load */
71808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    switch(sh) {
71818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    case 1:
71828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        tmp = gen_ld16u(addr, IS_USER(s));
71838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        break;
71848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    case 2:
71858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        tmp = gen_ld8s(addr, IS_USER(s));
71868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        break;
71878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    default:
71888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    case 3:
71898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        tmp = gen_ld16s(addr, IS_USER(s));
71908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        break;
71918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
71928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    load = 1;
71938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                } else if (sh & 2) {
71945285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    ARCH(5TE);
71958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    /* doubleword */
71968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if (sh & 1) {
71978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        /* store */
71988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        tmp = load_reg(s, rd);
71998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        gen_st32(tmp, addr, IS_USER(s));
72008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        tcg_gen_addi_i32(addr, addr, 4);
72018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        tmp = load_reg(s, rd + 1);
72028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        gen_st32(tmp, addr, IS_USER(s));
72038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        load = 0;
72048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    } else {
72058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        /* load */
72068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        tmp = gen_ld32(addr, IS_USER(s));
72078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        store_reg(s, rd, tmp);
72088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        tcg_gen_addi_i32(addr, addr, 4);
72098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        tmp = gen_ld32(addr, IS_USER(s));
72108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        rd++;
72118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        load = 1;
72128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
72138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    address_offset = -4;
72148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                } else {
72158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    /* store */
72168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    tmp = load_reg(s, rd);
72178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    gen_st16(tmp, addr, IS_USER(s));
72188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    load = 0;
72198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
72208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* Perform base writeback before the loaded value to
72218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                   ensure correct behavior with overlapping index registers.
72228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                   ldrd with base writeback is is undefined if the
72238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                   destination and index registers overlap.  */
72248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (!(insn & (1 << 24))) {
72258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    gen_add_datah_offset(s, insn, address_offset, addr);
72268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    store_reg(s, rn, addr);
72278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                } else if (insn & (1 << 21)) {
72288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if (address_offset)
72298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        tcg_gen_addi_i32(addr, addr, address_offset);
72308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    store_reg(s, rn, addr);
72318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                } else {
72325285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tcg_temp_free_i32(addr);
72338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
72348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (load) {
72358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    /* Complete the load.  */
72368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    store_reg(s, rd, tmp);
72378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
72388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
72398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
72408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0x4:
72418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0x5:
72428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            goto do_ldst;
72438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0x6:
72448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0x7:
72458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (insn & (1 << 4)) {
72468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                ARCH(6);
72478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* Armv6 Media instructions.  */
72488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                rm = insn & 0xf;
72498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                rn = (insn >> 16) & 0xf;
72508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                rd = (insn >> 12) & 0xf;
72518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                rs = (insn >> 8) & 0xf;
72528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                switch ((insn >> 23) & 3) {
72538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                case 0: /* Parallel add/subtract.  */
72548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    op1 = (insn >> 20) & 7;
72558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    tmp = load_reg(s, rn);
72568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    tmp2 = load_reg(s, rm);
72578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    sh = (insn >> 5) & 7;
72588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if ((op1 & 3) == 0 || sh == 5 || sh == 6)
72598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        goto illegal_op;
72608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    gen_arm_parallel_addsub(op1, sh, tmp, tmp2);
72615285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tcg_temp_free_i32(tmp2);
72628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    store_reg(s, rd, tmp);
72638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    break;
72648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                case 1:
72658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if ((insn & 0x00700020) == 0) {
72668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        /* Halfword pack.  */
72678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        tmp = load_reg(s, rn);
72688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        tmp2 = load_reg(s, rm);
72698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        shift = (insn >> 7) & 0x1f;
72708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        if (insn & (1 << 6)) {
72718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            /* pkhtb */
72728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            if (shift == 0)
72738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                shift = 31;
72748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            tcg_gen_sari_i32(tmp2, tmp2, shift);
72758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            tcg_gen_andi_i32(tmp, tmp, 0xffff0000);
72768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            tcg_gen_ext16u_i32(tmp2, tmp2);
72778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        } else {
72788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            /* pkhbt */
72798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            if (shift)
72808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                tcg_gen_shli_i32(tmp2, tmp2, shift);
72818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            tcg_gen_ext16u_i32(tmp, tmp);
72828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            tcg_gen_andi_i32(tmp2, tmp2, 0xffff0000);
72838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        }
72848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        tcg_gen_or_i32(tmp, tmp, tmp2);
72855285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tcg_temp_free_i32(tmp2);
72868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        store_reg(s, rd, tmp);
72878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    } else if ((insn & 0x00200020) == 0x00200000) {
72888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        /* [us]sat */
72898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        tmp = load_reg(s, rm);
72908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        shift = (insn >> 7) & 0x1f;
72918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        if (insn & (1 << 6)) {
72928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            if (shift == 0)
72938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                shift = 31;
72948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            tcg_gen_sari_i32(tmp, tmp, shift);
72958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        } else {
72968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            tcg_gen_shli_i32(tmp, tmp, shift);
72978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        }
72988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        sh = (insn >> 16) & 0x1f;
72995285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tmp2 = tcg_const_i32(sh);
73005285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        if (insn & (1 << 22))
73015285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                          gen_helper_usat(tmp, tmp, tmp2);
73025285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        else
73035285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                          gen_helper_ssat(tmp, tmp, tmp2);
73045285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tcg_temp_free_i32(tmp2);
73058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        store_reg(s, rd, tmp);
73068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    } else if ((insn & 0x00300fe0) == 0x00200f20) {
73078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        /* [us]sat16 */
73088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        tmp = load_reg(s, rm);
73098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        sh = (insn >> 16) & 0x1f;
73105285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tmp2 = tcg_const_i32(sh);
73115285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        if (insn & (1 << 22))
73125285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                          gen_helper_usat16(tmp, tmp, tmp2);
73135285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        else
73145285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                          gen_helper_ssat16(tmp, tmp, tmp2);
73155285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tcg_temp_free_i32(tmp2);
73168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        store_reg(s, rd, tmp);
73178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    } else if ((insn & 0x00700fe0) == 0x00000fa0) {
73188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        /* Select bytes.  */
73198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        tmp = load_reg(s, rn);
73208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        tmp2 = load_reg(s, rm);
73215285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tmp3 = tcg_temp_new_i32();
73228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        tcg_gen_ld_i32(tmp3, cpu_env, offsetof(CPUState, GE));
73238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        gen_helper_sel_flags(tmp, tmp3, tmp, tmp2);
73245285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tcg_temp_free_i32(tmp3);
73255285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tcg_temp_free_i32(tmp2);
73268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        store_reg(s, rd, tmp);
73278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    } else if ((insn & 0x000003e0) == 0x00000060) {
73288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        tmp = load_reg(s, rm);
73298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        shift = (insn >> 10) & 3;
73305285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        /* ??? In many cases it's not necessary to do a
73318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                           rotate, a shift is sufficient.  */
73328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        if (shift != 0)
73335285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            tcg_gen_rotri_i32(tmp, tmp, shift * 8);
73348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        op1 = (insn >> 20) & 7;
73358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        switch (op1) {
73368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        case 0: gen_sxtb16(tmp);  break;
73378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        case 2: gen_sxtb(tmp);    break;
73388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        case 3: gen_sxth(tmp);    break;
73398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        case 4: gen_uxtb16(tmp);  break;
73408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        case 6: gen_uxtb(tmp);    break;
73418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        case 7: gen_uxth(tmp);    break;
73425285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        default: tcg_temp_free_i32(tmp); goto illegal_op;
73438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        }
73448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        if (rn != 15) {
73458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            tmp2 = load_reg(s, rn);
73468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            if ((op1 & 3) == 0) {
73478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                gen_add16(tmp, tmp2);
73488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            } else {
73498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                tcg_gen_add_i32(tmp, tmp, tmp2);
73505285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                                tcg_temp_free_i32(tmp2);
73518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            }
73528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        }
73538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        store_reg(s, rd, tmp);
73548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    } else if ((insn & 0x003f0f60) == 0x003f0f20) {
73558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        /* rev */
73568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        tmp = load_reg(s, rm);
73578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        if (insn & (1 << 22)) {
73588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            if (insn & (1 << 7)) {
73598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                gen_revsh(tmp);
73608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            } else {
73618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                ARCH(6T2);
73628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                gen_helper_rbit(tmp, tmp);
73638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            }
73648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        } else {
73658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            if (insn & (1 << 7))
73668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                gen_rev16(tmp);
73678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            else
73685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                                tcg_gen_bswap32_i32(tmp, tmp);
73698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        }
73708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        store_reg(s, rd, tmp);
73718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    } else {
73728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        goto illegal_op;
73738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
73748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    break;
73758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                case 2: /* Multiplies (Type 3).  */
73768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    tmp = load_reg(s, rm);
73778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    tmp2 = load_reg(s, rs);
73788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if (insn & (1 << 20)) {
73795285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        /* Signed multiply most significant [accumulate].
73805285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                           (SMMUL, SMMLA, SMMLS) */
73815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                        tmp64 = gen_muls_i64_i32(tmp, tmp2);
73825285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
73835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                        if (rd != 15) {
73845285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            tmp = load_reg(s, rd);
73858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            if (insn & (1 << 6)) {
73865285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                                tmp64 = gen_subq_msw(tmp64, tmp);
73878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            } else {
73885285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                                tmp64 = gen_addq_msw(tmp64, tmp);
73898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            }
73908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        }
73915285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        if (insn & (1 << 5)) {
73925285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            tcg_gen_addi_i64(tmp64, tmp64, 0x80000000u);
73935285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        }
73945285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tcg_gen_shri_i64(tmp64, tmp64, 32);
73955285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tmp = tcg_temp_new_i32();
73965285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tcg_gen_trunc_i64_i32(tmp, tmp64);
73975285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tcg_temp_free_i64(tmp64);
73985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                        store_reg(s, rn, tmp);
73998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    } else {
74008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        if (insn & (1 << 5))
74018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            gen_swap_half(tmp2);
74028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        gen_smul_dual(tmp, tmp2);
74038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        if (insn & (1 << 6)) {
74045285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            /* This subtraction cannot overflow. */
74058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            tcg_gen_sub_i32(tmp, tmp, tmp2);
74068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        } else {
74075285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            /* This addition cannot overflow 32 bits;
74085285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                             * however it may overflow considered as a signed
74095285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                             * operation, in which case we must set the Q flag.
74105285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                             */
74115285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            gen_helper_add_setq(tmp, tmp, tmp2);
74128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        }
74135285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tcg_temp_free_i32(tmp2);
74148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        if (insn & (1 << 22)) {
74158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            /* smlald, smlsld */
74165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                            tmp64 = tcg_temp_new_i64();
74175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                            tcg_gen_ext_i32_i64(tmp64, tmp);
74185285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            tcg_temp_free_i32(tmp);
74195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                            gen_addq(s, tmp64, rd, rn);
74205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                            gen_storeq_reg(s, rd, rn, tmp64);
74215285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            tcg_temp_free_i64(tmp64);
74228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        } else {
74238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            /* smuad, smusd, smlad, smlsd */
74248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            if (rd != 15)
74258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                              {
74268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                tmp2 = load_reg(s, rd);
74278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                gen_helper_add_setq(tmp, tmp, tmp2);
74285285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                                tcg_temp_free_i32(tmp2);
74298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                              }
74308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            store_reg(s, rn, tmp);
74318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        }
74328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
74338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    break;
74348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                case 3:
74358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    op1 = ((insn >> 17) & 0x38) | ((insn >> 5) & 7);
74368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    switch (op1) {
74378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    case 0: /* Unsigned sum of absolute differences.  */
74388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        ARCH(6);
74398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        tmp = load_reg(s, rm);
74408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        tmp2 = load_reg(s, rs);
74418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        gen_helper_usad8(tmp, tmp, tmp2);
74425285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tcg_temp_free_i32(tmp2);
74435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                        if (rd != 15) {
74445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                            tmp2 = load_reg(s, rd);
74458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            tcg_gen_add_i32(tmp, tmp, tmp2);
74465285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            tcg_temp_free_i32(tmp2);
74478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        }
74485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                        store_reg(s, rn, tmp);
74498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        break;
74508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    case 0x20: case 0x24: case 0x28: case 0x2c:
74518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        /* Bitfield insert/clear.  */
74528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        ARCH(6T2);
74538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        shift = (insn >> 7) & 0x1f;
74548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        i = (insn >> 16) & 0x1f;
74558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        i = i + 1 - shift;
74568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        if (rm == 15) {
74575285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            tmp = tcg_temp_new_i32();
74588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            tcg_gen_movi_i32(tmp, 0);
74598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        } else {
74608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            tmp = load_reg(s, rm);
74618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        }
74628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        if (i != 32) {
74638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            tmp2 = load_reg(s, rd);
74648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            gen_bfi(tmp, tmp2, tmp, shift, (1u << i) - 1);
74655285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            tcg_temp_free_i32(tmp2);
74668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        }
74678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        store_reg(s, rd, tmp);
74688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        break;
74698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    case 0x12: case 0x16: case 0x1a: case 0x1e: /* sbfx */
74708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    case 0x32: case 0x36: case 0x3a: case 0x3e: /* ubfx */
74715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                        ARCH(6T2);
74728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        tmp = load_reg(s, rm);
74738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        shift = (insn >> 7) & 0x1f;
74748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        i = ((insn >> 16) & 0x1f) + 1;
74758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        if (shift + i > 32)
74768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            goto illegal_op;
74778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        if (i < 32) {
74788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            if (op1 & 0x20) {
74798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                gen_ubfx(tmp, shift, (1u << i) - 1);
74808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            } else {
74818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                gen_sbfx(tmp, shift, i);
74828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            }
74838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        }
74848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        store_reg(s, rd, tmp);
74858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        break;
74868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    default:
74878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        goto illegal_op;
74888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
74898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    break;
74908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
74918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                break;
74928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
74938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        do_ldst:
74948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* Check for undefined extension instructions
74958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project             * per the ARM Bible IE:
74968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project             * xxxx 0111 1111 xxxx  xxxx xxxx 1111 xxxx
74978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project             */
74988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            sh = (0xf << 20) | (0xf << 4);
74998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (op1 == 0x7 && ((insn & sh) == sh))
75008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            {
75018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                goto illegal_op;
75028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
75038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* load/store byte/word */
75048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            rn = (insn >> 16) & 0xf;
75058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            rd = (insn >> 12) & 0xf;
75068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tmp2 = load_reg(s, rn);
75078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            i = (IS_USER(s) || (insn & 0x01200000) == 0x00200000);
75088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (insn & (1 << 24))
75098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                gen_add_data_offset(s, insn, tmp2);
75108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (insn & (1 << 20)) {
75118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* load */
75128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (insn & (1 << 22)) {
75138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    tmp = gen_ld8u(tmp2, i);
75148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                } else {
75158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    tmp = gen_ld32(tmp2, i);
75168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
75178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            } else {
75188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* store */
75198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                tmp = load_reg(s, rd);
75208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (insn & (1 << 22))
75218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    gen_st8(tmp, tmp2, i);
75228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                else
75238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    gen_st32(tmp, tmp2, i);
75248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
75258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (!(insn & (1 << 24))) {
75268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                gen_add_data_offset(s, insn, tmp2);
75278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                store_reg(s, rn, tmp2);
75288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            } else if (insn & (1 << 21)) {
75298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                store_reg(s, rn, tmp2);
75308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            } else {
75315285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_temp_free_i32(tmp2);
75328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
75338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (insn & (1 << 20)) {
75348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* Complete the load.  */
75355285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                store_reg_from_load(env, s, rd, tmp);
75368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
75378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
75388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0x08:
75398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0x09:
75408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            {
75418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                int j, n, user, loaded_base;
75428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                TCGv loaded_var;
75438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* load/store multiple words */
75448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* XXX: store correct base if write back */
75458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                user = 0;
75468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (insn & (1 << 22)) {
75478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if (IS_USER(s))
75488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        goto illegal_op; /* only usable in supervisor mode */
75498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
75508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if ((insn & (1 << 15)) == 0)
75518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        user = 1;
75528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
75538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                rn = (insn >> 16) & 0xf;
75548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                addr = load_reg(s, rn);
75555285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tmp3 = tcg_const_i32(4);
75568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
75578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* compute total size */
75588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                loaded_base = 0;
75598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                TCGV_UNUSED(loaded_var);
75608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                n = 0;
75618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                for(i=0;i<16;i++) {
75628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if (insn & (1 << i))
75638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        n++;
75648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
75658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* XXX: test invalid n == 0 case ? */
75668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (insn & (1 << 23)) {
75678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if (insn & (1 << 24)) {
75688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        /* pre increment */
75695285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tcg_gen_add_i32(addr, addr, tmp3);
75708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    } else {
75718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        /* post increment */
75728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
75738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                } else {
75748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if (insn & (1 << 24)) {
75758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        /* pre decrement */
75768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        tcg_gen_addi_i32(addr, addr, -(n * 4));
75778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    } else {
75788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        /* post decrement */
75798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        if (n != 1)
75808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        tcg_gen_addi_i32(addr, addr, -((n - 1) * 4));
75818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
75828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
75838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                j = 0;
75848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                for(i=0;i<16;i++) {
75858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if (insn & (1 << i)) {
75868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        if (insn & (1 << 20)) {
75878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            /* load */
75888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            tmp = gen_ld32(addr, IS_USER(s));
75895285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            if (user) {
75905285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                                tmp2 = tcg_const_i32(i);
75915285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                                gen_helper_set_user_reg(tmp2, tmp);
75925285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                                tcg_temp_free_i32(tmp2);
75935285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                                tcg_temp_free_i32(tmp);
75948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            } else if (i == rn) {
75958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                loaded_var = tmp;
75968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                loaded_base = 1;
75978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            } else {
75985285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                                store_reg_from_load(env, s, i, tmp);
75998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            }
76008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        } else {
76018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            /* store */
76028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            if (i == 15) {
76038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                /* special case: r15 = PC + 8 */
76048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                val = (long)s->pc + 4;
76055285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                                tmp = tcg_temp_new_i32();
76068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                tcg_gen_movi_i32(tmp, val);
76078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            } else if (user) {
76085285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                                tmp = tcg_temp_new_i32();
76095285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                                tmp2 = tcg_const_i32(i);
76105285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                                gen_helper_get_user_reg(tmp, tmp2);
76115285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                                tcg_temp_free_i32(tmp2);
76128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            } else {
76138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                tmp = load_reg(s, i);
76148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            }
76158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            gen_st32(tmp, addr, IS_USER(s));
76168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        }
76178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        j++;
76188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        /* no need to add after the last transfer */
76198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        if (j != n)
76205285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            tcg_gen_add_i32(addr, addr, tmp3);
76218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
76228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
76238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (insn & (1 << 21)) {
76248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    /* write back */
76258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if (insn & (1 << 23)) {
76268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        if (insn & (1 << 24)) {
76278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            /* pre increment */
76288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        } else {
76298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            /* post increment */
76305285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            tcg_gen_add_i32(addr, addr, tmp3);
76318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        }
76328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    } else {
76338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        if (insn & (1 << 24)) {
76348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            /* pre decrement */
76358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            if (n != 1)
76368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                tcg_gen_addi_i32(addr, addr, -((n - 1) * 4));
76378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        } else {
76388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            /* post decrement */
76398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            tcg_gen_addi_i32(addr, addr, -(n * 4));
76408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        }
76418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
76428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    store_reg(s, rn, addr);
76438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                } else {
76445285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tcg_temp_free_i32(addr);
76458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
76465285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_temp_free_i32(tmp3);
76478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (loaded_base) {
76488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    store_reg(s, rn, loaded_var);
76498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
76508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if ((insn & (1 << 22)) && !user) {
76518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    /* Restore CPSR from SPSR.  */
76528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    tmp = load_cpu_field(spsr);
76538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    gen_set_cpsr(tmp, 0xffffffff);
76545285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tcg_temp_free_i32(tmp);
76558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    s->is_jmp = DISAS_UPDATE;
76568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
76578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
76588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
76598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0xa:
76608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0xb:
76618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            {
76628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                int32_t offset;
76635285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
76648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* branch (and link) */
76658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                val = (int32_t)s->pc;
76668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (insn & (1 << 24)) {
76675285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tmp = tcg_temp_new_i32();
76688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    tcg_gen_movi_i32(tmp, val);
76698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    store_reg(s, 14, tmp);
76708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
76718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                offset = (((int32_t)insn << 8) >> 8);
76728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                val += (offset << 2) + 4;
76738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                gen_jmp(s, val);
76748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
76758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
76768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0xc:
76778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0xd:
76788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0xe:
76798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* Coprocessor.  */
76808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (disas_coproc_insn(env, s, insn))
76818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                goto illegal_op;
76828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
76838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0xf:
76848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* swi */
76858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            gen_set_pc_im(s->pc);
76868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            s->is_jmp = DISAS_SWI;
76878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
76888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        default:
76898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        illegal_op:
76905285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            gen_exception_insn(s, 4, EXCP_UDEF);
76918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
76928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
76938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
76948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
76958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
76968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Return true if this is a Thumb-2 logical op.  */
76978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
76988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectthumb2_logic_op(int op)
76998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
77008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return (op < 8);
77018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
77028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
77038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Generate code for a Thumb-2 data processing operation.  If CONDS is nonzero
77048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   then set condition code flags based on the result of the operation.
77058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   If SHIFTER_OUT is nonzero then set the carry flag for logical operations
77068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   to the high bit of T1.
77078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   Returns zero if the opcode is valid.  */
77088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
77098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
77105285864985be9077e58e42235af6582dee72e841David 'Digit' Turnergen_thumb2_data_op(DisasContext *s, int op, int conds, uint32_t shifter_out, TCGv t0, TCGv t1)
77118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
77128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int logic_cc;
77138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
77148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    logic_cc = 0;
77158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    switch (op) {
77168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0: /* and */
77175285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tcg_gen_and_i32(t0, t0, t1);
77188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        logic_cc = conds;
77198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
77208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 1: /* bic */
77215285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tcg_gen_andc_i32(t0, t0, t1);
77228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        logic_cc = conds;
77238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
77248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 2: /* orr */
77255285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tcg_gen_or_i32(t0, t0, t1);
77268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        logic_cc = conds;
77278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
77288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 3: /* orn */
77295285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tcg_gen_orc_i32(t0, t0, t1);
77308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        logic_cc = conds;
77318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
77328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 4: /* eor */
77335285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tcg_gen_xor_i32(t0, t0, t1);
77348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        logic_cc = conds;
77358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
77368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 8: /* add */
77378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (conds)
77385285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            gen_helper_add_cc(t0, t0, t1);
77398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        else
77405285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tcg_gen_add_i32(t0, t0, t1);
77418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
77428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 10: /* adc */
77438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (conds)
77445285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            gen_helper_adc_cc(t0, t0, t1);
77458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        else
77465285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            gen_adc(t0, t1);
77478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
77488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 11: /* sbc */
77498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (conds)
77505285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            gen_helper_sbc_cc(t0, t0, t1);
77518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        else
77525285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            gen_sub_carry(t0, t0, t1);
77538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
77548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 13: /* sub */
77558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (conds)
77565285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            gen_helper_sub_cc(t0, t0, t1);
77578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        else
77585285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tcg_gen_sub_i32(t0, t0, t1);
77598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
77608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 14: /* rsb */
77618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (conds)
77625285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            gen_helper_sub_cc(t0, t1, t0);
77638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        else
77645285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tcg_gen_sub_i32(t0, t1, t0);
77658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
77668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    default: /* 5, 6, 7, 9, 12, 15. */
77678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return 1;
77688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
77698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (logic_cc) {
77705285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        gen_logic_CC(t0);
77718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (shifter_out)
77725285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            gen_set_CF_bit31(t1);
77738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
77748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
77758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
77768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
77778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Translate a 32-bit thumb instruction.  Returns nonzero if the instruction
77788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   is not legal.  */
77798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1)
77808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
77818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    uint32_t insn, imm, shift, offset;
77828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    uint32_t rd, rn, rm, rs;
77838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    TCGv tmp;
77848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    TCGv tmp2;
77858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    TCGv tmp3;
77868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    TCGv addr;
77875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    TCGv_i64 tmp64;
77888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int op;
77898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int shiftop;
77908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int conds;
77918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int logic_cc;
77928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
77938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!(arm_feature(env, ARM_FEATURE_THUMB2)
77948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project          || arm_feature (env, ARM_FEATURE_M))) {
77958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* Thumb-1 cores may need to treat bl and blx as a pair of
77968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project           16-bit instructions to get correct prefetch abort behavior.  */
77978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        insn = insn_hw1;
77988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if ((insn & (1 << 12)) == 0) {
77995285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            ARCH(5);
78008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* Second half of blx.  */
78018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            offset = ((insn & 0x7ff) << 1);
78028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tmp = load_reg(s, 14);
78038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tcg_gen_addi_i32(tmp, tmp, offset);
78048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tcg_gen_andi_i32(tmp, tmp, 0xfffffffc);
78058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
78065285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tmp2 = tcg_temp_new_i32();
78078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tcg_gen_movi_i32(tmp2, s->pc | 1);
78088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            store_reg(s, 14, tmp2);
78098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            gen_bx(s, tmp);
78108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 0;
78118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
78128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (insn & (1 << 11)) {
78138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* Second half of bl.  */
78148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            offset = ((insn & 0x7ff) << 1) | 1;
78158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tmp = load_reg(s, 14);
78168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tcg_gen_addi_i32(tmp, tmp, offset);
78178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
78185285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tmp2 = tcg_temp_new_i32();
78198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tcg_gen_movi_i32(tmp2, s->pc | 1);
78208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            store_reg(s, 14, tmp2);
78218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            gen_bx(s, tmp);
78228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 0;
78238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
78248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if ((s->pc & ~TARGET_PAGE_MASK) == 0) {
78258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* Instruction spans a page boundary.  Implement it as two
78268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project               16-bit instructions in case the second half causes an
78278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project               prefetch abort.  */
78288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            offset = ((int32_t)insn << 21) >> 9;
78295285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tcg_gen_movi_i32(cpu_R[14], s->pc + 2 + offset);
78308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 0;
78318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
78328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* Fall through to 32-bit decode.  */
78338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
78348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
78358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    insn = lduw_code(s->pc);
7836288208c386810fef725aa448a9f46bd2772bec8cDavid 'Digit' Turner    ANDROID_TRACE_START_THUMB();
78375389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine    s->pc += 2;
78385285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    insn |= (uint32_t)insn_hw1 << 16;
78395389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine
78408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if ((insn & 0xf800e800) != 0xf000e800) {
78418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        ARCH(6T2);
78428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
78438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
78448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    rn = (insn >> 16) & 0xf;
78458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    rs = (insn >> 12) & 0xf;
78468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    rd = (insn >> 8) & 0xf;
78478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    rm = insn & 0xf;
78488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    switch ((insn >> 25) & 0xf) {
78498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0: case 1: case 2: case 3:
78508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* 16-bit instructions.  Should never happen.  */
78518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        abort();
78528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 4:
78538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (insn & (1 << 22)) {
78548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* Other load/store, table branch.  */
78558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (insn & 0x01200000) {
78568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* Load/store doubleword.  */
78578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (rn == 15) {
78585285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    addr = tcg_temp_new_i32();
78598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    tcg_gen_movi_i32(addr, s->pc & ~3);
78608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                } else {
78618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    addr = load_reg(s, rn);
78628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
78638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                offset = (insn & 0xff) * 4;
78648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if ((insn & (1 << 23)) == 0)
78658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    offset = -offset;
78668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (insn & (1 << 24)) {
78678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    tcg_gen_addi_i32(addr, addr, offset);
78688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    offset = 0;
78698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
78708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (insn & (1 << 20)) {
78718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    /* ldrd */
78728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    tmp = gen_ld32(addr, IS_USER(s));
78738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    store_reg(s, rs, tmp);
78748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    tcg_gen_addi_i32(addr, addr, 4);
78758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    tmp = gen_ld32(addr, IS_USER(s));
78768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    store_reg(s, rd, tmp);
78778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                } else {
78788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    /* strd */
78798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    tmp = load_reg(s, rs);
78808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    gen_st32(tmp, addr, IS_USER(s));
78818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    tcg_gen_addi_i32(addr, addr, 4);
78828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    tmp = load_reg(s, rd);
78838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    gen_st32(tmp, addr, IS_USER(s));
78848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
78858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (insn & (1 << 21)) {
78868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    /* Base writeback.  */
78878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if (rn == 15)
78888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        goto illegal_op;
78898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    tcg_gen_addi_i32(addr, addr, offset - 4);
78908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    store_reg(s, rn, addr);
78918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                } else {
78925285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tcg_temp_free_i32(addr);
78938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
78948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            } else if ((insn & (1 << 23)) == 0) {
78958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* Load/store exclusive word.  */
78965285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                addr = tcg_temp_local_new();
78975285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                load_reg_var(s, addr, rn);
78985285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_gen_addi_i32(addr, addr, (insn & 0xff) << 2);
78998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (insn & (1 << 20)) {
79005285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    gen_load_exclusive(s, rs, 15, addr, 2);
79018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                } else {
79025285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    gen_store_exclusive(s, rd, rs, 15, addr, 2);
79038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
79045285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_temp_free(addr);
79058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            } else if ((insn & (1 << 6)) == 0) {
79068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* Table Branch.  */
79078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (rn == 15) {
79085285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    addr = tcg_temp_new_i32();
79098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    tcg_gen_movi_i32(addr, s->pc);
79108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                } else {
79118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    addr = load_reg(s, rn);
79128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
79138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                tmp = load_reg(s, rm);
79148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                tcg_gen_add_i32(addr, addr, tmp);
79158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (insn & (1 << 4)) {
79168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    /* tbh */
79178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    tcg_gen_add_i32(addr, addr, tmp);
79185285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tcg_temp_free_i32(tmp);
79198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    tmp = gen_ld16u(addr, IS_USER(s));
79208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                } else { /* tbb */
79215285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tcg_temp_free_i32(tmp);
79228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    tmp = gen_ld8u(addr, IS_USER(s));
79238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
79245285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_temp_free_i32(addr);
79258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                tcg_gen_shli_i32(tmp, tmp, 1);
79268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                tcg_gen_addi_i32(tmp, tmp, s->pc);
79278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                store_reg(s, 15, tmp);
79288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            } else {
79298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* Load/store exclusive byte/halfword/doubleword.  */
79305285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                ARCH(7);
79318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                op = (insn >> 4) & 0x3;
79325285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                if (op == 2) {
79335285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    goto illegal_op;
79345285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                }
79355285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                addr = tcg_temp_local_new();
79365285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                load_reg_var(s, addr, rn);
79378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (insn & (1 << 20)) {
79385285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    gen_load_exclusive(s, rs, rd, addr, op);
79398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                } else {
79405285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    gen_store_exclusive(s, rm, rs, rd, addr, op);
79418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
79425285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_temp_free(addr);
79438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
79448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        } else {
79458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* Load/store multiple, RFE, SRS.  */
79468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (((insn >> 23) & 1) == ((insn >> 24) & 1)) {
79478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* Not available in user mode.  */
79488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (IS_USER(s))
79498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    goto illegal_op;
79508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (insn & (1 << 20)) {
79518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    /* rfe */
79528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    addr = load_reg(s, rn);
79538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if ((insn & (1 << 24)) == 0)
79548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        tcg_gen_addi_i32(addr, addr, -8);
79558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    /* Load PC into tmp and CPSR into tmp2.  */
79568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    tmp = gen_ld32(addr, 0);
79578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    tcg_gen_addi_i32(addr, addr, 4);
79588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    tmp2 = gen_ld32(addr, 0);
79598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if (insn & (1 << 21)) {
79608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        /* Base writeback.  */
79618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        if (insn & (1 << 24)) {
79628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            tcg_gen_addi_i32(addr, addr, 4);
79638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        } else {
79648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            tcg_gen_addi_i32(addr, addr, -4);
79658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        }
79668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        store_reg(s, rn, addr);
79678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    } else {
79685285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tcg_temp_free_i32(addr);
79698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
79708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    gen_rfe(s, tmp, tmp2);
79718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                } else {
79728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    /* srs */
79738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    op = (insn & 0x1f);
79745285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    addr = tcg_temp_new_i32();
79755285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tmp = tcg_const_i32(op);
79765285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    gen_helper_get_r13_banked(addr, cpu_env, tmp);
79775285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tcg_temp_free_i32(tmp);
79788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if ((insn & (1 << 24)) == 0) {
79798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        tcg_gen_addi_i32(addr, addr, -8);
79808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
79818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    tmp = load_reg(s, 14);
79828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    gen_st32(tmp, addr, 0);
79838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    tcg_gen_addi_i32(addr, addr, 4);
79845285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tmp = tcg_temp_new_i32();
79858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    gen_helper_cpsr_read(tmp);
79868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    gen_st32(tmp, addr, 0);
79878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if (insn & (1 << 21)) {
79888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        if ((insn & (1 << 24)) == 0) {
79898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            tcg_gen_addi_i32(addr, addr, -4);
79908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        } else {
79918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            tcg_gen_addi_i32(addr, addr, 4);
79928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        }
79935285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tmp = tcg_const_i32(op);
79945285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        gen_helper_set_r13_banked(cpu_env, tmp, addr);
79955285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tcg_temp_free_i32(tmp);
79968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    } else {
79975285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tcg_temp_free_i32(addr);
79988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
79998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
80008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            } else {
80015285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                int i, loaded_base = 0;
80025285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                TCGv loaded_var;
80038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* Load/store multiple.  */
80048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                addr = load_reg(s, rn);
80058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                offset = 0;
80068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                for (i = 0; i < 16; i++) {
80078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if (insn & (1 << i))
80088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        offset += 4;
80098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
80108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (insn & (1 << 24)) {
80118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    tcg_gen_addi_i32(addr, addr, -offset);
80128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
80138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
80145285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                TCGV_UNUSED(loaded_var);
80155285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tmp2 = tcg_const_i32(4);
80168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                for (i = 0; i < 16; i++) {
80178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if ((insn & (1 << i)) == 0)
80188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        continue;
80198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if (insn & (1 << 20)) {
80208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        /* Load.  */
80218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        tmp = gen_ld32(addr, IS_USER(s));
80228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        if (i == 15) {
80238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            gen_bx(s, tmp);
80245285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        } else if (i == rn) {
80255285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            loaded_var = tmp;
80265285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            loaded_base = 1;
80278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        } else {
80288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            store_reg(s, i, tmp);
80298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        }
80308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    } else {
80318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        /* Store.  */
80328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        tmp = load_reg(s, i);
80338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        gen_st32(tmp, addr, IS_USER(s));
80348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
80355285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tcg_gen_add_i32(addr, addr, tmp2);
80365285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                }
80375285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                if (loaded_base) {
80385285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    store_reg(s, rn, loaded_var);
80398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
80405285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_temp_free_i32(tmp2);
80418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (insn & (1 << 21)) {
80428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    /* Base register writeback.  */
80438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if (insn & (1 << 24)) {
80448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        tcg_gen_addi_i32(addr, addr, -offset);
80458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
80468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    /* Fault if writeback register is in register list.  */
80478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if (insn & (1 << rn))
80488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        goto illegal_op;
80498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    store_reg(s, rn, addr);
80508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                } else {
80515285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tcg_temp_free_i32(addr);
80528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
80538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
80548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
80558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
80565285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    case 5:
80575285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
80588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        op = (insn >> 21) & 0xf;
80595285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        if (op == 6) {
80605285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            /* Halfword pack.  */
80615285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tmp = load_reg(s, rn);
80625285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tmp2 = load_reg(s, rm);
80635285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            shift = ((insn >> 10) & 0x1c) | ((insn >> 6) & 0x3);
80645285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            if (insn & (1 << 5)) {
80655285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                /* pkhtb */
80665285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                if (shift == 0)
80675285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    shift = 31;
80685285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_gen_sari_i32(tmp2, tmp2, shift);
80695285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_gen_andi_i32(tmp, tmp, 0xffff0000);
80705285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_gen_ext16u_i32(tmp2, tmp2);
80715285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            } else {
80725285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                /* pkhbt */
80735285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                if (shift)
80745285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tcg_gen_shli_i32(tmp2, tmp2, shift);
80755285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_gen_ext16u_i32(tmp, tmp);
80765285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_gen_andi_i32(tmp2, tmp2, 0xffff0000);
80775285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            }
80785285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tcg_gen_or_i32(tmp, tmp, tmp2);
80795285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tcg_temp_free_i32(tmp2);
80805285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            store_reg(s, rd, tmp);
80815285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        } else {
80825285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            /* Data processing register constant shift.  */
80835285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            if (rn == 15) {
80845285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tmp = tcg_temp_new_i32();
80855285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_gen_movi_i32(tmp, 0);
80865285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            } else {
80875285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tmp = load_reg(s, rn);
80885285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            }
80895285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tmp2 = load_reg(s, rm);
80905285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
80915285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            shiftop = (insn >> 4) & 3;
80925285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            shift = ((insn >> 6) & 3) | ((insn >> 10) & 0x1c);
80935285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            conds = (insn & (1 << 20)) != 0;
80945285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            logic_cc = (conds && thumb2_logic_op(op));
80955285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            gen_arm_shift_im(tmp2, shiftop, shift, logic_cc);
80965285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            if (gen_thumb2_data_op(s, op, conds, 0, tmp, tmp2))
80975285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                goto illegal_op;
80985285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tcg_temp_free_i32(tmp2);
80995285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            if (rd != 15) {
81005285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                store_reg(s, rd, tmp);
81015285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            } else {
81025285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_temp_free_i32(tmp);
81035285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            }
81045285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        }
81058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
81068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 13: /* Misc data processing.  */
81078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        op = ((insn >> 22) & 6) | ((insn >> 7) & 1);
81088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (op < 4 && (insn & 0xf000) != 0xf000)
81098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            goto illegal_op;
81108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        switch (op) {
81118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0: /* Register controlled shift.  */
81128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tmp = load_reg(s, rn);
81138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tmp2 = load_reg(s, rm);
81148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if ((insn & 0x70) != 0)
81158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                goto illegal_op;
81168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            op = (insn >> 21) & 3;
81178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            logic_cc = (insn & (1 << 20)) != 0;
81188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            gen_arm_shift_reg(tmp, op, tmp2, logic_cc);
81198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (logic_cc)
81208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                gen_logic_CC(tmp);
81215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            store_reg_bx(env, s, rd, tmp);
81228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
81238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 1: /* Sign/zero extend.  */
81248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tmp = load_reg(s, rm);
81258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            shift = (insn >> 4) & 3;
81265285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            /* ??? In many cases it's not necessary to do a
81278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project               rotate, a shift is sufficient.  */
81288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (shift != 0)
81295285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_gen_rotri_i32(tmp, tmp, shift * 8);
81308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            op = (insn >> 20) & 7;
81318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            switch (op) {
81328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            case 0: gen_sxth(tmp);   break;
81338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            case 1: gen_uxth(tmp);   break;
81348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            case 2: gen_sxtb16(tmp); break;
81358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            case 3: gen_uxtb16(tmp); break;
81368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            case 4: gen_sxtb(tmp);   break;
81378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            case 5: gen_uxtb(tmp);   break;
81388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            default: goto illegal_op;
81398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
81408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (rn != 15) {
81418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                tmp2 = load_reg(s, rn);
81428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if ((op >> 1) == 1) {
81438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    gen_add16(tmp, tmp2);
81448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                } else {
81458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    tcg_gen_add_i32(tmp, tmp, tmp2);
81465285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tcg_temp_free_i32(tmp2);
81478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
81488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
81498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            store_reg(s, rd, tmp);
81508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
81518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 2: /* SIMD add/subtract.  */
81528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            op = (insn >> 20) & 7;
81538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            shift = (insn >> 4) & 7;
81548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if ((op & 3) == 3 || (shift & 3) == 3)
81558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                goto illegal_op;
81568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tmp = load_reg(s, rn);
81578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tmp2 = load_reg(s, rm);
81588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            gen_thumb2_parallel_addsub(op, shift, tmp, tmp2);
81595285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tcg_temp_free_i32(tmp2);
81608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            store_reg(s, rd, tmp);
81618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
81628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 3: /* Other data processing.  */
81638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            op = ((insn >> 17) & 0x38) | ((insn >> 4) & 7);
81648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (op < 4) {
81658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* Saturating add/subtract.  */
81668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                tmp = load_reg(s, rn);
81678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                tmp2 = load_reg(s, rm);
81688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (op & 1)
81695285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    gen_helper_double_saturate(tmp, tmp);
81705285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                if (op & 2)
81718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    gen_helper_sub_saturate(tmp, tmp2, tmp);
81728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                else
81738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    gen_helper_add_saturate(tmp, tmp, tmp2);
81745285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_temp_free_i32(tmp2);
81758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            } else {
81768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                tmp = load_reg(s, rn);
81778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                switch (op) {
81788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                case 0x0a: /* rbit */
81798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    gen_helper_rbit(tmp, tmp);
81808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    break;
81818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                case 0x08: /* rev */
81825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                    tcg_gen_bswap32_i32(tmp, tmp);
81838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    break;
81848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                case 0x09: /* rev16 */
81858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    gen_rev16(tmp);
81868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    break;
81878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                case 0x0b: /* revsh */
81888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    gen_revsh(tmp);
81898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    break;
81908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                case 0x10: /* sel */
81918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    tmp2 = load_reg(s, rm);
81925285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tmp3 = tcg_temp_new_i32();
81938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    tcg_gen_ld_i32(tmp3, cpu_env, offsetof(CPUState, GE));
81948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    gen_helper_sel_flags(tmp, tmp3, tmp, tmp2);
81955285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tcg_temp_free_i32(tmp3);
81965285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tcg_temp_free_i32(tmp2);
81978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    break;
81988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                case 0x18: /* clz */
81998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    gen_helper_clz(tmp, tmp);
82008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    break;
82018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                default:
82028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    goto illegal_op;
82038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
82048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
82058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            store_reg(s, rd, tmp);
82068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
82078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 4: case 5: /* 32-bit multiply.  Sum of absolute differences.  */
82088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            op = (insn >> 4) & 0xf;
82098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tmp = load_reg(s, rn);
82108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tmp2 = load_reg(s, rm);
82118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            switch ((insn >> 20) & 7) {
82128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            case 0: /* 32 x 32 -> 32 */
82138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                tcg_gen_mul_i32(tmp, tmp, tmp2);
82145285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_temp_free_i32(tmp2);
82158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (rs != 15) {
82168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    tmp2 = load_reg(s, rs);
82178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if (op)
82188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        tcg_gen_sub_i32(tmp, tmp2, tmp);
82198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    else
82208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        tcg_gen_add_i32(tmp, tmp, tmp2);
82215285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tcg_temp_free_i32(tmp2);
82228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
82238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                break;
82248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            case 1: /* 16 x 16 -> 32 */
82258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                gen_mulxy(tmp, tmp2, op & 2, op & 1);
82265285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_temp_free_i32(tmp2);
82278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (rs != 15) {
82288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    tmp2 = load_reg(s, rs);
82298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    gen_helper_add_setq(tmp, tmp, tmp2);
82305285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tcg_temp_free_i32(tmp2);
82318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
82328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                break;
82338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            case 2: /* Dual multiply add.  */
82348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            case 4: /* Dual multiply subtract.  */
82358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (op)
82368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    gen_swap_half(tmp2);
82378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                gen_smul_dual(tmp, tmp2);
82388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (insn & (1 << 22)) {
82395285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    /* This subtraction cannot overflow. */
82408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    tcg_gen_sub_i32(tmp, tmp, tmp2);
82418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                } else {
82425285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    /* This addition cannot overflow 32 bits;
82435285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                     * however it may overflow considered as a signed
82445285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                     * operation, in which case we must set the Q flag.
82455285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                     */
82465285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    gen_helper_add_setq(tmp, tmp, tmp2);
82478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
82485285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_temp_free_i32(tmp2);
82498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (rs != 15)
82508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                  {
82518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    tmp2 = load_reg(s, rs);
82528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    gen_helper_add_setq(tmp, tmp, tmp2);
82535285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tcg_temp_free_i32(tmp2);
82548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                  }
82558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                break;
82568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            case 3: /* 32 * 16 -> 32msb */
82578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (op)
82588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    tcg_gen_sari_i32(tmp2, tmp2, 16);
82598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                else
82608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    gen_sxth(tmp2);
82615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                tmp64 = gen_muls_i64_i32(tmp, tmp2);
82625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                tcg_gen_shri_i64(tmp64, tmp64, 16);
82635285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tmp = tcg_temp_new_i32();
82645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                tcg_gen_trunc_i64_i32(tmp, tmp64);
82655285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_temp_free_i64(tmp64);
82668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (rs != 15)
82678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                  {
82688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    tmp2 = load_reg(s, rs);
82698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    gen_helper_add_setq(tmp, tmp, tmp2);
82705285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tcg_temp_free_i32(tmp2);
82718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                  }
82728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                break;
82735285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            case 5: case 6: /* 32 * 32 -> 32msb (SMMUL, SMMLA, SMMLS) */
82745285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tmp64 = gen_muls_i64_i32(tmp, tmp2);
82758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (rs != 15) {
82765285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tmp = load_reg(s, rs);
82775285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    if (insn & (1 << 20)) {
82785285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tmp64 = gen_addq_msw(tmp64, tmp);
82798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    } else {
82805285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tmp64 = gen_subq_msw(tmp64, tmp);
82818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
82828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
82835285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                if (insn & (1 << 4)) {
82845285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tcg_gen_addi_i64(tmp64, tmp64, 0x80000000u);
82855285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                }
82865285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_gen_shri_i64(tmp64, tmp64, 32);
82875285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tmp = tcg_temp_new_i32();
82885285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_gen_trunc_i64_i32(tmp, tmp64);
82895285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_temp_free_i64(tmp64);
82908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                break;
82918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            case 7: /* Unsigned sum of absolute differences.  */
82928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                gen_helper_usad8(tmp, tmp, tmp2);
82935285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_temp_free_i32(tmp2);
82948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (rs != 15) {
82958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    tmp2 = load_reg(s, rs);
82968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    tcg_gen_add_i32(tmp, tmp, tmp2);
82975285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tcg_temp_free_i32(tmp2);
82988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
82998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                break;
83008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
83018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            store_reg(s, rd, tmp);
83028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
83038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 6: case 7: /* 64-bit multiply, Divide.  */
83048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            op = ((insn >> 4) & 0xf) | ((insn >> 16) & 0x70);
83058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tmp = load_reg(s, rn);
83068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tmp2 = load_reg(s, rm);
83078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if ((op & 0x50) == 0x10) {
83088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* sdiv, udiv */
83098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (!arm_feature(env, ARM_FEATURE_DIV))
83108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    goto illegal_op;
83118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (op & 0x20)
83128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    gen_helper_udiv(tmp, tmp, tmp2);
83138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                else
83148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    gen_helper_sdiv(tmp, tmp, tmp2);
83155285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_temp_free_i32(tmp2);
83168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                store_reg(s, rd, tmp);
83178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            } else if ((op & 0xe) == 0xc) {
83188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* Dual multiply accumulate long.  */
83198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (op & 1)
83208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    gen_swap_half(tmp2);
83218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                gen_smul_dual(tmp, tmp2);
83228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (op & 0x10) {
83238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    tcg_gen_sub_i32(tmp, tmp, tmp2);
83248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                } else {
83258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    tcg_gen_add_i32(tmp, tmp, tmp2);
83268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
83275285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_temp_free_i32(tmp2);
83285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                /* BUGFIX */
83295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                tmp64 = tcg_temp_new_i64();
83305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                tcg_gen_ext_i32_i64(tmp64, tmp);
83315285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_temp_free_i32(tmp);
83325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                gen_addq(s, tmp64, rs, rd);
83335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                gen_storeq_reg(s, rs, rd, tmp64);
83345285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_temp_free_i64(tmp64);
83358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            } else {
83368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (op & 0x20) {
83378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    /* Unsigned 64-bit multiply  */
83385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                    tmp64 = gen_mulu_i64_i32(tmp, tmp2);
83398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                } else {
83408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if (op & 8) {
83418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        /* smlalxy */
83428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        gen_mulxy(tmp, tmp2, op & 2, op & 1);
83435285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tcg_temp_free_i32(tmp2);
83445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                        tmp64 = tcg_temp_new_i64();
83455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                        tcg_gen_ext_i32_i64(tmp64, tmp);
83465285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tcg_temp_free_i32(tmp);
83478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    } else {
83488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        /* Signed 64-bit multiply  */
83495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                        tmp64 = gen_muls_i64_i32(tmp, tmp2);
83508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
83518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
83528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (op & 4) {
83538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    /* umaal */
83545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                    gen_addq_lo(s, tmp64, rs);
83555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                    gen_addq_lo(s, tmp64, rd);
83568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                } else if (op & 0x40) {
83578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    /* 64-bit accumulate.  */
83585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                    gen_addq(s, tmp64, rs, rd);
83598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
83605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                gen_storeq_reg(s, rs, rd, tmp64);
83615285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_temp_free_i64(tmp64);
83628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
83638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
83648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
83658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
83668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 6: case 7: case 14: case 15:
83678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* Coprocessor.  */
83688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (((insn >> 24) & 3) == 3) {
83698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* Translate into the equivalent ARM encoding.  */
83705285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            insn = (insn & 0xe2ffffff) | ((insn & (1 << 28)) >> 4) | (1 << 28);
83718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (disas_neon_data_insn(env, s, insn))
83728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                goto illegal_op;
83738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        } else {
83748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (insn & (1 << 28))
83758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                goto illegal_op;
83768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (disas_coproc_insn (env, s, insn))
83778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                goto illegal_op;
83788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
83798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
83808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 8: case 9: case 10: case 11:
83818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (insn & (1 << 15)) {
83828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* Branches, misc control.  */
83838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (insn & 0x5000) {
83848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* Unconditional branch.  */
83858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* signextend(hw1[10:0]) -> offset[:12].  */
83868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                offset = ((int32_t)insn << 5) >> 9 & ~(int32_t)0xfff;
83878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* hw1[10:0] -> offset[11:1].  */
83888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                offset |= (insn & 0x7ff) << 1;
83898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* (~hw2[13, 11] ^ offset[24]) -> offset[23,22]
83908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                   offset[24:22] already have the same value because of the
83918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                   sign extension above.  */
83928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                offset ^= ((~insn) & (1 << 13)) << 10;
83938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                offset ^= ((~insn) & (1 << 11)) << 11;
83948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
83958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (insn & (1 << 14)) {
83968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    /* Branch and link.  */
83975285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tcg_gen_movi_i32(cpu_R[14], s->pc | 1);
83988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
83998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
84008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                offset += s->pc;
84018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (insn & (1 << 12)) {
84028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    /* b/bl */
84038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    gen_jmp(s, offset);
84048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                } else {
84058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    /* blx */
84068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    offset &= ~(uint32_t)2;
84075285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    /* thumb2 bx, no need to check */
84088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    gen_bx_im(s, offset);
84098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
84108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            } else if (((insn >> 23) & 7) == 7) {
84118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* Misc control */
84128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (insn & (1 << 13))
84138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    goto illegal_op;
84148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
84158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (insn & (1 << 26)) {
84165285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    /* Secure monitor call / smc (v6Z) */
84175285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    if (!(env->cp15.c0_c2[4] & 0xf000) || IS_USER(s)) {
84185285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        goto illegal_op;
84195285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    }
84205285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    gen_smc(env, s);
84218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                } else {
84228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    op = (insn >> 20) & 7;
84238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    switch (op) {
84248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    case 0: /* msr cpsr.  */
84258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        if (IS_M(env)) {
84268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            tmp = load_reg(s, rn);
84278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            addr = tcg_const_i32(insn & 0xff);
84288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            gen_helper_v7m_msr(cpu_env, addr, tmp);
84295285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            tcg_temp_free_i32(addr);
84305285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            tcg_temp_free_i32(tmp);
84318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            gen_lookup_tb(s);
84328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            break;
84338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        }
84348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        /* fall through */
84358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    case 1: /* msr spsr.  */
84368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        if (IS_M(env))
84378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            goto illegal_op;
84385285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tmp = load_reg(s, rn);
84395285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        if (gen_set_psr(s,
84408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                              msr_mask(env, s, (insn >> 8) & 0xf, op == 1),
84415285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                              op == 1, tmp))
84428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            goto illegal_op;
84438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        break;
84448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    case 2: /* cps, nop-hint.  */
84458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        if (((insn >> 8) & 7) == 0) {
84468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            gen_nop_hint(s, insn & 0xff);
84478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        }
84488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        /* Implemented as NOP in user mode.  */
84498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        if (IS_USER(s))
84508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            break;
84518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        offset = 0;
84528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        imm = 0;
84538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        if (insn & (1 << 10)) {
84548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            if (insn & (1 << 7))
84558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                offset |= CPSR_A;
84568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            if (insn & (1 << 6))
84578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                offset |= CPSR_I;
84588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            if (insn & (1 << 5))
84598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                offset |= CPSR_F;
84608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            if (insn & (1 << 9))
84618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                imm = CPSR_A | CPSR_I | CPSR_F;
84628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        }
84638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        if (insn & (1 << 8)) {
84648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            offset |= 0x1f;
84658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            imm |= (insn & 0x1f);
84668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        }
84678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        if (offset) {
84685285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            gen_set_psr_im(s, offset, 0, imm);
84698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        }
84708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        break;
84718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    case 3: /* Special control operations.  */
84725285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        ARCH(7);
84738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        op = (insn >> 4) & 0xf;
84748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        switch (op) {
84758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        case 2: /* clrex */
84765285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            gen_clrex(s);
84778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            break;
84788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        case 4: /* dsb */
84798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        case 5: /* dmb */
84808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        case 6: /* isb */
84818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            /* These execute as NOPs.  */
84828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            break;
84838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        default:
84848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            goto illegal_op;
84858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        }
84868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        break;
84878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    case 4: /* bxj */
84888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        /* Trivial implementation equivalent to bx.  */
84898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        tmp = load_reg(s, rn);
84908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        gen_bx(s, tmp);
84918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        break;
84928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    case 5: /* Exception return.  */
84935285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        if (IS_USER(s)) {
84945285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            goto illegal_op;
84955285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        }
84965285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        if (rn != 14 || rd != 15) {
84975285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            goto illegal_op;
84985285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        }
84995285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tmp = load_reg(s, rn);
85005285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tcg_gen_subi_i32(tmp, tmp, insn & 0xff);
85015285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        gen_exception_return(s, tmp);
85025285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        break;
85038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    case 6: /* mrs cpsr.  */
85045285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tmp = tcg_temp_new_i32();
85058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        if (IS_M(env)) {
85068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            addr = tcg_const_i32(insn & 0xff);
85078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            gen_helper_v7m_mrs(tmp, cpu_env, addr);
85085285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            tcg_temp_free_i32(addr);
85098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        } else {
85108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            gen_helper_cpsr_read(tmp);
85118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        }
85128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        store_reg(s, rd, tmp);
85138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        break;
85148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    case 7: /* mrs spsr.  */
85158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        /* Not accessible in user mode.  */
85168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        if (IS_USER(s) || IS_M(env))
85178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            goto illegal_op;
85188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        tmp = load_cpu_field(spsr);
85198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        store_reg(s, rd, tmp);
85208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        break;
85218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
85228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
85238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            } else {
85248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* Conditional branch.  */
85258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                op = (insn >> 22) & 0xf;
85268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* Generate a conditional jump to next instruction.  */
85278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                s->condlabel = gen_new_label();
85288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                gen_test_cc(op ^ 1, s->condlabel);
85298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                s->condjmp = 1;
85308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
85318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* offset[11:1] = insn[10:0] */
85328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                offset = (insn & 0x7ff) << 1;
85338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* offset[17:12] = insn[21:16].  */
85348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                offset |= (insn & 0x003f0000) >> 4;
85358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* offset[31:20] = insn[26].  */
85368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                offset |= ((int32_t)((insn << 5) & 0x80000000)) >> 11;
85378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* offset[18] = insn[13].  */
85388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                offset |= (insn & (1 << 13)) << 5;
85398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* offset[19] = insn[11].  */
85408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                offset |= (insn & (1 << 11)) << 8;
85418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
85428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* jump to the offset */
85438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                gen_jmp(s, s->pc + offset);
85448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
85458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        } else {
85468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* Data processing immediate.  */
85478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (insn & (1 << 25)) {
85488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (insn & (1 << 24)) {
85498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if (insn & (1 << 20))
85508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        goto illegal_op;
85518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    /* Bitfield/Saturate.  */
85528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    op = (insn >> 21) & 7;
85538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    imm = insn & 0x1f;
85548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    shift = ((insn >> 6) & 3) | ((insn >> 10) & 0x1c);
85558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if (rn == 15) {
85565285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tmp = tcg_temp_new_i32();
85578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        tcg_gen_movi_i32(tmp, 0);
85588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    } else {
85598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        tmp = load_reg(s, rn);
85608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
85618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    switch (op) {
85628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    case 2: /* Signed bitfield extract.  */
85638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        imm++;
85648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        if (shift + imm > 32)
85658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            goto illegal_op;
85668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        if (imm < 32)
85678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            gen_sbfx(tmp, shift, imm);
85688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        break;
85698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    case 6: /* Unsigned bitfield extract.  */
85708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        imm++;
85718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        if (shift + imm > 32)
85728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            goto illegal_op;
85738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        if (imm < 32)
85748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            gen_ubfx(tmp, shift, (1u << imm) - 1);
85758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        break;
85768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    case 3: /* Bitfield insert/clear.  */
85778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        if (imm < shift)
85788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            goto illegal_op;
85798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        imm = imm + 1 - shift;
85808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        if (imm != 32) {
85818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            tmp2 = load_reg(s, rd);
85828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            gen_bfi(tmp, tmp2, tmp, shift, (1u << imm) - 1);
85835285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            tcg_temp_free_i32(tmp2);
85848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        }
85858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        break;
85868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    case 7:
85878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        goto illegal_op;
85888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    default: /* Saturate.  */
85898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        if (shift) {
85908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            if (op & 1)
85918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                tcg_gen_sari_i32(tmp, tmp, shift);
85928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            else
85938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                tcg_gen_shli_i32(tmp, tmp, shift);
85948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        }
85958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        tmp2 = tcg_const_i32(imm);
85968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        if (op & 4) {
85978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            /* Unsigned.  */
85988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            if ((op & 1) && shift == 0)
85998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                gen_helper_usat16(tmp, tmp, tmp2);
86008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            else
86018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                gen_helper_usat(tmp, tmp, tmp2);
86028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        } else {
86038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            /* Signed.  */
86048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            if ((op & 1) && shift == 0)
86058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                gen_helper_ssat16(tmp, tmp, tmp2);
86068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            else
86078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                gen_helper_ssat(tmp, tmp, tmp2);
86088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        }
86095285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tcg_temp_free_i32(tmp2);
86108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        break;
86118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
86128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    store_reg(s, rd, tmp);
86138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                } else {
86148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    imm = ((insn & 0x04000000) >> 15)
86158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                          | ((insn & 0x7000) >> 4) | (insn & 0xff);
86168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if (insn & (1 << 22)) {
86178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        /* 16-bit immediate.  */
86188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        imm |= (insn >> 4) & 0xf000;
86198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        if (insn & (1 << 23)) {
86208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            /* movt */
86218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            tmp = load_reg(s, rd);
86228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            tcg_gen_ext16u_i32(tmp, tmp);
86238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            tcg_gen_ori_i32(tmp, tmp, imm << 16);
86248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        } else {
86258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            /* movw */
86265285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            tmp = tcg_temp_new_i32();
86278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            tcg_gen_movi_i32(tmp, imm);
86288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        }
86298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    } else {
86308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        /* Add/sub 12-bit immediate.  */
86318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        if (rn == 15) {
86328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            offset = s->pc & ~(uint32_t)3;
86338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            if (insn & (1 << 23))
86348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                offset -= imm;
86358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            else
86368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                offset += imm;
86375285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                            tmp = tcg_temp_new_i32();
86388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            tcg_gen_movi_i32(tmp, offset);
86398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        } else {
86408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            tmp = load_reg(s, rn);
86418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            if (insn & (1 << 23))
86428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                tcg_gen_subi_i32(tmp, tmp, imm);
86438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            else
86448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                tcg_gen_addi_i32(tmp, tmp, imm);
86458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        }
86468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
86478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    store_reg(s, rd, tmp);
86488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
86498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            } else {
86508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                int shifter_out = 0;
86518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* modified 12-bit immediate.  */
86528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                shift = ((insn & 0x04000000) >> 23) | ((insn & 0x7000) >> 12);
86538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                imm = (insn & 0xff);
86548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                switch (shift) {
86558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                case 0: /* XY */
86568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    /* Nothing to do.  */
86578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    break;
86588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                case 1: /* 00XY00XY */
86598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    imm |= imm << 16;
86608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    break;
86618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                case 2: /* XY00XY00 */
86628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    imm |= imm << 16;
86638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    imm <<= 8;
86648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    break;
86658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                case 3: /* XYXYXYXY */
86668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    imm |= imm << 16;
86678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    imm |= imm << 8;
86688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    break;
86698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                default: /* Rotated constant.  */
86708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    shift = (shift << 1) | (imm >> 7);
86718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    imm |= 0x80;
86728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    imm = imm << (32 - shift);
86738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    shifter_out = 1;
86748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    break;
86758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
86765285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tmp2 = tcg_temp_new_i32();
86775285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_gen_movi_i32(tmp2, imm);
86788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                rn = (insn >> 16) & 0xf;
86795285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                if (rn == 15) {
86805285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tmp = tcg_temp_new_i32();
86815285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tcg_gen_movi_i32(tmp, 0);
86825285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                } else {
86835285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tmp = load_reg(s, rn);
86845285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                }
86858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                op = (insn >> 21) & 0xf;
86868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (gen_thumb2_data_op(s, op, (insn & (1 << 20)) != 0,
86875285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                                       shifter_out, tmp, tmp2))
86888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    goto illegal_op;
86895285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_temp_free_i32(tmp2);
86908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                rd = (insn >> 8) & 0xf;
86918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (rd != 15) {
86925285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    store_reg(s, rd, tmp);
86935285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                } else {
86945285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tcg_temp_free_i32(tmp);
86958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
86968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
86978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
86988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
86998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 12: /* Load/store single data item.  */
87008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        {
87018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        int postinc = 0;
87028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        int writeback = 0;
87038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        int user;
87048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if ((insn & 0x01100000) == 0x01000000) {
87058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (disas_neon_ls_insn(env, s, insn))
87068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                goto illegal_op;
87078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
87088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
87095285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        op = ((insn >> 21) & 3) | ((insn >> 22) & 4);
87105285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        if (rs == 15) {
87115285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            if (!(insn & (1 << 20))) {
87125285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                goto illegal_op;
87135285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            }
87145285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            if (op != 2) {
87155285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                /* Byte or halfword load space with dest == r15 : memory hints.
87165285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                 * Catch them early so we don't emit pointless addressing code.
87175285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                 * This space is a mix of:
87185285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                 *  PLD/PLDW/PLI,  which we implement as NOPs (note that unlike
87195285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                 *     the ARM encodings, PLDW space doesn't UNDEF for non-v7MP
87205285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                 *     cores)
87215285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                 *  unallocated hints, which must be treated as NOPs
87225285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                 *  UNPREDICTABLE space, which we NOP or UNDEF depending on
87235285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                 *     which is easiest for the decoding logic
87245285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                 *  Some space which must UNDEF
87255285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                 */
87265285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                int op1 = (insn >> 23) & 3;
87275285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                int op2 = (insn >> 6) & 0x3f;
87285285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                if (op & 2) {
87295285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    goto illegal_op;
87305285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                }
87315285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                if (rn == 15) {
87325285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    /* UNPREDICTABLE or unallocated hint */
87335285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    return 0;
87345285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                }
87355285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                if (op1 & 1) {
87365285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    return 0; /* PLD* or unallocated hint */
87375285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                }
87385285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                if ((op2 == 0) || ((op2 & 0x3c) == 0x30)) {
87395285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    return 0; /* PLD* or unallocated hint */
87405285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                }
87415285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                /* UNDEF space, or an UNPREDICTABLE */
87425285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                return 1;
87435285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            }
87445285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        }
87458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        user = IS_USER(s);
87468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (rn == 15) {
87475285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            addr = tcg_temp_new_i32();
87488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* PC relative.  */
87498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* s->pc has already been incremented by 4.  */
87508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            imm = s->pc & 0xfffffffc;
87518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (insn & (1 << 23))
87528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                imm += insn & 0xfff;
87538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            else
87548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                imm -= insn & 0xfff;
87558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tcg_gen_movi_i32(addr, imm);
87568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        } else {
87578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            addr = load_reg(s, rn);
87588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (insn & (1 << 23)) {
87598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* Positive offset.  */
87608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                imm = insn & 0xfff;
87618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                tcg_gen_addi_i32(addr, addr, imm);
87628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            } else {
87638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                imm = insn & 0xff;
87645285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                switch ((insn >> 8) & 0xf) {
87655285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                case 0x0: /* Shifted Register.  */
87668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    shift = (insn >> 4) & 0xf;
87675285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    if (shift > 3) {
87685285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tcg_temp_free_i32(addr);
87698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        goto illegal_op;
87705285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    }
87718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    tmp = load_reg(s, rm);
87728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if (shift)
87738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        tcg_gen_shli_i32(tmp, tmp, shift);
87748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    tcg_gen_add_i32(addr, addr, tmp);
87755285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tcg_temp_free_i32(tmp);
87768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    break;
87775285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                case 0xc: /* Negative offset.  */
87788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    tcg_gen_addi_i32(addr, addr, -imm);
87798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    break;
87805285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                case 0xe: /* User privilege.  */
87818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    tcg_gen_addi_i32(addr, addr, imm);
87828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    user = 1;
87838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    break;
87845285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                case 0x9: /* Post-decrement.  */
87858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    imm = -imm;
87868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    /* Fall through.  */
87875285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                case 0xb: /* Post-increment.  */
87888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    postinc = 1;
87898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    writeback = 1;
87908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    break;
87915285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                case 0xd: /* Pre-decrement.  */
87928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    imm = -imm;
87938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    /* Fall through.  */
87945285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                case 0xf: /* Pre-increment.  */
87958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    tcg_gen_addi_i32(addr, addr, imm);
87968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    writeback = 1;
87978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    break;
87988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                default:
87995285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tcg_temp_free_i32(addr);
88008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    goto illegal_op;
88018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
88028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
88038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
88048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (insn & (1 << 20)) {
88058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* Load.  */
88065285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            switch (op) {
88075285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            case 0: tmp = gen_ld8u(addr, user); break;
88085285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            case 4: tmp = gen_ld8s(addr, user); break;
88095285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            case 1: tmp = gen_ld16u(addr, user); break;
88105285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            case 5: tmp = gen_ld16s(addr, user); break;
88115285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            case 2: tmp = gen_ld32(addr, user); break;
88125285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            default:
88135285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_temp_free_i32(addr);
88145285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                goto illegal_op;
88155285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            }
88165285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            if (rs == 15) {
88175285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                gen_bx(s, tmp);
88188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            } else {
88195285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                store_reg(s, rs, tmp);
88208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
88218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        } else {
88228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* Store.  */
88238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tmp = load_reg(s, rs);
88248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            switch (op) {
88258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            case 0: gen_st8(tmp, addr, user); break;
88268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            case 1: gen_st16(tmp, addr, user); break;
88278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            case 2: gen_st32(tmp, addr, user); break;
88285285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            default:
88295285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_temp_free_i32(addr);
88305285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                goto illegal_op;
88318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
88328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
88338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (postinc)
88348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tcg_gen_addi_i32(addr, addr, imm);
88358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (writeback) {
88368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            store_reg(s, rn, addr);
88378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        } else {
88385285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tcg_temp_free_i32(addr);
88398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
88408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
88418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
88428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    default:
88438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        goto illegal_op;
88448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
88458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
88468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectillegal_op:
88478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 1;
88488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
88498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
88508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void disas_thumb_insn(CPUState *env, DisasContext *s)
88518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
88528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    uint32_t val, insn, op, rm, rn, rd, shift, cond;
88538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int32_t offset;
88548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int i;
88558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    TCGv tmp;
88568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    TCGv tmp2;
88578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    TCGv addr;
88588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8859a1204591a52bf668ee72c86f98f53189621572a2Vladimir Chtchetkine    if (s->condexec_mask) {
8860a1204591a52bf668ee72c86f98f53189621572a2Vladimir Chtchetkine        cond = s->condexec_cond;
88615285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        if (cond != 0x0e) {     /* Skip conditional when condition is AL. */
88625285864985be9077e58e42235af6582dee72e841David 'Digit' Turner          s->condlabel = gen_new_label();
88635285864985be9077e58e42235af6582dee72e841David 'Digit' Turner          gen_test_cc(cond ^ 1, s->condlabel);
88645285864985be9077e58e42235af6582dee72e841David 'Digit' Turner          s->condjmp = 1;
88655285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        }
88668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
88678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
88688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    insn = lduw_code(s->pc);
88695389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine
8870288208c386810fef725aa448a9f46bd2772bec8cDavid 'Digit' Turner    ANDROID_WATCH_CALLSTACK_THUMB(s);
8871288208c386810fef725aa448a9f46bd2772bec8cDavid 'Digit' Turner
8872288208c386810fef725aa448a9f46bd2772bec8cDavid 'Digit' Turner    ANDROID_TRACE_START_THUMB();
8873288208c386810fef725aa448a9f46bd2772bec8cDavid 'Digit' Turner
88748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    s->pc += 2;
88758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
88768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    switch (insn >> 12) {
88778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 0: case 1:
88785285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
88798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        rd = insn & 7;
88808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        op = (insn >> 11) & 3;
88818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (op == 3) {
88828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* add/subtract */
88838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            rn = (insn >> 3) & 7;
88845285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tmp = load_reg(s, rn);
88858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (insn & (1 << 10)) {
88868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* immediate */
88875285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tmp2 = tcg_temp_new_i32();
88885285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_gen_movi_i32(tmp2, (insn >> 6) & 7);
88898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            } else {
88908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* reg */
88918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                rm = (insn >> 6) & 7;
88925285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tmp2 = load_reg(s, rm);
88938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
88948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (insn & (1 << 9)) {
88958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (s->condexec_mask)
88965285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tcg_gen_sub_i32(tmp, tmp, tmp2);
88978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                else
88985285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    gen_helper_sub_cc(tmp, tmp, tmp2);
88998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            } else {
89008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (s->condexec_mask)
89015285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tcg_gen_add_i32(tmp, tmp, tmp2);
89028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                else
89035285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    gen_helper_add_cc(tmp, tmp, tmp2);
89048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
89055285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tcg_temp_free_i32(tmp2);
89065285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            store_reg(s, rd, tmp);
89078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        } else {
89088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* shift immediate */
89098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            rm = (insn >> 3) & 7;
89108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            shift = (insn >> 6) & 0x1f;
89118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tmp = load_reg(s, rm);
89128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            gen_arm_shift_im(tmp, op, shift, s->condexec_mask == 0);
89138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (!s->condexec_mask)
89148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                gen_logic_CC(tmp);
89158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            store_reg(s, rd, tmp);
89168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
89178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
89188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 2: case 3:
89198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* arithmetic large immediate */
89208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        op = (insn >> 11) & 3;
89218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        rd = (insn >> 8) & 0x7;
89225285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        if (op == 0) { /* mov */
89235285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tmp = tcg_temp_new_i32();
89245285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tcg_gen_movi_i32(tmp, insn & 0xff);
89258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (!s->condexec_mask)
89265285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                gen_logic_CC(tmp);
89275285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            store_reg(s, rd, tmp);
89285285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        } else {
89295285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tmp = load_reg(s, rd);
89305285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tmp2 = tcg_temp_new_i32();
89315285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tcg_gen_movi_i32(tmp2, insn & 0xff);
89325285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            switch (op) {
89335285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            case 1: /* cmp */
89345285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                gen_helper_sub_cc(tmp, tmp, tmp2);
89355285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_temp_free_i32(tmp);
89365285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_temp_free_i32(tmp2);
89375285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                break;
89385285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            case 2: /* add */
89395285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                if (s->condexec_mask)
89405285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tcg_gen_add_i32(tmp, tmp, tmp2);
89415285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                else
89425285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    gen_helper_add_cc(tmp, tmp, tmp2);
89435285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_temp_free_i32(tmp2);
89445285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                store_reg(s, rd, tmp);
89455285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                break;
89465285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            case 3: /* sub */
89475285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                if (s->condexec_mask)
89485285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tcg_gen_sub_i32(tmp, tmp, tmp2);
89495285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                else
89505285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    gen_helper_sub_cc(tmp, tmp, tmp2);
89515285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_temp_free_i32(tmp2);
89525285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                store_reg(s, rd, tmp);
89535285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                break;
89545285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            }
89558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
89568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
89578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 4:
89588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (insn & (1 << 11)) {
89598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            rd = (insn >> 8) & 7;
89608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* load pc-relative.  Bit 1 of PC is ignored.  */
89618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            val = s->pc + 2 + ((insn & 0xff) * 4);
89628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            val &= ~(uint32_t)2;
89635285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            addr = tcg_temp_new_i32();
89648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tcg_gen_movi_i32(addr, val);
89658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tmp = gen_ld32(addr, IS_USER(s));
89665285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tcg_temp_free_i32(addr);
89678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            store_reg(s, rd, tmp);
89688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
89698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
89708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (insn & (1 << 10)) {
89718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* data processing extended or blx */
89728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            rd = (insn & 7) | ((insn >> 4) & 8);
89738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            rm = (insn >> 3) & 0xf;
89748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            op = (insn >> 8) & 3;
89758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            switch (op) {
89768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            case 0: /* add */
89775285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tmp = load_reg(s, rd);
89785285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tmp2 = load_reg(s, rm);
89795285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_gen_add_i32(tmp, tmp, tmp2);
89805285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_temp_free_i32(tmp2);
89815285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                store_reg(s, rd, tmp);
89828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                break;
89838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            case 1: /* cmp */
89845285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tmp = load_reg(s, rd);
89855285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tmp2 = load_reg(s, rm);
89865285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                gen_helper_sub_cc(tmp, tmp, tmp2);
89875285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_temp_free_i32(tmp2);
89885285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_temp_free_i32(tmp);
89898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                break;
89908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            case 2: /* mov/cpy */
89915285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tmp = load_reg(s, rm);
89925285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                store_reg(s, rd, tmp);
89938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                break;
89948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            case 3:/* branch [and link] exchange thumb register */
89958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                tmp = load_reg(s, rm);
89968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (insn & (1 << 7)) {
89975285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    ARCH(5);
89988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    val = (uint32_t)s->pc | 1;
89995285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tmp2 = tcg_temp_new_i32();
90008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    tcg_gen_movi_i32(tmp2, val);
90018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    store_reg(s, 14, tmp2);
90028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
90035285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                /* already thumb, no need to check */
90048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                gen_bx(s, tmp);
90058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                break;
90068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
90078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
90088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
90098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
90108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* data processing register */
90118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        rd = insn & 7;
90128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        rm = (insn >> 3) & 7;
90138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        op = (insn >> 6) & 0xf;
90148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (op == 2 || op == 3 || op == 4 || op == 7) {
90158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* the shift/rotate ops want the operands backwards */
90168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            val = rm;
90178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            rm = rd;
90188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            rd = val;
90198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            val = 1;
90208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        } else {
90218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            val = 0;
90228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
90238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
90245285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        if (op == 9) { /* neg */
90255285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tmp = tcg_temp_new_i32();
90265285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tcg_gen_movi_i32(tmp, 0);
90275285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        } else if (op != 0xf) { /* mvn doesn't read its first operand */
90285285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tmp = load_reg(s, rd);
90295285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        } else {
90305285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            TCGV_UNUSED(tmp);
90315285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        }
90328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
90335285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tmp2 = load_reg(s, rm);
90348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        switch (op) {
90358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0x0: /* and */
90365285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tcg_gen_and_i32(tmp, tmp, tmp2);
90378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (!s->condexec_mask)
90385285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                gen_logic_CC(tmp);
90398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
90408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0x1: /* eor */
90415285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tcg_gen_xor_i32(tmp, tmp, tmp2);
90428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (!s->condexec_mask)
90435285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                gen_logic_CC(tmp);
90448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
90458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0x2: /* lsl */
90468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (s->condexec_mask) {
90475285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                gen_helper_shl(tmp2, tmp2, tmp);
90488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            } else {
90495285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                gen_helper_shl_cc(tmp2, tmp2, tmp);
90505285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                gen_logic_CC(tmp2);
90518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
90528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
90538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0x3: /* lsr */
90548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (s->condexec_mask) {
90555285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                gen_helper_shr(tmp2, tmp2, tmp);
90568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            } else {
90575285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                gen_helper_shr_cc(tmp2, tmp2, tmp);
90585285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                gen_logic_CC(tmp2);
90598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
90608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
90618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0x4: /* asr */
90628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (s->condexec_mask) {
90635285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                gen_helper_sar(tmp2, tmp2, tmp);
90648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            } else {
90655285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                gen_helper_sar_cc(tmp2, tmp2, tmp);
90665285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                gen_logic_CC(tmp2);
90678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
90688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
90698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0x5: /* adc */
90708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (s->condexec_mask)
90715285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                gen_adc(tmp, tmp2);
90728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            else
90735285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                gen_helper_adc_cc(tmp, tmp, tmp2);
90748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
90758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0x6: /* sbc */
90768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (s->condexec_mask)
90775285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                gen_sub_carry(tmp, tmp, tmp2);
90788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            else
90795285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                gen_helper_sbc_cc(tmp, tmp, tmp2);
90808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
90818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0x7: /* ror */
90828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (s->condexec_mask) {
90835285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_gen_andi_i32(tmp, tmp, 0x1f);
90845285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_gen_rotr_i32(tmp2, tmp2, tmp);
90858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            } else {
90865285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                gen_helper_ror_cc(tmp2, tmp2, tmp);
90875285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                gen_logic_CC(tmp2);
90888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
90898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
90908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0x8: /* tst */
90915285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tcg_gen_and_i32(tmp, tmp, tmp2);
90925285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            gen_logic_CC(tmp);
90938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            rd = 16;
90948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
90958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0x9: /* neg */
90968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (s->condexec_mask)
90975285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_gen_neg_i32(tmp, tmp2);
90988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            else
90995285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                gen_helper_sub_cc(tmp, tmp, tmp2);
91008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
91018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0xa: /* cmp */
91025285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            gen_helper_sub_cc(tmp, tmp, tmp2);
91038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            rd = 16;
91048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
91058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0xb: /* cmn */
91065285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            gen_helper_add_cc(tmp, tmp, tmp2);
91078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            rd = 16;
91088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
91098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0xc: /* orr */
91105285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tcg_gen_or_i32(tmp, tmp, tmp2);
91118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (!s->condexec_mask)
91125285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                gen_logic_CC(tmp);
91138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
91148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0xd: /* mul */
91155285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tcg_gen_mul_i32(tmp, tmp, tmp2);
91168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (!s->condexec_mask)
91175285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                gen_logic_CC(tmp);
91188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
91198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0xe: /* bic */
91205285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tcg_gen_andc_i32(tmp, tmp, tmp2);
91218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (!s->condexec_mask)
91225285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                gen_logic_CC(tmp);
91238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
91248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0xf: /* mvn */
91255285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tcg_gen_not_i32(tmp2, tmp2);
91268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (!s->condexec_mask)
91275285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                gen_logic_CC(tmp2);
91288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            val = 1;
91298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            rm = rd;
91308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
91318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
91328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (rd != 16) {
91335285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            if (val) {
91345285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                store_reg(s, rm, tmp2);
91355285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                if (op != 0xf)
91365285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tcg_temp_free_i32(tmp);
91375285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            } else {
91385285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                store_reg(s, rd, tmp);
91395285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_temp_free_i32(tmp2);
91405285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            }
91415285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        } else {
91425285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tcg_temp_free_i32(tmp);
91435285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tcg_temp_free_i32(tmp2);
91448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
91458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
91468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
91478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 5:
91488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* load/store register offset.  */
91498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        rd = insn & 7;
91508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        rn = (insn >> 3) & 7;
91518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        rm = (insn >> 6) & 7;
91528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        op = (insn >> 9) & 7;
91538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        addr = load_reg(s, rn);
91548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tmp = load_reg(s, rm);
91558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tcg_gen_add_i32(addr, addr, tmp);
91565285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tcg_temp_free_i32(tmp);
91578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
91588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (op < 3) /* store */
91598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tmp = load_reg(s, rd);
91608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
91618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        switch (op) {
91628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0: /* str */
91638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            gen_st32(tmp, addr, IS_USER(s));
91648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
91658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 1: /* strh */
91668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            gen_st16(tmp, addr, IS_USER(s));
91678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
91688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 2: /* strb */
91698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            gen_st8(tmp, addr, IS_USER(s));
91708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
91718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 3: /* ldrsb */
91728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tmp = gen_ld8s(addr, IS_USER(s));
91738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
91748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 4: /* ldr */
91758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tmp = gen_ld32(addr, IS_USER(s));
91768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
91778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 5: /* ldrh */
91788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tmp = gen_ld16u(addr, IS_USER(s));
91798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
91808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 6: /* ldrb */
91818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tmp = gen_ld8u(addr, IS_USER(s));
91828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
91838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 7: /* ldrsh */
91848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tmp = gen_ld16s(addr, IS_USER(s));
91858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
91868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
91878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (op >= 3) /* load */
91888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            store_reg(s, rd, tmp);
91895285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tcg_temp_free_i32(addr);
91908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
91918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
91928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 6:
91938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* load/store word immediate offset */
91948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        rd = insn & 7;
91958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        rn = (insn >> 3) & 7;
91968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        addr = load_reg(s, rn);
91978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        val = (insn >> 4) & 0x7c;
91988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tcg_gen_addi_i32(addr, addr, val);
91998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
92008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (insn & (1 << 11)) {
92018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* load */
92028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tmp = gen_ld32(addr, IS_USER(s));
92038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            store_reg(s, rd, tmp);
92048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        } else {
92058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* store */
92068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tmp = load_reg(s, rd);
92078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            gen_st32(tmp, addr, IS_USER(s));
92088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
92095285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tcg_temp_free_i32(addr);
92108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
92118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
92128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 7:
92138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* load/store byte immediate offset */
92148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        rd = insn & 7;
92158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        rn = (insn >> 3) & 7;
92168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        addr = load_reg(s, rn);
92178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        val = (insn >> 6) & 0x1f;
92188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tcg_gen_addi_i32(addr, addr, val);
92198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
92208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (insn & (1 << 11)) {
92218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* load */
92228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tmp = gen_ld8u(addr, IS_USER(s));
92238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            store_reg(s, rd, tmp);
92248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        } else {
92258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* store */
92268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tmp = load_reg(s, rd);
92278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            gen_st8(tmp, addr, IS_USER(s));
92288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
92295285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tcg_temp_free_i32(addr);
92308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
92318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
92328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 8:
92338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* load/store halfword immediate offset */
92348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        rd = insn & 7;
92358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        rn = (insn >> 3) & 7;
92368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        addr = load_reg(s, rn);
92378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        val = (insn >> 5) & 0x3e;
92388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tcg_gen_addi_i32(addr, addr, val);
92398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
92408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (insn & (1 << 11)) {
92418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* load */
92428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tmp = gen_ld16u(addr, IS_USER(s));
92438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            store_reg(s, rd, tmp);
92448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        } else {
92458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* store */
92468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tmp = load_reg(s, rd);
92478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            gen_st16(tmp, addr, IS_USER(s));
92488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
92495285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tcg_temp_free_i32(addr);
92508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
92518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
92528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 9:
92538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* load/store from stack */
92548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        rd = (insn >> 8) & 7;
92558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        addr = load_reg(s, 13);
92568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        val = (insn & 0xff) * 4;
92578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tcg_gen_addi_i32(addr, addr, val);
92588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
92598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (insn & (1 << 11)) {
92608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* load */
92618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tmp = gen_ld32(addr, IS_USER(s));
92628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            store_reg(s, rd, tmp);
92638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        } else {
92648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* store */
92658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tmp = load_reg(s, rd);
92668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            gen_st32(tmp, addr, IS_USER(s));
92678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
92685285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tcg_temp_free_i32(addr);
92698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
92708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
92718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 10:
92728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* add to high reg */
92738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        rd = (insn >> 8) & 7;
92748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (insn & (1 << 11)) {
92758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* SP */
92768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tmp = load_reg(s, 13);
92778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        } else {
92788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* PC. bit 1 is ignored.  */
92795285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tmp = tcg_temp_new_i32();
92808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tcg_gen_movi_i32(tmp, (s->pc + 2) & ~(uint32_t)2);
92818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
92828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        val = (insn & 0xff) * 4;
92838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tcg_gen_addi_i32(tmp, tmp, val);
92848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        store_reg(s, rd, tmp);
92858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
92868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
92878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 11:
92888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* misc */
92898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        op = (insn >> 8) & 0xf;
92908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        switch (op) {
92918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0:
92928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* adjust stack pointer */
92938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tmp = load_reg(s, 13);
92948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            val = (insn & 0x7f) * 4;
92958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (insn & (1 << 7))
92968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                val = -(int32_t)val;
92978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tcg_gen_addi_i32(tmp, tmp, val);
92988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            store_reg(s, 13, tmp);
92998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
93008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
93018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 2: /* sign/zero extend.  */
93028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            ARCH(6);
93038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            rd = insn & 7;
93048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            rm = (insn >> 3) & 7;
93058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tmp = load_reg(s, rm);
93068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            switch ((insn >> 6) & 3) {
93078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            case 0: gen_sxth(tmp); break;
93088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            case 1: gen_sxtb(tmp); break;
93098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            case 2: gen_uxth(tmp); break;
93108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            case 3: gen_uxtb(tmp); break;
93118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
93128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            store_reg(s, rd, tmp);
93138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
93148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 4: case 5: case 0xc: case 0xd:
93158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* push/pop */
93168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            addr = load_reg(s, 13);
93178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (insn & (1 << 8))
93188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                offset = 4;
93198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            else
93208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                offset = 0;
93218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            for (i = 0; i < 8; i++) {
93228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (insn & (1 << i))
93238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    offset += 4;
93248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
93258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if ((insn & (1 << 11)) == 0) {
93268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                tcg_gen_addi_i32(addr, addr, -offset);
93278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
93285285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tmp2 = tcg_const_i32(4);
93298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            for (i = 0; i < 8; i++) {
93308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (insn & (1 << i)) {
93318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    if (insn & (1 << 11)) {
93328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        /* pop */
93338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        tmp = gen_ld32(addr, IS_USER(s));
93348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        store_reg(s, i, tmp);
93358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    } else {
93368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        /* push */
93378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        tmp = load_reg(s, i);
93388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        gen_st32(tmp, addr, IS_USER(s));
93398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    }
93408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    /* advance to the next address.  */
93415285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tcg_gen_add_i32(addr, addr, tmp2);
93428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
93438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
93448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            TCGV_UNUSED(tmp);
93458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (insn & (1 << 8)) {
93468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (insn & (1 << 11)) {
93478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    /* pop pc */
93488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    tmp = gen_ld32(addr, IS_USER(s));
93498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    /* don't set the pc until the rest of the instruction
93508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                       has completed */
93518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                } else {
93528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    /* push lr */
93538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    tmp = load_reg(s, 14);
93548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    gen_st32(tmp, addr, IS_USER(s));
93558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
93565285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_gen_add_i32(addr, addr, tmp2);
93578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
93585285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tcg_temp_free_i32(tmp2);
93598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if ((insn & (1 << 11)) == 0) {
93608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                tcg_gen_addi_i32(addr, addr, -offset);
93618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
93628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* write back the new stack pointer */
93638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            store_reg(s, 13, addr);
93648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* set the new PC value */
93655285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            if ((insn & 0x0900) == 0x0900) {
93665285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                store_reg_from_load(env, s, 15, tmp);
93675285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            }
93688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
93698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
93708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 1: case 3: case 9: case 11: /* czb */
93718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            rm = insn & 7;
93728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tmp = load_reg(s, rm);
93738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            s->condlabel = gen_new_label();
93748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            s->condjmp = 1;
93758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (insn & (1 << 11))
93768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, s->condlabel);
93778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            else
93788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, s->condlabel);
93795285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tcg_temp_free_i32(tmp);
93808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            offset = ((insn & 0xf8) >> 2) | (insn & 0x200) >> 3;
93818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            val = (uint32_t)s->pc + 2;
93828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            val += offset;
93838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            gen_jmp(s, val);
93848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
93858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
93868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 15: /* IT, nop-hint.  */
93878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if ((insn & 0xf) == 0) {
93888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                gen_nop_hint(s, (insn >> 4) & 0xf);
93898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                break;
93908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
93918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* If Then.  */
9392a1204591a52bf668ee72c86f98f53189621572a2Vladimir Chtchetkine            s->condexec_cond = (insn >> 4) & 0xe;
9393a1204591a52bf668ee72c86f98f53189621572a2Vladimir Chtchetkine            s->condexec_mask = insn & 0x1f;
93948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* No actual code generated for this insn, just setup state.  */
93958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
93968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
93978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0xe: /* bkpt */
93985285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            ARCH(5);
93995285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            gen_exception_insn(s, 2, EXCP_BKPT);
94008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
94018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
94028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 0xa: /* rev */
94038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            ARCH(6);
94048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            rn = (insn >> 3) & 0x7;
94058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            rd = insn & 0x7;
94068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tmp = load_reg(s, rn);
94078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            switch ((insn >> 6) & 3) {
94085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            case 0: tcg_gen_bswap32_i32(tmp, tmp); break;
94098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            case 1: gen_rev16(tmp); break;
94108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            case 3: gen_revsh(tmp); break;
94118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            default: goto illegal_op;
94128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
94138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            store_reg(s, rd, tmp);
94148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
94158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
94168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case 6: /* cps */
94178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            ARCH(6);
94188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (IS_USER(s))
94198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                break;
94208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (IS_M(env)) {
94218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                tmp = tcg_const_i32((insn & (1 << 4)) != 0);
94228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* PRIMASK */
94238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (insn & 1) {
94248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    addr = tcg_const_i32(16);
94258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    gen_helper_v7m_msr(cpu_env, addr, tmp);
94265285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tcg_temp_free_i32(addr);
94278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
94288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* FAULTMASK */
94298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (insn & 2) {
94308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    addr = tcg_const_i32(17);
94318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    gen_helper_v7m_msr(cpu_env, addr, tmp);
94325285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tcg_temp_free_i32(addr);
94338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
94345285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                tcg_temp_free_i32(tmp);
94358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                gen_lookup_tb(s);
94368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            } else {
94378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (insn & (1 << 4))
94388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    shift = CPSR_A | CPSR_I | CPSR_F;
94398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                else
94408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    shift = 0;
94415285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                gen_set_psr_im(s, ((insn & 7) << 6), 0, shift);
94428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
94438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
94448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
94458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        default:
94468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            goto undef;
94478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
94488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
94498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
94508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 12:
94515285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    {
94528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* load/store multiple */
94535285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        TCGv loaded_var;
94545285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        TCGV_UNUSED(loaded_var);
94558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        rn = (insn >> 8) & 0x7;
94568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        addr = load_reg(s, rn);
94578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        for (i = 0; i < 8; i++) {
94588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (insn & (1 << i)) {
94598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (insn & (1 << 11)) {
94608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    /* load */
94618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    tmp = gen_ld32(addr, IS_USER(s));
94625285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    if (i == rn) {
94635285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        loaded_var = tmp;
94645285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    } else {
94655285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        store_reg(s, i, tmp);
94665285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    }
94678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                } else {
94688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    /* store */
94698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    tmp = load_reg(s, i);
94708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    gen_st32(tmp, addr, IS_USER(s));
94718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
94728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* advance to the next address */
94738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                tcg_gen_addi_i32(addr, addr, 4);
94748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
94758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
94768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if ((insn & (1 << rn)) == 0) {
94775285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            /* base reg not in list: base register writeback */
94788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            store_reg(s, rn, addr);
94798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        } else {
94805285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            /* base reg in list: if load, complete it now */
94815285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            if (insn & (1 << 11)) {
94825285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                store_reg(s, rn, loaded_var);
94835285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            }
94845285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tcg_temp_free_i32(addr);
94858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
94868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
94875285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    }
94888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 13:
94898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* conditional branch or swi */
94908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        cond = (insn >> 8) & 0xf;
94918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (cond == 0xe)
94928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            goto undef;
94938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
94948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (cond == 0xf) {
94958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* swi */
94968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            gen_set_pc_im(s->pc);
94978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            s->is_jmp = DISAS_SWI;
94988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
94998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
95008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* generate a conditional jump to next instruction */
95018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        s->condlabel = gen_new_label();
95028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_test_cc(cond ^ 1, s->condlabel);
95038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        s->condjmp = 1;
95048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
95058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* jump to the offset */
95068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        val = (uint32_t)s->pc + 2;
95078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        offset = ((int32_t)insn << 24) >> 24;
95088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        val += offset << 1;
95098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_jmp(s, val);
95108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
95118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
95128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 14:
95138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (insn & (1 << 11)) {
95148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (disas_thumb2_insn(env, s, insn))
95158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project              goto undef32;
95168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
95178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
95188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* unconditional branch */
95198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        val = (uint32_t)s->pc;
95208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        offset = ((int32_t)insn << 21) >> 21;
95218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        val += (offset << 1) + 2;
95228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_jmp(s, val);
95238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
95248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
95258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case 15:
95268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (disas_thumb2_insn(env, s, insn))
95278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            goto undef32;
95288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
95298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
95308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return;
95318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectundef32:
95325285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    gen_exception_insn(s, 4, EXCP_UDEF);
95338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return;
95348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectillegal_op:
95358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectundef:
95365285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    gen_exception_insn(s, 2, EXCP_UDEF);
95378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
95388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
95398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* generate intermediate code in gen_opc_buf and gen_opparam_buf for
95408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   basic block 'tb'. If search_pc is TRUE, also generate PC
95418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   information for each intermediate instruction. */
95428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline void gen_intermediate_code_internal(CPUState *env,
95438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                                  TranslationBlock *tb,
95448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                                  int search_pc)
95458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
95468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    DisasContext dc1, *dc = &dc1;
95475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    CPUBreakpoint *bp;
95488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    uint16_t *gen_opc_end;
95498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int j, lj;
95508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    target_ulong pc_start;
95518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    uint32_t next_page_start;
95528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int num_insns;
95538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int max_insns;
95548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
95558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* generate intermediate code */
95568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    pc_start = tb->pc;
95578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
95588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    dc->tb = tb;
95598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
95608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
95618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
95628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    dc->is_jmp = DISAS_NEXT;
95638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    dc->pc = pc_start;
95648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    dc->singlestep_enabled = env->singlestep_enabled;
95658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    dc->condjmp = 0;
95665285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    dc->thumb = ARM_TBFLAG_THUMB(tb->flags);
95675285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    dc->condexec_mask = (ARM_TBFLAG_CONDEXEC(tb->flags) & 0xf) << 1;
95685285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    dc->condexec_cond = ARM_TBFLAG_CONDEXEC(tb->flags) >> 4;
95698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if !defined(CONFIG_USER_ONLY)
95705285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    dc->user = (ARM_TBFLAG_PRIV(tb->flags) == 0);
95718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
9572288208c386810fef725aa448a9f46bd2772bec8cDavid 'Digit' Turner    ANDROID_START_CODEGEN(search_pc);
95735285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    dc->vfp_enabled = ARM_TBFLAG_VFPEN(tb->flags);
95745285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    dc->vec_len = ARM_TBFLAG_VECLEN(tb->flags);
95755285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    dc->vec_stride = ARM_TBFLAG_VECSTRIDE(tb->flags);
95765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    cpu_F0s = tcg_temp_new_i32();
95775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    cpu_F1s = tcg_temp_new_i32();
95785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    cpu_F0d = tcg_temp_new_i64();
95795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    cpu_F1d = tcg_temp_new_i64();
95808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    cpu_V0 = cpu_F0d;
95818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    cpu_V1 = cpu_F1d;
95828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* FIXME: cpu_M0 can probably be the same as cpu_V0.  */
95835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    cpu_M0 = tcg_temp_new_i64();
95848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
95858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    lj = -1;
95868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    num_insns = 0;
95878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    max_insns = tb->cflags & CF_COUNT_MASK;
95888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (max_insns == 0)
95898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        max_insns = CF_COUNT_MASK;
95908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
95918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    gen_icount_start();
9592288208c386810fef725aa448a9f46bd2772bec8cDavid 'Digit' Turner    ANDROID_TRACE_START_BB();
95938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
95945285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    tcg_clear_temp_count();
95955285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
95965285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    /* A note on handling of the condexec (IT) bits:
95975285864985be9077e58e42235af6582dee72e841David 'Digit' Turner     *
95985285864985be9077e58e42235af6582dee72e841David 'Digit' Turner     * We want to avoid the overhead of having to write the updated condexec
95995285864985be9077e58e42235af6582dee72e841David 'Digit' Turner     * bits back to the CPUState for every instruction in an IT block. So:
96005285864985be9077e58e42235af6582dee72e841David 'Digit' Turner     * (1) if the condexec bits are not already zero then we write
96015285864985be9077e58e42235af6582dee72e841David 'Digit' Turner     * zero back into the CPUState now. This avoids complications trying
96025285864985be9077e58e42235af6582dee72e841David 'Digit' Turner     * to do it at the end of the block. (For example if we don't do this
96035285864985be9077e58e42235af6582dee72e841David 'Digit' Turner     * it's hard to identify whether we can safely skip writing condexec
96045285864985be9077e58e42235af6582dee72e841David 'Digit' Turner     * at the end of the TB, which we definitely want to do for the case
96055285864985be9077e58e42235af6582dee72e841David 'Digit' Turner     * where a TB doesn't do anything with the IT state at all.)
96065285864985be9077e58e42235af6582dee72e841David 'Digit' Turner     * (2) if we are going to leave the TB then we call gen_set_condexec()
96075285864985be9077e58e42235af6582dee72e841David 'Digit' Turner     * which will write the correct value into CPUState if zero is wrong.
96085285864985be9077e58e42235af6582dee72e841David 'Digit' Turner     * This is done both for leaving the TB at the end, and for leaving
96095285864985be9077e58e42235af6582dee72e841David 'Digit' Turner     * it because of an exception we know will happen, which is done in
96105285864985be9077e58e42235af6582dee72e841David 'Digit' Turner     * gen_exception_insn(). The latter is necessary because we need to
96115285864985be9077e58e42235af6582dee72e841David 'Digit' Turner     * leave the TB with the PC/IT state just prior to execution of the
96125285864985be9077e58e42235af6582dee72e841David 'Digit' Turner     * instruction which caused the exception.
96135285864985be9077e58e42235af6582dee72e841David 'Digit' Turner     * (3) if we leave the TB unexpectedly (eg a data abort on a load)
96145285864985be9077e58e42235af6582dee72e841David 'Digit' Turner     * then the CPUState will be wrong and we need to reset it.
96155285864985be9077e58e42235af6582dee72e841David 'Digit' Turner     * This is handled in the same way as restoration of the
96165285864985be9077e58e42235af6582dee72e841David 'Digit' Turner     * PC in these situations: we will be called again with search_pc=1
96175285864985be9077e58e42235af6582dee72e841David 'Digit' Turner     * and generate a mapping of the condexec bits for each PC in
96185285864985be9077e58e42235af6582dee72e841David 'Digit' Turner     * gen_opc_condexec_bits[]. restore_state_to_opc() then uses
96195285864985be9077e58e42235af6582dee72e841David 'Digit' Turner     * this to restore the condexec bits.
96205285864985be9077e58e42235af6582dee72e841David 'Digit' Turner     *
96215285864985be9077e58e42235af6582dee72e841David 'Digit' Turner     * Note that there are no instructions which can read the condexec
96225285864985be9077e58e42235af6582dee72e841David 'Digit' Turner     * bits, and none which can write non-static values to them, so
96235285864985be9077e58e42235af6582dee72e841David 'Digit' Turner     * we don't need to care about whether CPUState is correct in the
96245285864985be9077e58e42235af6582dee72e841David 'Digit' Turner     * middle of a TB.
96255285864985be9077e58e42235af6582dee72e841David 'Digit' Turner     */
96265285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
96275285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    /* Reset the conditional execution bits immediately. This avoids
96285285864985be9077e58e42235af6582dee72e841David 'Digit' Turner       complications trying to do it at the end of the block.  */
96295285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    if (dc->condexec_mask || dc->condexec_cond)
96305285864985be9077e58e42235af6582dee72e841David 'Digit' Turner      {
96315285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        TCGv tmp = tcg_temp_new_i32();
96325285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        tcg_gen_movi_i32(tmp, 0);
96335285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        store_cpu_field(tmp, condexec_bits);
96345285864985be9077e58e42235af6582dee72e841David 'Digit' Turner      }
96358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    do {
96368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef CONFIG_USER_ONLY
96378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* Intercept jump to the magic kernel page.  */
96388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (dc->pc >= 0xffff0000) {
96398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* We always get here via a jump, so know we are not in a
96408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project               conditional execution block.  */
96418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            gen_exception(EXCP_KERNEL_TRAP);
96428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            dc->is_jmp = DISAS_UPDATE;
96438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
96448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
96458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else
96468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (dc->pc >= 0xfffffff0 && IS_M(env)) {
96478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* We always get here via a jump, so know we are not in a
96488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project               conditional execution block.  */
96498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            gen_exception(EXCP_EXCEPTION_EXIT);
96508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            dc->is_jmp = DISAS_UPDATE;
96518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
96528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
96538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
96548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9655a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner        if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
9656a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner            QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
96575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                if (bp->pc == dc->pc) {
96585285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    gen_exception_insn(dc, 0, EXCP_DEBUG);
96598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    /* Advance PC so that clearing the breakpoint will
96608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                       invalidate this TB.  */
96618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    dc->pc += 2;
96628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    goto done_generating;
96638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    break;
96648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
96658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
96668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
96675389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine
9668288208c386810fef725aa448a9f46bd2772bec8cDavid 'Digit' Turner        if (ANDROID_CHECK_CODEGEN_PC(search_pc)) {
96698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            j = gen_opc_ptr - gen_opc_buf;
96708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (lj < j) {
96718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                lj++;
96728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                while (lj < j)
96738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    gen_opc_instr_start[lj++] = 0;
96748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
96758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            gen_opc_pc[lj] = dc->pc;
96765285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            gen_opc_condexec_bits[lj] = (dc->condexec_cond << 4) | (dc->condexec_mask >> 1);
96778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            gen_opc_instr_start[lj] = 1;
96788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            gen_opc_icount[lj] = num_insns;
96798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
96808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
96818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
96828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            gen_io_start();
96838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
96845285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP))) {
96855285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            tcg_gen_debug_insn_start(dc->pc);
96865285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        }
96875285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
96885285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        if (dc->thumb) {
96898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            disas_thumb_insn(env, dc);
96908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (dc->condexec_mask) {
9691a1204591a52bf668ee72c86f98f53189621572a2Vladimir Chtchetkine                dc->condexec_cond = (dc->condexec_cond & 0xe)
9692a1204591a52bf668ee72c86f98f53189621572a2Vladimir Chtchetkine                                   | ((dc->condexec_mask >> 4) & 1);
9693a1204591a52bf668ee72c86f98f53189621572a2Vladimir Chtchetkine                dc->condexec_mask = (dc->condexec_mask << 1) & 0x1f;
9694a1204591a52bf668ee72c86f98f53189621572a2Vladimir Chtchetkine                if (dc->condexec_mask == 0) {
9695a1204591a52bf668ee72c86f98f53189621572a2Vladimir Chtchetkine                    dc->condexec_cond = 0;
96968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                }
96978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
96988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        } else {
96998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            disas_arm_insn(env, dc);
97008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
97018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
97028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (dc->condjmp && !dc->is_jmp) {
97038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            gen_set_label(dc->condlabel);
97048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            dc->condjmp = 0;
97058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
97065285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
97075285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        if (tcg_check_temp_count()) {
97085285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            fprintf(stderr, "TCG temporary leak before %08x\n", dc->pc);
97095285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        }
97105285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
97115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        /* Translation stops when a conditional branch is encountered.
97128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         * Otherwise the subsequent code could get translated several times.
97138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         * Also stop translation when a page boundary is reached.  This
97148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         * ensures prefetch aborts occur at the right place.  */
97158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        num_insns ++;
97168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } while (!dc->is_jmp && gen_opc_ptr < gen_opc_end &&
97178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project             !env->singlestep_enabled &&
97185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner             !singlestep &&
97198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project             dc->pc < next_page_start &&
97208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project             num_insns < max_insns);
97218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9722288208c386810fef725aa448a9f46bd2772bec8cDavid 'Digit' Turner    ANDROID_TRACE_END_BB();
97238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
97248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (tb->cflags & CF_LAST_IO) {
97258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (dc->condjmp) {
97268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* FIXME:  This can theoretically happen with self-modifying
97278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project               code.  */
97288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            cpu_abort(env, "IO on conditional branch instruction");
97298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
97308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_io_end();
97318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
97328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
97338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* At this stage dc->condjmp will only be set when the skipped
97348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project       instruction was a conditional branch or trap, and the PC has
97358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project       already been written.  */
97368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (unlikely(env->singlestep_enabled)) {
97378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* Make sure the pc is updated, and raise a debug exception.  */
97388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (dc->condjmp) {
97398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            gen_set_condexec(dc);
97408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (dc->is_jmp == DISAS_SWI) {
97418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                gen_exception(EXCP_SWI);
97425285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            } else if (dc->is_jmp == DISAS_SMC) {
97435285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                gen_exception(EXCP_SMC);
97448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            } else {
97458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                gen_exception(EXCP_DEBUG);
97468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
97478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            gen_set_label(dc->condlabel);
97488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
97498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (dc->condjmp || !dc->is_jmp) {
97508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            gen_set_pc_im(dc->pc);
97518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            dc->condjmp = 0;
97528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
97538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_set_condexec(dc);
97548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (dc->is_jmp == DISAS_SWI && !dc->condjmp) {
97558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            gen_exception(EXCP_SWI);
97565285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        } else if (dc->is_jmp == DISAS_SMC && !dc->condjmp) {
97575285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            gen_exception(EXCP_SMC);
97588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        } else {
97598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* FIXME: Single stepping a WFI insn will not halt
97608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project               the CPU.  */
97618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            gen_exception(EXCP_DEBUG);
97628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
97638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } else {
97648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* While branches must always occur at the end of an IT block,
97658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project           there are a few other things that can cause us to terminate
97668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project           the TB in the middel of an IT block:
97678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            - Exception generating instructions (bkpt, swi, undefined).
97688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            - Page boundaries.
97698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            - Hardware watchpoints.
97708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project           Hardware breakpoints have already been handled and skip this code.
97718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         */
97728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        gen_set_condexec(dc);
97738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        switch(dc->is_jmp) {
97748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case DISAS_NEXT:
97758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            gen_goto_tb(dc, 1, dc->pc);
97768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
97778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        default:
97788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case DISAS_JUMP:
97798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case DISAS_UPDATE:
97808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* indicate that the hash table must be used to find the next TB */
97818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tcg_gen_exit_tb(0);
97828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
97838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case DISAS_TB_JUMP:
97848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* nothing more to generate */
97858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
97868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case DISAS_WFI:
97878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            gen_helper_wfi();
97888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
97898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case DISAS_SWI:
97908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            gen_exception(EXCP_SWI);
97918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
97925285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        case DISAS_SMC:
97935285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            gen_exception(EXCP_SMC);
97945285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            break;
97958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
97968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (dc->condjmp) {
97978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            gen_set_label(dc->condlabel);
97988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            gen_set_condexec(dc);
97998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            gen_goto_tb(dc, 1, dc->pc);
98008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            dc->condjmp = 0;
98018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
98028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
98038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
98048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdone_generating:
98058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    gen_icount_end(tb, num_insns);
98068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    *gen_opc_ptr = INDEX_op_end;
98078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
98088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef DEBUG_DISAS
98095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
98105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        qemu_log("----------------\n");
98115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        qemu_log("IN: %s\n", lookup_symbol(pc_start));
98125285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        log_target_disas(pc_start, dc->pc - pc_start, dc->thumb);
98135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        qemu_log("\n");
98148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
98158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
98168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (search_pc) {
98178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        j = gen_opc_ptr - gen_opc_buf;
98188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        lj++;
98198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        while (lj <= j)
98208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            gen_opc_instr_start[lj++] = 0;
98218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } else {
9822288208c386810fef725aa448a9f46bd2772bec8cDavid 'Digit' Turner        ANDROID_END_CODEGEN();
98238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tb->size = dc->pc - pc_start;
98248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tb->icount = num_insns;
98258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
98268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
98278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
98288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid gen_intermediate_code(CPUState *env, TranslationBlock *tb)
98298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
98308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    gen_intermediate_code_internal(env, tb, 0);
98318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
98328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
98338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid gen_intermediate_code_pc(CPUState *env, TranslationBlock *tb)
98348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
98358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    gen_intermediate_code_internal(env, tb, 1);
98368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
98378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
98388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic const char *cpu_mode_names[16] = {
98398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project  "usr", "fiq", "irq", "svc", "???", "???", "???", "abt",
98408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project  "???", "???", "???", "und", "???", "???", "???", "sys"
98418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project};
98428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
98435285864985be9077e58e42235af6582dee72e841David 'Digit' Turnervoid cpu_dump_state(CPUState *env, FILE *f, fprintf_function cpu_fprintf,
98448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    int flags)
98458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
98468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int i;
98478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if 0
98488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    union {
98498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        uint32_t i;
98508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        float s;
98518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } s0, s1;
98528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    CPU_DoubleU d;
98538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* ??? This assumes float64 and double have the same layout.
98548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project       Oh well, it's only debug dumps.  */
98558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    union {
98568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        float64 f64;
98578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        double d;
98588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } d0;
98598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
98608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    uint32_t psr;
98618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
98628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for(i=0;i<16;i++) {
98638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        cpu_fprintf(f, "R%02d=%08x", i, env->regs[i]);
98648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if ((i % 4) == 3)
98658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            cpu_fprintf(f, "\n");
98668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        else
98678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            cpu_fprintf(f, " ");
98688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
98698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    psr = cpsr_read(env);
98708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    cpu_fprintf(f, "PSR=%08x %c%c%c%c %c %s%d\n",
98718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                psr,
98728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                psr & (1 << 31) ? 'N' : '-',
98738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                psr & (1 << 30) ? 'Z' : '-',
98748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                psr & (1 << 29) ? 'C' : '-',
98758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                psr & (1 << 28) ? 'V' : '-',
98768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                psr & CPSR_T ? 'T' : 'A',
98778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                cpu_mode_names[psr & 0xf], (psr & 0x10) ? 32 : 26);
98788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
98798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if 0
98808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for (i = 0; i < 16; i++) {
98818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        d.d = env->vfp.regs[i];
98828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        s0.i = d.l.lower;
98838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        s1.i = d.l.upper;
98848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        d0.f64 = d.d;
98858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        cpu_fprintf(f, "s%02d=%08x(%8g) s%02d=%08x(%8g) d%02d=%08x%08x(%8g)\n",
98868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    i * 2, (int)s0.i, s0.s,
98878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    i * 2 + 1, (int)s1.i, s1.s,
98888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    i, (int)(uint32_t)d.l.upper, (int)(uint32_t)d.l.lower,
98898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    d0.d);
98908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
98918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    cpu_fprintf(f, "FPSCR: %08x\n", (int)env->vfp.xregs[ARM_VFP_FPSCR]);
98928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
98938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
98948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9895d3d4468189618e89f74d8f51b8470f277e000938David 'Digit' Turnervoid restore_state_to_opc(CPUState *env, TranslationBlock *tb, int pc_pos)
98968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
98978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    env->regs[15] = gen_opc_pc[pc_pos];
98985285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    env->condexec_bits = gen_opc_condexec_bits[pc_pos];
98998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
9900