aboutsummaryrefslogtreecommitdiff
path: root/target-tricore/op_helper.c
diff options
context:
space:
mode:
authorBastian Koppelmann <kbastian@mail.uni-paderborn.de>2015-02-25 11:46:55 +0000
committerBastian Koppelmann <kbastian@mail.uni-paderborn.de>2015-03-16 15:44:48 +0000
commit62e47b2e6d17020b78a676e086bf98cfeba595b7 (patch)
treee4a20e86f21a8bf3c71dfc884e4b85109ad1cec4 /target-tricore/op_helper.c
parentf4aef476afc4cab9bb594975401f6902a57aa9b9 (diff)
target-tricore: Add instructions of RRR1 opcode format, which have 0x63 as first opcode
Add helpers: * msub64_q_ssov: multiply two 32 bit q-format number, sub the result from a 64 bit q-format number and saturate. * msub32_q_sub_ssov: sub two 64 bit q-format numbers and return a 32 bit result. * msubr_q_ssov: multiply two 32 bit q-format numbers, sub the result from a 32 bit q-format number and saturate. * msubr_q: multiply two 32 bit q-format numbers and sub the result from a 32 bit q-format number. Reviewed-by: Richard Henderson <rth@twiddle.net> Signed-off-by: Bastian Koppelmann <kbastian@mail.uni-paderborn.de>
Diffstat (limited to 'target-tricore/op_helper.c')
-rw-r--r--target-tricore/op_helper.c154
1 files changed, 154 insertions, 0 deletions
diff --git a/target-tricore/op_helper.c b/target-tricore/op_helper.c
index d6b01c3c71..cc89ae3532 100644
--- a/target-tricore/op_helper.c
+++ b/target-tricore/op_helper.c
@@ -838,6 +838,132 @@ uint64_t helper_msub64_suov(CPUTriCoreState *env, target_ulong r1,
return ret;
}
+uint32_t
+helper_msub32_q_sub_ssov(CPUTriCoreState *env, uint64_t r1, uint64_t r2)
+{
+ int64_t result;
+ int64_t t1 = (int64_t)r1;
+ int64_t t2 = (int64_t)r2;
+
+ result = t1 - t2;
+
+ env->PSW_USB_AV = (result ^ result * 2u);
+ env->PSW_USB_SAV |= env->PSW_USB_AV;
+
+ /* we do the saturation by hand, since we produce an overflow on the host
+ if the mul before was (0x80000000 * 0x80000000) << 1). If this is the
+ case, we flip the saturated value. */
+ if (r2 == 0x8000000000000000LL) {
+ if (result > 0x7fffffffLL) {
+ env->PSW_USB_V = (1 << 31);
+ env->PSW_USB_SV = (1 << 31);
+ result = INT32_MIN;
+ } else if (result < -0x80000000LL) {
+ env->PSW_USB_V = (1 << 31);
+ env->PSW_USB_SV = (1 << 31);
+ result = INT32_MAX;
+ } else {
+ env->PSW_USB_V = 0;
+ }
+ } else {
+ if (result > 0x7fffffffLL) {
+ env->PSW_USB_V = (1 << 31);
+ env->PSW_USB_SV = (1 << 31);
+ result = INT32_MAX;
+ } else if (result < -0x80000000LL) {
+ env->PSW_USB_V = (1 << 31);
+ env->PSW_USB_SV = (1 << 31);
+ result = INT32_MIN;
+ } else {
+ env->PSW_USB_V = 0;
+ }
+ }
+ return (uint32_t)result;
+}
+
+uint64_t helper_msub64_q_ssov(CPUTriCoreState *env, uint64_t r1, uint32_t r2,
+ uint32_t r3, uint32_t n)
+{
+ int64_t t1 = (int64_t)r1;
+ int64_t t2 = sextract64(r2, 0, 32);
+ int64_t t3 = sextract64(r3, 0, 32);
+ int64_t result, mul;
+ int64_t ovf;
+
+ mul = (t2 * t3) << n;
+ result = t1 - mul;
+
+ env->PSW_USB_AV = (result ^ result * 2u) >> 32;
+ env->PSW_USB_SAV |= env->PSW_USB_AV;
+
+ ovf = (result ^ t1) & (t1 ^ mul);
+ /* we do the saturation by hand, since we produce an overflow on the host
+ if the mul before was (0x80000000 * 0x80000000) << 1). If this is the
+ case, we flip the saturated value. */
+ if (mul == 0x8000000000000000LL) {
+ if (ovf >= 0) {
+ env->PSW_USB_V = (1 << 31);
+ env->PSW_USB_SV = (1 << 31);
+ /* ext_ret > MAX_INT */
+ if (mul >= 0) {
+ result = INT64_MAX;
+ /* ext_ret < MIN_INT */
+ } else {
+ result = INT64_MIN;
+ }
+ }
+ } else {
+ if (ovf < 0) {
+ env->PSW_USB_V = (1 << 31);
+ env->PSW_USB_SV = (1 << 31);
+ /* ext_ret > MAX_INT */
+ if (mul < 0) {
+ result = INT64_MAX;
+ /* ext_ret < MIN_INT */
+ } else {
+ result = INT64_MIN;
+ }
+ } else {
+ env->PSW_USB_V = 0;
+ }
+ }
+
+ return (uint64_t)result;
+}
+
+uint32_t helper_msubr_q_ssov(CPUTriCoreState *env, uint32_t r1, uint32_t r2,
+ uint32_t r3, uint32_t n)
+{
+ int64_t t1 = sextract64(r1, 0, 32);
+ int64_t t2 = sextract64(r2, 0, 32);
+ int64_t t3 = sextract64(r3, 0, 32);
+ int64_t mul, ret;
+
+ if ((t2 == -0x8000ll) && (t3 == -0x8000ll) && (n == 1)) {
+ mul = 0x7fffffff;
+ } else {
+ mul = (t2 * t3) << n;
+ }
+
+ ret = t1 - mul + 0x8000;
+
+ env->PSW_USB_AV = ret ^ ret * 2u;
+ env->PSW_USB_SAV |= env->PSW_USB_AV;
+
+ if (ret > 0x7fffffffll) {
+ env->PSW_USB_V = (1 << 31);
+ env->PSW_USB_SV |= env->PSW_USB_V;
+ ret = INT32_MAX;
+ } else if (ret < -0x80000000ll) {
+ env->PSW_USB_V = (1 << 31);
+ env->PSW_USB_SV |= env->PSW_USB_V;
+ ret = INT32_MIN;
+ } else {
+ env->PSW_USB_V = 0;
+ }
+ return ret & 0xffff0000ll;
+}
+
uint32_t helper_abs_b(CPUTriCoreState *env, target_ulong arg)
{
int32_t b, i;
@@ -1126,6 +1252,34 @@ uint32_t helper_subr_h(CPUTriCoreState *env, uint64_t r1, uint32_t r2_l,
return (result1 & 0xffff0000ULL) | ((result0 >> 16) & 0xffffULL);
}
+uint32_t helper_msubr_q(CPUTriCoreState *env, uint32_t r1, uint32_t r2,
+ uint32_t r3, uint32_t n)
+{
+ int64_t t1 = sextract64(r1, 0, 32);
+ int64_t t2 = sextract64(r2, 0, 32);
+ int64_t t3 = sextract64(r3, 0, 32);
+ int64_t mul, ret;
+
+ if ((t2 == -0x8000ll) && (t3 == -0x8000ll) && (n == 1)) {
+ mul = 0x7fffffff;
+ } else {
+ mul = (t2 * t3) << n;
+ }
+
+ ret = t1 - mul + 0x8000;
+
+ if ((ret > 0x7fffffffll) || (ret < -0x80000000ll)) {
+ env->PSW_USB_V = (1 << 31);
+ env->PSW_USB_SV |= env->PSW_USB_V;
+ } else {
+ env->PSW_USB_V = 0;
+ }
+ env->PSW_USB_AV = ret ^ ret * 2u;
+ env->PSW_USB_SAV |= env->PSW_USB_AV;
+
+ return ret & 0xffff0000ll;
+}
+
uint32_t helper_sub_b(CPUTriCoreState *env, target_ulong r1, target_ulong r2)
{
int32_t b, i;