* [Qemu-devel] [PATCH] ppc32 guests: fix computation of XER.{CA, OV} in addme, subfme, mullwo @ 2008-05-11 0:04 Julian Seward 2008-06-17 12:27 ` Aurelien Jarno 2008-10-01 21:47 ` Aurelien Jarno 0 siblings, 2 replies; 13+ messages in thread From: Julian Seward @ 2008-05-11 0:04 UTC (permalink / raw) To: qemu-devel [-- Attachment #1: Type: text/plain, Size: 535 bytes --] 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 [-- Attachment #2: qemu-ppc32-fix-xer-ca-obscure-cases.diff --] [-- Type: text/x-diff, Size: 2323 bytes --] 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; ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [Qemu-devel] [PATCH] ppc32 guests: fix computation of XER.{CA, OV} in addme, subfme, mullwo 2008-05-11 0:04 [Qemu-devel] [PATCH] ppc32 guests: fix computation of XER.{CA, OV} in addme, subfme, mullwo Julian Seward @ 2008-06-17 12:27 ` Aurelien Jarno 2008-06-17 22:06 ` Julian Seward 2008-10-01 21:47 ` Aurelien Jarno 1 sibling, 1 reply; 13+ messages in thread From: Aurelien Jarno @ 2008-06-17 12:27 UTC (permalink / raw) To: Julian Seward; +Cc: qemu-devel On Sun, May 11, 2008 at 02:04:47AM +0200, Julian Seward wrote: > > 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 Could you please give us a corner case for at least one of the instructions? It would help to clearly understand the problem. Thanks, Aurelien -- .''`. Aurelien Jarno | GPG: 1024D/F1BCDB73 : :' : Debian developer | Electrical Engineer `. `' aurel32@debian.org | aurelien@aurel32.net `- people.debian.org/~aurel32 | www.aurel32.net ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [Qemu-devel] [PATCH] ppc32 guests: fix computation of XER.{CA, OV} in addme, subfme, mullwo 2008-06-17 12:27 ` Aurelien Jarno @ 2008-06-17 22:06 ` Julian Seward 2008-06-17 22:53 ` J. Mayer 2008-06-18 22:13 ` Tristan Gingold 0 siblings, 2 replies; 13+ messages in thread From: Julian Seward @ 2008-06-17 22:06 UTC (permalink / raw) To: Aurelien Jarno; +Cc: qemu-devel On Tuesday 17 June 2008 14:27, Aurelien Jarno wrote: > On Sun, May 11, 2008 at 02:04:47AM +0200, Julian Seward wrote: > > 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 > > Could you please give us a corner case for at least one of the > instructions? It would help to clearly understand the problem. Below is a test case showing the problem with mullwo, addme and subfme. On a real 7447 it prints mullwo. 000f423f ffffffff = fff0bdc1 (cr 80000000 xer 00000000) addme 00000000 XER.CA=1 = 00000000 (cr 00000000 xer 20000000) subfme 00000000 XER.CA=1 = ffffffff (cr 00000000 xer 20000000) On QEMU, unpatched, both the result cr and xer are wrong for mullwo., and the xer values are wrong for addme and subfme. mullwo. 000f423f ffffffff = fff0bdc1 (cr 90000000 xer c0000000) addme 00000000 XER.CA=1 = 00000000 (cr 00000000 xer 00000000) subfme 00000000 XER.CA=1 = ffffffff (cr 00000000 xer 00000000) On QEMU, with patch applied, result is same as on 7447. mullwo. 000f423f ffffffff = fff0bdc1 (cr 80000000 xer 00000000) addme 00000000 XER.CA=1 = 00000000 (cr 00000000 xer 20000000) subfme 00000000 XER.CA=1 = ffffffff (cr 00000000 xer 20000000) J /* Compiled with "gcc -Wall -g -O -o ppcbad ppcbad.c" */ #include <stdio.h> #include <string.h> typedef unsigned int UInt; /* At entry, res[0] and res[1] contain 2 args to "mullwo.". At exit, res[0] holds result, res[1] holds resulting %cr, and res[2] holds resulting %xer. */ void do_mullwo_dot ( UInt* res ) { __asm__ __volatile__( "\tmr 29,%0\n" "\tli 25,0\n" "\tmtxer 25\n" "\tmtcr 25\n" "\tlwz 21,0(29)\n" "\tlwz 22,4(29)\n" "\tmullwo. 23,21,22\n" "\tstw 23,0(29)\n" "\tmfcr 25\n" "\tstw 25,4(29)\n" "\tmfxer 25\n" "\tstw 25,8(29)\n" : /*OUT*/ : /*IN*/"b"(res) : /*trash*/ "r29","r25","r21","r22","r23", "memory","cc" ); } /* At entry, res[0] contain 1 arg to "addme". Set XER.CA=1. At exit, res[0] holds result, res[1] holds resulting %cr, and res[2] holds resulting %xer. */ void do_addme ( UInt* res ) { __asm__ __volatile__( "\tmr 29,%0\n" "\tli 25,0\n" "\tmtcr 25\n" "\tlis 25,0x2000\n" "\tmtxer 25\n" // set XER.CA=1 "\tlwz 21,0(29)\n" "\taddme 23,21\n" "\tstw 23,0(29)\n" "\tmfcr 25\n" "\tstw 25,4(29)\n" "\tmfxer 25\n" "\tstw 25,8(29)\n" : /*OUT*/ : /*IN*/"b"(res) : /*trash*/ "r29","r25","r21","r22","r23", "memory","cc" ); } /* At entry, res[0] contain 1 arg to "subfme". Set XER.CA=1. At exit, res[0] holds result, res[1] holds resulting %cr, and res[2] holds resulting %xer. */ void do_subfme ( UInt* res ) { __asm__ __volatile__( "\tmr 29,%0\n" "\tli 25,0\n" "\tmtcr 25\n" "\tlis 25,0x2000\n" "\tmtxer 25\n" // set XER.CA=1 "\tlwz 21,0(29)\n" "\tsubfme 23,21\n" "\tstw 23,0(29)\n" "\tmfcr 25\n" "\tstw 25,4(29)\n" "\tmfxer 25\n" "\tstw 25,8(29)\n" : /*OUT*/ : /*IN*/"b"(res) : /*trash*/ "r29","r25","r21","r22","r23", "memory","cc" ); } UInt zzz ( void ) { return 0x20000000; } int main ( void ) { UInt arr[3]; /* Try mullwo. */ arr[0] = 0x000f423f; arr[1] = 0xffffffff; arr[2] = 0; do_mullwo_dot(&arr[0]); printf("mullwo. 000f423f ffffffff = %08x (cr %08x xer %08x)\n", arr[0],arr[1],arr[2]); /* Try addme */ arr[0] = 0; arr[1] = 0; arr[2] = 0; do_addme(&arr[0]); printf("addme 00000000 XER.CA=1 = %08x (cr %08x xer %08x)\n", arr[0],arr[1],arr[2]); /* Try subfme */ arr[0] = 0; arr[1] = 0; arr[2] = 0; do_subfme(&arr[0]); printf("subfme 00000000 XER.CA=1 = %08x (cr %08x xer %08x)\n", arr[0],arr[1],arr[2]); return 0; } ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [Qemu-devel] [PATCH] ppc32 guests: fix computation of XER.{CA, OV} in addme, subfme, mullwo 2008-06-17 22:06 ` Julian Seward @ 2008-06-17 22:53 ` J. Mayer 2008-06-17 23:23 ` Julian Seward 2008-06-18 22:13 ` Tristan Gingold 1 sibling, 1 reply; 13+ messages in thread From: J. Mayer @ 2008-06-17 22:53 UTC (permalink / raw) To: qemu-devel On Wed, 2008-06-18 at 00:06 +0200, Julian Seward wrote: > On Tuesday 17 June 2008 14:27, Aurelien Jarno wrote: > > On Sun, May 11, 2008 at 02:04:47AM +0200, Julian Seward wrote: > > > 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 which seems to already been done... (and tested many times) > > Could you please give us a corner case for at least one of the > > instructions? It would help to clearly understand the problem. > > Below is a test case showing the problem with mullwo, addme and > subfme. On a real 7447 it prints This patch looks really ugly, does not respect the coding style and addme/subme changes seem very suspicious to me... I won't merge this as-is, but I could check more on real hardware I got (from 601 to G5). Could you please exactly describe the test conditions (host, ...) ? Thanks [...] -- J. Mayer <l_indien@magic.fr> Never organized ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [Qemu-devel] [PATCH] ppc32 guests: fix computation of XER.{CA, OV} in addme, subfme, mullwo 2008-06-17 22:53 ` J. Mayer @ 2008-06-17 23:23 ` Julian Seward 2008-06-18 21:32 ` J. Mayer 0 siblings, 1 reply; 13+ messages in thread From: Julian Seward @ 2008-06-17 23:23 UTC (permalink / raw) To: qemu-devel On Wednesday 18 June 2008 00:53, J. Mayer wrote: > This patch looks really ugly, does not respect the coding style and > addme/subme changes seem very suspicious to me... Thanks for the encouragement. > Could you please exactly describe the test conditions (host, ...) ? Core 2 Duo, openSUSE 10.2, 64-bit mode, gcc-3.4.6, qemu svn trunk from 2 days ago. J ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [Qemu-devel] [PATCH] ppc32 guests: fix computation of XER.{CA, OV} in addme, subfme, mullwo 2008-06-17 23:23 ` Julian Seward @ 2008-06-18 21:32 ` J. Mayer 2008-06-18 21:39 ` Julian Seward 0 siblings, 1 reply; 13+ messages in thread From: J. Mayer @ 2008-06-18 21:32 UTC (permalink / raw) To: qemu-devel On Wed, 2008-06-18 at 01:23 +0200, Julian Seward wrote: > On Wednesday 18 June 2008 00:53, J. Mayer wrote: > > > This patch looks really ugly, does not respect the coding style and > > addme/subme changes seem very suspicious to me... > > Thanks for the encouragement. I guess I won't become a diplomat soon... Looking at the (relativelly) recent changes in this code, I can see that I did an optimization that seems correct at first sight but... The goal was to avoid tests for xer_ov & xer_so computation. The previous version was OK, I still have tests results which validate the cases you describe. @@ -319,15 +149,12 @@ void do_addmeo (void) { T1 = T0; T0 += xer_ca + (-1); - if (likely(!((uint32_t)T1 & - ((uint32_t)T1 ^ (uint32_t)T0) & (1UL << 31)))) { - xer_ov = 0; - } else { - xer_ov = 1; - xer_so = 1; - } + xer_ov = ((uint32_t)T1 & ((uint32_t)T1 ^ (uint32_t)T0)) >> 31; + xer_so |= xer_ov; if (likely(T1 != 0)) xer_ca = 1; @@ -335,43 +162,40 @@ void do_addmeo_64 (void) { T1 = T0; T0 += xer_ca + (-1); - if (likely(!((uint64_t)T1 & - ((uint64_t)T1 ^ (uint64_t)T0) & (1ULL << 63)))) { - xer_ov = 0; - } else { - xer_ov = 1; - xer_so = 1; - } + xer_ov = ((uint64_t)T1 & ((uint64_t)T1 ^ (uint64_t)T0)) >> 63; + xer_so |= xer_ov; if (likely(T1 != 0)) xer_ca = 1; @@ -483,15 +308,12 @@ void do_subfmeo (void) { T1 = T0; T0 = ~T0 + xer_ca - 1; - if (likely(!((uint32_t)~T1 & ((uint32_t)~T1 ^ (uint32_t)T0) & - (1UL << 31)))) { - xer_ov = 0; - } else { - xer_ov = 1; - xer_so = 1; - } + xer_ov = ((uint32_t)~T1 & ((uint32_t)~T1 ^ (uint32_t)T0)) >> 31; + xer_so |= xer_ov; if (likely((uint32_t)T1 != UINT32_MAX)) xer_ca = 1; @@ -499,15 +321,12 @@ void do_subfmeo_64 (void) { T1 = T0; T0 = ~T0 + xer_ca - 1; - if (likely(!((uint64_t)~T1 & ((uint64_t)~T1 ^ (uint64_t)T0) & - (1ULL << 63)))) { - xer_ov = 0; - } else { - xer_ov = 1; - xer_so = 1; - } + xer_ov = ((uint64_t)~T1 & ((uint64_t)~T1 ^ (uint64_t)T0)) >> 63; + xer_so |= xer_ov; if (likely((uint64_t)T1 != UINT64_MAX)) xer_ca = 1; @@ -515,13 +334,9 @@ void do_subfzeo (void) { T1 = T0; T0 = ~T0 + xer_ca; - if (likely(!(((uint32_t)~T1 ^ UINT32_MAX) & - ((uint32_t)(~T1) ^ (uint32_t)T0) & (1UL << 31)))) { - xer_ov = 0; - } else { - xer_ov = 1; - xer_so = 1; - } + xer_ov = (((uint32_t)~T1 ^ UINT32_MAX) & + ((uint32_t)(~T1) ^ (uint32_t)T0)) >> 31; + xer_so |= xer_ov; if (likely((uint32_t)T0 >= (uint32_t)~T1)) { xer_ca = 0; } else { @@ -534,13 +349,9 @@ void do_subfzeo_64 (void) { T1 = T0; T0 = ~T0 + xer_ca; - if (likely(!(((uint64_t)~T1 ^ UINT64_MAX) & - ((uint64_t)(~T1) ^ (uint64_t)T0) & (1ULL << 63)))) { - xer_ov = 0; - } else { - xer_ov = 1; - xer_so = 1; - } + xer_ov = (((uint64_t)~T1 ^ UINT64_MAX) & + ((uint64_t)(~T1) ^ (uint64_t)T0)) >> 63; + xer_so |= xer_ov; if (likely((uint64_t)T0 >= (uint64_t)~T1)) { xer_ca = 0; } else { Do you feel like this patch is buggy ? > > > Could you please exactly describe the test conditions (host, ...) ? > > Core 2 Duo, openSUSE 10.2, 64-bit mode, gcc-3.4.6, qemu svn trunk from > 2 days ago. 64 bits only bug, for mullwo ? Well, I'm running amd64 for years, but.... -- J. Mayer <l_indien@magic.fr> Never organized ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [Qemu-devel] [PATCH] ppc32 guests: fix computation of XER.{CA, OV} in addme, subfme, mullwo 2008-06-18 21:32 ` J. Mayer @ 2008-06-18 21:39 ` Julian Seward 2008-06-18 22:09 ` J. Mayer 0 siblings, 1 reply; 13+ messages in thread From: Julian Seward @ 2008-06-18 21:39 UTC (permalink / raw) To: qemu-devel On Wednesday 18 June 2008 23:32, J. Mayer wrote: > Looking at the (relativelly) recent changes in this code, I can see that > I did an optimization that seems correct at first sight but... > [ .. big patch deleted .. ] > Do you feel like this patch is buggy ? Why don't you just commit the patch I sent? It's shorter, it fixes the problem I reported and it does not cause any regressions. J ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [Qemu-devel] [PATCH] ppc32 guests: fix computation of XER.{CA, OV} in addme, subfme, mullwo 2008-06-18 21:39 ` Julian Seward @ 2008-06-18 22:09 ` J. Mayer 0 siblings, 0 replies; 13+ messages in thread From: J. Mayer @ 2008-06-18 22:09 UTC (permalink / raw) To: qemu-devel On Wed, 2008-06-18 at 23:39 +0200, Julian Seward wrote: > On Wednesday 18 June 2008 23:32, J. Mayer wrote: > > Looking at the (relativelly) recent changes in this code, I can see that > > I did an optimization that seems correct at first sight but... > > [ .. big patch deleted .. ] > > Do you feel like this patch is buggy ? > > Why don't you just commit the patch I sent? It's shorter, it > fixes the problem I reported and it does not cause any regressions. it's ugly, obfuscated code, adding useless temporary variables and tests that used not to be needed to achieve the same computation (where we want the code to be fast and would like to remove all tests in flags computations...). Furthermore, it's inconsistent as more operations use similar code then would need to be patched too if those one are false. Then, I got numerous test results which gives the correct result with the same arguments you use, running qemu on different hosts (x86, x86_64 and PPC32/64), then I must find time to redo all those tests to get convinced it's now broken, find what did broke it, then rollback the changes that broke this code. -- J. Mayer <l_indien@magic.fr> Never organized ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [Qemu-devel] [PATCH] ppc32 guests: fix computation of XER.{CA, OV} in addme, subfme, mullwo 2008-06-17 22:06 ` Julian Seward 2008-06-17 22:53 ` J. Mayer @ 2008-06-18 22:13 ` Tristan Gingold 2008-06-19 7:36 ` Julian Seward 1 sibling, 1 reply; 13+ messages in thread From: Tristan Gingold @ 2008-06-18 22:13 UTC (permalink / raw) To: qemu-devel On Jun 17, 2008, at 6:06 PM, Julian Seward wrote: > Below is a test case showing the problem with mullwo, addme and > subfme. On a real 7447 it prints > > addme 00000000 XER.CA=1 = 00000000 (cr 00000000 xer 20000000) Did I miss the obvious, but why does 0 + 1 - 1 generate a carry ? ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [Qemu-devel] [PATCH] ppc32 guests: fix computation of XER.{CA, OV} in addme, subfme, mullwo 2008-06-18 22:13 ` Tristan Gingold @ 2008-06-19 7:36 ` Julian Seward 2008-06-19 8:36 ` Tristan Gingold 0 siblings, 1 reply; 13+ messages in thread From: Julian Seward @ 2008-06-19 7:36 UTC (permalink / raw) To: Tristan Gingold; +Cc: qemu-devel > > addme 00000000 XER.CA=1 = 00000000 (cr 00000000 xer 20000000) > > Did I miss the obvious, but why does 0 + 1 - 1 generate a carry ? Because (as per the docs) it's computing rA + XER.CA + 0xFFFF_FFFF, which is 0 + 1 + 0xFFFF_FFFF == 0x1_0000_0000. Which does indeed carry. I tested now on both a 7447 and a G5 and they both do that. On a real 7447: mullwo. 000f423f ffffffff = fff0bdc1 (cr 80000000 xer 00000000) addme 00000000 XER.CA=1 = 00000000 (cr 00000000 xer 20000000) subfme 00000000 XER.CA=1 = ffffffff (cr 00000000 xer 20000000) On a real G5: mullwo. 000f423f ffffffff = fff0bdc1 (cr 80000000 xer 00000000) addme 00000000 XER.CA=1 = 00000000 (cr 00000000 xer 20000000) subfme 00000000 XER.CA=1 = ffffffff (cr 00000000 xer 20000000) J ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [Qemu-devel] [PATCH] ppc32 guests: fix computation of XER.{CA, OV} in addme, subfme, mullwo 2008-06-19 7:36 ` Julian Seward @ 2008-06-19 8:36 ` Tristan Gingold 2008-06-19 9:12 ` J. Mayer 0 siblings, 1 reply; 13+ messages in thread From: Tristan Gingold @ 2008-06-19 8:36 UTC (permalink / raw) To: Julian Seward; +Cc: qemu-devel On Jun 19, 2008, at 3:36 AM, Julian Seward wrote: > >>> addme 00000000 XER.CA=1 = 00000000 (cr 00000000 xer 20000000) >> >> Did I miss the obvious, but why does 0 + 1 - 1 generate a carry ? > > Because (as per the docs) it's computing rA + XER.CA + 0xFFFF_FFFF, > which is 0 + 1 + 0xFFFF_FFFF == 0x1_0000_0000. Which does indeed > carry. I tested now on both a 7447 and a G5 and they both do that. Ok thanks. So addme set the carry unless both xer.ca and rA are 0. Your expression is a little bit complex, especially the second part. If xer_ca = 1 then res == argL, right ? For reference: 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); Tristan. ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [Qemu-devel] [PATCH] ppc32 guests: fix computation of XER.{CA, OV} in addme, subfme, mullwo 2008-06-19 8:36 ` Tristan Gingold @ 2008-06-19 9:12 ` J. Mayer 0 siblings, 0 replies; 13+ messages in thread From: J. Mayer @ 2008-06-19 9:12 UTC (permalink / raw) To: qemu-devel [-- Attachment #1: Type: text/plain, Size: 1438 bytes --] On Thu, 2008-06-19 at 04:36 -0400, Tristan Gingold wrote: > On Jun 19, 2008, at 3:36 AM, Julian Seward wrote: > > > > >>> addme 00000000 XER.CA=1 = 00000000 (cr 00000000 xer 20000000) > >> > >> Did I miss the obvious, but why does 0 + 1 - 1 generate a carry ? > > > > Because (as per the docs) it's computing rA + XER.CA + 0xFFFF_FFFF, > > which is 0 + 1 + 0xFFFF_FFFF == 0x1_0000_0000. Which does indeed > > carry. I tested now on both a 7447 and a G5 and they both do that. > > Ok thanks. So addme set the carry unless both xer.ca and rA are 0. > > Your expression is a little bit complex, especially the second part. > If xer_ca = 1 then res == argL, right ? OK, then I found the faulty change (from me) and reverting it should do the trick and fix addme and subfme in 32 and 64 bits cases. I also added some missing casts for addmeo. The fix is quite simple: the carry should never be reseted by those instructions as xer_ca == 1 will always lead to set the carry with the result (T0 + 1 -1 is always equal to T0, whatever T0 value...) For the mullw(o) issue, I guess the mullw seems faulty too, as it should produce a 64 bits signed result when running in 64 bits mode. And I guess this part of your patch is useless as res is already an int64_t : - if (likely((int32_t)res == res)) { + if (likely( ((int64_t)(int32_t)res) == ((int64_t)res) )) { . Can you confirm ? -- J. Mayer <l_indien@magic.fr> Never organized [-- Attachment #2: addme_subfme.diff --] [-- Type: text/x-patch, Size: 2301 bytes --] Index: op.c =================================================================== RCS file: /sources/qemu/qemu/target-ppc/op.c,v retrieving revision 1.68 diff -u -d -d -p -r1.68 op.c --- op.c 16 Nov 2007 14:11:28 -0000 1.68 +++ op.c 19 Jun 2008 08:57:01 -0000 @@ -920,8 +920,6 @@ void OPPROTO op_add_me (void) T0 += xer_ca + (-1); if (likely((uint32_t)T1 != 0)) xer_ca = 1; - else - xer_ca = 0; RETURN(); } @@ -931,8 +929,6 @@ void OPPROTO op_add_me_64 (void) T0 += xer_ca + (-1); if (likely((uint64_t)T1 != 0)) xer_ca = 1; - else - xer_ca = 0; RETURN(); } #endif @@ -1213,8 +1209,6 @@ void OPPROTO op_subfme (void) T0 = ~T0 + xer_ca - 1; if (likely((uint32_t)T0 != UINT32_MAX)) xer_ca = 1; - else - xer_ca = 0; RETURN(); } @@ -1224,8 +1218,6 @@ void OPPROTO op_subfme_64 (void) T0 = ~T0 + xer_ca - 1; if (likely((uint64_t)T0 != UINT64_MAX)) xer_ca = 1; - else - xer_ca = 0; RETURN(); } #endif Index: op_helper.c =================================================================== RCS file: /sources/qemu/qemu/target-ppc/op_helper.c,v retrieving revision 1.73 diff -u -d -d -p -r1.73 op_helper.c --- op_helper.c 24 Nov 2007 02:03:55 -0000 1.73 +++ op_helper.c 19 Jun 2008 08:57:01 -0000 @@ -151,10 +151,8 @@ void do_addmeo (void) T0 += xer_ca + (-1); xer_ov = ((uint32_t)T1 & ((uint32_t)T1 ^ (uint32_t)T0)) >> 31; xer_so |= xer_ov; - if (likely(T1 != 0)) + if (likely((uint32_t)T1 != 0)) xer_ca = 1; - else - xer_ca = 0; } #if defined(TARGET_PPC64) @@ -164,10 +162,8 @@ void do_addmeo_64 (void) T0 += xer_ca + (-1); xer_ov = ((uint64_t)T1 & ((uint64_t)T1 ^ (uint64_t)T0)) >> 63; xer_so |= xer_ov; - if (likely(T1 != 0)) + if (likely((uint64_t)T1 != 0)) xer_ca = 1; - else - xer_ca = 0; } #endif @@ -312,8 +308,6 @@ void do_subfmeo (void) xer_so |= xer_ov; if (likely((uint32_t)T1 != UINT32_MAX)) xer_ca = 1; - else - xer_ca = 0; } #if defined(TARGET_PPC64) @@ -325,8 +319,6 @@ void do_subfmeo_64 (void) xer_so |= xer_ov; if (likely((uint64_t)T1 != UINT64_MAX)) xer_ca = 1; - else - xer_ca = 0; } #endif ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [Qemu-devel] [PATCH] ppc32 guests: fix computation of XER.{CA, OV} in addme, subfme, mullwo 2008-05-11 0:04 [Qemu-devel] [PATCH] ppc32 guests: fix computation of XER.{CA, OV} in addme, subfme, mullwo Julian Seward 2008-06-17 12:27 ` Aurelien Jarno @ 2008-10-01 21:47 ` Aurelien Jarno 1 sibling, 0 replies; 13+ messages in thread From: Aurelien Jarno @ 2008-10-01 21:47 UTC (permalink / raw) To: qemu-devel On Sun, May 11, 2008 at 02:04:47AM +0200, Julian Seward wrote: > > 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 fixed both problems by applying a mix of your patch and of the patch from Jocelyn Mayer. -- .''`. Aurelien Jarno | GPG: 1024D/F1BCDB73 : :' : Debian developer | Electrical Engineer `. `' aurel32@debian.org | aurelien@aurel32.net `- people.debian.org/~aurel32 | www.aurel32.net ^ permalink raw reply [flat|nested] 13+ messages in thread
end of thread, other threads:[~2008-10-01 21:47 UTC | newest] Thread overview: 13+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2008-05-11 0:04 [Qemu-devel] [PATCH] ppc32 guests: fix computation of XER.{CA, OV} in addme, subfme, mullwo Julian Seward 2008-06-17 12:27 ` Aurelien Jarno 2008-06-17 22:06 ` Julian Seward 2008-06-17 22:53 ` J. Mayer 2008-06-17 23:23 ` Julian Seward 2008-06-18 21:32 ` J. Mayer 2008-06-18 21:39 ` Julian Seward 2008-06-18 22:09 ` J. Mayer 2008-06-18 22:13 ` Tristan Gingold 2008-06-19 7:36 ` Julian Seward 2008-06-19 8:36 ` Tristan Gingold 2008-06-19 9:12 ` J. Mayer 2008-10-01 21:47 ` Aurelien Jarno
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).