From patchwork Tue Nov 3 23:58:54 2009 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Artyom Tarasenko X-Patchwork-Id: 37540 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [199.232.76.165]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id 132CDB7BE3 for ; Wed, 4 Nov 2009 11:00:00 +1100 (EST) Received: from localhost ([127.0.0.1]:42567 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1N5TI3-0004Yj-Ak for incoming@patchwork.ozlabs.org; Tue, 03 Nov 2009 18:59:55 -0500 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1N5THW-0004YL-E1 for qemu-devel@nongnu.org; Tue, 03 Nov 2009 18:59:22 -0500 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1N5THS-0004Xj-U8 for qemu-devel@nongnu.org; Tue, 03 Nov 2009 18:59:22 -0500 Received: from [199.232.76.173] (port=40049 helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1N5THS-0004Xg-MB for qemu-devel@nongnu.org; Tue, 03 Nov 2009 18:59:18 -0500 Received: from mail-yx0-f188.google.com ([209.85.210.188]:54418) by monty-python.gnu.org with esmtp (Exim 4.60) (envelope-from ) id 1N5THS-0002p3-5d for qemu-devel@nongnu.org; Tue, 03 Nov 2009 18:59:18 -0500 Received: by yxe26 with SMTP id 26so5871553yxe.4 for ; Tue, 03 Nov 2009 15:59:17 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=googlemail.com; s=gamma; h=domainkey-signature:mime-version:received:from:date:message-id :subject:to:content-type; bh=hX4S9bJFBWVylbnv8T7ix/qDsiIXEZ62p6vu+JE7Bzo=; b=vyAEkn/rLC0/hrVqs4hTC3Rj13kntSAtGtlodcEQCfqYSzpWYfg5vhoKIhAIzWwP0N mHOWKps5heoQf4UWG22kUjriFNdUoNW5jmSr1VahJXfwHHD3IbzwQyG/ejlls+lRPMZG mVbJeY8Rii3FZOWhhQKJMkqE2ggctNtChSFLk= DomainKey-Signature: a=rsa-sha1; c=nofws; d=googlemail.com; s=gamma; h=mime-version:from:date:message-id:subject:to:content-type; b=tEZC5oyqx6j/AnVJv92OiCF2tOU2Zb4Y3PMJUahLOhK4dq60yWWr9buoogWYJIDKa8 75Zr2JRIgNC4swcrm2YVWCdxAOXiQ6V7tSU0ven6NeM322cELa3c/OAbskfbEv15ZDSE KLOxNo7/PUEJDORWTpyJCMsvoSWPcOln9kk8Y= MIME-Version: 1.0 Received: by 10.90.42.39 with SMTP id p39mr1748323agp.86.1257292754181; Tue, 03 Nov 2009 15:59:14 -0800 (PST) From: Artyom Tarasenko Date: Wed, 4 Nov 2009 00:58:54 +0100 Message-ID: To: qemu-devel , Blue Swirl X-detected-operating-system: by monty-python.gnu.org: GNU/Linux 2.6 (newer, 2) Cc: Subject: [Qemu-devel] [PATCH] sparc32 fix carry flag handling (Solaris bootblk fix) X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org 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 --- 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 }, 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;