[RFC][PATCH] parisc: Fix left-shift assembly to be PA1.1 compatible

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

 



According to the PARISC 1.1 Instruction Set Reference Manual, PA1.1 does
*not* support the depw,z instruction, but only the dep (depw)
instruction, e.g.:

  d5 8b 08 f6     depw,z r11,24,10,r12    # NOT PA1.1
  d5 8b 0c f6     depw   r11,24,10,r12    # OK for PA1.1

And in the Linux kernel source (arch/parisc/include/asm/assembly.h) I see

        /* Shift Left - note the r and t can NOT be the same! */
        .macro shl r, sa, t
        dep,z   \r, 31-(\sa), 32-(\sa), \t
        .endm
(by the way, this macro isn't used and correctly doesn't compile because
of the z completer)

But when I disassemble the kernel source code (built for PA1.1), I see
lots of depw,z instructions generated by gcc, e.g.:
   d4 84 09 8c     depw,z r4,19,20,r4

So, what's true?
For the shl macro, can't r and t not be the same, because then on
PA1.1 the shl leaves the rightmost bits untouched/not-zeroed in t?

Qemu, which emulates a PA1.1, seems to happily translate even the
depw,z instruction.

Do we maybe need a patch like the one below (and teach gcc not to emit
depw,z) to be fully PA1.1 compatible?
Suggestions?

Helge

The patch below should make the kernel fully PA1.1 compatible.

diff --git a/arch/parisc/include/asm/assembly.h b/arch/parisc/include/asm/assembly.h
index 60e6f07b7e32..87980fd1c4f1 100644
--- a/arch/parisc/include/asm/assembly.h
+++ b/arch/parisc/include/asm/assembly.h
@@ -44,7 +44,7 @@
 #define LDREGM	ldwm
 #define STREGM	stwm
 #define SHRREG	shr
-#define SHLREG	shlw
+#define SHLREG	shl
 #define ANDCM   andcm
 #define COND(x)	x
 #define RP_OFFSET	20
@@ -128,14 +128,15 @@
 	.endm
 
 
-	/* Shift Left - note the r and t can NOT be the same! */
 	.macro shl r, sa, t
-	dep,z	\r, 31-(\sa), 32-(\sa), \t
-	.endm
-
-	/* The PA 2.0 shift left */
-	.macro shlw r, sa, t
+#ifdef CONFIG_PA20
+	/* The PA 2.0 shift left (shlw) */
 	depw,z	\r, 31-(\sa), 32-(\sa), \t
+#else
+	/* PA 1.0 Shift Left - note the r and t can NOT be the same! */
+	copy	%r0, \t
+	dep	\r, 31-(\sa), 32-(\sa), \t
+#endif
 	.endm
 
 	/* And the PA 2.0W shift left */
diff --git a/arch/parisc/kernel/entry.S b/arch/parisc/kernel/entry.S
index 1b4732e20137..dca15d4d1d70 100644
--- a/arch/parisc/kernel/entry.S
+++ b/arch/parisc/kernel/entry.S
@@ -421,12 +421,16 @@
 # endif
 #endif
 	dep             %r0,31,PAGE_SHIFT,\pmd  /* clear offset */
-	copy		%r0,\pte
 	ldw,s		\index(\pmd),\pmd
 	bb,>=,n		\pmd,_PxD_PRESENT_BIT,\fault
 	dep		%r0,31,PxD_FLAG_SHIFT,\pmd /* clear flags */
-	copy		\pmd,%r9
-	SHLREG		%r9,PxD_VALUE_SHIFT,\pmd
+#ifdef CONFIG_PA20
+	SHLREG		\pmd,PxD_VALUE_SHIFT,\pmd
+#else
+	copy		\pmd,\pte
+	SHLREG		\pte,PxD_VALUE_SHIFT,\pmd
+#endif
+	copy		%r0,\pte
 	extru		\va,31-PAGE_SHIFT,ASM_BITS_PER_PTE,\index
 	dep		%r0,31,PAGE_SHIFT,\pmd  /* clear offset */
 	shladd		\index,BITS_PER_PTE_ENTRY,\pmd,\pmd /* pmd is now pte */
@@ -447,7 +451,6 @@
 	.macro		L3_ptep pgd,pte,index,va,fault
 #if CONFIG_PGTABLE_LEVELS == 3 /* we might have a 2-Level scheme, e.g. with 16kb page size */
 	extrd,u		\va,63-ASM_PGDIR_SHIFT,ASM_BITS_PER_PGD,\index
-	copy		%r0,\pte
 	extrd,u,*=	\va,63-ASM_PGDIR_SHIFT,64-ASM_PGDIR_SHIFT,%r0
 	ldw,s		\index(\pgd),\pgd
 	extrd,u,*=	\va,63-ASM_PGDIR_SHIFT,64-ASM_PGDIR_SHIFT,%r0
diff --git a/arch/parisc/kernel/syscall.S b/arch/parisc/kernel/syscall.S
index 5f7e57fcaeef..37fb08a48504 100644
--- a/arch/parisc/kernel/syscall.S
+++ b/arch/parisc/kernel/syscall.S
@@ -570,8 +570,8 @@ lws_compare_and_swap:
 	/* Find lock to use, the hash is either one of 0 to
 	   15, multiplied by 16 (keep it 16-byte aligned)
 	   and add to the lock table offset. */
-	shlw	%r20, 4, %r20
-	add	%r20, %r28, %r20
+	SHLREG	%r20, 4, %r21
+	add	%r21, %r28, %r20
 
 # if ENABLE_LWS_DEBUG
 	/*	
@@ -705,7 +705,7 @@ lws_compare_and_swap_2:
 
 	/* Jump to the functions which will load the old and new values into
 	   registers depending on the their size */
-	shlw	%r23, 2, %r29
+	SHLREG	%r23, 2, %r29
 	blr	%r29, %r0
 	nop
 
@@ -762,8 +762,8 @@ cas2_lock_start:
 	/* Find lock to use, the hash is either one of 0 to
 	   15, multiplied by 16 (keep it 16-byte aligned)
 	   and add to the lock table offset. */
-	shlw	%r20, 4, %r20
-	add	%r20, %r28, %r20
+	SHLREG	%r20, 4, %r21
+	add	%r21, %r28, %r20
 
 	rsm	PSW_SM_I, %r0			/* Disable interrupts */
 	/* COW breaks can cause contention on UP systems */



[Index of Archives]     [Linux SoC]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux