summaryrefslogblamecommitdiff
path: root/src/thread/sh/__set_thread_area.c
blob: 9c47f78d1accf1aa4dbf1015fc5bab8025b30946 (plain) (tree)
1
2
3
4
5
6
7
8
9

                         




                                   
                            
 







                                                                                       





                                                                     
                                     




                                                                               
                                              
                               

         



                                              


                 
#include "pthread_impl.h"
#include "libc.h"
#include <elf.h>

/* Also perform sh-specific init */

#define CPU_HAS_LLSC 0x0040
#define CPU_HAS_CAS_L 0x0400

__attribute__((__visibility__("hidden")))
extern const char __sh_cas_gusa[], __sh_cas_llsc[], __sh_cas_imask[], __sh_cas_cas_l[];

__attribute__((__visibility__("hidden")))
const void *__sh_cas_ptr;

__attribute__((__visibility__("hidden")))
unsigned __sh_nommu;

int __set_thread_area(void *p)
{
	size_t *aux;
	__asm__ __volatile__ ( "ldc %0, gbr" : : "r"(p) : "memory" );
#ifndef __SH4A__
	__sh_cas_ptr = __sh_cas_gusa;
#if !defined(__SH3__) && !defined(__SH4__)
	for (aux=libc.auxv; *aux; aux+=2) {
		if (*aux != AT_PLATFORM) continue;
		const char *s = (void *)aux[1];
		if (s[0]!='s' || s[1]!='h' || s[2]!='2' || s[3]-'0'<10u) break;
		__sh_cas_ptr = __sh_cas_imask;
		__sh_nommu = 1;
	}
#endif
	if (__hwcap & CPU_HAS_CAS_L)
		__sh_cas_ptr = __sh_cas_cas_l;
	else if (__hwcap & CPU_HAS_LLSC)
		__sh_cas_ptr = __sh_cas_llsc;
#endif
	return 0;
}