18b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*
28b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *  ARM helper routines
38b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *
48b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *  Copyright (c) 2005-2007 CodeSourcery, LLC
58b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *
68b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * This library is free software; you can redistribute it and/or
78b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * modify it under the terms of the GNU Lesser General Public
88b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * License as published by the Free Software Foundation; either
98b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * version 2 of the License, or (at your option) any later version.
108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *
118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * This library is distributed in the hope that it will be useful,
128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * but WITHOUT ANY WARRANTY; without even the implied warranty of
138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Lesser General Public License for more details.
158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *
168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * You should have received a copy of the GNU Lesser General Public
175285864985be9077e58e42235af6582dee72e841David 'Digit' Turner * License along with this library; if not, see <http://www.gnu.org/licenses/>.
188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */
198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "exec.h"
205285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#include "helper.h"
218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define SIGNBIT (uint32_t)0x80000000
238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define SIGNBIT64 ((uint64_t)1 << 63)
248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid raise_exception(int tt)
268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    env->exception_index = tt;
288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    cpu_loop_exit();
298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectuint32_t HELPER(neon_tbl)(uint32_t ireg, uint32_t def,
328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                          uint32_t rn, uint32_t maxindex)
338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    uint32_t val;
358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    uint32_t tmp;
368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int index;
378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int shift;
388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    uint64_t *table;
398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    table = (uint64_t *)&env->vfp.regs[rn];
408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    val = 0;
418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for (shift = 0; shift < 32; shift += 8) {
428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        index = (ireg >> shift) & 0xff;
438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (index < maxindex) {
445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            tmp = (table[index >> 3] >> ((index & 7) << 3)) & 0xff;
458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            val |= tmp << shift;
468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        } else {
478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            val |= def & (0xff << shift);
488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return val;
518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if !defined(CONFIG_USER_ONLY)
548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define MMUSUFFIX _mmu
568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define SHIFT 0
588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "softmmu_template.h"
598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define SHIFT 1
618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "softmmu_template.h"
628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define SHIFT 2
648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "softmmu_template.h"
658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define SHIFT 3
678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "softmmu_template.h"
688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* try to fill the TLB and return an exception if error. If retaddr is
708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   NULL, it means that the function was called in C code (i.e. not
718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   from generated code or from helper.c) */
728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* XXX: fix it to restore all registers */
738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid tlb_fill (target_ulong addr, int is_write, int mmu_idx, void *retaddr)
748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    TranslationBlock *tb;
768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    CPUState *saved_env;
778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    unsigned long pc;
788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int ret;
798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* XXX: hack to restore env in all cases, even if not called from
818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project       generated code */
828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    saved_env = env;
838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    env = cpu_single_env;
848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    ret = cpu_arm_handle_mmu_fault(env, addr, is_write, mmu_idx, 1);
858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (unlikely(ret)) {
868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (retaddr) {
878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* now we have a real cpu fault */
888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            pc = (unsigned long)retaddr;
898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            tb = tb_find_pc(pc);
908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (tb) {
918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /* the PC is inside the translated code. It means that we have
928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                   a virtual CPU fault */
93f645f7d6fd841e39524e5df8c1a7fd8347f92ac1David 'Digit' Turner                cpu_restore_state(tb, env, pc);
948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        raise_exception(env->exception_index);
978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    env = saved_env;
998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
1008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1015285864985be9077e58e42235af6582dee72e841David 'Digit' Turnervoid HELPER(set_cp)(CPUState *env, uint32_t insn, uint32_t val)
1025285864985be9077e58e42235af6582dee72e841David 'Digit' Turner{
1035285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    int cp_num = (insn >> 8) & 0xf;
1045285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    int cp_info = (insn >> 5) & 7;
1055285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    int src = (insn >> 16) & 0xf;
1065285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    int operand = insn & 0xf;
1075285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
1085285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    if (env->cp[cp_num].cp_write)
1095285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        env->cp[cp_num].cp_write(env->cp[cp_num].opaque,
1105285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                                 cp_info, src, operand, val, GETPC());
1115285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        }
1125285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
1135285864985be9077e58e42235af6582dee72e841David 'Digit' Turneruint32_t HELPER(get_cp)(CPUState *env, uint32_t insn)
1145285864985be9077e58e42235af6582dee72e841David 'Digit' Turner{
1155285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    int cp_num = (insn >> 8) & 0xf;
1165285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    int cp_info = (insn >> 5) & 7;
1175285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    int dest = (insn >> 16) & 0xf;
1185285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    int operand = insn & 0xf;
1195285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
1205285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    if (env->cp[cp_num].cp_read)
1215285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        return env->cp[cp_num].cp_read(env->cp[cp_num].opaque,
1225285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                                       cp_info, dest, operand, GETPC());
1235285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        return 0;
1245285864985be9077e58e42235af6582dee72e841David 'Digit' Turner}
1255285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
1265285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#else
1275285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
1285285864985be9077e58e42235af6582dee72e841David 'Digit' Turnervoid HELPER(set_cp)(CPUState *env, uint32_t insn, uint32_t val)
1295285864985be9077e58e42235af6582dee72e841David 'Digit' Turner{
1305285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    int op1 = (insn >> 8) & 0xf;
1315285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    cpu_abort(env, "cp%i insn %08x\n", op1, insn);
1325285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    return;
1335285864985be9077e58e42235af6582dee72e841David 'Digit' Turner}
1345285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
1355285864985be9077e58e42235af6582dee72e841David 'Digit' Turneruint32_t HELPER(get_cp)(CPUState *env, uint32_t insn)
1365285864985be9077e58e42235af6582dee72e841David 'Digit' Turner{
1375285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    int op1 = (insn >> 8) & 0xf;
1385285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    cpu_abort(env, "cp%i insn %08x\n", op1, insn);
1395285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    return 0;
1405285864985be9077e58e42235af6582dee72e841David 'Digit' Turner}
1415285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
1428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
1438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* FIXME: Pass an axplicit pointer to QF to CPUState, and move saturating
1458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   instructions into helper.c  */
1468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectuint32_t HELPER(add_setq)(uint32_t a, uint32_t b)
1478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    uint32_t res = a + b;
1498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (((res ^ a) & SIGNBIT) && !((a ^ b) & SIGNBIT))
1508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        env->QF = 1;
1518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return res;
1528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
1538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectuint32_t HELPER(add_saturate)(uint32_t a, uint32_t b)
1558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    uint32_t res = a + b;
1578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (((res ^ a) & SIGNBIT) && !((a ^ b) & SIGNBIT)) {
1588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        env->QF = 1;
1598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        res = ~(((int32_t)a >> 31) ^ SIGNBIT);
1608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
1618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return res;
1628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
1638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectuint32_t HELPER(sub_saturate)(uint32_t a, uint32_t b)
1658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    uint32_t res = a - b;
1678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (((res ^ a) & SIGNBIT) && ((a ^ b) & SIGNBIT)) {
1688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        env->QF = 1;
1698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        res = ~(((int32_t)a >> 31) ^ SIGNBIT);
1708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
1718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return res;
1728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
1738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectuint32_t HELPER(double_saturate)(int32_t val)
1758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    uint32_t res;
1778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (val >= 0x40000000) {
1788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        res = ~SIGNBIT;
1798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        env->QF = 1;
1808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } else if (val <= (int32_t)0xc0000000) {
1818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        res = SIGNBIT;
1828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        env->QF = 1;
1838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } else {
1848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        res = val << 1;
1858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
1868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return res;
1878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
1888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectuint32_t HELPER(add_usaturate)(uint32_t a, uint32_t b)
1908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    uint32_t res = a + b;
1928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (res < a) {
1938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        env->QF = 1;
1948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        res = ~0;
1958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
1968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return res;
1978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
1988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectuint32_t HELPER(sub_usaturate)(uint32_t a, uint32_t b)
2008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
2018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    uint32_t res = a - b;
2028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (res > a) {
2038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        env->QF = 1;
2048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        res = 0;
2058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
2068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return res;
2078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
2088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Signed saturation.  */
2108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline uint32_t do_ssat(int32_t val, int shift)
2118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
2128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int32_t top;
2138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    uint32_t mask;
2148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    top = val >> shift;
2168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    mask = (1u << shift) - 1;
2178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (top > 0) {
2188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        env->QF = 1;
2198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return mask;
2208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } else if (top < -1) {
2218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        env->QF = 1;
2228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return ~mask;
2238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
2248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return val;
2258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
2268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Unsigned saturation.  */
2288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline uint32_t do_usat(int32_t val, int shift)
2298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
2308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    uint32_t max;
2318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    max = (1u << shift) - 1;
2338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (val < 0) {
2348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        env->QF = 1;
2358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return 0;
2368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } else if (val > max) {
2378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        env->QF = 1;
2388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return max;
2398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
2408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return val;
2418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
2428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Signed saturate.  */
2448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectuint32_t HELPER(ssat)(uint32_t x, uint32_t shift)
2458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
2468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return do_ssat(x, shift);
2478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
2488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Dual halfword signed saturate.  */
2508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectuint32_t HELPER(ssat16)(uint32_t x, uint32_t shift)
2518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
2528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    uint32_t res;
2538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    res = (uint16_t)do_ssat((int16_t)x, shift);
2558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    res |= do_ssat(((int32_t)x) >> 16, shift) << 16;
2568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return res;
2578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
2588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Unsigned saturate.  */
2608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectuint32_t HELPER(usat)(uint32_t x, uint32_t shift)
2618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
2628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return do_usat(x, shift);
2638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
2648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Dual halfword unsigned saturate.  */
2668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectuint32_t HELPER(usat16)(uint32_t x, uint32_t shift)
2678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
2688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    uint32_t res;
2698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    res = (uint16_t)do_usat((int16_t)x, shift);
2718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    res |= do_usat(((int32_t)x) >> 16, shift) << 16;
2728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return res;
2738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
2748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid HELPER(wfi)(void)
2768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
2778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    env->exception_index = EXCP_HLT;
2788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    env->halted = 1;
2798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    cpu_loop_exit();
2808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
2818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid HELPER(exception)(uint32_t excp)
2838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
2848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    env->exception_index = excp;
2858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    cpu_loop_exit();
2868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
2878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectuint32_t HELPER(cpsr_read)(void)
2898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
2908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return cpsr_read(env) & ~CPSR_EXEC;
2918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
2928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid HELPER(cpsr_write)(uint32_t val, uint32_t mask)
2948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
2958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    cpsr_write(env, val, mask);
2968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
2978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Access to user mode registers from privileged modes.  */
2998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectuint32_t HELPER(get_user_reg)(uint32_t regno)
3008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
3018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    uint32_t val;
3028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (regno == 13) {
3048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        val = env->banked_r13[0];
3058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } else if (regno == 14) {
3068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        val = env->banked_r14[0];
3078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } else if (regno >= 8
3088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project               && (env->uncached_cpsr & 0x1f) == ARM_CPU_MODE_FIQ) {
3098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        val = env->usr_regs[regno - 8];
3108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } else {
3118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        val = env->regs[regno];
3128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
3138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return val;
3148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
3158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid HELPER(set_user_reg)(uint32_t regno, uint32_t val)
3178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
3188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (regno == 13) {
3198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        env->banked_r13[0] = val;
3208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } else if (regno == 14) {
3218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        env->banked_r14[0] = val;
3228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } else if (regno >= 8
3238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project               && (env->uncached_cpsr & 0x1f) == ARM_CPU_MODE_FIQ) {
3248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        env->usr_regs[regno - 8] = val;
3258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } else {
3268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        env->regs[regno] = val;
3278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
3288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
3298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* ??? Flag setting arithmetic is awkward because we need to do comparisons.
3318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   The only way to do that in TCG is a conditional branch, which clobbers
3328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   all our temporaries.  For now implement these as helper functions.  */
3338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectuint32_t HELPER (add_cc)(uint32_t a, uint32_t b)
3358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
3368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    uint32_t result;
3375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    result = a + b;
3388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    env->NF = env->ZF = result;
3398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    env->CF = result < a;
3408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    env->VF = (a ^ b ^ -1) & (a ^ result);
3418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return result;
3428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
3438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectuint32_t HELPER(adc_cc)(uint32_t a, uint32_t b)
3458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
3468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    uint32_t result;
3478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!env->CF) {
3488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        result = a + b;
3498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        env->CF = result < a;
3508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } else {
3518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        result = a + b + 1;
3528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        env->CF = result <= a;
3538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
3548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    env->VF = (a ^ b ^ -1) & (a ^ result);
3558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    env->NF = env->ZF = result;
3568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return result;
3578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
3588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectuint32_t HELPER(sub_cc)(uint32_t a, uint32_t b)
3608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
3618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    uint32_t result;
3628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    result = a - b;
3638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    env->NF = env->ZF = result;
3648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    env->CF = a >= b;
3658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    env->VF = (a ^ b) & (a ^ result);
3668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return result;
3678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
3688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectuint32_t HELPER(sbc_cc)(uint32_t a, uint32_t b)
3708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
3718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    uint32_t result;
3728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!env->CF) {
3738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        result = a - b - 1;
3748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        env->CF = a > b;
3758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } else {
3768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        result = a - b;
3778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        env->CF = a >= b;
3788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
3798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    env->VF = (a ^ b) & (a ^ result);
3808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    env->NF = env->ZF = result;
3818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return result;
3828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
3838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Similarly for variable shift instructions.  */
3858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectuint32_t HELPER(shl)(uint32_t x, uint32_t i)
3878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
3888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int shift = i & 0xff;
3898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (shift >= 32)
3908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return 0;
3918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return x << shift;
3928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
3938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectuint32_t HELPER(shr)(uint32_t x, uint32_t i)
3958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
3968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int shift = i & 0xff;
3978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (shift >= 32)
3988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return 0;
3998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return (uint32_t)x >> shift;
4008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
4018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectuint32_t HELPER(sar)(uint32_t x, uint32_t i)
4038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
4048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int shift = i & 0xff;
4058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (shift >= 32)
4068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        shift = 31;
4078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return (int32_t)x >> shift;
4088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
4098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectuint32_t HELPER(shl_cc)(uint32_t x, uint32_t i)
4118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
4128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int shift = i & 0xff;
4138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (shift >= 32) {
4148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (shift == 32)
4158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            env->CF = x & 1;
4168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        else
4178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            env->CF = 0;
4188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return 0;
4198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } else if (shift != 0) {
4208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        env->CF = (x >> (32 - shift)) & 1;
4218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return x << shift;
4228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
4238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return x;
4248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
4258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectuint32_t HELPER(shr_cc)(uint32_t x, uint32_t i)
4278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
4288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int shift = i & 0xff;
4298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (shift >= 32) {
4308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (shift == 32)
4318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            env->CF = (x >> 31) & 1;
4328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        else
4338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            env->CF = 0;
4348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return 0;
4358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } else if (shift != 0) {
4368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        env->CF = (x >> (shift - 1)) & 1;
4378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return x >> shift;
4388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
4398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return x;
4408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
4418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectuint32_t HELPER(sar_cc)(uint32_t x, uint32_t i)
4438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
4448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int shift = i & 0xff;
4458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (shift >= 32) {
4468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        env->CF = (x >> 31) & 1;
4478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return (int32_t)x >> 31;
4488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } else if (shift != 0) {
4498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        env->CF = (x >> (shift - 1)) & 1;
4508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return (int32_t)x >> shift;
4518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
4528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return x;
4538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
4548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectuint32_t HELPER(ror_cc)(uint32_t x, uint32_t i)
4568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
4578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int shift1, shift;
4588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    shift1 = i & 0xff;
4598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    shift = shift1 & 0x1f;
4608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (shift == 0) {
4618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (shift1 != 0)
4628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            env->CF = (x >> 31) & 1;
4638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return x;
4648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } else {
4658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        env->CF = (x >> (shift - 1)) & 1;
4668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return ((uint32_t)x >> shift) | (x << (32 - shift));
4678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
4688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
4698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4705285864985be9077e58e42235af6582dee72e841David 'Digit' Turnervoid HELPER(neon_vldst_all)(uint32_t insn)
4715285864985be9077e58e42235af6582dee72e841David 'Digit' Turner{
4725285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#if defined(CONFIG_USER_ONLY)
4735285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define LDB(addr) ldub(addr)
4745285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define LDW(addr) lduw(addr)
4755285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define LDL(addr) ldl(addr)
4765285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define LDQ(addr) ldq(addr)
4775285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define STB(addr, val) stb(addr, val)
4785285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define STW(addr, val) stw(addr, val)
4795285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define STL(addr, val) stl(addr, val)
4805285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define STQ(addr, val) stq(addr, val)
4815285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#else
4825285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    int user = cpu_mmu_index(env);
4835285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define LDB(addr) slow_ldb_mmu(addr, user, GETPC())
4845285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define LDW(addr) slow_ldw_mmu(addr, user, GETPC())
4855285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define LDL(addr) slow_ldl_mmu(addr, user, GETPC())
4865285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define LDQ(addr) slow_ldq_mmu(addr, user, GETPC())
4875285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define STB(addr, val) slow_stb_mmu(addr, val, user, GETPC())
4885285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define STW(addr, val) slow_stw_mmu(addr, val, user, GETPC())
4895285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define STL(addr, val) slow_stl_mmu(addr, val, user, GETPC())
4905285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#define STQ(addr, val) slow_stq_mmu(addr, val, user, GETPC())
4915285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#endif
4925285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    static const struct {
4935285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        int nregs;
4945285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        int interleave;
4955285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        int spacing;
4965285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    } neon_ls_element_type[11] = {
4975285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        {4, 4, 1},
4985285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        {4, 4, 2},
4995285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        {4, 1, 1},
5005285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        {4, 2, 1},
5015285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        {3, 3, 1},
5025285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        {3, 3, 2},
5035285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        {3, 1, 1},
5045285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        {1, 1, 1},
5055285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        {2, 2, 1},
5065285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        {2, 2, 2},
5075285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        {2, 1, 1}
5085285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    };
5095285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
5105285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    const int op = (insn >> 8) & 0xf;
5115285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    const int size = (insn >> 6) & 3;
5125285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    int rd = ((insn >> 12) & 0x0f) | ((insn >> 18) & 0x10);
5135285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    const int rn = (insn >> 16) & 0xf;
5145285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    const int load = (insn & (1 << 21)) != 0;
5155285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    const int nregs = neon_ls_element_type[op].nregs;
5165285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    const int interleave = neon_ls_element_type[op].interleave;
5175285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    const int spacing = neon_ls_element_type[op].spacing;
5185285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    uint32_t addr = env->regs[rn];
5195285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    const int stride = (1 << size) * interleave;
5205285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    int i, reg;
5215285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    uint64_t tmp64;
5225285864985be9077e58e42235af6582dee72e841David 'Digit' Turner
5235285864985be9077e58e42235af6582dee72e841David 'Digit' Turner    for (reg = 0; reg < nregs; reg++) {
5245285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        if (interleave > 2 || (interleave == 2 && nregs == 2)) {
5255285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            addr = env->regs[rn] + (1 << size) * reg;
5265285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        } else if (interleave == 2 && nregs == 4 && reg == 2) {
5275285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            addr = env->regs[rn] + (1 << size);
5285285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        }
5295285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        switch (size) {
5305285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            case 3:
5315285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                if (load) {
5325285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    env->vfp.regs[rd] = make_float64(LDQ(addr));
5335285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                } else {
5345285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    STQ(addr, float64_val(env->vfp.regs[rd]));
5355285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                }
5365285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                addr += stride;
5375285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                break;
5385285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            case 2:
5395285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                if (load) {
5405285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tmp64 = (uint32_t)LDL(addr);
5415285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    addr += stride;
5425285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tmp64 |= (uint64_t)LDL(addr) << 32;
5435285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    addr += stride;
5445285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    env->vfp.regs[rd] = make_float64(tmp64);
5455285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                } else {
5465285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tmp64 = float64_val(env->vfp.regs[rd]);
5475285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    STL(addr, tmp64);
5485285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    addr += stride;
5495285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    STL(addr, tmp64 >> 32);
5505285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    addr += stride;
5515285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                }
5525285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                break;
5535285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            case 1:
5545285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                if (load) {
5555285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tmp64 = 0ull;
5565285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    for (i = 0; i < 4; i++, addr += stride) {
5575285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tmp64 |= (uint64_t)LDW(addr) << (i * 16);
5585285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    }
5595285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    env->vfp.regs[rd] = make_float64(tmp64);
5605285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                } else {
5615285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tmp64 = float64_val(env->vfp.regs[rd]);
5625285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    for (i = 0; i < 4; i++, addr += stride, tmp64 >>= 16) {
5635285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        STW(addr, tmp64);
5645285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    }
5655285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                }
5665285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                break;
5675285864985be9077e58e42235af6582dee72e841David 'Digit' Turner            case 0:
5685285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                if (load) {
5695285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tmp64 = 0ull;
5705285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    for (i = 0; i < 8; i++, addr += stride) {
5715285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        tmp64 |= (uint64_t)LDB(addr) << (i * 8);
5725285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    }
5735285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    env->vfp.regs[rd] = make_float64(tmp64);
5745285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                } else {
5755285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    tmp64 = float64_val(env->vfp.regs[rd]);
5765285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    for (i = 0; i < 8; i++, addr += stride, tmp64 >>= 8) {
5775285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                        STB(addr, tmp64);
5785285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                    }
5795285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                }
5805285864985be9077e58e42235af6582dee72e841David 'Digit' Turner                break;
5815285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        }
5825285864985be9077e58e42235af6582dee72e841David 'Digit' Turner        rd += spacing;
5838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
5845285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#undef LDB
5855285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#undef LDW
5865285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#undef LDL
5875285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#undef LDQ
5885285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#undef STB
5895285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#undef STW
5905285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#undef STL
5915285864985be9077e58e42235af6582dee72e841David 'Digit' Turner#undef STQ
5928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
593