aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/lib/sstep.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/lib/sstep.c')
-rw-r--r--arch/powerpc/lib/sstep.c20
1 files changed, 20 insertions, 0 deletions
diff --git a/arch/powerpc/lib/sstep.c b/arch/powerpc/lib/sstep.c
index f208f560aecd..70274b7b4773 100644
--- a/arch/powerpc/lib/sstep.c
+++ b/arch/powerpc/lib/sstep.c
@@ -31,6 +31,8 @@ extern char system_call_common[];
31#define XER_SO 0x80000000U 31#define XER_SO 0x80000000U
32#define XER_OV 0x40000000U 32#define XER_OV 0x40000000U
33#define XER_CA 0x20000000U 33#define XER_CA 0x20000000U
34#define XER_OV32 0x00080000U
35#define XER_CA32 0x00040000U
34 36
35#ifdef CONFIG_PPC_FPU 37#ifdef CONFIG_PPC_FPU
36/* 38/*
@@ -962,6 +964,16 @@ static nokprobe_inline void set_cr0(const struct pt_regs *regs,
962 op->ccval |= 0x20000000; 964 op->ccval |= 0x20000000;
963} 965}
964 966
967static nokprobe_inline void set_ca32(struct instruction_op *op, bool val)
968{
969 if (cpu_has_feature(CPU_FTR_ARCH_300)) {
970 if (val)
971 op->xerval |= XER_CA32;
972 else
973 op->xerval &= ~XER_CA32;
974 }
975}
976
965static nokprobe_inline void add_with_carry(const struct pt_regs *regs, 977static nokprobe_inline void add_with_carry(const struct pt_regs *regs,
966 struct instruction_op *op, int rd, 978 struct instruction_op *op, int rd,
967 unsigned long val1, unsigned long val2, 979 unsigned long val1, unsigned long val2,
@@ -985,6 +997,9 @@ static nokprobe_inline void add_with_carry(const struct pt_regs *regs,
985 op->xerval |= XER_CA; 997 op->xerval |= XER_CA;
986 else 998 else
987 op->xerval &= ~XER_CA; 999 op->xerval &= ~XER_CA;
1000
1001 set_ca32(op, (unsigned int)val < (unsigned int)val1 ||
1002 (carry_in && (unsigned int)val == (unsigned int)val1));
988} 1003}
989 1004
990static nokprobe_inline void do_cmp_signed(const struct pt_regs *regs, 1005static nokprobe_inline void do_cmp_signed(const struct pt_regs *regs,
@@ -1791,6 +1806,7 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
1791 op->xerval |= XER_CA; 1806 op->xerval |= XER_CA;
1792 else 1807 else
1793 op->xerval &= ~XER_CA; 1808 op->xerval &= ~XER_CA;
1809 set_ca32(op, op->xerval & XER_CA);
1794 goto logical_done; 1810 goto logical_done;
1795 1811
1796 case 824: /* srawi */ 1812 case 824: /* srawi */
@@ -1803,6 +1819,7 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
1803 op->xerval |= XER_CA; 1819 op->xerval |= XER_CA;
1804 else 1820 else
1805 op->xerval &= ~XER_CA; 1821 op->xerval &= ~XER_CA;
1822 set_ca32(op, op->xerval & XER_CA);
1806 goto logical_done; 1823 goto logical_done;
1807 1824
1808#ifdef __powerpc64__ 1825#ifdef __powerpc64__
@@ -1832,6 +1849,7 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
1832 op->xerval |= XER_CA; 1849 op->xerval |= XER_CA;
1833 else 1850 else
1834 op->xerval &= ~XER_CA; 1851 op->xerval &= ~XER_CA;
1852 set_ca32(op, op->xerval & XER_CA);
1835 goto logical_done; 1853 goto logical_done;
1836 1854
1837 case 826: /* sradi with sh_5 = 0 */ 1855 case 826: /* sradi with sh_5 = 0 */
@@ -1845,6 +1863,7 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
1845 op->xerval |= XER_CA; 1863 op->xerval |= XER_CA;
1846 else 1864 else
1847 op->xerval &= ~XER_CA; 1865 op->xerval &= ~XER_CA;
1866 set_ca32(op, op->xerval & XER_CA);
1848 goto logical_done; 1867 goto logical_done;
1849#endif /* __powerpc64__ */ 1868#endif /* __powerpc64__ */
1850 1869
@@ -2698,6 +2717,7 @@ void emulate_update_regs(struct pt_regs *regs, struct instruction_op *op)
2698 } 2717 }
2699 regs->nip = next_pc; 2718 regs->nip = next_pc;
2700} 2719}
2720NOKPROBE_SYMBOL(emulate_update_regs);
2701 2721
2702/* 2722/*
2703 * Emulate a previously-analysed load or store instruction. 2723 * Emulate a previously-analysed load or store instruction.