From 99c475abf16b10923baac09682a9d801ae421ac6 Mon Sep 17 00:00:00 2001 From: bellard Date: Mon, 31 Jan 2005 20:45:13 +0000 Subject: armv5te support (Paul Brook) git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1258 c046a42c-6fe2-441c-8c8c-71466251a162 --- target-arm/op.c | 144 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 144 insertions(+) (limited to 'target-arm/op.c') diff --git a/target-arm/op.c b/target-arm/op.c index 6596de76f..dc1c7341e 100644 --- a/target-arm/op.c +++ b/target-arm/op.c @@ -81,8 +81,15 @@ #define REGNAME r15 #define REG (env->regs[15]) +#define SET_REG(x) REG = x & ~(uint32_t)1 #include "op_template.h" +void OPPROTO op_bx_T0(void) +{ + env->regs[15] = T0 & ~(uint32_t)1; + env->thumb = (T0 & 1) != 0; +} + void OPPROTO op_movl_T0_0(void) { T0 = 0; @@ -382,6 +389,14 @@ void OPPROTO op_imull_T0_T1(void) T0 = res; } +/* 48 bit signed mul, top 32 bits */ +void OPPROTO op_imulw_T0_T1(void) +{ + uint64_t res; + res = (int64_t)((int32_t)T0) * (int64_t)((int32_t)T1); + T0 = res >> 16; +} + void OPPROTO op_addq_T0_T1(void) { uint64_t res; @@ -391,6 +406,15 @@ void OPPROTO op_addq_T0_T1(void) T0 = res; } +void OPPROTO op_addq_lo_T0_T1(void) +{ + uint64_t res; + res = ((uint64_t)T1 << 32) | T0; + res += (uint64_t)(env->regs[PARAM1]); + T1 = res >> 32; + T0 = res; +} + void OPPROTO op_logicq_cc(void) { env->NZF = (T1 & 0x80000000) | ((T0 | T1) != 0); @@ -694,6 +718,126 @@ void OPPROTO op_rorl_T1_T0_cc(void) FORCE_RET(); } +/* misc */ +void OPPROTO op_clz_T0(void) +{ + int count; + for (count = 32; T0 > 0; count--) + T0 = T0 >> 1; + T0 = count; + FORCE_RET(); +} + +void OPPROTO op_sarl_T0_im(void) +{ + T0 = (int32_t)T0 >> PARAM1; +} + +/* 16->32 Sign extend */ +void OPPROTO op_sxl_T0(void) +{ + T0 = (int16_t)T0; +} + +void OPPROTO op_sxl_T1(void) +{ + T1 = (int16_t)T1; +} + +#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 = 0x8000000; + else + T0 = 0x7fffffff; + } + else + T0 = res; + + FORCE_RET(); +} + +/* thumb shift by immediate */ +void OPPROTO op_shll_T0_im_thumb(void) +{ + int shift; + shift = PARAM1; + if (shift != 0) { + env->CF = (T1 >> (32 - shift)) & 1; + T0 = T0 << shift; + } + env->NZF = T0; + FORCE_RET(); +} + +void OPPROTO op_shrl_T0_im_thumb(void) +{ + int shift; + + shift = PARAM1; + if (shift == 0) { + env->CF = 0; + T0 = 0; + } else { + env->CF = (T0 >> (shift - 1)) & 1; + T0 = T0 >> shift; + } + FORCE_RET(); +} + +void OPPROTO op_sarl_T0_im_thumb(void) +{ + int shift; + + shift = PARAM1; + if (shift == 0) { + T0 = ((int32_t)T0) >> 31; + env->CF = T0 & 1; + } else { + env->CF = (T0 >> (shift - 1)) & 1; + T0 = ((int32_t)T0) >> shift; + } + env->NZF = T0; + FORCE_RET(); +} + /* exceptions */ void OPPROTO op_swi(void) -- cgit v1.2.3