diff mbox

PPC: Depend behavior of cmp instructions only on instruction encoding

Message ID 1368019560-25218-1-git-send-email-agraf@suse.de
State New
Headers show

Commit Message

Alexander Graf May 8, 2013, 1:26 p.m. UTC
When running an L=1 cmp instruction on a 64bit PPC CPU with SF off, it
still behaves identical to what it does when SF is on. Remove the implicit
difference in the code.

However, the situation is more complex than that. On 32bit CPUs, L=1
instructions are either treated identical to L=0 instructions (G4) or
treated as illegal instructions (e500mc). Differenciating these cases
is out of scope for the 1.5 release and will follow afterwards. For now
just treat the 32bit CPU, 64bit cmp case as undefined.

Reported-by: Torbjorn Granlund <tg@gmplib.org>
Signed-off-by: Alexander Graf <agraf@suse.de>
---
 target-ppc/translate.c |    8 ++++----
 1 files changed, 4 insertions(+), 4 deletions(-)

Comments

Richard Henderson May 8, 2013, 1:30 p.m. UTC | #1
On 2013-05-08 08:26, Alexander Graf wrote:
> However, the situation is more complex than that. On 32bit CPUs, L=1
> instructions are either treated identical to L=0 instructions (G4) or
> treated as illegal instructions (e500mc). Differenciating these cases
> is out of scope for the 1.5 release and will follow afterwards. For now
> just treat the 32bit CPU, 64bit cmp case as undefined.

Ah ha.  Interesting g4/e500 difference.

Reviewed-by: Richard Henderson <rth@twiddle.net>


r~
Torbjorn Granlund May 8, 2013, 1:49 p.m. UTC | #2
Alexander Graf <agraf@suse.de> writes:

  Reported-by: Torbjorn Granlund <tg@gmplib.org>
  Signed-off-by: Alexander Graf <agraf@suse.de>

