mirror of
https://github.com/xemu-project/xemu.git
synced 2025-02-17 10:38:52 +00:00
ARM TCG conversion 4/16.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4141 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
parent
9a119ff6c1
commit
1497c961af
@ -322,7 +322,6 @@ void cpsr_write(CPUARMState *env, uint32_t val, uint32_t mask)
|
||||
env->uncached_cpsr = (env->uncached_cpsr & ~mask) | (val & mask);
|
||||
}
|
||||
|
||||
#define HELPER(x) helper_##x
|
||||
/* Sign/zero extend */
|
||||
uint32_t HELPER(sxtb16)(uint32_t x)
|
||||
{
|
||||
@ -1894,4 +1893,3 @@ void cpu_arm_set_cp_io(CPUARMState *env, int cpnum,
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -1,7 +1,36 @@
|
||||
#ifndef DEF_HELPER
|
||||
#define DEF_HELPER(name, ret, args) ret helper_##name args;
|
||||
|
||||
#ifdef GEN_HELPER
|
||||
#define DEF_HELPER_1_1(name, ret, args) \
|
||||
DEF_HELPER(name, ret, args) \
|
||||
static inline void gen_helper_##name(TCGv ret, TCGv arg1) \
|
||||
{ \
|
||||
tcg_gen_helper_1_1(helper_##name, ret, arg1); \
|
||||
}
|
||||
#define DEF_HELPER_1_2(name, ret, args) \
|
||||
DEF_HELPER(name, ret, args) \
|
||||
static inline void gen_helper_##name(TCGv ret, TCGv arg1, TCGv arg2) \
|
||||
{ \
|
||||
tcg_gen_helper_1_2(helper_##name, ret, arg1, arg2); \
|
||||
}
|
||||
#else /* !GEN_HELPER */
|
||||
#define DEF_HELPER_1_1 DEF_HELPER
|
||||
#define DEF_HELPER_1_2 DEF_HELPER
|
||||
#define HELPER(x) helper_##x
|
||||
#endif
|
||||
|
||||
DEF_HELPER(clz, uint32_t, (uint32_t))
|
||||
DEF_HELPER(sxtb16, uint32_t, (uint32_t))
|
||||
DEF_HELPER(uxtb16, uint32_t, (uint32_t))
|
||||
DEF_HELPER_1_1(clz, uint32_t, (uint32_t))
|
||||
DEF_HELPER_1_1(sxtb16, uint32_t, (uint32_t))
|
||||
DEF_HELPER_1_1(uxtb16, uint32_t, (uint32_t))
|
||||
|
||||
DEF_HELPER_1_2(add_setq, uint32_t, (uint32_t, uint32_t))
|
||||
DEF_HELPER_1_2(add_saturate, uint32_t, (uint32_t, uint32_t))
|
||||
DEF_HELPER_1_2(sub_saturate, uint32_t, (uint32_t, uint32_t))
|
||||
DEF_HELPER_1_2(add_usaturate, uint32_t, (uint32_t, uint32_t))
|
||||
DEF_HELPER_1_2(sub_usaturate, uint32_t, (uint32_t, uint32_t))
|
||||
DEF_HELPER_1_1(double_saturate, uint32_t, (int32_t))
|
||||
|
||||
#undef DEF_HELPER
|
||||
#undef DEF_HELPER_1_1
|
||||
#undef DEF_HELPER_1_2
|
||||
#undef GEN_HELPER
|
||||
|
@ -425,105 +425,6 @@ void OPPROTO op_rorl_T1_T0_cc(void)
|
||||
FORCE_RET();
|
||||
}
|
||||
|
||||
/* misc */
|
||||
#define SIGNBIT (uint32_t)0x80000000
|
||||
/* saturating arithmetic */
|
||||
void OPPROTO op_addl_T0_T1_setq(void)
|
||||
{
|
||||
uint32_t res;
|
||||
|
||||
res = T0 + T1;
|
||||
if (((res ^ T0) & SIGNBIT) && !((T0 ^ T1) & SIGNBIT))
|
||||
env->QF = 1;
|
||||
|
||||
T0 = res;
|
||||
FORCE_RET();
|
||||
}
|
||||
|
||||
void OPPROTO op_addl_T0_T1_saturate(void)
|
||||
{
|
||||
uint32_t res;
|
||||
|
||||
res = T0 + T1;
|
||||
if (((res ^ T0) & SIGNBIT) && !((T0 ^ T1) & SIGNBIT)) {
|
||||
env->QF = 1;
|
||||
if (T0 & SIGNBIT)
|
||||
T0 = 0x80000000;
|
||||
else
|
||||
T0 = 0x7fffffff;
|
||||
}
|
||||
else
|
||||
T0 = res;
|
||||
|
||||
FORCE_RET();
|
||||
}
|
||||
|
||||
void OPPROTO op_subl_T0_T1_saturate(void)
|
||||
{
|
||||
uint32_t res;
|
||||
|
||||
res = T0 - T1;
|
||||
if (((res ^ T0) & SIGNBIT) && ((T0 ^ T1) & SIGNBIT)) {
|
||||
env->QF = 1;
|
||||
if (T0 & SIGNBIT)
|
||||
T0 = 0x80000000;
|
||||
else
|
||||
T0 = 0x7fffffff;
|
||||
}
|
||||
else
|
||||
T0 = res;
|
||||
|
||||
FORCE_RET();
|
||||
}
|
||||
|
||||
void OPPROTO op_double_T1_saturate(void)
|
||||
{
|
||||
int32_t val;
|
||||
|
||||
val = T1;
|
||||
if (val >= 0x40000000) {
|
||||
T1 = 0x7fffffff;
|
||||
env->QF = 1;
|
||||
} else if (val <= (int32_t)0xc0000000) {
|
||||
T1 = 0x80000000;
|
||||
env->QF = 1;
|
||||
} else {
|
||||
T1 = val << 1;
|
||||
}
|
||||
FORCE_RET();
|
||||
}
|
||||
|
||||
/* Unsigned saturating arithmetic for NEON. */
|
||||
void OPPROTO op_addl_T0_T1_usaturate(void)
|
||||
{
|
||||
uint32_t res;
|
||||
|
||||
res = T0 + T1;
|
||||
if (res < T0) {
|
||||
env->QF = 1;
|
||||
T0 = 0xffffffff;
|
||||
} else {
|
||||
T0 = res;
|
||||
}
|
||||
|
||||
FORCE_RET();
|
||||
}
|
||||
|
||||
void OPPROTO op_subl_T0_T1_usaturate(void)
|
||||
{
|
||||
uint32_t res;
|
||||
|
||||
res = T0 - T1;
|
||||
if (res > T0) {
|
||||
env->QF = 1;
|
||||
T0 = 0;
|
||||
} else {
|
||||
T0 = res;
|
||||
}
|
||||
|
||||
FORCE_RET();
|
||||
}
|
||||
|
||||
/* exceptions */
|
||||
|
||||
void OPPROTO op_swi(void)
|
||||
|
@ -18,6 +18,7 @@
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
#include "exec.h"
|
||||
#include "helpers.h"
|
||||
|
||||
void raise_exception(int tt)
|
||||
{
|
||||
@ -303,3 +304,68 @@ void tlb_fill (target_ulong addr, int is_write, int mmu_idx, void *retaddr)
|
||||
env = saved_env;
|
||||
}
|
||||
#endif
|
||||
|
||||
#define SIGNBIT (uint32_t)0x80000000
|
||||
uint32_t HELPER(add_setq)(uint32_t a, uint32_t b)
|
||||
{
|
||||
uint32_t res = a + b;
|
||||
if (((res ^ a) & SIGNBIT) && !((a ^ b) & SIGNBIT))
|
||||
env->QF = 1;
|
||||
return res;
|
||||
}
|
||||
|
||||
uint32_t HELPER(add_saturate)(uint32_t a, uint32_t b)
|
||||
{
|
||||
uint32_t res = a + b;
|
||||
if (((res ^ a) & SIGNBIT) && !((a ^ b) & SIGNBIT)) {
|
||||
env->QF = 1;
|
||||
res = ~(((int32_t)a >> 31) ^ SIGNBIT);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
uint32_t HELPER(sub_saturate)(uint32_t a, uint32_t b)
|
||||
{
|
||||
uint32_t res = a - b;
|
||||
if (((res ^ a) & SIGNBIT) && ((a ^ b) & SIGNBIT)) {
|
||||
env->QF = 1;
|
||||
res = ~(((int32_t)a >> 31) ^ SIGNBIT);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
uint32_t HELPER(double_saturate)(int32_t val)
|
||||
{
|
||||
uint32_t res;
|
||||
if (val >= 0x40000000) {
|
||||
res = ~SIGNBIT;
|
||||
env->QF = 1;
|
||||
} else if (val <= (int32_t)0xc0000000) {
|
||||
res = SIGNBIT;
|
||||
env->QF = 1;
|
||||
} else {
|
||||
res = val << 1;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
uint32_t HELPER(add_usaturate)(uint32_t a, uint32_t b)
|
||||
{
|
||||
uint32_t res = a + b;
|
||||
if (res < a) {
|
||||
env->QF = 1;
|
||||
res = ~0;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
uint32_t HELPER(sub_usaturate)(uint32_t a, uint32_t b)
|
||||
{
|
||||
uint32_t res = a - b;
|
||||
if (res > a) {
|
||||
env->QF = 1;
|
||||
res = 0;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
|
@ -9,6 +9,7 @@
|
||||
/* Note that for NEON an "l" prefix means it is a wide operation, unlike
|
||||
scalar arm ops where it means a word size operation. */
|
||||
|
||||
#define SIGNBIT (uint32_t)0x80000000
|
||||
/* ??? NEON ops should probably have their own float status. */
|
||||
#define NFS &env->vfp.fp_status
|
||||
#define NEON_OP(name) void OPPROTO op_neon_##name (void)
|
||||
|
@ -29,6 +29,8 @@
|
||||
#include "exec-all.h"
|
||||
#include "disas.h"
|
||||
#include "tcg-op.h"
|
||||
|
||||
#define GEN_HELPER 1
|
||||
#include "helpers.h"
|
||||
|
||||
#define ENABLE_ARCH_5J 0
|
||||
@ -200,13 +202,19 @@ static void store_reg(DisasContext *s, int reg, TCGv var)
|
||||
#define gen_sxtb(var) tcg_gen_ext8s_i32(var, var)
|
||||
#define gen_sxth(var) tcg_gen_ext16s_i32(var, var)
|
||||
|
||||
#define HELPER_ADDR(x) helper_##x
|
||||
#define gen_sxtb16(var) gen_helper_sxtb16(var, var)
|
||||
#define gen_uxtb16(var) gen_helper_uxtb16(var, var)
|
||||
|
||||
#define gen_sxtb16(var) tcg_gen_helper_1_1(HELPER_ADDR(sxtb16), var, var)
|
||||
#define gen_uxtb16(var) tcg_gen_helper_1_1(HELPER_ADDR(uxtb16), var, var)
|
||||
|
||||
#define gen_op_clz_T0(var) \
|
||||
tcg_gen_helper_1_1(HELPER_ADDR(clz), cpu_T[0], cpu_T[0])
|
||||
#define gen_op_addl_T0_T1_setq() \
|
||||
gen_helper_add_setq(cpu_T[0], cpu_T[0], cpu_T[1])
|
||||
#define gen_op_addl_T0_T1_saturate() \
|
||||
gen_helper_add_saturate(cpu_T[0], cpu_T[0], cpu_T[1])
|
||||
#define gen_op_subl_T0_T1_saturate() \
|
||||
gen_helper_sub_saturate(cpu_T[0], cpu_T[0], cpu_T[1])
|
||||
#define gen_op_addl_T0_T1_usaturate() \
|
||||
gen_helper_add_usaturate(cpu_T[0], cpu_T[0], cpu_T[1])
|
||||
#define gen_op_subl_T0_T1_usaturate() \
|
||||
gen_helper_sub_usaturate(cpu_T[0], cpu_T[0], cpu_T[1])
|
||||
|
||||
/* Dual 16-bit add. Result placed in t0 and t1 is marked as dead.
|
||||
tmp = (t0 ^ t1) & 0x8000;
|
||||
@ -4526,7 +4534,7 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
|
||||
switch (size) {
|
||||
case 0: gen_op_neon_clz_u8(); break;
|
||||
case 1: gen_op_neon_clz_u16(); break;
|
||||
case 2: gen_op_clz_T0(); break;
|
||||
case 2: gen_helper_clz(cpu_T[0], cpu_T[0]); break;
|
||||
default: return 1;
|
||||
}
|
||||
break;
|
||||
@ -5021,9 +5029,9 @@ static void disas_arm_insn(CPUState * env, DisasContext *s)
|
||||
} else if (op1 == 3) {
|
||||
/* clz */
|
||||
rd = (insn >> 12) & 0xf;
|
||||
gen_movl_T0_reg(s, rm);
|
||||
gen_op_clz_T0();
|
||||
gen_movl_reg_T0(s, rd);
|
||||
tmp = load_reg(s, rm);
|
||||
gen_helper_clz(tmp, tmp);
|
||||
store_reg(s, rd, tmp);
|
||||
} else {
|
||||
goto illegal_op;
|
||||
}
|
||||
@ -5055,7 +5063,7 @@ static void disas_arm_insn(CPUState * env, DisasContext *s)
|
||||
gen_movl_T0_reg(s, rm);
|
||||
gen_movl_T1_reg(s, rn);
|
||||
if (op1 & 2)
|
||||
gen_op_double_T1_saturate();
|
||||
gen_helper_double_saturate(cpu_T[1], cpu_T[1]);
|
||||
if (op1 & 1)
|
||||
gen_op_subl_T0_T1_saturate();
|
||||
else
|
||||
@ -6317,7 +6325,7 @@ static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1)
|
||||
gen_movl_T0_reg(s, rm);
|
||||
gen_movl_T1_reg(s, rn);
|
||||
if (op & 2)
|
||||
gen_op_double_T1_saturate();
|
||||
gen_helper_double_saturate(cpu_T[1], cpu_T[1]);
|
||||
if (op & 1)
|
||||
gen_op_subl_T0_T1_saturate();
|
||||
else
|
||||
@ -6342,7 +6350,7 @@ static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1)
|
||||
gen_op_sel_T0_T1();
|
||||
break;
|
||||
case 0x18: /* clz */
|
||||
gen_op_clz_T0();
|
||||
gen_helper_clz(cpu_T[0], cpu_T[0]);
|
||||
break;
|
||||
default:
|
||||
goto illegal_op;
|
||||
|
Loading…
x
Reference in New Issue
Block a user