aboutsummaryrefslogtreecommitdiff
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.c109
1 files changed, 109 insertions, 0 deletions
diff --git a/target-tricore/op_helper.c b/target-tricore/op_helper.c
index 40d32af5d3..d6b01c3c71 100644
--- a/target-tricore/op_helper.c
+++ b/target-tricore/op_helper.c
@@ -340,6 +340,31 @@ target_ulong helper_sub_ssov(CPUTriCoreState *env, target_ulong r1,
return ssov32(env, result);
}
+uint64_t helper_sub64_ssov(CPUTriCoreState *env, uint64_t r1, uint64_t r2)
+{
+ uint64_t result;
+ int64_t ovf;
+
+ result = r1 - r2;
+ ovf = (result ^ r1) & (r1 ^ r2);
+ env->PSW_USB_AV = (result ^ result * 2u) >> 32;
+ env->PSW_USB_SAV |= env->PSW_USB_AV;
+ if (ovf < 0) {
+ env->PSW_USB_V = (1 << 31);
+ env->PSW_USB_SV = (1 << 31);
+ /* ext_ret > MAX_INT */
+ if ((int64_t)r1 >= 0) {
+ result = INT64_MAX;
+ /* ext_ret < MIN_INT */
+ } else {
+ result = INT64_MIN;
+ }
+ } else {
+ env->PSW_USB_V = 0;
+ }
+ return result;
+}
+
target_ulong helper_sub_h_ssov(CPUTriCoreState *env, target_ulong r1,
target_ulong r2)
{
@@ -350,6 +375,52 @@ target_ulong helper_sub_h_ssov(CPUTriCoreState *env, target_ulong r1,
return ssov16(env, ret_hw0, ret_hw1);
}
+uint32_t helper_subr_h_ssov(CPUTriCoreState *env, uint64_t r1, uint32_t r2_l,
+ uint32_t r2_h)
+{
+ int64_t mul_res0 = sextract64(r1, 0, 32);
+ int64_t mul_res1 = sextract64(r1, 32, 32);
+ int64_t r2_low = sextract64(r2_l, 0, 32);
+ int64_t r2_high = sextract64(r2_h, 0, 32);
+ int64_t result0, result1;
+ uint32_t ovf0, ovf1;
+ uint32_t avf0, avf1;
+
+ ovf0 = ovf1 = 0;
+
+ result0 = r2_low - mul_res0 + 0x8000;
+ result1 = r2_high - mul_res1 + 0x8000;
+
+ avf0 = result0 * 2u;
+ avf0 = result0 ^ avf0;
+ avf1 = result1 * 2u;
+ avf1 = result1 ^ avf1;
+
+ if (result0 > INT32_MAX) {
+ ovf0 = (1 << 31);
+ result0 = INT32_MAX;
+ } else if (result0 < INT32_MIN) {
+ ovf0 = (1 << 31);
+ result0 = INT32_MIN;
+ }
+
+ if (result1 > INT32_MAX) {
+ ovf1 = (1 << 31);
+ result1 = INT32_MAX;
+ } else if (result1 < INT32_MIN) {
+ ovf1 = (1 << 31);
+ result1 = INT32_MIN;
+ }
+
+ env->PSW_USB_V = ovf0 | ovf1;
+ env->PSW_USB_SV |= env->PSW_USB_V;
+
+ env->PSW_USB_AV = avf0 | avf1;
+ env->PSW_USB_SAV |= env->PSW_USB_AV;
+
+ return (result1 & 0xffff0000ULL) | ((result0 >> 16) & 0xffffULL);
+}
+
target_ulong helper_sub_suov(CPUTriCoreState *env, target_ulong r1,
target_ulong r2)
{
@@ -1017,6 +1088,44 @@ uint32_t helper_add_h(CPUTriCoreState *env, target_ulong r1, target_ulong r2)
return ret;
}
+uint32_t helper_subr_h(CPUTriCoreState *env, uint64_t r1, uint32_t r2_l,
+ uint32_t r2_h)
+{
+ int64_t mul_res0 = sextract64(r1, 0, 32);
+ int64_t mul_res1 = sextract64(r1, 32, 32);
+ int64_t r2_low = sextract64(r2_l, 0, 32);
+ int64_t r2_high = sextract64(r2_h, 0, 32);
+ int64_t result0, result1;
+ uint32_t ovf0, ovf1;
+ uint32_t avf0, avf1;
+
+ ovf0 = ovf1 = 0;
+
+ result0 = r2_low - mul_res0 + 0x8000;
+ result1 = r2_high - mul_res1 + 0x8000;
+
+ if ((result0 > INT32_MAX) || (result0 < INT32_MIN)) {
+ ovf0 = (1 << 31);
+ }
+
+ if ((result1 > INT32_MAX) || (result1 < INT32_MIN)) {
+ ovf1 = (1 << 31);
+ }
+
+ env->PSW_USB_V = ovf0 | ovf1;
+ env->PSW_USB_SV |= env->PSW_USB_V;
+
+ avf0 = result0 * 2u;
+ avf0 = result0 ^ avf0;
+ avf1 = result1 * 2u;
+ avf1 = result1 ^ avf1;
+
+ env->PSW_USB_AV = avf0 | avf1;
+ env->PSW_USB_SAV |= env->PSW_USB_AV;
+
+ return (result1 & 0xffff0000ULL) | ((result0 >> 16) & 0xffffULL);
+}
+
uint32_t helper_sub_b(CPUTriCoreState *env, target_ulong r1, target_ulong r2)
{
int32_t b, i;