All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/48] FPU and FP emulation clean-ups, fixes and feature updates
@ 2015-04-03 22:23 Maciej W. Rozycki
  2015-04-03 22:23 ` [PATCH 01/48] doc: kernel-parameters.txt: Mark `nofpu' for MIPS too Maciej W. Rozycki
                   ` (46 more replies)
  0 siblings, 47 replies; 62+ messages in thread
From: Maciej W. Rozycki @ 2015-04-03 22:23 UTC (permalink / raw)
  To: Ralf Baechle; +Cc: linux-mips

Hi,

 These are fixes to address code structuring and coding style problems 
and then bug fixes I discovered in the course of implementing an 
upcoming FPU feature.  There are some minor feature updates too.  They 
are related to one another to a various extent, sometimes very loosely, 
but I decided to keep them as a series because there is a lot of 
syntactical overlap, as changes are made in steps, one issue at a time.  
Keeping them in order guarantees that they apply on top of one another.

 Clean-ups come first as they should be completely uncontroversial, 
followed by restructuring, bug fixes and new features.

  Maciej

^ permalink raw reply	[flat|nested] 62+ messages in thread

* [PATCH 01/48] doc: kernel-parameters.txt: Mark `nofpu' for MIPS too
  2015-04-03 22:23 [PATCH 00/48] FPU and FP emulation clean-ups, fixes and feature updates Maciej W. Rozycki
@ 2015-04-03 22:23 ` Maciej W. Rozycki
  2015-04-03 22:23 ` [PATCH 02/48] MIPS: mipsregs.h: Remove broken comments Maciej W. Rozycki
                   ` (45 subsequent siblings)
  46 siblings, 0 replies; 62+ messages in thread
From: Maciej W. Rozycki @ 2015-04-03 22:23 UTC (permalink / raw)
  To: Ralf Baechle; +Cc: linux-mips

The MIPS port has supported this option since forever, long before SH 
was even in plans.

Signed-off-by: Maciej W. Rozycki <macro@linux-mips.org>
---
linux-mips-nofpu.diff
Index: linux/Documentation/kernel-parameters.txt
===================================================================
--- linux.orig/Documentation/kernel-parameters.txt	2015-04-02 20:27:51.263153000 +0100
+++ linux/Documentation/kernel-parameters.txt	2015-04-02 20:27:51.477157000 +0100
@@ -2321,7 +2321,7 @@ bytes respectively. Such letter suffixes
 			noexec32=off: disable non-executable mappings
 				read implies executable mappings
 
-	nofpu		[SH] Disable hardware FPU at boot time.
+	nofpu		[MIPS,SH] Disable hardware FPU at boot time.
 
 	nofxsr		[BUGS=X86-32] Disables x86 floating point extended
 			register save and restore. The kernel will only save

^ permalink raw reply	[flat|nested] 62+ messages in thread

* [PATCH 02/48] MIPS: mipsregs.h: Remove broken comments
  2015-04-03 22:23 [PATCH 00/48] FPU and FP emulation clean-ups, fixes and feature updates Maciej W. Rozycki
  2015-04-03 22:23 ` [PATCH 01/48] doc: kernel-parameters.txt: Mark `nofpu' for MIPS too Maciej W. Rozycki
@ 2015-04-03 22:23 ` Maciej W. Rozycki
  2015-04-03 22:23 ` [PATCH 03/48] MIPS: mipsregs.h: Reorder CP1 macro definitions Maciej W. Rozycki
                   ` (44 subsequent siblings)
  46 siblings, 0 replies; 62+ messages in thread
From: Maciej W. Rozycki @ 2015-04-03 22:23 UTC (permalink / raw)
  To: Ralf Baechle; +Cc: linux-mips

Remove a duplicate FPU Status Register reference that has been there 
since forever and a mistakenly copied and pasted R4xx0 manual reference.

Signed-off-by: Maciej W. Rozycki <macro@linux-mips.org>
---
linux-mips-regs-fcsr-comment.diff
Index: linux/arch/mips/include/asm/mipsregs.h
===================================================================
--- linux.orig/arch/mips/include/asm/mipsregs.h	2015-04-02 20:18:53.073537000 +0100
+++ linux/arch/mips/include/asm/mipsregs.h	2015-04-02 20:27:51.667161000 +0100
@@ -120,10 +120,6 @@
 /*
  * FPU Status Register Values
  */
-/*
- * Status Register Values
- */
-
 #define FPU_CSR_FLUSH	0x01000000	/* flush denormalised results to 0 */
 #define FPU_CSR_COND	0x00800000	/* $fcc0 */
 #define FPU_CSR_COND0	0x00800000	/* $fcc0 */
@@ -425,8 +421,6 @@
 
 /*
  * Bitfields and bit numbers in the coprocessor 0 IntCtl register. (MIPSR2)
- *
- * Refer to your MIPS R4xx0 manual, chapter 5 for explanation.
  */
 #define INTCTLB_IPPCI		26
 #define INTCTLF_IPPCI		(_ULCAST_(7) << INTCTLB_IPPCI)

^ permalink raw reply	[flat|nested] 62+ messages in thread

* [PATCH 03/48] MIPS: mipsregs.h: Reorder CP1 macro definitions
  2015-04-03 22:23 [PATCH 00/48] FPU and FP emulation clean-ups, fixes and feature updates Maciej W. Rozycki
  2015-04-03 22:23 ` [PATCH 01/48] doc: kernel-parameters.txt: Mark `nofpu' for MIPS too Maciej W. Rozycki
  2015-04-03 22:23 ` [PATCH 02/48] MIPS: mipsregs.h: Remove broken comments Maciej W. Rozycki
@ 2015-04-03 22:23 ` Maciej W. Rozycki
  2015-04-03 22:23 ` [PATCH 04/48] MIPS: mipsregs.h: Move TX39 macros out of the way Maciej W. Rozycki
                   ` (43 subsequent siblings)
  46 siblings, 0 replies; 62+ messages in thread
From: Maciej W. Rozycki @ 2015-04-03 22:23 UTC (permalink / raw)
  To: Ralf Baechle; +Cc: linux-mips

Originally CP1 macros were placed between CP0 register name macros and 
CP0 register value macros.  As changes were applied to the header the 
position of CP1 macros gradually has become more and more arbitrary and 
two separate blocks were created.  This may only cause confusion.

Move them out of the way then and place together after all the CP0 
macros.  No semantic change.

Signed-off-by: Maciej W. Rozycki <macro@linux-mips.org>
---
Ralf,

 FYI, checkpatch.pl has bogus issues with this change:

ERROR: Macros with complex values should be enclosed in parentheses
#99: FILE: arch/mips/include/asm/mipsregs.h:680:
+#define CP1_REVISION   $0

ERROR: Macros with complex values should be enclosed in parentheses
#100: FILE: arch/mips/include/asm/mipsregs.h:681:
+#define CP1_STATUS     $31

I hope that's not going to disturb your patch handling flow.

  Maciej

linux-mips-regs-cp1.diff
Index: linux/arch/mips/include/asm/mipsregs.h
===================================================================
--- linux.orig/arch/mips/include/asm/mipsregs.h	2015-04-02 20:27:51.667161000 +0100
+++ linux/arch/mips/include/asm/mipsregs.h	2015-04-02 20:27:51.855157000 +0100
@@ -111,66 +111,6 @@
  */
 #define CP0_TX39_CACHE	$7
 
-/*
- * Coprocessor 1 (FPU) register names
- */
-#define CP1_REVISION   $0
-#define CP1_STATUS     $31
-
-/*
- * FPU Status Register Values
- */
-#define FPU_CSR_FLUSH	0x01000000	/* flush denormalised results to 0 */
-#define FPU_CSR_COND	0x00800000	/* $fcc0 */
-#define FPU_CSR_COND0	0x00800000	/* $fcc0 */
-#define FPU_CSR_COND1	0x02000000	/* $fcc1 */
-#define FPU_CSR_COND2	0x04000000	/* $fcc2 */
-#define FPU_CSR_COND3	0x08000000	/* $fcc3 */
-#define FPU_CSR_COND4	0x10000000	/* $fcc4 */
-#define FPU_CSR_COND5	0x20000000	/* $fcc5 */
-#define FPU_CSR_COND6	0x40000000	/* $fcc6 */
-#define FPU_CSR_COND7	0x80000000	/* $fcc7 */
-
-/*
- * Bits 18 - 20 of the FPU Status Register will be read as 0,
- * and should be written as zero.
- */
-#define FPU_CSR_RSVD	0x001c0000
-
-/*
- * X the exception cause indicator
- * E the exception enable
- * S the sticky/flag bit
-*/
-#define FPU_CSR_ALL_X	0x0003f000
-#define FPU_CSR_UNI_X	0x00020000
-#define FPU_CSR_INV_X	0x00010000
-#define FPU_CSR_DIV_X	0x00008000
-#define FPU_CSR_OVF_X	0x00004000
-#define FPU_CSR_UDF_X	0x00002000
-#define FPU_CSR_INE_X	0x00001000
-
-#define FPU_CSR_ALL_E	0x00000f80
-#define FPU_CSR_INV_E	0x00000800
-#define FPU_CSR_DIV_E	0x00000400
-#define FPU_CSR_OVF_E	0x00000200
-#define FPU_CSR_UDF_E	0x00000100
-#define FPU_CSR_INE_E	0x00000080
-
-#define FPU_CSR_ALL_S	0x0000007c
-#define FPU_CSR_INV_S	0x00000040
-#define FPU_CSR_DIV_S	0x00000020
-#define FPU_CSR_OVF_S	0x00000010
-#define FPU_CSR_UDF_S	0x00000008
-#define FPU_CSR_INE_S	0x00000004
-
-/* Bits 0 and 1 of FPU Status Register specify the rounding mode */
-#define FPU_CSR_RM	0x00000003
-#define FPU_CSR_RN	0x0	/* nearest */
-#define FPU_CSR_RZ	0x1	/* towards zero */
-#define FPU_CSR_RU	0x2	/* towards +Infinity */
-#define FPU_CSR_RD	0x3	/* towards -Infinity */
-
 
 /*
  * Values for PageMask register
@@ -683,18 +623,6 @@
 #define MIPS_CMGCRF_BASE	(~_ULCAST_((1 << MIPS_CMGCRB_BASE) - 1))
 
 /*
- * Bits in the MIPS32/64 coprocessor 1 (FPU) revision register.
- */
-#define MIPS_FPIR_S		(_ULCAST_(1) << 16)
-#define MIPS_FPIR_D		(_ULCAST_(1) << 17)
-#define MIPS_FPIR_PS		(_ULCAST_(1) << 18)
-#define MIPS_FPIR_3D		(_ULCAST_(1) << 19)
-#define MIPS_FPIR_W		(_ULCAST_(1) << 20)
-#define MIPS_FPIR_L		(_ULCAST_(1) << 21)
-#define MIPS_FPIR_F64		(_ULCAST_(1) << 22)
-#define MIPS_FPIR_FREP		(_ULCAST_(1) << 29)
-
-/*
  * Bits in the MIPS32 Memory Segmentation registers.
  */
 #define MIPS_SEGCFG_PA_SHIFT	9
@@ -745,6 +673,81 @@
 #define MIPS_PWCTL_PSN_SHIFT	0
 #define MIPS_PWCTL_PSN_MASK	0x0000003f
 
+
+/*
+ * Coprocessor 1 (FPU) register names
+ */
+#define CP1_REVISION   $0
+#define CP1_STATUS     $31
+
+
+/*
+ * Bits in the MIPS32/64 coprocessor 1 (FPU) revision register.
+ */
+#define MIPS_FPIR_S		(_ULCAST_(1) << 16)
+#define MIPS_FPIR_D		(_ULCAST_(1) << 17)
+#define MIPS_FPIR_PS		(_ULCAST_(1) << 18)
+#define MIPS_FPIR_3D		(_ULCAST_(1) << 19)
+#define MIPS_FPIR_W		(_ULCAST_(1) << 20)
+#define MIPS_FPIR_L		(_ULCAST_(1) << 21)
+#define MIPS_FPIR_F64		(_ULCAST_(1) << 22)
+#define MIPS_FPIR_FREP		(_ULCAST_(1) << 29)
+
+/*
+ * FPU Status Register Values
+ */
+#define FPU_CSR_FLUSH	0x01000000	/* flush denormalised results to 0 */
+#define FPU_CSR_COND	0x00800000	/* $fcc0 */
+#define FPU_CSR_COND0	0x00800000	/* $fcc0 */
+#define FPU_CSR_COND1	0x02000000	/* $fcc1 */
+#define FPU_CSR_COND2	0x04000000	/* $fcc2 */
+#define FPU_CSR_COND3	0x08000000	/* $fcc3 */
+#define FPU_CSR_COND4	0x10000000	/* $fcc4 */
+#define FPU_CSR_COND5	0x20000000	/* $fcc5 */
+#define FPU_CSR_COND6	0x40000000	/* $fcc6 */
+#define FPU_CSR_COND7	0x80000000	/* $fcc7 */
+
+/*
+ * Bits 18 - 20 of the FPU Status Register will be read as 0,
+ * and should be written as zero.
+ */
+#define FPU_CSR_RSVD	0x001c0000
+
+/*
+ * X the exception cause indicator
+ * E the exception enable
+ * S the sticky/flag bit
+*/
+#define FPU_CSR_ALL_X	0x0003f000
+#define FPU_CSR_UNI_X	0x00020000
+#define FPU_CSR_INV_X	0x00010000
+#define FPU_CSR_DIV_X	0x00008000
+#define FPU_CSR_OVF_X	0x00004000
+#define FPU_CSR_UDF_X	0x00002000
+#define FPU_CSR_INE_X	0x00001000
+
+#define FPU_CSR_ALL_E	0x00000f80
+#define FPU_CSR_INV_E	0x00000800
+#define FPU_CSR_DIV_E	0x00000400
+#define FPU_CSR_OVF_E	0x00000200
+#define FPU_CSR_UDF_E	0x00000100
+#define FPU_CSR_INE_E	0x00000080
+
+#define FPU_CSR_ALL_S	0x0000007c
+#define FPU_CSR_INV_S	0x00000040
+#define FPU_CSR_DIV_S	0x00000020
+#define FPU_CSR_OVF_S	0x00000010
+#define FPU_CSR_UDF_S	0x00000008
+#define FPU_CSR_INE_S	0x00000004
+
+/* Bits 0 and 1 of FPU Status Register specify the rounding mode */
+#define FPU_CSR_RM	0x00000003
+#define FPU_CSR_RN	0x0	/* nearest */
+#define FPU_CSR_RZ	0x1	/* towards zero */
+#define FPU_CSR_RU	0x2	/* towards +Infinity */
+#define FPU_CSR_RD	0x3	/* towards -Infinity */
+
+
 #ifndef __ASSEMBLY__
 
 /*

^ permalink raw reply	[flat|nested] 62+ messages in thread

* [PATCH 04/48] MIPS: mipsregs.h: Move TX39 macros out of the way
  2015-04-03 22:23 [PATCH 00/48] FPU and FP emulation clean-ups, fixes and feature updates Maciej W. Rozycki
                   ` (2 preceding siblings ...)
  2015-04-03 22:23 ` [PATCH 03/48] MIPS: mipsregs.h: Reorder CP1 macro definitions Maciej W. Rozycki
@ 2015-04-03 22:23 ` Maciej W. Rozycki
  2015-04-03 22:23 ` [PATCH 05/48] MIPS: mipsregs.h: Reindent CP0 Cause macros Maciej W. Rozycki
                   ` (42 subsequent siblings)
  46 siblings, 0 replies; 62+ messages in thread
From: Maciej W. Rozycki @ 2015-04-03 22:23 UTC (permalink / raw)
  To: Ralf Baechle; +Cc: linux-mips

TX39 CP0 Configuration Register 3 macro definitions have been randomly 
thrown in the middle of a block of CP0 Status register value macros.  
Move them to the end of the whole CP0 register value macro block, 
complementing the location of the TX39 Cache register name macro at the 
end of the CP0 register name macro block.

Signed-off-by: Maciej W. Rozycki <macro@linux-mips.org>
---
linux-mips-regs-tx39-conf.diff
Index: linux/arch/mips/include/asm/mipsregs.h
===================================================================
--- linux.orig/arch/mips/include/asm/mipsregs.h	2015-04-02 20:27:51.855157000 +0100
+++ linux/arch/mips/include/asm/mipsregs.h	2015-04-02 20:27:52.045161000 +0100
@@ -277,39 +277,6 @@
 #define ST0_MX			0x01000000
 
 /*
- * Bitfields in the TX39 family CP0 Configuration Register 3
- */
-#define TX39_CONF_ICS_SHIFT	19
-#define TX39_CONF_ICS_MASK	0x00380000
-#define TX39_CONF_ICS_1KB	0x00000000
-#define TX39_CONF_ICS_2KB	0x00080000
-#define TX39_CONF_ICS_4KB	0x00100000
-#define TX39_CONF_ICS_8KB	0x00180000
-#define TX39_CONF_ICS_16KB	0x00200000
-
-#define TX39_CONF_DCS_SHIFT	16
-#define TX39_CONF_DCS_MASK	0x00070000
-#define TX39_CONF_DCS_1KB	0x00000000
-#define TX39_CONF_DCS_2KB	0x00010000
-#define TX39_CONF_DCS_4KB	0x00020000
-#define TX39_CONF_DCS_8KB	0x00030000
-#define TX39_CONF_DCS_16KB	0x00040000
-
-#define TX39_CONF_CWFON		0x00004000
-#define TX39_CONF_WBON		0x00002000
-#define TX39_CONF_RF_SHIFT	10
-#define TX39_CONF_RF_MASK	0x00000c00
-#define TX39_CONF_DOZE		0x00000200
-#define TX39_CONF_HALT		0x00000100
-#define TX39_CONF_LOCK		0x00000080
-#define TX39_CONF_ICE		0x00000020
-#define TX39_CONF_DCE		0x00000010
-#define TX39_CONF_IRSIZE_SHIFT	2
-#define TX39_CONF_IRSIZE_MASK	0x0000000c
-#define TX39_CONF_DRSIZE_SHIFT	0
-#define TX39_CONF_DRSIZE_MASK	0x00000003
-
-/*
  * Status register bits available in all MIPS CPUs.
  */
 #define ST0_IM			0x0000ff00
@@ -673,6 +640,39 @@
 #define MIPS_PWCTL_PSN_SHIFT	0
 #define MIPS_PWCTL_PSN_MASK	0x0000003f
 
+/*
+ * Bitfields in the TX39 family CP0 Configuration Register 3
+ */
+#define TX39_CONF_ICS_SHIFT	19
+#define TX39_CONF_ICS_MASK	0x00380000
+#define TX39_CONF_ICS_1KB	0x00000000
+#define TX39_CONF_ICS_2KB	0x00080000
+#define TX39_CONF_ICS_4KB	0x00100000
+#define TX39_CONF_ICS_8KB	0x00180000
+#define TX39_CONF_ICS_16KB	0x00200000
+
+#define TX39_CONF_DCS_SHIFT	16
+#define TX39_CONF_DCS_MASK	0x00070000
+#define TX39_CONF_DCS_1KB	0x00000000
+#define TX39_CONF_DCS_2KB	0x00010000
+#define TX39_CONF_DCS_4KB	0x00020000
+#define TX39_CONF_DCS_8KB	0x00030000
+#define TX39_CONF_DCS_16KB	0x00040000
+
+#define TX39_CONF_CWFON		0x00004000
+#define TX39_CONF_WBON		0x00002000
+#define TX39_CONF_RF_SHIFT	10
+#define TX39_CONF_RF_MASK	0x00000c00
+#define TX39_CONF_DOZE		0x00000200
+#define TX39_CONF_HALT		0x00000100
+#define TX39_CONF_LOCK		0x00000080
+#define TX39_CONF_ICE		0x00000020
+#define TX39_CONF_DCE		0x00000010
+#define TX39_CONF_IRSIZE_SHIFT	2
+#define TX39_CONF_IRSIZE_MASK	0x0000000c
+#define TX39_CONF_DRSIZE_SHIFT	0
+#define TX39_CONF_DRSIZE_MASK	0x00000003
+
 
 /*
  * Coprocessor 1 (FPU) register names

^ permalink raw reply	[flat|nested] 62+ messages in thread

* [PATCH 05/48] MIPS: mipsregs.h: Reindent CP0 Cause macros
  2015-04-03 22:23 [PATCH 00/48] FPU and FP emulation clean-ups, fixes and feature updates Maciej W. Rozycki
                   ` (3 preceding siblings ...)
  2015-04-03 22:23 ` [PATCH 04/48] MIPS: mipsregs.h: Move TX39 macros out of the way Maciej W. Rozycki
@ 2015-04-03 22:23 ` Maciej W. Rozycki
  2015-04-03 22:24 ` [PATCH 06/48] MIPS: ieee754.h: Correct comments for special values Maciej W. Rozycki
                   ` (41 subsequent siblings)
  46 siblings, 0 replies; 62+ messages in thread
From: Maciej W. Rozycki @ 2015-04-03 22:23 UTC (permalink / raw)
  To: Ralf Baechle; +Cc: linux-mips

Reindent CP0 Cause macros for a single space after #define, leaving 
extra indentation for individual Interrupt Pending bits as with CP0 
Status register's Interrupt Mask bits.

Signed-off-by: Maciej W. Rozycki <macro@linux-mips.org>
---
linux-mips-regs-cause.diff
Index: linux/arch/mips/include/asm/mipsregs.h
===================================================================
--- linux.orig/arch/mips/include/asm/mipsregs.h	2015-04-02 20:27:52.045161000 +0100
+++ linux/arch/mips/include/asm/mipsregs.h	2015-04-02 20:27:52.242161000 +0100
@@ -339,10 +339,10 @@
  *
  * Refer to your MIPS R4xx0 manual, chapter 5 for explanation.
  */
-#define	 CAUSEB_EXCCODE		2
-#define	 CAUSEF_EXCCODE		(_ULCAST_(31)  <<  2)
-#define	 CAUSEB_IP		8
-#define	 CAUSEF_IP		(_ULCAST_(255) <<  8)
+#define CAUSEB_EXCCODE		2
+#define CAUSEF_EXCCODE		(_ULCAST_(31)  <<  2)
+#define CAUSEB_IP		8
+#define CAUSEF_IP		(_ULCAST_(255) <<  8)
 #define	 CAUSEB_IP0		8
 #define	 CAUSEF_IP0		(_ULCAST_(1)   <<  8)
 #define	 CAUSEB_IP1		9
@@ -359,16 +359,16 @@
 #define	 CAUSEF_IP6		(_ULCAST_(1)   << 14)
 #define	 CAUSEB_IP7		15
 #define	 CAUSEF_IP7		(_ULCAST_(1)   << 15)
-#define	 CAUSEB_IV		23
-#define	 CAUSEF_IV		(_ULCAST_(1)   << 23)
-#define	 CAUSEB_PCI		26
-#define	 CAUSEF_PCI		(_ULCAST_(1)   << 26)
-#define	 CAUSEB_CE		28
-#define	 CAUSEF_CE		(_ULCAST_(3)   << 28)
-#define	 CAUSEB_TI		30
-#define	 CAUSEF_TI		(_ULCAST_(1)   << 30)
-#define	 CAUSEB_BD		31
-#define	 CAUSEF_BD		(_ULCAST_(1)   << 31)
+#define CAUSEB_IV		23
+#define CAUSEF_IV		(_ULCAST_(1)   << 23)
+#define CAUSEB_PCI		26
+#define CAUSEF_PCI		(_ULCAST_(1)   << 26)
+#define CAUSEB_CE		28
+#define CAUSEF_CE		(_ULCAST_(3)   << 28)
+#define CAUSEB_TI		30
+#define CAUSEF_TI		(_ULCAST_(1)   << 30)
+#define CAUSEB_BD		31
+#define CAUSEF_BD		(_ULCAST_(1)   << 31)
 
 /*
  * Bits in the coprocessor 0 config register.

^ permalink raw reply	[flat|nested] 62+ messages in thread

* [PATCH 06/48] MIPS: ieee754.h: Correct comments for special values
  2015-04-03 22:23 [PATCH 00/48] FPU and FP emulation clean-ups, fixes and feature updates Maciej W. Rozycki
                   ` (4 preceding siblings ...)
  2015-04-03 22:23 ` [PATCH 05/48] MIPS: mipsregs.h: Reindent CP0 Cause macros Maciej W. Rozycki
@ 2015-04-03 22:24 ` Maciej W. Rozycki
  2015-04-03 22:24 ` [PATCH 07/48] MIPS: ieee754.h: Supplement " Maciej W. Rozycki
                   ` (40 subsequent siblings)
  46 siblings, 0 replies; 62+ messages in thread
From: Maciej W. Rozycki @ 2015-04-03 22:24 UTC (permalink / raw)
  To: Ralf Baechle; +Cc: linux-mips

IEEE754_SPCVAL_NMIN denotes the index into the special value array where 
the closest to zero negative normal number expressible is stored.  
Similarly IEEE754_SPCVAL_NMIND denotes such index for the closest to 
zero negative subnormal number expressible.  Make comments match that.

Signed-off-by: Maciej W. Rozycki <macro@linux-mips.org>
---
linux-mips-emu-ieee754-comment-fix.diff
Index: linux/arch/mips/math-emu/ieee754.h
===================================================================
--- linux.orig/arch/mips/math-emu/ieee754.h	2015-04-02 20:18:52.566531000 +0100
+++ linux/arch/mips/math-emu/ieee754.h	2015-04-02 20:27:52.428168000 +0100
@@ -269,9 +269,9 @@ union ieee754dp ieee754dp_dump(char *s, 
 #define IEEE754_SPCVAL_PMAX	9	/* +max norm */
 #define IEEE754_SPCVAL_NMAX	10	/* -max norm */
 #define IEEE754_SPCVAL_PMIN	11	/* +min norm */
-#define IEEE754_SPCVAL_NMIN	12	/* +min norm */
+#define IEEE754_SPCVAL_NMIN	12	/* -min norm */
 #define IEEE754_SPCVAL_PMIND	13	/* +min denorm */
-#define IEEE754_SPCVAL_NMIND	14	/* +min denorm */
+#define IEEE754_SPCVAL_NMIND	14	/* -min denorm */
 #define IEEE754_SPCVAL_P1E31	15	/* + 1.0e31 */
 #define IEEE754_SPCVAL_P1E63	16	/* + 1.0e63 */
 

^ permalink raw reply	[flat|nested] 62+ messages in thread

* [PATCH 07/48] MIPS: ieee754.h: Supplement comments for special values
  2015-04-03 22:23 [PATCH 00/48] FPU and FP emulation clean-ups, fixes and feature updates Maciej W. Rozycki
                   ` (5 preceding siblings ...)
  2015-04-03 22:24 ` [PATCH 06/48] MIPS: ieee754.h: Correct comments for special values Maciej W. Rozycki
@ 2015-04-03 22:24 ` Maciej W. Rozycki
  2015-04-03 22:24 ` [PATCH 08/48] MIPS: Correct the comment for FPU emulator traps Maciej W. Rozycki
                   ` (39 subsequent siblings)
  46 siblings, 0 replies; 62+ messages in thread
From: Maciej W. Rozycki @ 2015-04-03 22:24 UTC (permalink / raw)
  To: Ralf Baechle; +Cc: linux-mips

Add the remaining missing comments for IEEE 754 special value array 
indices.  Reindent macro definitions for consistency.

Signed-off-by: Maciej W. Rozycki <macro@linux-mips.org>
---
linux-mips-emu-ieee754-comment.diff
Index: linux/arch/mips/math-emu/ieee754.h
===================================================================
--- linux.orig/arch/mips/math-emu/ieee754.h	2015-04-02 20:27:52.428168000 +0100
+++ linux/arch/mips/math-emu/ieee754.h	2015-04-02 20:27:52.599179000 +0100
@@ -257,23 +257,23 @@ static inline int ieee754_sxtest(unsigne
 union ieee754sp ieee754sp_dump(char *s, union ieee754sp x);
 union ieee754dp ieee754dp_dump(char *s, union ieee754dp x);
 
-#define IEEE754_SPCVAL_PZERO	0
-#define IEEE754_SPCVAL_NZERO	1
-#define IEEE754_SPCVAL_PONE	2
-#define IEEE754_SPCVAL_NONE	3
-#define IEEE754_SPCVAL_PTEN	4
-#define IEEE754_SPCVAL_NTEN	5
-#define IEEE754_SPCVAL_PINFINITY	6
-#define IEEE754_SPCVAL_NINFINITY	7
-#define IEEE754_SPCVAL_INDEF	8
-#define IEEE754_SPCVAL_PMAX	9	/* +max norm */
-#define IEEE754_SPCVAL_NMAX	10	/* -max norm */
-#define IEEE754_SPCVAL_PMIN	11	/* +min norm */
-#define IEEE754_SPCVAL_NMIN	12	/* -min norm */
-#define IEEE754_SPCVAL_PMIND	13	/* +min denorm */
-#define IEEE754_SPCVAL_NMIND	14	/* -min denorm */
-#define IEEE754_SPCVAL_P1E31	15	/* + 1.0e31 */
-#define IEEE754_SPCVAL_P1E63	16	/* + 1.0e63 */
+#define IEEE754_SPCVAL_PZERO		0	/* +0.0 */
+#define IEEE754_SPCVAL_NZERO		1	/* -0.0 */
+#define IEEE754_SPCVAL_PONE		2	/* +1.0 */
+#define IEEE754_SPCVAL_NONE		3	/* -1.0 */
+#define IEEE754_SPCVAL_PTEN		4	/* +10.0 */
+#define IEEE754_SPCVAL_NTEN		5	/* -10.0 */
+#define IEEE754_SPCVAL_PINFINITY	6	/* +inf */
+#define IEEE754_SPCVAL_NINFINITY	7	/* -inf */
+#define IEEE754_SPCVAL_INDEF		8	/* quiet NaN */
+#define IEEE754_SPCVAL_PMAX		9	/* +max norm */
+#define IEEE754_SPCVAL_NMAX		10	/* -max norm */
+#define IEEE754_SPCVAL_PMIN		11	/* +min norm */
+#define IEEE754_SPCVAL_NMIN		12	/* -min norm */
+#define IEEE754_SPCVAL_PMIND		13	/* +min denorm */
+#define IEEE754_SPCVAL_NMIND		14	/* -min denorm */
+#define IEEE754_SPCVAL_P1E31		15	/* + 1.0e31 */
+#define IEEE754_SPCVAL_P1E63		16	/* + 1.0e63 */
 
 extern const union ieee754dp __ieee754dp_spcvals[];
 extern const union ieee754sp __ieee754sp_spcvals[];

^ permalink raw reply	[flat|nested] 62+ messages in thread

* [PATCH 08/48] MIPS: Correct the comment for FPU emulator traps
  2015-04-03 22:23 [PATCH 00/48] FPU and FP emulation clean-ups, fixes and feature updates Maciej W. Rozycki
                   ` (6 preceding siblings ...)
  2015-04-03 22:24 ` [PATCH 07/48] MIPS: ieee754.h: Supplement " Maciej W. Rozycki
@ 2015-04-03 22:24 ` Maciej W. Rozycki
  2015-04-03 22:24 ` [PATCH 09/48] MIPS: Clarify the comment for `__cpu_has_fpu' Maciej W. Rozycki
                   ` (38 subsequent siblings)
  46 siblings, 0 replies; 62+ messages in thread
From: Maciej W. Rozycki @ 2015-04-03 22:24 UTC (permalink / raw)
  To: Ralf Baechle; +Cc: linux-mips

Adjust the explanatory comment for FPU emulator traps according to 
ba3049ed [MIPS: Switch FPU emulator trap to BREAK instruction.]; 
originally coming from `do_ade'.

