qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [PATCH] sparc32 fix carry flag handling (Solaris bootblk fi


From: Artyom Tarasenko
Subject: [Qemu-devel] [PATCH] sparc32 fix carry flag handling (Solaris bootblk fix)
Date: Wed, 4 Nov 2009 00:58:54 +0100

The page 108 of the SPARC Version 8 Architecture Manual describes
that addcc and addxcc shall compute carry flag the same way.
The page 110 claims the same about subcc and subxcc instructions.
This patch fixes carry computation in corner cases and removes redundant code.
The most visible effect of the patch is enabling Solaris boot when using OBP.

Signed-off-by: Artyom Tarasenko <address@hidden>
---
diff --git a/target-sparc/op_helper.c b/target-sparc/op_helper.c
index a1ada8b..818c5f5 100644
--- a/target-sparc/op_helper.c
+++ b/target-sparc/op_helper.c
@@ -912,12 +912,16 @@ static uint32_t compute_C_div(void)
     return 0;
 }

-static inline uint32_t get_C_add_icc(target_ulong dst, target_ulong
src1)
+/* carry = (src1[31] & src2[31]) | ( ~dst[31] & (src1[31] |
src2[31])) */
+static inline uint32_t get_C_add_icc(target_ulong dst, target_ulong
src1,
+                                     target_ulong src2)
 {
     uint32_t ret = 0;

-    if ((dst & 0xffffffffULL) < (src1 & 0xffffffffULL))
-        ret |= PSR_CARRY;
+    if (((src1 & (1ULL << 31)) & (src2 & (1ULL << 31)))
+        | ((~(dst & (1ULL << 31)))
+           & ((src1 & (1ULL << 31)) | (src2 & (1ULL << 31)))) )
+        ret  |=PSR_CARRY;
     return ret;
 }

@@ -931,21 +935,6 @@ static inline uint32_t get_V_add_icc(target_ulong
dst, target_ulong src1,
     return ret;
 }

-static uint32_t compute_all_add(void)
-{
-    uint32_t ret;
-
-    ret = get_NZ_icc(CC_DST);
-    ret |= get_C_add_icc(CC_DST, CC_SRC);
-    ret |= get_V_add_icc(CC_DST, CC_SRC, CC_SRC2);
-    return ret;
-}
-
-static uint32_t compute_C_add(void)
-{
-    return get_C_add_icc(CC_DST, CC_SRC);
-}
-
 #ifdef TARGET_SPARC64
 static inline uint32_t get_C_add_xcc(target_ulong dst, target_ulong
src1)
 {
@@ -982,24 +971,19 @@ static uint32_t compute_C_add_xcc(void)
 }
 #endif

-static uint32_t compute_all_addx(void)
+static uint32_t compute_all_add(void)
 {
     uint32_t ret;

     ret = get_NZ_icc(CC_DST);
-    ret |= get_C_add_icc(CC_DST - CC_SRC2, CC_SRC);
-    ret |= get_C_add_icc(CC_DST, CC_SRC);
+    ret |= get_C_add_icc(CC_DST, CC_SRC, CC_SRC2);
     ret |= get_V_add_icc(CC_DST, CC_SRC, CC_SRC2);
     return ret;
 }

-static uint32_t compute_C_addx(void)
+static uint32_t compute_C_add(void)
 {
-    uint32_t ret;
-
-    ret = get_C_add_icc(CC_DST - CC_SRC2, CC_SRC);
-    ret |= get_C_add_icc(CC_DST, CC_SRC);
-    return ret;
+    return get_C_add_icc(CC_DST, CC_SRC, CC_SRC2);
 }

 #ifdef TARGET_SPARC64
@@ -1038,7 +1022,7 @@ static uint32_t compute_all_tadd(void)
     uint32_t ret;

     ret = get_NZ_icc(CC_DST);
-    ret |= get_C_add_icc(CC_DST, CC_SRC);
+    ret |= get_C_add_icc(CC_DST, CC_SRC, CC_SRC2);
     ret |= get_V_add_icc(CC_DST, CC_SRC, CC_SRC2);
     ret |= get_V_tag_icc(CC_SRC, CC_SRC2);
     return ret;
@@ -1046,7 +1030,7 @@ static uint32_t compute_all_tadd(void)

 static uint32_t compute_C_tadd(void)
 {
-    return get_C_add_icc(CC_DST, CC_SRC);
+    return get_C_add_icc(CC_DST, CC_SRC, CC_SRC2);
 }

 static uint32_t compute_all_taddtv(void)
@@ -1054,21 +1038,25 @@ static uint32_t compute_all_taddtv(void)
     uint32_t ret;

     ret = get_NZ_icc(CC_DST);
-    ret |= get_C_add_icc(CC_DST, CC_SRC);
+    ret |= get_C_add_icc(CC_DST, CC_SRC, CC_SRC2);
     return ret;
 }

 static uint32_t compute_C_taddtv(void)
 {
-    return get_C_add_icc(CC_DST, CC_SRC);
+    return get_C_add_icc(CC_DST, CC_SRC, CC_SRC2);
 }

