Commit dc39c1d6 authored by Sandipan Das's avatar Sandipan Das Committed by Michael Ellerman

powerpc/lib/sstep: Fix fixed-point arithmetic instructions that set CA32

There are existing fixed-point arithmetic instructions that always set the
CA bit of XER to reflect the carry out of bit 0 in 64-bit mode and out of
bit 32 in 32-bit mode. In ISA v3.0, these instructions also always set the
CA32 bit of XER to reflect the carry out of bit 32.

This fixes the emulated behaviour of such instructions when running on a
system that is compliant with POWER ISA v3.0. The following instructions
are affected:
  * Add Immediate Carrying (addic)
  * Add Immediate Carrying and Record (addic.)
  * Subtract From Immediate Carrying (subfic)
  * Add Carrying (addc[.])
  * Subtract From Carrying (subfc[.])
  * Add Extended (adde[.])
  * Subtract From Extended (subfe[.])
  * Add to Minus One Extended (addme[.])
  * Subtract From Minus One Extended (subfme[.])
  * Add to Zero Extended (addze[.])
  * Subtract From Zero Extended (subfze[.])

Fixes: 0016a4cf ("powerpc: Emulate most Book I instructions in emulate_step()")
Signed-off-by: default avatarSandipan Das <sandipan@linux.vnet.ibm.com>
Signed-off-by: default avatarMichael Ellerman <mpe@ellerman.id.au>
parent 924c8feb
...@@ -964,6 +964,16 @@ static nokprobe_inline void set_cr0(const struct pt_regs *regs, ...@@ -964,6 +964,16 @@ static nokprobe_inline void set_cr0(const struct pt_regs *regs,
op->ccval |= 0x20000000; op->ccval |= 0x20000000;
} }
static nokprobe_inline void set_ca32(struct instruction_op *op, bool val)
{
if (cpu_has_feature(CPU_FTR_ARCH_300)) {
if (val)
op->xerval |= XER_CA32;
else
op->xerval &= ~XER_CA32;
}
}
static nokprobe_inline void add_with_carry(const struct pt_regs *regs, static nokprobe_inline void add_with_carry(const struct pt_regs *regs,
struct instruction_op *op, int rd, struct instruction_op *op, int rd,
unsigned long val1, unsigned long val2, unsigned long val1, unsigned long val2,
...@@ -987,6 +997,9 @@ static nokprobe_inline void add_with_carry(const struct pt_regs *regs, ...@@ -987,6 +997,9 @@ static nokprobe_inline void add_with_carry(const struct pt_regs *regs,
op->xerval |= XER_CA; op->xerval |= XER_CA;
else else
op->xerval &= ~XER_CA; op->xerval &= ~XER_CA;
set_ca32(op, (unsigned int)val < (unsigned int)val1 ||
(carry_in && (unsigned int)val == (unsigned int)val1));
} }
static nokprobe_inline void do_cmp_signed(const struct pt_regs *regs, static nokprobe_inline void do_cmp_signed(const struct pt_regs *regs,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment