summary refs log tree commit diff stats
path: root/target-tricore/op_helper.c
diff options
context:
space:
mode:
Diffstat (limited to 'target-tricore/op_helper.c')
-rw-r--r--target-tricore/op_helper.c278
1 files changed, 278 insertions, 0 deletions
diff --git a/target-tricore/op_helper.c b/target-tricore/op_helper.c
index a36988aa1b..4da76ff232 100644
--- a/target-tricore/op_helper.c
+++ b/target-tricore/op_helper.c
@@ -77,6 +77,27 @@ uint32_t helper_circ_update(uint32_t reg, uint32_t off)
     env->PSW_USB_SAV |= env->PSW_USB_AV;            \
 } while (0)
 
+#define SUOV(env, ret, arg, len) do {               \
+    int64_t max_pos = UINT##len ##_MAX;             \
+    if (arg > max_pos) {                            \
+        env->PSW_USB_V = (1 << 31);                 \
+        env->PSW_USB_SV = (1 << 31);                \
+        ret = (target_ulong)max_pos;                \
+    } else {                                        \
+        if (arg < 0) {                              \
+            env->PSW_USB_V = (1 << 31);             \
+            env->PSW_USB_SV = (1 << 31);            \
+            ret = 0;                                \
+        } else {                                    \
+            env->PSW_USB_V = 0;                     \
+            ret = (target_ulong)arg;                \
+        }                                           \
+     }                                              \
+    env->PSW_USB_AV = arg ^ arg * 2u;               \
+    env->PSW_USB_SAV |= env->PSW_USB_AV;            \
+} while (0)
+
+
 target_ulong helper_add_ssov(CPUTriCoreState *env, target_ulong r1,
                              target_ulong r2)
 {
@@ -88,6 +109,17 @@ target_ulong helper_add_ssov(CPUTriCoreState *env, target_ulong r1,
     return ret;
 }
 
+target_ulong helper_add_suov(CPUTriCoreState *env, target_ulong r1,
+                             target_ulong r2)
+{
+    target_ulong ret;
+    int64_t t1 = extract64(r1, 0, 32);
+    int64_t t2 = extract64(r2, 0, 32);
+    int64_t result = t1 + t2;
+    SUOV(env, ret, result, 32);
+    return ret;
+}
+
 target_ulong helper_sub_ssov(CPUTriCoreState *env, target_ulong r1,
                              target_ulong r2)
 {
@@ -99,6 +131,241 @@ target_ulong helper_sub_ssov(CPUTriCoreState *env, target_ulong r1,
     return ret;
 }
 
+target_ulong helper_sub_suov(CPUTriCoreState *env, target_ulong r1,
+                             target_ulong r2)
+{
+    target_ulong ret;
+    int64_t t1 = extract64(r1, 0, 32);
+    int64_t t2 = extract64(r2, 0, 32);
+    int64_t result = t1 - t2;
+    SUOV(env, ret, result, 32);
+    return ret;
+}
+
+target_ulong helper_mul_ssov(CPUTriCoreState *env, target_ulong r1,
+                             target_ulong r2)
+{
+    target_ulong ret;
+    int64_t t1 = sextract64(r1, 0, 32);
+    int64_t t2 = sextract64(r2, 0, 32);
+    int64_t result = t1 * t2;
+    SSOV(env, ret, result, 32);
+    return ret;
+}
+
+target_ulong helper_mul_suov(CPUTriCoreState *env, target_ulong r1,
+                             target_ulong r2)
+{
+    target_ulong ret;
+    int64_t t1 = extract64(r1, 0, 32);
+    int64_t t2 = extract64(r2, 0, 32);
+    int64_t result = t1 * t2;
+    SUOV(env, ret, result, 32);
+    return ret;
+}
+
+target_ulong helper_sha_ssov(CPUTriCoreState *env, target_ulong r1,
+                             target_ulong r2)
+{
+    target_ulong ret;
+    int64_t t1 = sextract64(r1, 0, 32);
+    int32_t t2 = sextract64(r2, 0, 6);
+    int64_t result;
+    if (t2 == 0) {
+        result = t1;
+    } else if (t2 > 0) {
+        result = t1 << t2;
+    } else {
+        result = t1 >> -t2;
+    }
+    SSOV(env, ret, result, 32);
+    return ret;
+}
+
+target_ulong helper_absdif_ssov(CPUTriCoreState *env, target_ulong r1,
+                                target_ulong r2)
+{
+    target_ulong ret;
+    int64_t t1 = sextract64(r1, 0, 32);
+    int64_t t2 = sextract64(r2, 0, 32);
+    int64_t result;
+
+    if (t1 > t2) {
+        result = t1 - t2;
+    } else {
+        result = t2 - t1;
+    }
+    SSOV(env, ret, result, 32);
+    return ret;
+}
+
+target_ulong helper_madd32_ssov(CPUTriCoreState *env, target_ulong r1,
+                                target_ulong r2, target_ulong r3)
+{
+    target_ulong ret;
+    int64_t t1 = sextract64(r1, 0, 32);
+    int64_t t2 = sextract64(r2, 0, 32);
+    int64_t t3 = sextract64(r3, 0, 32);
+    int64_t result;
+
+    result = t2 + (t1 * t3);
+    SSOV(env, ret, result, 32);
+    return ret;
+}
+
+target_ulong helper_madd32_suov(CPUTriCoreState *env, target_ulong r1,
+                                target_ulong r2, target_ulong r3)
+{
+    target_ulong ret;
+    uint64_t t1 = extract64(r1, 0, 32);
+    uint64_t t2 = extract64(r2, 0, 32);
+    uint64_t t3 = extract64(r3, 0, 32);
+    int64_t result;
+
+    result = t2 + (t1 * t3);
+    SUOV(env, ret, result, 32);
+    return ret;
+}
+
+uint64_t helper_madd64_ssov(CPUTriCoreState *env, target_ulong r1,
+                            uint64_t r2, target_ulong r3)
+{
+    uint64_t ret, ovf;
+    int64_t t1 = sextract64(r1, 0, 32);
+    int64_t t3 = sextract64(r3, 0, 32);
+    int64_t mul;
+
+    mul = t1 * t3;
+    ret = mul + r2;
+    ovf = (ret ^ mul) & ~(mul ^ r2);
+
+    if ((int64_t)ovf < 0) {
+        env->PSW_USB_V = (1 << 31);
+        env->PSW_USB_SV = (1 << 31);
+        /* ext_ret > MAX_INT */
+        if (mul >= 0) {
+            ret = INT64_MAX;
+        /* ext_ret < MIN_INT */
+        } else {
+            ret = INT64_MIN;
+        }
+    } else {
+        env->PSW_USB_V = 0;
+    }
+    t1 = ret >> 32;
+    env->PSW_USB_AV = t1 ^ t1 * 2u;
+    env->PSW_USB_SAV |= env->PSW_USB_AV;
+
+    return ret;
+}
+
+uint64_t helper_madd64_suov(CPUTriCoreState *env, target_ulong r1,
+                            uint64_t r2, target_ulong r3)
+{
+    uint64_t ret, mul;
+    uint64_t t1 = extract64(r1, 0, 32);
+    uint64_t t3 = extract64(r3, 0, 32);
+
+    mul = t1 * t3;
+    ret = mul + r2;
+
+    if (ret < r2) {
+        env->PSW_USB_V = (1 << 31);
+        env->PSW_USB_SV = (1 << 31);
+        /* saturate */
+        ret = UINT64_MAX;
+    } else {
+        env->PSW_USB_V = 0;
+    }
+    t1 = ret >> 32;
+    env->PSW_USB_AV = t1 ^ t1 * 2u;
+    env->PSW_USB_SAV |= env->PSW_USB_AV;
+    return ret;
+}
+
+target_ulong helper_msub32_ssov(CPUTriCoreState *env, target_ulong r1,
+                                target_ulong r2, target_ulong r3)
+{
+    target_ulong ret;
+    int64_t t1 = sextract64(r1, 0, 32);
+    int64_t t2 = sextract64(r2, 0, 32);
+    int64_t t3 = sextract64(r3, 0, 32);
+    int64_t result;
+
+    result = t2 - (t1 * t3);
+    SSOV(env, ret, result, 32);
+    return ret;
+}
+
+target_ulong helper_msub32_suov(CPUTriCoreState *env, target_ulong r1,
+                                target_ulong r2, target_ulong r3)
+{
+    target_ulong ret;
+    int64_t t1 = extract64(r1, 0, 32);
+    int64_t t2 = extract64(r2, 0, 32);
+    int64_t t3 = extract64(r3, 0, 32);
+    int64_t result;
+
+    result = t2 - (t1 * t3);
+    SUOV(env, ret, result, 32);
+    return ret;
+}
+
+uint64_t helper_msub64_ssov(CPUTriCoreState *env, target_ulong r1,
+                            uint64_t r2, target_ulong r3)
+{
+    uint64_t ret, ovf;
+    int64_t t1 = sextract64(r1, 0, 32);
+    int64_t t3 = sextract64(r3, 0, 32);
+    int64_t mul;
+
+    mul = t1 * t3;
+    ret = r2 - mul;
+    ovf = (ret ^ r2) & (mul ^ r2);
+
+    if ((int64_t)ovf < 0) {
+        env->PSW_USB_V = (1 << 31);
+        env->PSW_USB_SV = (1 << 31);
+        /* ext_ret > MAX_INT */
+        if (mul < 0) {
+            ret = INT64_MAX;
+        /* ext_ret < MIN_INT */
+        } else {
+            ret = INT64_MIN;
+        }
+    } else {
+        env->PSW_USB_V = 0;
+    }
+    t1 = ret >> 32;
+    env->PSW_USB_AV = t1 ^ t1 * 2u;
+    env->PSW_USB_SAV |= env->PSW_USB_AV;
+    return ret;
+}
+
+uint64_t helper_msub64_suov(CPUTriCoreState *env, target_ulong r1,
+                            uint64_t r2, target_ulong r3)
+{
+    uint64_t ret, mul;
+    uint64_t t1 = extract64(r1, 0, 32);
+    uint64_t t3 = extract64(r3, 0, 32);
+
+    mul = t1 * t3;
+    ret = r2 - mul;
+
+    if (ret > r2) {
+        env->PSW_USB_V = (1 << 31);
+        env->PSW_USB_SV = (1 << 31);
+        /* saturate */
+        ret = 0;
+    } else {
+        env->PSW_USB_V = 0;
+    }
+    t1 = ret >> 32;
+    env->PSW_USB_AV = t1 ^ t1 * 2u;
+    env->PSW_USB_SAV |= env->PSW_USB_AV;
+    return ret;
+}
+
 /* context save area (CSA) related helpers */
 
 static int cdc_increment(target_ulong *psw)
@@ -437,6 +704,17 @@ void helper_stucx(CPUTriCoreState *env, uint32_t ea)
     save_context_upper(env, ea);
 }
 
+void helper_psw_write(CPUTriCoreState *env, uint32_t arg)
+{
+    psw_write(env, arg);
+}
+
+uint32_t helper_psw_read(CPUTriCoreState *env)
+{
+    return psw_read(env);
+}
+
+
 static inline void QEMU_NORETURN do_raise_exception_err(CPUTriCoreState *env,
                                                         uint32_t exception,
                                                         int error_code,