From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1Juz93-0003gS-Le for qemu-devel@nongnu.org; Sat, 10 May 2008 20:10:29 -0400 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1Juz92-0003fy-1K for qemu-devel@nongnu.org; Sat, 10 May 2008 20:10:29 -0400 Received: from [199.232.76.173] (port=53815 helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1Juz91-0003fq-Tz for qemu-devel@nongnu.org; Sat, 10 May 2008 20:10:27 -0400 Received: from server1linux.rebelnetworks.com ([66.135.44.167]:46173) by monty-python.gnu.org with esmtps (TLS-1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.60) (envelope-from ) id 1Juz91-0008AH-CM for qemu-devel@nongnu.org; Sat, 10 May 2008 20:10:27 -0400 Received: from p5b164eee.dip.t-dialin.net ([91.22.78.238] helo=phoenix2.frop.org) by server1linux.rebelnetworks.com with esmtpa (Exim 4.68) (envelope-from ) id 1Juz8s-0006GX-Ny for qemu-devel@nongnu.org; Sat, 10 May 2008 19:10:19 -0500 From: Julian Seward Date: Sun, 11 May 2008 02:04:47 +0200 MIME-Version: 1.0 Content-Type: Multipart/Mixed; boundary="Boundary-00=_fgjJI3JzDfSd2b6" Message-Id: <200805110204.47184.jseward@acm.org> Subject: [Qemu-devel] [PATCH] ppc32 guests: fix computation of XER.{CA, OV} in addme, subfme, mullwo Reply-To: qemu-devel@nongnu.org List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org --Boundary-00=_fgjJI3JzDfSd2b6 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Content-Disposition: inline For ppc32 guests, computation of XER.CA and XER.OV in some obscure cases is incorrect. At least, it doesn't produce the same results as a real MPC7447, and doesn't appear to be in accordance with the instruction set documentation. The attached patch fixes it: * addme{o}{.}, subfme{o}{.}: compute XER.CA correctly * mullwo{.}: sign extend arguments before doing 64-bit multiply, so as to make the XER.OV computation correct I suspect the handling of the 64-bit equivalents is similarly borked, but I haven't checked so far. J --Boundary-00=_fgjJI3JzDfSd2b6 Content-Type: text/x-diff; charset="us-ascii"; name="qemu-ppc32-fix-xer-ca-obscure-cases.diff" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="qemu-ppc32-fix-xer-ca-obscure-cases.diff" Index: target-ppc/op_helper.c =================================================================== --- target-ppc/op_helper.c (revision 4422) +++ target-ppc/op_helper.c (working copy) @@ -147,11 +147,14 @@ void do_addmeo (void) { + uint32_t argL = T0; + uint32_t res = T0 + xer_ca + (-1); + uint32_t carried = res < argL || ((xer_ca & 1) == 1 && res == argL); T1 = T0; - T0 += xer_ca + (-1); + T0 = res; xer_ov = ((uint32_t)T1 & ((uint32_t)T1 ^ (uint32_t)T0)) >> 31; xer_so |= xer_ov; - if (likely(T1 != 0)) + if (carried) xer_ca = 1; else xer_ca = 0; @@ -227,9 +230,9 @@ void do_mullwo (void) { - int64_t res = (int64_t)T0 * (int64_t)T1; + int64_t res = ((int64_t)(int32_t)T0) * ((int64_t)(int32_t)T1); - if (likely((int32_t)res == res)) { + if (likely( ((int64_t)(int32_t)res) == ((int64_t)res) )) { xer_ov = 0; } else { xer_ov = 1; @@ -306,11 +309,14 @@ void do_subfmeo (void) { + uint32_t argR = -1; + uint32_t res = ~T0 + xer_ca - 1; + uint32_t carried = res < argR || ((xer_ca & 1) == 1 && res == argR); T1 = T0; - T0 = ~T0 + xer_ca - 1; + T0 = res; xer_ov = ((uint32_t)~T1 & ((uint32_t)~T1 ^ (uint32_t)T0)) >> 31; xer_so |= xer_ov; - if (likely((uint32_t)T1 != UINT32_MAX)) + if (carried) xer_ca = 1; else xer_ca = 0; Index: target-ppc/op.c =================================================================== --- target-ppc/op.c (revision 4422) +++ target-ppc/op.c (working copy) @@ -883,8 +883,11 @@ /* add to minus one extended */ void OPPROTO op_add_me (void) { - T0 += xer_ca + (-1); - if (likely((uint32_t)T1 != 0)) + uint32_t argL = T0; + uint32_t res = T0 + xer_ca + (-1); + uint32_t carried = res < argL || ((xer_ca & 1) == 1 && res == argL); + T0 = res; + if (carried) xer_ca = 1; else xer_ca = 0; @@ -1176,8 +1179,11 @@ /* subtract from minus one extended */ void OPPROTO op_subfme (void) { - T0 = ~T0 + xer_ca - 1; - if (likely((uint32_t)T0 != UINT32_MAX)) + uint32_t argR = -1; + uint32_t res = ~T0 + xer_ca - 1; + uint32_t carried = res < argR || ((xer_ca & 1) == 1 && res == argR); + T0 = res; + if (carried) xer_ca = 1; else xer_ca = 0; --Boundary-00=_fgjJI3JzDfSd2b6--