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

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

 



On 2018-10-18 3:20 PM, Helge Deller wrote:
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.:
No.  This is a mnemonics issue.  PA 1.1 has zdep instruction that is the same as PA 2.0 depw,z.
The have same instruction encoding.

   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
Should be zdep.
         .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 */



--
John David Anglin  dave.anglin@xxxxxxxx




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

  Powered by Linux