-static inline uint32_t get_C_sub_icc(target_ulong src1, target_ulong
src2)
+/* carry = (~src1[31] & src2[31]) | ( dst[31]  & (~src1[31] |
src2[31])) */
+static inline uint32_t get_C_sub_icc(target_ulong dst, target_ulong
src1,
+                                     target_ulong src2)
 {
     uint32_t ret = 0;

-    if ((src1 & 0xffffffffULL) < (src2 & 0xffffffffULL))
-        ret |= PSR_CARRY;
+    if((( ~(src1 & (1ULL << 31))) & (src2 & (1ULL << 31)))
+       | ((dst & (1ULL << 31)) & (( ~(src1 & (1ULL << 31)))
+                                         | (src2 & (1ULL << 31)))))
+       ret  |=PSR_CARRY;
     return ret;
 }

@@ -1082,20 +1070,6 @@ static inline uint32_t
get_V_sub_icc(target_ulong dst, target_ulong src1,
     return ret;
 }

-static uint32_t compute_all_sub(void)
-{
-    uint32_t ret;
-
-    ret = get_NZ_icc(CC_DST);
-    ret |= get_C_sub_icc(CC_SRC, CC_SRC2);
-    ret |= get_V_sub_icc(CC_DST, CC_SRC, CC_SRC2);
-    return ret;
-}
-
-static uint32_t compute_C_sub(void)
-{
-    return get_C_sub_icc(CC_SRC, CC_SRC2);
-}

 #ifdef TARGET_SPARC64
 static inline uint32_t get_C_sub_xcc(target_ulong src1, target_ulong
src2)
@@ -1133,24 +1107,19 @@ static uint32_t compute_C_sub_xcc(void)
 }
 #endif

-static uint32_t compute_all_subx(void)
+static uint32_t compute_all_sub(void)
 {
     uint32_t ret;

     ret = get_NZ_icc(CC_DST);
-    ret |= get_C_sub_icc(CC_DST - CC_SRC2, CC_SRC);
-    ret |= get_C_sub_icc(CC_DST, CC_SRC2);
+    ret |= get_C_sub_icc(CC_DST, CC_SRC, CC_SRC2);
     ret |= get_V_sub_icc(CC_DST, CC_SRC, CC_SRC2);
     return ret;
 }

-static uint32_t compute_C_subx(void)
+static uint32_t compute_C_sub(void)
 {
-    uint32_t ret;
-
-    ret = get_C_sub_icc(CC_DST - CC_SRC2, CC_SRC);
-    ret |= get_C_sub_icc(CC_DST, CC_SRC2);
-    return ret;
+    return get_C_sub_icc(CC_DST, CC_SRC, CC_SRC2);
 }

 #ifdef TARGET_SPARC64
@@ -1180,7 +1149,7 @@ static uint32_t compute_all_tsub(void)
     uint32_t ret;

     ret = get_NZ_icc(CC_DST);
-    ret |= get_C_sub_icc(CC_DST, CC_SRC);
+    ret |= get_C_sub_icc(CC_DST, CC_SRC, CC_SRC2);
     ret |= get_V_sub_icc(CC_DST, CC_SRC, CC_SRC2);
     ret |= get_V_tag_icc(CC_SRC, CC_SRC2);
     return ret;
@@ -1188,7 +1157,7 @@ static uint32_t compute_all_tsub(void)

 static uint32_t compute_C_tsub(void)
 {
-    return get_C_sub_icc(CC_DST, CC_SRC);
+    return get_C_sub_icc(CC_DST, CC_SRC, CC_SRC2);
 }

 static uint32_t compute_all_tsubtv(void)
@@ -1196,13 +1165,13 @@ static uint32_t compute_all_tsubtv(void)
     uint32_t ret;

     ret = get_NZ_icc(CC_DST);
-    ret |= get_C_sub_icc(CC_DST, CC_SRC);
+    ret |= get_C_sub_icc(CC_DST, CC_SRC, CC_SRC2);
     return ret;
 }

 static uint32_t compute_C_tsubtv(void)
 {
-    return get_C_sub_icc(CC_DST, CC_SRC);
+    return get_C_sub_icc(CC_DST, CC_SRC, CC_SRC2);
 }

 static uint32_t compute_all_logic(void)
@@ -1232,11 +1201,11 @@ static const CCTable icc_table[CC_OP_NB] = {
     [CC_OP_FLAGS] = { compute_all_flags, compute_C_flags },
     [CC_OP_DIV] = { compute_all_div, compute_C_div },
     [CC_OP_ADD] = { compute_all_add, compute_C_add },
-    [CC_OP_ADDX] = { compute_all_addx, compute_C_addx },
+    [CC_OP_ADDX] = { compute_all_add, compute_C_add },
     [CC_OP_TADD] = { compute_all_tadd, compute_C_tadd },
     [CC_OP_TADDTV] = { compute_all_taddtv, compute_C_taddtv },
     [CC_OP_SUB] = { compute_all_sub, compute_C_sub },
-    [CC_OP_SUBX] = { compute_all_subx, compute_C_subx },
+    [CC_OP_SUBX] = { compute_all_sub, compute_C_sub },
     [CC_OP_TSUB] = { compute_all_tsub, compute_C_tsub },
     [CC_OP_TSUBTV] = { compute_all_tsubtv, compute_C_tsubtv },
     [CC_OP_LOGIC] = { compute_all_logic, compute_C_logic },

Attachment: 0001-op_helper-carry.patch
Description: Binary data


reply via email to

[Prev in Thread] Current Thread [Next in Thread]