X-Git-Url: https://repo.jachan.dev/qemu.git/blobdiff_plain/2e44928e3c1b9425c17d0786f7d9139871bba43f..b048960f15dbedeceb4e1d7e469080cf68d4cf67:/target-arm/op_helper.c diff --git a/target-arm/op_helper.c b/target-arm/op_helper.c index 43baa63006..a918e5b27a 100644 --- a/target-arm/op_helper.c +++ b/target-arm/op_helper.c @@ -16,19 +16,19 @@ * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, see <http://www.gnu.org/licenses/>. */ -#include "exec.h" -#include "helpers.h" +#include "cpu.h" +#include "helper.h" #define SIGNBIT (uint32_t)0x80000000 #define SIGNBIT64 ((uint64_t)1 << 63) -void raise_exception(int tt) +static void raise_exception(CPUARMState *env, int tt) { env->exception_index = tt; - cpu_loop_exit(); + cpu_loop_exit(env); } -uint32_t HELPER(neon_tbl)(uint32_t ireg, uint32_t def, +uint32_t HELPER(neon_tbl)(CPUARMState *env, uint32_t ireg, uint32_t def, uint32_t rn, uint32_t maxindex) { uint32_t val; @@ -52,56 +52,42 @@ uint32_t HELPER(neon_tbl)(uint32_t ireg, uint32_t def, #if !defined(CONFIG_USER_ONLY) +#include "exec/softmmu_exec.h" + #define MMUSUFFIX _mmu #define SHIFT 0 -#include "softmmu_template.h" +#include "exec/softmmu_template.h" #define SHIFT 1 -#include "softmmu_template.h" +#include "exec/softmmu_template.h" #define SHIFT 2 -#include "softmmu_template.h" +#include "exec/softmmu_template.h" #define SHIFT 3 -#include "softmmu_template.h" +#include "exec/softmmu_template.h" /* try to fill the TLB and return an exception if error. If retaddr is NULL, it means that the function was called in C code (i.e. not from generated code or from helper.c) */ -/* XXX: fix it to restore all registers */ -void tlb_fill (target_ulong addr, int is_write, int mmu_idx, void *retaddr) +void tlb_fill(CPUARMState *env, target_ulong addr, int is_write, int mmu_idx, + uintptr_t retaddr) { - TranslationBlock *tb; - CPUState *saved_env; - unsigned long pc; int ret; - /* XXX: hack to restore env in all cases, even if not called from - generated code */ - saved_env = env; - env = cpu_single_env; - ret = cpu_arm_handle_mmu_fault(env, addr, is_write, mmu_idx, 1); + ret = cpu_arm_handle_mmu_fault(env, addr, is_write, mmu_idx); if (unlikely(ret)) { if (retaddr) { /* now we have a real cpu fault */ - pc = (unsigned long)retaddr; - tb = tb_find_pc(pc); - if (tb) { - /* the PC is inside the translated code. It means that we have - a virtual CPU fault */ - cpu_restore_state(tb, env, pc, NULL); - } + cpu_restore_state(env, retaddr); } - raise_exception(env->exception_index); + raise_exception(env, env->exception_index); } - env = saved_env; } #endif -/* FIXME: Pass an axplicit pointer to QF to CPUState, and move saturating - instructions into helper.c */ -uint32_t HELPER(add_setq)(uint32_t a, uint32_t b) +uint32_t HELPER(add_setq)(CPUARMState *env, uint32_t a, uint32_t b) { uint32_t res = a + b; if (((res ^ a) & SIGNBIT) && !((a ^ b) & SIGNBIT)) @@ -109,7 +95,7 @@ uint32_t HELPER(add_setq)(uint32_t a, uint32_t b) return res; } -uint32_t HELPER(add_saturate)(uint32_t a, uint32_t b) +uint32_t HELPER(add_saturate)(CPUARMState *env, uint32_t a, uint32_t b) { uint32_t res = a + b; if (((res ^ a) & SIGNBIT) && !((a ^ b) & SIGNBIT)) { @@ -119,7 +105,7 @@ uint32_t HELPER(add_saturate)(uint32_t a, uint32_t b) return res; } -uint32_t HELPER(sub_saturate)(uint32_t a, uint32_t b) +uint32_t HELPER(sub_saturate)(CPUARMState *env, uint32_t a, uint32_t b) { uint32_t res = a - b; if (((res ^ a) & SIGNBIT) && ((a ^ b) & SIGNBIT)) { @@ -129,7 +115,7 @@ uint32_t HELPER(sub_saturate)(uint32_t a, uint32_t b) return res; } -uint32_t HELPER(double_saturate)(int32_t val) +uint32_t HELPER(double_saturate)(CPUARMState *env, int32_t val) { uint32_t res; if (val >= 0x40000000) { @@ -144,7 +130,7 @@ uint32_t HELPER(double_saturate)(int32_t val) return res; } -uint32_t HELPER(add_usaturate)(uint32_t a, uint32_t b) +uint32_t HELPER(add_usaturate)(CPUARMState *env, uint32_t a, uint32_t b) { uint32_t res = a + b; if (res < a) { @@ -154,7 +140,7 @@ uint32_t HELPER(add_usaturate)(uint32_t a, uint32_t b) return res; } -uint32_t HELPER(sub_usaturate)(uint32_t a, uint32_t b) +uint32_t HELPER(sub_usaturate)(CPUARMState *env, uint32_t a, uint32_t b) { uint32_t res = a - b; if (res > a) { @@ -165,7 +151,7 @@ uint32_t HELPER(sub_usaturate)(uint32_t a, uint32_t b) } /* Signed saturation. */ -static inline uint32_t do_ssat(int32_t val, int shift) +static inline uint32_t do_ssat(CPUARMState *env, int32_t val, int shift) { int32_t top; uint32_t mask; @@ -183,7 +169,7 @@ static inline uint32_t do_ssat(int32_t val, int shift) } /* Unsigned saturation. */ -static inline uint32_t do_usat(int32_t val, int shift) +static inline uint32_t do_usat(CPUARMState *env, int32_t val, int shift) { uint32_t max; @@ -199,62 +185,64 @@ static inline uint32_t do_usat(int32_t val, int shift) } /* Signed saturate. */ -uint32_t HELPER(ssat)(uint32_t x, uint32_t shift) +uint32_t HELPER(ssat)(CPUARMState *env, uint32_t x, uint32_t shift) { - return do_ssat(x, shift); + return do_ssat(env, x, shift); } /* Dual halfword signed saturate. */ -uint32_t HELPER(ssat16)(uint32_t x, uint32_t shift) +uint32_t HELPER(ssat16)(CPUARMState *env, uint32_t x, uint32_t shift) { uint32_t res; - res = (uint16_t)do_ssat((int16_t)x, shift); - res |= do_ssat(((int32_t)x) >> 16, shift) << 16; + res = (uint16_t)do_ssat(env, (int16_t)x, shift); + res |= do_ssat(env, ((int32_t)x) >> 16, shift) << 16; return res; } /* Unsigned saturate. */ -uint32_t HELPER(usat)(uint32_t x, uint32_t shift) +uint32_t HELPER(usat)(CPUARMState *env, uint32_t x, uint32_t shift) { - return do_usat(x, shift); + return do_usat(env, x, shift); } /* Dual halfword unsigned saturate. */ -uint32_t HELPER(usat16)(uint32_t x, uint32_t shift) +uint32_t HELPER(usat16)(CPUARMState *env, uint32_t x, uint32_t shift) { uint32_t res; - res = (uint16_t)do_usat((int16_t)x, shift); - res |= do_usat(((int32_t)x) >> 16, shift) << 16; + res = (uint16_t)do_usat(env, (int16_t)x, shift); + res |= do_usat(env, ((int32_t)x) >> 16, shift) << 16; return res; } -void HELPER(wfi)(void) +void HELPER(wfi)(CPUARMState *env) { + CPUState *cs = CPU(arm_env_get_cpu(env)); + env->exception_index = EXCP_HLT; - env->halted = 1; - cpu_loop_exit(); + cs->halted = 1; + cpu_loop_exit(env); } -void HELPER(exception)(uint32_t excp) +void HELPER(exception)(CPUARMState *env, uint32_t excp) { env->exception_index = excp; - cpu_loop_exit(); + cpu_loop_exit(env); } -uint32_t HELPER(cpsr_read)(void) +uint32_t HELPER(cpsr_read)(CPUARMState *env) { return cpsr_read(env) & ~CPSR_EXEC; } -void HELPER(cpsr_write)(uint32_t val, uint32_t mask) +void HELPER(cpsr_write)(CPUARMState *env, uint32_t val, uint32_t mask) { cpsr_write(env, val, mask); } /* Access to user mode registers from privileged modes. */ -uint32_t HELPER(get_user_reg)(uint32_t regno) +uint32_t HELPER(get_user_reg)(CPUARMState *env, uint32_t regno) { uint32_t val; @@ -271,7 +259,7 @@ uint32_t HELPER(get_user_reg)(uint32_t regno) return val; } -void HELPER(set_user_reg)(uint32_t regno, uint32_t val) +void HELPER(set_user_reg)(CPUARMState *env, uint32_t regno, uint32_t val) { if (regno == 13) { env->banked_r13[0] = val; @@ -285,87 +273,53 @@ void HELPER(set_user_reg)(uint32_t regno, uint32_t val) } } -/* ??? Flag setting arithmetic is awkward because we need to do comparisons. - The only way to do that in TCG is a conditional branch, which clobbers - all our temporaries. For now implement these as helper functions. */ - -uint32_t HELPER (add_cc)(uint32_t a, uint32_t b) +void HELPER(set_cp_reg)(CPUARMState *env, void *rip, uint32_t value) { - uint32_t result; - result = a + b; - env->NF = env->ZF = result; - env->CF = result < a; - env->VF = (a ^ b ^ -1) & (a ^ result); - return result; -} - -uint32_t HELPER(adc_cc)(uint32_t a, uint32_t b) -{ - uint32_t result; - if (!env->CF) { - result = a + b; - env->CF = result < a; - } else { - result = a + b + 1; - env->CF = result <= a; + const ARMCPRegInfo *ri = rip; + int excp = ri->writefn(env, ri, value); + if (excp) { + raise_exception(env, excp); } - env->VF = (a ^ b ^ -1) & (a ^ result); - env->NF = env->ZF = result; - return result; } -uint32_t HELPER(sub_cc)(uint32_t a, uint32_t b) +uint32_t HELPER(get_cp_reg)(CPUARMState *env, void *rip) { - uint32_t result; - result = a - b; - env->NF = env->ZF = result; - env->CF = a >= b; - env->VF = (a ^ b) & (a ^ result); - return result; + const ARMCPRegInfo *ri = rip; + uint64_t value; + int excp = ri->readfn(env, ri, &value); + if (excp) { + raise_exception(env, excp); + } + return value; } -uint32_t HELPER(sbc_cc)(uint32_t a, uint32_t b) +void HELPER(set_cp_reg64)(CPUARMState *env, void *rip, uint64_t value) { - uint32_t result; - if (!env->CF) { - result = a - b - 1; - env->CF = a > b; - } else { - result = a - b; - env->CF = a >= b; + const ARMCPRegInfo *ri = rip; + int excp = ri->writefn(env, ri, value); + if (excp) { + raise_exception(env, excp); } - env->VF = (a ^ b) & (a ^ result); - env->NF = env->ZF = result; - return result; } -/* Similarly for variable shift instructions. */ - -uint32_t HELPER(shl)(uint32_t x, uint32_t i) +uint64_t HELPER(get_cp_reg64)(CPUARMState *env, void *rip) { - int shift = i & 0xff; - if (shift >= 32) - return 0; - return x << shift; + const ARMCPRegInfo *ri = rip; + uint64_t value; + int excp = ri->readfn(env, ri, &value); + if (excp) { + raise_exception(env, excp); + } + return value; } -uint32_t HELPER(shr)(uint32_t x, uint32_t i) -{ - int shift = i & 0xff; - if (shift >= 32) - return 0; - return (uint32_t)x >> shift; -} +/* ??? Flag setting arithmetic is awkward because we need to do comparisons. + The only way to do that in TCG is a conditional branch, which clobbers + all our temporaries. For now implement these as helper functions. */ -uint32_t HELPER(sar)(uint32_t x, uint32_t i) -{ - int shift = i & 0xff; - if (shift >= 32) - shift = 31; - return (int32_t)x >> shift; -} +/* Similarly for variable shift instructions. */ -uint32_t HELPER(shl_cc)(uint32_t x, uint32_t i) +uint32_t HELPER(shl_cc)(CPUARMState *env, uint32_t x, uint32_t i) { int shift = i & 0xff; if (shift >= 32) { @@ -381,7 +335,7 @@ uint32_t HELPER(shl_cc)(uint32_t x, uint32_t i) return x; } -uint32_t HELPER(shr_cc)(uint32_t x, uint32_t i) +uint32_t HELPER(shr_cc)(CPUARMState *env, uint32_t x, uint32_t i) { int shift = i & 0xff; if (shift >= 32) { @@ -397,7 +351,7 @@ uint32_t HELPER(shr_cc)(uint32_t x, uint32_t i) return x; } -uint32_t HELPER(sar_cc)(uint32_t x, uint32_t i) +uint32_t HELPER(sar_cc)(CPUARMState *env, uint32_t x, uint32_t i) { int shift = i & 0xff; if (shift >= 32) { @@ -410,7 +364,7 @@ uint32_t HELPER(sar_cc)(uint32_t x, uint32_t i) return x; } -uint32_t HELPER(ror_cc)(uint32_t x, uint32_t i) +uint32_t HELPER(ror_cc)(CPUARMState *env, uint32_t x, uint32_t i) { int shift1, shift; shift1 = i & 0xff; @@ -424,52 +378,3 @@ uint32_t HELPER(ror_cc)(uint32_t x, uint32_t i) return ((uint32_t)x >> shift) | (x << (32 - shift)); } } - -uint64_t HELPER(neon_add_saturate_s64)(uint64_t src1, uint64_t src2) -{ - uint64_t res; - - res = src1 + src2; - if (((res ^ src1) & SIGNBIT64) && !((src1 ^ src2) & SIGNBIT64)) { - env->QF = 1; - res = ((int64_t)src1 >> 63) ^ ~SIGNBIT64; - } - return res; -} - -uint64_t HELPER(neon_add_saturate_u64)(uint64_t src1, uint64_t src2) -{ - uint64_t res; - - res = src1 + src2; - if (res < src1) { - env->QF = 1; - res = ~(uint64_t)0; - } - return res; -} - -uint64_t HELPER(neon_sub_saturate_s64)(uint64_t src1, uint64_t src2) -{ - uint64_t res; - - res = src1 - src2; - if (((res ^ src1) & SIGNBIT64) && ((src1 ^ src2) & SIGNBIT64)) { - env->QF = 1; - res = ((int64_t)src1 >> 63) ^ ~SIGNBIT64; - } - return res; -} - -uint64_t HELPER(neon_sub_saturate_u64)(uint64_t src1, uint64_t src2) -{ - uint64_t res; - - if (src1 < src2) { - env->QF = 1; - res = 0; - } else { - res = src1 - src2; - } - return res; -}