qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH] sparc32 fix carry flag handling (Solaris bootblk fix)
@ 2009-11-03 23:58 Artyom Tarasenko
  2009-11-04 19:44 ` [Qemu-devel] " Blue Swirl
  0 siblings, 1 reply; 8+ messages in thread
From: Artyom Tarasenko @ 2009-11-03 23:58 UTC (permalink / raw)
  To: qemu-devel, Blue Swirl

[-- Attachment #1: Type: text/plain, Size: 7094 bytes --]

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 <atar4qemu@gmail.com>
---
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 #2: 0001-op_helper-carry.patch --]
[-- Type: application/octet-stream, Size: 6768 bytes --]

Signed-off-by: Artyom Tarasenko <atar4qemu@gmail.com>
---
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 },

^ permalink raw reply related	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2009-12-16 16:42 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-11-03 23:58 [Qemu-devel] [PATCH] sparc32 fix carry flag handling (Solaris bootblk fix) Artyom Tarasenko
2009-11-04 19:44 ` [Qemu-devel] " Blue Swirl
2009-11-05 20:48   ` Artyom Tarasenko
2009-11-13 14:28     ` Artyom Tarasenko
2009-11-13 21:01       ` Blue Swirl
2009-12-10 18:27         ` Artyom Tarasenko
2009-12-12  9:07           ` Blue Swirl
2009-12-16 16:41   ` Artyom Tarasenko

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).