24 changed files with 257 additions and 327 deletions
@ -0,0 +1,145 @@ |
|||
/* Private floating point rounding and exceptions handling. RISC-V version.
|
|||
Copyright (C) 2014-2015 Free Software Foundation, Inc. |
|||
This file is part of the GNU C Library. |
|||
|
|||
The GNU C Library is free software; you can redistribute it and/or |
|||
modify it under the terms of the GNU Lesser General Public |
|||
License as published by the Free Software Foundation; either |
|||
version 2.1 of the License, or (at your option) any later version. |
|||
|
|||
The GNU C Library is distributed in the hope that it will be useful, |
|||
but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
|||
Lesser General Public License for more details. |
|||
|
|||
You should have received a copy of the GNU Lesser General Public |
|||
License along with the GNU C Library; if not, see |
|||
<http://www.gnu.org/licenses/>. */
|
|||
|
|||
#ifndef RISCV_MATH_PRIVATE_H |
|||
#define RISCV_MATH_PRIVATE_H 1 |
|||
|
|||
#include <fenv.h> |
|||
#include <fpu_control.h> |
|||
|
|||
static __always_inline void |
|||
libc_feholdexcept_riscv (fenv_t *envp) |
|||
{ |
|||
_FPU_GETCW (*envp); |
|||
_FPU_SETFLAGS (0); |
|||
} |
|||
|
|||
#define libc_feholdexcept libc_feholdexcept_riscv |
|||
#define libc_feholdexceptf libc_feholdexcept_riscv |
|||
#define libc_feholdexceptl libc_feholdexcept_riscv |
|||
|
|||
static __always_inline void |
|||
libc_fesetround_riscv (int round) |
|||
{ |
|||
_FPU_SETROUND (round); |
|||
} |
|||
|
|||
#define libc_fesetround libc_fesetround_riscv |
|||
#define libc_fesetroundf libc_fesetround_riscv |
|||
#define libc_fesetroundl libc_fesetround_riscv |
|||
|
|||
static __always_inline void |
|||
libc_feholdexcept_setround_riscv (fenv_t *envp, int round) |
|||
{ |
|||
libc_fesetround_riscv (round); |
|||
libc_feholdexcept_riscv (envp); |
|||
} |
|||
|
|||
#define libc_feholdexcept_setround libc_feholdexcept_setround_riscv |
|||
#define libc_feholdexcept_setroundf libc_feholdexcept_setround_riscv |
|||
#define libc_feholdexcept_setroundl libc_feholdexcept_setround_riscv |
|||
|
|||
static __always_inline int |
|||
libc_fetestexcept_riscv (int ex) |
|||
{ |
|||
int cw; |
|||
|
|||
_FPU_GETFLAGS (cw); |
|||
|
|||
return cw & ex; |
|||
} |
|||
|
|||
#define libc_fetestexcept libc_fetestexcept_riscv |
|||
#define libc_fetestexceptf libc_fetestexcept_riscv |
|||
#define libc_fetestexceptl libc_fetestexcept_riscv |
|||
|
|||
static __always_inline void |
|||
libc_fesetenv_riscv (const fenv_t *envp) |
|||
{ |
|||
long env = (long) envp - (long) FE_DFL_ENV; |
|||
if (env != 0) |
|||
env = *envp; |
|||
|
|||
_FPU_SETCW (env); |
|||
} |
|||
|
|||
#define libc_fesetenv libc_fesetenv_riscv |
|||
#define libc_fesetenvf libc_fesetenv_riscv |
|||
#define libc_fesetenvl libc_fesetenv_riscv |
|||
#define libc_feresetround_noex libc_fesetenv_riscv |
|||
#define libc_feresetround_noexf libc_fesetenv_riscv |
|||
#define libc_feresetround_noexl libc_fesetenv_riscv |
|||
|
|||
static __always_inline int |
|||
libc_feupdateenv_test_riscv (const fenv_t *envp, int ex) |
|||
{ |
|||
fenv_t env = *envp; |
|||
int excepts; |
|||
|
|||
_FPU_SETROUND (0); |
|||
asm volatile ("csrrs %0, fcsr, %1" : "=r"(excepts) : "r"(env)); |
|||
|
|||
return excepts & ex; |
|||
} |
|||
|
|||
#define libc_feupdateenv_test libc_feupdateenv_test_riscv |
|||
#define libc_feupdateenv_testf libc_feupdateenv_test_riscv |
|||
#define libc_feupdateenv_testl libc_feupdateenv_test_riscv |
|||
|
|||
static __always_inline void |
|||
libc_feupdateenv_riscv (const fenv_t *envp) |
|||
{ |
|||
fenv_t env = *envp; |
|||
|
|||
_FPU_SETROUND (0); |
|||
asm volatile ("csrs fcsr, %0" : : "r"(env)); |
|||
} |
|||
|
|||
#define libc_feupdateenv libc_feupdateenv_riscv |
|||
#define libc_feupdateenvf libc_feupdateenv_riscv |
|||
#define libc_feupdateenvl libc_feupdateenv_riscv |
|||
|
|||
static __always_inline void |
|||
libc_feholdsetround_riscv (fenv_t *envp, int round) |
|||
{ |
|||
/* Note this implementation makes an improperly-formatted fenv_t and
|
|||
so should only be used in conjunction with libc_feresetround. */ |
|||
int old_round; |
|||
asm volatile ("csrrw %0, frm, %1" : "=r"(old_round) : "r"(round)); |
|||
*envp = old_round; |
|||
} |
|||
|
|||
#define libc_feholdsetround libc_feholdsetround_riscv |
|||
#define libc_feholdsetroundf libc_feholdsetround_riscv |
|||
#define libc_feholdsetroundl libc_feholdsetround_riscv |
|||
|
|||
static __always_inline void |
|||
libc_feresetround_riscv (fenv_t *envp) |
|||
{ |
|||
/* Note this implementation takes an improperly-formatted fenv_t and
|
|||
so should only be used in conjunction with libc_feholdsetround. */ |
|||
_FPU_SETROUND (*envp); |
|||
} |
|||
|
|||
#define libc_feresetround libc_feresetround_riscv |
|||
#define libc_feresetroundf libc_feresetround_riscv |
|||
#define libc_feresetroundl libc_feresetround_riscv |
|||
|
|||
#include_next <math_private.h> |
|||
|
|||
#endif |
|||
@ -1,262 +0,0 @@ |
|||
/* Copyright (C) 2011-2014 Free Software Foundation, Inc.
|
|||
This file is part of the GNU C Library. |
|||
|
|||
The GNU C Library is free software; you can redistribute it and/or |
|||
modify it under the terms of the GNU Lesser General Public |
|||
License as published by the Free Software Foundation; either |
|||
version 2.1 of the License, or (at your option) any later version. |
|||
|
|||
The GNU C Library is distributed in the hope that it will be useful, |
|||
but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
|||
Lesser General Public License for more details. |
|||
|
|||
You should have received a copy of the GNU Lesser General Public |
|||
License along with the GNU C Library; if not, write to the Free |
|||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA |
|||
02111-1307 USA. */ |
|||
|
|||
#ifndef _LOWLEVELLOCK_H |
|||
#define _LOWLEVELLOCK_H 1 |
|||
|
|||
#include <time.h> |
|||
#include <sys/param.h> |
|||
#include <bits/pthreadtypes.h> |
|||
#include <atomic.h> |
|||
#include <sysdep.h> |
|||
#include <kernel-features.h> |
|||
|
|||
#define FUTEX_WAIT 0 |
|||
#define FUTEX_WAKE 1 |
|||
#define FUTEX_REQUEUE 3 |
|||
#define FUTEX_CMP_REQUEUE 4 |
|||
#define FUTEX_WAKE_OP 5 |
|||
#define FUTEX_OP_CLEAR_WAKE_IF_GT_ONE ((4 << 24) | 1) |
|||
#define FUTEX_LOCK_PI 6 |
|||
#define FUTEX_UNLOCK_PI 7 |
|||
#define FUTEX_TRYLOCK_PI 8 |
|||
#define FUTEX_WAIT_BITSET 9 |
|||
#define FUTEX_WAKE_BITSET 10 |
|||
#define FUTEX_PRIVATE_FLAG 128 |
|||
#define FUTEX_CLOCK_REALTIME 256 |
|||
|
|||
#define FUTEX_BITSET_MATCH_ANY 0xffffffff |
|||
|
|||
/* Values for 'private' parameter of locking macros. Yes, the
|
|||
definition seems to be backwards. But it is not. The bit will be |
|||
reversed before passing to the system call. */ |
|||
#define LLL_PRIVATE 0 |
|||
#define LLL_SHARED FUTEX_PRIVATE_FLAG |
|||
|
|||
|
|||
#if !defined NOT_IN_libc || defined IS_IN_rtld |
|||
/* In libc.so or ld.so all futexes are private. */ |
|||
# ifdef __ASSUME_PRIVATE_FUTEX |
|||
# define __lll_private_flag(fl, private) \ |
|||
((fl) | FUTEX_PRIVATE_FLAG) |
|||
# else |
|||
# define __lll_private_flag(fl, private) \ |
|||
((fl) | THREAD_GETMEM (THREAD_SELF, header.private_futex)) |
|||
# endif |
|||
#else |
|||
# ifdef __ASSUME_PRIVATE_FUTEX |
|||
# define __lll_private_flag(fl, private) \ |
|||
(((fl) | FUTEX_PRIVATE_FLAG) ^ (private)) |
|||
# else |
|||
# define __lll_private_flag(fl, private) \ |
|||
(__builtin_constant_p (private) \ |
|||
? ((private) == 0 \ |
|||
? ((fl) | THREAD_GETMEM (THREAD_SELF, header.private_futex)) \ |
|||
: (fl)) \ |
|||
: ((fl) | (((private) ^ FUTEX_PRIVATE_FLAG) \ |
|||
& THREAD_GETMEM (THREAD_SELF, header.private_futex)))) |
|||
# endif |
|||
#endif |
|||
|
|||
|
|||
#define lll_futex_wait(futexp, val, private) \ |
|||
lll_futex_timed_wait(futexp, val, NULL, private) |
|||
|
|||
#define lll_futex_timed_wait(futexp, val, timespec, private) \ |
|||
({ \ |
|||
INTERNAL_SYSCALL_DECL (__err); \ |
|||
long int __ret; \ |
|||
__ret = INTERNAL_SYSCALL (futex, __err, 4, (long) (futexp), \ |
|||
__lll_private_flag (FUTEX_WAIT, private), \ |
|||
(val), (timespec)); \ |
|||
INTERNAL_SYSCALL_ERROR_P (__ret, __err) ? -__ret : __ret; \ |
|||
}) |
|||
|
|||
#define lll_futex_wake(futexp, nr, private) \ |
|||
({ \ |
|||
INTERNAL_SYSCALL_DECL (__err); \ |
|||
long int __ret; \ |
|||
__ret = INTERNAL_SYSCALL (futex, __err, 4, (long) (futexp), \ |
|||
__lll_private_flag (FUTEX_WAKE, private), \ |
|||
(nr), 0); \ |
|||
INTERNAL_SYSCALL_ERROR_P (__ret, __err) ? -__ret : __ret; \ |
|||
}) |
|||
|
|||
#define lll_robust_dead(futexv, private) \ |
|||
do \ |
|||
{ \ |
|||
int *__futexp = &(futexv); \ |
|||
atomic_or (__futexp, FUTEX_OWNER_DIED); \ |
|||
lll_futex_wake (__futexp, 1, private); \ |
|||
} \ |
|||
while (0) |
|||
|
|||
/* Returns non-zero if error happened, zero if success. */ |
|||
#define lll_futex_requeue(futexp, nr_wake, nr_move, mutex, val, private) \ |
|||
({ \ |
|||
INTERNAL_SYSCALL_DECL (__err); \ |
|||
long int __ret; \ |
|||
__ret = INTERNAL_SYSCALL (futex, __err, 6, (long) (futexp), \ |
|||
__lll_private_flag (FUTEX_CMP_REQUEUE, private),\ |
|||
(nr_wake), (nr_move), (mutex), (val)); \ |
|||
INTERNAL_SYSCALL_ERROR_P (__ret, __err); \ |
|||
}) |
|||
|
|||
/* Returns non-zero if error happened, zero if success. */ |
|||
#define lll_futex_wake_unlock(futexp, nr_wake, nr_wake2, futexp2, private) \ |
|||
({ \ |
|||
INTERNAL_SYSCALL_DECL (__err); \ |
|||
long int __ret; \ |
|||
\ |
|||
__ret = INTERNAL_SYSCALL (futex, __err, 6, (futexp), \ |
|||
__lll_private_flag (FUTEX_WAKE_OP, private), \ |
|||
(nr_wake), (nr_wake2), (futexp2), \ |
|||
FUTEX_OP_CLEAR_WAKE_IF_GT_ONE); \ |
|||
INTERNAL_SYSCALL_ERROR_P (__ret, __err); \ |
|||
}) |
|||
|
|||
#define lll_trylock(futex) \ |
|||
({ \ |
|||
atomic_compare_and_exchange_val_acq (&(futex), 1, 0) != 0; \ |
|||
}) |
|||
|
|||
#define lll_cond_trylock(futex) \ |
|||
({ \ |
|||
atomic_compare_and_exchange_val_acq (&(futex), 2, 0) != 0; \ |
|||
}) |
|||
|
|||
#define lll_robust_trylock(futex, id) \ |
|||
({ \ |
|||
atomic_compare_and_exchange_val_acq (&(futex), id, 0) != 0; \ |
|||
}) |
|||
|
|||
extern void __lll_lock_wait_private (int *futex) attribute_hidden; |
|||
extern void __lll_lock_wait (int *futex, int private) attribute_hidden; |
|||
extern int __lll_robust_lock_wait (int *futex, int private) attribute_hidden; |
|||
|
|||
#define lll_lock(futex, private) \ |
|||
({ \ |
|||
int val = atomic_compare_and_exchange_val_acq (&(futex), 1, 0); \ |
|||
\ |
|||
if (__builtin_expect (val != 0, 0)) \ |
|||
{ \ |
|||
if (__builtin_constant_p (private) && private == LLL_PRIVATE) \ |
|||
__lll_lock_wait_private (&(futex)); \ |
|||
else \ |
|||
__lll_lock_wait (&(futex), private); \ |
|||
} \ |
|||
}) |
|||
|
|||
#define lll_robust_lock(futex, id, private) \ |
|||
({ \ |
|||
int result = 0; \ |
|||
if (atomic_compare_and_exchange_bool_acq (&(futex), id, 0) != 0) \ |
|||
result = __lll_robust_lock_wait (&(futex), private); \ |
|||
result; \ |
|||
}) |
|||
|
|||
#define lll_cond_lock(futex, private) \ |
|||
({ \ |
|||
int val = atomic_compare_and_exchange_val_acq (&(futex), 2, 0); \ |
|||
\ |
|||
if (__builtin_expect (val != 0, 0)) \ |
|||
__lll_lock_wait (&(futex), private); \ |
|||
}) |
|||
|
|||
#define lll_robust_cond_lock(futex, id, private) \ |
|||
lll_robust_lock (futex, (id) | FUTEX_WAITERS, private) |
|||
|
|||
|
|||
extern int __lll_timedlock_wait (int *futex, const struct timespec *, |
|||
int private) attribute_hidden; |
|||
extern int __lll_robust_timedlock_wait (int *futex, const struct timespec *, |
|||
int private) attribute_hidden; |
|||
|
|||
#define lll_timedlock(futex, abstime, private) \ |
|||
({ \ |
|||
int val = atomic_compare_and_exchange_val_acq (&(futex), 1, 0); \ |
|||
int result = 0; \ |
|||
\ |
|||
if (__builtin_expect (val != 0, 0)) \ |
|||
result = __lll_timedlock_wait (&(futex), abstime, private); \ |
|||
result; \ |
|||
}) |
|||
|
|||
#define lll_robust_timedlock(futex, abstime, id, private) \ |
|||
({ \ |
|||
int result = 0; \ |
|||
if (atomic_compare_and_exchange_bool_acq (&(futex), id, 0) != 0) \ |
|||
result = __lll_robust_timedlock_wait (&(futex), abstime, private); \ |
|||
result; \ |
|||
}) |
|||
|
|||
#define lll_unlock(lock, private) \ |
|||
((void) ({ \ |
|||
int *__futex = &(lock); \ |
|||
int __val = atomic_exchange_rel (__futex, 0); \ |
|||
if (__builtin_expect (__val > 1, 0)) \ |
|||
lll_futex_wake (__futex, 1, private); \ |
|||
})) |
|||
|
|||
#define lll_robust_unlock(lock, private) \ |
|||
((void) ({ \ |
|||
int *__futex = &(lock); \ |
|||
int __val = atomic_exchange_rel (__futex, 0); \ |
|||
if (__builtin_expect (__val & FUTEX_WAITERS, 0)) \ |
|||
lll_futex_wake (__futex, 1, private); \ |
|||
})) |
|||
|
|||
#define lll_islocked(futex) \ |
|||
(futex != 0) |
|||
|
|||
|
|||
/* Our internal lock implementation is identical to the binary-compatible
|
|||
mutex implementation. */ |
|||
|
|||
/* Initializers for lock. */ |
|||
#define LLL_LOCK_INITIALIZER (0) |
|||
#define LLL_LOCK_INITIALIZER_LOCKED (1) |
|||
|
|||
/* The states of a lock are:
|
|||
0 - untaken |
|||
1 - taken by one user |
|||
>1 - taken by more users */ |
|||
|
|||
/* The kernel notifies a process which uses CLONE_CLEARTID via futex
|
|||
wakeup when the clone terminates. The memory location contains the |
|||
thread ID while the clone is running and is reset to zero |
|||
afterwards. */ |
|||
#define lll_wait_tid(tid) \ |
|||
do { \ |
|||
__typeof (tid) __tid; \ |
|||
while ((__tid = (tid)) != 0) \ |
|||
lll_futex_wait (&(tid), __tid, LLL_SHARED); \ |
|||
} while (0) |
|||
|
|||
extern int __lll_timedwait_tid (int *, const struct timespec *) |
|||
attribute_hidden; |
|||
|
|||
#define lll_timedwait_tid(tid, abstime) \ |
|||
({ \ |
|||
int __res = 0; \ |
|||
if ((tid) != 0) \ |
|||
__res = __lll_timedwait_tid (&(tid), (abstime)); \ |
|||
__res; \ |
|||
}) |
|||
|
|||
#endif /* lowlevellock.h */ |
|||
@ -0,0 +1,51 @@ |
|||
/* Override generic sotruss-lib.c to define actual functions for RISC-V.
|
|||
Copyright (C) 2012-2015 Free Software Foundation, Inc. |
|||
This file is part of the GNU C Library. |
|||
|
|||
The GNU C Library is free software; you can redistribute it and/or |
|||
modify it under the terms of the GNU Lesser General Public |
|||
License as published by the Free Software Foundation; either |
|||
version 2.1 of the License, or (at your option) any later version. |
|||
|
|||
The GNU C Library is distributed in the hope that it will be useful, |
|||
but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
|||
Lesser General Public License for more details. |
|||
|
|||
You should have received a copy of the GNU Lesser General Public |
|||
License along with the GNU C Library. If not, see |
|||
<http://www.gnu.org/licenses/>. */
|
|||
|
|||
#define HAVE_ARCH_PLTENTER |
|||
#define HAVE_ARCH_PLTEXIT |
|||
|
|||
#include <elf/sotruss-lib.c> |
|||
|
|||
ElfW(Addr) |
|||
la_riscv_gnu_pltenter (ElfW(Sym) *sym __attribute__ ((unused)), |
|||
unsigned int ndx __attribute__ ((unused)), |
|||
uintptr_t *refcook, uintptr_t *defcook, |
|||
La_riscv_regs *regs, unsigned int *flags, |
|||
const char *symname, long int *framesizep) |
|||
{ |
|||
print_enter (refcook, defcook, symname, |
|||
regs->lr_reg[0], regs->lr_reg[1], regs->lr_reg[2], |
|||
*flags); |
|||
|
|||
/* No need to copy anything, we will not need the parameters in any case. */ |
|||
*framesizep = 0; |
|||
|
|||
return sym->st_value; |
|||
} |
|||
|
|||
unsigned int |
|||
la_riscv_gnu_pltexit (ElfW(Sym) *sym, unsigned int ndx, uintptr_t *refcook, |
|||
uintptr_t *defcook, |
|||
const struct La_riscv_regs *inregs, |
|||
struct La_riscv_retval *outregs, |
|||
const char *symname) |
|||
{ |
|||
print_exit (refcook, defcook, symname, outregs->lrv_a0); |
|||
|
|||
return 0; |
|||
} |
|||
@ -0,0 +1 @@ |
|||
DEFAULT GLIBC_2.20 |
|||
Loading…
Reference in new issue