Browse Source

add support for mips and mips64 r6 isa

mips32r6 and mips64r6 are actually new isas at both the asm source and
opcode levels (pre-r6 code cannot run on r6) and thus need to be
treated as a new subarch. the following changes are made, some of
which yield code generation improvements for non-r6 targets too:

- add subarch logic in configure script and reloc.h files for dynamic
  linker name.

- suppress use of .set mips2 asm directives (used to allow mips2
  atomic instructions on baseline mips1 builds; the kernel has to
  emulate them on mips1) except when actually needed. they cause wrong
  instruction encodings on r6, and pessimize inlining on at least some
  compilers.

- only hard-code sync instruction encoding on mips1.

- use "ZC" constraint instead of "m" constraint for llsc memory
  operands on r6, where the ll/sc instructions no longer accept full
  16-bit offsets.

- only hard-code rdhwr instruction encoding with .word on targets
  (pre-r2) where it may need trap-and-emulate by the kernel.
  otherwise, just use the instruction mnemonic, and allow an arbitrary
  destination register to be used.
master
Rich Felker 10 years ago
parent
commit
6d99ad91e8
  1. 27
      arch/mips/atomic_arch.h
  2. 9
      arch/mips/pthread_arch.h
  3. 8
      arch/mips/reloc.h
  4. 20
      arch/mips64/atomic_arch.h
  5. 8
      arch/mips64/pthread_arch.h
  6. 8
      arch/mips64/reloc.h
  7. 2
      configure

27
arch/mips/atomic_arch.h

@ -1,12 +1,24 @@
#if __mips_isa_rev < 6
#define LLSC_M "m"
#else
#define LLSC_M "ZC"
#endif
#define a_ll a_ll
static inline int a_ll(volatile int *p)
{
int v;
#if __mips < 2
__asm__ __volatile__ (
".set push ; .set mips2\n\t"
"ll %0, %1"
"\n\t.set pop"
: "=r"(v) : "m"(*p));
#else
__asm__ __volatile__ (
"ll %0, %1"
: "=r"(v) : LLSC_M(*p));
#endif
return v;
}
@ -14,26 +26,33 @@ static inline int a_ll(volatile int *p)
static inline int a_sc(volatile int *p, int v)
{
int r;
#if __mips < 2
__asm__ __volatile__ (
".set push ; .set mips2\n\t"
"sc %0, %1"
"\n\t.set pop"
: "=r"(r), "=m"(*p) : "0"(v) : "memory");
#else
__asm__ __volatile__ (
"sc %0, %1"
: "=r"(r), "="LLSC_M(*p) : "0"(v) : "memory");
#endif
return r;
}
#define a_barrier a_barrier
static inline void a_barrier()
{
#if __mips < 2
/* mips2 sync, but using too many directives causes
* gcc not to inline it, so encode with .long instead. */
__asm__ __volatile__ (".long 0xf" : : : "memory");
#if 0
__asm__ __volatile__ (
".set push ; .set mips2 ; sync ; .set pop"
: : : "memory");
#else
__asm__ __volatile__ ("sync" : : : "memory");
#endif
}
#define a_pre_llsc a_barrier
#define a_post_llsc a_barrier
#undef LLSC_M

9
arch/mips/pthread_arch.h

@ -1,12 +1,11 @@
static inline struct pthread *__pthread_self()
{
#ifdef __clang__
char *tp;
__asm__ __volatile__ (".word 0x7c03e83b ; move %0, $3" : "=r" (tp) : : "$3" );
#else
#if __mips_isa_rev < 2
register char *tp __asm__("$3");
/* rdhwr $3,$29 */
__asm__ __volatile__ (".word 0x7c03e83b" : "=r" (tp) );
#else
char *tp;
__asm__ __volatile__ ("rdhwr %0, $29" : "=r" (tp) );
#endif
return (pthread_t)(tp - 0x7000 - sizeof(struct pthread));
}

8
arch/mips/reloc.h

@ -1,5 +1,11 @@
#include <endian.h>
#if __mips_isa_rev >= 6
#define ISA_SUFFIX "r6"
#else
#define ISA_SUFFIX ""
#endif
#if __BYTE_ORDER == __LITTLE_ENDIAN
#define ENDIAN_SUFFIX "el"
#else
@ -12,7 +18,7 @@
#define FP_SUFFIX ""
#endif
#define LDSO_ARCH "mips" ENDIAN_SUFFIX FP_SUFFIX
#define LDSO_ARCH "mips" ISA_SUFFIX ENDIAN_SUFFIX FP_SUFFIX
#define TPOFF_K (-0x7000)

20
arch/mips64/atomic_arch.h

@ -1,10 +1,16 @@
#if __mips_isa_rev < 6
#define LLSC_M "m"
#else
#define LLSC_M "ZC"
#endif
#define a_ll a_ll
static inline int a_ll(volatile int *p)
{
int v;
__asm__ __volatile__ (
"ll %0, %1"
: "=r"(v) : "m"(*p));
: "=r"(v) : LLSC_M(*p));
return v;
}
@ -14,7 +20,7 @@ static inline int a_sc(volatile int *p, int v)
int r;
__asm__ __volatile__ (
"sc %0, %1"
: "=r"(r), "=m"(*p) : "0"(v) : "memory");
: "=r"(r), "="LLSC_M(*p) : "0"(v) : "memory");
return r;
}
@ -24,7 +30,7 @@ static inline void *a_ll_p(volatile void *p)
void *v;
__asm__ __volatile__ (
"lld %0, %1"
: "=r"(v) : "m"(*(void *volatile *)p));
: "=r"(v) : LLSC_M(*(void *volatile *)p));
return v;
}
@ -34,17 +40,17 @@ static inline int a_sc_p(volatile void *p, void *v)
long r;
__asm__ __volatile__ (
"scd %0, %1"
: "=r"(r), "=m"(*(void *volatile *)p) : "0"(v) : "memory");
: "=r"(r), "="LLSC_M(*(void *volatile *)p) : "0"(v) : "memory");
return r;
}
#define a_barrier a_barrier
static inline void a_barrier()
{
/* mips2 sync, but using too many directives causes
* gcc not to inline it, so encode with .long instead. */
__asm__ __volatile__ (".long 0xf" : : : "memory");
__asm__ __volatile__ ("sync" : : : "memory");
}
#define a_pre_llsc a_barrier
#define a_post_llsc a_barrier
#undef LLSC_M

8
arch/mips64/pthread_arch.h

@ -1,11 +1,11 @@
static inline struct pthread *__pthread_self()
{
#ifdef __clang__
char *tp;
__asm__ __volatile__ (".word 0x7c03e83b ; move %0, $3" : "=r" (tp) : : "$3" );
#else
#if __mips_isa_rev < 2
register char *tp __asm__("$3");
__asm__ __volatile__ (".word 0x7c03e83b" : "=r" (tp) );
#else
char *tp;
__asm__ __volatile__ ("rdhwr %0, $29" : "=r" (tp) );
#endif
return (pthread_t)(tp - 0x7000 - sizeof(struct pthread));
}

8
arch/mips64/reloc.h

@ -4,6 +4,12 @@
#define _GNU_SOURCE
#include <endian.h>
#if __mips_isa_rev >= 6
#define ISA_SUFFIX "r6"
#else
#define ISA_SUFFIX ""
#endif
#if __BYTE_ORDER == __LITTLE_ENDIAN
#define ENDIAN_SUFFIX "el"
#else
@ -16,7 +22,7 @@
#define FP_SUFFIX ""
#endif
#define LDSO_ARCH "mips64" ENDIAN_SUFFIX FP_SUFFIX
#define LDSO_ARCH "mips64" ISA_SUFFIX ENDIAN_SUFFIX FP_SUFFIX
#define TPOFF_K (-0x7000)

2
configure

@ -612,11 +612,13 @@ trycppif __AARCH64EB__ "$t" && SUBARCH=${SUBARCH}_be
fi
if test "$ARCH" = "mips" ; then
trycppif "__mips_isa_rev >= 6" "$t" && SUBARCH=${SUBARCH}r6
trycppif "_MIPSEL || __MIPSEL || __MIPSEL__" "$t" && SUBARCH=${SUBARCH}el
trycppif __mips_soft_float "$t" && SUBARCH=${SUBARCH}-sf
fi
if test "$ARCH" = "mips64" ; then
trycppif "__mips_isa_rev >= 6" "$t" && SUBARCH=${SUBARCH}r6
trycppif "_MIPSEL || __MIPSEL || __MIPSEL__" "$t" && SUBARCH=${SUBARCH}el
trycppif __mips_soft_float "$t" && SUBARCH=${SUBARCH}-sf
fi

Loading…
Cancel
Save