qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Qemu-devel] [PATCH] ppc32 guests: fix computation of XER.{CA, OV} i


From: Julian Seward
Subject: Re: [Qemu-devel] [PATCH] ppc32 guests: fix computation of XER.{CA, OV} in addme, subfme, mullwo
Date: Wed, 18 Jun 2008 00:06:51 +0200
User-agent: KMail/1.9.5

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;
}





reply via email to

[Prev in Thread] Current Thread [Next in Thread]