Commit 82b89152 authored by Maciej W. Rozycki's avatar Maciej W. Rozycki Committed by Ralf Baechle

MIPS: LD/SD o32 macro GAS fix update

I am about to commit:

http://sourceware.org/ml/binutils/2010-10/msg00033.html

that fixes a problem with the LD/SD macro currently implemented by GAS for
the o32 ABI in an inconsistent way.  This is best illustrated with a
simple program, which I'm copying here from the message above for easier
reference:

$ cat ld.s
	ld	$5,32767($4)
	ld	$5,32768($4)

This gets assebled into the following output:

$ mips-linux-as -32 -mips3 -o ld.o ld.s
$ mips-linux-objdump -d ld.o

ld.o:     file format elf32-tradbigmips

Disassembly of section .text:

00000000 <.text>:
   0:	dc857fff 	ld	a1,32767(a0)
   4:	3c010001 	lui	at,0x1
   8:	00810821 	addu	at,a0,at
   c:	8c258000 	lw	a1,-32768(at)
  10:	8c268004 	lw	a2,-32764(at)
	...

Oops!

 The GAS fix makes the macro behave in a consistent way and pairs of LW/SW
instructions to be output as appropriate regardless of the size of the
offset associated with the address used.  The machine instruction is still
available, but to reach it macros have to be disabled first.  This has a
side effect of requiring the use of a machine-addressable memory operand.

 As some platforms require 64-bit operations for accesses to some I/O
registers LD/SD instructions are used in a couple of places in Linux
regardless of the ABI selected.  Here's a fix for some pieces of code
affected I've been able to track down.  The fix should be backwards
compatible with all supported binutils releases in existence and can be
used as a reference for any other places or off-tree code.  The use of the
"R" constraint guarantees a machine-addressable operand.
Signed-off-by: default avatarMaciej W. Rozycki <macro@linux-mips.org>
Cc: linux-mips@linux-mips.org
Patchwork: https://patchwork.linux-mips.org/patch/1680/Signed-off-by: default avatarRalf Baechle <ralf@linux-mips.org>
parent cf745a39
...@@ -329,10 +329,14 @@ static inline void pfx##write##bwlq(type val, \ ...@@ -329,10 +329,14 @@ static inline void pfx##write##bwlq(type val, \
"dsrl32 %L0, %L0, 0" "\n\t" \ "dsrl32 %L0, %L0, 0" "\n\t" \
"dsll32 %M0, %M0, 0" "\n\t" \ "dsll32 %M0, %M0, 0" "\n\t" \
"or %L0, %L0, %M0" "\n\t" \ "or %L0, %L0, %M0" "\n\t" \
".set push" "\n\t" \
".set noreorder" "\n\t" \
".set nomacro" "\n\t" \
"sd %L0, %2" "\n\t" \ "sd %L0, %2" "\n\t" \
".set pop" "\n\t" \
".set mips0" "\n" \ ".set mips0" "\n" \
: "=r" (__tmp) \ : "=r" (__tmp) \
: "0" (__val), "m" (*__mem)); \ : "0" (__val), "R" (*__mem)); \
if (irq) \ if (irq) \
local_irq_restore(__flags); \ local_irq_restore(__flags); \
} else \ } else \
...@@ -355,12 +359,16 @@ static inline type pfx##read##bwlq(const volatile void __iomem *mem) \ ...@@ -355,12 +359,16 @@ static inline type pfx##read##bwlq(const volatile void __iomem *mem) \
local_irq_save(__flags); \ local_irq_save(__flags); \
__asm__ __volatile__( \ __asm__ __volatile__( \
".set mips3" "\t\t# __readq" "\n\t" \ ".set mips3" "\t\t# __readq" "\n\t" \
".set push" "\n\t" \
".set noreorder" "\n\t" \
".set nomacro" "\n\t" \
"ld %L0, %1" "\n\t" \ "ld %L0, %1" "\n\t" \
".set pop" "\n\t" \
"dsra32 %M0, %L0, 0" "\n\t" \ "dsra32 %M0, %L0, 0" "\n\t" \
"sll %L0, %L0, 0" "\n\t" \ "sll %L0, %L0, 0" "\n\t" \
".set mips0" "\n" \ ".set mips0" "\n" \
: "=r" (__val) \ : "=r" (__val) \
: "m" (*__mem)); \ : "R" (*__mem)); \
if (irq) \ if (irq) \
local_irq_restore(__flags); \ local_irq_restore(__flags); \
} else { \ } else { \
......
...@@ -65,11 +65,15 @@ static unsigned char readb_outer_space(unsigned long long phys) ...@@ -65,11 +65,15 @@ static unsigned char readb_outer_space(unsigned long long phys)
__asm__ __volatile__ ( __asm__ __volatile__ (
" .set mips3 \n" " .set mips3 \n"
" .set push \n"
" .set noreorder \n"
" .set nomacro \n"
" ld %0, %1 \n" " ld %0, %1 \n"
" .set pop \n"
" lbu %0, (%0) \n" " lbu %0, (%0) \n"
" .set mips0 \n" " .set mips0 \n"
: "=r" (res) : "=r" (res)
: "m" (vaddr)); : "R" (vaddr));
write_c0_status(sr); write_c0_status(sr);
ssnop_4(); ssnop_4();
...@@ -89,11 +93,15 @@ static void writeb_outer_space(unsigned long long phys, unsigned char c) ...@@ -89,11 +93,15 @@ static void writeb_outer_space(unsigned long long phys, unsigned char c)
__asm__ __volatile__ ( __asm__ __volatile__ (
" .set mips3 \n" " .set mips3 \n"
" .set push \n"
" .set noreorder \n"
" .set nomacro \n"
" ld %0, %1 \n" " ld %0, %1 \n"
" .set pop \n"
" sb %2, (%0) \n" " sb %2, (%0) \n"
" .set mips0 \n" " .set mips0 \n"
: "=&r" (tmp) : "=&r" (tmp)
: "m" (vaddr), "r" (c)); : "R" (vaddr), "r" (c));
write_c0_status(sr); write_c0_status(sr);
ssnop_4(); ssnop_4();
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment