Module Name:    src
Committed By:   joerg
Date:           Thu Mar 29 13:23:40 UTC 2018

Modified Files:
        src/distrib/sets/lists/comp: md.sparc md.sparc64
        src/lib/csu/common: crt0-common.c
        src/libexec/ld.elf_so/arch/sparc: mdreloc.c
        src/libexec/ld.elf_so/arch/sparc64: mdreloc.c
        src/sys/arch/sparc/include: Makefile
        src/sys/arch/sparc64/include: Makefile
Added Files:
        src/sys/arch/sparc/include: elf_support.h
        src/sys/arch/sparc64/include: elf_support.h

Log Message:
Move the complex logic for dynamically writing branches from ld.elf_so
into a header for reuse in crt0.o for static ifunc support. Change the
existing logic for sparc64 to use the Bicc variant of ba,a as it allows
+-8MB displacement compared to the BPcc variant's +-1MB. Teach the sparc
variant the same trick for using ba,a and not sethi+jmp when possible.


To generate a diff of this commit:
cvs rdiff -u -r1.92 -r1.93 src/distrib/sets/lists/comp/md.sparc
cvs rdiff -u -r1.199 -r1.200 src/distrib/sets/lists/comp/md.sparc64
cvs rdiff -u -r1.15 -r1.16 src/lib/csu/common/crt0-common.c
cvs rdiff -u -r1.53 -r1.54 src/libexec/ld.elf_so/arch/sparc/mdreloc.c
cvs rdiff -u -r1.67 -r1.68 src/libexec/ld.elf_so/arch/sparc64/mdreloc.c
cvs rdiff -u -r1.33 -r1.34 src/sys/arch/sparc/include/Makefile
cvs rdiff -u -r0 -r1.1 src/sys/arch/sparc/include/elf_support.h
cvs rdiff -u -r1.30 -r1.31 src/sys/arch/sparc64/include/Makefile
cvs rdiff -u -r0 -r1.1 src/sys/arch/sparc64/include/elf_support.h

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/distrib/sets/lists/comp/md.sparc
diff -u src/distrib/sets/lists/comp/md.sparc:1.92 src/distrib/sets/lists/comp/md.sparc:1.93
--- src/distrib/sets/lists/comp/md.sparc:1.92	Sat Feb  3 21:27:45 2018
+++ src/distrib/sets/lists/comp/md.sparc	Thu Mar 29 13:23:39 2018
@@ -1,4 +1,4 @@
-# $NetBSD: md.sparc,v 1.92 2018/02/03 21:27:45 mrg Exp $
+# $NetBSD: md.sparc,v 1.93 2018/03/29 13:23:39 joerg Exp $
 ./usr/include/gcc-4.5/tgmath.h			comp-obsolete		obsolete
 ./usr/include/gcc-4.8/tgmath.h			comp-c-include		obsolete
 ./usr/include/gcc-4.8/visintrin.h		comp-c-include		obsolete
@@ -24,6 +24,7 @@
 ./usr/include/sparc/disklabel.h			comp-c-include
 ./usr/include/sparc/eeprom.h			comp-c-include
 ./usr/include/sparc/elf_machdep.h		comp-c-include
+./usr/include/sparc/elf_support.h		comp-c-include
 ./usr/include/sparc/endian.h			comp-c-include
 ./usr/include/sparc/endian_machdep.h		comp-c-include
 ./usr/include/sparc/fbio.h			comp-obsolete		obsolete
@@ -92,6 +93,7 @@
 ./usr/include/sparc64/disklabel.h		comp-c-include
 ./usr/include/sparc64/eeprom.h			comp-c-include
 ./usr/include/sparc64/elf_machdep.h		comp-c-include
+./usr/include/sparc64/elf_support.h		comp-c-include
 ./usr/include/sparc64/endian.h			comp-c-include
 ./usr/include/sparc64/endian_machdep.h		comp-c-include
 ./usr/include/sparc64/fbio.h			comp-obsolete		obsolete

Index: src/distrib/sets/lists/comp/md.sparc64
diff -u src/distrib/sets/lists/comp/md.sparc64:1.199 src/distrib/sets/lists/comp/md.sparc64:1.200
--- src/distrib/sets/lists/comp/md.sparc64:1.199	Sat Feb  3 21:27:45 2018
+++ src/distrib/sets/lists/comp/md.sparc64	Thu Mar 29 13:23:39 2018
@@ -1,4 +1,4 @@
-# $NetBSD: md.sparc64,v 1.199 2018/02/03 21:27:45 mrg Exp $
+# $NetBSD: md.sparc64,v 1.200 2018/03/29 13:23:39 joerg Exp $
 ./usr/include/g++/bits/sparc			comp-c-include		compat
 ./usr/include/g++/bits/sparc/c++config.h	comp-c-include		gcc,compat
 ./usr/include/g++/bits/sparc64			comp-c-include		compat
@@ -28,6 +28,7 @@
 ./usr/include/sparc/disklabel.h			comp-c-include
 ./usr/include/sparc/eeprom.h			comp-c-include
 ./usr/include/sparc/elf_machdep.h		comp-c-include
+./usr/include/sparc/elf_support.h		comp-c-include
 ./usr/include/sparc/endian.h			comp-c-include
 ./usr/include/sparc/endian_machdep.h		comp-c-include
 ./usr/include/sparc/fbio.h			comp-obsolete		obsolete
@@ -95,6 +96,7 @@
 ./usr/include/sparc64/disklabel.h		comp-c-include
 ./usr/include/sparc64/eeprom.h			comp-c-include
 ./usr/include/sparc64/elf_machdep.h		comp-c-include
+./usr/include/sparc64/elf_support.h		comp-c-include
 ./usr/include/sparc64/endian.h			comp-c-include
 ./usr/include/sparc64/endian_machdep.h		comp-c-include
 ./usr/include/sparc64/fbio.h			comp-obsolete		obsolete

Index: src/lib/csu/common/crt0-common.c
diff -u src/lib/csu/common/crt0-common.c:1.15 src/lib/csu/common/crt0-common.c:1.16
--- src/lib/csu/common/crt0-common.c:1.15	Fri Mar  9 20:20:47 2018
+++ src/lib/csu/common/crt0-common.c	Thu Mar 29 13:23:39 2018
@@ -1,4 +1,4 @@
-/* $NetBSD: crt0-common.c,v 1.15 2018/03/09 20:20:47 joerg Exp $ */
+/* $NetBSD: crt0-common.c,v 1.16 2018/03/29 13:23:39 joerg Exp $ */
 
 /*
  * Copyright (c) 1998 Christos Zoulas
@@ -36,7 +36,7 @@
  */
 
 #include <sys/cdefs.h>
-__RCSID("$NetBSD: crt0-common.c,v 1.15 2018/03/09 20:20:47 joerg Exp $");
+__RCSID("$NetBSD: crt0-common.c,v 1.16 2018/03/29 13:23:39 joerg Exp $");
 
 #include <sys/types.h>
 #include <sys/exec.h>
@@ -140,6 +140,14 @@ static void fix_iplt(void) __noinline;
 #include <stdio.h>
 extern const Elf_Rela __rela_iplt_start[] __dso_hidden __weak;
 extern const Elf_Rela __rela_iplt_end[] __dso_hidden __weak;
+#ifdef __sparc__
+#define IFUNC_RELOCATION R_TYPE(JMP_IREL)
+#include <machine/elf_support.h>
+#define write_plt(where, value) sparc_write_branch((void *)where, (void *)value)
+#else
+#define IFUNC_RELOCATION R_TYPE(IRELATIVE)
+#define write_plt(where, value) *where = value
+#endif
 
 static void
 fix_iplta(void)
@@ -150,31 +158,20 @@ fix_iplta(void)
 
 	rela = __rela_iplt_start;
 	relalim = __rela_iplt_end;
-#if DEBUG
-	printf("%p - %p\n", rela, relalim);
-#endif
 	for (; rela < relalim; ++rela) {
-		if (ELF_R_TYPE(rela->r_info) != R_TYPE(IRELATIVE))
+		if (ELF_R_TYPE(rela->r_info) != IFUNC_RELOCATION)
 			abort();
 		where = (Elf_Addr *)(relocbase + rela->r_offset);
-#if DEBUG
-		printf("location: %p\n", where);
-#endif
 		target = (Elf_Addr)(relocbase + rela->r_addend);
-#if DEBUG
-		printf("target: %p\n", (void *)target);
-#endif
 		target = ((Elf_Addr(*)(void))target)();
-#if DEBUG
-		printf("...resolves to: %p\n", (void *)target);
-#endif
-		*where = target;
+		write_plt(where, target);
 	}
 }
 #endif
 #ifdef HAS_IPLT
 extern const Elf_Rel __rel_iplt_start[] __dso_hidden __weak;
 extern const Elf_Rel __rel_iplt_end[] __dso_hidden __weak;
+#define IFUNC_RELOCATION R_TYPE(IRELATIVE)
 
 static void
 fix_iplt(void)
@@ -186,7 +183,7 @@ fix_iplt(void)
 	rel = __rel_iplt_start;
 	rellim = __rel_iplt_end;
 	for (; rel < rellim; ++rel) {
-		if (ELF_R_TYPE(rel->r_info) != R_TYPE(IRELATIVE))
+		if (ELF_R_TYPE(rel->r_info) != IFUNC_RELOCATION)
 			abort();
 		where = (Elf_Addr *)(relocbase + rel->r_offset);
 		target = ((Elf_Addr(*)(void))*where)();

Index: src/libexec/ld.elf_so/arch/sparc/mdreloc.c
diff -u src/libexec/ld.elf_so/arch/sparc/mdreloc.c:1.53 src/libexec/ld.elf_so/arch/sparc/mdreloc.c:1.54
--- src/libexec/ld.elf_so/arch/sparc/mdreloc.c:1.53	Sun Mar 25 18:56:01 2018
+++ src/libexec/ld.elf_so/arch/sparc/mdreloc.c	Thu Mar 29 13:23:39 2018
@@ -1,4 +1,4 @@
-/*	$NetBSD: mdreloc.c,v 1.53 2018/03/25 18:56:01 joerg Exp $	*/
+/*	$NetBSD: mdreloc.c,v 1.54 2018/03/29 13:23:39 joerg Exp $	*/
 
 /*-
  * Copyright (c) 1999, 2002 The NetBSD Foundation, Inc.
@@ -31,9 +31,11 @@
 
 #include <sys/cdefs.h>
 #ifndef lint
-__RCSID("$NetBSD: mdreloc.c,v 1.53 2018/03/25 18:56:01 joerg Exp $");
+__RCSID("$NetBSD: mdreloc.c,v 1.54 2018/03/29 13:23:39 joerg Exp $");
 #endif /* not lint */
 
+#include <machine/elf_support.h>
+
 #include <errno.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -404,31 +406,6 @@ _rtld_relocate_plt_lazy(Obj_Entry *obj)
 	return 0;
 }
 
-static inline void
-_rtld_write_plt(Elf_Word *where, Elf_Addr value)
-{
-	/*
-	 * At the PLT entry pointed at by `where', we now construct
-	 * a direct transfer to the now fully resolved function
-	 * address.  The resulting code in the jump slot is:
-	 *
-	 *	sethi	%hi(roffset), %g1
-	 *	sethi	%hi(addr), %g1
-	 *	jmp	%g1+%lo(addr)
-	 *
-	 * We write the third instruction first, since that leaves the
-	 * previous `b,a' at the second word in place. Hence the whole
-	 * PLT slot can be atomically change to the new sequence by
-	 * writing the `sethi' instruction at word 2.
-	 */
-	const uint32_t SETHI = 0x03000000U;
-	const uint32_t JMP = 0x81c06000U;
-	where[2] = JMP   | (value & 0x000003ff);
-	where[1] = SETHI | ((value >> 10) & 0x003fffff);
-	__asm volatile("iflush %0+8" : : "r" (where));
-	__asm volatile("iflush %0+4" : : "r" (where));
-}
-
 void
 _rtld_call_ifunc(Obj_Entry *obj, sigset_t *mask, u_int cur_objgen)
 {
@@ -444,7 +421,7 @@ _rtld_call_ifunc(Obj_Entry *obj, sigset_
 		_rtld_exclusive_exit(mask);
 		target = _rtld_resolve_ifunc2(obj, target);
 		_rtld_exclusive_enter(mask);
-		_rtld_write_plt(where, target);
+		sparc_write_branch(where + 1, (void *)target);
 	}
 
 	while (obj->ifunc_remaining_nonplt > 0 && _rtld_objgen == cur_objgen) {
@@ -521,7 +498,7 @@ _rtld_relocate_plt_object(const Obj_Entr
 	rdbg(("bind now/fixup in %s --> new=%p", 
 	    defobj->strtab + def->st_name, (void *)value));
 
-	_rtld_write_plt(where, value);
+	sparc_write_branch(where + 1, (void *)value);
 
 	if (tp)
 		*tp = value;

Index: src/libexec/ld.elf_so/arch/sparc64/mdreloc.c
diff -u src/libexec/ld.elf_so/arch/sparc64/mdreloc.c:1.67 src/libexec/ld.elf_so/arch/sparc64/mdreloc.c:1.68
--- src/libexec/ld.elf_so/arch/sparc64/mdreloc.c:1.67	Mon Dec 25 17:00:15 2017
+++ src/libexec/ld.elf_so/arch/sparc64/mdreloc.c	Thu Mar 29 13:23:39 2018
@@ -1,4 +1,4 @@
-/*	$NetBSD: mdreloc.c,v 1.67 2017/12/25 17:00:15 joerg Exp $	*/
+/*	$NetBSD: mdreloc.c,v 1.68 2018/03/29 13:23:39 joerg Exp $	*/
 
 /*-
  * Copyright (c) 2000 Eduardo Horvath.
@@ -32,9 +32,11 @@
 
 #include <sys/cdefs.h>
 #ifndef lint
-__RCSID("$NetBSD: mdreloc.c,v 1.67 2017/12/25 17:00:15 joerg Exp $");
+__RCSID("$NetBSD: mdreloc.c,v 1.68 2018/03/29 13:23:39 joerg Exp $");
 #endif /* not lint */
 
+#include <machine/elf_support.h>
+
 #include <errno.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -192,19 +194,6 @@ static const long reloc_target_bitmask[]
 /*
  * Instruction templates:
  */
-#define	BAA	0x30680000	/*	ba,a	%xcc, 0 */
-#define	SETHI	0x03000000	/*	sethi	%hi(0), %g1 */
-#define	JMP	0x81c06000	/*	jmpl	%g1+%lo(0), %g0 */
-#define	NOP	0x01000000	/*	sethi	%hi(0), %g0 */
-#define	OR	0x82106000	/*	or	%g1, 0, %g1 */
-#define	XOR	0x82186000	/*	xor	%g1, 0, %g1 */
-#define	MOV71	0x8213e000	/*	or	%o7, 0, %g1 */
-#define	MOV17	0x9e106000	/*	or	%g1, 0, %o7 */
-#define	CALL	0x40000000	/*	call	0 */
-#define	SLLX	0x83287000	/*	sllx	%g1, 0, %g1 */
-#define	NEG	0x82200001	/*	neg	%g1 */
-#define	SETHIG5	0x0b000000	/*	sethi	%hi(0), %g5 */
-#define	ORG5	0x82104005	/*	or	%g1, %g5, %g1 */
 
 
 /* %hi(v)/%lo(v) with variable shift */
@@ -589,34 +578,6 @@ static inline void
 _rtld_write_plt(Elf_Word *where, Elf_Addr value, const Elf_Rela *rela,
     const Obj_Entry *obj)
 {
-	Elf_Addr offset, offBAA;
-
-	/*
-	 * At the PLT entry pointed at by `where', we now construct a direct
-	 * transfer to the now fully resolved function address.
-	 *
-	 * A PLT entry is supposed to start by looking like this:
-	 *
-	 *	sethi	%hi(. - .PLT0), %g1
-	 *	ba,a	%xcc, .PLT1
-	 *	nop
-	 *	nop
-	 *	nop
-	 *	nop
-	 *	nop
-	 *	nop
-	 *
-	 * When we replace these entries we start from the last instruction
-	 * and do it in reverse order so the last thing we do is replace the
-	 * branch.  That allows us to change this atomically.
-	 *
-	 * We now need to find out how far we need to jump.  We have a choice
-	 * of several different relocation techniques which are increasingly
-	 * expensive.
-	 */
-
-	offset = ((Elf_Addr)where) - value;
-	offBAA = value - (((Elf_Addr)where) + 4);	/* ba,a at where[1] */
 	if (rela && rela->r_addend) {
 		Elf_Addr *ptr = (Elf_Addr *)where;
 		/*
@@ -625,169 +586,8 @@ _rtld_write_plt(Elf_Word *where, Elf_Add
 		 * PLT section.  Update it to point to the target function.
 		 */
 		ptr[0] += value - (Elf_Addr)obj->pltgot;
-	} else if (offBAA <= (1L<<20) && (Elf_SOff)offBAA >= -(1L<<20)) {
-		/* 
-		 * We're within 1MB -- we can use a direct branch insn.
-		 *
-		 * We can generate this pattern:
-		 *
-		 *	sethi	%hi(. - .PLT0), %g1
-		 *	ba,a	%xcc, addr
-		 *	nop
-		 *	nop
-		 *	nop
-		 *	nop
-		 *	nop
-		 *	nop
-		 *
-		 */
-		where[1] = BAA | ((offBAA >> 2) & 0x7ffff);
-		__asm volatile("iflush %0+4" : : "r" (where));
-	} else if (value < (1L<<32)) {
-		/* 
-		 * We're within 32-bits of address zero.
-		 *
-		 * The resulting code in the jump slot is:
-		 *
-		 *	sethi	%hi(. - .PLT0), %g1
-		 *	sethi	%hi(addr), %g1
-		 *	jmp	%g1+%lo(addr)
-		 *	nop
-		 *	nop
-		 *	nop
-		 *	nop
-		 *	nop
-		 *
-		 */
-		where[2] = JMP   | LOVAL(value, 0);
-		where[1] = SETHI | HIVAL(value, 10);
-		__asm volatile("iflush %0+8" : : "r" (where));
-		__asm volatile("iflush %0+4" : : "r" (where));
-	} else if ((Elf_SOff)value <= 0 && (Elf_SOff)value > -(1L<<32)) {
-		/* 
-		 * We're within 32-bits of address -1.
-		 *
-		 * The resulting code in the jump slot is:
-		 *
-		 *	sethi	%hi(. - .PLT0), %g1
-		 *	sethi	%hix(addr), %g1
-		 *	xor	%g1, %lox(addr), %g1
-		 *	jmp	%g1
-		 *	nop
-		 *	nop
-		 *	nop
-		 *	nop
-		 *
-		 */
-		where[3] = JMP;
-		where[2] = XOR | (value & 0x00003ff) | 0x1c00;
-		where[1] = SETHI | HIVAL(~value, 10);
-		__asm volatile("iflush %0+12" : : "r" (where));
-		__asm volatile("iflush %0+8" : : "r" (where));
-		__asm volatile("iflush %0+4" : : "r" (where));
-	} else if ((offset+8) <= (1L<<31) &&
-	    (Elf_SOff)(offset+8) >= -((1L<<31) - 4)) {
-		/* 
-		 * We're within 32-bits -- we can use a direct call insn 
-		 *
-		 * The resulting code in the jump slot is:
-		 *
-		 *	sethi	%hi(. - .PLT0), %g1
-		 *	mov	%o7, %g1
-		 *	call	(.+offset)
-		 *	 mov	%g1, %o7
-		 *	nop
-		 *	nop
-		 *	nop
-		 *	nop
-		 *
-		 */
-		offset += 8;	/* call is at where[2], 8 byte further */
-		where[3] = MOV17;
-		where[2] = CALL	  | ((-offset >> 2) & 0x3fffffff);
-		where[1] = MOV71;
-		__asm volatile("iflush %0+12" : : "r" (where));
-		__asm volatile("iflush %0+8" : : "r" (where));
-		__asm volatile("iflush %0+4" : : "r" (where));
-	} else if ((Elf_SOff)value > 0 && value < (1L<<44)) {
-		/* 
-		 * We're within 44 bits.  We can generate this pattern:
-		 *
-		 * The resulting code in the jump slot is:
-		 *
-		 *	sethi	%hi(. - .PLT0), %g1
-		 *	sethi	%h44(addr), %g1
-		 *	or	%g1, %m44(addr), %g1
-		 *	sllx	%g1, 12, %g1	
-		 *	jmp	%g1+%l44(addr)	
-		 *	nop
-		 *	nop
-		 *	nop
-		 *
-		 */
-		where[4] = JMP   | LOVAL(value, 0);
-		where[3] = SLLX  | 12;
-		where[2] = OR    | (((value) >> 12) & 0x00001fff);
-		where[1] = SETHI | HIVAL(value, 22);
-		__asm volatile("iflush %0+16" : : "r" (where));
-		__asm volatile("iflush %0+12" : : "r" (where));
-		__asm volatile("iflush %0+8" : : "r" (where));
-		__asm volatile("iflush %0+4" : : "r" (where));
-	} else if ((Elf_SOff)value < 0 && (Elf_SOff)value > -(1L<<44)) {
-		/*
-		 *  We're within 44 bits.  We can generate this pattern:
-		 *
-		 * The resulting code in the jump slot is:
-		 *
-		 *	sethi	%hi(. - .PLT0), %g1
-		 *	sethi	%hi((-addr)>>12), %g1
-		 *	or	%g1, %lo((-addr)>>12), %g1
-		 *	neg	%g1
-		 *	sllx	%g1, 12, %g1
-		 *	jmp	%g1+(addr&0x0fff)
-		 *	nop
-		 *	nop
-		 *
-		 */
-		Elf_Addr neg = (~value+1)>>12;
-		where[5] = JMP   | (value & 0x0fff);
-		where[4] = SLLX  | 12;
-		where[3] = NEG;
-		where[2] = OR    | (LOVAL(neg, 0)+1);
-		where[1] = SETHI | HIVAL(neg, 10);
-		__asm volatile("iflush %0+20" : : "r" (where));
-		__asm volatile("iflush %0+16" : : "r" (where));
-		__asm volatile("iflush %0+12" : : "r" (where));
-		__asm volatile("iflush %0+8" : : "r" (where));
-		__asm volatile("iflush %0+4" : : "r" (where));
 	} else {
-		/* 
-		 * We need to load all 64-bits
-		 *
-		 * The resulting code in the jump slot is:
-		 *
-		 *	sethi	%hi(. - .PLT0), %g1
-		 *	sethi	%hh(addr), %g1
-		 *	sethi	%lm(addr), %g5
-		 *	or	%g1, %hm(addr), %g1
-		 *	sllx	%g1, 32, %g1
-		 *	or	%g1, %g5, %g1
-		 *	jmp	%g1+%lo(addr)
-		 *	nop
-		 *
-		 */
-		where[6] = JMP     | LOVAL(value, 0);
-		where[5] = ORG5;
-		where[4] = SLLX    | 32;
-		where[3] = OR      | LOVAL(value, 32);
-		where[2] = SETHIG5 | HIVAL(value, 10);
-		where[1] = SETHI   | HIVAL(value, 42);
-		__asm volatile("iflush %0+24" : : "r" (where));
-		__asm volatile("iflush %0+20" : : "r" (where));
-		__asm volatile("iflush %0+16" : : "r" (where));
-		__asm volatile("iflush %0+12" : : "r" (where));
-		__asm volatile("iflush %0+8" : : "r" (where));
-		__asm volatile("iflush %0+4" : : "r" (where));
+		sparc_write_branch(where + 1, (void *)value);
 	}
 }
 
@@ -851,7 +651,7 @@ _rtld_call_ifunc(Obj_Entry *obj, sigset_
 		_rtld_exclusive_exit(mask);
 		target = _rtld_resolve_ifunc2(obj, target);
 		_rtld_exclusive_enter(mask);
-		_rtld_write_plt(where2, target, NULL, obj);
+		sparc_write_branch(where2 + 1, (void *)target);
 	}
 
 	while (obj->ifunc_remaining_nonplt > 0 && _rtld_objgen == cur_objgen) {

Index: src/sys/arch/sparc/include/Makefile
diff -u src/sys/arch/sparc/include/Makefile:1.33 src/sys/arch/sparc/include/Makefile:1.34
--- src/sys/arch/sparc/include/Makefile:1.33	Wed Jul 23 18:19:45 2014
+++ src/sys/arch/sparc/include/Makefile	Thu Mar 29 13:23:39 2018
@@ -1,4 +1,4 @@
-#	$NetBSD: Makefile,v 1.33 2014/07/23 18:19:45 alnsn Exp $
+#	$NetBSD: Makefile,v 1.34 2018/03/29 13:23:39 joerg Exp $
 
 INCSDIR= /usr/include/sparc
 
@@ -6,7 +6,7 @@ INCS=	ansi.h aout_machdep.h apmvar.h asm
 	bswap.h bootinfo.h \
 	cdefs.h cgtworeg.h cpu.h cpuconf.h \
 	disklabel.h \
-	eeprom.h elf_machdep.h endian.h endian_machdep.h \
+	eeprom.h elf_machdep.h elf_support.h endian.h endian_machdep.h \
 	fenv.h float.h frame.h fsr.h \
 	idprom.h ieee.h ieeefp.h \
 	int_const.h int_fmtio.h int_limits.h int_mwgwtypes.h int_types.h \

Index: src/sys/arch/sparc64/include/Makefile
diff -u src/sys/arch/sparc64/include/Makefile:1.30 src/sys/arch/sparc64/include/Makefile:1.31
--- src/sys/arch/sparc64/include/Makefile:1.30	Wed Jul 23 18:19:45 2014
+++ src/sys/arch/sparc64/include/Makefile	Thu Mar 29 13:23:40 2018
@@ -1,4 +1,4 @@
-#	$NetBSD: Makefile,v 1.30 2014/07/23 18:19:45 alnsn Exp $
+#	$NetBSD: Makefile,v 1.31 2018/03/29 13:23:40 joerg Exp $
 
 INCSDIR= /usr/include/sparc64
 
@@ -6,7 +6,7 @@ INCS=	ansi.h aout_machdep.h asm.h autoco
 	bswap.h bsd_openprom.h \
 	cdefs.h cgtworeg.h cpu.h ctlreg.h \
 	disklabel.h \
-	eeprom.h elf_machdep.h endian.h endian_machdep.h \
+	eeprom.h elf_machdep.h elf_support.h endian.h endian_machdep.h \
 	fenv.h float.h frame.h fsr.h \
 	idprom.h ieee.h ieeefp.h instr.h intr.h \
 	int_const.h int_fmtio.h int_limits.h int_mwgwtypes.h int_types.h \

Added files:

Index: src/sys/arch/sparc/include/elf_support.h
diff -u /dev/null src/sys/arch/sparc/include/elf_support.h:1.1
--- /dev/null	Thu Mar 29 13:23:40 2018
+++ src/sys/arch/sparc/include/elf_support.h	Thu Mar 29 13:23:39 2018
@@ -0,0 +1,64 @@
+/*	$NetBSD: elf_support.h,v 1.1 2018/03/29 13:23:39 joerg Exp $	*/
+
+/*-
+ * Copyright (c) 2018 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef _SPARC_ELF_SUPPORT_H
+#define _SPARC_ELF_SUPPORT_H
+
+static inline void
+sparc_write_branch(void *where_, void *target)
+{
+	const unsigned int BAA     = 0x30800000U; /* ba,a  (offset / 4) */
+	const unsigned int SETHI   = 0x03000000U; /* sethi %hi(0), %g1 */
+	const unsigned int JMP     = 0x81c06000U; /* jmpl  %g1+%lo(0), %g0 */
+
+	unsigned int *where = (unsigned int *)where_;
+	unsigned long value = (unsigned long)target;
+	unsigned long offset = value - (unsigned long)where;
+
+#define	HIVAL(v, s)	(((v) >> (s)) & 0x003fffffU)
+#define	LOVAL(v, s)	(((v) >> (s)) & 0x000003ffU)
+	if (offset + 0x800000 <= 0x7ffffc) {
+		/* Displacement is within 8MB, use a direct branch. */
+		where[0] = BAA | ((offset >> 2) & 0x3fffff);
+		__asm volatile("iflush %0+0" : : "r" (where));
+		return;
+	}
+
+	/*
+	 * The absolute address is a 32bit value.
+	 * This can be encoded as:
+	 *	sethi	%hi(value), %g1
+	 *	jmp	%g1+%lo(value)
+	 */
+	where[1] = JMP   | LOVAL(value, 0);
+	__asm volatile("iflush %0+4" : : "r" (where));
+	where[0] = SETHI | HIVAL(value, 10);
+	__asm volatile("iflush %0+0" : : "r" (where));
+#undef	HIVAL
+#undef	LOVAL
+}
+#endif

Index: src/sys/arch/sparc64/include/elf_support.h
diff -u /dev/null src/sys/arch/sparc64/include/elf_support.h:1.1
--- /dev/null	Thu Mar 29 13:23:40 2018
+++ src/sys/arch/sparc64/include/elf_support.h	Thu Mar 29 13:23:40 2018
@@ -0,0 +1,186 @@
+/*	$NetBSD: elf_support.h,v 1.1 2018/03/29 13:23:40 joerg Exp $	*/
+
+/*-
+ * Copyright (c) 2000 Eduardo Horvath.
+ * Copyright (c) 2018 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef _SPARC64_ELF_SUPPORT_H
+#define _SPARC64_ELF_SUPPORT_H
+
+#ifdef __arch64__
+/*
+ * Create a jump to the location `target` starting at `where`.
+ * This requires up to 6 instructions.
+ * The first instruction is written last as it replaces a branch
+ * in the PLT during lazy binding.
+ * The resulting code can trash %g1 and %g5.
+ */
+static inline void
+sparc_write_branch(void *where_, void *target)
+{
+	const unsigned int BAA     = 0x30800000U; /* ba,a  (offset / 4) */
+	const unsigned int SETHI   = 0x03000000U; /* sethi %hi(0), %g1 */
+	const unsigned int JMP     = 0x81c06000U; /* jmpl  %g1+%lo(0), %g0 */
+	const unsigned int OR      = 0x82106000U; /* or    %g1, 0, %g1 */
+	const unsigned int XOR     = 0x82186000U; /* xor   %g1, 0, %g1 */
+	const unsigned int MOV71   = 0x8213e000U; /* or    %o7, 0, %g1 */
+	const unsigned int MOV17   = 0x9e106000U; /* or    %g1, 0, %o7 */
+	const unsigned int CALL    = 0x40000000U; /* call  0 */
+	const unsigned int SLLX    = 0x83287000U; /* sllx  %g1, 0, %g1 */
+	const unsigned int NEG     = 0x82200001U; /* neg   %g1 */
+	const unsigned int SETHIG5 = 0x0b000000U; /* sethi %hi(0), %g5 */
+	const unsigned int ORG5    = 0x82104005U; /* or    %g1, %g5, %g1 */
+
+	unsigned int *where = (unsigned int *)where_;
+	unsigned long value = (unsigned long)target;
+	unsigned long offset = value - (unsigned long)where;
+
+#define	HIVAL(v, s)	(((v) >> (s)) & 0x003fffffU)
+#define	LOVAL(v, s)	(((v) >> (s)) & 0x000003ffU)
+	if (offset + 0x800000 <= 0x7ffffc) {
+		/* Displacement is within 8MB, use a direct branch. */
+		where[0] = BAA | ((offset >> 2) & 0x3fffff);
+		__asm volatile("iflush %0+0" : : "r" (where));
+		return;
+	}
+
+	if (value <= 0xffffffffUL) {
+		/*
+		 * The absolute address is a 32bit value.
+		 * This can be encoded as:
+		 *	sethi	%hi(value), %g1
+		 *	jmp	%g1+%lo(value)
+		 */
+		where[1] = JMP   | LOVAL(value, 0);
+		__asm volatile("iflush %0+4" : : "r" (where));
+		where[0] = SETHI | HIVAL(value, 10);
+		__asm volatile("iflush %0+0" : : "r" (where));
+		return;
+	}
+
+	if (value >= 0xffffffff00000000UL) {
+		/*
+		 * The top 32bit address range can be encoded as:
+		 *	sethi	%hix(addr), %g1
+		 *	xor	%g1, %lox(addr), %g1
+		 *	jmp	%g1
+		 */
+		where[2] = JMP;
+		where[1] = XOR | (value & 0x00003ff) | 0x1c00;
+		__asm volatile("iflush %0+4" : : "r" (where));
+		__asm volatile("iflush %0+8" : : "r" (where));
+		where[0] = SETHI | HIVAL(~value, 10);
+		__asm volatile("iflush %0+0" : : "r" (where));
+		return;
+	}
+
+	if ((offset + 4) + 0x80000000UL <= 0x100000000UL) {
+		/*
+		 * Displacement of the second instruction is within
+		 * +-2GB. This can use a direct call instruction:
+		 *	mov	%o7, %g1
+		 *	call	(value - .)
+		 *	 mov	%g1, %o7
+		 */
+		where[1] = CALL | ((-(offset + 4)>> 2) & 0x3fffffffU);
+		where[2] = MOV17;
+		__asm volatile("iflush %0+4" : : "r" (where));
+		__asm volatile("iflush %0+8" : : "r" (where));
+		where[0] = MOV71;
+		__asm volatile("iflush %0+0" : : "r" (where));
+		return;
+	}
+
+	if (value < 0x100000000000UL) {
+		/*
+		 * The absolute address is a 44bit value.
+		 * This can be encoded as:
+		 *	sethi	%h44(addr), %g1
+		 *	or	%g1, %m44(addr), %g1
+		 *	sllx	%g1, 12, %g1
+		 *	jmp	%g1+%l44(addr)
+		 */
+		where[1] = OR    | (((value) >> 12) & 0x00001fff);
+		where[2] = SLLX  | 12;
+		where[3] = JMP   | LOVAL(value, 0);
+		__asm volatile("iflush %0+4" : : "r" (where));
+		__asm volatile("iflush %0+8" : : "r" (where));
+		__asm volatile("iflush %0+12" : : "r" (where));
+		where[0] = SETHI | HIVAL(value, 22);
+		__asm volatile("iflush %0+0" : : "r" (where));
+		return;
+	}
+
+	if (value > 0xfffff00000000000UL) {
+		/*
+		 * The top 44bit address range can be encoded as:
+		 *	sethi	%hi((-addr)>>12), %g1
+		 *	or	%g1, %lo((-addr)>>12), %g1
+		 *	neg	%g1
+		 *	sllx	%g1, 12, %g1
+		 *	jmp	%g1+(addr&0x0fff)
+		 */
+		unsigned long neg = (-value)>>12;
+		where[1] = OR    | (LOVAL(neg, 0)+1);
+		where[2] = NEG;
+		where[3] = SLLX  | 12;
+		where[4] = JMP   | (value & 0x0fff);
+		__asm volatile("iflush %0+4" : : "r" (where));
+		__asm volatile("iflush %0+8" : : "r" (where));
+		__asm volatile("iflush %0+12" : : "r" (where));
+		__asm volatile("iflush %0+16" : : "r" (where));
+		where[0] = SETHI | HIVAL(neg, 10);
+		__asm volatile("iflush %0+0" : : "r" (where));
+		return;
+	}
+
+	/*
+	 * The general case of a 64bit address is encoded as:
+	 *	sethi	%hh(addr), %g1
+	 *	sethi	%lm(addr), %g5
+	 *	or	%g1, %hm(addr), %g1
+	 *	sllx	%g1, 32, %g1
+	 *	or	%g1, %g5, %g1
+	 *	jmp	%g1+%lo(addr)
+	 */
+	where[1] = SETHIG5 | HIVAL(value, 10);
+	where[2] = OR      | LOVAL(value, 32);
+	where[3] = SLLX    | 32;
+	where[4] = ORG5;
+	where[5] = JMP     | LOVAL(value, 0);
+	__asm volatile("iflush %0+4" : : "r" (where));
+	__asm volatile("iflush %0+8" : : "r" (where));
+	__asm volatile("iflush %0+12" : : "r" (where));
+	__asm volatile("iflush %0+16" : : "r" (where));
+	__asm volatile("iflush %0+20" : : "r" (where));
+	where[0] = SETHI   | HIVAL(value, 42);
+	__asm volatile("iflush %0+0" : : "r" (where));
+#undef	HIVAL
+#undef	LOVAL
+}
+#else
+#include <sparc/elf_support.h>
+#endif
+#endif

Reply via email to