Signed-off-by: Maciej W. Rozycki <macro@linux-mips.org>
---
linux-mips-brk-memu-comment.patch
Index: linux/arch/mips/kernel/traps.c
===================================================================
--- linux.orig/arch/mips/kernel/traps.c	2015-04-02 20:18:52.208524000 +0100
+++ linux/arch/mips/kernel/traps.c	2015-04-02 20:27:52.799182000 +0100
@@ -879,9 +879,9 @@ void do_trap_or_bp(struct pt_regs *regs,
 		break;
 	case BRK_MEMU:
 		/*
-		 * Address errors may be deliberately induced by the FPU
-		 * emulator to retake control of the CPU after executing the
-		 * instruction in the delay slot of an emulated branch.
+		 * This breakpoint code is used by the FPU emulator to retake
+		 * control of the CPU after executing the instruction from the
+		 * delay slot of an emulated branch.
 		 *
 		 * Terminate if exception was recognized as a delay slot return
 		 * otherwise handle as normal.

^ permalink raw reply	[flat|nested] 62+ messages in thread

* [PATCH 09/48] MIPS: Clarify the comment for `__cpu_has_fpu'
  2015-04-03 22:23 [PATCH 00/48] FPU and FP emulation clean-ups, fixes and feature updates Maciej W. Rozycki
                   ` (7 preceding siblings ...)
  2015-04-03 22:24 ` [PATCH 08/48] MIPS: Correct the comment for FPU emulator traps Maciej W. Rozycki
@ 2015-04-03 22:24 ` Maciej W. Rozycki
  2015-04-03 22:24 ` [PATCH 10/48] MIPS: math-emu: Reindent `bc_op' emulation Maciej W. Rozycki
                   ` (37 subsequent siblings)
  46 siblings, 0 replies; 62+ messages in thread
From: Maciej W. Rozycki @ 2015-04-03 22:24 UTC (permalink / raw)
  To: Ralf Baechle; +Cc: linux-mips

Reword the comment for `__cpu_has_fpu' to make it unambiguous this code 
is for external floating-point units only, generally MIPS I processors 
using the original CP1 hardware interface.

Signed-off-by: Maciej W. Rozycki <macro@linux-mips.org>
---
linux-mips-cpu-has-fpu-comment.diff
Index: linux/arch/mips/kernel/cpu-probe.c
===================================================================
--- linux.orig/arch/mips/kernel/cpu-probe.c	2015-04-02 20:18:52.108532000 +0100
+++ linux/arch/mips/kernel/cpu-probe.c	2015-04-02 20:27:52.971189000 +0100
@@ -193,7 +193,7 @@ static inline unsigned long cpu_get_fpu_
 }
 
 /*
- * Check the CPU has an FPU the official way.
+ * Check if the CPU has an external FPU.
  */
 static inline int __cpu_has_fpu(void)
 {

^ permalink raw reply	[flat|nested] 62+ messages in thread

* [PATCH 10/48] MIPS: math-emu: Reindent `bc_op' emulation
  2015-04-03 22:23 [PATCH 00/48] FPU and FP emulation clean-ups, fixes and feature updates Maciej W. Rozycki
                   ` (8 preceding siblings ...)
  2015-04-03 22:24 ` [PATCH 09/48] MIPS: Clarify the comment for `__cpu_has_fpu' Maciej W. Rozycki
@ 2015-04-03 22:24 ` Maciej W. Rozycki
  2015-04-03 22:24 ` [PATCH 11/48] MIPS: Correct the comment for and reformat `movf_func' Maciej W. Rozycki
                   ` (36 subsequent siblings)
  46 siblings, 0 replies; 62+ messages in thread
From: Maciej W. Rozycki @ 2015-04-03 22:24 UTC (permalink / raw)
  To: Ralf Baechle; +Cc: linux-mips

Correct the double-tab indentation of the branch-likely not-taken case.

Signed-off-by: Maciej W. Rozycki <macro@linux-mips.org>
---
linux-mips-emu-bc1x-indent.patch
Index: linux/arch/mips/math-emu/cp1emu.c
===================================================================
--- linux.orig/arch/mips/math-emu/cp1emu.c	2015-04-02 20:18:52.010538000 +0100
+++ linux/arch/mips/math-emu/cp1emu.c	2015-04-02 20:27:53.154170000 +0100
@@ -1192,17 +1192,17 @@ static int cop1Emulate(struct pt_regs *x
 				 */
 				return mips_dsemul(xcp, ir, contpc);
 			} else if (likely) {	/* branch not taken */
-					/*
-					 * branch likely nullifies
-					 * dslot if not taken
-					 */
-					xcp->cp0_epc += dec_insn.pc_inc;
-					contpc += dec_insn.pc_inc;
-					/*
-					 * else continue & execute
-					 * dslot as normal insn
-					 */
-				}
+				/*
+				 * branch likely nullifies
+				 * dslot if not taken
+				 */
+				xcp->cp0_epc += dec_insn.pc_inc;
+				contpc += dec_insn.pc_inc;
+				/*
+				 * else continue & execute
+				 * dslot as normal insn
+				 */
+			}
 			break;
 
 		default:

^ permalink raw reply	[flat|nested] 62+ messages in thread

* [PATCH 11/48] MIPS: Correct the comment for and reformat `movf_func'
  2015-04-03 22:23 [PATCH 00/48] FPU and FP emulation clean-ups, fixes and feature updates Maciej W. Rozycki
                   ` (9 preceding siblings ...)
  2015-04-03 22:24 ` [PATCH 10/48] MIPS: math-emu: Reindent `bc_op' emulation Maciej W. Rozycki
@ 2015-04-03 22:24 ` Maciej W. Rozycki
  2015-04-03 22:24 ` [PATCH 12/48] MIPS: math-emu: Fix oversize lines in comparisons Maciej W. Rozycki
                   ` (35 subsequent siblings)
  46 siblings, 0 replies; 62+ messages in thread
From: Maciej W. Rozycki @ 2015-04-03 22:24 UTC (permalink / raw)
  To: Ralf Baechle; +Cc: linux-mips

Correct a copy-and-paste issue with the description for `movf_func' 
referring to `movt_func'.  Reformat the former function to match the 
latter.

Signed-off-by: Maciej W. Rozycki <macro@linux-mips.org>
---
linux-mips-r6-movf-comment.patch
Index: linux/arch/mips/kernel/mips-r2-to-r6-emul.c
===================================================================
--- linux.orig/arch/mips/kernel/mips-r2-to-r6-emul.c	2015-04-02 20:18:51.890522000 +0100
+++ linux/arch/mips/kernel/mips-r2-to-r6-emul.c	2015-04-02 20:27:53.338178000 +0100
@@ -187,7 +187,7 @@ static inline int mipsr6_emul(struct pt_
 }
 
 /**
- * movt_func - Emulate a MOVT instruction
+ * movf_func - Emulate a MOVF instruction
  * @regs: Process register set
  * @ir: Instruction
  *
@@ -200,9 +200,12 @@ static int movf_func(struct pt_regs *reg
 
 	csr = current->thread.fpu.fcr31;
 	cond = fpucondbit[MIPSInst_RT(ir) >> 2];
+
 	if (((csr & cond) == 0) && MIPSInst_RD(ir))
 		regs->regs[MIPSInst_RD(ir)] = regs->regs[MIPSInst_RS(ir)];
+
 	MIPS_R2_STATS(movs);
+
 	return 0;
 }
 

^ permalink raw reply	[flat|nested] 62+ messages in thread

* [PATCH 12/48] MIPS: math-emu: Fix oversize lines in comparisons
  2015-04-03 22:23 [PATCH 00/48] FPU and FP emulation clean-ups, fixes and feature updates Maciej W. Rozycki
                   ` (10 preceding siblings ...)
  2015-04-03 22:24 ` [PATCH 11/48] MIPS: Correct the comment for and reformat `movf_func' Maciej W. Rozycki
@ 2015-04-03 22:24 ` Maciej W. Rozycki
  2015-04-03 22:24 ` [PATCH 13/48] MIPS: ELF: Drop `get_fp_abi' Maciej W. Rozycki
                   ` (34 subsequent siblings)
  46 siblings, 0 replies; 62+ messages in thread
From: Maciej W. Rozycki @ 2015-04-03 22:24 UTC (permalink / raw)
  To: Ralf Baechle; +Cc: linux-mips

Signed-off-by: Maciej W. Rozycki <macro@linux-mips.org>
---
Ralf,

 There's another line going past 79 columns in these functions, it'll be 
removed altogether with a later functional change.

  Maciej

linux-mips-emu-cmp-indent.diff
Index: linux/arch/mips/math-emu/dp_cmp.c
===================================================================
--- linux.orig/arch/mips/math-emu/dp_cmp.c	2015-04-03 12:57:39.280529000 +0100
+++ linux/arch/mips/math-emu/dp_cmp.c	2015-04-03 12:57:45.552589000 +0100
@@ -36,7 +36,8 @@ int ieee754dp_cmp(union ieee754dp x, uni
 	ieee754_clearcx();	/* Even clear inexact flag here */
 
 	if (ieee754dp_isnan(x) || ieee754dp_isnan(y)) {
-		if (sig || xc == IEEE754_CLASS_SNAN || yc == IEEE754_CLASS_SNAN)
+		if (sig ||
+		    xc == IEEE754_CLASS_SNAN || yc == IEEE754_CLASS_SNAN)
 			ieee754_setcx(IEEE754_INVALID_OPERATION);
 		if (cmp & IEEE754_CUN)
 			return 1;
Index: linux/arch/mips/math-emu/sp_cmp.c
===================================================================
--- linux.orig/arch/mips/math-emu/sp_cmp.c	2015-04-03 12:57:39.282535000 +0100
+++ linux/arch/mips/math-emu/sp_cmp.c	2015-04-03 12:57:45.554593000 +0100
@@ -36,7 +36,8 @@ int ieee754sp_cmp(union ieee754sp x, uni
 	ieee754_clearcx();	/* Even clear inexact flag here */
 
 	if (ieee754sp_isnan(x) || ieee754sp_isnan(y)) {
-		if (sig || xc == IEEE754_CLASS_SNAN || yc == IEEE754_CLASS_SNAN)
+		if (sig ||
+		    xc == IEEE754_CLASS_SNAN || yc == IEEE754_CLASS_SNAN)
 			ieee754_setcx(IEEE754_INVALID_OPERATION);
 		if (cmp & IEEE754_CUN)
 			return 1;

^ permalink raw reply	[flat|nested] 62+ messages in thread

* [PATCH 13/48] MIPS: ELF: Drop `get_fp_abi'
  2015-04-03 22:23 [PATCH 00/48] FPU and FP emulation clean-ups, fixes and feature updates Maciej W. Rozycki
                   ` (11 preceding siblings ...)
  2015-04-03 22:24 ` [PATCH 12/48] MIPS: math-emu: Fix oversize lines in comparisons Maciej W. Rozycki
@ 2015-04-03 22:24 ` Maciej W. Rozycki
  2015-04-03 22:24 ` [PATCH 14/48] MIPS: mips-r2-to-r6-emul.h: Inline empty `mipsr2_decoder' Maciej W. Rozycki
                   ` (33 subsequent siblings)
  46 siblings, 0 replies; 62+ messages in thread
From: Maciej W. Rozycki @ 2015-04-03 22:24 UTC (permalink / raw)
  To: Ralf Baechle; +Cc: Markos Chandras, linux-mips

Commit 46490b57 [MIPS: kernel: elf: Improve the overall ABI and FPU mode 
checks] reduced `get_fp_abi' to an elaborate pass-through.  Drop it 
then.

Cc: Markos Chandras <markos.chandras@imgtec.com>
Signed-off-by: Maciej W. Rozycki <macro@linux-mips.org>
---
linux-mips-get-fp-abi.diff
Index: linux/arch/mips/kernel/elf.c
===================================================================
--- linux.orig/arch/mips/kernel/elf.c	2015-04-02 20:18:51.786524000 +0100
+++ linux/arch/mips/kernel/elf.c	2015-04-02 20:27:53.523178000 +0100
@@ -131,16 +131,6 @@ int arch_elf_pt_proc(void *_ehdr, void *
 	return 0;
 }
 
-static inline unsigned get_fp_abi(int in_abi)
-{
-	/* If the ABI requirement is provided, simply return that */
-	if (in_abi != MIPS_ABI_FP_UNKNOWN)
-		return in_abi;
-
-	/* Unknown ABI */
-	return MIPS_ABI_FP_UNKNOWN;
-}
-
 int arch_check_elf(void *_ehdr, bool has_interpreter,
 		   struct arch_elf_state *state)
 {
@@ -151,10 +141,10 @@ int arch_check_elf(void *_ehdr, bool has
 	if (!config_enabled(CONFIG_MIPS_O32_FP64_SUPPORT))
 		return 0;
 
-	fp_abi = get_fp_abi(state->fp_abi);
+	fp_abi = state->fp_abi;
 
 	if (has_interpreter) {
-		interp_fp_abi = get_fp_abi(state->interp_fp_abi);
+		interp_fp_abi = state->interp_fp_abi;
 
 		abi0 = min(fp_abi, interp_fp_abi);
 		abi1 = max(fp_abi, interp_fp_abi);

^ permalink raw reply	[flat|nested] 62+ messages in thread

* [PATCH 14/48] MIPS: mips-r2-to-r6-emul.h: Inline empty `mipsr2_decoder'
  2015-04-03 22:23 [PATCH 00/48] FPU and FP emulation clean-ups, fixes and feature updates Maciej W. Rozycki
                   ` (12 preceding siblings ...)
  2015-04-03 22:24 ` [PATCH 13/48] MIPS: ELF: Drop `get_fp_abi' Maciej W. Rozycki
@ 2015-04-03 22:24 ` Maciej W. Rozycki
  2015-04-03 22:24 ` [PATCH 15/48] MIPS: Reindent R6 RI exception emulation Maciej W. Rozycki
                   ` (32 subsequent siblings)
  46 siblings, 0 replies; 62+ messages in thread
From: Maciej W. Rozycki @ 2015-04-03 22:24 UTC (permalink / raw)
  To: Ralf Baechle; +Cc: Leonid Yegoshin, linux-mips

Use `static inline' rather than `static __maybe_unused' for 
`mipsr2_decoder' in the empty case, making inlining explicit where it 
will happen anyway.

Cc: Leonid Yegoshin <Leonid.Yegoshin@imgtec.com>
Signed-off-by: Maciej W. Rozycki <macro@linux-mips.org>
---
linux-mips-r2-decoder-inline.patch
Index: linux/arch/mips/include/asm/mips-r2-to-r6-emul.h
===================================================================
--- linux.orig/arch/mips/include/asm/mips-r2-to-r6-emul.h	2015-04-02 20:18:51.667537000 +0100
+++ linux/arch/mips/include/asm/mips-r2-to-r6-emul.h	2015-04-02 20:27:53.724187000 +0100
@@ -84,7 +84,7 @@ extern void do_trap_or_bp(struct pt_regs
 
 #ifndef CONFIG_MIPSR2_TO_R6_EMULATOR
 static int mipsr2_emulation;
-static __maybe_unused int mipsr2_decoder(struct pt_regs *regs, u32 inst) { return 0; };
+static inline int mipsr2_decoder(struct pt_regs *regs, u32 inst) { return 0; };
 #else
 /* MIPS R2 Emulator ON/OFF */
 extern int mipsr2_emulation;

^ permalink raw reply	[flat|nested] 62+ messages in thread

* [PATCH 15/48] MIPS: Reindent R6 RI exception emulation
  2015-04-03 22:23 [PATCH 00/48] FPU and FP emulation clean-ups, fixes and feature updates Maciej W. Rozycki
                   ` (13 preceding siblings ...)
  2015-04-03 22:24 ` [PATCH 14/48] MIPS: mips-r2-to-r6-emul.h: Inline empty `mipsr2_decoder' Maciej W. Rozycki
@ 2015-04-03 22:24 ` Maciej W. Rozycki
  2015-04-03 22:24 ` [PATCH 16/48] MIPS: math-emu: Remove `modeindex' macro Maciej W. Rozycki
                   ` (31 subsequent siblings)
  46 siblings, 0 replies; 62+ messages in thread
From: Maciej W. Rozycki @ 2015-04-03 22:24 UTC (permalink / raw)
  To: Ralf Baechle; +Cc: Leonid Yegoshin, linux-mips

Fold a nested `if' statement for the R6 case in `do_ri' into its 
containing `if' block, removing excessive indentation causing code to 
extend beyond 79 columns.

Cc: Leonid Yegoshin <Leonid.Yegoshin@imgtec.com>
Signed-off-by: Maciej W. Rozycki <macro@linux-mips.org>
---
linux-mips-do-ri-r6-indent.patch
Index: linux/arch/mips/kernel/traps.c
===================================================================
--- linux.orig/arch/mips/kernel/traps.c	2015-04-02 20:27:52.799182000 +0100
+++ linux/arch/mips/kernel/traps.c	2015-04-02 20:27:53.911190000 +0100
@@ -1033,22 +1033,21 @@ asmlinkage void do_ri(struct pt_regs *re
 	 * as quickly as possible.
 	 */
 	if (mipsr2_emulation && cpu_has_mips_r6 &&
-	    likely(user_mode(regs))) {
-		if (likely(get_user(opcode, epc) >= 0)) {
-			status = mipsr2_decoder(regs, opcode);
-			switch (status) {
-			case 0:
-			case SIGEMT:
-				task_thread_info(current)->r2_emul_return = 1;
-				return;
-			case SIGILL:
-				goto no_r2_instr;
-			default:
-				process_fpemu_return(status,
-						     &current->thread.cp0_baduaddr);
-				task_thread_info(current)->r2_emul_return = 1;
-				return;
-			}
+	    likely(user_mode(regs)) &&
+	    likely(get_user(opcode, epc) >= 0)) {
+		status = mipsr2_decoder(regs, opcode);
+		switch (status) {
+		case 0:
+		case SIGEMT:
+			task_thread_info(current)->r2_emul_return = 1;
+			return;
+		case SIGILL:
+			goto no_r2_instr;
+		default:
+			process_fpemu_return(status,
+					     &current->thread.cp0_baduaddr);
+			task_thread_info(current)->r2_emul_return = 1;
+			return;
 		}
 	}
 

^ permalink raw reply	[flat|nested] 62+ messages in thread

* [PATCH 16/48] MIPS: math-emu: Remove `modeindex' macro
  2015-04-03 22:23 [PATCH 00/48] FPU and FP emulation clean-ups, fixes and feature updates Maciej W. Rozycki
                   ` (14 preceding siblings ...)
  2015-04-03 22:24 ` [PATCH 15/48] MIPS: Reindent R6 RI exception emulation Maciej W. Rozycki
@ 2015-04-03 22:24 ` Maciej W. Rozycki
  2015-04-03 22:25 ` [PATCH 17/48] MIPS: bitops.h: Avoid inline asm for constant FLS Maciej W. Rozycki
                   ` (30 subsequent siblings)
  46 siblings, 0 replies; 62+ messages in thread
From: Maciej W. Rozycki @ 2015-04-03 22:24 UTC (permalink / raw)
  To: Ralf Baechle; +Cc: linux-mips

Commit 56a64733 [MIPS: math-emu: Switch to using the MIPS rounding 
modes.] removed the distinction between hardware and emulator rounding 
mode encodings, the hardware encoding is now used in emulation as well.  
Complement the change and remove the `modeindex' macro previously used 
for indexing into encoding translation tables, it now does nothing and 
only obfuscates code by reinserting the value extracted from FCSR.  
Adjust comments accordingly.

Signed-off-by: Maciej W. Rozycki <macro@linux-mips.org>
---
linux-mips-emu-fcsr-rm-modeindex.diff
Index: linux/arch/mips/math-emu/cp1emu.c
===================================================================
--- linux.orig/arch/mips/math-emu/cp1emu.c	2015-04-02 20:27:53.154170000 +0100
+++ linux/arch/mips/math-emu/cp1emu.c	2015-04-02 20:27:54.099185000 +0100
@@ -65,9 +65,6 @@ static int fpux_emu(struct pt_regs *,
 #define FPCREG_RID	0	/* $0  = revision id */
 #define FPCREG_CSR	31	/* $31 = csr */
 
-/* Determine rounding mode from the RM bits of the FCSR */
-#define modeindex(v) ((v) & FPU_CSR_RM)
-
 /* convert condition code register number to csr bit */
 const unsigned int fpucondbit[8] = {
 	FPU_CSR_COND0,
@@ -1051,7 +1048,6 @@ static int cop1Emulate(struct pt_regs *x
 			/* cop control register rd -> gpr[rt] */
 			if (MIPSInst_RD(ir) == FPCREG_CSR) {
 				value = ctx->fcr31;
-				value = (value & ~FPU_CSR_RM) | modeindex(value);
 				pr_debug("%p gpr[%d]<-csr=%08x\n",
 					 (void *) (xcp->cp0_epc),
 					 MIPSInst_RT(ir), value);
@@ -1078,12 +1074,8 @@ static int cop1Emulate(struct pt_regs *x
 					 (void *) (xcp->cp0_epc),
 					 MIPSInst_RT(ir), value);
 
-				/*
-				 * Don't write reserved bits,
-				 * and convert to ieee library modes
-				 */
-				ctx->fcr31 = (value & ~(FPU_CSR_RSVD | FPU_CSR_RM)) |
-					     modeindex(value);
+				/* Don't write reserved bits.  */
+				ctx->fcr31 = value & ~FPU_CSR_RSVD;
 			}
 			if ((ctx->fcr31 >> 5) & ctx->fcr31 & FPU_CSR_ALL_E) {
 				return SIGFPE;
@@ -1675,7 +1667,7 @@ static int fpu_emu(struct pt_regs *xcp, 
 
 			oldrm = ieee754_csr.rm;
 			SPFROMREG(fs, MIPSInst_FS(ir));
-			ieee754_csr.rm = modeindex(MIPSInst_FUNC(ir));
+			ieee754_csr.rm = MIPSInst_FUNC(ir);
 			rv.w = ieee754sp_tint(fs);
 			ieee754_csr.rm = oldrm;
 			rfmt = w_fmt;
@@ -1699,7 +1691,7 @@ static int fpu_emu(struct pt_regs *xcp, 
 
 			oldrm = ieee754_csr.rm;
 			SPFROMREG(fs, MIPSInst_FS(ir));
-			ieee754_csr.rm = modeindex(MIPSInst_FUNC(ir));
+			ieee754_csr.rm = MIPSInst_FUNC(ir);
 			rv.l = ieee754sp_tlong(fs);
 			ieee754_csr.rm = oldrm;
 			rfmt = l_fmt;
@@ -1852,7 +1844,7 @@ static int fpu_emu(struct pt_regs *xcp, 
 
 			oldrm = ieee754_csr.rm;
 			DPFROMREG(fs, MIPSInst_FS(ir));
-			ieee754_csr.rm = modeindex(MIPSInst_FUNC(ir));
+			ieee754_csr.rm = MIPSInst_FUNC(ir);
 			rv.w = ieee754dp_tint(fs);
 			ieee754_csr.rm = oldrm;
 			rfmt = w_fmt;
@@ -1876,7 +1868,7 @@ static int fpu_emu(struct pt_regs *xcp, 
 
 			oldrm = ieee754_csr.rm;
 			DPFROMREG(fs, MIPSInst_FS(ir));
-			ieee754_csr.rm = modeindex(MIPSInst_FUNC(ir));
+			ieee754_csr.rm = MIPSInst_FUNC(ir);
 			rv.l = ieee754dp_tlong(fs);
 			ieee754_csr.rm = oldrm;
 			rfmt = l_fmt;
@@ -2081,10 +2073,8 @@ int fpu_emulator_cop1Handler(struct pt_r
 			xcp->cp0_epc += dec_insn.pc_inc;	/* Skip NOPs */
 		else {
 			/*
-			 * The 'ieee754_csr' is an alias of
-			 * ctx->fcr31.	No need to copy ctx->fcr31 to
-			 * ieee754_csr.	 But ieee754_csr.rm is ieee
-			 * library modes. (not mips rounding mode)
+			 * The 'ieee754_csr' is an alias of ctx->fcr31.
+			 * No need to copy ctx->fcr31 to ieee754_csr.
 			 */
 			sig = cop1Emulate(xcp, ctx, dec_insn, fault_addr);
 		}

^ permalink raw reply	[flat|nested] 62+ messages in thread

* [PATCH 17/48] MIPS: bitops.h: Avoid inline asm for constant FLS
  2015-04-03 22:23 [PATCH 00/48] FPU and FP emulation clean-ups, fixes and feature updates Maciej W. Rozycki
                   ` (15 preceding siblings ...)
  2015-04-03 22:24 ` [PATCH 16/48] MIPS: math-emu: Remove `modeindex' macro Maciej W. Rozycki
@ 2015-04-03 22:25 ` Maciej W. Rozycki
  2015-04-03 22:25 ` [PATCH 18/48] MIPS: math-emu: Factor out CFC1/CTC1 emulation Maciej W. Rozycki
                   ` (29 subsequent siblings)
  46 siblings, 0 replies; 62+ messages in thread
From: Maciej W. Rozycki @ 2015-04-03 22:25 UTC (permalink / raw)
  To: Ralf Baechle; +Cc: linux-mips

GCC is smart enough to substitute the final result for FLS calculations 
as implemented in the fallback C code we have in `__fls' and `fls' 
applied to constant values.  The presence of inline asm defeats the 
compiler though, forcing it to emit extraneous CLZ/DCLZ calculation for 
processors that support these instructions.

Use `__builtin_constant_p' then to avoid inline asm altogether for 
constants.

Signed-off-by: Maciej W. Rozycki <macro@linux-mips.org>
---
Ralf,

 Even my good old trusty 4.1.2 can do it...

  Maciej

linux-mips-const-fls.diff
Index: linux/arch/mips/include/asm/bitops.h
===================================================================
--- linux.orig/arch/mips/include/asm/bitops.h	2015-04-02 20:18:51.384515000 +0100
+++ linux/arch/mips/include/asm/bitops.h	2015-04-02 20:27:54.273191000 +0100
@@ -481,7 +481,7 @@ static inline unsigned long __fls(unsign
 {
 	int num;
 
-	if (BITS_PER_LONG == 32 &&
+	if (BITS_PER_LONG == 32 && !__builtin_constant_p(word) &&
 	    __builtin_constant_p(cpu_has_clo_clz) && cpu_has_clo_clz) {
 		__asm__(
 		"	.set	push					\n"
@@ -494,7 +494,7 @@ static inline unsigned long __fls(unsign
 		return 31 - num;
 	}
 
-	if (BITS_PER_LONG == 64 &&
+	if (BITS_PER_LONG == 64 && !__builtin_constant_p(word) &&
 	    __builtin_constant_p(cpu_has_mips64) && cpu_has_mips64) {
 		__asm__(
 		"	.set	push					\n"
@@ -559,7 +559,8 @@ static inline int fls(int x)
 {
 	int r;
 
-	if (__builtin_constant_p(cpu_has_clo_clz) && cpu_has_clo_clz) {
+	if (!__builtin_constant_p(x) &&
+	    __builtin_constant_p(cpu_has_clo_clz) && cpu_has_clo_clz) {
 		__asm__(
 		"	.set	push					\n"
 		"	.set	"MIPS_ISA_LEVEL"			\n"

^ permalink raw reply	[flat|nested] 62+ messages in thread

* [PATCH 18/48] MIPS: math-emu: Factor out CFC1/CTC1 emulation
  2015-04-03 22:23 [PATCH 00/48] FPU and FP emulation clean-ups, fixes and feature updates Maciej W. Rozycki
                   ` (16 preceding siblings ...)
  2015-04-03 22:25 ` [PATCH 17/48] MIPS: bitops.h: Avoid inline asm for constant FLS Maciej W. Rozycki
@ 2015-04-03 22:25 ` Maciej W. Rozycki
  2015-04-03 23:33   ` Sergei Shtylyov
  2015-04-03 22:25 ` [PATCH 19/48] MIPS: Normalise code flow in the CpU exception handler Maciej W. Rozycki
                   ` (28 subsequent siblings)
  46 siblings, 1 reply; 62+ messages in thread
From: Maciej W. Rozycki @ 2015-04-03 22:25 UTC (permalink / raw)
  To: Ralf Baechle; +Cc: linux-mips

Move CFC1/CTC1 emulation code to separate functions to avoid excessive 
indentation in forthcoming changes.  Adjust formatting in a minor way 
and remove extraneous round brackets.

Signed-off-by: Maciej W. Rozycki <macro@linux-mips.org>
---
linux-mips-emu-cxc.diff
Index: linux/arch/mips/math-emu/cp1emu.c
===================================================================
--- linux.orig/arch/mips/math-emu/cp1emu.c	2015-04-02 20:27:54.099185000 +0100
+++ linux/arch/mips/math-emu/cp1emu.c	2015-04-02 20:27:54.459192000 +0100
@@ -840,6 +840,52 @@ do {									\
 #define DPTOREG(dp, x)	DITOREG((dp).bits, x)
 
 /*
+ * Emulate a CFC1 instruction.
+ */
+static inline void cop1_cfc(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
+			    mips_instruction ir)
+{
+	u32 value;
+
+	if (MIPSInst_RD(ir) == FPCREG_CSR) {
+		value = ctx->fcr31;
+		pr_debug("%p gpr[%d]<-csr=%08x\n",
+			 (void *)xcp->cp0_epc,
+			 MIPSInst_RT(ir), value);
+	} else if (MIPSInst_RD(ir) == FPCREG_RID)
+		value = 0;
+	else
+		value = 0;
+	if (MIPSInst_RT(ir))
+		xcp->regs[MIPSInst_RT(ir)] = value;
+}
+
+/*
+ * Emulate a CTC1 instruction.
+ */
+static inline void cop1_ctc(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
+			    mips_instruction ir)
+{
+	u32 value;
+
+	if (MIPSInst_RT(ir) == 0)
+		value = 0;
+	else
+		value = xcp->regs[MIPSInst_RT(ir)];
+
+	/* we only have one writable control reg
+	 */
+	if (MIPSInst_RD(ir) == FPCREG_CSR) {
+		pr_debug("%p gpr[%d]->csr=%08x\n",
+			 (void *)xcp->cp0_epc,
+			 MIPSInst_RT(ir), value);
+
+		/* Don't write reserved bits.  */
+		ctx->fcr31 = value & ~FPU_CSR_RSVD;
+	}
+}
+
+/*
  * Emulate the single floating point instruction pointed at by EPC.
  * Two instructions if the instruction is in a branch delay slot.
  */
@@ -853,7 +899,6 @@ static int cop1Emulate(struct pt_regs *x
 	int likely, pc_inc;
 	u32 __user *wva;
 	u64 __user *dva;
-	u32 value;
 	u32 wval;
 	u64 dval;
 	int sig;
@@ -1046,37 +1091,12 @@ static int cop1Emulate(struct pt_regs *x
 
 		case cfc_op:
 			/* cop control register rd -> gpr[rt] */
-			if (MIPSInst_RD(ir) == FPCREG_CSR) {
-				value = ctx->fcr31;
-				pr_debug("%p gpr[%d]<-csr=%08x\n",
-					 (void *) (xcp->cp0_epc),
-					 MIPSInst_RT(ir), value);
-			}
-			else if (MIPSInst_RD(ir) == FPCREG_RID)
-				value = 0;
-			else
-				value = 0;
-			if (MIPSInst_RT(ir))
-				xcp->regs[MIPSInst_RT(ir)] = value;
+			cop1_cfc(xcp, ctx, ir);
 			break;
 
 		case ctc_op:
 			/* copregister rd <- rt */
-			if (MIPSInst_RT(ir) == 0)
-				value = 0;
-			else
-				value = xcp->regs[MIPSInst_RT(ir)];
-
-			/* we only have one writable control reg
-			 */
-			if (MIPSInst_RD(ir) == FPCREG_CSR) {
-				pr_debug("%p gpr[%d]->csr=%08x\n",
-					 (void *) (xcp->cp0_epc),
-					 MIPSInst_RT(ir), value);
-
-				/* Don't write reserved bits.  */
-				ctx->fcr31 = value & ~FPU_CSR_RSVD;
-			}
+			cop1_ctc(xcp, ctx, ir);
 			if ((ctx->fcr31 >> 5) & ctx->fcr31 & FPU_CSR_ALL_E) {
 				return SIGFPE;
 			}

^ permalink raw reply	[flat|nested] 62+ messages in thread

* [PATCH 19/48] MIPS: Normalise code flow in the CpU exception handler
  2015-04-03 22:23 [PATCH 00/48] FPU and FP emulation clean-ups, fixes and feature updates Maciej W. Rozycki
                   ` (17 preceding siblings ...)
  2015-04-03 22:25 ` [PATCH 18/48] MIPS: math-emu: Factor out CFC1/CTC1 emulation Maciej W. Rozycki
@ 2015-04-03 22:25 ` Maciej W. Rozycki
  2015-04-03 22:25 ` [PATCH 20/48] MIPS: Use `FPU_CSR_ALL_X' in `__build_clear_fpe' Maciej W. Rozycki
                   ` (27 subsequent siblings)
  46 siblings, 0 replies; 62+ messages in thread
From: Maciej W. Rozycki @ 2015-04-03 22:25 UTC (permalink / raw)
  To: Ralf Baechle; +Cc: linux-mips

Changes applied to `do_cpu' over time reduced the use of the SIGILL 
issued with `force_sig' at the end to a single CU3 case only in the 
switch statement there.  Move that `force_sig' call over to right where 
required then and toss out the pile of gotos now not needed to skip over 
the call, replacing them with regular breaks out of the switch.

Signed-off-by: Maciej W. Rozycki <macro@linux-mips.org>
---
linux-mips-cpu-switch.diff
Index: linux/arch/mips/kernel/traps.c
===================================================================
--- linux.orig/arch/mips/kernel/traps.c	2015-04-02 20:27:53.911190000 +0100
+++ linux/arch/mips/kernel/traps.c	2015-04-02 20:27:54.637186000 +0100
@@ -1312,7 +1312,7 @@ asmlinkage void do_cpu(struct pt_regs *r
 		status = -1;
 
 		if (unlikely(compute_return_epc(regs) < 0))
-			goto out;
+			break;
 
 		if (get_isa16_mode(regs->cp0_epc)) {
 			unsigned short mmop[2] = { 0 };
@@ -1345,7 +1345,7 @@ asmlinkage void do_cpu(struct pt_regs *r
 			force_sig(status, current);
 		}
 
-		goto out;
+		break;
 
 	case 3:
 		/*
@@ -1361,8 +1361,10 @@ asmlinkage void do_cpu(struct pt_regs *r
 		 * erroneously too, so they are covered by this choice
 		 * as well.
 		 */
-		if (raw_cpu_has_fpu)
+		if (raw_cpu_has_fpu) {
+			force_sig(SIGILL, current);
 			break;
+		}
 		/* Fall through.  */
 
 	case 1:
@@ -1378,16 +1380,13 @@ asmlinkage void do_cpu(struct pt_regs *r
 				mt_ase_fp_affinity();
 		}
 
-		goto out;
+		break;
 
 	case 2:
 		raw_notifier_call_chain(&cu2_chain, CU2_EXCEPTION, regs);
-		goto out;
+		break;
 	}
 
-	force_sig(SIGILL, current);
-
-out:
 	exception_exit(prev_state);
 }
 

^ permalink raw reply	[flat|nested] 62+ messages in thread

* [PATCH 20/48] MIPS: Use `FPU_CSR_ALL_X' in `__build_clear_fpe'
  2015-04-03 22:23 [PATCH 00/48] FPU and FP emulation clean-ups, fixes and feature updates Maciej W. Rozycki
                   ` (18 preceding siblings ...)
  2015-04-03 22:25 ` [PATCH 19/48] MIPS: Normalise code flow in the CpU exception handler Maciej W. Rozycki
@ 2015-04-03 22:25 ` Maciej W. Rozycki
  2015-04-03 22:25 ` [PATCH 21/48] MIPS: math-emu: Update sNaN quieting handlers Maciej W. Rozycki
                   ` (26 subsequent siblings)
  46 siblings, 0 replies; 62+ messages in thread
From: Maciej W. Rozycki @ 2015-04-03 22:25 UTC (permalink / raw)
  To: Ralf Baechle; +Cc: linux-mips

Replace a hardcoded numeric bitmask for FCSR cause bits with 
`FPU_CSR_ALL_X' in `__build_clear_fpe'.

Signed-off-by: Maciej W. Rozycki <macro@linux-mips.org>
---
linux-mips-genex-fpe-all-x.diff
Index: linux/arch/mips/kernel/genex.S
===================================================================
--- linux.orig/arch/mips/kernel/genex.S	2015-04-02 20:18:51.068520000 +0100
+++ linux/arch/mips/kernel/genex.S	2015-04-02 20:27:54.807188000 +0100
@@ -360,7 +360,7 @@ NESTED(nmi_handler, PT_SIZE, sp)
 	.set	mips1
 	SET_HARDFLOAT
 	cfc1	a1, fcr31
-	li	a2, ~(0x3f << 12)
+	li	a2, ~FPU_CSR_ALL_X
 	and	a2, a1
 	ctc1	a2, fcr31
 	.set	pop

^ permalink raw reply	[flat|nested] 62+ messages in thread

* [PATCH 21/48] MIPS: math-emu: Update sNaN quieting handlers
  2015-04-03 22:23 [PATCH 00/48] FPU and FP emulation clean-ups, fixes and feature updates Maciej W. Rozycki
                   ` (19 preceding siblings ...)
  2015-04-03 22:25 ` [PATCH 20/48] MIPS: Use `FPU_CSR_ALL_X' in `__build_clear_fpe' Maciej W. Rozycki
@ 2015-04-03 22:25 ` Maciej W. Rozycki
  2015-04-03 22:25 ` [PATCH 23/48] MIPS: math-emu: Don't pass qNaNs through " Maciej W. Rozycki
                   ` (25 subsequent siblings)
  46 siblings, 0 replies; 62+ messages in thread
From: Maciej W. Rozycki @ 2015-04-03 22:25 UTC (permalink / raw)
  To: Ralf Baechle; +Cc: linux-mips

Commit fdffbafb [Lots of FPU bug fixes from Kjeld Borch Egevang.] 
replaced the two single `ieee754sp_nanxcpt' and `ieee754dp_nanxcpt' 
places, where sNaN quieting used to happen for single and double 
floating-point operations respectively, with individual qNaN 
instantiations across all the call sites instead.  It also made most of 
these two functions dead code as where called on a qNaN they return 
right away.

To revert the damage and make sNaN quieting uniform again first rewrite 
`ieee754sp_nanxcpt' and `ieee754dp_nanxcpt' to do the same quieting all 
the call sites do, that is return the default qNaN encoding for all 
input sNaN values; never propagate any sNaN payload bits from its 
trailing significand field.

Signed-off-by: Maciej W. Rozycki <macro@linux-mips.org>
---
linux-mips-emu-nanxcpt-snan.diff
Index: linux/arch/mips/math-emu/ieee754dp.c
===================================================================
--- linux.orig/arch/mips/math-emu/ieee754dp.c	2015-04-02 20:18:51.033516000 +0100
+++ linux/arch/mips/math-emu/ieee754dp.c	2015-04-02 20:27:54.976193000 +0100
@@ -49,14 +49,9 @@ union ieee754dp __cold ieee754dp_nanxcpt
 	if (!ieee754dp_issnan(r))	/* QNAN does not cause invalid op !! */
 		return r;
 
-	if (!ieee754_setandtestcx(IEEE754_INVALID_OPERATION)) {
-		/* not enabled convert to a quiet NaN */
-		DPMANT(r) &= (~DP_MBIT(DP_FBITS-1));
-		if (ieee754dp_isnan(r))
-			return r;
-		else
-			return ieee754dp_indef();
-	}
+	/* If not enabled convert to a quiet NaN.  */
+	if (!ieee754_setandtestcx(IEEE754_INVALID_OPERATION))
+		return ieee754dp_indef();
 
 	return r;
 }
Index: linux/arch/mips/math-emu/ieee754sp.c
===================================================================
--- linux.orig/arch/mips/math-emu/ieee754sp.c	2015-04-02 20:18:51.036515000 +0100
+++ linux/arch/mips/math-emu/ieee754sp.c	2015-04-02 20:27:54.979190000 +0100
@@ -49,14 +49,9 @@ union ieee754sp __cold ieee754sp_nanxcpt
 	if (!ieee754sp_issnan(r))	/* QNAN does not cause invalid op !! */
 		return r;
 
-	if (!ieee754_setandtestcx(IEEE754_INVALID_OPERATION)) {
-		/* not enabled convert to a quiet NaN */
-		SPMANT(r) &= (~SP_MBIT(SP_FBITS-1));
-		if (ieee754sp_isnan(r))
-			return r;
-		else
-			return ieee754sp_indef();
-	}
+	/* If not enabled convert to a quiet NaN.  */
+	if (!ieee754_setandtestcx(IEEE754_INVALID_OPERATION))
+		return ieee754sp_indef();
 
 	return r;
 }

^ permalink raw reply	[flat|nested] 62+ messages in thread

* [PATCH 23/48] MIPS: math-emu: Don't pass qNaNs through quieting handlers
  2015-04-03 22:23 [PATCH 00/48] FPU and FP emulation clean-ups, fixes and feature updates Maciej W. Rozycki
                   ` (20 preceding siblings ...)
  2015-04-03 22:25 ` [PATCH 21/48] MIPS: math-emu: Update sNaN quieting handlers Maciej W. Rozycki
@ 2015-04-03 22:25 ` Maciej W. Rozycki
  2015-04-03 22:25 ` [PATCH 24/48] MIPS: math-emu: Reinstate sNaN " Maciej W. Rozycki
                   ` (24 subsequent siblings)
  46 siblings, 0 replies; 62+ messages in thread
From: Maciej W. Rozycki @ 2015-04-03 22:25 UTC (permalink / raw)
  To: Ralf Baechle; +Cc: linux-mips

Don't call the `ieee754sp_nanxcpt' and `ieee754dp_nanxcpt' sNaN quieting 
handlers for a qNaN supplied to floating-point format conversions or 
SQRT.S/SQRT.D instructions, or for a qNaN produced out of a negative 
operand supplied to SQRT.S/SQRT.D instructions.  Return the qNaN right 
away in these cases.

Signed-off-by: Maciej W. Rozycki <macro@linux-mips.org>
---
linux-mips-emu-nanxcpt-qnan.diff
Index: linux/arch/mips/math-emu/dp_fsp.c
===================================================================
--- linux.orig/arch/mips/math-emu/dp_fsp.c	2015-04-03 04:57:50.206062000 +0100
+++ linux/arch/mips/math-emu/dp_fsp.c	2015-04-03 04:58:06.696244000 +0100
@@ -44,7 +44,7 @@ union ieee754dp ieee754dp_fsp(union ieee
 		return ieee754dp_nanxcpt(ieee754dp_indef());
 
 	case IEEE754_CLASS_QNAN:
-		return ieee754dp_nanxcpt(ieee754dp_nan_fsp(xs, xm));
+		return ieee754dp_nan_fsp(xs, xm);
 
 	case IEEE754_CLASS_INF:
 		return ieee754dp_inf(xs);
Index: linux/arch/mips/math-emu/dp_sqrt.c
===================================================================
--- linux.orig/arch/mips/math-emu/dp_sqrt.c	2015-04-03 04:57:13.570713000 +0100
+++ linux/arch/mips/math-emu/dp_sqrt.c	2015-04-03 04:58:06.699229000 +0100
@@ -44,7 +44,7 @@ union ieee754dp ieee754dp_sqrt(union iee
 	switch (xc) {
 	case IEEE754_CLASS_QNAN:
 		/* sqrt(Nan) = Nan */
-		return ieee754dp_nanxcpt(x);
+		return x;
 
 	case IEEE754_CLASS_SNAN:
 		ieee754_setcx(IEEE754_INVALID_OPERATION);
@@ -58,7 +58,7 @@ union ieee754dp ieee754dp_sqrt(union iee
 		if (xs) {
 			/* sqrt(-Inf) = Nan */
 			ieee754_setcx(IEEE754_INVALID_OPERATION);
-			return ieee754dp_nanxcpt(ieee754dp_indef());
+			return ieee754dp_indef();
 		}
 		/* sqrt(+Inf) = Inf */
 		return x;
@@ -71,7 +71,7 @@ union ieee754dp ieee754dp_sqrt(union iee
 		if (xs) {
 			/* sqrt(-x) = Nan */
 			ieee754_setcx(IEEE754_INVALID_OPERATION);
-			return ieee754dp_nanxcpt(ieee754dp_indef());
+			return ieee754dp_indef();
 		}
 		break;
 	}
Index: linux/arch/mips/math-emu/sp_fdp.c
===================================================================
--- linux.orig/arch/mips/math-emu/sp_fdp.c	2015-04-03 04:57:50.208062000 +0100
+++ linux/arch/mips/math-emu/sp_fdp.c	2015-04-03 04:58:06.701235000 +0100
@@ -50,7 +50,7 @@ union ieee754sp ieee754sp_fdp(union ieee
 		nan = ieee754sp_nan_fdp(xs, xm);
 		if (!ieee754sp_isnan(nan))
 			nan = ieee754sp_indef();
-		return ieee754sp_nanxcpt(nan);
+		return nan;
 
 	case IEEE754_CLASS_INF:
 		return ieee754sp_inf(xs);
Index: linux/arch/mips/math-emu/sp_sqrt.c
===================================================================
--- linux.orig/arch/mips/math-emu/sp_sqrt.c	2015-04-03 04:57:13.582698000 +0100
+++ linux/arch/mips/math-emu/sp_sqrt.c	2015-04-03 04:58:06.703246000 +0100
@@ -37,7 +37,7 @@ union ieee754sp ieee754sp_sqrt(union iee
 	switch (xc) {
 	case IEEE754_CLASS_QNAN:
 		/* sqrt(Nan) = Nan */
-		return ieee754sp_nanxcpt(x);
+		return x;
 
 	case IEEE754_CLASS_SNAN:
 		ieee754_setcx(IEEE754_INVALID_OPERATION);
@@ -51,7 +51,7 @@ union ieee754sp ieee754sp_sqrt(union iee
 		if (xs) {
 			/* sqrt(-Inf) = Nan */
 			ieee754_setcx(IEEE754_INVALID_OPERATION);
-			return ieee754sp_nanxcpt(ieee754sp_indef());
+			return ieee754sp_indef();
 		}
 		/* sqrt(+Inf) = Inf */
 		return x;
@@ -61,7 +61,7 @@ union ieee754sp ieee754sp_sqrt(union iee
 		if (xs) {
 			/* sqrt(-x) = Nan */
 			ieee754_setcx(IEEE754_INVALID_OPERATION);
-			return ieee754sp_nanxcpt(ieee754sp_indef());
+			return ieee754sp_indef();
 		}
 		break;
 	}

^ permalink raw reply	[flat|nested] 62+ messages in thread

* [PATCH 24/48] MIPS: math-emu: Reinstate sNaN quieting handlers
  2015-04-03 22:23 [PATCH 00/48] FPU and FP emulation clean-ups, fixes and feature updates Maciej W. Rozycki
                   ` (21 preceding siblings ...)
  2015-04-03 22:25 ` [PATCH 23/48] MIPS: math-emu: Don't pass qNaNs through " Maciej W. Rozycki
@ 2015-04-03 22:25 ` Maciej W. Rozycki
  2015-04-03 22:25 ` [PATCH 25/48] MIPS: math-emu: Optimise NaN handling in comparisons Maciej W. Rozycki
                   ` (23 subsequent siblings)
  46 siblings, 0 replies; 62+ messages in thread
From: Maciej W. Rozycki @ 2015-04-03 22:25 UTC (permalink / raw)
  To: Ralf Baechle; +Cc: linux-mips

Revert the changes made by commit fdffbafb [Lots of FPU bug fixes from 
Kjeld Borch Egevang.] to `ieee754sp_nanxcpt' and `ieee754dp_nanxcpt' 
sNaN quieting handlers and their callers so that sNaN processing is done 
within the handlers againg.  Pass the sNaN causing an IEEE 754 invalid 
operation exception down to the relevant handler.  Pass the sNaN in `fs' 
where two sNaNs are supplied to a binary operation.

Set the Invalid Operation FCSR exception bits in the quieting handlers 
rather than at their call sites throughout.  Make the handlers exclusive 
for sNaN processing.

Signed-off-by: Maciej W. Rozycki <macro@linux-mips.org>
---
linux-mips-emu-nanxcpt.diff
Index: linux/arch/mips/math-emu/dp_add.c
===================================================================
--- linux.orig/arch/mips/math-emu/dp_add.c	2015-04-03 04:57:13.565700000 +0100
+++ linux/arch/mips/math-emu/dp_add.c	2015-04-03 04:58:15.978323000 +0100
@@ -37,19 +37,20 @@ union ieee754dp ieee754dp_add(union ieee
 	FLUSHYDP;
 
 	switch (CLPAIR(xc, yc)) {
-	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN):
 	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN):
-	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN):
 	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN):
 	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN):
 	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN):
 	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN):
+		return ieee754dp_nanxcpt(y);
+
+	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN):
+	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN):
 	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO):
 	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM):
 	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM):
 	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF):
-		ieee754_setcx(IEEE754_INVALID_OPERATION);
-		return ieee754dp_nanxcpt(ieee754dp_indef());
+		return ieee754dp_nanxcpt(x);
 
 	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN):
 	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN):
Index: linux/arch/mips/math-emu/dp_div.c
===================================================================
--- linux.orig/arch/mips/math-emu/dp_div.c	2015-04-03 04:57:13.566710000 +0100
+++ linux/arch/mips/math-emu/dp_div.c	2015-04-03 04:58:15.980324000 +0100
@@ -39,19 +39,20 @@ union ieee754dp ieee754dp_div(union ieee
 	FLUSHYDP;
 
 	switch (CLPAIR(xc, yc)) {
-	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN):
 	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN):
-	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN):
 	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN):
 	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN):
 	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN):
 	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN):
+		return ieee754dp_nanxcpt(y);
+
+	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN):
+	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN):
 	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO):
 	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM):
 	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM):
 	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF):
-		ieee754_setcx(IEEE754_INVALID_OPERATION);
-		return ieee754dp_nanxcpt(ieee754dp_indef());
+		return ieee754dp_nanxcpt(x);
 
 	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN):
 	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN):
Index: linux/arch/mips/math-emu/dp_fsp.c
===================================================================
--- linux.orig/arch/mips/math-emu/dp_fsp.c	2015-04-03 04:58:06.696244000 +0100
+++ linux/arch/mips/math-emu/dp_fsp.c	2015-04-03 04:58:15.982329000 +0100
@@ -40,8 +40,7 @@ union ieee754dp ieee754dp_fsp(union ieee
 
 	switch (xc) {
 	case IEEE754_CLASS_SNAN:
-		ieee754_setcx(IEEE754_INVALID_OPERATION);
-		return ieee754dp_nanxcpt(ieee754dp_indef());
+		return ieee754dp_nanxcpt(ieee754dp_nan_fsp(xs, xm));
 
 	case IEEE754_CLASS_QNAN:
 		return ieee754dp_nan_fsp(xs, xm);
Index: linux/arch/mips/math-emu/dp_mul.c
===================================================================
--- linux.orig/arch/mips/math-emu/dp_mul.c	2015-04-03 04:57:13.569704000 +0100
+++ linux/arch/mips/math-emu/dp_mul.c	2015-04-03 04:58:15.985318000 +0100
@@ -47,19 +47,20 @@ union ieee754dp ieee754dp_mul(union ieee
 	FLUSHYDP;
 
 	switch (CLPAIR(xc, yc)) {
-	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN):
 	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN):
-	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN):
 	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN):
 	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN):
 	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN):
 	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN):
+		return ieee754dp_nanxcpt(y);
+
+	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN):
+	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN):
 	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO):
 	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM):
 	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM):
 	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF):
-		ieee754_setcx(IEEE754_INVALID_OPERATION);
-		return ieee754dp_nanxcpt(ieee754dp_indef());
+		return ieee754dp_nanxcpt(x);
 
 	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN):
 	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN):
Index: linux/arch/mips/math-emu/dp_sqrt.c
===================================================================
--- linux.orig/arch/mips/math-emu/dp_sqrt.c	2015-04-03 04:58:06.699229000 +0100
+++ linux/arch/mips/math-emu/dp_sqrt.c	2015-04-03 04:58:15.986332000 +0100
@@ -42,14 +42,13 @@ union ieee754dp ieee754dp_sqrt(union iee
 
 	/* x == INF or NAN? */
 	switch (xc) {
+	case IEEE754_CLASS_SNAN:
+		return ieee754dp_nanxcpt(x);
+
 	case IEEE754_CLASS_QNAN:
 		/* sqrt(Nan) = Nan */
 		return x;
 
-	case IEEE754_CLASS_SNAN:
-		ieee754_setcx(IEEE754_INVALID_OPERATION);
-		return ieee754dp_nanxcpt(ieee754dp_indef());
-
 	case IEEE754_CLASS_ZERO:
 		/* sqrt(0) = 0 */
 		return x;
Index: linux/arch/mips/math-emu/dp_sub.c
===================================================================
--- linux.orig/arch/mips/math-emu/dp_sub.c	2015-04-03 04:57:13.572700000 +0100
+++ linux/arch/mips/math-emu/dp_sub.c	2015-04-03 04:58:15.989320000 +0100
@@ -37,19 +37,20 @@ union ieee754dp ieee754dp_sub(union ieee
 	FLUSHYDP;
 
 	switch (CLPAIR(xc, yc)) {
-	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN):
 	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN):
-	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN):
 	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN):
 	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN):
 	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN):
 	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN):
+		return ieee754dp_nanxcpt(y);
+
+	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN):
+	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN):
 	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO):
 	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM):
 	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM):
 	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF):
-		ieee754_setcx(IEEE754_INVALID_OPERATION);
-		return ieee754dp_nanxcpt(ieee754dp_indef());
+		return ieee754dp_nanxcpt(x);
 
 	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN):
 	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN):
Index: linux/arch/mips/math-emu/ieee754dp.c
===================================================================
--- linux.orig/arch/mips/math-emu/ieee754dp.c	2015-04-03 04:57:47.065031000 +0100
+++ linux/arch/mips/math-emu/ieee754dp.c	2015-04-03 04:58:15.991322000 +0100
@@ -42,18 +42,16 @@ static inline int ieee754dp_issnan(union
 }
 
 
+/*
+ * Raise the Invalid Operation IEEE 754 exception
+ * and convert the signaling NaN supplied to a quiet NaN.
+ */
 union ieee754dp __cold ieee754dp_nanxcpt(union ieee754dp r)
 {
-	assert(ieee754dp_isnan(r));
-
-	if (!ieee754dp_issnan(r))	/* QNAN does not cause invalid op !! */
-		return r;
-
-	/* If not enabled convert to a quiet NaN.  */
-	if (!ieee754_setandtestcx(IEEE754_INVALID_OPERATION))
-		return ieee754dp_indef();
+	assert(ieee754dp_issnan(r));
 
-	return r;
+	ieee754_setcx(IEEE754_INVALID_OPERATION);
+	return ieee754dp_indef();
 }
 
 static u64 ieee754dp_get_rounding(int sn, u64 xm)
Index: linux/arch/mips/math-emu/ieee754sp.c
===================================================================
--- linux.orig/arch/mips/math-emu/ieee754sp.c	2015-04-03 04:57:47.067040000 +0100
+++ linux/arch/mips/math-emu/ieee754sp.c	2015-04-03 04:58:15.993327000 +0100
@@ -42,18 +42,16 @@ static inline int ieee754sp_issnan(union
 }
 
 
+/*
+ * Raise the Invalid Operation IEEE 754 exception
+ * and convert the signaling NaN supplied to a quiet NaN.
+ */
 union ieee754sp __cold ieee754sp_nanxcpt(union ieee754sp r)
 {
-	assert(ieee754sp_isnan(r));
-
-	if (!ieee754sp_issnan(r))	/* QNAN does not cause invalid op !! */
-		return r;
-
-	/* If not enabled convert to a quiet NaN.  */
-	if (!ieee754_setandtestcx(IEEE754_INVALID_OPERATION))
-		return ieee754sp_indef();
+	assert(ieee754sp_issnan(r));
 
-	return r;
+	ieee754_setcx(IEEE754_INVALID_OPERATION);
+	return ieee754sp_indef();
 }
 
 static unsigned ieee754sp_get_rounding(int sn, unsigned xm)
Index: linux/arch/mips/math-emu/sp_add.c
===================================================================
--- linux.orig/arch/mips/math-emu/sp_add.c	2015-04-03 04:57:13.576708000 +0100
+++ linux/arch/mips/math-emu/sp_add.c	2015-04-03 04:58:16.002321000 +0100
@@ -37,19 +37,20 @@ union ieee754sp ieee754sp_add(union ieee
 	FLUSHYSP;
 
 	switch (CLPAIR(xc, yc)) {
-	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN):
 	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN):
-	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN):
 	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN):
 	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN):
 	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN):
 	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN):
+		return ieee754sp_nanxcpt(y);
+
+	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN):
+	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN):
 	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO):
 	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM):
 	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM):
 	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF):
-		ieee754_setcx(IEEE754_INVALID_OPERATION);
-		return ieee754sp_nanxcpt(ieee754sp_indef());
+		return ieee754sp_nanxcpt(x);
 
 	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN):
 	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN):
Index: linux/arch/mips/math-emu/sp_div.c
===================================================================
--- linux.orig/arch/mips/math-emu/sp_div.c	2015-04-03 04:57:13.578697000 +0100
+++ linux/arch/mips/math-emu/sp_div.c	2015-04-03 04:58:16.005320000 +0100
@@ -39,19 +39,20 @@ union ieee754sp ieee754sp_div(union ieee
 	FLUSHYSP;
 
 	switch (CLPAIR(xc, yc)) {
-	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN):
 	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN):
-	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN):
 	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN):
 	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN):
 	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN):
 	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN):
+		return ieee754sp_nanxcpt(y);
+
+	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN):
+	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN):
 	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO):
 	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM):
 	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM):
 	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF):
-		ieee754_setcx(IEEE754_INVALID_OPERATION);
-		return ieee754sp_nanxcpt(ieee754sp_indef());
+		return ieee754sp_nanxcpt(x);
 
 	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN):
 	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN):
Index: linux/arch/mips/math-emu/sp_fdp.c
===================================================================
--- linux.orig/arch/mips/math-emu/sp_fdp.c	2015-04-03 04:58:06.701235000 +0100
+++ linux/arch/mips/math-emu/sp_fdp.c	2015-04-03 04:58:16.006329000 +0100
@@ -43,8 +43,7 @@ union ieee754sp ieee754sp_fdp(union ieee
 
 	switch (xc) {
 	case IEEE754_CLASS_SNAN:
-		ieee754_setcx(IEEE754_INVALID_OPERATION);
-		return ieee754sp_nanxcpt(ieee754sp_indef());
+		return ieee754sp_nanxcpt(ieee754sp_nan_fdp(xs, xm));
 
 	case IEEE754_CLASS_QNAN:
 		nan = ieee754sp_nan_fdp(xs, xm);
Index: linux/arch/mips/math-emu/sp_mul.c
===================================================================
--- linux.orig/arch/mips/math-emu/sp_mul.c	2015-04-03 04:57:13.580714000 +0100
+++ linux/arch/mips/math-emu/sp_mul.c	2015-04-03 04:58:16.009320000 +0100
@@ -47,19 +47,20 @@ union ieee754sp ieee754sp_mul(union ieee
 	FLUSHYSP;
 
 	switch (CLPAIR(xc, yc)) {
-	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN):
 	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN):
-	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN):
 	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN):
 	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN):
 	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN):
 	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN):
+		return ieee754sp_nanxcpt(y);
+
+	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN):
+	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN):
 	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO):
 	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM):
 	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM):
 	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF):
-		ieee754_setcx(IEEE754_INVALID_OPERATION);
-		return ieee754sp_nanxcpt(ieee754sp_indef());
+		return ieee754sp_nanxcpt(x);
 
 	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN):
 	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN):
Index: linux/arch/mips/math-emu/sp_sqrt.c
===================================================================
--- linux.orig/arch/mips/math-emu/sp_sqrt.c	2015-04-03 04:58:06.703246000 +0100
+++ linux/arch/mips/math-emu/sp_sqrt.c	2015-04-03 04:58:16.011320000 +0100
@@ -35,14 +35,13 @@ union ieee754sp ieee754sp_sqrt(union iee
 
 	/* x == INF or NAN? */
 	switch (xc) {
+	case IEEE754_CLASS_SNAN:
+		return ieee754sp_nanxcpt(x);
+
 	case IEEE754_CLASS_QNAN:
 		/* sqrt(Nan) = Nan */
 		return x;
 
-	case IEEE754_CLASS_SNAN:
-		ieee754_setcx(IEEE754_INVALID_OPERATION);
-		return ieee754sp_nanxcpt(ieee754sp_indef());
-
 	case IEEE754_CLASS_ZERO:
 		/* sqrt(0) = 0 */
 		return x;
Index: linux/arch/mips/math-emu/sp_sub.c
===================================================================
--- linux.orig/arch/mips/math-emu/sp_sub.c	2015-04-03 04:57:13.584711000 +0100
+++ linux/arch/mips/math-emu/sp_sub.c	2015-04-03 04:58:16.013323000 +0100
@@ -37,19 +37,20 @@ union ieee754sp ieee754sp_sub(union ieee
 	FLUSHYSP;
 
 	switch (CLPAIR(xc, yc)) {
-	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN):
 	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN):
-	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN):
 	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN):
 	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN):
 	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN):
 	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN):
+		return ieee754sp_nanxcpt(y);
+
+	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN):
+	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN):
 	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO):
 	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM):
 	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM):
 	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF):
-		ieee754_setcx(IEEE754_INVALID_OPERATION);
-		return ieee754sp_nanxcpt(ieee754sp_indef());
+		return ieee754sp_nanxcpt(x);
 
 	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN):
 	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN):

^ permalink raw reply	[flat|nested] 62+ messages in thread

* [PATCH 25/48] MIPS: math-emu: Optimise NaN handling in comparisons
  2015-04-03 22:23 [PATCH 00/48] FPU and FP emulation clean-ups, fixes and feature updates Maciej W. Rozycki
                   ` (22 preceding siblings ...)
  2015-04-03 22:25 ` [PATCH 24/48] MIPS: math-emu: Reinstate sNaN " Maciej W. Rozycki
@ 2015-04-03 22:25 ` Maciej W. Rozycki
  2015-04-03 22:25 ` [PATCH 26/48] MIPS: math-emu: Remove redundant code from NaN comparison Maciej W. Rozycki
                   ` (22 subsequent siblings)
  46 siblings, 0 replies; 62+ messages in thread
From: Maciej W. Rozycki @ 2015-04-03 22:25 UTC (permalink / raw)
  To: Ralf Baechle; +Cc: linux-mips

We have the input operands already classified in `ieee754sp_cmp' and 
`ieee754dp_cmp' comparison operations, so use the class obtained to tell 
NaNs and numbers apart rather than classifying inputs again for this 
purpose, reducing the size of code by 24 and 40 instructions or 96 and 
160 bytes respectively.

Signed-off-by: Maciej W. Rozycki <macro@linux-mips.org>
---
linux-mips-emu-cmp-nan.diff
Index: linux/arch/mips/math-emu/dp_cmp.c
===================================================================
--- linux.orig/arch/mips/math-emu/dp_cmp.c	2015-04-03 13:23:28.348835000 +0100
+++ linux/arch/mips/math-emu/dp_cmp.c	2015-04-03 13:23:31.663867000 +0100
@@ -35,7 +35,7 @@ int ieee754dp_cmp(union ieee754dp x, uni
 	FLUSHYDP;
 	ieee754_clearcx();	/* Even clear inexact flag here */
 
-	if (ieee754dp_isnan(x) || ieee754dp_isnan(y)) {
+	if (ieee754_class_nan(xc) || ieee754_class_nan(yc)) {
 		if (sig ||
 		    xc == IEEE754_CLASS_SNAN || yc == IEEE754_CLASS_SNAN)
 			ieee754_setcx(IEEE754_INVALID_OPERATION);
Index: linux/arch/mips/math-emu/ieee754dp.c
===================================================================
--- linux.orig/arch/mips/math-emu/ieee754dp.c	2015-04-03 13:23:28.349836000 +0100
+++ linux/arch/mips/math-emu/ieee754dp.c	2015-04-03 13:23:31.665869000 +0100
@@ -32,7 +32,7 @@ int ieee754dp_class(union ieee754dp x)
 
 int ieee754dp_isnan(union ieee754dp x)
 {
-	return ieee754dp_class(x) >= IEEE754_CLASS_SNAN;
+	return ieee754_class_nan(ieee754dp_class(x));
 }
 
 static inline int ieee754dp_issnan(union ieee754dp x)
Index: linux/arch/mips/math-emu/ieee754int.h
===================================================================
--- linux.orig/arch/mips/math-emu/ieee754int.h	2015-04-03 13:23:28.350839000 +0100
+++ linux/arch/mips/math-emu/ieee754int.h	2015-04-03 13:23:31.667874000 +0100
@@ -44,6 +44,11 @@ static inline int ieee754_setandtestcx(c
 	return ieee754_csr.mx & x;
 }
 
+static inline int ieee754_class_nan(int xc)
+{
+	return xc >= IEEE754_CLASS_SNAN;
+}
+
 #define COMPXSP \
 	unsigned xm; int xe; int xs __maybe_unused; int xc
 
Index: linux/arch/mips/math-emu/ieee754sp.c
===================================================================
--- linux.orig/arch/mips/math-emu/ieee754sp.c	2015-04-03 13:23:28.352832000 +0100
+++ linux/arch/mips/math-emu/ieee754sp.c	2015-04-03 13:23:31.678870000 +0100
@@ -32,7 +32,7 @@ int ieee754sp_class(union ieee754sp x)
 
 int ieee754sp_isnan(union ieee754sp x)
 {
-	return ieee754sp_class(x) >= IEEE754_CLASS_SNAN;
+	return ieee754_class_nan(ieee754sp_class(x));
 }
 
 static inline int ieee754sp_issnan(union ieee754sp x)
Index: linux/arch/mips/math-emu/sp_cmp.c
===================================================================
--- linux.orig/arch/mips/math-emu/sp_cmp.c	2015-04-03 13:23:28.354835000 +0100
+++ linux/arch/mips/math-emu/sp_cmp.c	2015-04-03 13:23:31.680870000 +0100
@@ -35,7 +35,7 @@ int ieee754sp_cmp(union ieee754sp x, uni
 	FLUSHYSP;
 	ieee754_clearcx();	/* Even clear inexact flag here */
 
-	if (ieee754sp_isnan(x) || ieee754sp_isnan(y)) {
+	if (ieee754_class_nan(xc) || ieee754_class_nan(yc)) {
 		if (sig ||
 		    xc == IEEE754_CLASS_SNAN || yc == IEEE754_CLASS_SNAN)
 			ieee754_setcx(IEEE754_INVALID_OPERATION);

^ permalink raw reply	[flat|nested] 62+ messages in thread

* [PATCH 26/48] MIPS: math-emu: Remove redundant code from NaN comparison
  2015-04-03 22:23 [PATCH 00/48] FPU and FP emulation clean-ups, fixes and feature updates Maciej W. Rozycki
                   ` (23 preceding siblings ...)
  2015-04-03 22:25 ` [PATCH 25/48] MIPS: math-emu: Optimise NaN handling in comparisons Maciej W. Rozycki
@ 2015-04-03 22:25 ` Maciej W. Rozycki
  2015-04-03 22:25 ` [PATCH 27/48] MIPS: math-emu: Remove dead comparison helpers Maciej W. Rozycki
                   ` (21 subsequent siblings)
  46 siblings, 0 replies; 62+ messages in thread
From: Maciej W. Rozycki @ 2015-04-03 22:25 UTC (permalink / raw)
  To: Ralf Baechle; +Cc: linux-mips

Remove a redundant call to `ieee754_setandtestcx' in `ieee754sp_cmp' and 
`ieee754dp_cmp'.  The IEEE 754 exception requested will have already 
been set by a call to `ieee754_setcx' immediately above, because `sig' 
has to be non-zero to reach here, and the comparison result returned 
will be 0 regardless of the result from the call.  Simplify the return 
expression remaining.  All this reducing the size of code by 16 and 12 
instructions or 64 and 48 bytes respectively.

Signed-off-by: Maciej W. Rozycki <macro@linux-mips.org>
---
linux-mips-emu-cmp.diff
Index: linux/arch/mips/math-emu/dp_cmp.c
===================================================================
--- linux.orig/arch/mips/math-emu/dp_cmp.c	2015-04-03 13:23:31.663867000 +0100
+++ linux/arch/mips/math-emu/dp_cmp.c	2015-04-03 13:23:37.279924000 +0100
@@ -39,13 +39,7 @@ int ieee754dp_cmp(union ieee754dp x, uni
 		if (sig ||
 		    xc == IEEE754_CLASS_SNAN || yc == IEEE754_CLASS_SNAN)
 			ieee754_setcx(IEEE754_INVALID_OPERATION);
-		if (cmp & IEEE754_CUN)
-			return 1;
-		if (cmp & (IEEE754_CLT | IEEE754_CGT)) {
-			if (sig && ieee754_setandtestcx(IEEE754_INVALID_OPERATION))
-				return 0;
-		}
-		return 0;
+		return (cmp & IEEE754_CUN) != 0;
 	} else {
 		vx = x.bits;
 		vy = y.bits;
Index: linux/arch/mips/math-emu/sp_cmp.c
===================================================================
--- linux.orig/arch/mips/math-emu/sp_cmp.c	2015-04-03 13:23:31.680870000 +0100
+++ linux/arch/mips/math-emu/sp_cmp.c	2015-04-03 13:23:37.281921000 +0100
@@ -39,13 +39,7 @@ int ieee754sp_cmp(union ieee754sp x, uni
 		if (sig ||
 		    xc == IEEE754_CLASS_SNAN || yc == IEEE754_CLASS_SNAN)
 			ieee754_setcx(IEEE754_INVALID_OPERATION);
-		if (cmp & IEEE754_CUN)
-			return 1;
-		if (cmp & (IEEE754_CLT | IEEE754_CGT)) {
-			if (sig && ieee754_setandtestcx(IEEE754_INVALID_OPERATION))
-				return 0;
-		}
-		return 0;
+		return (cmp & IEEE754_CUN) != 0;
 	} else {
 		vx = x.bits;
 		vy = y.bits;

^ permalink raw reply	[flat|nested] 62+ messages in thread

* [PATCH 27/48] MIPS: math-emu: Remove dead comparison helpers
  2015-04-03 22:23 [PATCH 00/48] FPU and FP emulation clean-ups, fixes and feature updates Maciej W. Rozycki
                   ` (24 preceding siblings ...)
  2015-04-03 22:25 ` [PATCH 26/48] MIPS: math-emu: Remove redundant code from NaN comparison Maciej W. Rozycki
@ 2015-04-03 22:25 ` Maciej W. Rozycki
  2015-04-03 22:25 ` [PATCH 29/48] MIPS: math-emu: Make NaN classifiers static Maciej W. Rozycki
                   ` (20 subsequent siblings)
  46 siblings, 0 replies; 62+ messages in thread
From: Maciej W. Rozycki @ 2015-04-03 22:25 UTC (permalink / raw)
  To: Ralf Baechle; +Cc: linux-mips

None of the comparison helpers in ieee754.h is used, remove them.

Signed-off-by: Maciej W. Rozycki <macro@linux-mips.org>
---
linux-mips-emu-cmp-helper.diff
Index: linux/arch/mips/math-emu/ieee754.h
===================================================================
--- linux.orig/arch/mips/math-emu/ieee754.h	2015-04-03 12:38:50.000000000 +0100
+++ linux/arch/mips/math-emu/ieee754.h	2015-04-03 13:42:52.928882000 +0100
@@ -126,71 +126,6 @@ enum {
 #define IEEE754_CGT	0x04
 #define IEEE754_CUN	0x08
 
-/* "normal" comparisons
-*/
-static inline int ieee754sp_eq(union ieee754sp x, union ieee754sp y)
-{
-	return ieee754sp_cmp(x, y, IEEE754_CEQ, 0);
-}
-
-static inline int ieee754sp_ne(union ieee754sp x, union ieee754sp y)
-{
-	return ieee754sp_cmp(x, y,
-			     IEEE754_CLT | IEEE754_CGT | IEEE754_CUN, 0);
-}
-
-static inline int ieee754sp_lt(union ieee754sp x, union ieee754sp y)
-{
-	return ieee754sp_cmp(x, y, IEEE754_CLT, 0);
-}
-
-static inline int ieee754sp_le(union ieee754sp x, union ieee754sp y)
-{
-	return ieee754sp_cmp(x, y, IEEE754_CLT | IEEE754_CEQ, 0);
-}
-
-static inline int ieee754sp_gt(union ieee754sp x, union ieee754sp y)
-{
-	return ieee754sp_cmp(x, y, IEEE754_CGT, 0);
-}
-
-
-static inline int ieee754sp_ge(union ieee754sp x, union ieee754sp y)
-{
-	return ieee754sp_cmp(x, y, IEEE754_CGT | IEEE754_CEQ, 0);
-}
-
-static inline int ieee754dp_eq(union ieee754dp x, union ieee754dp y)
-{
-	return ieee754dp_cmp(x, y, IEEE754_CEQ, 0);
-}
-
-static inline int ieee754dp_ne(union ieee754dp x, union ieee754dp y)
-{
-	return ieee754dp_cmp(x, y,
-			     IEEE754_CLT | IEEE754_CGT | IEEE754_CUN, 0);
-}
-
-static inline int ieee754dp_lt(union ieee754dp x, union ieee754dp y)
-{
-	return ieee754dp_cmp(x, y, IEEE754_CLT, 0);
-}
-
-static inline int ieee754dp_le(union ieee754dp x, union ieee754dp y)
-{
-	return ieee754dp_cmp(x, y, IEEE754_CLT | IEEE754_CEQ, 0);
-}
-
-static inline int ieee754dp_gt(union ieee754dp x, union ieee754dp y)
-{
-	return ieee754dp_cmp(x, y, IEEE754_CGT, 0);
-}
-
-static inline int ieee754dp_ge(union ieee754dp x, union ieee754dp y)
-{
-	return ieee754dp_cmp(x, y, IEEE754_CGT | IEEE754_CEQ, 0);
-}
-
 /*
  * The control status register
  */

^ permalink raw reply	[flat|nested] 62+ messages in thread

* [PATCH 29/48] MIPS: math-emu: Make NaN classifiers static
  2015-04-03 22:23 [PATCH 00/48] FPU and FP emulation clean-ups, fixes and feature updates Maciej W. Rozycki
                   ` (25 preceding siblings ...)
  2015-04-03 22:25 ` [PATCH 27/48] MIPS: math-emu: Remove dead comparison helpers Maciej W. Rozycki
@ 2015-04-03 22:25 ` Maciej W. Rozycki
  2015-04-03 23:22   ` Sergei Shtylyov
  2015-04-03 22:26 ` [PATCH 30/48] MIPS: Correct `nofpu' non-functionality Maciej W. Rozycki
                   ` (19 subsequent siblings)
  46 siblings, 1 reply; 62+ messages in thread
From: Maciej W. Rozycki @ 2015-04-03 22:25 UTC (permalink / raw)
  To: Ralf Baechle; +Cc: linux-mips

The `ieee754sp_isnan' and `ieee754dp_isnan' NaN classifiers are now no 
longer externally referred, remove their header prototypes and make them 
local to the two only respective places still making use of them.

Signed-off-by: Maciej W. Rozycki <macro@linux-mips.org>
---
linux-mips-emu-isnan.diff
Index: linux/arch/mips/math-emu/ieee754dp.c
===================================================================
--- linux.orig/arch/mips/math-emu/ieee754dp.c	2015-04-02 20:27:55.587207000 +0100
+++ linux/arch/mips/math-emu/ieee754dp.c	2015-04-02 20:27:56.032207000 +0100
@@ -30,7 +30,7 @@ int ieee754dp_class(union ieee754dp x)
 	return xc;
 }
 
-int ieee754dp_isnan(union ieee754dp x)
+static inline int ieee754dp_isnan(union ieee754dp x)
 {
 	return ieee754_class_nan(ieee754dp_class(x));
 }
Index: linux/arch/mips/math-emu/ieee754dp.h
===================================================================
--- linux.orig/arch/mips/math-emu/ieee754dp.h	2015-04-02 20:18:50.309509000 +0100
+++ linux/arch/mips/math-emu/ieee754dp.h	2015-04-02 20:27:56.035204000 +0100
@@ -77,6 +77,5 @@ static inline union ieee754dp builddp(in
 	return r;
 }
 
-extern int ieee754dp_isnan(union ieee754dp);
 extern union ieee754dp __cold ieee754dp_nanxcpt(union ieee754dp);
 extern union ieee754dp ieee754dp_format(int, int, u64);
Index: linux/arch/mips/math-emu/ieee754sp.c
===================================================================
--- linux.orig/arch/mips/math-emu/ieee754sp.c	2015-04-02 20:27:55.601223000 +0100
+++ linux/arch/mips/math-emu/ieee754sp.c	2015-04-02 20:27:56.037202000 +0100
@@ -30,7 +30,7 @@ int ieee754sp_class(union ieee754sp x)
 	return xc;
 }
 
-int ieee754sp_isnan(union ieee754sp x)
+static inline int ieee754sp_isnan(union ieee754sp x)
 {
 	return ieee754_class_nan(ieee754sp_class(x));
 }
Index: linux/arch/mips/math-emu/ieee754sp.h
===================================================================
--- linux.orig/arch/mips/math-emu/ieee754sp.h	2015-04-02 20:18:50.314505000 +0100
+++ linux/arch/mips/math-emu/ieee754sp.h	2015-04-02 20:27:56.039206000 +0100
@@ -82,6 +82,5 @@ static inline union ieee754sp buildsp(in
 	return r;
 }
 
-extern int ieee754sp_isnan(union ieee754sp);
 extern union ieee754sp __cold ieee754sp_nanxcpt(union ieee754sp);
 extern union ieee754sp ieee754sp_format(int, int, unsigned);

^ permalink raw reply	[flat|nested] 62+ messages in thread

* [PATCH 30/48] MIPS: Correct `nofpu' non-functionality
  2015-04-03 22:23 [PATCH 00/48] FPU and FP emulation clean-ups, fixes and feature updates Maciej W. Rozycki
                   ` (26 preceding siblings ...)
  2015-04-03 22:25 ` [PATCH 29/48] MIPS: math-emu: Make NaN classifiers static Maciej W. Rozycki
@ 2015-04-03 22:26 ` Maciej W. Rozycki
  2015-04-03 22:26 ` [PATCH 31/48] MIPS: Correct MIPS16 BREAK code interpretation Maciej W. Rozycki
                   ` (18 subsequent siblings)
  46 siblings, 0 replies; 62+ messages in thread
From: Maciej W. Rozycki @ 2015-04-03 22:26 UTC (permalink / raw)
  To: Ralf Baechle; +Cc: linux-mips

The `cpu_has_fpu' feature flag must not be hardcoded to 1 or the `nofpu'
kernel option will be ignored.  Remove any such overrides and add a 
cautionary note.  Hardcoding to 0 is fine for FPU-less platforms.

Signed-off-by: Maciej W. Rozycki <macro@linux-mips.org>
---
linux-mips-cpu-has-fpu.patch
Index: linux/arch/mips/include/asm/cpu-features.h
===================================================================
--- linux.orig/arch/mips/include/asm/cpu-features.h	2015-04-02 20:18:50.163509000 +0100
+++ linux/arch/mips/include/asm/cpu-features.h	2015-04-02 20:27:56.252205000 +0100
@@ -68,6 +68,7 @@
 #ifndef cpu_has_octeon_cache
 #define cpu_has_octeon_cache	0
 #endif
+/* Don't override `cpu_has_fpu' to 1 or the "nofpu" option won't work.  */
 #ifndef cpu_has_fpu
 #define cpu_has_fpu		(current_cpu_data.options & MIPS_CPU_FPU)
 #define raw_cpu_has_fpu		(raw_current_cpu_data.options & MIPS_CPU_FPU)
Index: linux/arch/mips/include/asm/mach-cobalt/cpu-feature-overrides.h
===================================================================
--- linux.orig/arch/mips/include/asm/mach-cobalt/cpu-feature-overrides.h	2015-04-02 20:18:50.166512000 +0100
+++ linux/arch/mips/include/asm/mach-cobalt/cpu-feature-overrides.h	2015-04-02 20:27:56.276209000 +0100
@@ -14,7 +14,6 @@
 #define cpu_has_3k_cache	0
 #define cpu_has_4k_cache	1
 #define cpu_has_tx39_cache	0
-#define cpu_has_fpu		1
 #define cpu_has_32fpr		1
 #define cpu_has_counter		1
 #define cpu_has_watch		0
Index: linux/arch/mips/include/asm/mach-dec/cpu-feature-overrides.h
===================================================================
--- linux.orig/arch/mips/include/asm/mach-dec/cpu-feature-overrides.h	2015-04-02 20:18:50.169511000 +0100
+++ linux/arch/mips/include/asm/mach-dec/cpu-feature-overrides.h	2015-04-02 20:27:56.289206000 +0100
@@ -15,7 +15,6 @@
 /* Generic ones first.  */
 #define cpu_has_tlb			1
 #define cpu_has_tx39_cache		0
-#define cpu_has_fpu			1
 #define cpu_has_divec			0
 #define cpu_has_prefetch		0
 #define cpu_has_mcheck			0
Index: linux/arch/mips/include/asm/mach-ip22/cpu-feature-overrides.h
===================================================================
--- linux.orig/arch/mips/include/asm/mach-ip22/cpu-feature-overrides.h	2015-04-02 20:18:50.172504000 +0100
+++ linux/arch/mips/include/asm/mach-ip22/cpu-feature-overrides.h	2015-04-02 20:27:56.299204000 +0100
@@ -16,7 +16,6 @@
 #define cpu_has_tlb		1
 #define cpu_has_4kex		1
 #define cpu_has_4k_cache	1
-#define cpu_has_fpu		1
 #define cpu_has_32fpr		1
 #define cpu_has_counter		1
 #define cpu_has_mips16		0
Index: linux/arch/mips/include/asm/mach-ip32/cpu-feature-overrides.h
===================================================================
--- linux.orig/arch/mips/include/asm/mach-ip32/cpu-feature-overrides.h	2015-04-02 20:18:50.175504000 +0100
+++ linux/arch/mips/include/asm/mach-ip32/cpu-feature-overrides.h	2015-04-02 20:27:56.306207000 +0100
@@ -26,7 +26,6 @@
 /* Settings which are common for all ip32 CPUs */
 #define cpu_has_tlb		1
 #define cpu_has_4kex		1
-#define cpu_has_fpu		1
 #define cpu_has_32fpr		1
 #define cpu_has_counter		1
 #define cpu_has_mips16		0
Index: linux/arch/mips/include/asm/mach-loongson/cpu-feature-overrides.h
===================================================================
--- linux.orig/arch/mips/include/asm/mach-loongson/cpu-feature-overrides.h	2015-04-02 20:18:50.178504000 +0100
+++ linux/arch/mips/include/asm/mach-loongson/cpu-feature-overrides.h	2015-04-02 20:27:56.323205000 +0100
@@ -34,7 +34,6 @@
 #define cpu_has_dsp		0
 #define cpu_has_dsp2		0
 #define cpu_has_ejtag		0
-#define cpu_has_fpu		1
 #define cpu_has_ic_fills_f_dc	0
 #define cpu_has_inclusive_pcaches	1
 #define cpu_has_llsc		1
Index: linux/arch/mips/include/asm/mach-rm/cpu-feature-overrides.h
===================================================================
--- linux.orig/arch/mips/include/asm/mach-rm/cpu-feature-overrides.h	2015-04-02 20:18:50.182511000 +0100
+++ linux/arch/mips/include/asm/mach-rm/cpu-feature-overrides.h	2015-04-02 20:27:56.333207000 +0100
@@ -15,7 +15,6 @@
 #define cpu_has_tlb		1
 #define cpu_has_4kex		1
 #define cpu_has_4k_cache	1
-#define cpu_has_fpu		1
 #define cpu_has_32fpr		1
 #define cpu_has_counter		1
 #define cpu_has_watch		0

^ permalink raw reply	[flat|nested] 62+ messages in thread

* [PATCH 31/48] MIPS: Correct MIPS16 BREAK code interpretation
  2015-04-03 22:23 [PATCH 00/48] FPU and FP emulation clean-ups, fixes and feature updates Maciej W. Rozycki
                   ` (27 preceding siblings ...)
  2015-04-03 22:26 ` [PATCH 30/48] MIPS: Correct `nofpu' non-functionality Maciej W. Rozycki
@ 2015-04-03 22:26 ` Maciej W. Rozycki
  2015-04-03 22:26 ` [PATCH 32/48] MIPS: BREAK instruction interpretation corrections Maciej W. Rozycki
                   ` (17 subsequent siblings)
  46 siblings, 0 replies; 62+ messages in thread
From: Maciej W. Rozycki @ 2015-04-03 22:26 UTC (permalink / raw)
  To: Ralf Baechle; +Cc: linux-mips

Correct the interpretation of the immediate MIPS16 BREAK instruction 
code embedded in the instruction word across bits 10:5 rather than 11:6 
as current code implies, fixing the interpretation of integer overflow 
and divide by zero traps.

Signed-off-by: Maciej W. Rozycki <macro@linux-mips.org>
---
linux-mips-do-bp16.diff
Index: linux/arch/mips/kernel/traps.c
===================================================================
--- linux.orig/arch/mips/kernel/traps.c	2015-04-02 20:27:54.637186000 +0100
+++ linux/arch/mips/kernel/traps.c	2015-04-02 20:27:56.610207000 +0100
@@ -925,7 +925,7 @@ asmlinkage void do_bp(struct pt_regs *re
 			if (__get_user(instr[0],
 				       (u16 __user *)msk_isa16_mode(epc)))
 				goto out_sigsegv;
-			bcode = (instr[0] >> 6) & 0x3f;
+			bcode = (instr[0] >> 5) & 0x3f;
 			do_trap_or_bp(regs, bcode, "Break");
 			goto out;
 		}

^ permalink raw reply	[flat|nested] 62+ messages in thread

* [PATCH 32/48] MIPS: BREAK instruction interpretation corrections
  2015-04-03 22:23 [PATCH 00/48] FPU and FP emulation clean-ups, fixes and feature updates Maciej W. Rozycki
                   ` (28 preceding siblings ...)
  2015-04-03 22:26 ` [PATCH 31/48] MIPS: Correct MIPS16 BREAK code interpretation Maciej W. Rozycki
@ 2015-04-03 22:26 ` Maciej W. Rozycki
  2015-04-03 22:26 ` [PATCH 33/48] MIPS: Fix BREAK code interpretation heuristics Maciej W. Rozycki
                   ` (16 subsequent siblings)
  46 siblings, 0 replies; 62+ messages in thread
From: Maciej W. Rozycki @ 2015-04-03 22:26 UTC (permalink / raw)
  To: Ralf Baechle; +Cc: linux-mips

Add the missing microMIPS BREAK16 instruction code interpretation and 
reshape code removing instruction fetching duplication and the separate 
call to `do_trap_or_bp' in the MIPS16 path.

Signed-off-by: Maciej W. Rozycki <macro@linux-mips.org>
---
linux-mips-do-bp.diff
Index: linux/arch/mips/kernel/traps.c
===================================================================
--- linux.orig/arch/mips/kernel/traps.c	2015-04-02 20:27:56.610207000 +0100
+++ linux/arch/mips/kernel/traps.c	2015-04-02 20:27:56.780209000 +0100
@@ -901,10 +901,9 @@ void do_trap_or_bp(struct pt_regs *regs,
 
 asmlinkage void do_bp(struct pt_regs *regs)
 {
+	unsigned long epc = msk_isa16_mode(exception_epc(regs));
 	unsigned int opcode, bcode;
 	enum ctx_state prev_state;
-	unsigned long epc;
-	u16 instr[2];
 	mm_segment_t seg;
 
 	seg = get_fs();
@@ -913,26 +912,28 @@ asmlinkage void do_bp(struct pt_regs *re
 
 	prev_state = exception_enter();
 	if (get_isa16_mode(regs->cp0_epc)) {
-		/* Calculate EPC. */
-		epc = exception_epc(regs);
-		if (cpu_has_mmips) {
-			if ((__get_user(instr[0], (u16 __user *)msk_isa16_mode(epc)) ||
-			    (__get_user(instr[1], (u16 __user *)msk_isa16_mode(epc + 2)))))
-				goto out_sigsegv;
-			opcode = (instr[0] << 16) | instr[1];
-		} else {
+		u16 instr[2];
+
+		if (__get_user(instr[0], (u16 __user *)epc))
+			goto out_sigsegv;
+
+		if (!cpu_has_mmips) {
 			/* MIPS16e mode */
-			if (__get_user(instr[0],
-				       (u16 __user *)msk_isa16_mode(epc)))
-				goto out_sigsegv;
 			bcode = (instr[0] >> 5) & 0x3f;
-			do_trap_or_bp(regs, bcode, "Break");
-			goto out;
+		} else if (mm_insn_16bit(instr[0])) {
+			/* 16-bit microMIPS BREAK */
+			bcode = instr[0] & 0xf;
+		} else {
+			/* 32-bit microMIPS BREAK */
+			if (__get_user(instr[1], (u16 __user *)(epc + 2)))
+				goto out_sigsegv;
+			opcode = (instr[0] << 16) | instr[1];
+			bcode = (opcode >> 6) & ((1 << 20) - 1);
 		}
 	} else {
-		if (__get_user(opcode,
-			       (unsigned int __user *) exception_epc(regs)))
+		if (__get_user(opcode, (unsigned int __user *)epc))
 			goto out_sigsegv;
+		bcode = (opcode >> 6) & ((1 << 20) - 1);
 	}
 
 	/*
@@ -941,7 +942,6 @@ asmlinkage void do_bp(struct pt_regs *re
 	 * Gas is bug-compatible, but not always, grrr...
 	 * We handle both cases with a simple heuristics.  --macro
 	 */
-	bcode = ((opcode >> 6) & ((1 << 20) - 1));
 	if (bcode >= (1 << 10))
 		bcode >>= 10;
 

^ permalink raw reply	[flat|nested] 62+ messages in thread

* [PATCH 33/48] MIPS: Fix BREAK code interpretation heuristics
  2015-04-03 22:23 [PATCH 00/48] FPU and FP emulation clean-ups, fixes and feature updates Maciej W. Rozycki
                   ` (29 preceding siblings ...)
  2015-04-03 22:26 ` [PATCH 32/48] MIPS: BREAK instruction interpretation corrections Maciej W. Rozycki
@ 2015-04-03 22:26 ` Maciej W. Rozycki
  2015-04-03 22:26 ` [PATCH 34/48] MIPS: math-emu: Fix delay-slot emulation cache incoherency Maciej W. Rozycki
                   ` (15 subsequent siblings)
  46 siblings, 0 replies; 62+ messages in thread
From: Maciej W. Rozycki @ 2015-04-03 22:26 UTC (permalink / raw)
  To: Ralf Baechle; +Cc: linux-mips

Do not lose the other half of the BREAK code where there is an upper 
half.  This is so that e.g. `BREAK 7, 7' is not interpreted as a divide 
by zero trap, while `BREAK 0, 7' or `BREAK 7, 0' still are.

Signed-off-by: Maciej W. Rozycki <macro@linux-mips.org>
---
linux-mips-do-bp-code.diff
Index: linux/arch/mips/kernel/traps.c
===================================================================
--- linux.orig/arch/mips/kernel/traps.c	2015-04-02 20:27:56.780209000 +0100
+++ linux/arch/mips/kernel/traps.c	2015-04-02 20:27:56.948213000 +0100
@@ -943,7 +943,7 @@ asmlinkage void do_bp(struct pt_regs *re
 	 * We handle both cases with a simple heuristics.  --macro
 	 */
 	if (bcode >= (1 << 10))
-		bcode >>= 10;
+		bcode = ((bcode & ((1 << 10) - 1)) << 10) | (bcode >> 10);
 
 	/*
 	 * notify the kprobe handlers, if instruction is likely to

^ permalink raw reply	[flat|nested] 62+ messages in thread

* [PATCH 34/48] MIPS: math-emu: Fix delay-slot emulation cache incoherency
  2015-04-03 22:23 [PATCH 00/48] FPU and FP emulation clean-ups, fixes and feature updates Maciej W. Rozycki
                   ` (30 preceding siblings ...)
  2015-04-03 22:26 ` [PATCH 33/48] MIPS: Fix BREAK code interpretation heuristics Maciej W. Rozycki
@ 2015-04-03 22:26 ` Maciej W. Rozycki
  2015-04-03 22:26 ` [PATCH 35/48] MIPS: Correct MIPS I FP context layout Maciej W. Rozycki
                   ` (14 subsequent siblings)
  46 siblings, 0 replies; 62+ messages in thread
From: Maciej W. Rozycki @ 2015-04-03 22:26 UTC (permalink / raw)
  To: Ralf Baechle; +Cc: linux-mips

Correct a cache coherency regression introduced with be1664c4 [Another 
round of fixes for the fp emulator.] for the emulation frame used in 
delay-slot emulation.

Two instructions are copied into the frame and as from the commit 
referred a cache synchronisation call is made for the second instruction 
aka `badinst' of the two only.  The `flush_cache_sigtramp' interface is 
reused that guarantees that synchronisation will be made for 8 bytes or 
2 instructions starting from the address requested, although if cache 
lines are wider then a larger area may be synchronised.

Change the call to point to the first of the two instructions aka `emul' 
instead, removing unpredictable behaviour resulting from cache 
incoherency.

This bug only ever manifested itself on systems implementing 4-byte 
cache lines, typically MIPS I systems, causing all kinds of weirdness.  
This is because the sequence of two instructions starting from `emul' is 
8-byte aligned and for 8-byte or wider cache lines the line synchronised 
will span both, so the vast majority of systems have escaped unharmed.

Signed-off-by: Maciej W. Rozycki <macro@linux-mips.org>
---
linux-mips-emu-dsemul-flush-cache.patch
Index: linux/arch/mips/math-emu/dsemul.c
===================================================================
--- linux.orig/arch/mips/math-emu/dsemul.c	2015-04-02 20:18:49.616501000 +0100
+++ linux/arch/mips/math-emu/dsemul.c	2015-04-02 20:27:57.133225000 +0100
@@ -94,7 +94,7 @@ int mips_dsemul(struct pt_regs *regs, mi
 	regs->cp0_epc = ((unsigned long) &fr->emul) |
 		get_isa16_mode(regs->cp0_epc);
 
-	flush_cache_sigtramp((unsigned long)&fr->badinst);
+	flush_cache_sigtramp((unsigned long)&fr->emul);
 
 	return SIGILL;		/* force out of emulation loop */
 }

^ permalink raw reply	[flat|nested] 62+ messages in thread

* [PATCH 35/48] MIPS: Correct MIPS I FP context layout
  2015-04-03 22:23 [PATCH 00/48] FPU and FP emulation clean-ups, fixes and feature updates Maciej W. Rozycki
                   ` (31 preceding siblings ...)
  2015-04-03 22:26 ` [PATCH 34/48] MIPS: math-emu: Fix delay-slot emulation cache incoherency Maciej W. Rozycki
@ 2015-04-03 22:26 ` Maciej W. Rozycki
  2015-04-03 22:26 ` [PATCH 36/48] MIPS: Correct FP ISA requirements Maciej W. Rozycki
                   ` (13 subsequent siblings)
  46 siblings, 0 replies; 62+ messages in thread
From: Maciej W. Rozycki @ 2015-04-03 22:26 UTC (permalink / raw)
  To: Ralf Baechle; +Cc: linux-mips

Implement the correct ordering of individual floating-point registers 
within double-precision register pairs for the MIPS I FP context, as 
required by our FP emulation code and expected by userland talking via 
ptrace(2).  Use L.D and S.D assembly macros that do the right thing like 
LDC1 and SDC1 from MIPS II up, avoiding the need to mess up with 
endianness conditionals.

This in particular fixes the handling of denormals and NaN generation in 
Unimplemented Operation emulation traps.

Signed-off-by: Maciej W. Rozycki <macro@linux-mips.org>
---
linux-mips-isa1-fp-context.patch
Index: linux/arch/mips/include/asm/asmmacro-32.h
===================================================================
--- linux.orig/arch/mips/include/asm/asmmacro-32.h	2015-04-02 20:18:49.474495000 +0100
+++ linux/arch/mips/include/asm/asmmacro-32.h	2015-04-02 20:27:57.304220000 +0100
@@ -16,38 +16,22 @@
 	.set push
 	SET_HARDFLOAT
 	cfc1	\tmp,  fcr31
-	swc1	$f0,  THREAD_FPR0_LS64(\thread)
-	swc1	$f1,  THREAD_FPR1_LS64(\thread)
-	swc1	$f2,  THREAD_FPR2_LS64(\thread)
-	swc1	$f3,  THREAD_FPR3_LS64(\thread)
-	swc1	$f4,  THREAD_FPR4_LS64(\thread)
-	swc1	$f5,  THREAD_FPR5_LS64(\thread)
-	swc1	$f6,  THREAD_FPR6_LS64(\thread)
-	swc1	$f7,  THREAD_FPR7_LS64(\thread)
-	swc1	$f8,  THREAD_FPR8_LS64(\thread)
-	swc1	$f9,  THREAD_FPR9_LS64(\thread)
-	swc1	$f10, THREAD_FPR10_LS64(\thread)
-	swc1	$f11, THREAD_FPR11_LS64(\thread)
-	swc1	$f12, THREAD_FPR12_LS64(\thread)
-	swc1	$f13, THREAD_FPR13_LS64(\thread)
-	swc1	$f14, THREAD_FPR14_LS64(\thread)
-	swc1	$f15, THREAD_FPR15_LS64(\thread)
-	swc1	$f16, THREAD_FPR16_LS64(\thread)
-	swc1	$f17, THREAD_FPR17_LS64(\thread)
-	swc1	$f18, THREAD_FPR18_LS64(\thread)
-	swc1	$f19, THREAD_FPR19_LS64(\thread)
-	swc1	$f20, THREAD_FPR20_LS64(\thread)
-	swc1	$f21, THREAD_FPR21_LS64(\thread)
-	swc1	$f22, THREAD_FPR22_LS64(\thread)
-	swc1	$f23, THREAD_FPR23_LS64(\thread)
-	swc1	$f24, THREAD_FPR24_LS64(\thread)
-	swc1	$f25, THREAD_FPR25_LS64(\thread)
-	swc1	$f26, THREAD_FPR26_LS64(\thread)
-	swc1	$f27, THREAD_FPR27_LS64(\thread)
-	swc1	$f28, THREAD_FPR28_LS64(\thread)
-	swc1	$f29, THREAD_FPR29_LS64(\thread)
-	swc1	$f30, THREAD_FPR30_LS64(\thread)
-	swc1	$f31, THREAD_FPR31_LS64(\thread)
+	s.d	$f0,  THREAD_FPR0_LS64(\thread)
+	s.d	$f2,  THREAD_FPR2_LS64(\thread)
+	s.d	$f4,  THREAD_FPR4_LS64(\thread)
+	s.d	$f6,  THREAD_FPR6_LS64(\thread)
+	s.d	$f8,  THREAD_FPR8_LS64(\thread)
+	s.d	$f10, THREAD_FPR10_LS64(\thread)
+	s.d	$f12, THREAD_FPR12_LS64(\thread)
+	s.d	$f14, THREAD_FPR14_LS64(\thread)
+	s.d	$f16, THREAD_FPR16_LS64(\thread)
+	s.d	$f18, THREAD_FPR18_LS64(\thread)
+	s.d	$f20, THREAD_FPR20_LS64(\thread)
+	s.d	$f22, THREAD_FPR22_LS64(\thread)
+	s.d	$f24, THREAD_FPR24_LS64(\thread)
+	s.d	$f26, THREAD_FPR26_LS64(\thread)
+	s.d	$f28, THREAD_FPR28_LS64(\thread)
+	s.d	$f30, THREAD_FPR30_LS64(\thread)
 	sw	\tmp, THREAD_FCR31(\thread)
 	.set pop
 	.endm
@@ -56,38 +40,22 @@
 	.set push
 	SET_HARDFLOAT
 	lw	\tmp, THREAD_FCR31(\thread)
-	lwc1	$f0,  THREAD_FPR0_LS64(\thread)
-	lwc1	$f1,  THREAD_FPR1_LS64(\thread)
-	lwc1	$f2,  THREAD_FPR2_LS64(\thread)
-	lwc1	$f3,  THREAD_FPR3_LS64(\thread)
-	lwc1	$f4,  THREAD_FPR4_LS64(\thread)
-	lwc1	$f5,  THREAD_FPR5_LS64(\thread)
-	lwc1	$f6,  THREAD_FPR6_LS64(\thread)
-	lwc1	$f7,  THREAD_FPR7_LS64(\thread)
-	lwc1	$f8,  THREAD_FPR8_LS64(\thread)
-	lwc1	$f9,  THREAD_FPR9_LS64(\thread)
-	lwc1	$f10, THREAD_FPR10_LS64(\thread)
-	lwc1	$f11, THREAD_FPR11_LS64(\thread)
-	lwc1	$f12, THREAD_FPR12_LS64(\thread)
-	lwc1	$f13, THREAD_FPR13_LS64(\thread)
-	lwc1	$f14, THREAD_FPR14_LS64(\thread)
-	lwc1	$f15, THREAD_FPR15_LS64(\thread)
-	lwc1	$f16, THREAD_FPR16_LS64(\thread)
-	lwc1	$f17, THREAD_FPR17_LS64(\thread)
-	lwc1	$f18, THREAD_FPR18_LS64(\thread)
-	lwc1	$f19, THREAD_FPR19_LS64(\thread)
-	lwc1	$f20, THREAD_FPR20_LS64(\thread)
-	lwc1	$f21, THREAD_FPR21_LS64(\thread)
-	lwc1	$f22, THREAD_FPR22_LS64(\thread)
-	lwc1	$f23, THREAD_FPR23_LS64(\thread)
-	lwc1	$f24, THREAD_FPR24_LS64(\thread)
-	lwc1	$f25, THREAD_FPR25_LS64(\thread)
-	lwc1	$f26, THREAD_FPR26_LS64(\thread)
-	lwc1	$f27, THREAD_FPR27_LS64(\thread)
-	lwc1	$f28, THREAD_FPR28_LS64(\thread)
-	lwc1	$f29, THREAD_FPR29_LS64(\thread)
-	lwc1	$f30, THREAD_FPR30_LS64(\thread)
-	lwc1	$f31, THREAD_FPR31_LS64(\thread)
+	l.d	$f0,  THREAD_FPR0_LS64(\thread)
+	l.d	$f2,  THREAD_FPR2_LS64(\thread)
+	l.d	$f4,  THREAD_FPR4_LS64(\thread)
+	l.d	$f6,  THREAD_FPR6_LS64(\thread)
+	l.d	$f8,  THREAD_FPR8_LS64(\thread)
+	l.d	$f10, THREAD_FPR10_LS64(\thread)
+	l.d	$f12, THREAD_FPR12_LS64(\thread)
+	l.d	$f14, THREAD_FPR14_LS64(\thread)
+	l.d	$f16, THREAD_FPR16_LS64(\thread)
+	l.d	$f18, THREAD_FPR18_LS64(\thread)
+	l.d	$f20, THREAD_FPR20_LS64(\thread)
+	l.d	$f22, THREAD_FPR22_LS64(\thread)
+	l.d	$f24, THREAD_FPR24_LS64(\thread)
+	l.d	$f26, THREAD_FPR26_LS64(\thread)
+	l.d	$f28, THREAD_FPR28_LS64(\thread)
+	l.d	$f30, THREAD_FPR30_LS64(\thread)
 	ctc1	\tmp, fcr31
 	.set pop
 	.endm

^ permalink raw reply	[flat|nested] 62+ messages in thread

* [PATCH 36/48] MIPS: Correct FP ISA requirements
  2015-04-03 22:23 [PATCH 00/48] FPU and FP emulation clean-ups, fixes and feature updates Maciej W. Rozycki
                   ` (32 preceding siblings ...)
  2015-04-03 22:26 ` [PATCH 35/48] MIPS: Correct MIPS I FP context layout Maciej W. Rozycki
@ 2015-04-03 22:26 ` Maciej W. Rozycki
  2015-04-03 22:26 ` [PATCH 37/48] MIPS: math-emu: Correct delay-slot exception propagation Maciej W. Rozycki
                   ` (12 subsequent siblings)
  46 siblings, 0 replies; 62+ messages in thread
From: Maciej W. Rozycki @ 2015-04-03 22:26 UTC (permalink / raw)
  To: Ralf Baechle; +Cc: linux-mips

Correct ISA requirements for floating-point instructions:

* the CU3 exception signifies a real COP3 instruction in MIPS I & II,

* the BC1FL and BC1TL instructions are not supported in MIPS I,

* the SQRT.fmt instructions are indeed supported in MIPS II,

* the LDC1 and SDC1 instructions are indeed supported in MIPS32r1,

* the CEIL.W.fmt, FLOOR.W.fmt, ROUND.W.fmt and TRUNC.W.fmt instructions 
  are indeed supported in MIPS32,

* the CVT.L.fmt and CVT.fmt.L instructions are indeed supported in 
  MIPS32r2 and MIPS32r6,

* the CEIL.L.fmt, FLOOR.L.fmt, ROUND.L.fmt and TRUNC.L.fmt instructions 
  are indeed supported in MIPS32r2 and MIPS32r6,

* the RSQRT.fmt and RECIP.fmt instructions are indeed supported in 
  MIPS64r1,

Also simplify conditionals for MIPS III and MIPS IV FPU instructions and 
the handling of the MOVCI minor opcode.

Signed-off-by: Maciej W. Rozycki <macro@linux-mips.org>
---
linux-mips-emu-isa.diff
Index: linux/arch/mips/include/asm/cpu-features.h
===================================================================
--- linux.orig/arch/mips/include/asm/cpu-features.h	2015-04-02 20:27:56.252205000 +0100
+++ linux/arch/mips/include/asm/cpu-features.h	2015-04-02 20:27:57.478232000 +0100
@@ -221,8 +221,11 @@
 #define cpu_has_mips_4_5_r	(cpu_has_mips_4 | cpu_has_mips_5_r)
 #define cpu_has_mips_5_r	(cpu_has_mips_5 | cpu_has_mips_r)
 
-#define cpu_has_mips_4_5_r2_r6	(cpu_has_mips_4_5 | cpu_has_mips_r2 | \
-				 cpu_has_mips_r6)
+#define cpu_has_mips_3_4_5_64_r2_r6					\
+				(cpu_has_mips_3 | cpu_has_mips_4_5_64_r2_r6)
+#define cpu_has_mips_4_5_64_r2_r6					\
+				(cpu_has_mips_4_5 | cpu_has_mips64r1 |	\
+				 cpu_has_mips_r2 | cpu_has_mips_r6)
 
 #define cpu_has_mips32	(cpu_has_mips32r1 | cpu_has_mips32r2 | cpu_has_mips32r6)
 #define cpu_has_mips64	(cpu_has_mips64r1 | cpu_has_mips64r2 | cpu_has_mips64r6)
Index: linux/arch/mips/kernel/traps.c
===================================================================
--- linux.orig/arch/mips/kernel/traps.c	2015-04-02 20:27:56.948213000 +0100
+++ linux/arch/mips/kernel/traps.c	2015-04-02 20:27:57.489216000 +0100
@@ -1349,19 +1349,18 @@ asmlinkage void do_cpu(struct pt_regs *r
 
 	case 3:
 		/*
-		 * Old (MIPS I and MIPS II) processors will set this code
-		 * for COP1X opcode instructions that replaced the original
-		 * COP3 space.	We don't limit COP1 space instructions in
-		 * the emulator according to the CPU ISA, so we want to
-		 * treat COP1X instructions consistently regardless of which
-		 * code the CPU chose.	Therefore we redirect this trap to
-		 * the FP emulator too.
-		 *
-		 * Then some newer FPU-less processors use this code
-		 * erroneously too, so they are covered by this choice
-		 * as well.
+		 * The COP3 opcode space and consequently the CP0.Status.CU3
+		 * bit and the CP0.Cause.CE=3 encoding have been removed as
+		 * of the MIPS III ISA.  From the MIPS IV and MIPS32r2 ISAs
+		 * up the space has been reused for COP1X instructions, that
+		 * are enabled by the CP0.Status.CU1 bit and consequently
+		 * use the CP0.Cause.CE=1 encoding for Coprocessor Unusable
+		 * exceptions.  Some FPU-less processors that implement one
+		 * of these ISAs however use this code erroneously for COP1X
+		 * instructions.  Therefore we redirect this trap to the FP
+		 * emulator too.
 		 */
-		if (raw_cpu_has_fpu) {
+		if (raw_cpu_has_fpu || !cpu_has_mips_4_5_64_r2_r6) {
 			force_sig(SIGILL, current);
 			break;
 		}
Index: linux/arch/mips/math-emu/cp1emu.c
===================================================================
--- linux.orig/arch/mips/math-emu/cp1emu.c	2015-04-02 20:27:54.459192000 +0100
+++ linux/arch/mips/math-emu/cp1emu.c	2015-04-02 20:27:57.493218000 +0100
@@ -1115,17 +1115,18 @@ static int cop1Emulate(struct pt_regs *x
 			likely = 0;
 			switch (MIPSInst_RT(ir) & 3) {
 			case bcfl_op:
-				likely = 1;
+				if (cpu_has_mips_2_3_4_5_r)
+					likely = 1;
+				/* Fall through */
 			case bcf_op:
 				cond = !cond;
 				break;
 			case bctl_op:
-				likely = 1;
+				if (cpu_has_mips_2_3_4_5_r)
+					likely = 1;
+				/* Fall through */
 			case bct_op:
 				break;
-			default:
-				/* thats an illegal instruction */
-				return SIGILL;
 			}
 
 			set_delay_slot(xcp);
@@ -1165,36 +1166,34 @@ static int cop1Emulate(struct pt_regs *x
 
 				switch (MIPSInst_OPCODE(ir)) {
 				case lwc1_op:
-					goto emul;
-
 				case swc1_op:
 					goto emul;
 
 				case ldc1_op:
 				case sdc1_op:
-					if (cpu_has_mips_2_3_4_5 ||
-					    cpu_has_mips64)
+					if (cpu_has_mips_2_3_4_5_r)
 						goto emul;
 
 					return SIGILL;
-					goto emul;
 
 				case cop1_op:
 					goto emul;
 
 				case cop1x_op:
-					if (cpu_has_mips_4_5 || cpu_has_mips64 || cpu_has_mips32r2)
+					if (cpu_has_mips_4_5_64_r2_r6)
 						/* its one of ours */
 						goto emul;
 
 					return SIGILL;
 
 				case spec_op:
-					if (!cpu_has_mips_4_5_r)
-						return SIGILL;
+					switch (MIPSInst_FUNC(ir)) {
+					case movc_op:
+						if (cpu_has_mips_4_5_r)
+							goto emul;
 
-					if (MIPSInst_FUNC(ir) == movc_op)
-						goto emul;
+						return SIGILL;
+					}
 					break;
 				}
 
@@ -1228,7 +1227,7 @@ static int cop1Emulate(struct pt_regs *x
 		break;
 
 	case cop1x_op:
-		if (!cpu_has_mips_4_5 && !cpu_has_mips64 && !cpu_has_mips32r2)
+		if (!cpu_has_mips_4_5_64_r2_r6)
 			return SIGILL;
 
 		sig = fpux_emu(xcp, ctx, ir, fault_addr);
@@ -1561,7 +1560,7 @@ static int fpu_emu(struct pt_regs *xcp, 
 
 			/* unary  ops */
 		case fsqrt_op:
-			if (!cpu_has_mips_4_5_r)
+			if (!cpu_has_mips_2_3_4_5_r)
 				return SIGILL;
 
 			handler.u = ieee754sp_sqrt;
@@ -1573,14 +1572,14 @@ static int fpu_emu(struct pt_regs *xcp, 
 		 * achieve full IEEE-754 accuracy - however this emulator does.
 		 */
 		case frsqrt_op:
-			if (!cpu_has_mips_4_5_r2_r6)
+			if (!cpu_has_mips_4_5_64_r2_r6)
 				return SIGILL;
 
 			handler.u = fpemu_sp_rsqrt;
 			goto scopuop;
 
 		case frecip_op:
-			if (!cpu_has_mips_4_5_r2_r6)
+			if (!cpu_has_mips_4_5_64_r2_r6)
 				return SIGILL;
 
 			handler.u = fpemu_sp_recip;
@@ -1682,7 +1681,7 @@ static int fpu_emu(struct pt_regs *xcp, 
 		case ftrunc_op:
 		case fceil_op:
 		case ffloor_op:
-			if (!cpu_has_mips_2_3_4_5 && !cpu_has_mips64)
+			if (!cpu_has_mips_2_3_4_5_r)
 				return SIGILL;
 
 			oldrm = ieee754_csr.rm;
@@ -1694,7 +1693,7 @@ static int fpu_emu(struct pt_regs *xcp, 
 			goto copcsr;
 
 		case fcvtl_op:
-			if (!cpu_has_mips_3_4_5 && !cpu_has_mips64)
+			if (!cpu_has_mips_3_4_5_64_r2_r6)
 				return SIGILL;
 
 			SPFROMREG(fs, MIPSInst_FS(ir));
@@ -1706,7 +1705,7 @@ static int fpu_emu(struct pt_regs *xcp, 
 		case ftruncl_op:
 		case fceill_op:
 		case ffloorl_op:
-			if (!cpu_has_mips_3_4_5 && !cpu_has_mips64)
+			if (!cpu_has_mips_3_4_5_64_r2_r6)
 				return SIGILL;
 
 			oldrm = ieee754_csr.rm;
@@ -1775,13 +1774,13 @@ static int fpu_emu(struct pt_regs *xcp, 
 		 * achieve full IEEE-754 accuracy - however this emulator does.
 		 */
 		case frsqrt_op:
-			if (!cpu_has_mips_4_5_r2_r6)
+			if (!cpu_has_mips_4_5_64_r2_r6)
 				return SIGILL;
 
 			handler.u = fpemu_dp_rsqrt;
 			goto dcopuop;
 		case frecip_op:
-			if (!cpu_has_mips_4_5_r2_r6)
+			if (!cpu_has_mips_4_5_64_r2_r6)
 				return SIGILL;
 
 			handler.u = fpemu_dp_recip;
@@ -1871,7 +1870,7 @@ static int fpu_emu(struct pt_regs *xcp, 
 			goto copcsr;
 
 		case fcvtl_op:
-			if (!cpu_has_mips_3_4_5 && !cpu_has_mips64)
+			if (!cpu_has_mips_3_4_5_64_r2_r6)
 				return SIGILL;
 
 			DPFROMREG(fs, MIPSInst_FS(ir));
@@ -1883,7 +1882,7 @@ static int fpu_emu(struct pt_regs *xcp, 
 		case ftruncl_op:
 		case fceill_op:
 		case ffloorl_op:
-			if (!cpu_has_mips_3_4_5 && !cpu_has_mips64)
+			if (!cpu_has_mips_3_4_5_64_r2_r6)
 				return SIGILL;
 
 			oldrm = ieee754_csr.rm;
@@ -1942,7 +1941,7 @@ static int fpu_emu(struct pt_regs *xcp, 
 
 	case l_fmt:
 
-		if (!cpu_has_mips_3_4_5 && !cpu_has_mips64)
+		if (!cpu_has_mips_3_4_5_64_r2_r6)
 			return SIGILL;
 
 		DIFROMREG(bits, MIPSInst_FS(ir));
@@ -2006,7 +2005,7 @@ static int fpu_emu(struct pt_regs *xcp, 
 		SITOREG(rv.w, MIPSInst_FD(ir));
 		break;
 	case l_fmt:
-		if (!cpu_has_mips_3_4_5 && !cpu_has_mips64)
+		if (!cpu_has_mips_3_4_5_64_r2_r6)
 			return SIGILL;
 
 		DITOREG(rv.l, MIPSInst_FD(ir));

^ permalink raw reply	[flat|nested] 62+ messages in thread

* [PATCH 37/48] MIPS: math-emu: Correct delay-slot exception propagation
  2015-04-03 22:23 [PATCH 00/48] FPU and FP emulation clean-ups, fixes and feature updates Maciej W. Rozycki
                   ` (33 preceding siblings ...)
  2015-04-03 22:26 ` [PATCH 36/48] MIPS: Correct FP ISA requirements Maciej W. Rozycki
@ 2015-04-03 22:26 ` Maciej W. Rozycki
  2016-01-20 10:50   ` Aurelien Jarno
  2015-04-03 22:27 ` [PATCH 38/48] MIPS: math-emu: Move long fixed-point support into an `ar' library Maciej W. Rozycki
                   ` (11 subsequent siblings)
  46 siblings, 1 reply; 62+ messages in thread
From: Maciej W. Rozycki @ 2015-04-03 22:26 UTC (permalink / raw)
  To: Ralf Baechle; +Cc: linux-mips

Restore EPC at the branch whose delay slot is emulated if the delay-slot 
instruction signals.  This is so that code in `fpu_emulator_cop1Handler' 
does not see EPC having advanced and mistakenly successfully resume 
userland execution from the location at the branch target in that case.
Restoring EPC guarantees an immediate exit from the emulation loop and 
if EPC hasn't advanced at all since entering the loop, also issuing the 
signal reported by the delay-slot instruction.

Signed-off-by: Maciej W. Rozycki <macro@linux-mips.org>
---
linux-mips-emu-bc1x-sigill.patch
Index: linux/arch/mips/math-emu/cp1emu.c
===================================================================
--- linux.orig/arch/mips/math-emu/cp1emu.c	2015-04-02 20:27:57.493218000 +0100
+++ linux/arch/mips/math-emu/cp1emu.c	2015-04-02 20:27:57.710224000 +0100
@@ -1134,6 +1134,14 @@ static int cop1Emulate(struct pt_regs *x
 				/*
 				 * Branch taken: emulate dslot instruction
 				 */
+				unsigned long bcpc;
+
+				/*
+				 * Remember EPC at the branch to point back
+				 * at so that any delay-slot instruction
+				 * signal is not silently ignored.
+				 */
+				bcpc = xcp->cp0_epc;
 				xcp->cp0_epc += dec_insn.pc_inc;
 
 				contpc = MIPSInst_SIMM(ir);
@@ -1159,7 +1167,15 @@ static int cop1Emulate(struct pt_regs *x
 						 * Single step the non-CP1
 						 * instruction in the dslot.
 						 */
-						return mips_dsemul(xcp, ir, contpc);
+						sig = mips_dsemul(xcp, ir,
+								  contpc);
+						if (sig)
+							xcp->cp0_epc = bcpc;
+						/*
+						 * SIGILL forces out of
+						 * the emulation loop.
+						 */
+						return sig ? sig : SIGILL;
 					}
 				} else
 					contpc = (xcp->cp0_epc + (contpc << 2));
@@ -1174,7 +1190,7 @@ static int cop1Emulate(struct pt_regs *x
 					if (cpu_has_mips_2_3_4_5_r)
 						goto emul;
 
-					return SIGILL;
+					goto bc_sigill;
 
 				case cop1_op:
 					goto emul;
@@ -1184,7 +1200,7 @@ static int cop1Emulate(struct pt_regs *x
 						/* its one of ours */
 						goto emul;
 
-					return SIGILL;
+					goto bc_sigill;
 
 				case spec_op:
 					switch (MIPSInst_FUNC(ir)) {
@@ -1192,16 +1208,24 @@ static int cop1Emulate(struct pt_regs *x
 						if (cpu_has_mips_4_5_r)
 							goto emul;
 
-						return SIGILL;
+						goto bc_sigill;
 					}
 					break;
+
+				bc_sigill:
+					xcp->cp0_epc = bcpc;
+					return SIGILL;
 				}
 
 				/*
 				 * Single step the non-cp1
 				 * instruction in the dslot
 				 */
-				return mips_dsemul(xcp, ir, contpc);
+				sig = mips_dsemul(xcp, ir, contpc);
+				if (sig)
+					xcp->cp0_epc = bcpc;
+				/* SIGILL forces out of the emulation loop.  */
+				return sig ? sig : SIGILL;
 			} else if (likely) {	/* branch not taken */
 				/*
 				 * branch likely nullifies
Index: linux/arch/mips/math-emu/dsemul.c
===================================================================
--- linux.orig/arch/mips/math-emu/dsemul.c	2015-04-02 20:27:57.133225000 +0100
+++ linux/arch/mips/math-emu/dsemul.c	2015-04-02 20:27:57.713219000 +0100
@@ -96,7 +96,7 @@ int mips_dsemul(struct pt_regs *regs, mi
 
 	flush_cache_sigtramp((unsigned long)&fr->emul);
 
-	return SIGILL;		/* force out of emulation loop */
+	return 0;
 }
 
 int do_dsemulret(struct pt_regs *xcp)

^ permalink raw reply	[flat|nested] 62+ messages in thread

* [PATCH 38/48] MIPS: math-emu: Move long fixed-point support into an `ar' library
  2015-04-03 22:23 [PATCH 00/48] FPU and FP emulation clean-ups, fixes and feature updates Maciej W. Rozycki
                   ` (34 preceding siblings ...)
  2015-04-03 22:26 ` [PATCH 37/48] MIPS: math-emu: Correct delay-slot exception propagation Maciej W. Rozycki
@ 2015-04-03 22:27 ` Maciej W. Rozycki
  2015-04-03 22:27 ` [PATCH 39/48] MIPS: Respect the FCSR exception mask for `si_code' Maciej W. Rozycki
                   ` (10 subsequent siblings)
  46 siblings, 0 replies; 62+ messages in thread
From: Maciej W. Rozycki @ 2015-04-03 22:27 UTC (permalink / raw)
  To: Ralf Baechle; +Cc: linux-mips

Complement 593d33fe [MIPS: math-emu: Move various objects into an ar 
library.] and also move sp_tlong.o, sp_flong.o, dp_tlong.o, and 
dp_flong.o into an `ar' library.  These objects implement long 
fixed-point format support that can be omitted from MIPS I, MIPS II and 
MIPS32r1 configurations.

Signed-off-by: Maciej W. Rozycki <macro@linux-mips.org>
---
Ralf,

 Please note however that contrary to your comment for 593d33fe 
sp_sqrt.o and dp_sqrt.o will be omitted from MIPS I configurations only.

  Maciej

linux-mips-emu-lib.diff
Index: linux/arch/mips/math-emu/Makefile
===================================================================
--- linux.orig/arch/mips/math-emu/Makefile	2015-04-02 20:18:48.993504000 +0100
+++ linux/arch/mips/math-emu/Makefile	2015-04-02 20:27:57.896229000 +0100
@@ -2,12 +2,15 @@
 # Makefile for the Linux/MIPS kernel FPU emulation.
 #
 
-obj-y	+= cp1emu.o ieee754dp.o ieee754sp.o ieee754.o dp_div.o dp_mul.o \
-	   dp_sub.o dp_add.o dp_fsp.o dp_cmp.o dp_simple.o dp_tint.o \
-	   dp_fint.o dp_tlong.o dp_flong.o sp_div.o sp_mul.o sp_sub.o \
-	   sp_add.o sp_fdp.o sp_cmp.o sp_simple.o sp_tint.o sp_fint.o \
-	   sp_tlong.o sp_flong.o dsemul.o
+obj-y	+= cp1emu.o ieee754dp.o ieee754sp.o ieee754.o \
+	   dp_div.o dp_mul.o dp_sub.o dp_add.o dp_fsp.o dp_cmp.o dp_simple.o \
+	   dp_tint.o dp_fint.o \
+	   sp_div.o sp_mul.o sp_sub.o sp_add.o sp_fdp.o sp_cmp.o sp_simple.o \
+	   sp_tint.o sp_fint.o \
+	   dsemul.o
 
-lib-y	+= ieee754d.o dp_sqrt.o sp_sqrt.o
+lib-y	+= ieee754d.o \
+	   dp_tlong.o dp_flong.o dp_sqrt.o \
+	   sp_tlong.o sp_flong.o sp_sqrt.o
 
 obj-$(CONFIG_DEBUG_FS) += me-debugfs.o

^ permalink raw reply	[flat|nested] 62+ messages in thread

* [PATCH 39/48] MIPS: Respect the FCSR exception mask for `si_code'
  2015-04-03 22:23 [PATCH 00/48] FPU and FP emulation clean-ups, fixes and feature updates Maciej W. Rozycki
                   ` (35 preceding siblings ...)
  2015-04-03 22:27 ` [PATCH 38/48] MIPS: math-emu: Move long fixed-point support into an `ar' library Maciej W. Rozycki
@ 2015-04-03 22:27 ` Maciej W. Rozycki
  2015-04-03 22:27 ` [PATCH 40/48] MIPS: Always clear FCSR cause bits after emulation Maciej W. Rozycki
                   ` (9 subsequent siblings)
  46 siblings, 0 replies; 62+ messages in thread
From: Maciej W. Rozycki @ 2015-04-03 22:27 UTC (permalink / raw)
  To: Ralf Baechle; +Cc: linux-mips

Respect the FCSR exception mask when interpreting the IEEE 754 exception 
condition to report with SIGFPE in `si_code', so as not to use one that 
has been masked where a different one set in parallel caused the FPE 
hardware exception to trigger.  As per the IEEE Std 754 the Inexact 
exception can happen together with Overflow or Underflow.

Signed-off-by: Maciej W. Rozycki <macro@linux-mips.org>
---
linux-mips-fpe-except-mask.diff
Index: linux/arch/mips/kernel/traps.c
===================================================================
--- linux.orig/arch/mips/kernel/traps.c	2015-04-02 20:27:57.489216000 +0100
+++ linux/arch/mips/kernel/traps.c	2015-04-02 20:27:58.065226000 +0100
@@ -12,6 +12,7 @@
  * Copyright (C) 2000, 2001, 2012 MIPS Technologies, Inc.  All rights reserved.
  * Copyright (C) 2014, Imagination Technologies Ltd.
  */
+#include <linux/bitops.h>
 #include <linux/bug.h>
 #include <linux/compiler.h>
 #include <linux/context_tracking.h>
@@ -817,7 +818,15 @@ asmlinkage void do_fpe(struct pt_regs *r
 		process_fpemu_return(sig, fault_addr);
 
 		goto out;
-	} else if (fcr31 & FPU_CSR_INV_X)
+	}
+
+	/*
+	 * Inexact can happen together with Overflow or Underflow.
+	 * Respect the mask to deliver the correct exception.
+	 */
+	fcr31 &= (fcr31 & FPU_CSR_ALL_E) <<
+		 (ffs(FPU_CSR_ALL_X) - ffs(FPU_CSR_ALL_E));
+	if (fcr31 & FPU_CSR_INV_X)
 		info.si_code = FPE_FLTINV;
 	else if (fcr31 & FPU_CSR_DIV_X)
 		info.si_code = FPE_FLTDIV;

^ permalink raw reply	[flat|nested] 62+ messages in thread

* [PATCH 40/48] MIPS: Always clear FCSR cause bits after emulation
  2015-04-03 22:23 [PATCH 00/48] FPU and FP emulation clean-ups, fixes and feature updates Maciej W. Rozycki
                   ` (36 preceding siblings ...)
  2015-04-03 22:27 ` [PATCH 39/48] MIPS: Respect the FCSR exception mask for `si_code' Maciej W. Rozycki
@ 2015-04-03 22:27 ` Maciej W. Rozycki
  2015-04-03 22:27 ` [PATCH 41/48] MIPS: Set `si_code' for SIGFPE signals sent from emulation too Maciej W. Rozycki
                   ` (8 subsequent siblings)
  46 siblings, 0 replies; 62+ messages in thread
From: Maciej W. Rozycki @ 2015-04-03 22:27 UTC (permalink / raw)
  To: Ralf Baechle; +Cc: linux-mips

Clear any FCSR cause bits recorded in the saved FPU context after 
emulation in all cases rather than in `do_fpe' only, so that any 
unmasked IEEE 754 exception left from emulation does not cause a fatal 
kernel-mode FPE hardware exception with the CTC1 instruction used by the 
kernel to subsequently restore FCSR hardware from the saved FPU context.

Signed-off-by: Maciej W. Rozycki <macro@linux-mips.org>
---
linux-mips-fpe-emu-fcsr-cause.diff
Index: linux/arch/mips/kernel/mips-r2-to-r6-emul.c
===================================================================
--- linux.orig/arch/mips/kernel/mips-r2-to-r6-emul.c	2015-04-02 20:27:53.338178000 +0100
+++ linux/arch/mips/kernel/mips-r2-to-r6-emul.c	2015-04-02 20:27:58.241225000 +0100
@@ -1170,6 +1170,12 @@ int mipsr2_decoder(struct pt_regs *regs,
 					       &fault_addr);
 
 		/*
+		 * We can't allow the emulated instruction to leave any of
+		 * the cause bits set in $fcr31.
+		 */
+		current->thread.fpu.fcr31 &= ~FPU_CSR_ALL_X;
+
+		/*
 		 * this is a tricky issue - lose_fpu() uses LL/SC atomics
 		 * if FPU is owned and effectively cancels user level LL/SC.
 		 * So, it could be logical to don't restore FPU ownership here.
Index: linux/arch/mips/kernel/traps.c
===================================================================
--- linux.orig/arch/mips/kernel/traps.c	2015-04-02 20:27:58.065226000 +0100
+++ linux/arch/mips/kernel/traps.c	2015-04-02 20:27:58.244233000 +0100
@@ -761,6 +761,12 @@ static int simulate_fp(struct pt_regs *r
 	sig = fpu_emulator_cop1Handler(regs, &current->thread.fpu, 1,
 				       &fault_addr);
 
+	/*
+	 * We can't allow the emulated instruction to leave any of
+	 * the cause bits set in $fcr31.
+	 */
+	current->thread.fpu.fcr31 &= ~FPU_CSR_ALL_X;
+
 	/* If something went wrong, signal */
 	process_fpemu_return(sig, fault_addr);
 
@@ -807,7 +813,7 @@ asmlinkage void do_fpe(struct pt_regs *r
 
 		/*
 		 * We can't allow the emulated instruction to leave any of
-		 * the cause bit set in $fcr31.
+		 * the cause bits set in $fcr31.
 		 */
 		current->thread.fpu.fcr31 &= ~FPU_CSR_ALL_X;
 
@@ -1384,6 +1390,13 @@ asmlinkage void do_cpu(struct pt_regs *r
 			sig = fpu_emulator_cop1Handler(regs,
 						       &current->thread.fpu,
 						       0, &fault_addr);
+
+			/*
+			 * We can't allow the emulated instruction to leave
+			 * any of the cause bits set in $fcr31.
+			 */
+			current->thread.fpu.fcr31 &= ~FPU_CSR_ALL_X;
+
 			if (!process_fpemu_return(sig, fault_addr) && !err)
 				mt_ase_fp_affinity();
 		}

^ permalink raw reply	[flat|nested] 62+ messages in thread

* [PATCH 41/48] MIPS: Set `si_code' for SIGFPE signals sent from emulation too
  2015-04-03 22:23 [PATCH 00/48] FPU and FP emulation clean-ups, fixes and feature updates Maciej W. Rozycki
                   ` (37 preceding siblings ...)
  2015-04-03 22:27 ` [PATCH 40/48] MIPS: Always clear FCSR cause bits after emulation Maciej W. Rozycki
@ 2015-04-03 22:27 ` Maciej W. Rozycki
  2015-04-03 22:27 ` [PATCH 42/48] MIPS: Correct ISA masking in FPU feature determination Maciej W. Rozycki
                   ` (7 subsequent siblings)
  46 siblings, 0 replies; 62+ messages in thread
From: Maciej W. Rozycki @ 2015-04-03 22:27 UTC (permalink / raw)
  To: Ralf Baechle; +Cc: linux-mips

Rework `process_fpemu_return' and move IEEE 754 exception interpretation 
there, from `do_fpe'.  Record the cause bits set in FCSR before they are 
cleared and pass them through to `process_fpemu_return' so as to set 
`si_code' correctly too for SIGFPE signals sent from emulation rather 
than those issued by hardware with the FPE processor exception only.

For simplicity `mipsr2_decoder' assumes `*fcr31' has been preinitialised 
and only sets it to anything if an FPU instruction has been emulated, 
which in turn is the only case SIGFPE can be issued for here.

Signed-off-by: Maciej W. Rozycki <macro@linux-mips.org>
---
linux-mips-fpe-emu-siginfo.diff
Index: linux/arch/mips/include/asm/fpu_emulator.h
===================================================================
--- linux.orig/arch/mips/include/asm/fpu_emulator.h	2015-04-02 20:18:48.693493000 +0100
+++ linux/arch/mips/include/asm/fpu_emulator.h	2015-04-02 20:27:58.453234000 +0100
@@ -65,7 +65,8 @@ extern int do_dsemulret(struct pt_regs *
 extern int fpu_emulator_cop1Handler(struct pt_regs *xcp,
 				    struct mips_fpu_struct *ctx, int has_fpu,
 				    void *__user *fault_addr);
-int process_fpemu_return(int sig, void __user *fault_addr);
+int process_fpemu_return(int sig, void __user *fault_addr,
+			 unsigned long fcr31);
 int mm_isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn,
 		     unsigned long *contpc);
 
Index: linux/arch/mips/include/asm/mips-r2-to-r6-emul.h
===================================================================
--- linux.orig/arch/mips/include/asm/mips-r2-to-r6-emul.h	2015-04-02 20:27:53.724187000 +0100
+++ linux/arch/mips/include/asm/mips-r2-to-r6-emul.h	2015-04-02 20:27:58.456228000 +0100
@@ -84,11 +84,16 @@ extern void do_trap_or_bp(struct pt_regs
 
 #ifndef CONFIG_MIPSR2_TO_R6_EMULATOR
 static int mipsr2_emulation;
-static inline int mipsr2_decoder(struct pt_regs *regs, u32 inst) { return 0; };
+static inline int mipsr2_decoder(struct pt_regs *regs, u32 inst,
+				 unsigned long *fcr31)
+{
+	return 0;
+};
 #else
 /* MIPS R2 Emulator ON/OFF */
 extern int mipsr2_emulation;
-extern int mipsr2_decoder(struct pt_regs *regs, u32 inst);
+extern int mipsr2_decoder(struct pt_regs *regs, u32 inst,
+			  unsigned long *fcr31);
 #endif /* CONFIG_MIPSR2_TO_R6_EMULATOR */
 
 #define NO_R6EMU	(cpu_has_mips_r6 && !mipsr2_emulation)
Index: linux/arch/mips/kernel/mips-r2-to-r6-emul.c
===================================================================
--- linux.orig/arch/mips/kernel/mips-r2-to-r6-emul.c	2015-04-02 20:27:58.241225000 +0100
+++ linux/arch/mips/kernel/mips-r2-to-r6-emul.c	2015-04-02 20:27:58.460231000 +0100
@@ -898,8 +898,9 @@ static inline int mipsr2_find_op_func(st
  * mipsr2_decoder: Decode and emulate a MIPS R2 instruction
  * @regs: Process register set
  * @inst: Instruction to decode and emulate
+ * @fcr31: Floating Point Control and Status Register returned
  */
-int mipsr2_decoder(struct pt_regs *regs, u32 inst)
+int mipsr2_decoder(struct pt_regs *regs, u32 inst, unsigned long *fcr31)
 {
 	int err = 0;
 	unsigned long vaddr;
@@ -1168,6 +1169,7 @@ int mipsr2_decoder(struct pt_regs *regs,
 
 		err = fpu_emulator_cop1Handler(regs, &current->thread.fpu, 0,
 					       &fault_addr);
+		*fcr31 = current->thread.fpu.fcr31;
 
 		/*
 		 * We can't allow the emulated instruction to leave any of
Index: linux/arch/mips/kernel/traps.c
===================================================================
--- linux.orig/arch/mips/kernel/traps.c	2015-04-02 20:27:58.244233000 +0100
+++ linux/arch/mips/kernel/traps.c	2015-04-02 20:27:58.463232000 +0100
@@ -700,29 +700,60 @@ asmlinkage void do_ov(struct pt_regs *re
 	exception_exit(prev_state);
 }
 
-int process_fpemu_return(int sig, void __user *fault_addr)
+int process_fpemu_return(int sig, void __user *fault_addr, unsigned long fcr31)
 {
-	if (sig == SIGSEGV || sig == SIGBUS) {
-		struct siginfo si = {0};
+	struct siginfo si = { 0 };
+
+	switch (sig) {
+	case 0:
+		return 0;
+
+	case SIGFPE:
 		si.si_addr = fault_addr;
 		si.si_signo = sig;
-		if (sig == SIGSEGV) {
-			down_read(&current->mm->mmap_sem);
-			if (find_vma(current->mm, (unsigned long)fault_addr))
-				si.si_code = SEGV_ACCERR;
-			else
-				si.si_code = SEGV_MAPERR;
-			up_read(&current->mm->mmap_sem);
-		} else {
-			si.si_code = BUS_ADRERR;
-		}
+		/*
+		 * Inexact can happen together with Overflow or Underflow.
+		 * Respect the mask to deliver the correct exception.
+		 */
+		fcr31 &= (fcr31 & FPU_CSR_ALL_E) <<
+			 (ffs(FPU_CSR_ALL_X) - ffs(FPU_CSR_ALL_E));
+		if (fcr31 & FPU_CSR_INV_X)
+			si.si_code = FPE_FLTINV;
+		else if (fcr31 & FPU_CSR_DIV_X)
+			si.si_code = FPE_FLTDIV;
+		else if (fcr31 & FPU_CSR_OVF_X)
+			si.si_code = FPE_FLTOVF;
+		else if (fcr31 & FPU_CSR_UDF_X)
+			si.si_code = FPE_FLTUND;
+		else if (fcr31 & FPU_CSR_INE_X)
+			si.si_code = FPE_FLTRES;
+		else
+			si.si_code = __SI_FAULT;
 		force_sig_info(sig, &si, current);
 		return 1;
-	} else if (sig) {
+
+	case SIGBUS:
+		si.si_addr = fault_addr;
+		si.si_signo = sig;
+		si.si_code = BUS_ADRERR;
+		force_sig_info(sig, &si, current);
+		return 1;
+
+	case SIGSEGV:
+		si.si_addr = fault_addr;
+		si.si_signo = sig;
+		down_read(&current->mm->mmap_sem);
+		if (find_vma(current->mm, (unsigned long)fault_addr))
+			si.si_code = SEGV_ACCERR;
+		else
+			si.si_code = SEGV_MAPERR;
+		up_read(&current->mm->mmap_sem);
+		force_sig_info(sig, &si, current);
+		return 1;
+
+	default:
 		force_sig(sig, current);
 		return 1;
-	} else {
-		return 0;
 	}
 }
 
@@ -730,7 +761,8 @@ static int simulate_fp(struct pt_regs *r
 		       unsigned long old_epc, unsigned long old_ra)
 {
 	union mips_instruction inst = { .word = opcode };
-	void __user *fault_addr = NULL;
+	void __user *fault_addr;
+	unsigned long fcr31;
 	int sig;
 
 	/* If it's obviously not an FP instruction, skip it */
@@ -760,6 +792,7 @@ static int simulate_fp(struct pt_regs *r
 	/* Run the emulator */
 	sig = fpu_emulator_cop1Handler(regs, &current->thread.fpu, 1,
 				       &fault_addr);
+	fcr31 = current->thread.fpu.fcr31;
 
 	/*
 	 * We can't allow the emulated instruction to leave any of
@@ -767,12 +800,12 @@ static int simulate_fp(struct pt_regs *r
 	 */
 	current->thread.fpu.fcr31 &= ~FPU_CSR_ALL_X;
 
-	/* If something went wrong, signal */
-	process_fpemu_return(sig, fault_addr);
-
 	/* Restore the hardware register state */
 	own_fpu(1);
 
+	/* Send a signal if required.  */
+	process_fpemu_return(sig, fault_addr, fcr31);
+
 	return 0;
 }
 
@@ -782,7 +815,8 @@ static int simulate_fp(struct pt_regs *r
 asmlinkage void do_fpe(struct pt_regs *regs, unsigned long fcr31)
 {
 	enum ctx_state prev_state;
-	siginfo_t info = {0};
+	void __user *fault_addr;
+	int sig;
 
 	prev_state = exception_enter();
 	if (notify_die(DIE_FP, "FP exception", regs, 0, regs_to_trapnr(regs),
@@ -791,9 +825,6 @@ asmlinkage void do_fpe(struct pt_regs *r
 	die_if_kernel("FP exception in kernel code", regs);
 
 	if (fcr31 & FPU_CSR_UNI_X) {
-		int sig;
-		void __user *fault_addr = NULL;
-
 		/*
 		 * Unimplemented operation exception.  If we've got the full
 		 * software emulator on-board, let's use it...
@@ -810,6 +841,7 @@ asmlinkage void do_fpe(struct pt_regs *r
 		/* Run the emulator */
 		sig = fpu_emulator_cop1Handler(regs, &current->thread.fpu, 1,
 					       &fault_addr);
+		fcr31 = current->thread.fpu.fcr31;
 
 		/*
 		 * We can't allow the emulated instruction to leave any of
@@ -819,35 +851,13 @@ asmlinkage void do_fpe(struct pt_regs *r
 
 		/* Restore the hardware register state */
 		own_fpu(1);	/* Using the FPU again.	 */
-
-		/* If something went wrong, signal */
-		process_fpemu_return(sig, fault_addr);
-
-		goto out;
+	} else {
+		sig = SIGFPE;
+		fault_addr = (void __user *) regs->cp0_epc;
 	}
 
-	/*
-	 * Inexact can happen together with Overflow or Underflow.
-	 * Respect the mask to deliver the correct exception.
-	 */
-	fcr31 &= (fcr31 & FPU_CSR_ALL_E) <<
-		 (ffs(FPU_CSR_ALL_X) - ffs(FPU_CSR_ALL_E));
-	if (fcr31 & FPU_CSR_INV_X)
-		info.si_code = FPE_FLTINV;
-	else if (fcr31 & FPU_CSR_DIV_X)
-		info.si_code = FPE_FLTDIV;
-	else if (fcr31 & FPU_CSR_OVF_X)
-		info.si_code = FPE_FLTOVF;
-	else if (fcr31 & FPU_CSR_UDF_X)
-		info.si_code = FPE_FLTUND;
-	else if (fcr31 & FPU_CSR_INE_X)
-		info.si_code = FPE_FLTRES;
-	else
-		info.si_code = __SI_FAULT;
-	info.si_signo = SIGFPE;
-	info.si_errno = 0;
-	info.si_addr = (void __user *) regs->cp0_epc;
-	force_sig_info(SIGFPE, &info, current);
+	/* Send a signal if required.  */
+	process_fpemu_return(sig, fault_addr, fcr31);
 
 out:
 	exception_exit(prev_state);
@@ -1050,7 +1060,9 @@ asmlinkage void do_ri(struct pt_regs *re
 	if (mipsr2_emulation && cpu_has_mips_r6 &&
 	    likely(user_mode(regs)) &&
 	    likely(get_user(opcode, epc) >= 0)) {
-		status = mipsr2_decoder(regs, opcode);
+		unsigned long fcr31 = 0;
+
+		status = mipsr2_decoder(regs, opcode, &fcr31);
 		switch (status) {
 		case 0:
 		case SIGEMT:
@@ -1060,7 +1072,8 @@ asmlinkage void do_ri(struct pt_regs *re
 			goto no_r2_instr;
 		default:
 			process_fpemu_return(status,
-					     &current->thread.cp0_baduaddr);
+					     &current->thread.cp0_baduaddr,
+					     fcr31);
 			task_thread_info(current)->r2_emul_return = 1;
 			return;
 		}
@@ -1307,10 +1320,13 @@ asmlinkage void do_cpu(struct pt_regs *r
 	enum ctx_state prev_state;
 	unsigned int __user *epc;
 	unsigned long old_epc, old31;
+	void __user *fault_addr;
 	unsigned int opcode;
+	unsigned long fcr31;
 	unsigned int cpid;
 	int status, err;
 	unsigned long __maybe_unused flags;
+	int sig;
 
 	prev_state = exception_enter();
 	cpid = (regs->cp0_cause >> CAUSEB_CE) & 3;
@@ -1384,22 +1400,22 @@ asmlinkage void do_cpu(struct pt_regs *r
 	case 1:
 		err = enable_restore_fp_context(0);
 
-		if (!raw_cpu_has_fpu || err) {
-			int sig;
-			void __user *fault_addr = NULL;
-			sig = fpu_emulator_cop1Handler(regs,
-						       &current->thread.fpu,
-						       0, &fault_addr);
+		if (raw_cpu_has_fpu && !err)
+			break;
 
-			/*
-			 * We can't allow the emulated instruction to leave
-			 * any of the cause bits set in $fcr31.
-			 */
-			current->thread.fpu.fcr31 &= ~FPU_CSR_ALL_X;
+		sig = fpu_emulator_cop1Handler(regs, &current->thread.fpu, 0,
+					       &fault_addr);
+		fcr31 = current->thread.fpu.fcr31;
 
-			if (!process_fpemu_return(sig, fault_addr) && !err)
-				mt_ase_fp_affinity();
-		}
+		/*
+		 * We can't allow the emulated instruction to leave
+		 * any of the cause bits set in $fcr31.
+		 */
+		current->thread.fpu.fcr31 &= ~FPU_CSR_ALL_X;
+
+		/* Send a signal if required.  */
+		if (!process_fpemu_return(sig, fault_addr, fcr31) && !err)
+			mt_ase_fp_affinity();
 
 		break;
 
Index: linux/arch/mips/kernel/unaligned.c
===================================================================
--- linux.orig/arch/mips/kernel/unaligned.c	2015-04-02 20:18:48.702496000 +0100
+++ linux/arch/mips/kernel/unaligned.c	2015-04-02 20:27:58.466232000 +0100
@@ -1076,7 +1076,7 @@ static void emulate_load_store_insn(stru
 		own_fpu(1);	/* Restore FPU state. */
 
 		/* Signal if something went wrong. */
-		process_fpemu_return(res, fault_addr);
+		process_fpemu_return(res, fault_addr, 0);
 
 		if (res == 0)
 			break;
@@ -1511,7 +1511,7 @@ static void emulate_load_store_microMIPS
 		own_fpu(1);	/* restore FPU state */
 
 		/* If something went wrong, signal */
-		process_fpemu_return(res, fault_addr);
+		process_fpemu_return(res, fault_addr, 0);
 
 		if (res == 0)
 			goto success;

^ permalink raw reply	[flat|nested] 62+ messages in thread

* [PATCH 42/48] MIPS: Correct ISA masking in FPU feature determination
  2015-04-03 22:23 [PATCH 00/48] FPU and FP emulation clean-ups, fixes and feature updates Maciej W. Rozycki
                   ` (38 preceding siblings ...)
  2015-04-03 22:27 ` [PATCH 41/48] MIPS: Set `si_code' for SIGFPE signals sent from emulation too Maciej W. Rozycki
@ 2015-04-03 22:27 ` Maciej W. Rozycki
  2015-04-03 22:27 ` [PATCH 43/48] MIPS: math-emu: Set FIR feature flags for full emulation Maciej W. Rozycki
                   ` (6 subsequent siblings)
  46 siblings, 0 replies; 62+ messages in thread
From: Maciej W. Rozycki @ 2015-04-03 22:27 UTC (permalink / raw)
  To: Ralf Baechle; +Cc: Leonid Yegoshin, linux-mips

Correct an ISA level determination problem introduced with 8b8aa636 
[MIPS: kernel: cpu-probe.c: Add support for MIPS R6], reverting explicit 
masking against individual `MIPS_CPU_ISA_*' macros in FPU feature 
determination.

Feature macros such as `cpu_has_mips_r' cannot be used here, because 
they operate on CPU #0 and we want to refer to the current CPU instead.  
They cannot be used for masking against the current CPU either because 
they mask against CPU #0 too, e.g.:

# define cpu_has_mips32r1	(cpu_data[0].isa_level & MIPS_CPU_ISA_M32R1)

Cc: Leonid Yegoshin <Leonid.Yegoshin@imgtec.com>
Signed-off-by: Maciej W. Rozycki <macro@linux-mips.org>
---
linux-mips-fpu-probe-isa.diff
Index: linux/arch/mips/kernel/cpu-probe.c
===================================================================
--- linux.orig/arch/mips/kernel/cpu-probe.c	2015-04-02 20:27:52.971189000 +0100
+++ linux/arch/mips/kernel/cpu-probe.c	2015-04-02 20:27:58.700229000 +0100
@@ -1367,7 +1367,9 @@ void cpu_probe(void)
 	if (c->options & MIPS_CPU_FPU) {
 		c->fpu_id = cpu_get_fpu_id();
 
-		if (c->isa_level & cpu_has_mips_r) {
+		if (c->isa_level & (MIPS_CPU_ISA_M32R1 | MIPS_CPU_ISA_M64R1 |
+				    MIPS_CPU_ISA_M32R2 | MIPS_CPU_ISA_M64R2 |
+				    MIPS_CPU_ISA_M32R6 | MIPS_CPU_ISA_M64R6)) {
 			if (c->fpu_id & MIPS_FPIR_3D)
 				c->ases |= MIPS_ASE_MIPS3D;
 			if (c->fpu_id & MIPS_FPIR_FREP)

^ permalink raw reply	[flat|nested] 62+ messages in thread

* [PATCH 43/48] MIPS: math-emu: Set FIR feature flags for full emulation
  2015-04-03 22:23 [PATCH 00/48] FPU and FP emulation clean-ups, fixes and feature updates Maciej W. Rozycki
                   ` (39 preceding siblings ...)
  2015-04-03 22:27 ` [PATCH 42/48] MIPS: Correct ISA masking in FPU feature determination Maciej W. Rozycki
@ 2015-04-03 22:27 ` Maciej W. Rozycki
  2015-04-03 23:18   ` Sergei Shtylyov
  2015-04-03 22:27 ` [PATCH 44/48] MIPS: math-emu: Implement the FCCR, FEXR and FENR registers Maciej W. Rozycki
                   ` (5 subsequent siblings)
  46 siblings, 1 reply; 62+ messages in thread
From: Maciej W. Rozycki @ 2015-04-03 22:27 UTC (permalink / raw)
  To: Ralf Baechle; +Cc: linux-mips

Implement FIR feature flags in the FPU emulator according to features 
supported and architecture level requirements.  The W, L and F64 bits 
have only been added at level #2 even though the features they refer to 
were also included with the MIPS64r1 ISA and the W fixed-point format 
also with the MIPS32r1 ISA.

This is only relevant for the full emulation mode and the emulated CFC1 
instruction as well as ptrace(2) accesses.

Signed-off-by: Maciej W. Rozycki <macro@linux-mips.org>
---
linux-mips-emu-fir.diff
Index: linux/arch/mips/kernel/cpu-probe.c
===================================================================
--- linux.orig/arch/mips/kernel/cpu-probe.c	2015-04-02 20:27:58.700229000 +0100
+++ linux/arch/mips/kernel/cpu-probe.c	2015-04-02 20:27:58.890231000 +0100
@@ -20,6 +20,7 @@
 
 #include <asm/bugs.h>
 #include <asm/cpu.h>
+#include <asm/cpu-features.h>
 #include <asm/cpu-type.h>
 #include <asm/fpu.h>
 #include <asm/mipsregs.h>
@@ -31,11 +32,30 @@
 #include <asm/spram.h>
 #include <asm/uaccess.h>
 
+/*
+ * Set the FIR feature flags for the FPU emulator.
+ */
+static void cpu_set_nofpu_id(struct cpuinfo_mips *c)
+{
+	u32 value;
+
+	value = 0;
+	if (c->isa_level & (MIPS_CPU_ISA_M32R1 | MIPS_CPU_ISA_M64R1 |
+			    MIPS_CPU_ISA_M32R2 | MIPS_CPU_ISA_M64R2 |
+			    MIPS_CPU_ISA_M32R6 | MIPS_CPU_ISA_M64R6))
+		value |= MIPS_FPIR_D | MIPS_FPIR_S;
+	if (c->isa_level & (MIPS_CPU_ISA_M32R2 | MIPS_CPU_ISA_M64R2 |
+			    MIPS_CPU_ISA_M32R6 | MIPS_CPU_ISA_M64R6))
+		value |= MIPS_FPIR_F64 | MIPS_FPIR_L | MIPS_FPIR_W;
+	c->fpu_id = value;
+}
+
 static int mips_fpu_disabled;
 
 static int __init fpu_disable(char *s)
 {
-	cpu_data[0].options &= ~MIPS_CPU_FPU;
+	boot_cpu_data.options &= ~MIPS_CPU_FPU;
+	cpu_set_nofpu_id(&boot_cpu_data);
 	mips_fpu_disabled = 1;
 
 	return 1;
@@ -1375,7 +1395,8 @@ void cpu_probe(void)
 			if (c->fpu_id & MIPS_FPIR_FREP)
 				c->options |= MIPS_CPU_FRE;
 		}
-	}
+	} else
+		cpu_set_nofpu_id(c);
 
 	if (cpu_has_mips_r2_r6) {
 		c->srsets = ((read_c0_srsctl() >> 26) & 0x0f) + 1;
Index: linux/arch/mips/math-emu/cp1emu.c
===================================================================
--- linux.orig/arch/mips/math-emu/cp1emu.c	2015-04-02 20:27:57.710224000 +0100
+++ linux/arch/mips/math-emu/cp1emu.c	2015-04-02 20:27:58.894230000 +0100
@@ -45,6 +45,7 @@
 #include <asm/signal.h>
 #include <asm/uaccess.h>
 
+#include <asm/cpu-info.h>
 #include <asm/processor.h>
 #include <asm/fpu_emulator.h>
 #include <asm/fpu.h>
@@ -853,7 +854,7 @@ static inline void cop1_cfc(struct pt_re
 			 (void *)xcp->cp0_epc,
 			 MIPSInst_RT(ir), value);
 	} else if (MIPSInst_RD(ir) == FPCREG_RID)
-		value = 0;
+		value = current_cpu_data.fpu_id;
 	else
 		value = 0;
 	if (MIPSInst_RT(ir))

^ permalink raw reply	[flat|nested] 62+ messages in thread

* [PATCH 44/48] MIPS: math-emu: Implement the FCCR, FEXR and FENR registers
  2015-04-03 22:23 [PATCH 00/48] FPU and FP emulation clean-ups, fixes and feature updates Maciej W. Rozycki
                   ` (40 preceding siblings ...)
  2015-04-03 22:27 ` [PATCH 43/48] MIPS: math-emu: Set FIR feature flags for full emulation Maciej W. Rozycki
@ 2015-04-03 22:27 ` Maciej W. Rozycki
  2015-04-03 22:27 ` [PATCH 45/48] MIPS: math-emu: Define IEEE 754-2008 feature control bits Maciej W. Rozycki
                   ` (4 subsequent siblings)
  46 siblings, 0 replies; 62+ messages in thread
From: Maciej W. Rozycki @ 2015-04-03 22:27 UTC (permalink / raw)
  To: Ralf Baechle; +Cc: linux-mips

Implement the FCCR, FEXR and FENR "shadow" FPU registers for the 
architecture levels that include them, for the CFC1 and CTC1 
instructions in the full emulation mode.

For completeness add macros for the CP1 UFR and UNFR registers too, no 
actual implementation though.

Signed-off-by: Maciej W. Rozycki <macro@linux-mips.org>
---
Ralf,

 Again, this causes a flood of checkpatch.pl errors:

ERROR: Macros with complex values should be enclosed in parentheses
#11: FILE: arch/mips/include/asm/mipsregs.h:680:
+#define CP1_REVISION	$0

ERROR: Macros with complex values should be enclosed in parentheses
#12: FILE: arch/mips/include/asm/mipsregs.h:681:
+#define CP1_UFR		$1

ERROR: Macros with complex values should be enclosed in parentheses
#13: FILE: arch/mips/include/asm/mipsregs.h:682:
+#define CP1_UNFR	$4

ERROR: Macros with complex values should be enclosed in parentheses
#14: FILE: arch/mips/include/asm/mipsregs.h:683:
+#define CP1_FCCR	$25

ERROR: Macros with complex values should be enclosed in parentheses
#15: FILE: arch/mips/include/asm/mipsregs.h:684:
+#define CP1_FEXR	$26

ERROR: Macros with complex values should be enclosed in parentheses
#16: FILE: arch/mips/include/asm/mipsregs.h:685:
+#define CP1_FENR	$28

ERROR: Macros with complex values should be enclosed in parentheses
#17: FILE: arch/mips/include/asm/mipsregs.h:686:
+#define CP1_STATUS	$31

that I think we'll just have to live with, there's nothing wrong with 
these macros and their intended purpose.

  Maciej

linux-mips-emu-fcr.diff
Index: linux/arch/mips/include/asm/mipsregs.h
===================================================================
--- linux.orig/arch/mips/include/asm/mipsregs.h	2015-04-02 20:27:52.242161000 +0100
+++ linux/arch/mips/include/asm/mipsregs.h	2015-04-02 20:27:59.089235000 +0100
@@ -677,8 +677,13 @@
 /*
  * Coprocessor 1 (FPU) register names
  */
-#define CP1_REVISION   $0
-#define CP1_STATUS     $31
+#define CP1_REVISION	$0
+#define CP1_UFR		$1
+#define CP1_UNFR	$4
+#define CP1_FCCR	$25
+#define CP1_FEXR	$26
+#define CP1_FENR	$28
+#define CP1_STATUS	$31
 
 
 /*
@@ -694,18 +699,58 @@
 #define MIPS_FPIR_FREP		(_ULCAST_(1) << 29)
 
 /*
+ * Bits in the MIPS32/64 coprocessor 1 (FPU) condition codes register.
+ */
+#define MIPS_FCCR_CONDX_S	0
+#define MIPS_FCCR_CONDX		(_ULCAST_(255) << MIPS_FCCR_CONDX_S)
+#define MIPS_FCCR_COND0_S	0
+#define MIPS_FCCR_COND0		(_ULCAST_(1) << MIPS_FCCR_COND0_S)
+#define MIPS_FCCR_COND1_S	1
+#define MIPS_FCCR_COND1		(_ULCAST_(1) << MIPS_FCCR_COND1_S)
+#define MIPS_FCCR_COND2_S	2
+#define MIPS_FCCR_COND2		(_ULCAST_(1) << MIPS_FCCR_COND2_S)
+#define MIPS_FCCR_COND3_S	3
+#define MIPS_FCCR_COND3		(_ULCAST_(1) << MIPS_FCCR_COND3_S)
+#define MIPS_FCCR_COND4_S	4
+#define MIPS_FCCR_COND4		(_ULCAST_(1) << MIPS_FCCR_COND4_S)
+#define MIPS_FCCR_COND5_S	5
+#define MIPS_FCCR_COND5		(_ULCAST_(1) << MIPS_FCCR_COND5_S)
+#define MIPS_FCCR_COND6_S	6
+#define MIPS_FCCR_COND6		(_ULCAST_(1) << MIPS_FCCR_COND6_S)
+#define MIPS_FCCR_COND7_S	7
+#define MIPS_FCCR_COND7		(_ULCAST_(1) << MIPS_FCCR_COND7_S)
+
+/*
+ * Bits in the MIPS32/64 coprocessor 1 (FPU) enables register.
+ */
+#define MIPS_FENR_FS_S		2
+#define MIPS_FENR_FS		(_ULCAST_(1) << MIPS_FENR_FS_S)
+
+/*
  * FPU Status Register Values
  */
-#define FPU_CSR_FLUSH	0x01000000	/* flush denormalised results to 0 */
-#define FPU_CSR_COND	0x00800000	/* $fcc0 */
-#define FPU_CSR_COND0	0x00800000	/* $fcc0 */
-#define FPU_CSR_COND1	0x02000000	/* $fcc1 */
-#define FPU_CSR_COND2	0x04000000	/* $fcc2 */
-#define FPU_CSR_COND3	0x08000000	/* $fcc3 */
-#define FPU_CSR_COND4	0x10000000	/* $fcc4 */
-#define FPU_CSR_COND5	0x20000000	/* $fcc5 */
-#define FPU_CSR_COND6	0x40000000	/* $fcc6 */
-#define FPU_CSR_COND7	0x80000000	/* $fcc7 */
+#define FPU_CSR_COND_S	23					/* $fcc0 */
+#define FPU_CSR_COND	(_ULCAST_(1) << FPU_CSR_COND_S)
+
+#define FPU_CSR_FS_S	24		/* flush denormalised results to 0 */
+#define FPU_CSR_FS	(_ULCAST_(1) << FPU_CSR_FS_S)
+
+#define FPU_CSR_CONDX_S	25					/* $fcc[7:1] */
+#define FPU_CSR_CONDX	(_ULCAST_(127) << FPU_CSR_CONDX_S)
+#define FPU_CSR_COND1_S	25					/* $fcc1 */
+#define FPU_CSR_COND1	(_ULCAST_(1) << FPU_CSR_COND1_S)
+#define FPU_CSR_COND2_S	26					/* $fcc2 */
+#define FPU_CSR_COND2	(_ULCAST_(1) << FPU_CSR_COND2_S)
+#define FPU_CSR_COND3_S	27					/* $fcc3 */
+#define FPU_CSR_COND3	(_ULCAST_(1) << FPU_CSR_COND3_S)
+#define FPU_CSR_COND4_S	28					/* $fcc4 */
+#define FPU_CSR_COND4	(_ULCAST_(1) << FPU_CSR_COND4_S)
+#define FPU_CSR_COND5_S	29					/* $fcc5 */
+#define FPU_CSR_COND5	(_ULCAST_(1) << FPU_CSR_COND5_S)
+#define FPU_CSR_COND6_S	30					/* $fcc6 */
+#define FPU_CSR_COND6	(_ULCAST_(1) << FPU_CSR_COND6_S)
+#define FPU_CSR_COND7_S	31					/* $fcc7 */
+#define FPU_CSR_COND7	(_ULCAST_(1) << FPU_CSR_COND7_S)
 
 /*
  * Bits 18 - 20 of the FPU Status Register will be read as 0,
Index: linux/arch/mips/math-emu/cp1emu.c
===================================================================
--- linux.orig/arch/mips/math-emu/cp1emu.c	2015-04-02 20:27:58.894230000 +0100
+++ linux/arch/mips/math-emu/cp1emu.c	2015-04-02 20:27:59.094235000 +0100
@@ -64,11 +64,14 @@ static int fpux_emu(struct pt_regs *,
 /* Control registers */
 
 #define FPCREG_RID	0	/* $0  = revision id */
+#define FPCREG_FCCR	25	/* $25 = fccr */
+#define FPCREG_FEXR	26	/* $26 = fexr */
+#define FPCREG_FENR	28	/* $28 = fenr */
 #define FPCREG_CSR	31	/* $31 = csr */
 
 /* convert condition code register number to csr bit */
 const unsigned int fpucondbit[8] = {
-	FPU_CSR_COND0,
+	FPU_CSR_COND,
 	FPU_CSR_COND1,
 	FPU_CSR_COND2,
 	FPU_CSR_COND3,
@@ -846,17 +849,53 @@ do {									\
 static inline void cop1_cfc(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
 			    mips_instruction ir)
 {
-	u32 value;
+	u32 fcr31 = ctx->fcr31;
+	u32 value = 0;
 
-	if (MIPSInst_RD(ir) == FPCREG_CSR) {
-		value = ctx->fcr31;
+	switch (MIPSInst_RD(ir)) {
+	case FPCREG_CSR:
+		value = fcr31;
 		pr_debug("%p gpr[%d]<-csr=%08x\n",
-			 (void *)xcp->cp0_epc,
-			 MIPSInst_RT(ir), value);
-	} else if (MIPSInst_RD(ir) == FPCREG_RID)
+			 (void *)xcp->cp0_epc, MIPSInst_RT(ir), value);
+		break;
+
+	case FPCREG_FENR:
+		if (!cpu_has_mips_r)
+			break;
+		value = (fcr31 >> (FPU_CSR_FS_S - MIPS_FENR_FS_S)) &
+			MIPS_FENR_FS;
+		value |= fcr31 & (FPU_CSR_ALL_E | FPU_CSR_RM);
+		pr_debug("%p gpr[%d]<-enr=%08x\n",
+			 (void *)xcp->cp0_epc, MIPSInst_RT(ir), value);
+		break;
+
+	case FPCREG_FEXR:
+		if (!cpu_has_mips_r)
+			break;
+		value = fcr31 & (FPU_CSR_ALL_X | FPU_CSR_ALL_S);
+		pr_debug("%p gpr[%d]<-exr=%08x\n",
+			 (void *)xcp->cp0_epc, MIPSInst_RT(ir), value);
+		break;
+
+	case FPCREG_FCCR:
+		if (!cpu_has_mips_r)
+			break;
+		value = (fcr31 >> (FPU_CSR_COND_S - MIPS_FCCR_COND0_S)) &
+			MIPS_FCCR_COND0;
+		value |= (fcr31 >> (FPU_CSR_COND1_S - MIPS_FCCR_COND1_S)) &
+			 (MIPS_FCCR_CONDX & ~MIPS_FCCR_COND0);
+		pr_debug("%p gpr[%d]<-ccr=%08x\n",
+			 (void *)xcp->cp0_epc, MIPSInst_RT(ir), value);
+		break;
+
+	case FPCREG_RID:
 		value = current_cpu_data.fpu_id;
-	else
-		value = 0;
+		break;
+
+	default:
+		break;
+	}
+
 	if (MIPSInst_RT(ir))
 		xcp->regs[MIPSInst_RT(ir)] = value;
 }
@@ -867,6 +906,7 @@ static inline void cop1_cfc(struct pt_re
 static inline void cop1_ctc(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
 			    mips_instruction ir)
 {
+	u32 fcr31 = ctx->fcr31;
 	u32 value;
 
 	if (MIPSInst_RT(ir) == 0)
@@ -874,16 +914,52 @@ static inline void cop1_ctc(struct pt_re
 	else
 		value = xcp->regs[MIPSInst_RT(ir)];
 
-	/* we only have one writable control reg
-	 */
-	if (MIPSInst_RD(ir) == FPCREG_CSR) {
+	switch (MIPSInst_RD(ir)) {
+	case FPCREG_CSR:
 		pr_debug("%p gpr[%d]->csr=%08x\n",
-			 (void *)xcp->cp0_epc,
-			 MIPSInst_RT(ir), value);
+			 (void *)xcp->cp0_epc, MIPSInst_RT(ir), value);
 
 		/* Don't write reserved bits.  */
-		ctx->fcr31 = value & ~FPU_CSR_RSVD;
+		fcr31 = value & ~FPU_CSR_RSVD;
+		break;
+
+	case FPCREG_FENR:
+		if (!cpu_has_mips_r)
+			break;
+		pr_debug("%p gpr[%d]->enr=%08x\n",
+			 (void *)xcp->cp0_epc, MIPSInst_RT(ir), value);
+		fcr31 &= ~(FPU_CSR_FS | FPU_CSR_ALL_E | FPU_CSR_RM);
+		fcr31 |= (value << (FPU_CSR_FS_S - MIPS_FENR_FS_S)) &
+			 FPU_CSR_FS;
+		fcr31 |= value & (FPU_CSR_ALL_E | FPU_CSR_RM);
+		break;
+
+	case FPCREG_FEXR:
+		if (!cpu_has_mips_r)
+			break;
+		pr_debug("%p gpr[%d]->exr=%08x\n",
+			 (void *)xcp->cp0_epc, MIPSInst_RT(ir), value);
+		fcr31 &= ~(FPU_CSR_ALL_X | FPU_CSR_ALL_S);
+		fcr31 |= value & (FPU_CSR_ALL_X | FPU_CSR_ALL_S);
+		break;
+
+	case FPCREG_FCCR:
+		if (!cpu_has_mips_r)
+			break;
+		pr_debug("%p gpr[%d]->ccr=%08x\n",
+			 (void *)xcp->cp0_epc, MIPSInst_RT(ir), value);
+		fcr31 &= ~(FPU_CSR_CONDX | FPU_CSR_COND);
+		fcr31 |= (value << (FPU_CSR_COND_S - MIPS_FCCR_COND0_S)) &
+			 FPU_CSR_COND;
+		fcr31 |= (value << (FPU_CSR_COND1_S - MIPS_FCCR_COND1_S)) &
+			 FPU_CSR_CONDX;
+		break;
+
+	default:
+		break;
 	}
+
+	ctx->fcr31 = fcr31;
 }
 
 /*

^ permalink raw reply	[flat|nested] 62+ messages in thread

* [PATCH 45/48] MIPS: math-emu: Define IEEE 754-2008 feature control bits
  2015-04-03 22:23 [PATCH 00/48] FPU and FP emulation clean-ups, fixes and feature updates Maciej W. Rozycki
                   ` (41 preceding siblings ...)
  2015-04-03 22:27 ` [PATCH 44/48] MIPS: math-emu: Implement the FCCR, FEXR and FENR registers Maciej W. Rozycki
@ 2015-04-03 22:27 ` Maciej W. Rozycki
  2015-04-03 22:27 ` [PATCH 46/48] MIPS: math-emu: Make ABS.fmt and NEG.fmt arithmetic again Maciej W. Rozycki
                   ` (3 subsequent siblings)
  46 siblings, 0 replies; 62+ messages in thread
From: Maciej W. Rozycki @ 2015-04-03 22:27 UTC (permalink / raw)
  To: Ralf Baechle; +Cc: linux-mips

Define IEEE 754-2008 feature control bits: FIR.HAS2008, FCSR.ABS2008 and 
FCSR.NAN2008, and update the `_ieee754_csr' structure accordingly.

For completeness define FIR.UFRP too.

Signed-off-by: Maciej W. Rozycki <macro@linux-mips.org>
---
linux-mips-cp1-fcsr.diff
Index: linux/arch/mips/include/asm/mipsregs.h
===================================================================
--- linux.orig/arch/mips/include/asm/mipsregs.h	2015-04-03 15:55:16.641969000 +0100
+++ linux/arch/mips/include/asm/mipsregs.h	2015-04-03 15:55:17.630977000 +0100
@@ -696,6 +696,8 @@
 #define MIPS_FPIR_W		(_ULCAST_(1) << 20)
 #define MIPS_FPIR_L		(_ULCAST_(1) << 21)
 #define MIPS_FPIR_F64		(_ULCAST_(1) << 22)
+#define MIPS_FPIR_HAS2008	(_ULCAST_(1) << 23)
+#define MIPS_FPIR_UFRP		(_ULCAST_(1) << 28)
 #define MIPS_FPIR_FREP		(_ULCAST_(1) << 29)
 
 /*
@@ -753,10 +755,13 @@
 #define FPU_CSR_COND7	(_ULCAST_(1) << FPU_CSR_COND7_S)
 
 /*
- * Bits 18 - 20 of the FPU Status Register will be read as 0,
+ * Bits 22:20 of the FPU Status Register will be read as 0,
  * and should be written as zero.
  */
-#define FPU_CSR_RSVD	0x001c0000
+#define FPU_CSR_RSVD	(_ULCAST_(7) << 20)
+
+#define FPU_CSR_ABS2008	(_ULCAST_(1) << 19)
+#define FPU_CSR_NAN2008	(_ULCAST_(1) << 18)
 
 /*
  * X the exception cause indicator
Index: linux/arch/mips/math-emu/cp1emu.c
===================================================================
--- linux.orig/arch/mips/math-emu/cp1emu.c	2015-04-03 15:55:16.656968000 +0100
+++ linux/arch/mips/math-emu/cp1emu.c	2015-04-03 15:55:17.635977000 +0100
@@ -919,8 +919,9 @@ static inline void cop1_ctc(struct pt_re
 		pr_debug("%p gpr[%d]->csr=%08x\n",
 			 (void *)xcp->cp0_epc, MIPSInst_RT(ir), value);
 
-		/* Don't write reserved bits.  */
-		fcr31 = value & ~FPU_CSR_RSVD;
+		/* Don't write unsupported bits.  */
+		fcr31 = value &
+			~(FPU_CSR_RSVD | FPU_CSR_ABS2008 | FPU_CSR_NAN2008);
 		break;
 
 	case FPCREG_FENR:
Index: linux/arch/mips/math-emu/ieee754.h
===================================================================
--- linux.orig/arch/mips/math-emu/ieee754.h	2015-04-03 13:42:52.928882000 +0100
+++ linux/arch/mips/math-emu/ieee754.h	2015-04-03 15:55:17.637981000 +0100
@@ -130,15 +130,17 @@ enum {
  * The control status register
  */
 struct _ieee754_csr {
-	__BITFIELD_FIELD(unsigned pad0:7,
-	__BITFIELD_FIELD(unsigned nod:1,	/* set 1 for no denormalised numbers */
-	__BITFIELD_FIELD(unsigned c:1,		/* condition */
-	__BITFIELD_FIELD(unsigned pad1:5,
+	__BITFIELD_FIELD(unsigned fcc:7,	/* condition[7:1] */
+	__BITFIELD_FIELD(unsigned nod:1,	/* set 1 for no denormals */
+	__BITFIELD_FIELD(unsigned c:1,		/* condition[0] */
+	__BITFIELD_FIELD(unsigned pad0:3,
+	__BITFIELD_FIELD(unsigned abs2008:1,	/* IEEE 754-2008 ABS/NEG.fmt */
+	__BITFIELD_FIELD(unsigned nan2008:1,	/* IEEE 754-2008 NaN mode */
 	__BITFIELD_FIELD(unsigned cx:6,		/* exceptions this operation */
 	__BITFIELD_FIELD(unsigned mx:5,		/* exception enable  mask */
 	__BITFIELD_FIELD(unsigned sx:5,		/* exceptions total */
 	__BITFIELD_FIELD(unsigned rm:2,		/* current rounding mode */
-	;))))))))
+	;))))))))))
 };
 #define ieee754_csr (*(struct _ieee754_csr *)(&current->thread.fpu.fcr31))
 

^ permalink raw reply	[flat|nested] 62+ messages in thread

* [PATCH 46/48] MIPS: math-emu: Make ABS.fmt and NEG.fmt arithmetic again
  2015-04-03 22:23 [PATCH 00/48] FPU and FP emulation clean-ups, fixes and feature updates Maciej W. Rozycki
                   ` (42 preceding siblings ...)
  2015-04-03 22:27 ` [PATCH 45/48] MIPS: math-emu: Define IEEE 754-2008 feature control bits Maciej W. Rozycki
@ 2015-04-03 22:27 ` Maciej W. Rozycki
  2015-04-07 15:24   ` Maciej W. Rozycki
  2015-04-03 22:27 ` [PATCH 47/48] MIPS: Respect the ISA level in FCSR handling Maciej W. Rozycki
                   ` (2 subsequent siblings)
  46 siblings, 1 reply; 62+ messages in thread
From: Maciej W. Rozycki @ 2015-04-03 22:27 UTC (permalink / raw)
  To: Ralf Baechle; +Cc: linux-mips

The ABS.fmt and NEG.fmt instructions have been specified as arithmetic 
in the MIPS architecture, which in particular implies handling NaN data 
in the usual way with qNaN bit patterns propagated unchanged and sNaN 
bit patterns signalling the usual IEEE 754 Invalid Operation exception 
and quieted by default.

A series of changes applied over time to our implementation:

c5033d78 [MIPS] ieee754[sd]p_neg workaround
cea2be44 MIPS: Fix abs.[sd] and neg.[sd] emulation for NaN operands

has led to the current situation where the sign bit is updated according 
to the operation requested even for NaN inputs.  This is according to 
these commits a workaround so that broken binaries produced by GCC 
disregarding the properties of these instructions have a chance to work.

For sNaN inputs this remains within IEEE Std 754 as the standard leaves 
the choice of output qNaN bit patterns produced under the default 
Invalid Operation exception handling for individual sNaN input bit 
patterns to implementer's discretion, even though it still recommends as 
much NaN input information to be preserved in NaN outputs.

For qNaN inputs however it violates the standard as it requires a qNaN 
input bit patterns to propagate unchanged to output.

This is also unlike real MIPS FPU hardware behaves where sNaN and/or 
qNaN processing has been fully implemented with no Unimplemented 
Operation exception signalled.  Such hardware propagates any input qNaN 
bit pattern unchanged.  It also quiets any input sNaN bit pattern in an 
implementer-specific manner, for example the MIPS 74Kf processor returns 
the default qNaN pattern with the sign bit always clear and the Broadcom 
SB-1 and BMIPS5000 processors propagate the input sNaN bit pattern with 
the sign bit unchanged and the quiet bit first cleared in the trailing 
significand field and then the next lower bit set if clearing the quiet 
bit left the field with no other bit set.

Especially the latter observation indicates the limited usefulness of 
the workaround as it will cover many hardware configurations, but not 
all of them, only making it harder to discover such broken binaries that 
need to be recompiled with GCC told to avoid the use of ABS.fmt and 
NEG.fmt instructions where non-arithmetic semantics is required by the 
algorithm used.

Revert the damage done by the series of changes then, and take the 
opportunity to simplify implementation by calling `ieee754dp_sub' and 
`ieee754dp_add' as required and also the rounding mode set towards -Inf 
temporarily so that the sign of 0 is correctly handled.

Signed-off-by: Maciej W. Rozycki <macro@linux-mips.org>
---
linux-mips-fpe-emu-abs.diff
Index: linux/arch/mips/math-emu/dp_simple.c
===================================================================
--- linux.orig/arch/mips/math-emu/dp_simple.c	2015-04-02 20:18:47.633483000 +0100
+++ linux/arch/mips/math-emu/dp_simple.c	2015-04-02 20:27:59.532238000 +0100
@@ -23,44 +23,27 @@
 
 union ieee754dp ieee754dp_neg(union ieee754dp x)
 {
-	COMPXDP;
-
-	EXPLODEXDP;
-	ieee754_clearcx();
-	FLUSHXDP;
-
-	/*
-	 * Invert the sign ALWAYS to prevent an endless recursion on
-	 * pow() in libc.
-	 */
-	/* quick fix up */
-	DPSIGN(x) ^= 1;
-
-	if (xc == IEEE754_CLASS_SNAN) {
-		union ieee754dp y = ieee754dp_indef();
-		ieee754_setcx(IEEE754_INVALID_OPERATION);
-		DPSIGN(y) = DPSIGN(x);
-		return ieee754dp_nanxcpt(y);
-	}
+	unsigned int oldrm;
+	union ieee754dp y;
 
-	return x;
+	oldrm = ieee754_csr.rm;
+	ieee754_csr.rm = FPU_CSR_RD;
+	y = ieee754dp_sub(ieee754dp_zero(0), x);
+	ieee754_csr.rm = oldrm;
+	return y;
 }
 
 union ieee754dp ieee754dp_abs(union ieee754dp x)
 {
-	COMPXDP;
-
-	EXPLODEXDP;
-	ieee754_clearcx();
-	FLUSHXDP;
-
-	/* Clear sign ALWAYS, irrespective of NaN */
-	DPSIGN(x) = 0;
-
-	if (xc == IEEE754_CLASS_SNAN) {
-		ieee754_setcx(IEEE754_INVALID_OPERATION);
-		return ieee754dp_nanxcpt(ieee754dp_indef());
-	}
+	unsigned int oldrm;
+	union ieee754dp y;
 
-	return x;
+	oldrm = ieee754_csr.rm;
+	ieee754_csr.rm = FPU_CSR_RD;
+	if (DPSIGN(x))
+		y = ieee754dp_sub(ieee754dp_zero(0), x);
+	else
+		y = ieee754dp_add(ieee754dp_zero(0), x);
+	ieee754_csr.rm = oldrm;
+	return y;
 }
Index: linux/arch/mips/math-emu/sp_simple.c
===================================================================
--- linux.orig/arch/mips/math-emu/sp_simple.c	2015-04-02 20:18:47.637483000 +0100
+++ linux/arch/mips/math-emu/sp_simple.c	2015-04-02 20:27:59.534255000 +0100
@@ -23,44 +23,27 @@
 
 union ieee754sp ieee754sp_neg(union ieee754sp x)
 {
-	COMPXSP;
-
-	EXPLODEXSP;
-	ieee754_clearcx();
-	FLUSHXSP;
-
-	/*
-	 * Invert the sign ALWAYS to prevent an endless recursion on
-	 * pow() in libc.
-	 */
-	/* quick fix up */
-	SPSIGN(x) ^= 1;
-
-	if (xc == IEEE754_CLASS_SNAN) {
-		union ieee754sp y = ieee754sp_indef();
-		ieee754_setcx(IEEE754_INVALID_OPERATION);
-		SPSIGN(y) = SPSIGN(x);
-		return ieee754sp_nanxcpt(y);
-	}
+	unsigned int oldrm;
+	union ieee754sp y;
 
-	return x;
+	oldrm = ieee754_csr.rm;
+	ieee754_csr.rm = FPU_CSR_RD;
+	y = ieee754sp_sub(ieee754sp_zero(0), x);
+	ieee754_csr.rm = oldrm;
+	return y;
 }
 
 union ieee754sp ieee754sp_abs(union ieee754sp x)
 {
-	COMPXSP;
-
-	EXPLODEXSP;
-	ieee754_clearcx();
-	FLUSHXSP;
-
-	/* Clear sign ALWAYS, irrespective of NaN */
-	SPSIGN(x) = 0;
-
-	if (xc == IEEE754_CLASS_SNAN) {
-		ieee754_setcx(IEEE754_INVALID_OPERATION);
-		return ieee754sp_nanxcpt(ieee754sp_indef());
-	}
+	unsigned int oldrm;
+	union ieee754sp y;
 
-	return x;
+	oldrm = ieee754_csr.rm;
+	ieee754_csr.rm = FPU_CSR_RD;
+	if (SPSIGN(x))
+		y = ieee754sp_sub(ieee754sp_zero(0), x);
+	else
+		y = ieee754sp_add(ieee754sp_zero(0), x);
+	ieee754_csr.rm = oldrm;
+	return y;
 }

^ permalink raw reply	[flat|nested] 62+ messages in thread

* [PATCH 47/48] MIPS: Respect the ISA level in FCSR handling
  2015-04-03 22:23 [PATCH 00/48] FPU and FP emulation clean-ups, fixes and feature updates Maciej W. Rozycki
                   ` (43 preceding siblings ...)
  2015-04-03 22:27 ` [PATCH 46/48] MIPS: math-emu: Make ABS.fmt and NEG.fmt arithmetic again Maciej W. Rozycki
@ 2015-04-03 22:27 ` Maciej W. Rozycki
  2015-04-07 12:54   ` Ralf Baechle
  2015-04-03 22:27 ` [PATCH 48/48] MIPS: Factor out FPU feature probing Maciej W. Rozycki
  2015-04-04 20:04 ` [PATCH 00/48] FPU and FP emulation clean-ups, fixes and feature updates Ralf Baechle
  46 siblings, 1 reply; 62+ messages in thread
From: Maciej W. Rozycki @ 2015-04-03 22:27 UTC (permalink / raw)
  To: Ralf Baechle; +Cc: linux-mips

Define the central place the default FCSR value is set from, initialised 
in `cpu_probe'.  Determine the FCSR mask applied to values written to 
the register with CTC1 in the full emulation mode and via ptrace(2), 
according to the ISA level of processor hardware or the writability of 
bits 31:18 if actual FPU hardware is used.

Software may rely on FCSR bits whose functions our emulator does not 
implement, so it should not allow them to be set or software may get 
confused.  For ptrace(2) it's just sanity.

Signed-off-by: Maciej W. Rozycki <macro@linux-mips.org>
---
linux-mips-emu-fcsr-isa.diff
Index: linux/arch/mips/include/asm/cpu-info.h
===================================================================
--- linux.orig/arch/mips/include/asm/cpu-info.h	2015-04-02 20:18:47.496475000 +0100
+++ linux/arch/mips/include/asm/cpu-info.h	2015-04-02 20:27:59.740240000 +0100
@@ -49,6 +49,8 @@ struct cpuinfo_mips {
 	unsigned int		udelay_val;
 	unsigned int		processor_id;
 	unsigned int		fpu_id;
+	unsigned int		fpu_csr31;
+	unsigned int		fpu_msk31;
 	unsigned int		msa_id;
 	unsigned int		cputype;
 	int			isa_level;
Index: linux/arch/mips/include/asm/elf.h
===================================================================
--- linux.orig/arch/mips/include/asm/elf.h	2015-04-02 20:18:47.497482000 +0100
+++ linux/arch/mips/include/asm/elf.h	2015-04-02 20:27:59.742251000 +0100
@@ -11,6 +11,9 @@
 #include <linux/fs.h>
 #include <uapi/linux/elf.h>
 
+#include <asm/cpu-info.h>
+#include <asm/current.h>
+
 /* ELF header e_flags defines. */
 /* MIPS architecture level. */
 #define EF_MIPS_ARCH_1		0x00000000	/* -mips1 code.	 */
@@ -297,6 +300,8 @@ do {									\
 	mips_set_personality_fp(state);					\
 									\
 	current->thread.abi = &mips_abi;				\
+									\
+	current->thread.fpu.fcr31 = current_cpu_data.fpu_csr31;		\
 } while (0)
 
 #endif /* CONFIG_32BIT */
@@ -356,6 +361,8 @@ do {									\
 	else								\
 		current->thread.abi = &mips_abi;			\
 									\
+	current->thread.fpu.fcr31 = current_cpu_data.fpu_csr31;		\
+									\
 	p = personality(current->personality);				\
 	if (p != PER_LINUX32 && p != PER_LINUX)				\
 		set_personality(PER_LINUX);				\
Index: linux/arch/mips/include/asm/fpu.h
===================================================================
--- linux.orig/arch/mips/include/asm/fpu.h	2015-04-02 20:18:47.499480000 +0100
+++ linux/arch/mips/include/asm/fpu.h	2015-04-02 20:27:59.745241000 +0100
@@ -14,6 +14,7 @@
 #include <linux/thread_info.h>
 #include <linux/bitops.h>
 
+#include <asm/current.h>
 #include <asm/mipsregs.h>
 #include <asm/cpu.h>
 #include <asm/cpu-features.h>
@@ -30,7 +31,7 @@
 struct sigcontext;
 struct sigcontext32;
 
-extern void _init_fpu(void);
+extern void _init_fpu(unsigned int);
 extern void _save_fp(struct task_struct *);
 extern void _restore_fp(struct task_struct *);
 
@@ -182,6 +183,7 @@ static inline void lose_fpu(int save)
 
 static inline int init_fpu(void)
 {
+	unsigned int fcr31 = current->thread.fpu.fcr31;
 	int ret = 0;
 
 	if (cpu_has_fpu) {
@@ -192,7 +194,7 @@ static inline int init_fpu(void)
 			return ret;
 
 		if (!cpu_has_fre) {
-			_init_fpu();
+			_init_fpu(fcr31);
 
 			return 0;
 		}
@@ -206,7 +208,7 @@ static inline int init_fpu(void)
 		config5 = clear_c0_config5(MIPS_CONF5_FRE);
 		enable_fpu_hazard();
 
-		_init_fpu();
+		_init_fpu(fcr31);
 
 		/* Restore FRE */
 		write_c0_config5(config5);
Index: linux/arch/mips/include/asm/fpu_emulator.h
===================================================================
--- linux.orig/arch/mips/include/asm/fpu_emulator.h	2015-04-02 20:27:58.453234000 +0100
+++ linux/arch/mips/include/asm/fpu_emulator.h	2015-04-02 20:27:59.747241000 +0100
@@ -87,8 +87,6 @@ static inline void fpu_emulator_init_fpu
 	struct task_struct *t = current;
 	int i;
 
-	t->thread.fpu.fcr31 = 0;
-
 	for (i = 0; i < 32; i++)
 		set_fpr64(&t->thread.fpu.fpr[i], 0, SIGNALLING_NAN);
 }
Index: linux/arch/mips/kernel/cpu-probe.c
===================================================================
--- linux.orig/arch/mips/kernel/cpu-probe.c	2015-04-02 20:27:58.890231000 +0100
+++ linux/arch/mips/kernel/cpu-probe.c	2015-04-02 20:27:59.750245000 +0100
@@ -33,6 +33,35 @@
 #include <asm/uaccess.h>
 
 /*
+ * Determine the FCSR mask for FPU hardware.
+ */
+static inline void cpu_set_fpu_fcsr_mask(struct cpuinfo_mips *c)
+{
+	unsigned long sr, mask, fcsr, fcsr0, fcsr1;
+
+	mask = FPU_CSR_ALL_X | FPU_CSR_ALL_E | FPU_CSR_ALL_S | FPU_CSR_RM;
+
+	sr = read_c0_status();
+	__enable_fpu(FPU_AS_IS);
+
+	fcsr = read_32bit_cp1_register(CP1_STATUS);
+
+	fcsr0 = fcsr & mask;
+	write_32bit_cp1_register(CP1_STATUS, fcsr0);
+	fcsr0 = read_32bit_cp1_register(CP1_STATUS);
+
+	fcsr1 = fcsr | ~mask;
+	write_32bit_cp1_register(CP1_STATUS, fcsr1);
+	fcsr1 = read_32bit_cp1_register(CP1_STATUS);
+
+	write_32bit_cp1_register(CP1_STATUS, fcsr);
+
+	write_c0_status(sr);
+
+	c->fpu_msk31 = ~(fcsr0 ^ fcsr1) & ~mask;
+}
+
+/*
  * Set the FIR feature flags for the FPU emulator.
  */
 static void cpu_set_nofpu_id(struct cpuinfo_mips *c)
@@ -50,11 +79,15 @@ static void cpu_set_nofpu_id(struct cpui
 	c->fpu_id = value;
 }
 
+/* Determined FPU emulator mask to use for the boot CPU with "nofpu".  */
+static unsigned int mips_nofpu_msk31;
+
 static int mips_fpu_disabled;
 
 static int __init fpu_disable(char *s)
 {
 	boot_cpu_data.options &= ~MIPS_CPU_FPU;
+	boot_cpu_data.fpu_msk31 = mips_nofpu_msk31;
 	cpu_set_nofpu_id(&boot_cpu_data);
 	mips_fpu_disabled = 1;
 
@@ -595,6 +628,7 @@ static inline void cpu_probe_legacy(stru
 	case PRID_IMP_R2000:
 		c->cputype = CPU_R2000;
 		__cpu_name[cpu] = "R2000";
+		c->fpu_msk31 |= FPU_CSR_CONDX | FPU_CSR_FS;
 		c->options = MIPS_CPU_TLB | MIPS_CPU_3K_CACHE |
 			     MIPS_CPU_NOFPUEX;
 		if (__cpu_has_fpu())
@@ -614,6 +648,7 @@ static inline void cpu_probe_legacy(stru
 			c->cputype = CPU_R3000;
 			__cpu_name[cpu] = "R3000";
 		}
+		c->fpu_msk31 |= FPU_CSR_CONDX | FPU_CSR_FS;
 		c->options = MIPS_CPU_TLB | MIPS_CPU_3K_CACHE |
 			     MIPS_CPU_NOFPUEX;
 		if (__cpu_has_fpu())
@@ -662,6 +697,7 @@ static inline void cpu_probe_legacy(stru
 		}
 
 		set_isa(c, MIPS_CPU_ISA_III);
+		c->fpu_msk31 |= FPU_CSR_CONDX;
 		c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR |
 			     MIPS_CPU_WATCH | MIPS_CPU_VCE |
 			     MIPS_CPU_LLSC;
@@ -669,6 +705,7 @@ static inline void cpu_probe_legacy(stru
 		break;
 	case PRID_IMP_VR41XX:
 		set_isa(c, MIPS_CPU_ISA_III);
+		c->fpu_msk31 |= FPU_CSR_CONDX;
 		c->options = R4K_OPTS;
 		c->tlbsize = 32;
 		switch (c->processor_id & 0xf0) {
@@ -710,6 +747,7 @@ static inline void cpu_probe_legacy(stru
 		c->cputype = CPU_R4300;
 		__cpu_name[cpu] = "R4300";
 		set_isa(c, MIPS_CPU_ISA_III);
+		c->fpu_msk31 |= FPU_CSR_CONDX;
 		c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR |
 			     MIPS_CPU_LLSC;
 		c->tlbsize = 32;
@@ -718,6 +756,7 @@ static inline void cpu_probe_legacy(stru
 		c->cputype = CPU_R4600;
 		__cpu_name[cpu] = "R4600";
 		set_isa(c, MIPS_CPU_ISA_III);
+		c->fpu_msk31 |= FPU_CSR_CONDX;
 		c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR |
 			     MIPS_CPU_LLSC;
 		c->tlbsize = 48;
@@ -733,11 +772,13 @@ static inline void cpu_probe_legacy(stru
 		c->cputype = CPU_R4650;
 		__cpu_name[cpu] = "R4650";
 		set_isa(c, MIPS_CPU_ISA_III);
+		c->fpu_msk31 |= FPU_CSR_CONDX;
 		c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_LLSC;
 		c->tlbsize = 48;
 		break;
 	#endif
 	case PRID_IMP_TX39:
+		c->fpu_msk31 |= FPU_CSR_CONDX | FPU_CSR_FS;
 		c->options = MIPS_CPU_TLB | MIPS_CPU_TX39_CACHE;
 
 		if ((c->processor_id & 0xf0) == (PRID_REV_TX3927 & 0xf0)) {
@@ -763,6 +804,7 @@ static inline void cpu_probe_legacy(stru
 		c->cputype = CPU_R4700;
 		__cpu_name[cpu] = "R4700";
 		set_isa(c, MIPS_CPU_ISA_III);
+		c->fpu_msk31 |= FPU_CSR_CONDX;
 		c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR |
 			     MIPS_CPU_LLSC;
 		c->tlbsize = 48;
@@ -771,6 +813,7 @@ static inline void cpu_probe_legacy(stru
 		c->cputype = CPU_TX49XX;
 		__cpu_name[cpu] = "R49XX";
 		set_isa(c, MIPS_CPU_ISA_III);
+		c->fpu_msk31 |= FPU_CSR_CONDX;
 		c->options = R4K_OPTS | MIPS_CPU_LLSC;
 		if (!(c->processor_id & 0x08))
 			c->options |= MIPS_CPU_FPU | MIPS_CPU_32FPR;
@@ -812,6 +855,7 @@ static inline void cpu_probe_legacy(stru
 		c->cputype = CPU_R6000;
 		__cpu_name[cpu] = "R6000";
 		set_isa(c, MIPS_CPU_ISA_II);
+		c->fpu_msk31 |= FPU_CSR_CONDX | FPU_CSR_FS;
 		c->options = MIPS_CPU_TLB | MIPS_CPU_FPU |
 			     MIPS_CPU_LLSC;
 		c->tlbsize = 32;
@@ -820,6 +864,7 @@ static inline void cpu_probe_legacy(stru
 		c->cputype = CPU_R6000A;
 		__cpu_name[cpu] = "R6000A";
 		set_isa(c, MIPS_CPU_ISA_II);
+		c->fpu_msk31 |= FPU_CSR_CONDX | FPU_CSR_FS;
 		c->options = MIPS_CPU_TLB | MIPS_CPU_FPU |
 			     MIPS_CPU_LLSC;
 		c->tlbsize = 32;
@@ -886,12 +931,14 @@ static inline void cpu_probe_legacy(stru
 			__cpu_name[cpu] = "ICT Loongson-2";
 			set_elf_platform(cpu, "loongson2e");
 			set_isa(c, MIPS_CPU_ISA_III);
+			c->fpu_msk31 |= FPU_CSR_CONDX;
 			break;
 		case PRID_REV_LOONGSON2F:
 			c->cputype = CPU_LOONGSON2;
 			__cpu_name[cpu] = "ICT Loongson-2";
 			set_elf_platform(cpu, "loongson2f");
 			set_isa(c, MIPS_CPU_ISA_III);
+			c->fpu_msk31 |= FPU_CSR_CONDX;
 			break;
 		case PRID_REV_LOONGSON3A:
 			c->cputype = CPU_LOONGSON3;
@@ -1328,6 +1375,9 @@ void cpu_probe(void)
 	c->cputype	= CPU_UNKNOWN;
 	c->writecombine = _CACHE_UNCACHED;
 
+	c->fpu_csr31	= FPU_CSR_RN;
+	c->fpu_msk31	= FPU_CSR_RSVD | FPU_CSR_ABS2008 | FPU_CSR_NAN2008;
+
 	c->processor_id = read_c0_prid();
 	switch (c->processor_id & PRID_COMP_MASK) {
 	case PRID_COMP_LEGACY:
@@ -1386,6 +1436,7 @@ void cpu_probe(void)
 
 	if (c->options & MIPS_CPU_FPU) {
 		c->fpu_id = cpu_get_fpu_id();
+		mips_nofpu_msk31 = c->fpu_msk31;
 
 		if (c->isa_level & (MIPS_CPU_ISA_M32R1 | MIPS_CPU_ISA_M64R1 |
 				    MIPS_CPU_ISA_M32R2 | MIPS_CPU_ISA_M64R2 |
@@ -1395,6 +1446,8 @@ void cpu_probe(void)
 			if (c->fpu_id & MIPS_FPIR_FREP)
 				c->options |= MIPS_CPU_FRE;
 		}
+
+		cpu_set_fpu_fcsr_mask(c);
 	} else
 		cpu_set_nofpu_id(c);
 
Index: linux/arch/mips/kernel/ptrace.c
===================================================================
--- linux.orig/arch/mips/kernel/ptrace.c	2015-04-02 20:18:47.505476000 +0100
+++ linux/arch/mips/kernel/ptrace.c	2015-04-02 20:27:59.753242000 +0100
@@ -32,6 +32,7 @@
 
 #include <asm/byteorder.h>
 #include <asm/cpu.h>
+#include <asm/cpu-info.h>
 #include <asm/dsp.h>
 #include <asm/fpu.h>
 #include <asm/mipsregs.h>
@@ -137,6 +138,9 @@ int ptrace_setfpregs(struct task_struct 
 {
 	union fpureg *fregs;
 	u64 fpr_val;
+	u32 fcr31;
+	u32 value;
+	u32 mask;
 	int i;
 
 	if (!access_ok(VERIFY_READ, data, 33 * 8))
@@ -149,8 +153,10 @@ int ptrace_setfpregs(struct task_struct 
 		set_fpr64(&fregs[i], 0, fpr_val);
 	}
 
-	__get_user(child->thread.fpu.fcr31, data + 64);
-	child->thread.fpu.fcr31 &= ~FPU_CSR_ALL_X;
+	__get_user(value, data + 64);
+	fcr31 = child->thread.fpu.fcr31;
+	mask = current_cpu_data.fpu_msk31;
+	child->thread.fpu.fcr31 = (value & ~mask) | (fcr31 & mask);
 
 	/* FIR may not be written.  */
 
Index: linux/arch/mips/kernel/r2300_switch.S
===================================================================
--- linux.orig/arch/mips/kernel/r2300_switch.S	2015-04-02 20:18:47.506481000 +0100
+++ linux/arch/mips/kernel/r2300_switch.S	2015-04-02 20:27:59.755248000 +0100
@@ -115,11 +115,9 @@ LEAF(_restore_fp)
  * the property that no matter whether considered as single or as double
  * precision represents signaling NANS.
  *
- * We initialize fcr31 to rounding to nearest, no exceptions.
+ * The value to initialize fcr31 to comes in $a0.
  */
 
-#define FPU_DEFAULT  0x00000000
-
 	.set push
 	SET_HARDFLOAT
 
@@ -129,8 +127,7 @@ LEAF(_init_fpu)
 	or	t0, t1
 	mtc0	t0, CP0_STATUS
 
-	li	t1, FPU_DEFAULT
-	ctc1	t1, fcr31
+	ctc1	a0, fcr31
 
 	li	t0, -1
 
Index: linux/arch/mips/kernel/r4k_switch.S
===================================================================
--- linux.orig/arch/mips/kernel/r4k_switch.S	2015-04-02 20:18:47.508482000 +0100
+++ linux/arch/mips/kernel/r4k_switch.S	2015-04-02 20:27:59.758240000 +0100
@@ -165,11 +165,9 @@ LEAF(_init_msa_upper)
  * the property that no matter whether considered as single or as double
  * precision represents signaling NANS.
  *
- * We initialize fcr31 to rounding to nearest, no exceptions.
+ * The value to initialize fcr31 to comes in $a0.
  */
 
-#define FPU_DEFAULT  0x00000000
-
 	.set push
 	SET_HARDFLOAT
 
@@ -180,8 +178,7 @@ LEAF(_init_fpu)
 	mtc0	t0, CP0_STATUS
 	enable_fpu_hazard
 
-	li	t1, FPU_DEFAULT
-	ctc1	t1, fcr31
+	ctc1	a0, fcr31
 
 	li	t1, -1				# SNaN
 
Index: linux/arch/mips/loongson/loongson-3/cop2-ex.c
===================================================================
--- linux.orig/arch/mips/loongson/loongson-3/cop2-ex.c	2015-04-02 20:18:47.515499000 +0100
+++ linux/arch/mips/loongson/loongson-3/cop2-ex.c	2015-04-02 20:27:59.767246000 +0100
@@ -43,7 +43,7 @@ static int loongson_cu2_call(struct noti
 		if (!fpu_owned) {
 			set_thread_flag(TIF_USEDFPU);
 			if (!used_math()) {
-				_init_fpu();
+				_init_fpu(current->thread.fpu.fcr31);
 				set_used_math();
 			} else
 				_restore_fp(current);
Index: linux/arch/mips/math-emu/cp1emu.c
===================================================================
--- linux.orig/arch/mips/math-emu/cp1emu.c	2015-04-02 20:27:59.304242000 +0100
+++ linux/arch/mips/math-emu/cp1emu.c	2015-04-02 20:27:59.771244000 +0100
@@ -908,6 +908,7 @@ static inline void cop1_ctc(struct pt_re
 {
 	u32 fcr31 = ctx->fcr31;
 	u32 value;
+	u32 mask;
 
 	if (MIPSInst_RT(ir) == 0)
 		value = 0;
@@ -919,9 +920,9 @@ static inline void cop1_ctc(struct pt_re
 		pr_debug("%p gpr[%d]->csr=%08x\n",
 			 (void *)xcp->cp0_epc, MIPSInst_RT(ir), value);
 
-		/* Don't write unsupported bits.  */
-		fcr31 = value &
-			~(FPU_CSR_RSVD | FPU_CSR_ABS2008 | FPU_CSR_NAN2008);
+		/* Preserve read-only bits.  */
+		mask = current_cpu_data.fpu_msk31;
+		fcr31 = (value & ~mask) | (fcr31 & mask);
 		break;
 
 	case FPCREG_FENR:

^ permalink raw reply	[flat|nested] 62+ messages in thread

* [PATCH 48/48] MIPS: Factor out FPU feature probing
  2015-04-03 22:23 [PATCH 00/48] FPU and FP emulation clean-ups, fixes and feature updates Maciej W. Rozycki
                   ` (44 preceding siblings ...)
  2015-04-03 22:27 ` [PATCH 47/48] MIPS: Respect the ISA level in FCSR handling Maciej W. Rozycki
@ 2015-04-03 22:27 ` Maciej W. Rozycki
  2015-04-04 20:04 ` [PATCH 00/48] FPU and FP emulation clean-ups, fixes and feature updates Ralf Baechle
  46 siblings, 0 replies; 62+ messages in thread
From: Maciej W. Rozycki @ 2015-04-03 22:27 UTC (permalink / raw)
  To: Ralf Baechle; +Cc: linux-mips

Factor out FPU feature probing, mainly to remove code duplication from 
`fpu_disable'.  No functional change although shuffle some code to avoid 
forward references.

Signed-off-by: Maciej W. Rozycki <macro@linux-mips.org>
---
linux-mips-fpu-probe.diff
Index: linux/arch/mips/kernel/cpu-probe.c
===================================================================
--- linux.orig/arch/mips/kernel/cpu-probe.c	2015-04-02 20:27:59.750245000 +0100
+++ linux/arch/mips/kernel/cpu-probe.c	2015-04-02 20:28:00.091243000 +0100
@@ -33,6 +33,41 @@
 #include <asm/uaccess.h>
 
 /*
+ * Get the FPU Implementation/Revision.
+ */
+static inline unsigned long cpu_get_fpu_id(void)
+{
+	unsigned long tmp, fpu_id;
+
+	tmp = read_c0_status();
+	__enable_fpu(FPU_AS_IS);
+	fpu_id = read_32bit_cp1_register(CP1_REVISION);
+	write_c0_status(tmp);
+	return fpu_id;
+}
+
+/*
+ * Check if the CPU has an external FPU.
+ */
+static inline int __cpu_has_fpu(void)
+{
+	return (cpu_get_fpu_id() & FPIR_IMP_MASK) != FPIR_IMP_NONE;
+}
+
+static inline unsigned long cpu_get_msa_id(void)
+{
+	unsigned long status, msa_id;
+
+	status = read_c0_status();
+	__enable_fpu(FPU_64BIT);
+	enable_msa();
+	msa_id = read_msa_ir();
+	disable_msa();
+	write_c0_status(status);
+	return msa_id;
+}
+
+/*
  * Determine the FCSR mask for FPU hardware.
  */
 static inline void cpu_set_fpu_fcsr_mask(struct cpuinfo_mips *c)
@@ -82,13 +117,42 @@ static void cpu_set_nofpu_id(struct cpui
 /* Determined FPU emulator mask to use for the boot CPU with "nofpu".  */
 static unsigned int mips_nofpu_msk31;
 
+/*
+ * Set options for FPU hardware.
+ */
+static void cpu_set_fpu_opts(struct cpuinfo_mips *c)
+{
+	c->fpu_id = cpu_get_fpu_id();
+	mips_nofpu_msk31 = c->fpu_msk31;
+
+	if (c->isa_level & (MIPS_CPU_ISA_M32R1 | MIPS_CPU_ISA_M64R1 |
+			    MIPS_CPU_ISA_M32R2 | MIPS_CPU_ISA_M64R2 |
+			    MIPS_CPU_ISA_M32R6 | MIPS_CPU_ISA_M64R6)) {
+		if (c->fpu_id & MIPS_FPIR_3D)
+			c->ases |= MIPS_ASE_MIPS3D;
+		if (c->fpu_id & MIPS_FPIR_FREP)
+			c->options |= MIPS_CPU_FRE;
+	}
+
+	cpu_set_fpu_fcsr_mask(c);
+}
+
+/*
+ * Set options for the FPU emulator.
+ */
+static void cpu_set_nofpu_opts(struct cpuinfo_mips *c)
+{
+	c->options &= ~MIPS_CPU_FPU;
+	c->fpu_msk31 = mips_nofpu_msk31;
+
+	cpu_set_nofpu_id(c);
+}
+
 static int mips_fpu_disabled;
 
 static int __init fpu_disable(char *s)
 {
-	boot_cpu_data.options &= ~MIPS_CPU_FPU;
-	boot_cpu_data.fpu_msk31 = mips_nofpu_msk31;
-	cpu_set_nofpu_id(&boot_cpu_data);
+	cpu_set_nofpu_opts(&boot_cpu_data);
 	mips_fpu_disabled = 1;
 
 	return 1;
@@ -231,41 +295,6 @@ static inline void set_elf_platform(int 
 		__elf_platform = plat;
 }
 
-/*
- * Get the FPU Implementation/Revision.
- */
-static inline unsigned long cpu_get_fpu_id(void)
-{
-	unsigned long tmp, fpu_id;
-
-	tmp = read_c0_status();
-	__enable_fpu(FPU_AS_IS);
-	fpu_id = read_32bit_cp1_register(CP1_REVISION);
-	write_c0_status(tmp);
-	return fpu_id;
-}
-
-/*
- * Check if the CPU has an external FPU.
- */
-static inline int __cpu_has_fpu(void)
-{
-	return (cpu_get_fpu_id() & FPIR_IMP_MASK) != FPIR_IMP_NONE;
-}
-
-static inline unsigned long cpu_get_msa_id(void)
-{
-	unsigned long status, msa_id;
-
-	status = read_c0_status();
-	__enable_fpu(FPU_64BIT);
-	enable_msa();
-	msa_id = read_msa_ir();
-	disable_msa();
-	write_c0_status(status);
-	return msa_id;
-}
-
 static inline void cpu_probe_vmbits(struct cpuinfo_mips *c)
 {
 #ifdef __NEED_VMBITS_PROBE
@@ -1434,22 +1463,10 @@ void cpu_probe(void)
 			       ~(1 << MIPS_PWCTL_PWEN_SHIFT));
 	}
 
-	if (c->options & MIPS_CPU_FPU) {
-		c->fpu_id = cpu_get_fpu_id();
-		mips_nofpu_msk31 = c->fpu_msk31;
-
-		if (c->isa_level & (MIPS_CPU_ISA_M32R1 | MIPS_CPU_ISA_M64R1 |
-				    MIPS_CPU_ISA_M32R2 | MIPS_CPU_ISA_M64R2 |
-				    MIPS_CPU_ISA_M32R6 | MIPS_CPU_ISA_M64R6)) {
-			if (c->fpu_id & MIPS_FPIR_3D)
-				c->ases |= MIPS_ASE_MIPS3D;
-			if (c->fpu_id & MIPS_FPIR_FREP)
-				c->options |= MIPS_CPU_FRE;
-		}
-
-		cpu_set_fpu_fcsr_mask(c);
-	} else
-		cpu_set_nofpu_id(c);
+	if (c->options & MIPS_CPU_FPU)
+		cpu_set_fpu_opts(c);
+	else
+		cpu_set_nofpu_opts(c);
 
 	if (cpu_has_mips_r2_r6) {
 		c->srsets = ((read_c0_srsctl() >> 26) & 0x0f) + 1;

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH 43/48] MIPS: math-emu: Set FIR feature flags for full emulation
  2015-04-03 22:27 ` [PATCH 43/48] MIPS: math-emu: Set FIR feature flags for full emulation Maciej W. Rozycki
@ 2015-04-03 23:18   ` Sergei Shtylyov
  0 siblings, 0 replies; 62+ messages in thread
From: Sergei Shtylyov @ 2015-04-03 23:18 UTC (permalink / raw)
  To: Maciej W. Rozycki, Ralf Baechle; +Cc: linux-mips

Hello.

On 04/04/2015 01:27 AM, Maciej W. Rozycki wrote:

> Implement FIR feature flags in the FPU emulator according to features
> supported and architecture level requirements.  The W, L and F64 bits
> have only been added at level #2 even though the features they refer to
> were also included with the MIPS64r1 ISA and the W fixed-point format
> also with the MIPS32r1 ISA.

> This is only relevant for the full emulation mode and the emulated CFC1
> instruction as well as ptrace(2) accesses.

> Signed-off-by: Maciej W. Rozycki <macro@linux-mips.org>
> ---
> linux-mips-emu-fir.diff
> Index: linux/arch/mips/kernel/cpu-probe.c
> ===================================================================
> --- linux.orig/arch/mips/kernel/cpu-probe.c	2015-04-02 20:27:58.700229000 +0100
> +++ linux/arch/mips/kernel/cpu-probe.c	2015-04-02 20:27:58.890231000 +0100
[...]
> @@ -31,11 +32,30 @@
>   #include <asm/spram.h>
>   #include <asm/uaccess.h>
>
> +/*
> + * Set the FIR feature flags for the FPU emulator.
> + */
> +static void cpu_set_nofpu_id(struct cpuinfo_mips *c)
> +{
> +	u32 value;
> +
> +	value = 0;

    Why not just do it in an initializer?

> +	if (c->isa_level & (MIPS_CPU_ISA_M32R1 | MIPS_CPU_ISA_M64R1 |
> +			    MIPS_CPU_ISA_M32R2 | MIPS_CPU_ISA_M64R2 |
> +			    MIPS_CPU_ISA_M32R6 | MIPS_CPU_ISA_M64R6))
> +		value |= MIPS_FPIR_D | MIPS_FPIR_S;
> +	if (c->isa_level & (MIPS_CPU_ISA_M32R2 | MIPS_CPU_ISA_M64R2 |
> +			    MIPS_CPU_ISA_M32R6 | MIPS_CPU_ISA_M64R6))
> +		value |= MIPS_FPIR_F64 | MIPS_FPIR_L | MIPS_FPIR_W;
> +	c->fpu_id = value;
> +}
> +
>   static int mips_fpu_disabled;
>
>   static int __init fpu_disable(char *s)
>   {
> -	cpu_data[0].options &= ~MIPS_CPU_FPU;
> +	boot_cpu_data.options &= ~MIPS_CPU_FPU;
> +	cpu_set_nofpu_id(&boot_cpu_data);
>   	mips_fpu_disabled = 1;
>
>   	return 1;
> @@ -1375,7 +1395,8 @@ void cpu_probe(void)
>   			if (c->fpu_id & MIPS_FPIR_FREP)
>   				c->options |= MIPS_CPU_FRE;
>   		}
> -	}
> +	} else
> +		cpu_set_nofpu_id(c);

    CodingStyle: need {} in the *else* branch as well.

[...]

WBR, Sergei

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH 29/48] MIPS: math-emu: Make NaN classifiers static
  2015-04-03 22:25 ` [PATCH 29/48] MIPS: math-emu: Make NaN classifiers static Maciej W. Rozycki
@ 2015-04-03 23:22   ` Sergei Shtylyov
  0 siblings, 0 replies; 62+ messages in thread
From: Sergei Shtylyov @ 2015-04-03 23:22 UTC (permalink / raw)
  To: Maciej W. Rozycki, Ralf Baechle; +Cc: linux-mips

Hello.

On 04/04/2015 01:25 AM, Maciej W. Rozycki wrote:

> The `ieee754sp_isnan' and `ieee754dp_isnan' NaN classifiers are now no
> longer externally referred, remove their header prototypes and make them
> local to the two only respective places still making use of them.

> Signed-off-by: Maciej W. Rozycki <macro@linux-mips.org>
> ---
> linux-mips-emu-isnan.diff
> Index: linux/arch/mips/math-emu/ieee754dp.c
> ===================================================================
> --- linux.orig/arch/mips/math-emu/ieee754dp.c	2015-04-02 20:27:55.587207000 +0100
> +++ linux/arch/mips/math-emu/ieee754dp.c	2015-04-02 20:27:56.032207000 +0100
> @@ -30,7 +30,7 @@ int ieee754dp_class(union ieee754dp x)
>   	return xc;
>   }
>
> -int ieee754dp_isnan(union ieee754dp x)
> +static inline int ieee754dp_isnan(union ieee754dp x)

    I think the current trend is to let gcc figure out whether to inline or not.

[...]

WBR, Sergei

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH 18/48] MIPS: math-emu: Factor out CFC1/CTC1 emulation
  2015-04-03 22:25 ` [PATCH 18/48] MIPS: math-emu: Factor out CFC1/CTC1 emulation Maciej W. Rozycki
@ 2015-04-03 23:33   ` Sergei Shtylyov
  2015-04-04  0:07     ` Maciej W. Rozycki
  0 siblings, 1 reply; 62+ messages in thread
From: Sergei Shtylyov @ 2015-04-03 23:33 UTC (permalink / raw)
  To: Maciej W. Rozycki, Ralf Baechle; +Cc: linux-mips

Hello.

On 04/04/2015 01:25 AM, Maciej W. Rozycki wrote:

> Move CFC1/CTC1 emulation code to separate functions to avoid excessive
> indentation in forthcoming changes.  Adjust formatting in a minor way
> and remove extraneous round brackets.

> Signed-off-by: Maciej W. Rozycki <macro@linux-mips.org>
> ---
> linux-mips-emu-cxc.diff
> Index: linux/arch/mips/math-emu/cp1emu.c
> ===================================================================
> --- linux.orig/arch/mips/math-emu/cp1emu.c	2015-04-02 20:27:54.099185000 +0100
> +++ linux/arch/mips/math-emu/cp1emu.c	2015-04-02 20:27:54.459192000 +0100
> @@ -840,6 +840,52 @@ do {									\
>   #define DPTOREG(dp, x)	DITOREG((dp).bits, x)
>
>   /*
> + * Emulate a CFC1 instruction.
> + */
> +static inline void cop1_cfc(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
> +			    mips_instruction ir)
> +{
> +	u32 value;
> +
> +	if (MIPSInst_RD(ir) == FPCREG_CSR) {
> +		value = ctx->fcr31;
> +		pr_debug("%p gpr[%d]<-csr=%08x\n",
> +			 (void *)xcp->cp0_epc,
> +			 MIPSInst_RT(ir), value);
> +	} else if (MIPSInst_RD(ir) == FPCREG_RID)
> +		value = 0;
> +	else
> +		value = 0;

    CodingStyle: all arms of the *if* statement shouyld have {} if at leats 
one has them.

> +	if (MIPSInst_RT(ir))
> +		xcp->regs[MIPSInst_RT(ir)] = value;
> +}
> +
> +/*
> + * Emulate a CTC1 instruction.
> + */
> +static inline void cop1_ctc(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
> +			    mips_instruction ir)
> +{
> +	u32 value;
> +
> +	if (MIPSInst_RT(ir) == 0)
> +		value = 0;
> +	else
> +		value = xcp->regs[MIPSInst_RT(ir)];
> +
> +	/* we only have one writable control reg
> +	 */

    This comment would fit on a single line.

[...]

WBR, Sergei

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH 18/48] MIPS: math-emu: Factor out CFC1/CTC1 emulation
  2015-04-03 23:33   ` Sergei Shtylyov
@ 2015-04-04  0:07     ` Maciej W. Rozycki
  0 siblings, 0 replies; 62+ messages in thread
From: Maciej W. Rozycki @ 2015-04-04  0:07 UTC (permalink / raw)
  To: Sergei Shtylyov; +Cc: Ralf Baechle, linux-mips

On Sat, 4 Apr 2015, Sergei Shtylyov wrote:

> > +	if (MIPSInst_RD(ir) == FPCREG_CSR) {
> > +		value = ctx->fcr31;
> > +		pr_debug("%p gpr[%d]<-csr=%08x\n",
> > +			 (void *)xcp->cp0_epc,
> > +			 MIPSInst_RT(ir), value);
> > +	} else if (MIPSInst_RD(ir) == FPCREG_RID)
> > +		value = 0;
> > +	else
> > +		value = 0;
> 
>    CodingStyle: all arms of the *if* statement shouyld have {} if at leats one
> has them.
> 
> > +	if (MIPSInst_RT(ir))
> > +		xcp->regs[MIPSInst_RT(ir)] = value;
> > +}
> > +
> > +/*
> > + * Emulate a CTC1 instruction.
> > + */
> > +static inline void cop1_ctc(struct pt_regs *xcp, struct mips_fpu_struct
> > *ctx,
> > +			    mips_instruction ir)
> > +{
> > +	u32 value;
> > +
> > +	if (MIPSInst_RT(ir) == 0)
> > +		value = 0;
> > +	else
> > +		value = xcp->regs[MIPSInst_RT(ir)];
> > +
> > +	/* we only have one writable control reg
> > +	 */
> 
>    This comment would fit on a single line.

 Thanks for your comments.

 These patches move lots of preexisting code around, in some cases copying 
preexiting problems.  These problems are addressed as code is updated by 
later changes, so please have a look there too before pointing out issues.  
If I missed anything and a problem remains in code being poked at after 
all the changes have been applied, then please do let me know, I'll 
correct it.

 Thanks for your assistance with keeping our code clean!

  Maciej

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH 00/48] FPU and FP emulation clean-ups, fixes and feature updates
  2015-04-03 22:23 [PATCH 00/48] FPU and FP emulation clean-ups, fixes and feature updates Maciej W. Rozycki
                   ` (45 preceding siblings ...)
  2015-04-03 22:27 ` [PATCH 48/48] MIPS: Factor out FPU feature probing Maciej W. Rozycki
@ 2015-04-04 20:04 ` Ralf Baechle
  2015-04-04 20:55   ` Maciej W. Rozycki
  46 siblings, 1 reply; 62+ messages in thread
From: Ralf Baechle @ 2015-04-04 20:04 UTC (permalink / raw)
  To: Maciej W. Rozycki; +Cc: linux-mips

On Fri, Apr 03, 2015 at 11:23:29PM +0100, Maciej W. Rozycki wrote:

>  These are fixes to address code structuring and coding style problems 
> and then bug fixes I discovered in the course of implementing an 
> upcoming FPU feature.  There are some minor feature updates too.  They 
> are related to one another to a various extent, sometimes very loosely, 
> but I decided to keep them as a series because there is a lot of 
> syntactical overlap, as changes are made in steps, one issue at a time.  
> Keeping them in order guarantees that they apply on top of one another.
> 
>  Clean-ups come first as they should be completely uncontroversial, 
> followed by restructuring, bug fixes and new features.

It would have been nice if the bug fixes or at least those relevant to
4.0 and older were at the beginning to reduce issue when applying them
to the 4.0-fixes and possibly -stable branches.

I applied your patches on top of my working branch and ran into a number
of conflicts.  Will push the result out as soon as I'm done with the
conflict resolution.

Thanks!

  Ralf

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH 00/48] FPU and FP emulation clean-ups, fixes and feature updates
  2015-04-04 20:04 ` [PATCH 00/48] FPU and FP emulation clean-ups, fixes and feature updates Ralf Baechle
@ 2015-04-04 20:55   ` Maciej W. Rozycki
  2015-04-04 21:57     ` Ralf Baechle
  0 siblings, 1 reply; 62+ messages in thread
From: Maciej W. Rozycki @ 2015-04-04 20:55 UTC (permalink / raw)
  To: Ralf Baechle; +Cc: linux-mips

On Sat, 4 Apr 2015, Ralf Baechle wrote:

> >  Clean-ups come first as they should be completely uncontroversial, 
> > followed by restructuring, bug fixes and new features.
> 
> It would have been nice if the bug fixes or at least those relevant to
> 4.0 and older were at the beginning to reduce issue when applying them
> to the 4.0-fixes and possibly -stable branches.

 Good point, I will keep it in mind in the future.  I think there's 
actually little if any overlap here though, you should be able to ignore 
comment and formatting changes when doing any backports and the rest 
should just apply right away.

 I can send you a pre-r6 version of the relevant patches too if that would 
help -- I think there are 3 or 4 that I had to rework while rebasing from 
3.19 to 4.0.

> I applied your patches on top of my working branch and ran into a number
> of conflicts.  Will push the result out as soon as I'm done with the
> conflict resolution.

 Great, thanks!

 Is there a better branch than master of ralf/linux.git to base patches 
submitted against so as to save you from the need to sort out conflicts?  
Let me know if you need help with any unobvious 3-way merge too.

  Maciej

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH 00/48] FPU and FP emulation clean-ups, fixes and feature updates
  2015-04-04 20:55   ` Maciej W. Rozycki
@ 2015-04-04 21:57     ` Ralf Baechle
  0 siblings, 0 replies; 62+ messages in thread
From: Ralf Baechle @ 2015-04-04 21:57 UTC (permalink / raw)
  To: Maciej W. Rozycki; +Cc: linux-mips

On Sat, Apr 04, 2015 at 09:55:09PM +0100, Maciej W. Rozycki wrote:

>  Is there a better branch than master of ralf/linux.git to base patches 
> submitted against so as to save you from the need to sort out conflicts?  
> Let me know if you need help with any unobvious 3-way merge too.

That's a little harder this time.  Normally the top of upstream-sfr's
mips-for-linux-next is a good choice for the base but this time I have
another branch, 4.1-fp in upstream-sfr and I want to keep the merge
commit pulling this branch and the 4.0-fixes branch on top which lands
me in a bunch of conflicts.

The conflicts are in

    arch/mips/include/asm/asmmacro-32.h
    arch/mips/kernel/traps.c

I've tested a number of defconfigs and I'm pushing a new upstream-sfr
now.  I'd appreciate if you could test/review the result.

  Ralf

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH 47/48] MIPS: Respect the ISA level in FCSR handling
  2015-04-03 22:27 ` [PATCH 47/48] MIPS: Respect the ISA level in FCSR handling Maciej W. Rozycki
@ 2015-04-07 12:54   ` Ralf Baechle
  2015-04-07 21:13     ` Maciej W. Rozycki
  0 siblings, 1 reply; 62+ messages in thread
From: Ralf Baechle @ 2015-04-07 12:54 UTC (permalink / raw)
  To: Maciej W. Rozycki; +Cc: linux-mips

On Fri, Apr 03, 2015 at 11:27:48PM +0100, Maciej W. Rozycki wrote:
> Date:   Fri, 3 Apr 2015 23:27:48 +0100 (BST)

> Index: linux/arch/mips/include/asm/fpu.h
> ===================================================================
> --- linux.orig/arch/mips/include/asm/fpu.h	2015-04-02 20:18:47.499480000 +0100
> +++ linux/arch/mips/include/asm/fpu.h	2015-04-02 20:27:59.745241000 +0100
> @@ -14,6 +14,7 @@
>  #include <linux/thread_info.h>
>  #include <linux/bitops.h>
>  
> +#include <asm/current.h>
>  #include <asm/mipsregs.h>
>  #include <asm/cpu.h>
>  #include <asm/cpu-features.h>

This is adding a 2nd inclusion of <asm/current.h>.  Will fix that.

  Ralf

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH 46/48] MIPS: math-emu: Make ABS.fmt and NEG.fmt arithmetic again
  2015-04-03 22:27 ` [PATCH 46/48] MIPS: math-emu: Make ABS.fmt and NEG.fmt arithmetic again Maciej W. Rozycki
@ 2015-04-07 15:24   ` Maciej W. Rozycki
  2015-04-07 17:31     ` Ralf Baechle
  0 siblings, 1 reply; 62+ messages in thread
From: Maciej W. Rozycki @ 2015-04-07 15:24 UTC (permalink / raw)
  To: Ralf Baechle; +Cc: linux-mips

On Fri, 3 Apr 2015, Maciej W. Rozycki wrote:

> The ABS.fmt and NEG.fmt instructions have been specified as arithmetic 
> in the MIPS architecture, which in particular implies handling NaN data 
> in the usual way with qNaN bit patterns propagated unchanged and sNaN 
> bit patterns signalling the usual IEEE 754 Invalid Operation exception 
> and quieted by default.
> 
> A series of changes applied over time to our implementation:
> 
> c5033d78 [MIPS] ieee754[sd]p_neg workaround
> cea2be44 MIPS: Fix abs.[sd] and neg.[sd] emulation for NaN operands
> 
> has led to the current situation where the sign bit is updated according 
> to the operation requested even for NaN inputs.  This is according to 
> these commits a workaround so that broken binaries produced by GCC 
> disregarding the properties of these instructions have a chance to work.
> 
> For sNaN inputs this remains within IEEE Std 754 as the standard leaves 
> the choice of output qNaN bit patterns produced under the default 
> Invalid Operation exception handling for individual sNaN input bit 
> patterns to implementer's discretion, even though it still recommends as 
> much NaN input information to be preserved in NaN outputs.
> 
> For qNaN inputs however it violates the standard as it requires a qNaN 
> input bit patterns to propagate unchanged to output.
> 
> This is also unlike real MIPS FPU hardware behaves where sNaN and/or 
> qNaN processing has been fully implemented with no Unimplemented 
> Operation exception signalled.  Such hardware propagates any input qNaN 
> bit pattern unchanged.  It also quiets any input sNaN bit pattern in an 
> implementer-specific manner, for example the MIPS 74Kf processor returns 
> the default qNaN pattern with the sign bit always clear and the Broadcom 
> SB-1 and BMIPS5000 processors propagate the input sNaN bit pattern with 
> the sign bit unchanged and the quiet bit first cleared in the trailing 
> significand field and then the next lower bit set if clearing the quiet 
> bit left the field with no other bit set.
> 
> Especially the latter observation indicates the limited usefulness of 
> the workaround as it will cover many hardware configurations, but not 
> all of them, only making it harder to discover such broken binaries that 
> need to be recompiled with GCC told to avoid the use of ABS.fmt and 
> NEG.fmt instructions where non-arithmetic semantics is required by the 
> algorithm used.
> 
> Revert the damage done by the series of changes then, and take the 
> opportunity to simplify implementation by calling `ieee754dp_sub' and 
> `ieee754dp_add' as required and also the rounding mode set towards -Inf 
> temporarily so that the sign of 0 is correctly handled.
> 
> Signed-off-by: Maciej W. Rozycki <macro@linux-mips.org>
> ---

 One point to make here is the use of `ieee754dp_sub' and `ieee754dp_add' 
makes emulated ABS.fmt and NEG.fmt respect FCSR.FS for denormals just as 
hardware does.  I should have noted that in the commit message, perhaps it 
can be retrofitted?

  Maciej

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH 46/48] MIPS: math-emu: Make ABS.fmt and NEG.fmt arithmetic again
  2015-04-07 15:24   ` Maciej W. Rozycki
@ 2015-04-07 17:31     ` Ralf Baechle
  2015-04-07 23:11       ` Maciej W. Rozycki
  0 siblings, 1 reply; 62+ messages in thread
From: Ralf Baechle @ 2015-04-07 17:31 UTC (permalink / raw)
  To: Maciej W. Rozycki; +Cc: linux-mips

On Tue, Apr 07, 2015 at 04:24:32PM +0100, Maciej W. Rozycki wrote:

> > Revert the damage done by the series of changes then, and take the 
> > opportunity to simplify implementation by calling `ieee754dp_sub' and 
> > `ieee754dp_add' as required and also the rounding mode set towards -Inf 
> > temporarily so that the sign of 0 is correctly handled.
> > 
> > Signed-off-by: Maciej W. Rozycki <macro@linux-mips.org>
> > ---
> 
>  One point to make here is the use of `ieee754dp_sub' and `ieee754dp_add' 
> makes emulated ABS.fmt and NEG.fmt respect FCSR.FS for denormals just as 
> hardware does.  I should have noted that in the commit message, perhaps it 
> can be retrofitted?

Yes, it can.  Just send the new commit message.

  Ralf

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH 47/48] MIPS: Respect the ISA level in FCSR handling
  2015-04-07 12:54   ` Ralf Baechle
@ 2015-04-07 21:13     ` Maciej W. Rozycki
  2015-04-07 22:45       ` Ralf Baechle
  0 siblings, 1 reply; 62+ messages in thread
From: Maciej W. Rozycki @ 2015-04-07 21:13 UTC (permalink / raw)
  To: Ralf Baechle; +Cc: linux-mips

On Tue, 7 Apr 2015, Ralf Baechle wrote:

> > Index: linux/arch/mips/include/asm/fpu.h
> > ===================================================================
> > --- linux.orig/arch/mips/include/asm/fpu.h	2015-04-02 20:18:47.499480000 +0100
> > +++ linux/arch/mips/include/asm/fpu.h	2015-04-02 20:27:59.745241000 +0100
> > @@ -14,6 +14,7 @@
> >  #include <linux/thread_info.h>
> >  #include <linux/bitops.h>
> >  
> > +#include <asm/current.h>
> >  #include <asm/mipsregs.h>
> >  #include <asm/cpu.h>
> >  #include <asm/cpu-features.h>
> 
> This is adding a 2nd inclusion of <asm/current.h>.  Will fix that.

 Thanks!  I resisted the temptation to include changes to sort inclusions 
with this series or it would risk becoming an ever going effort.  Though 
it would have avoided an oversight like this.

  Maciej

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH 47/48] MIPS: Respect the ISA level in FCSR handling
  2015-04-07 21:13     ` Maciej W. Rozycki
@ 2015-04-07 22:45       ` Ralf Baechle
  0 siblings, 0 replies; 62+ messages in thread
From: Ralf Baechle @ 2015-04-07 22:45 UTC (permalink / raw)
  To: Maciej W. Rozycki; +Cc: linux-mips

On Tue, Apr 07, 2015 at 10:13:38PM +0100, Maciej W. Rozycki wrote:

> > > Index: linux/arch/mips/include/asm/fpu.h
> > > ===================================================================
> > > --- linux.orig/arch/mips/include/asm/fpu.h	2015-04-02 20:18:47.499480000 +0100
> > > +++ linux/arch/mips/include/asm/fpu.h	2015-04-02 20:27:59.745241000 +0100
> > > @@ -14,6 +14,7 @@
> > >  #include <linux/thread_info.h>
> > >  #include <linux/bitops.h>
> > >  
> > > +#include <asm/current.h>
> > >  #include <asm/mipsregs.h>
> > >  #include <asm/cpu.h>
> > >  #include <asm/cpu-features.h>
> > 
> > This is adding a 2nd inclusion of <asm/current.h>.  Will fix that.
> 
>  Thanks!  I resisted the temptation to include changes to sort inclusions 
> with this series or it would risk becoming an ever going effort.  Though 
> it would have avoided an oversight like this.

I found it only because once in a blue moon I run the various checkers
that ship with the kernel.  Turns out half of them don't work out of
the box, at least not for my setup so there's yet more work to do.

  Ralf

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH 46/48] MIPS: math-emu: Make ABS.fmt and NEG.fmt arithmetic again
  2015-04-07 17:31     ` Ralf Baechle
@ 2015-04-07 23:11       ` Maciej W. Rozycki
  0 siblings, 0 replies; 62+ messages in thread
From: Maciej W. Rozycki @ 2015-04-07 23:11 UTC (permalink / raw)
  To: Ralf Baechle; +Cc: linux-mips

On Tue, 7 Apr 2015, Ralf Baechle wrote:

> >  One point to make here is the use of `ieee754dp_sub' and `ieee754dp_add' 
> > makes emulated ABS.fmt and NEG.fmt respect FCSR.FS for denormals just as 
> > hardware does.  I should have noted that in the commit message, perhaps it 
> > can be retrofitted?
> 
> Yes, it can.  Just send the new commit message.

 I take it back, the FLUSHXSP and FLUSHXDP macros the old implementation 
had did handle FCSR.FS.  So the original message is good.  Sorry for the 
confusion.

  Maciej

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH 37/48] MIPS: math-emu: Correct delay-slot exception propagation
  2015-04-03 22:26 ` [PATCH 37/48] MIPS: math-emu: Correct delay-slot exception propagation Maciej W. Rozycki
@ 2016-01-20 10:50   ` Aurelien Jarno
  2016-01-20 15:15     ` Maciej W. Rozycki
  0 siblings, 1 reply; 62+ messages in thread
From: Aurelien Jarno @ 2016-01-20 10:50 UTC (permalink / raw)
  To: Maciej W. Rozycki; +Cc: Ralf Baechle, linux-mips

Hi,

On 2015-04-03 23:26, Maciej W. Rozycki wrote:
> Restore EPC at the branch whose delay slot is emulated if the delay-slot 
> instruction signals.  This is so that code in `fpu_emulator_cop1Handler' 
> does not see EPC having advanced and mistakenly successfully resume 
> userland execution from the location at the branch target in that case.
> Restoring EPC guarantees an immediate exit from the emulation loop and 
> if EPC hasn't advanced at all since entering the loop, also issuing the 
> signal reported by the delay-slot instruction.
> 
> Signed-off-by: Maciej W. Rozycki <macro@linux-mips.org>
> ---

Unfortunately this patch broke the case where the delay slot contains a
NOP instruction. In practice this causes a lot of code to now fails with
a SIGILL. For example the following code, extracted from R, reports a
SIGILL address 0x76f29670.

=> 0x76f29670:  ldc1    $f2,40(s8)
   0x76f29674:  ldc1    $f0,40(s8)
   0x76f29678:  add.d   $f0,$f2,$f0
   0x76f2967c:  sdc1    $f0,40(s8)
   0x76f29680:  ldc1    $f2,40(s8)
   0x76f29684:  ldc1    $f0,80(s8)
   0x76f29688:  add.d   $f0,$f2,$f0
   0x76f2968c:  sdc1    $f0,96(s8)
   0x76f29690:  ldc1    $f2,96(s8)
   0x76f29694:  ldc1    $f0,40(s8)
   0x76f29698:  sub.d   $f0,$f2,$f0
   0x76f2969c:  sdc1    $f0,112(s8)
   0x76f296a0:  ldc1    $f2,112(s8)
   0x76f296a4:  ldc1    $f0,80(s8)
   0x76f296a8:  sub.d   $f2,$f2,$f0
   0x76f296ac:  ldc1    $f0,144(s8)
   0x76f296b0:  c.eq.d  $f2,$f0
   0x76f296b4:  bc1t    0x76f29670
   0x76f296b8:  nop

The issues lies in the following part of the patch:

> --- linux.orig/arch/mips/math-emu/cp1emu.c	2015-04-02 20:27:57.493218000 +0100
> +++ linux/arch/mips/math-emu/cp1emu.c	2015-04-02 20:27:57.710224000 +0100
> @@ -1192,16 +1208,24 @@ static int cop1Emulate(struct pt_regs *x
>  						if (cpu_has_mips_4_5_r)
>  							goto emul;
>  
> -						return SIGILL;
> +						goto bc_sigill;
>  					}
>  					break;
> +
> +				bc_sigill:
> +					xcp->cp0_epc = bcpc;
> +					return SIGILL;
>  				}
>  
>  				/*
>  				 * Single step the non-cp1
>  				 * instruction in the dslot
>  				 */
> -				return mips_dsemul(xcp, ir, contpc);
> +				sig = mips_dsemul(xcp, ir, contpc);
> +				if (sig)
> +					xcp->cp0_epc = bcpc;
> +				/* SIGILL forces out of the emulation loop.  */
> +				return sig ? sig : SIGILL;

This assumes we should get out of the emulation loop if the returned
value is 0. However this value is used to signal the instruction has
been emulated in case of a NOP.

>  			} else if (likely) {	/* branch not taken */
>  				/*
>  				 * branch likely nullifies
> Index: linux/arch/mips/math-emu/dsemul.c
> ===================================================================
> --- linux.orig/arch/mips/math-emu/dsemul.c	2015-04-02 20:27:57.133225000 +0100
> +++ linux/arch/mips/math-emu/dsemul.c	2015-04-02 20:27:57.713219000 +0100
> @@ -96,7 +96,7 @@ int mips_dsemul(struct pt_regs *regs, mi
>  
>  	flush_cache_sigtramp((unsigned long)&fr->emul);
>  
> -	return SIGILL;		/* force out of emulation loop */
> +	return 0;

With this change there is no way to distinguish the NOP case and the
normal instruction case anymore.


An easy workaround to the issue (with performance impact though) is to
get rid of the NOP special case in dsemul.c

diff --git a/arch/mips/math-emu/dsemul.c b/arch/mips/math-emu/dsemul.c
index cbb36c1..c6e3901 100644
--- a/arch/mips/math-emu/dsemul.c
+++ b/arch/mips/math-emu/dsemul.c
@@ -35,7 +35,7 @@ int mips_dsemul(struct pt_regs *regs, mips_instruction ir, unsigned long cpc)
 {
 	struct emuframe __user *fr;
 	int err;
-
+#if 0
 	if ((get_isa16_mode(regs->cp0_epc) && ((ir >> 16) == MM_NOP16)) ||
 		(ir == 0)) {
 		/* NOP is easy */
@@ -43,7 +43,7 @@ int mips_dsemul(struct pt_regs *regs, mips_instruction ir, unsigned long cpc)
 		clear_delay_slot(regs);
 		return 0;
 	}
-
+#endif
 	pr_debug("dsemul %lx %lx\n", regs->cp0_epc, cpc);
 
 	/*

-- 
Aurelien Jarno                          GPG: 4096R/1DDD8C9B
aurelien@aurel32.net                 http://www.aurel32.net

^ permalink raw reply related	[flat|nested] 62+ messages in thread

* Re: [PATCH 37/48] MIPS: math-emu: Correct delay-slot exception propagation
  2016-01-20 10:50   ` Aurelien Jarno
@ 2016-01-20 15:15     ` Maciej W. Rozycki
  0 siblings, 0 replies; 62+ messages in thread
From: Maciej W. Rozycki @ 2016-01-20 15:15 UTC (permalink / raw)
  To: Aurelien Jarno; +Cc: Ralf Baechle, linux-mips

Hi Aurelien,

> On 2015-04-03 23:26, Maciej W. Rozycki wrote:
> > Restore EPC at the branch whose delay slot is emulated if the delay-slot 
> > instruction signals.  This is so that code in `fpu_emulator_cop1Handler' 
> > does not see EPC having advanced and mistakenly successfully resume 
> > userland execution from the location at the branch target in that case.
> > Restoring EPC guarantees an immediate exit from the emulation loop and 
> > if EPC hasn't advanced at all since entering the loop, also issuing the 
> > signal reported by the delay-slot instruction.
> > 
> > Signed-off-by: Maciej W. Rozycki <macro@linux-mips.org>
> > ---
> 
> Unfortunately this patch broke the case where the delay slot contains a
> NOP instruction. In practice this causes a lot of code to now fails with
> a SIGILL. For example the following code, extracted from R, reports a
> SIGILL address 0x76f29670.
> 
> => 0x76f29670:  ldc1    $f2,40(s8)
>    0x76f29674:  ldc1    $f0,40(s8)
>    0x76f29678:  add.d   $f0,$f2,$f0
>    0x76f2967c:  sdc1    $f0,40(s8)
>    0x76f29680:  ldc1    $f2,40(s8)
>    0x76f29684:  ldc1    $f0,80(s8)
>    0x76f29688:  add.d   $f0,$f2,$f0
>    0x76f2968c:  sdc1    $f0,96(s8)
>    0x76f29690:  ldc1    $f2,96(s8)
>    0x76f29694:  ldc1    $f0,40(s8)
>    0x76f29698:  sub.d   $f0,$f2,$f0
>    0x76f2969c:  sdc1    $f0,112(s8)
>    0x76f296a0:  ldc1    $f2,112(s8)
>    0x76f296a4:  ldc1    $f0,80(s8)
>    0x76f296a8:  sub.d   $f2,$f2,$f0
>    0x76f296ac:  ldc1    $f0,144(s8)
>    0x76f296b0:  c.eq.d  $f2,$f0
>    0x76f296b4:  bc1t    0x76f29670
>    0x76f296b8:  nop

 Thanks for your report, I'll have a look ASAP.

  Maciej

^ permalink raw reply	[flat|nested] 62+ messages in thread

end of thread, other threads:[~2016-01-20 15:15 UTC | newest]

Thread overview: 62+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-04-03 22:23 [PATCH 00/48] FPU and FP emulation clean-ups, fixes and feature updates Maciej W. Rozycki
2015-04-03 22:23 ` [PATCH 01/48] doc: kernel-parameters.txt: Mark `nofpu' for MIPS too Maciej W. Rozycki
2015-04-03 22:23 ` [PATCH 02/48] MIPS: mipsregs.h: Remove broken comments Maciej W. Rozycki
2015-04-03 22:23 ` [PATCH 03/48] MIPS: mipsregs.h: Reorder CP1 macro definitions Maciej W. Rozycki
2015-04-03 22:23 ` [PATCH 04/48] MIPS: mipsregs.h: Move TX39 macros out of the way Maciej W. Rozycki
2015-04-03 22:23 ` [PATCH 05/48] MIPS: mipsregs.h: Reindent CP0 Cause macros Maciej W. Rozycki
2015-04-03 22:24 ` [PATCH 06/48] MIPS: ieee754.h: Correct comments for special values Maciej W. Rozycki
2015-04-03 22:24 ` [PATCH 07/48] MIPS: ieee754.h: Supplement " Maciej W. Rozycki
2015-04-03 22:24 ` [PATCH 08/48] MIPS: Correct the comment for FPU emulator traps Maciej W. Rozycki
2015-04-03 22:24 ` [PATCH 09/48] MIPS: Clarify the comment for `__cpu_has_fpu' Maciej W. Rozycki
2015-04-03 22:24 ` [PATCH 10/48] MIPS: math-emu: Reindent `bc_op' emulation Maciej W. Rozycki
2015-04-03 22:24 ` [PATCH 11/48] MIPS: Correct the comment for and reformat `movf_func' Maciej W. Rozycki
2015-04-03 22:24 ` [PATCH 12/48] MIPS: math-emu: Fix oversize lines in comparisons Maciej W. Rozycki
2015-04-03 22:24 ` [PATCH 13/48] MIPS: ELF: Drop `get_fp_abi' Maciej W. Rozycki
2015-04-03 22:24 ` [PATCH 14/48] MIPS: mips-r2-to-r6-emul.h: Inline empty `mipsr2_decoder' Maciej W. Rozycki
2015-04-03 22:24 ` [PATCH 15/48] MIPS: Reindent R6 RI exception emulation Maciej W. Rozycki
2015-04-03 22:24 ` [PATCH 16/48] MIPS: math-emu: Remove `modeindex' macro Maciej W. Rozycki
2015-04-03 22:25 ` [PATCH 17/48] MIPS: bitops.h: Avoid inline asm for constant FLS Maciej W. Rozycki
2015-04-03 22:25 ` [PATCH 18/48] MIPS: math-emu: Factor out CFC1/CTC1 emulation Maciej W. Rozycki
2015-04-03 23:33   ` Sergei Shtylyov
2015-04-04  0:07     ` Maciej W. Rozycki
2015-04-03 22:25 ` [PATCH 19/48] MIPS: Normalise code flow in the CpU exception handler Maciej W. Rozycki
2015-04-03 22:25 ` [PATCH 20/48] MIPS: Use `FPU_CSR_ALL_X' in `__build_clear_fpe' Maciej W. Rozycki
2015-04-03 22:25 ` [PATCH 21/48] MIPS: math-emu: Update sNaN quieting handlers Maciej W. Rozycki
2015-04-03 22:25 ` [PATCH 23/48] MIPS: math-emu: Don't pass qNaNs through " Maciej W. Rozycki
2015-04-03 22:25 ` [PATCH 24/48] MIPS: math-emu: Reinstate sNaN " Maciej W. Rozycki
2015-04-03 22:25 ` [PATCH 25/48] MIPS: math-emu: Optimise NaN handling in comparisons Maciej W. Rozycki
2015-04-03 22:25 ` [PATCH 26/48] MIPS: math-emu: Remove redundant code from NaN comparison Maciej W. Rozycki
2015-04-03 22:25 ` [PATCH 27/48] MIPS: math-emu: Remove dead comparison helpers Maciej W. Rozycki
2015-04-03 22:25 ` [PATCH 29/48] MIPS: math-emu: Make NaN classifiers static Maciej W. Rozycki
2015-04-03 23:22   ` Sergei Shtylyov
2015-04-03 22:26 ` [PATCH 30/48] MIPS: Correct `nofpu' non-functionality Maciej W. Rozycki
2015-04-03 22:26 ` [PATCH 31/48] MIPS: Correct MIPS16 BREAK code interpretation Maciej W. Rozycki
2015-04-03 22:26 ` [PATCH 32/48] MIPS: BREAK instruction interpretation corrections Maciej W. Rozycki
2015-04-03 22:26 ` [PATCH 33/48] MIPS: Fix BREAK code interpretation heuristics Maciej W. Rozycki
2015-04-03 22:26 ` [PATCH 34/48] MIPS: math-emu: Fix delay-slot emulation cache incoherency Maciej W. Rozycki
2015-04-03 22:26 ` [PATCH 35/48] MIPS: Correct MIPS I FP context layout Maciej W. Rozycki
2015-04-03 22:26 ` [PATCH 36/48] MIPS: Correct FP ISA requirements Maciej W. Rozycki
2015-04-03 22:26 ` [PATCH 37/48] MIPS: math-emu: Correct delay-slot exception propagation Maciej W. Rozycki
2016-01-20 10:50   ` Aurelien Jarno
2016-01-20 15:15     ` Maciej W. Rozycki
2015-04-03 22:27 ` [PATCH 38/48] MIPS: math-emu: Move long fixed-point support into an `ar' library Maciej W. Rozycki
2015-04-03 22:27 ` [PATCH 39/48] MIPS: Respect the FCSR exception mask for `si_code' Maciej W. Rozycki
2015-04-03 22:27 ` [PATCH 40/48] MIPS: Always clear FCSR cause bits after emulation Maciej W. Rozycki
2015-04-03 22:27 ` [PATCH 41/48] MIPS: Set `si_code' for SIGFPE signals sent from emulation too Maciej W. Rozycki
2015-04-03 22:27 ` [PATCH 42/48] MIPS: Correct ISA masking in FPU feature determination Maciej W. Rozycki
2015-04-03 22:27 ` [PATCH 43/48] MIPS: math-emu: Set FIR feature flags for full emulation Maciej W. Rozycki
2015-04-03 23:18   ` Sergei Shtylyov
2015-04-03 22:27 ` [PATCH 44/48] MIPS: math-emu: Implement the FCCR, FEXR and FENR registers Maciej W. Rozycki
2015-04-03 22:27 ` [PATCH 45/48] MIPS: math-emu: Define IEEE 754-2008 feature control bits Maciej W. Rozycki
2015-04-03 22:27 ` [PATCH 46/48] MIPS: math-emu: Make ABS.fmt and NEG.fmt arithmetic again Maciej W. Rozycki
2015-04-07 15:24   ` Maciej W. Rozycki
2015-04-07 17:31     ` Ralf Baechle
2015-04-07 23:11       ` Maciej W. Rozycki
2015-04-03 22:27 ` [PATCH 47/48] MIPS: Respect the ISA level in FCSR handling Maciej W. Rozycki
2015-04-07 12:54   ` Ralf Baechle
2015-04-07 21:13     ` Maciej W. Rozycki
2015-04-07 22:45       ` Ralf Baechle
2015-04-03 22:27 ` [PATCH 48/48] MIPS: Factor out FPU feature probing Maciej W. Rozycki
2015-04-04 20:04 ` [PATCH 00/48] FPU and FP emulation clean-ups, fixes and feature updates Ralf Baechle
2015-04-04 20:55   ` Maciej W. Rozycki
2015-04-04 21:57     ` Ralf Baechle

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.