Ah, so my original patch was correct after all.
Only the name of the author needed changing, apparently.  :-)

  ---
   target-ppc/translate.c |    8 ++++----
   1 files changed, 4 insertions(+), 4 deletions(-)
  
  diff --git a/target-ppc/translate.c b/target-ppc/translate.c
  index a018616..89a4445 100644
  --- a/target-ppc/translate.c
  +++ b/target-ppc/translate.c
  @@ -675,7 +675,7 @@ static inline void gen_set_Rc0(DisasContext *ctx, TCGv reg)
   /* cmp */
   static void gen_cmp(DisasContext *ctx)
   {
  -    if (NARROW_MODE(ctx) || !(ctx->opcode & 0x00200000)) {
  +    if (!(ctx->opcode & 0x00200000)) {
           gen_op_cmp32(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],
                        1, crfD(ctx->opcode));
       } else {
  @@ -687,7 +687,7 @@ static void gen_cmp(DisasContext *ctx)
   /* cmpi */
   static void gen_cmpi(DisasContext *ctx)
   {
  -    if (NARROW_MODE(ctx) || !(ctx->opcode & 0x00200000)) {
  +    if (!(ctx->opcode & 0x00200000)) {
           gen_op_cmpi32(cpu_gpr[rA(ctx->opcode)], SIMM(ctx->opcode),
                         1, crfD(ctx->opcode));
       } else {
  @@ -699,7 +699,7 @@ static void gen_cmpi(DisasContext *ctx)
   /* cmpl */
   static void gen_cmpl(DisasContext *ctx)
   {
  -    if (NARROW_MODE(ctx) || !(ctx->opcode & 0x00200000)) {
  +    if (!(ctx->opcode & 0x00200000)) {
           gen_op_cmp32(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],
                        0, crfD(ctx->opcode));
       } else {
  @@ -711,7 +711,7 @@ static void gen_cmpl(DisasContext *ctx)
   /* cmpli */
   static void gen_cmpli(DisasContext *ctx)
   {
  -    if (NARROW_MODE(ctx) || !(ctx->opcode & 0x00200000)) {
  +    if (!(ctx->opcode & 0x00200000)) {
           gen_op_cmpi32(cpu_gpr[rA(ctx->opcode)], UIMM(ctx->opcode),
                         0, crfD(ctx->opcode));
       } else {

Hopefully my cmp speedup patch will be reposted under a new name and
then included.
Alexander Graf May 8, 2013, 1:51 p.m. UTC | #3
On 08.05.2013, at 15:49, Torbjorn Granlund wrote:

> Alexander Graf <agraf@suse.de> writes:
> 
>  Reported-by: Torbjorn Granlund <tg@gmplib.org>
>  Signed-off-by: Alexander Graf <agraf@suse.de>
> 
> Ah, so my original patch was correct after all.
> Only the name of the author needed changing, apparently.  :-)

No, I need a patch header and a Signed-off-by as well as understanding of the full problem space. If you can repost your patch with a proper header and SOB line I'll happily pull that into the queue.


Alex
Aurelien Jarno May 8, 2013, 2:25 p.m. UTC | #4
On Wed, May 08, 2013 at 03:26:00PM +0200, Alexander Graf wrote:
> When running an L=1 cmp instruction on a 64bit PPC CPU with SF off, it
> still behaves identical to what it does when SF is on. Remove the implicit
> difference in the code.
> 
> However, the situation is more complex than that. On 32bit CPUs, L=1
> instructions are either treated identical to L=0 instructions (G4) or
> treated as illegal instructions (e500mc). Differenciating these cases
> is out of scope for the 1.5 release and will follow afterwards. For now
> just treat the 32bit CPU, 64bit cmp case as undefined.
> 
> Reported-by: Torbjorn Granlund <tg@gmplib.org>
> Signed-off-by: Alexander Graf <agraf@suse.de>
> ---
>  target-ppc/translate.c |    8 ++++----
>  1 files changed, 4 insertions(+), 4 deletions(-)
> 
> diff --git a/target-ppc/translate.c b/target-ppc/translate.c
> index a018616..89a4445 100644
> --- a/target-ppc/translate.c
> +++ b/target-ppc/translate.c
> @@ -675,7 +675,7 @@ static inline void gen_set_Rc0(DisasContext *ctx, TCGv reg)
>  /* cmp */
>  static void gen_cmp(DisasContext *ctx)
>  {
> -    if (NARROW_MODE(ctx) || !(ctx->opcode & 0x00200000)) {
> +    if (!(ctx->opcode & 0x00200000)) {
>          gen_op_cmp32(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],
>                       1, crfD(ctx->opcode));
>      } else {
> @@ -687,7 +687,7 @@ static void gen_cmp(DisasContext *ctx)
>  /* cmpi */
>  static void gen_cmpi(DisasContext *ctx)
>  {
> -    if (NARROW_MODE(ctx) || !(ctx->opcode & 0x00200000)) {
> +    if (!(ctx->opcode & 0x00200000)) {
>          gen_op_cmpi32(cpu_gpr[rA(ctx->opcode)], SIMM(ctx->opcode),
>                        1, crfD(ctx->opcode));
>      } else {
> @@ -699,7 +699,7 @@ static void gen_cmpi(DisasContext *ctx)
>  /* cmpl */
>  static void gen_cmpl(DisasContext *ctx)
>  {
> -    if (NARROW_MODE(ctx) || !(ctx->opcode & 0x00200000)) {
> +    if (!(ctx->opcode & 0x00200000)) {
>          gen_op_cmp32(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],
>                       0, crfD(ctx->opcode));
>      } else {
> @@ -711,7 +711,7 @@ static void gen_cmpl(DisasContext *ctx)
>  /* cmpli */
>  static void gen_cmpli(DisasContext *ctx)
>  {
> -    if (NARROW_MODE(ctx) || !(ctx->opcode & 0x00200000)) {
> +    if (!(ctx->opcode & 0x00200000)) {
>          gen_op_cmpi32(cpu_gpr[rA(ctx->opcode)], UIMM(ctx->opcode),
>                        0, crfD(ctx->opcode));
>      } else {

Reviewed-by: Aurelien Jarno <aurelien@aurel32.net>

That said this does implement neither the specification nor the silicon
behaviour. This is fine for 1.5 as we are in freeze period, but this 
should be fixed for the 1.6 release.
Torbjorn Granlund May 8, 2013, 2:48 p.m. UTC | #5
Aurelien Jarno <aurelien@aurel32.net> writes:

  That said this does implement neither the specification nor the silicon
  behaviour. This is fine for 1.5 as we are in freeze period, but this 
  should be fixed for the 1.6 release.

I talked to IBM now.  Reserved fields should be ignored by hardware.

The architecture owner is IBM, not Freescale.  That Freescale deviates
from the architecture, is something that you may decide to ignore,
unless it is vital for qemu's behaviour in practice.

I very much doubt that L = 1 often, for code targeting a 32-bit
processor.

Trying to mimic decoding flaws on a per-processor basis, is going to
take a lot of research, and will be prone to errors.

So as far as I can tell, the patch is correct as per the architecture
specification.

One caveat though: Does 32-bit implementations define the SF bit, or
else, does qemu define it and make sure it is 0 for 32-bit emulation?
If not, the patch might cause trouble.

Congrats, you read a "user message" until the last line.  :-)
Aurelien Jarno May 8, 2013, 3:04 p.m. UTC | #6
On Wed, May 08, 2013 at 04:48:22PM +0200, Torbjorn Granlund wrote:
> Aurelien Jarno <aurelien@aurel32.net> writes:
> 
>   That said this does implement neither the specification nor the silicon
>   behaviour. This is fine for 1.5 as we are in freeze period, but this 
>   should be fixed for the 1.6 release.
> 
> I talked to IBM now.  Reserved fields should be ignored by hardware.

As it seems you have good contact with IBM, could you please ask them
to fix their manuals?

> The architecture owner is IBM, not Freescale.  That Freescale deviates
> from the architecture, is something that you may decide to ignore,
> unless it is vital for qemu's behaviour in practice.

At least Freescale CPUs matches what IBM documentation says. IBM CPUs
doesn't.

> I very much doubt that L = 1 often, for code targeting a 32-bit
> processor.
> 
> Trying to mimic decoding flaws on a per-processor basis, is going to
> take a lot of research, and will be prone to errors.
> 
> So as far as I can tell, the patch is correct as per the architecture
> specification.

No it's not correct, it doesn't match neither Freescale nor IBM
behaviour. It also means the same code executed on a 32-bit emulated CPU
run with qemu-system-ppc will behave differently than when run with
qemu-system-ppc64. This is fine for now as we are in freeze period, but
should be fixed afterwards.

> One caveat though: Does 32-bit implementations define the SF bit, or
> else, does qemu define it and make sure it is 0 for 32-bit emulation?
> If not, the patch might cause trouble.

QEMU makes sure it is 0 for 32-bit CPU.

> Congrats, you read a "user message" until the last line.  :-)
> 

Like I did for the previous one. Would be nice if you can do the same.
Torbjorn Granlund May 8, 2013, 3:54 p.m. UTC | #7
Aurelien Jarno <aurelien@aurel32.net> writes:

  As it seems you have good contact with IBM, could you please ask them
  to fix their manuals?
  
What flaw have your found?

  At least Freescale CPUs match what IBM documentation says.

Which ones?  Freescale 7447 and Freescale e500 disagree.  (Or at least
some versions of these chips, perhaps newer e500 steppings ignore the L
bit.)

  IBM CPUs don't.
  
Which ones?

  No it's not correct, it doesn't match neither Freescale nor IBM
  behaviour. It also means the same code executed on a 32-bit emulated CPU
  run with qemu-system-ppc will behave differently than when run with
  qemu-system-ppc64. This is fine for now as we are in freeze period, but
  should be fixed afterwards.
  
I think one should check if it is a 64-bit CPU vs 32-bit CPU, as your
patch did.  (If I read it correctly; while I am an expert in the area, I
am very little familiar with qemu's innards.)  Except that it should
probably not cast an exception (but I think either way there is no
calamity).
Aurelien Jarno May 8, 2013, 4:16 p.m. UTC | #8
On Wed, May 08, 2013 at 05:54:27PM +0200, Torbjorn Granlund wrote:
> Aurelien Jarno <aurelien@aurel32.net> writes:
> 
>   As it seems you have good contact with IBM, could you please ask them
>   to fix their manuals?
>   
> What flaw have your found?

Don't people read what I write? From one of my previous email:

Quoting the "IBM PowerPC Microprocessor Family: The Programming                                                                                                                       
Environments Manual for 32 and 64-bit Microprocessors":                                                                                                                               

| Note: In 32-bit implementations, if L = 1 the instruction form is invalid.

This doesn't match what your contact says.

>   At least Freescale CPUs match what IBM documentation says.
> 
> Which ones?  Freescale 7447 and Freescale e500 disagree.  (Or at least
> some versions of these chips, perhaps newer e500 steppings ignore the L
> bit.)

The e500 CPU doesn't ignore the L bit, like the IBM manual says.

>   IBM CPUs don't.
>   
> Which ones?

The one from your contact saying that reserved fields should be ignored
by hardware.

>   No it's not correct, it doesn't match neither Freescale nor IBM
>   behaviour. It also means the same code executed on a 32-bit emulated CPU
>   run with qemu-system-ppc will behave differently than when run with
>   qemu-system-ppc64. This is fine for now as we are in freeze period, but
>   should be fixed afterwards.
>   
> I think one should check if it is a 64-bit CPU vs 32-bit CPU, as your
> patch did.  (If I read it correctly; while I am an expert in the area, I
> am very little familiar with qemu's innards.)  Except that it should
> probably not cast an exception (but I think either way there is no
> calamity).
> 

Looking more into details about the issue. Old *PowerPC* manuals (the
one from the 7447 era) clearly states that the L bit must trigger an
invalid instruction exception.

*POWER* manuals states that reserved fields in instructions are ignored by
on Server environment, but not on Embedded environment, though it is now
phased-in on the latter.

In short everybody is correct, it only depends on the CPU.
Torbjorn Granlund May 8, 2013, 4:31 p.m. UTC | #9
Aurelien Jarno <aurelien@aurel32.net> writes:

  Don't people read what I write? From one of my previous email:
  
I do...and even scrutinise it for grammar errors.  ;-)

  Quoting the "IBM PowerPC Microprocessor Family: The Programming                                                                                                                       
  Environments Manual for 32 and 64-bit Microprocessors":                                                                                                                               
  | Note: In 32-bit implementations, if L = 1 the instruction form is invalid.
  
  This doesn't match what your contact says.
  
I think you're reading too much into that wording.

It is perhaps intended to mean that L = 1 makes no sense, that it will
not have the desired effect.

(I don't much like the way IBM's powerpc docs are written.  They ought
to be much more unambiguous, and could be less wordy.)
diff mbox

Patch

diff --git a/target-ppc/translate.c b/target-ppc/translate.c
index a018616..89a4445 100644
--- a/target-ppc/translate.c
+++ b/target-ppc/translate.c
@@ -675,7 +675,7 @@  static inline void gen_set_Rc0(DisasContext *ctx, TCGv reg)
 /* cmp */
 static void gen_cmp(DisasContext *ctx)
 {
-    if (NARROW_MODE(ctx) || !(ctx->opcode & 0x00200000)) {
+    if (!(ctx->opcode & 0x00200000)) {
         gen_op_cmp32(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],
                      1, crfD(ctx->opcode));
     } else {
@@ -687,7 +687,7 @@  static void gen_cmp(DisasContext *ctx)
 /* cmpi */
 static void gen_cmpi(DisasContext *ctx)
 {
-    if (NARROW_MODE(ctx) || !(ctx->opcode & 0x00200000)) {
+    if (!(ctx->opcode & 0x00200000)) {
         gen_op_cmpi32(cpu_gpr[rA(ctx->opcode)], SIMM(ctx->opcode),
                       1, crfD(ctx->opcode));
     } else {
@@ -699,7 +699,7 @@  static void gen_cmpi(DisasContext *ctx)
 /* cmpl */
 static void gen_cmpl(DisasContext *ctx)
 {
-    if (NARROW_MODE(ctx) || !(ctx->opcode & 0x00200000)) {
+    if (!(ctx->opcode & 0x00200000)) {
         gen_op_cmp32(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],
                      0, crfD(ctx->opcode));
     } else {
@@ -711,7 +711,7 @@  static void gen_cmpl(DisasContext *ctx)
 /* cmpli */
 static void gen_cmpli(DisasContext *ctx)
 {
-    if (NARROW_MODE(ctx) || !(ctx->opcode & 0x00200000)) {
+    if (!(ctx->opcode & 0x00200000)) {
         gen_op_cmpi32(cpu_gpr[rA(ctx->opcode)], UIMM(ctx->opcode),
                       0, crfD(ctx->opcode));
     } else {