From: Artyom Tarasenko <atar4qemu@googlemail.com>
To: qemu-devel <qemu-devel@nongnu.org>, Blue Swirl <blauwirbel@gmail.com>
Subject: [Qemu-devel] [PATCH] sparc32 fix carry flag handling (Solaris bootblk fix)
Date: Wed, 4 Nov 2009 00:58:54 +0100 [thread overview]
Message-ID: <fb8d4f70911031558p6acadde8ubb372c4bc6ba82f4@mail.gmail.com> (raw)
[-- 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 },
next reply other threads:[~2009-11-03 23:59 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2009-11-03 23:58 Artyom Tarasenko [this message]
2009-11-04 19:44 ` [Qemu-devel] Re: [PATCH] sparc32 fix carry flag handling (Solaris bootblk fix) 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
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=fb8d4f70911031558p6acadde8ubb372c4bc6ba82f4@mail.gmail.com \
--to=atar4qemu@googlemail.com \
--cc=blauwirbel@gmail.com \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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).