| From 1ec63d4d2358f97e6a184987660ec1a4a58fe723 Mon Sep 17 00:00:00 2001 |
| From: Stephen McGruer <smcgruer@google.com> |
| Date: Wed, 17 Jun 2015 14:39:19 -0400 |
| Subject: [PATCH] uclibc: updates for Chromium |
| |
| + pull in part of: |
| http://lists.busybox.net/pipermail/buildroot/2015-March/123387.html |
| to add fmaxf/fminf |
| |
| + pull in |
| http://git.uclibc.org/uClibc/commit/?id=a8dc90eaaa5e6474beac828558d969b1aafee4af |
| to add context methods |
| |
| + enable UCLIBC_SUSV3_LEGACY and UCLIBC_HAS_CONTEXT_FUNCS for |
| getcontext/setcontent |
| --- |
| ...bc-0069-Add-missing-C99-float-ld-wrappers.patch | 870 +++++++ |
| ...t-set-swap-make-context-user-context-mani.patch | 2550 ++++++++++++++++++++ |
| package/uclibc/uclibc.mk | 2 + |
| 3 files changed, 3422 insertions(+) |
| create mode 100644 package/uclibc/0.9.33.2/uclibc-0069-Add-missing-C99-float-ld-wrappers.patch |
| create mode 100644 package/uclibc/0.9.33.2/uclibc-0070-libc-add-get-set-swap-make-context-user-context-mani.patch |
| |
| diff --git a/package/uclibc/0.9.33.2/uclibc-0069-Add-missing-C99-float-ld-wrappers.patch b/package/uclibc/0.9.33.2/uclibc-0069-Add-missing-C99-float-ld-wrappers.patch |
| new file mode 100644 |
| index 0000000..35cf3e4 |
| --- /dev/null |
| +++ b/package/uclibc/0.9.33.2/uclibc-0069-Add-missing-C99-float-ld-wrappers.patch |
| @@ -0,0 +1,870 @@ |
| +From 6c4538905e65ceb203f59aaa9a61728e81c6bc0a Mon Sep 17 00:00:00 2001 |
| +From: Bernhard Reutner-Fischer <rep.dot.nop at gmail.com> |
| +Date: Wed, 18 Mar 2015 21:32:22 +0000 |
| +Subject: libm: Add missing C99 float/ld wrappers |
| + |
| +Signed-off-by: Bernhard Reutner-Fischer <rep.dot.nop at gmail.com> |
| + |
| +Status: upstream [uClibc] |
| +http://git.uclibc.org/uClibc/commit/?id=6c4538905e65ceb203f59aaa9a61728e81c6bc0a |
| + |
| +Removed patch for ./TODO. |
| +Needed to avoid run-time errors with mesa3d which depends on fminf |
| + |
| +Signed-off-by: Bernd Kuhls <bernd.kuhls at t-online.de> |
| +--- |
| +diff --git a/include/complex.h b/include/complex.h |
| +index 91efc0d..ed7e502 100644 |
| +--- a/include/complex.h |
| ++++ b/include/complex.h |
| +@@ -79,6 +79,7 @@ __BEGIN_DECLS |
| + #endif |
| + #include <bits/cmathcalls.h> |
| + #undef _Mdouble_ |
| ++#undef _Mfloat_ |
| + #undef __MATH_PRECNAME |
| + |
| + /* And the long double versions. It is non-critical to define them |
| +@@ -97,6 +98,7 @@ __BEGIN_DECLS |
| + # include <bits/cmathcalls.h> |
| + #endif |
| + #undef _Mdouble_ |
| ++#undef _Mlong_double_ |
| + #undef __MATH_PRECNAME |
| + #undef __MATHDECL_1 |
| + #undef __MATHDECL |
| +diff --git a/include/math.h b/include/math.h |
| +index ecb9aa6..1b54c9e 100644 |
| +--- a/include/math.h |
| ++++ b/include/math.h |
| +@@ -129,6 +129,7 @@ __BEGIN_DECLS |
| + # undef _Mdouble_ |
| + # undef _Mdouble_BEGIN_NAMESPACE |
| + # undef _Mdouble_END_NAMESPACE |
| ++# undef _Mfloat_ |
| + # undef __MATH_PRECNAME |
| + # undef __MATH_maybe_libm_hidden_proto |
| + |
| +@@ -176,6 +177,7 @@ extern long double __REDIRECT_NTH (nexttowardl, (long double __x, long double __ |
| + # undef _Mdouble_ |
| + # undef _Mdouble_BEGIN_NAMESPACE |
| + # undef _Mdouble_END_NAMESPACE |
| ++# undef _Mlong_double_ |
| + # undef __MATH_PRECNAME |
| + # undef __MATH_maybe_libm_hidden_proto |
| + |
| +diff --git a/libc/sysdeps/linux/common/bits/mathcalls.h b/libc/sysdeps/linux/common/bits/mathcalls.h |
| +index 84b793c..9bebb51 100644 |
| +--- a/libc/sysdeps/linux/common/bits/mathcalls.h |
| ++++ b/libc/sysdeps/linux/common/bits/mathcalls.h |
| +@@ -74,8 +74,22 @@ __MATHCALLI (atan2,, (_Mdouble_ __y, _Mdouble_ __x)) |
| + |
| + /* Cosine of X. */ |
| + __MATHCALLI (cos,, (_Mdouble_ __x)) |
| ++# if defined _LIBC && defined _Mlong_double_ |
| ++libm_hidden_proto(cosl) |
| ++# endif |
| ++# if defined _LIBC && defined _Mfloat_ |
| ++libm_hidden_proto(cosf) |
| ++# endif |
| ++ |
| + /* Sine of X. */ |
| + __MATHCALLI (sin,, (_Mdouble_ __x)) |
| ++# if defined _LIBC && defined _Mlong_double_ |
| ++libm_hidden_proto(sinl) |
| ++# endif |
| ++# if defined _LIBC && defined _Mfloat_ |
| ++libm_hidden_proto(sinf) |
| ++# endif |
| ++ |
| + /* Tangent of X. */ |
| + __MATHCALLI (tan,, (_Mdouble_ __x)) |
| + |
| +@@ -111,6 +125,9 @@ __END_NAMESPACE_C99 |
| + _Mdouble_BEGIN_NAMESPACE |
| + /* Exponential function of X. */ |
| + __MATHCALLI (exp,, (_Mdouble_ __x)) |
| ++# if defined _LIBC && defined _Mlong_double_ |
| ++libm_hidden_proto(expl) |
| ++# endif |
| + |
| + /* Break VALUE into a normalized fraction and an integral power of 2. */ |
| + __MATHCALLI (frexp,, (_Mdouble_ __x, int *__exponent)) |
| +@@ -173,6 +190,9 @@ _Mdouble_END_NAMESPACE |
| + __BEGIN_NAMESPACE_C99 |
| + /* Return `sqrt(X*X + Y*Y)'. */ |
| + __MATHCALLI (hypot,, (_Mdouble_ __x, _Mdouble_ __y)) |
| ++# if defined _LIBC && defined _Mlong_double_ |
| ++libm_hidden_proto(hypotl) |
| ++# endif |
| + __END_NAMESPACE_C99 |
| + #endif |
| + |
| +@@ -298,6 +318,9 @@ __MATHCALLI (rint,, (_Mdouble_ __x)) |
| + |
| + /* Return X + epsilon if X < Y, X - epsilon if X > Y. */ |
| + __MATHCALLX (nextafter,, (_Mdouble_ __x, _Mdouble_ __y), (__const__)) |
| ++# if defined _LIBC && defined _Mlong_double_ |
| ++libm_hidden_proto(nextafterl) |
| ++# endif |
| + # if defined __USE_ISOC99 && !defined __LDBL_COMPAT |
| + __MATHCALLX (nexttoward,, (_Mdouble_ __x, long double __y), (__const__)) |
| + # endif |
| +diff --git a/libm/Makefile.in b/libm/Makefile.in |
| +index 7511706..d886cdb 100644 |
| +--- a/libm/Makefile.in |
| ++++ b/libm/Makefile.in |
| +@@ -75,9 +75,6 @@ libm_CSRC := \ |
| + s_remquo.c w_exp2.c \ |
| + cexp.c sincos.c |
| + |
| +-# Not implemented [yet?], see comment in float_wrappers.c: |
| +-# fdimf.o fmaf.o fmaxf.o fminf.o |
| +-# nearbyintf.o remquof.o scalblnf.o tgammaf.o |
| + FL_MOBJ := \ |
| + acosf.o \ |
| + acoshf.o \ |
| +@@ -98,7 +95,11 @@ FL_MOBJ := \ |
| + expf.o \ |
| + expm1f.o \ |
| + fabsf.o \ |
| ++ fdimf.o \ |
| + floorf.o \ |
| ++ fmaf.o \ |
| ++ fmaxf.o \ |
| ++ fminf.o \ |
| + fmodf.o \ |
| + frexpf.o \ |
| + gammaf.o \ |
| +@@ -116,11 +117,14 @@ FL_MOBJ := \ |
| + lrintf.o \ |
| + lroundf.o \ |
| + modff.o \ |
| ++ nearbyintf.o \ |
| ++ nexttowardf.o \ |
| + powf.o \ |
| + remainderf.o \ |
| ++ remquof.o \ |
| + rintf.o \ |
| + roundf.o \ |
| +- scalbf.o \ |
| ++ scalblnf.o \ |
| + scalbnf.o \ |
| + significandf.o \ |
| + sinf.o \ |
| +@@ -128,9 +132,24 @@ FL_MOBJ := \ |
| + sqrtf.o \ |
| + tanf.o \ |
| + tanhf.o \ |
| ++ tgammaf.o \ |
| + truncf.o \ |
| + |
| +-# Not implemented [yet?]: nexttowardl.o |
| ++ifeq ($(UCLIBC_SUSV3_LEGACY),y) |
| ++FL_MOBJ += scalbf.o |
| ++endif |
| ++ |
| ++# Do not (yet?) implement the float variants of bessel functions |
| ++ifeq (not-yet-implemented-$(DO_XSI_MATH),y) |
| ++FL_MOBJ += \ |
| ++ j0f.o \ |
| ++ j1f.o \ |
| ++ jnf.o \ |
| ++ y0f.o \ |
| ++ y1f.o \ |
| ++ ynf.o |
| ++endif |
| ++ |
| + LD_MOBJ := \ |
| + __finitel.o \ |
| + __fpclassifyl.o \ |
| +@@ -180,6 +199,7 @@ LD_MOBJ := \ |
| + modfl.o \ |
| + nearbyintl.o \ |
| + nextafterl.o \ |
| ++ nexttowardl.o \ |
| + powl.o \ |
| + remainderl.o \ |
| + remquol.o \ |
| +@@ -196,6 +216,17 @@ LD_MOBJ := \ |
| + tgammal.o \ |
| + truncl.o \ |
| + |
| ++# Do not (yet?) implement the long double variants of bessel functions |
| ++ifeq (not-yet-implemented-$(DO_XSI_MATH),y) |
| ++LD_MOBJ += \ |
| ++ j0l.o \ |
| ++ j1l.o \ |
| ++ jnl.o \ |
| ++ y0l.o \ |
| ++ y1l.o \ |
| ++ ynl.o |
| ++endif |
| ++ |
| + else |
| + |
| + # This list of math functions was taken from POSIX/IEEE 1003.1b-1993 |
| +diff --git a/libm/float_wrappers.c b/libm/float_wrappers.c |
| +index 82b7963..105486e 100644 |
| +--- a/libm/float_wrappers.c |
| ++++ b/libm/float_wrappers.c |
| +@@ -38,19 +38,14 @@ long long func##f (float x) \ |
| + return func((double)x); \ |
| + } |
| + |
| +- |
| +-/* For the time being, do _NOT_ implement these functions |
| +- * that are defined by SuSv3 [because we don't need them |
| +- * and nobody asked to include them] */ |
| +-#undef L_fdimf /*float fdimf(float, float);*/ |
| +-#undef L_fmaf /*float fmaf(float, float, float);*/ |
| +-#undef L_fmaxf /*float fmaxf(float, float);*/ |
| +-#undef L_fminf /*float fminf(float, float);*/ |
| +-#undef L_nearbyintf /*float nearbyintf(float);*/ |
| +-#undef L_nexttowardf /*float nexttowardf(float, long double);*/ |
| +-#undef L_remquof /*float remquof(float, float, int *);*/ |
| +-#undef L_scalblnf /*float scalblnf(float, long);*/ |
| +-#undef L_tgammaf /*float tgammaf(float);*/ |
| ++#ifndef __DO_XSI_MATH__ |
| ++# undef L_j0f /* float j0f(float x); */ |
| ++# undef L_j1f /* float j1f(float x); */ |
| ++# undef L_jnf /* float jnf(int n, float x); */ |
| ++# undef L_y0f /* float y0f(float x); */ |
| ++# undef L_y1f /* float y1f(float x); */ |
| ++# undef L_ynf /* float ynf(int n, float x); */ |
| ++#endif |
| + |
| + /* Implement the following, as defined by SuSv3 */ |
| + #if 0 |
| +@@ -155,6 +150,7 @@ float copysignf (float x, float y) |
| + |
| + #ifdef L_cosf |
| + WRAPPER1(cos) |
| ++libm_hidden_def(cosf) |
| + #endif |
| + |
| + #ifdef L_coshf |
| +@@ -242,6 +238,21 @@ float hypotf (float x, float y) |
| + int_WRAPPER1(ilogb) |
| + #endif |
| + |
| ++#ifdef L_j0f |
| ++WRAPPER1(j0) |
| ++#endif |
| ++ |
| ++#ifdef L_j1f |
| ++WRAPPER1(j1) |
| ++#endif |
| ++ |
| ++#ifdef L_jnf |
| ++float jnf(int n, float x) |
| ++{ |
| ++ return (float) jn(n, (double)x); |
| ++} |
| ++#endif |
| ++ |
| + #ifdef L_ldexpf |
| + float ldexpf (float x, int _exp) |
| + { |
| +@@ -306,7 +317,7 @@ WRAPPER1(nearbyint) |
| + #ifdef L_nexttowardf |
| + float nexttowardf (float x, long double y) |
| + { |
| +- return (float) nexttoward( (double)x, (double)y ); |
| ++ return (float) nexttoward( (double)x, (long double)y ); |
| + } |
| + #endif |
| + |
| +@@ -355,6 +366,7 @@ float scalbnf (float x, int _exp) |
| + |
| + #ifdef L_sinf |
| + WRAPPER1(sin) |
| ++libm_hidden_def(sinf) |
| + #endif |
| + |
| + #ifdef L_sinhf |
| +@@ -381,13 +393,6 @@ WRAPPER1(tgamma) |
| + WRAPPER1(trunc) |
| + #endif |
| + |
| +-#ifdef L_fmaf |
| +-float fmaf (float x, float y, float z) |
| +-{ |
| +- return (float) fma( (double)x, (double)y, (double)z ); |
| +-} |
| +-#endif |
| +- |
| + #if defined L_scalbf && defined __UCLIBC_SUSV3_LEGACY__ |
| + float scalbf (float x, float y) |
| + { |
| +@@ -402,3 +407,18 @@ WRAPPER1(gamma) |
| + #ifdef L_significandf |
| + WRAPPER1(significand) |
| + #endif |
| ++ |
| ++#ifdef L_y0f |
| ++WRAPPER1(y0) |
| ++#endif |
| ++ |
| ++#ifdef L_y1f |
| ++WRAPPER1(y1) |
| ++#endif |
| ++ |
| ++#ifdef L_ynf |
| ++float ynf(int n, float x) |
| ++{ |
| ++ return (float) yn(n, (double)x); |
| ++} |
| ++#endif |
| +diff --git a/libm/ldouble_wrappers.c b/libm/ldouble_wrappers.c |
| +index 118a78f..b4215cb 100644 |
| +--- a/libm/ldouble_wrappers.c |
| ++++ b/libm/ldouble_wrappers.c |
| +@@ -42,6 +42,15 @@ long long func##l(long double x) \ |
| + return func((double) x); \ |
| + } |
| + |
| ++#ifndef __DO_XSI_MATH__ |
| ++# undef L_j0l /* long double j0l(long double x); */ |
| ++# undef L_j1l /* long double j1l(long double x); */ |
| ++# undef L_jnl /* long double jnl(int n, long double x); */ |
| ++# undef L_y0l /* long double y0l(long double x); */ |
| ++# undef L_y1l /* long double y1l(long double x); */ |
| ++# undef L_ynl /* long double ynl(int n, long double x); */ |
| ++#endif |
| ++ |
| + /* Implement the following, as defined by SuSv3 */ |
| + #if 0 |
| + long double acoshl(long double); |
| +@@ -156,6 +165,7 @@ WRAPPER1(cosh) |
| + |
| + #ifdef L_cosl |
| + WRAPPER1(cos) |
| ++libm_hidden_def(cosl) |
| + #endif |
| + |
| + #ifdef L_erfcl |
| +@@ -172,6 +182,7 @@ WRAPPER1(exp2) |
| + |
| + #ifdef L_expl |
| + WRAPPER1(exp) |
| ++libm_hidden_def(expl) |
| + #endif |
| + |
| + #ifdef L_expm1l |
| +@@ -222,12 +233,28 @@ WRAPPER1(gamma) |
| + |
| + #ifdef L_hypotl |
| + WRAPPER2(hypot) |
| ++libm_hidden_def(hypotl) |
| + #endif |
| + |
| + #ifdef L_ilogbl |
| + int_WRAPPER1(ilogb) |
| + #endif |
| + |
| ++#ifdef L_j0l |
| ++ WRAPPER1(j0) |
| ++#endif |
| ++ |
| ++#ifdef L_j1l |
| ++ WRAPPER1(j1) |
| ++#endif |
| ++ |
| ++#ifdef L_jnl |
| ++long double jnl(int n, long double x) |
| ++{ |
| ++ return (long double) jn(n, (double)x); |
| ++} |
| ++#endif |
| ++ |
| + #ifdef L_ldexpl |
| + long double ldexpl (long double x, int ex) |
| + { |
| +@@ -291,12 +318,18 @@ WRAPPER1(nearbyint) |
| + |
| + #ifdef L_nextafterl |
| + WRAPPER2(nextafter) |
| ++libm_hidden_def(nextafterl) |
| + #endif |
| + |
| +-/* Disabled in Makefile.in */ |
| +-#if 0 /* def L_nexttowardl */ |
| +-WRAPPER2(nexttoward) |
| +-libm_hidden_def(nexttowardl) |
| ++#ifdef L_nexttowardl |
| ++# if 0 /* TODO */ |
| ++strong_alias(nextafterl, nexttowardl) |
| ++# else |
| ++long double nexttowardl(long double x, long double y) |
| ++{ |
| ++ return nextafterl(x, y); |
| ++} |
| ++#endif |
| + #endif |
| + |
| + #ifdef L_powl |
| +@@ -344,6 +377,7 @@ WRAPPER1(sinh) |
| + |
| + #ifdef L_sinl |
| + WRAPPER1(sin) |
| ++libm_hidden_def(sinl) |
| + #endif |
| + |
| + #ifdef L_sqrtl |
| +@@ -370,6 +404,22 @@ WRAPPER1(trunc) |
| + WRAPPER1(significand) |
| + #endif |
| + |
| ++#ifdef L_y0l |
| ++WRAPPER1(y0) |
| ++#endif |
| ++ |
| ++#ifdef L_y1l |
| ++WRAPPER1(y1) |
| ++#endif |
| ++ |
| ++#ifdef L_ynl |
| ++long double ynl(int n, long double x) |
| ++{ |
| ++ return (long double) yn(n, (double)x); |
| ++} |
| ++#endif |
| ++ |
| ++ |
| + #if defined __DO_C99_MATH__ && !defined __NO_LONG_DOUBLE_MATH |
| + |
| + # ifdef L___fpclassifyl |
| +diff --git a/libm/s_fdim.c b/libm/s_fdim.c |
| +index 6249219..6ed695c 100644 |
| +--- a/libm/s_fdim.c |
| ++++ b/libm/s_fdim.c |
| +@@ -6,13 +6,22 @@ |
| + |
| + #include "math.h" |
| + #include "math_private.h" |
| ++#include <errno.h> |
| + |
| + double fdim(double x, double y) |
| + { |
| +- int c = __fpclassify(x); |
| +- if (c == FP_NAN || c == FP_INFINITE) |
| +- return HUGE_VAL; |
| ++ int cx = __fpclassify(x); /* need both NAN and INF */ |
| ++ int cy = __fpclassify(y); /* need both NAN and INF */ |
| ++ if (cx == FP_NAN || cy == NAN) |
| ++ return x - y; |
| + |
| +- return x > y ? x - y : 0.0; |
| ++ if (x <= y) |
| ++ return .0; |
| ++ |
| ++ double z = x - y; |
| ++ if (isinf(z) && cx != FP_INFINITE && cy != FP_INFINITE) |
| ++ __set_errno(ERANGE); |
| ++ |
| ++ return z; |
| + } |
| + libm_hidden_def(fdim) |
| +diff --git a/libm/s_fmax.c b/libm/s_fmax.c |
| +index 21dfaa9..5f29ad8 100644 |
| +--- a/libm/s_fmax.c |
| ++++ b/libm/s_fmax.c |
| +@@ -9,10 +9,10 @@ |
| + |
| + double fmax(double x, double y) |
| + { |
| +- if (__fpclassify(x) == FP_NAN) |
| +- return x; |
| +- if (__fpclassify(y) == FP_NAN) |
| ++ if (isnan(x)) |
| + return y; |
| ++ if (isnan(y)) |
| ++ return x; |
| + |
| + return x > y ? x : y; |
| + } |
| +diff --git a/libm/s_fmin.c b/libm/s_fmin.c |
| +index 674d9a5..a549678 100644 |
| +--- a/libm/s_fmin.c |
| ++++ b/libm/s_fmin.c |
| +@@ -9,10 +9,10 @@ |
| + |
| + double fmin(double x, double y) |
| + { |
| +- if (__fpclassify(x) == FP_NAN) |
| +- return x; |
| +- if (__fpclassify(y) == FP_NAN) |
| ++ if (isnan(x)) |
| + return y; |
| ++ if (isnan(y)) |
| ++ return x; |
| + |
| + return x < y ? x : y; |
| + } |
| +diff --git a/libm/s_nextafter.c b/libm/s_nextafter.c |
| +index ee4621c..73a8ab2 100644 |
| +--- a/libm/s_nextafter.c |
| ++++ b/libm/s_nextafter.c |
| +@@ -32,7 +32,7 @@ double nextafter(double x, double y) |
| + if(((ix>=0x7ff00000)&&((ix-0x7ff00000)|lx)!=0) || /* x is nan */ |
| + ((iy>=0x7ff00000)&&((iy-0x7ff00000)|ly)!=0)) /* y is nan */ |
| + return x+y; |
| +- if(x==y) return x; /* x=y, return x */ |
| ++ if(x==y) return y; /* x=y, return y */ |
| + if((ix|lx)==0) { /* x == 0 */ |
| + INSERT_WORDS(x,hy&0x80000000,1); /* return +-minsubnormal */ |
| + y = x*x; |
| +@@ -68,3 +68,5 @@ double nextafter(double x, double y) |
| + return x; |
| + } |
| + libm_hidden_def(nextafter) |
| ++strong_alias_untyped(nextafter, nexttoward) |
| ++libm_hidden_def(nexttoward) |
| +diff --git a/test/math/compile_test.c b/test/math/compile_test.c |
| +index ab8c40c..aedfde6 100644 |
| +--- a/test/math/compile_test.c |
| ++++ b/test/math/compile_test.c |
| +@@ -22,11 +22,11 @@ r += exp2f(float_x); |
| + r += expf(float_x); |
| + r += expm1f(float_x); |
| + r += fabsf(float_x); |
| +-/*r += fdimf(float_x, float_x); - uclibc does not have it (yet?) */ |
| ++r += fdimf(float_x, float_x); |
| + r += floorf(float_x); |
| +-/*r += fmaf(float_x, float_x, float_x); - uclibc does not have it (yet?) */ |
| +-/*r += fmaxf(float_x, float_x); - uclibc does not have it (yet?) */ |
| +-/*r += fminf(float_x, float_x); - uclibc does not have it (yet?) */ |
| ++r += fmaf(float_x, float_x, float_x); |
| ++r += fmaxf(float_x, float_x); |
| ++r += fminf(float_x, float_x); |
| + r += fmodf(float_x, float_x); |
| + r += frexpf(float_x, &int_x); |
| + r += gammaf(float_x); |
| +@@ -44,17 +44,17 @@ r += logf(float_x); |
| + r += lrintf(float_x); |
| + r += lroundf(float_x); |
| + r += modff(float_x, &float_x); |
| +-/*r += nearbyintf(float_x); - uclibc does not have it (yet?) */ |
| +-/*r += nexttowardf(float_x, long_double_x); - uclibc does not have it (yet?) */ |
| ++r += nearbyintf(float_x); |
| ++r += nexttowardf(float_x, long_double_x); |
| + r += powf(float_x, float_x); |
| + r += remainderf(float_x, float_x); |
| +-/*r += remquof(float_x, float_x, &int_x); - uclibc does not have it (yet?) */ |
| ++r += remquof(float_x, float_x, &int_x); |
| + r += rintf(float_x); |
| + r += roundf(float_x); |
| + #ifdef __UCLIBC_SUSV3_LEGACY__ |
| + r += scalbf(float_x, float_x); |
| + #endif |
| +-/*r += scalblnf(float_x, long_x); - uclibc does not have it (yet?) */ |
| ++r += scalblnf(float_x, long_x); |
| + r += scalbnf(float_x, int_x); |
| + r += significandf(float_x); |
| + r += sinf(float_x); |
| +@@ -62,7 +62,7 @@ r += sinhf(float_x); |
| + r += sqrtf(float_x); |
| + r += tanf(float_x); |
| + r += tanhf(float_x); |
| +-/*r += tgammaf(float_x); - uclibc does not have it (yet?) */ |
| ++r += tgammaf(float_x); |
| + r += truncf(float_x); |
| + return r; |
| + } |
| +@@ -116,7 +116,7 @@ r += lroundl(long_double_x); |
| + r += modfl(long_double_x, &long_double_x); |
| + r += nearbyintl(long_double_x); |
| + r += nextafterl(long_double_x, long_double_x); |
| +-/* r += nexttowardl(long_double_x, long_double_x); - uclibc doesn't provide this [yet?] */ |
| ++r += nexttowardl(long_double_x, long_double_x); |
| + r += powl(long_double_x, long_double_x); |
| + r += remainderl(long_double_x, long_double_x); |
| + r += remquol(long_double_x, long_double_x, &int_x); |
| +diff --git a/test/math/libm-test.inc b/test/math/libm-test.inc |
| +index d0f0a0c..8f0db3c 100644 |
| +--- a/test/math/libm-test.inc |
| ++++ b/test/math/libm-test.inc |
| +@@ -115,6 +115,9 @@ |
| + # define _GNU_SOURCE |
| + #endif |
| + |
| ++#undef __CHK_COMPLEX_STUFF |
| ++#define __CHK_COMPLEX_STUFF 0 |
| ++ |
| + #include "libm-test-ulps.h" |
| + #include <complex.h> |
| + #include <math.h> |
| +@@ -1120,8 +1123,10 @@ cacosh_test (void) |
| + |
| + END (cacosh, complex); |
| + } |
| ++#endif |
| + |
| + |
| ++#if __CHK_COMPLEX_STUFF |
| + static void |
| + carg_test (void) |
| + { |
| +@@ -1188,7 +1193,9 @@ carg_test (void) |
| + |
| + END (carg); |
| + } |
| ++#endif /* __CHK_COMPLEX_STUFF */ |
| + |
| ++#if 0 |
| + static void |
| + casin_test (void) |
| + { |
| +@@ -1683,7 +1690,7 @@ ceil_test (void) |
| + } |
| + |
| + |
| +-#if 0 |
| ++#if __CHK_COMPLEX_STUFF |
| + static void |
| + cexp_test (void) |
| + { |
| +@@ -1746,8 +1753,9 @@ cexp_test (void) |
| + |
| + END (cexp, complex); |
| + } |
| ++#endif /* __CHK_COMPLEX_STUFF */ |
| + |
| +- |
| ++#if 0 |
| + static void |
| + cimag_test (void) |
| + { |
| +@@ -2588,7 +2596,6 @@ fabs_test (void) |
| + } |
| + |
| + |
| +-#if 0 |
| + static void |
| + fdim_test (void) |
| + { |
| +@@ -2624,7 +2631,6 @@ fdim_test (void) |
| + |
| + END (fdim); |
| + } |
| +-#endif |
| + |
| + |
| + static void |
| +@@ -2694,7 +2700,6 @@ floor_test (void) |
| + } |
| + |
| + |
| +-#if 0 |
| + static void |
| + fma_test (void) |
| + { |
| +@@ -2797,7 +2802,6 @@ fmin_test (void) |
| + |
| + END (fmin); |
| + } |
| +-#endif |
| + |
| + |
| + static void |
| +@@ -3002,7 +3006,7 @@ isnormal_test (void) |
| + END (isnormal); |
| + } |
| + |
| +-#if defined __DO_XSI_MATH__ |
| ++#if defined __DO_XSI_MATH__ && !(defined TEST_LDOUBLE || defined TEST_FLOAT) |
| + static void |
| + j0_test (void) |
| + { |
| +@@ -3629,7 +3633,6 @@ modf_test (void) |
| + } |
| + |
| + |
| +-#if 0 |
| + static void |
| + nearbyint_test (void) |
| + { |
| +@@ -3710,7 +3713,6 @@ nexttoward_test (void) |
| + |
| + END (nexttoward); |
| + } |
| +-#endif |
| + |
| + |
| + static void |
| +@@ -3950,7 +3952,6 @@ remainder_test (void) |
| + END (remainder); |
| + } |
| + |
| +-#if 0 |
| + static void |
| + remquo_test (void) |
| + { |
| +@@ -3981,7 +3982,6 @@ remquo_test (void) |
| + |
| + END (remquo); |
| + } |
| +-#endif |
| + |
| + static void |
| + rint_test (void) |
| +@@ -4229,12 +4229,12 @@ round_test (void) |
| + #endif |
| + |
| + |
| ++#ifdef __UCLIBC_SUSV3_LEGACY__ |
| + static void |
| + scalb_test (void) |
| + { |
| + START (scalb); |
| + #ifndef TEST_LDOUBLE /* uclibc doesn't have scalbl */ |
| +-#ifdef __UCLIBC_SUSV3_LEGACY__ /* scalbf is susv3 legacy */ |
| + |
| + TEST_ff_f (scalb, 2.0, 0.5, nan_value, INVALID_EXCEPTION); |
| + TEST_ff_f (scalb, 3.0, -2.5, nan_value, INVALID_EXCEPTION); |
| +@@ -4285,11 +4285,10 @@ scalb_test (void) |
| + |
| + TEST_ff_f (scalb, 0.8L, 4, 12.8L); |
| + TEST_ff_f (scalb, -0.854375L, 5, -27.34L); |
| +-#endif /* __UCLIBC_SUSV3_LEGACY__ */ |
| + #endif /* TEST_LDOUBLE */ |
| + END (scalb); |
| + } |
| +- |
| ++#endif |
| + |
| + static void |
| + scalbn_test (void) |
| +@@ -4313,7 +4312,6 @@ scalbn_test (void) |
| + } |
| + |
| + |
| +-#if 0 |
| + static void |
| + scalbln_test (void) |
| + { |
| +@@ -4334,7 +4332,6 @@ scalbln_test (void) |
| + |
| + END (scalbn); |
| + } |
| +-#endif |
| + |
| + |
| + static void |
| +@@ -4539,7 +4536,6 @@ tanh_test (void) |
| + END (tanh); |
| + } |
| + |
| +-#if 0 |
| + static void |
| + tgamma_test (void) |
| + { |
| +@@ -4571,7 +4567,6 @@ tgamma_test (void) |
| + |
| + END (tgamma); |
| + } |
| +-#endif |
| + |
| + |
| + #if 0 |
| +@@ -4651,7 +4646,7 @@ trunc_test (void) |
| + } |
| + #endif |
| + |
| +-#if defined __DO_XSI_MATH__ |
| ++#if defined __DO_XSI_MATH__ && !(defined TEST_LDOUBLE || defined TEST_FLOAT) |
| + static void |
| + y0_test (void) |
| + { |
| +@@ -4979,11 +4974,11 @@ main (int argc, char **argv) |
| + logb_test (); |
| + modf_test (); |
| + ilogb_test (); |
| ++#ifdef __UCLIBC_SUSV3_LEGACY__ |
| + scalb_test (); |
| ++#endif |
| + scalbn_test (); |
| +-#if 0 |
| + scalbln_test (); |
| +-#endif |
| + significand_test (); |
| + |
| + /* Power and absolute value functions: */ |
| +@@ -4998,16 +4993,12 @@ main (int argc, char **argv) |
| + erfc_test (); |
| + gamma_test (); |
| + lgamma_test (); |
| +-#if 0 |
| + tgamma_test (); |
| +-#endif |
| + |
| + /* Nearest integer functions: */ |
| + ceil_test (); |
| + floor_test (); |
| +-#if 0 |
| + nearbyint_test (); |
| +-#endif |
| + rint_test (); |
| + #if 0 |
| + rint_test_tonearest (); |
| +@@ -5025,13 +5016,10 @@ main (int argc, char **argv) |
| + /* Remainder functions: */ |
| + fmod_test (); |
| + remainder_test (); |
| +-#if 0 |
| + remquo_test (); |
| +-#endif |
| + |
| + /* Manipulation functions: */ |
| + copysign_test (); |
| +-#if 0 |
| + nextafter_test (); |
| + nexttoward_test (); |
| + |
| +@@ -5043,24 +5031,29 @@ main (int argc, char **argv) |
| + /* Multiply and add: */ |
| + fma_test (); |
| + |
| ++ |
| + /* Complex functions: */ |
| + cabs_test (); |
| ++#if __CHK_COMPLEX_STUFF |
| ++#if 0 |
| + cacos_test (); |
| + cacosh_test (); |
| ++#endif |
| + carg_test (); |
| ++#if 0 |
| + casin_test (); |
| + casinh_test (); |
| + catan_test (); |
| + catanh_test (); |
| + ccos_test (); |
| + ccosh_test (); |
| ++#endif |
| + cexp_test (); |
| ++#if 0 |
| + cimag_test (); |
| + clog10_test (); |
| + clog_test (); |
| +-#if 0 |
| + conj_test (); |
| +-#endif |
| + cpow_test (); |
| + cproj_test (); |
| + creal_test (); |
| +@@ -5070,9 +5063,10 @@ main (int argc, char **argv) |
| + ctan_test (); |
| + ctanh_test (); |
| + #endif |
| ++#endif /* __CHK_COMPLEX_STUFF */ |
| + |
| + /* Bessel functions: */ |
| +-#if defined __DO_XSI_MATH__ |
| ++#if defined __DO_XSI_MATH__ && !(defined TEST_LDOUBLE || defined TEST_FLOAT) |
| + j0_test (); |
| + j1_test (); |
| + jn_test (); |
| +-- |
| +cgit v0.9.1 |
| diff --git a/package/uclibc/0.9.33.2/uclibc-0070-libc-add-get-set-swap-make-context-user-context-mani.patch b/package/uclibc/0.9.33.2/uclibc-0070-libc-add-get-set-swap-make-context-user-context-mani.patch |
| new file mode 100644 |
| index 0000000..c955b00 |
| --- /dev/null |
| +++ b/package/uclibc/0.9.33.2/uclibc-0070-libc-add-get-set-swap-make-context-user-context-mani.patch |
| @@ -0,0 +1,2550 @@ |
| +From a8dc90eaaa5e6474beac828558d969b1aafee4af Mon Sep 17 00:00:00 2001 |
| +From: Florian Fainelli <florian@openwrt.org> |
| +Date: Wed, 9 Jan 2013 16:17:21 +0100 |
| +Subject: [PATCH] libc: add {get,set,swap,make}context user context |
| + manipulation functions |
| + |
| +Add the obsolescent SUSv3 family of user context manipulating functions |
| +for arm, i386, mips, x86_64. |
| + |
| +Signed-off-by: Timon ter Braak <timonterbraak@gmail.com> |
| +Signed-off-by: Florian Fainelli <florian@openwrt.org> |
| +Signed-off-by: Bernhard Reutner-Fischer <rep.dot.nop@gmail.com> |
| +Signed-off-by: Natanael Copa <ncopa@alpinelinux.org> |
| +Signed-off-by: Bernhard Reutner-Fischer <rep.dot.nop@gmail.com> |
| +--- |
| + Rules.mak | 2 + |
| + extra/Configs/Config.arm | 1 + |
| + extra/Configs/Config.i386 | 1 + |
| + extra/Configs/Config.in | 16 ++ |
| + extra/Configs/Config.mips | 1 + |
| + extra/Configs/Config.x86_64 | 1 + |
| + include/ucontext.h | 32 +++- |
| + libc/.gitignore | 1 + |
| + libc/sysdeps/linux/Makefile.commonarch | 20 +- |
| + libc/sysdeps/linux/arm/Makefile.arch | 5 + |
| + libc/sysdeps/linux/arm/getcontext.S | 80 ++++++++ |
| + libc/sysdeps/linux/arm/makecontext.c | 73 +++++++ |
| + libc/sysdeps/linux/arm/setcontext.S | 76 ++++++++ |
| + libc/sysdeps/linux/arm/swapcontext.S | 63 ++++++ |
| + libc/sysdeps/linux/arm/ucontext_i.sym | 30 +++ |
| + libc/sysdeps/linux/i386/Makefile.arch | 4 + |
| + libc/sysdeps/linux/i386/getcontext.S | 84 ++++++++ |
| + libc/sysdeps/linux/i386/makecontext.S | 123 ++++++++++++ |
| + libc/sysdeps/linux/i386/setcontext.S | 96 ++++++++++ |
| + libc/sysdeps/linux/i386/swapcontext.S | 110 +++++++++++ |
| + libc/sysdeps/linux/i386/ucontext_i.sym | 30 +++ |
| + libc/sysdeps/linux/mips/Makefile.arch | 4 + |
| + libc/sysdeps/linux/mips/getcontext.S | 148 +++++++++++++++ |
| + libc/sysdeps/linux/mips/kernel_rt_sigframe.h | 10 + |
| + libc/sysdeps/linux/mips/makecontext.S | 188 ++++++++++++++++++ |
| + libc/sysdeps/linux/mips/setcontext.S | 191 +++++++++++++++++++ |
| + libc/sysdeps/linux/mips/swapcontext.S | 211 +++++++++++++++++++++ |
| + libc/sysdeps/linux/mips/ucontext_i.sym | 52 +++++ |
| + libc/sysdeps/linux/x86_64/Makefile.arch | 5 + |
| + libc/sysdeps/linux/x86_64/__start_context.S | 49 +++++ |
| + libc/sysdeps/linux/x86_64/getcontext.S | 88 +++++++++ |
| + libc/sysdeps/linux/x86_64/makecontext.c | 121 ++++++++++++ |
| + libc/sysdeps/linux/x86_64/setcontext.S | 103 ++++++++++ |
| + libc/sysdeps/linux/x86_64/swapcontext.S | 121 ++++++++++++ |
| + libc/sysdeps/linux/x86_64/ucontext_i.sym | 37 ++++ |
| + libpthread/nptl/sysdeps/Makefile.commonarch | 3 +- |
| + .../sysdeps/unix/sysv/linux/Makefile.commonarch | 2 - |
| + 37 files changed, 2174 insertions(+), 8 deletions(-) |
| + create mode 100644 libc/.gitignore |
| + create mode 100644 libc/sysdeps/linux/arm/getcontext.S |
| + create mode 100644 libc/sysdeps/linux/arm/makecontext.c |
| + create mode 100644 libc/sysdeps/linux/arm/setcontext.S |
| + create mode 100644 libc/sysdeps/linux/arm/swapcontext.S |
| + create mode 100644 libc/sysdeps/linux/arm/ucontext_i.sym |
| + create mode 100644 libc/sysdeps/linux/i386/getcontext.S |
| + create mode 100644 libc/sysdeps/linux/i386/makecontext.S |
| + create mode 100644 libc/sysdeps/linux/i386/setcontext.S |
| + create mode 100644 libc/sysdeps/linux/i386/swapcontext.S |
| + create mode 100644 libc/sysdeps/linux/i386/ucontext_i.sym |
| + create mode 100644 libc/sysdeps/linux/mips/getcontext.S |
| + create mode 100644 libc/sysdeps/linux/mips/kernel_rt_sigframe.h |
| + create mode 100644 libc/sysdeps/linux/mips/makecontext.S |
| + create mode 100644 libc/sysdeps/linux/mips/setcontext.S |
| + create mode 100644 libc/sysdeps/linux/mips/swapcontext.S |
| + create mode 100644 libc/sysdeps/linux/mips/ucontext_i.sym |
| + create mode 100644 libc/sysdeps/linux/x86_64/__start_context.S |
| + create mode 100644 libc/sysdeps/linux/x86_64/getcontext.S |
| + create mode 100644 libc/sysdeps/linux/x86_64/makecontext.c |
| + create mode 100644 libc/sysdeps/linux/x86_64/setcontext.S |
| + create mode 100644 libc/sysdeps/linux/x86_64/swapcontext.S |
| + create mode 100644 libc/sysdeps/linux/x86_64/ucontext_i.sym |
| + |
| +diff --git a/Rules.mak b/Rules.mak |
| +index 96871e1..8943fbf 100644 |
| +--- a/Rules.mak |
| ++++ b/Rules.mak |
| +@@ -813,3 +813,5 @@ SHARED_END_FILES:=$(LIBGCC_DIR)crtendS.o $(top_builddir)lib/crtn.o |
| + endif |
| + |
| + LOCAL_INSTALL_PATH := install_dir |
| ++ |
| ++PTHREAD_GENERATE_MANGLE ?= -n "s/^.*@@@name@@@\([^@]*\)@@@value@@@[^0-9Xxa-fA-F-]*\([0-9Xxa-fA-F-][0-9Xxa-fA-F-]*\).*@@@end@@@.*\$$/\#define \1 \2/p" |
| +diff --git a/extra/Configs/Config.arm b/extra/Configs/Config.arm |
| +index 0bb2971..dc53643 100644 |
| +--- a/extra/Configs/Config.arm |
| ++++ b/extra/Configs/Config.arm |
| +@@ -11,6 +11,7 @@ config FORCE_OPTIONS_FOR_ARCH |
| + bool |
| + default y |
| + select ARCH_ANY_ENDIAN |
| ++ select ARCH_HAS_UCONTEXT |
| + |
| + config CONFIG_ARM_EABI |
| + bool "Build for EABI" |
| +diff --git a/extra/Configs/Config.i386 b/extra/Configs/Config.i386 |
| +index 288aa5e..92cee3b 100644 |
| +--- a/extra/Configs/Config.i386 |
| ++++ b/extra/Configs/Config.i386 |
| +@@ -12,6 +12,7 @@ config FORCE_OPTIONS_FOR_ARCH |
| + default y |
| + select ARCH_LITTLE_ENDIAN |
| + select ARCH_HAS_MMU |
| ++ select ARCH_HAS_UCONTEXT |
| + |
| + choice |
| + prompt "Target x86 Processor Family" |
| +diff --git a/extra/Configs/Config.in b/extra/Configs/Config.in |
| +index 4bb6812..62bcd9b 100644 |
| +--- a/extra/Configs/Config.in |
| ++++ b/extra/Configs/Config.in |
| +@@ -261,6 +261,9 @@ config ARCH_HAS_NO_LDSO |
| + bool |
| + select ARCH_HAS_NO_SHARED |
| + |
| ++config ARCH_HAS_UCONTEXT |
| ++ bool |
| ++ |
| + config HAVE_SHARED |
| + bool "Enable shared libraries" |
| + depends on !ARCH_HAS_NO_SHARED |
| +@@ -678,6 +681,19 @@ config UCLIBC_SUSV3_LEGACY |
| + |
| + WARNING! ABI incompatibility. |
| + |
| ++config UCLIBC_HAS_CONTEXT_FUNCS |
| ++ bool "Use obsolescent context control functions" |
| ++ depends on UCLIBC_SUSV3_LEGACY && ARCH_HAS_UCONTEXT |
| ++ help |
| ++ Add into library the SuSv3 obsolescent functions used for context |
| ++ control. The setcontext family allows the implementation in C of |
| ++ advanced control flow patterns such as iterators, fibers, and |
| ++ coroutines. They may be viewed as an advanced version of |
| ++ setjmp/longjmp; whereas the latter allows only a single non-local jump |
| ++ up the stack, setcontext allows the creation of multiple cooperative |
| ++ threads of control, each with its own stack. |
| ++ These functions are: setcontext, getcontext, makecontext, swapcontext. |
| ++ |
| + config UCLIBC_SUSV3_LEGACY_MACROS |
| + bool "Enable SuSv3 LEGACY macros" |
| + help |
| +diff --git a/extra/Configs/Config.mips b/extra/Configs/Config.mips |
| +index 063b07c..48e0b64 100644 |
| +--- a/extra/Configs/Config.mips |
| ++++ b/extra/Configs/Config.mips |
| +@@ -11,6 +11,7 @@ config FORCE_OPTIONS_FOR_ARCH |
| + bool |
| + default y |
| + select ARCH_ANY_ENDIAN |
| ++ select ARCH_HAS_UCONTEXT |
| + |
| + choice |
| + prompt "Target ABI" |
| +diff --git a/extra/Configs/Config.x86_64 b/extra/Configs/Config.x86_64 |
| +index 1b28088..4c8c3a9 100644 |
| +--- a/extra/Configs/Config.x86_64 |
| ++++ b/extra/Configs/Config.x86_64 |
| +@@ -12,3 +12,4 @@ config FORCE_OPTIONS_FOR_ARCH |
| + default y |
| + select ARCH_LITTLE_ENDIAN |
| + select ARCH_HAS_MMU |
| ++ select ARCH_HAS_UCONTEXT |
| +diff --git a/include/ucontext.h b/include/ucontext.h |
| +index 14a1270..f11db77 100644 |
| +--- a/include/ucontext.h |
| ++++ b/include/ucontext.h |
| +@@ -15,17 +15,43 @@ |
| + License along with the GNU C Library; if not, see |
| + <http://www.gnu.org/licenses/>. */ |
| + |
| ++/* The System V ABI user-level context switching support functions |
| ++ are marked obsolescent by SuSv3. */ |
| ++ |
| + #ifndef _UCONTEXT_H |
| + #define _UCONTEXT_H 1 |
| + |
| + #include <features.h> |
| + |
| ++#ifdef __UCLIBC_HAS_CONTEXT_FUNCS__ |
| ++ |
| + /* Get machine dependent definition of data structures. */ |
| + #include <sys/ucontext.h> |
| + |
| +-/* The System V ABI user-level context switching support functions |
| +- * are marked obsolescent by SuSv3, and are not implemented by |
| +- * uClibc. This header is therefore empty. */ |
| ++__BEGIN_DECLS |
| ++ |
| ++/* Get user context and store it in variable pointed to by UCP. */ |
| ++extern int getcontext (ucontext_t *__ucp) __THROW; |
| ++ |
| ++/* Set user context from information of variable pointed to by UCP. */ |
| ++extern int setcontext (const ucontext_t *__ucp) __THROW; |
| ++ |
| ++/* Save current context in context variable pointed to by OUCP and set |
| ++ context from variable pointed to by UCP. */ |
| ++extern int swapcontext (ucontext_t *__restrict __oucp, |
| ++ const ucontext_t *__restrict __ucp) __THROW; |
| ++ |
| ++/* Manipulate user context UCP to continue with calling functions FUNC |
| ++ and the ARGC-1 parameters following ARGC when the context is used |
| ++ the next time in `setcontext' or `swapcontext'. |
| ++ |
| ++ We cannot say anything about the parameters FUNC takes; `void' |
| ++ is as good as any other choice. */ |
| ++extern void makecontext (ucontext_t *__ucp, void (*__func) (void), |
| ++ int __argc, ...) __THROW; |
| ++ |
| ++__END_DECLS |
| + |
| ++#endif |
| + |
| + #endif /* ucontext.h */ |
| +diff --git a/libc/.gitignore b/libc/.gitignore |
| +new file mode 100644 |
| +index 0000000..f4c0305 |
| +--- /dev/null |
| ++++ b/libc/.gitignore |
| +@@ -0,0 +1 @@ |
| ++ucontext_i.[chs] |
| +diff --git a/libc/sysdeps/linux/Makefile.commonarch b/libc/sysdeps/linux/Makefile.commonarch |
| +index c1bc5df..ac89e72 100644 |
| +--- a/libc/sysdeps/linux/Makefile.commonarch |
| ++++ b/libc/sysdeps/linux/Makefile.commonarch |
| +@@ -37,5 +37,23 @@ headers-y += $(ARCH_HEADERS_OUT) |
| + headers_clean-y += HEADERCLEAN_$(subst $(top_builddir),,$(ARCH_OUT)) |
| + HEADERCLEAN_$(subst $(top_builddir),,$(ARCH_OUT)): |
| + $(do_rm) $(ARCH_HEADERS_OUT) |
| +- |
| + endif |
| ++ |
| ++CFLAGS-ucontext_i.c = -S |
| ++ |
| ++$(ARCH_OUT)/ucontext_i.c: $(ARCH_DIR)/ucontext_i.sym |
| ++ $(do_awk) $(top_srcdir)extra/scripts/gen-as-const.awk $< > $@ |
| ++ |
| ++$(ARCH_OUT)/ucontext_i.s: $(ARCH_OUT)/ucontext_i.c |
| ++ $(compile.c) |
| ++ |
| ++$(ARCH_OUT)/ucontext_i.h: $(ARCH_OUT)/ucontext_i.s |
| ++ $(do_sed) $(PTHREAD_GENERATE_MANGLE) $< > $@ |
| ++ |
| ++pregen-headers-$(UCLIBC_HAS_CONTEXT_FUNCS) += $(ARCH_OUT)/ucontext_i.h |
| ++ |
| ++headers_clean-$(UCLIBC_HAS_CONTEXT_FUNCS) += \ |
| ++ HEADERCLEAN_$(subst $(top_builddir),,$(ARCH_OUT)/ucontext_i) |
| ++ |
| ++HEADERCLEAN_$(subst $(top_builddir),,$(ARCH_OUT)/ucontext_i): |
| ++ $(do_rm) $(addprefix $(ARCH_OUT)/ucontext_i., c h s) |
| +diff --git a/libc/sysdeps/linux/arm/Makefile.arch b/libc/sysdeps/linux/arm/Makefile.arch |
| +index 5fc3e54..36d988b 100644 |
| +--- a/libc/sysdeps/linux/arm/Makefile.arch |
| ++++ b/libc/sysdeps/linux/arm/Makefile.arch |
| +@@ -43,3 +43,8 @@ libc-static-y += $(ARCH_OUT)/aeabi_lcsts.o $(ARCH_OUT)/aeabi_math.o \ |
| + libc-nonshared-y += $(ARCH_OUT)/aeabi_lcsts.os $(ARCH_OUT)/aeabi_math.os \ |
| + $(ARCH_OUT)/aeabi_sighandlers.os $(ARCH_OUT)/aeabi_unwind_cpp_pr1.o |
| + endif |
| ++ |
| ++ifeq ($(UCLIBC_HAS_CONTEXT_FUNCS),y) |
| ++CSRC += makecontext.c |
| ++SSRC += getcontext.S setcontext.S swapcontext.S |
| ++endif |
| +diff --git a/libc/sysdeps/linux/arm/getcontext.S b/libc/sysdeps/linux/arm/getcontext.S |
| +new file mode 100644 |
| +index 0000000..a987c52 |
| +--- /dev/null |
| ++++ b/libc/sysdeps/linux/arm/getcontext.S |
| +@@ -0,0 +1,80 @@ |
| ++/* Copyright (C) 2012 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/>. */ |
| ++ |
| ++#include <sysdep.h> |
| ++ |
| ++#include "ucontext_i.h" |
| ++ |
| ++ .syntax unified |
| ++ .text |
| ++ |
| ++/* int getcontext (ucontext_t *ucp) */ |
| ++ |
| ++ENTRY(__getcontext) |
| ++ /* No need to save r0-r3, d0-d7, or d16-d31. */ |
| ++ add r1, r0, #MCONTEXT_ARM_R4 |
| ++ stmia r1, {r4-r11} |
| ++ |
| ++ /* Save R13 separately as Thumb can't STM it. */ |
| ++ str r13, [r0, #MCONTEXT_ARM_SP] |
| ++ str r14, [r0, #MCONTEXT_ARM_LR] |
| ++ /* Return to LR */ |
| ++ str r14, [r0, #MCONTEXT_ARM_PC] |
| ++ /* Return zero */ |
| ++ mov r2, #0 |
| ++ str r2, [r0, #MCONTEXT_ARM_R0] |
| ++ |
| ++ /* Save ucontext_t * across the next call. */ |
| ++ mov r4, r0 |
| ++ |
| ++ /* __sigprocmask(SIG_BLOCK, NULL, &(ucontext->uc_sigmask)) */ |
| ++ mov r0, #SIG_BLOCK |
| ++ mov r1, #0 |
| ++ add r2, r4, #UCONTEXT_SIGMASK |
| ++ bl PLTJMP(sigprocmask) |
| ++ |
| ++#if defined __UCLIBC_HAS_FLOATS__ && ! defined __UCLIBC_HAS_SOFT_FLOAT__ |
| ++# ifdef __VFP_FP__ |
| ++ /* Store the VFP registers. */ |
| ++ /* Following instruction is fstmiax ip!, {d8-d15}. */ |
| ++ stc p11, cr8, [r0], #64 |
| ++ /* Store the floating-point status register. */ |
| ++ /* Following instruction is fmrx r2, fpscr. */ |
| ++ mrc p10, 7, r1, cr1, cr0, 0 |
| ++ str r1, [r0], #4 |
| ++# endif |
| ++#endif |
| ++#ifdef __IWMMXT__ |
| ++ /* Save the call-preserved iWMMXt registers. */ |
| ++ /* Following instructions are wstrd wr10, [r0], #8 (etc.) */ |
| ++ stcl p1, cr10, [r0], #8 |
| ++ stcl p1, cr11, [r0], #8 |
| ++ stcl p1, cr12, [r0], #8 |
| ++ stcl p1, cr13, [r0], #8 |
| ++ stcl p1, cr14, [r0], #8 |
| ++ stcl p1, cr15, [r0], #8 |
| ++#endif |
| ++ |
| ++ /* Restore the clobbered R4 and LR. */ |
| ++ ldr r14, [r4, #MCONTEXT_ARM_LR] |
| ++ ldr r4, [r4, #MCONTEXT_ARM_R4] |
| ++ |
| ++ mov r0, #0 |
| ++ DO_RET(r14) |
| ++ |
| ++END(__getcontext) |
| ++weak_alias(__getcontext, getcontext) |
| +diff --git a/libc/sysdeps/linux/arm/makecontext.c b/libc/sysdeps/linux/arm/makecontext.c |
| +new file mode 100644 |
| +index 0000000..d6ae6f0 |
| +--- /dev/null |
| ++++ b/libc/sysdeps/linux/arm/makecontext.c |
| +@@ -0,0 +1,73 @@ |
| ++/* Copyright (C) 2012 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/>. */ |
| ++ |
| ++#include <stdarg.h> |
| ++#include <ucontext.h> |
| ++ |
| ++/* Number of arguments that go in registers. */ |
| ++#define NREG_ARGS 4 |
| ++ |
| ++/* Take a context previously prepared via getcontext() and set to |
| ++ call func() with the given int only args. */ |
| ++void |
| ++__makecontext (ucontext_t *ucp, void (*func) (void), int argc, ...) |
| ++{ |
| ++ extern void __startcontext (void); |
| ++ unsigned long *funcstack; |
| ++ va_list vl; |
| ++ unsigned long *regptr; |
| ++ unsigned int reg; |
| ++ int misaligned; |
| ++ |
| ++ /* Start at the top of stack. */ |
| ++ funcstack = (unsigned long *) (ucp->uc_stack.ss_sp + ucp->uc_stack.ss_size); |
| ++ |
| ++ /* Ensure the stack stays eight byte aligned. */ |
| ++ misaligned = ((unsigned long) funcstack & 4) != 0; |
| ++ |
| ++ if ((argc > NREG_ARGS) && (argc & 1) != 0) |
| ++ misaligned = !misaligned; |
| ++ |
| ++ if (misaligned) |
| ++ funcstack -= 1; |
| ++ |
| ++ va_start (vl, argc); |
| ++ |
| ++ /* Reserve space for the on-stack arguments. */ |
| ++ if (argc > NREG_ARGS) |
| ++ funcstack -= (argc - NREG_ARGS); |
| ++ |
| ++ ucp->uc_mcontext.arm_sp = (unsigned long) funcstack; |
| ++ ucp->uc_mcontext.arm_pc = (unsigned long) func; |
| ++ |
| ++ /* Exit to startcontext() with the next context in R4 */ |
| ++ ucp->uc_mcontext.arm_r4 = (unsigned long) ucp->uc_link; |
| ++ ucp->uc_mcontext.arm_lr = (unsigned long) __startcontext; |
| ++ |
| ++ /* The first four arguments go into registers. */ |
| ++ regptr = &(ucp->uc_mcontext.arm_r0); |
| ++ |
| ++ for (reg = 0; (reg < argc) && (reg < NREG_ARGS); reg++) |
| ++ *regptr++ = va_arg (vl, unsigned long); |
| ++ |
| ++ /* And the remainder on the stack. */ |
| ++ for (; reg < argc; reg++) |
| ++ *funcstack++ = va_arg (vl, unsigned long); |
| ++ |
| ++ va_end (vl); |
| ++} |
| ++weak_alias (__makecontext, makecontext) |
| +diff --git a/libc/sysdeps/linux/arm/setcontext.S b/libc/sysdeps/linux/arm/setcontext.S |
| +new file mode 100644 |
| +index 0000000..a5c33a0 |
| +--- /dev/null |
| ++++ b/libc/sysdeps/linux/arm/setcontext.S |
| +@@ -0,0 +1,76 @@ |
| ++/* Copyright (C) 2012 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/>. */ |
| ++ |
| ++#include <sysdep.h> |
| ++ |
| ++#include "ucontext_i.h" |
| ++ |
| ++ .syntax unified |
| ++ .text |
| ++ |
| ++/* int setcontext (const ucontext_t *ucp) */ |
| ++ |
| ++ENTRY(__setcontext) |
| ++ mov r4, r0 |
| ++ |
| ++#if defined __UCLIBC_HAS_FLOATS__ && ! defined __UCLIBC_HAS_SOFT_FLOAT__ |
| ++# ifdef __VFP_FP__ |
| ++ /* Following instruction is vldmia r0!, {d8-d15}. */ |
| ++ ldc p11, cr8, [r0], #64 |
| ++ /* Restore the floating-point status register. */ |
| ++ ldr r1, [r0], #4 |
| ++ /* Following instruction is fmxr fpscr, r1. */ |
| ++ mcr p10, 7, r1, cr1, cr0, 0 |
| ++# endif |
| ++#endif |
| ++ |
| ++#ifdef __IWMMXT__ |
| ++ /* Restore the call-preserved iWMMXt registers. */ |
| ++ /* Following instructions are wldrd wr10, [r0], #8 (etc.) */ |
| ++ ldcl p1, cr10, [r0], #8 |
| ++ ldcl p1, cr11, [r0], #8 |
| ++ ldcl p1, cr12, [r0], #8 |
| ++ ldcl p1, cr13, [r0], #8 |
| ++ ldcl p1, cr14, [r0], #8 |
| ++ ldcl p1, cr15, [r0], #8 |
| ++#endif |
| ++ |
| ++ /* Now bring back the signal status. */ |
| ++ mov r0, #SIG_SETMASK |
| ++ add r1, r4, #UCONTEXT_SIGMASK |
| ++ mov r2, #0 |
| ++ bl PLTJMP(sigprocmask) |
| ++ |
| ++ /* Loading r0-r3 makes makecontext easier. */ |
| ++ add r14, r4, #MCONTEXT_ARM_R0 |
| ++ ldmia r14, {r0-r11} |
| ++ ldr r13, [r14, #(MCONTEXT_ARM_SP - MCONTEXT_ARM_R0)] |
| ++ add r14, r14, #(MCONTEXT_ARM_LR - MCONTEXT_ARM_R0) |
| ++ ldmia r14, {r14, pc} |
| ++ |
| ++END(setcontext) |
| ++weak_alias(__setcontext, setcontext) |
| ++ |
| ++ /* Called when a makecontext() context returns. Start the |
| ++ context in R4 or fall through to exit(). */ |
| ++ENTRY(__startcontext) |
| ++ movs r0, r4 |
| ++ bne PLTJMP(__setcontext) |
| ++ |
| ++ @ New context was 0 - exit |
| ++ b PLTJMP(_exit) |
| ++END(__startcontext) |
| +diff --git a/libc/sysdeps/linux/arm/swapcontext.S b/libc/sysdeps/linux/arm/swapcontext.S |
| +new file mode 100644 |
| +index 0000000..ba6e31c |
| +--- /dev/null |
| ++++ b/libc/sysdeps/linux/arm/swapcontext.S |
| +@@ -0,0 +1,63 @@ |
| ++/* Copyright (C) 2012 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/>. */ |
| ++ |
| ++#include <sysdep.h> |
| ++ |
| ++#include "ucontext_i.h" |
| ++ |
| ++ .syntax unified |
| ++ .text |
| ++ |
| ++/* int swapcontext (ucontext_t *oucp, const ucontext_t *ucp) */ |
| ++ |
| ++ENTRY(swapcontext) |
| ++ |
| ++ /* Have getcontext() do most of the work then fix up |
| ++ LR afterwards. Save R3 to keep the stack aligned. */ |
| ++ push {r0,r1,r3,r14} |
| ++ cfi_adjust_cfa_offset (16) |
| ++ cfi_rel_offset (r0,0) |
| ++ cfi_rel_offset (r1,4) |
| ++ cfi_rel_offset (r3,8) |
| ++ cfi_rel_offset (r14,12) |
| ++ |
| ++ bl __getcontext |
| ++ mov r4, r0 |
| ++ |
| ++ pop {r0,r1,r3,r14} |
| ++ cfi_adjust_cfa_offset (-16) |
| ++ cfi_restore (r0) |
| ++ cfi_restore (r1) |
| ++ cfi_restore (r3) |
| ++ cfi_restore (r14) |
| ++ |
| ++ /* Exit if getcontext() failed. */ |
| ++ cmp r4, #0 |
| ++ itt ne |
| ++ movne r0, r4 |
| ++ RETINSTR(ne, r14) |
| ++ |
| ++ /* Fix up LR and the PC. */ |
| ++ str r13,[r0, #MCONTEXT_ARM_SP] |
| ++ str r14,[r0, #MCONTEXT_ARM_LR] |
| ++ str r14,[r0, #MCONTEXT_ARM_PC] |
| ++ |
| ++ /* And swap using swapcontext(). */ |
| ++ mov r0, r1 |
| ++ b __setcontext |
| ++ |
| ++END(swapcontext) |
| +diff --git a/libc/sysdeps/linux/arm/ucontext_i.sym b/libc/sysdeps/linux/arm/ucontext_i.sym |
| +new file mode 100644 |
| +index 0000000..9650322 |
| +--- /dev/null |
| ++++ b/libc/sysdeps/linux/arm/ucontext_i.sym |
| +@@ -0,0 +1,30 @@ |
| ++#include <inttypes.h> |
| ++#include <signal.h> |
| ++#include <stddef.h> |
| ++#include <sys/ucontext.h> |
| ++ |
| ++SIG_BLOCK |
| ++SIG_SETMASK |
| ++ |
| ++-- Offsets of the fields in the ucontext_t structure. |
| ++#define ucontext(member) offsetof (ucontext_t, member) |
| ++#define mcontext(member) ucontext (uc_mcontext.member) |
| ++ |
| ++UCONTEXT_FLAGS ucontext (uc_flags) |
| ++UCONTEXT_LINK ucontext (uc_link) |
| ++UCONTEXT_STACK ucontext (uc_stack) |
| ++UCONTEXT_MCONTEXT ucontext (uc_mcontext) |
| ++UCONTEXT_SIGMASK ucontext (uc_sigmask) |
| ++ |
| ++UCONTEXT_REGSPACE ucontext (uc_regspace) |
| ++ |
| ++MCONTEXT_TRAP_NO mcontext (trap_no) |
| ++MCONTEXT_ERROR_CODE mcontext (error_code) |
| ++MCONTEXT_OLDMASK mcontext (oldmask) |
| ++MCONTEXT_ARM_R0 mcontext (arm_r0) |
| ++MCONTEXT_ARM_R4 mcontext (arm_r4) |
| ++MCONTEXT_ARM_SP mcontext (arm_sp) |
| ++MCONTEXT_ARM_LR mcontext (arm_lr) |
| ++MCONTEXT_ARM_PC mcontext (arm_pc) |
| ++MCONTEXT_ARM_CPSR mcontext (arm_cpsr) |
| ++MCONTEXT_FAULT_ADDRESS mcontext (fault_address) |
| +diff --git a/libc/sysdeps/linux/i386/Makefile.arch b/libc/sysdeps/linux/i386/Makefile.arch |
| +index a3bf32f..e7fd28e 100644 |
| +--- a/libc/sysdeps/linux/i386/Makefile.arch |
| ++++ b/libc/sysdeps/linux/i386/Makefile.arch |
| +@@ -18,3 +18,7 @@ endif |
| + ifneq ($(UCLIBC_HAS_THREADS_NATIVE),y) |
| + SSRC += vfork.S clone.S |
| + endif |
| ++ |
| ++ifeq ($(UCLIBC_HAS_CONTEXT_FUNCS),y) |
| ++SSRC += makecontext.S setcontext.S getcontext.S swapcontext.S |
| ++endif |
| +diff --git a/libc/sysdeps/linux/i386/getcontext.S b/libc/sysdeps/linux/i386/getcontext.S |
| +new file mode 100644 |
| +index 0000000..3221b59 |
| +--- /dev/null |
| ++++ b/libc/sysdeps/linux/i386/getcontext.S |
| +@@ -0,0 +1,84 @@ |
| ++/* Save current context. |
| ++ Copyright (C) 2001-2012 Free Software Foundation, Inc. |
| ++ This file is part of the GNU C Library. |
| ++ Contributed by Ulrich Drepper <drepper@redhat.com>, 2001. |
| ++ |
| ++ 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/>. */ |
| ++ |
| ++#include <sysdep.h> |
| ++ |
| ++#include "ucontext_i.h" |
| ++ |
| ++ |
| ++ENTRY(__getcontext) |
| ++ /* Load address of the context data structure. */ |
| ++ movl 4(%esp), %eax |
| ++ |
| ++ /* Return value of getcontext. EAX is the only register whose |
| ++ value is not preserved. */ |
| ++ movl $0, oEAX(%eax) |
| ++ |
| ++ /* Save the 32-bit register values and the return address. */ |
| ++ movl %ecx, oECX(%eax) |
| ++ movl %edx, oEDX(%eax) |
| ++ movl %edi, oEDI(%eax) |
| ++ movl %esi, oESI(%eax) |
| ++ movl %ebp, oEBP(%eax) |
| ++ movl (%esp), %ecx |
| ++ movl %ecx, oEIP(%eax) |
| ++ leal 4(%esp), %ecx /* Exclude the return address. */ |
| ++ movl %ecx, oESP(%eax) |
| ++ movl %ebx, oEBX(%eax) |
| ++ |
| ++ /* Save the FS segment register. We don't touch the GS register |
| ++ since it is used for threads. */ |
| ++ xorl %edx, %edx |
| ++ movw %fs, %dx |
| ++ movl %edx, oFS(%eax) |
| ++ |
| ++ /* We have separate floating-point register content memory on the |
| ++ stack. We use the __fpregs_mem block in the context. Set the |
| ++ links up correctly. */ |
| ++ leal oFPREGSMEM(%eax), %ecx |
| ++ movl %ecx, oFPREGS(%eax) |
| ++ /* Save the floating-point context. */ |
| ++ fnstenv (%ecx) |
| ++ /* And load it right back since the processor changes the mask. |
| ++ Intel thought this opcode to be used in interrupt handlers which |
| ++ would block all exceptions. */ |
| ++ fldenv (%ecx) |
| ++ |
| ++ /* Save the current signal mask. */ |
| ++ pushl %ebx |
| ++ cfi_adjust_cfa_offset (4) |
| ++ cfi_rel_offset (ebx, 0) |
| ++ leal oSIGMASK(%eax), %edx |
| ++ xorl %ecx, %ecx |
| ++ movl $SIG_BLOCK, %ebx |
| ++ movl $__NR_sigprocmask, %eax |
| ++ ENTER_KERNEL |
| ++ popl %ebx |
| ++ cfi_adjust_cfa_offset (-4) |
| ++ cfi_restore (ebx) |
| ++ cmpl $-4095, %eax /* Check %eax for error. */ |
| ++ jae SYSCALL_ERROR_LABEL /* Jump to error handler if error. */ |
| ++ |
| ++ /* All done, return 0 for success. */ |
| ++ xorl %eax, %eax |
| ++L(pseudo_end): |
| ++ ret |
| ++PSEUDO_END(__getcontext) |
| ++ |
| ++weak_alias (__getcontext, getcontext) |
| +diff --git a/libc/sysdeps/linux/i386/makecontext.S b/libc/sysdeps/linux/i386/makecontext.S |
| +new file mode 100644 |
| +index 0000000..d12799d |
| +--- /dev/null |
| ++++ b/libc/sysdeps/linux/i386/makecontext.S |
| +@@ -0,0 +1,123 @@ |
| ++/* Create new context. |
| ++ Copyright (C) 2001,2002,2005,2007,2008,2009 Free Software Foundation, Inc. |
| ++ This file is part of the GNU C Library. |
| ++ Contributed by Ulrich Drepper <drepper@redhat.com>, 2001. |
| ++ |
| ++ 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/>. */ |
| ++ |
| ++#include <sysdep.h> |
| ++ |
| ++#include "ucontext_i.h" |
| ++ |
| ++ |
| ++ENTRY(__makecontext) |
| ++ movl 4(%esp), %eax |
| ++ |
| ++ /* Load the address of the function we are supposed to run. */ |
| ++ movl 8(%esp), %ecx |
| ++ |
| ++ /* Compute the address of the stack. The information comes from |
| ++ to us_stack element. */ |
| ++ movl oSS_SP(%eax), %edx |
| ++ movl %ecx, oEIP(%eax) |
| ++ addl oSS_SIZE(%eax), %edx |
| ++ |
| ++ /* Remember the number of parameters for the exit handler since |
| ++ it has to remove them. We store the number in the EBX register |
| ++ which the function we will call must preserve. */ |
| ++ movl 12(%esp), %ecx |
| ++ movl %ecx, oEBX(%eax) |
| ++ |
| ++ /* Make room on the new stack for the parameters. |
| ++ Room for the arguments, return address (== L(exitcode)) and |
| ++ oLINK pointer is needed. One of the pointer sizes is subtracted |
| ++ after aligning the stack. */ |
| ++ negl %ecx |
| ++ leal -4(%edx,%ecx,4), %edx |
| ++ negl %ecx |
| ++ |
| ++ /* Align the stack. */ |
| ++ andl $0xfffffff0, %edx |
| ++ subl $4, %edx |
| ++ |
| ++ /* Store the future stack pointer. */ |
| ++ movl %edx, oESP(%eax) |
| ++ |
| ++ /* Put the next context on the new stack (from the uc_link |
| ++ element). */ |
| ++ movl oLINK(%eax), %eax |
| ++ movl %eax, 4(%edx,%ecx,4) |
| ++ |
| ++ /* Copy all the parameters. */ |
| ++ jecxz 2f |
| ++1: movl 12(%esp,%ecx,4), %eax |
| ++ movl %eax, (%edx,%ecx,4) |
| ++ decl %ecx |
| ++ jnz 1b |
| ++2: |
| ++ |
| ++ /* If the function we call returns we must continue with the |
| ++ context which is given in the uc_link element. To do this |
| ++ set the return address for the function the user provides |
| ++ to a little bit of helper code which does the magic (see |
| ++ below). */ |
| ++#ifdef __PIC__ |
| ++ call 1f |
| ++ cfi_adjust_cfa_offset (4) |
| ++1: popl %ecx |
| ++ cfi_adjust_cfa_offset (-4) |
| ++ addl $L(exitcode)-1b, %ecx |
| ++ movl %ecx, (%edx) |
| ++#else |
| ++ movl $L(exitcode), (%edx) |
| ++#endif |
| ++ /* 'makecontext' returns no value. */ |
| ++L(pseudo_end): |
| ++ ret |
| ++ |
| ++ /* This is the helper code which gets called if a function which |
| ++ is registered with 'makecontext' returns. In this case we |
| ++ have to install the context listed in the uc_link element of |
| ++ the context 'makecontext' manipulated at the time of the |
| ++ 'makecontext' call. If the pointer is NULL the process must |
| ++ terminate. */ |
| ++ cfi_endproc |
| ++L(exitcode): |
| ++ /* This removes the parameters passed to the function given to |
| ++ 'makecontext' from the stack. EBX contains the number of |
| ++ parameters (see above). */ |
| ++ leal (%esp,%ebx,4), %esp |
| ++ |
| ++#ifdef __PIC__ |
| ++ call 1f |
| ++1: popl %ebx |
| ++ addl $_GLOBAL_OFFSET_TABLE_+[.-1b], %ebx |
| ++#endif |
| ++ cmpl $0, (%esp) /* Check the next context. */ |
| ++ je 2f /* If it is zero exit. */ |
| ++ |
| ++ call JUMPTARGET(__setcontext) |
| ++ /* If this returns (which can happen if the syscall fails) we'll |
| ++ exit the program with the return error value (-1). */ |
| ++ |
| ++ movl %eax, (%esp) |
| ++2: call HIDDEN_JUMPTARGET(exit) |
| ++ /* The 'exit' call should never return. In case it does cause |
| ++ the process to terminate. */ |
| ++ hlt |
| ++ cfi_startproc |
| ++END(__makecontext) |
| ++ |
| ++weak_alias (__makecontext, makecontext) |
| +diff --git a/libc/sysdeps/linux/i386/setcontext.S b/libc/sysdeps/linux/i386/setcontext.S |
| +new file mode 100644 |
| +index 0000000..ae953cc |
| +--- /dev/null |
| ++++ b/libc/sysdeps/linux/i386/setcontext.S |
| +@@ -0,0 +1,96 @@ |
| ++/* Install given context. |
| ++ Copyright (C) 2001-2012 Free Software Foundation, Inc. |
| ++ This file is part of the GNU C Library. |
| ++ Contributed by Ulrich Drepper <drepper@redhat.com>, 2001. |
| ++ |
| ++ 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/>. */ |
| ++ |
| ++#include <sysdep.h> |
| ++ |
| ++#include "ucontext_i.h" |
| ++ |
| ++ |
| ++ENTRY(__setcontext) |
| ++ /* Load address of the context data structure. */ |
| ++ movl 4(%esp), %eax |
| ++ |
| ++ /* Get the current signal mask. Note that we preserve EBX in case |
| ++ the system call fails and we return from the function with an |
| ++ error. */ |
| ++ pushl %ebx |
| ++ cfi_adjust_cfa_offset (4) |
| ++ xorl %edx, %edx |
| ++ leal oSIGMASK(%eax), %ecx |
| ++ movl $SIG_SETMASK, %ebx |
| ++ cfi_rel_offset (ebx, 0) |
| ++ movl $__NR_sigprocmask, %eax |
| ++ ENTER_KERNEL |
| ++ popl %ebx |
| ++ cfi_adjust_cfa_offset (-4) |
| ++ cfi_restore (ebx) |
| ++ cmpl $-4095, %eax /* Check %eax for error. */ |
| ++ jae SYSCALL_ERROR_LABEL /* Jump to error handler if error. */ |
| ++ |
| ++ /* EAX was modified, reload it. */ |
| ++ movl 4(%esp), %eax |
| ++ |
| ++ /* Restore the floating-point context. Not the registers, only the |
| ++ rest. */ |
| ++ movl oFPREGS(%eax), %ecx |
| ++ fldenv (%ecx) |
| ++ |
| ++ /* Restore the FS segment register. We don't touch the GS register |
| ++ since it is used for threads. */ |
| ++ movl oFS(%eax), %ecx |
| ++ movw %cx, %fs |
| ++ |
| ++ /* Fetch the address to return to. */ |
| ++ movl oEIP(%eax), %ecx |
| ++ |
| ++ /* Load the new stack pointer. */ |
| ++ cfi_def_cfa (eax, 0) |
| ++ cfi_offset (edi, oEDI) |
| ++ cfi_offset (esi, oESI) |
| ++ cfi_offset (ebp, oEBP) |
| ++ cfi_offset (ebx, oEBX) |
| ++ cfi_offset (edx, oEDX) |
| ++ cfi_offset (ecx, oECX) |
| ++ movl oESP(%eax), %esp |
| ++ |
| ++ /* Push the return address on the new stack so we can return there. */ |
| ++ pushl %ecx |
| ++ |
| ++ /* Load the values of all the 32-bit registers (except ESP). |
| ++ Since we are loading from EAX, it must be last. */ |
| ++ movl oEDI(%eax), %edi |
| ++ movl oESI(%eax), %esi |
| ++ movl oEBP(%eax), %ebp |
| ++ movl oEBX(%eax), %ebx |
| ++ movl oEDX(%eax), %edx |
| ++ movl oECX(%eax), %ecx |
| ++ movl oEAX(%eax), %eax |
| ++ |
| ++ /* End FDE here, we fall into another context. */ |
| ++ cfi_endproc |
| ++ cfi_startproc |
| ++ |
| ++ /* The following 'ret' will pop the address of the code and jump |
| ++ to it. */ |
| ++ |
| ++L(pseudo_end): |
| ++ ret |
| ++PSEUDO_END(__setcontext) |
| ++ |
| ++weak_alias (__setcontext, setcontext) |
| +diff --git a/libc/sysdeps/linux/i386/swapcontext.S b/libc/sysdeps/linux/i386/swapcontext.S |
| +new file mode 100644 |
| +index 0000000..ee5d0e4 |
| +--- /dev/null |
| ++++ b/libc/sysdeps/linux/i386/swapcontext.S |
| +@@ -0,0 +1,110 @@ |
| ++/* Save current context and install the given one. |
| ++ Copyright (C) 2001-2012 Free Software Foundation, Inc. |
| ++ This file is part of the GNU C Library. |
| ++ Contributed by Ulrich Drepper <drepper@redhat.com>, 2001. |
| ++ |
| ++ 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/>. */ |
| ++ |
| ++#include <sysdep.h> |
| ++ |
| ++#include "ucontext_i.h" |
| ++ |
| ++ |
| ++ENTRY(__swapcontext) |
| ++ /* Load address of the context data structure we save in. */ |
| ++ movl 4(%esp), %eax |
| ++ |
| ++ /* Return value of swapcontext. EAX is the only register whose |
| ++ value is not preserved. */ |
| ++ movl $0, oEAX(%eax) |
| ++ |
| ++ /* Save the 32-bit register values and the return address. */ |
| ++ movl %ecx, oECX(%eax) |
| ++ movl %edx, oEDX(%eax) |
| ++ movl %edi, oEDI(%eax) |
| ++ movl %esi, oESI(%eax) |
| ++ movl %ebp, oEBP(%eax) |
| ++ movl (%esp), %ecx |
| ++ movl %ecx, oEIP(%eax) |
| ++ leal 4(%esp), %ecx |
| ++ movl %ecx, oESP(%eax) |
| ++ movl %ebx, oEBX(%eax) |
| ++ |
| ++ /* Save the FS segment register. */ |
| ++ xorl %edx, %edx |
| ++ movw %fs, %dx |
| ++ movl %edx, oFS(%eax) |
| ++ |
| ++ /* We have separate floating-point register content memory on the |
| ++ stack. We use the __fpregs_mem block in the context. Set the |
| ++ links up correctly. */ |
| ++ leal oFPREGSMEM(%eax), %ecx |
| ++ movl %ecx, oFPREGS(%eax) |
| ++ /* Save the floating-point context. */ |
| ++ fnstenv (%ecx) |
| ++ |
| ++ /* Load address of the context data structure we have to load. */ |
| ++ movl 8(%esp), %ecx |
| ++ |
| ++ /* Save the current signal mask and install the new one. */ |
| ++ pushl %ebx |
| ++ leal oSIGMASK(%eax), %edx |
| ++ leal oSIGMASK(%ecx), %ecx |
| ++ movl $SIG_SETMASK, %ebx |
| ++ movl $__NR_sigprocmask, %eax |
| ++ ENTER_KERNEL |
| ++ popl %ebx |
| ++ cmpl $-4095, %eax /* Check %eax for error. */ |
| ++ jae SYSCALL_ERROR_LABEL /* Jump to error handler if error. */ |
| ++ |
| ++ /* EAX was modified, reload it. */ |
| ++ movl 8(%esp), %eax |
| ++ |
| ++ /* Restore the floating-point context. Not the registers, only the |
| ++ rest. */ |
| ++ movl oFPREGS(%eax), %ecx |
| ++ fldenv (%ecx) |
| ++ |
| ++ /* Restore the FS segment register. We don't touch the GS register |
| ++ since it is used for threads. */ |
| ++ movl oFS(%eax), %edx |
| ++ movw %dx, %fs |
| ++ |
| ++ /* Fetch the address to return to. */ |
| ++ movl oEIP(%eax), %ecx |
| ++ |
| ++ /* Load the new stack pointer. */ |
| ++ movl oESP(%eax), %esp |
| ++ |
| ++ /* Push the return address on the new stack so we can return there. */ |
| ++ pushl %ecx |
| ++ |
| ++ /* Load the values of all the 32-bit registers (except ESP). |
| ++ Since we are loading from EAX, it must be last. */ |
| ++ movl oEDI(%eax), %edi |
| ++ movl oESI(%eax), %esi |
| ++ movl oEBP(%eax), %ebp |
| ++ movl oEBX(%eax), %ebx |
| ++ movl oEDX(%eax), %edx |
| ++ movl oECX(%eax), %ecx |
| ++ movl oEAX(%eax), %eax |
| ++ |
| ++ /* The following 'ret' will pop the address of the code and jump |
| ++ to it. */ |
| ++L(pseudo_end): |
| ++ ret |
| ++PSEUDO_END(__swapcontext) |
| ++ |
| ++weak_alias (__swapcontext, swapcontext) |
| +diff --git a/libc/sysdeps/linux/i386/ucontext_i.sym b/libc/sysdeps/linux/i386/ucontext_i.sym |
| +new file mode 100644 |
| +index 0000000..b11a550 |
| +--- /dev/null |
| ++++ b/libc/sysdeps/linux/i386/ucontext_i.sym |
| +@@ -0,0 +1,30 @@ |
| ++#include <stddef.h> |
| ++#include <signal.h> |
| ++#include <sys/ucontext.h> |
| ++ |
| ++-- |
| ++ |
| ++SIG_BLOCK |
| ++SIG_SETMASK |
| ++ |
| ++#define ucontext(member) offsetof (ucontext_t, member) |
| ++#define mcontext(member) ucontext (uc_mcontext.member) |
| ++#define mreg(reg) mcontext (gregs[REG_##reg]) |
| ++ |
| ++oLINK ucontext (uc_link) |
| ++oSS_SP ucontext (uc_stack.ss_sp) |
| ++oSS_SIZE ucontext (uc_stack.ss_size) |
| ++oGS mreg (GS) |
| ++oFS mreg (FS) |
| ++oEDI mreg (EDI) |
| ++oESI mreg (ESI) |
| ++oEBP mreg (EBP) |
| ++oESP mreg (ESP) |
| ++oEBX mreg (EBX) |
| ++oEDX mreg (EDX) |
| ++oECX mreg (ECX) |
| ++oEAX mreg (EAX) |
| ++oEIP mreg (EIP) |
| ++oFPREGS mcontext (fpregs) |
| ++oSIGMASK ucontext (uc_sigmask) |
| ++oFPREGSMEM ucontext (__fpregs_mem) |
| +diff --git a/libc/sysdeps/linux/mips/Makefile.arch b/libc/sysdeps/linux/mips/Makefile.arch |
| +index fce99f8..00b9331 100644 |
| +--- a/libc/sysdeps/linux/mips/Makefile.arch |
| ++++ b/libc/sysdeps/linux/mips/Makefile.arch |
| +@@ -27,3 +27,7 @@ ASFLAGS-syscall_error.S += -D_LIBC_REENTRANT |
| + |
| + ARCH_HEADERS := sgidefs.h |
| + # regdef.h |
| ++ |
| ++ifeq ($(UCLIBC_HAS_CONTEXT_FUNCS),y) |
| ++SSRC += makecontext.S setcontext.S getcontext.S swapcontext.S |
| ++endif |
| +diff --git a/libc/sysdeps/linux/mips/getcontext.S b/libc/sysdeps/linux/mips/getcontext.S |
| +new file mode 100644 |
| +index 0000000..c4ad081 |
| +--- /dev/null |
| ++++ b/libc/sysdeps/linux/mips/getcontext.S |
| +@@ -0,0 +1,148 @@ |
| ++/* Save current context. |
| ++ Copyright (C) 2009 Free Software Foundation, Inc. |
| ++ This file is part of the GNU C Library. |
| ++ Contributed by Maciej W. Rozycki <macro@codesourcery.com>. |
| ++ |
| ++ 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/>. */ |
| ++ |
| ++#include <sysdep.h> |
| ++#include <sys/asm.h> |
| ++#include <sys/fpregdef.h> |
| ++#include <sys/regdef.h> |
| ++ |
| ++#include "ucontext_i.h" |
| ++ |
| ++/* int getcontext (ucontext_t *ucp) */ |
| ++ |
| ++ .text |
| ++LOCALSZ = 0 |
| ++MASK = 0x00000000 |
| ++#ifdef __PIC__ |
| ++LOCALSZ = 1 /* save gp */ |
| ++# if _MIPS_SIM != _ABIO32 |
| ++MASK = 0x10000000 |
| ++# endif |
| ++#endif |
| ++FRAMESZ = ((LOCALSZ * SZREG) + ALSZ) & ALMASK |
| ++GPOFF = FRAMESZ - (1 * SZREG) |
| ++ |
| ++NESTED (__getcontext, FRAMESZ, ra) |
| ++ .mask MASK, 0 |
| ++ .fmask 0x00000000, 0 |
| ++ |
| ++#ifdef __PIC__ |
| ++ SETUP_GP |
| ++ |
| ++ move a2, sp |
| ++# define _SP a2 |
| ++ |
| ++# if _MIPS_SIM != _ABIO32 |
| ++ move a3, gp |
| ++# define _GP a3 |
| ++# endif |
| ++ |
| ++ PTR_ADDIU sp, -FRAMESZ |
| ++ SETUP_GP64 (GPOFF, __getcontext) |
| ++ SAVE_GP (GPOFF) |
| ++ |
| ++#else /* ! __PIC__ */ |
| ++# define _SP sp |
| ++# define _GP gp |
| ++ |
| ++#endif /* ! __PIC__ */ |
| ++ |
| ++#ifdef PROF |
| ++ .set noat |
| ++ move AT, ra |
| ++ jal _mcount |
| ++ .set at |
| ++#endif |
| ++ |
| ++ /* Store a magic flag. */ |
| ++ li v1, 1 |
| ++ REG_S v1, (0 * SZREG + MCONTEXT_GREGS)(a0) /* zero */ |
| ++ |
| ++ REG_S s0, (16 * SZREG + MCONTEXT_GREGS)(a0) |
| ++ REG_S s1, (17 * SZREG + MCONTEXT_GREGS)(a0) |
| ++ REG_S s2, (18 * SZREG + MCONTEXT_GREGS)(a0) |
| ++ REG_S s3, (19 * SZREG + MCONTEXT_GREGS)(a0) |
| ++ REG_S s4, (20 * SZREG + MCONTEXT_GREGS)(a0) |
| ++ REG_S s5, (21 * SZREG + MCONTEXT_GREGS)(a0) |
| ++ REG_S s6, (22 * SZREG + MCONTEXT_GREGS)(a0) |
| ++ REG_S s7, (23 * SZREG + MCONTEXT_GREGS)(a0) |
| ++#if ! defined (__PIC__) || _MIPS_SIM != _ABIO32 |
| ++ REG_S _GP, (28 * SZREG + MCONTEXT_GREGS)(a0) |
| ++#endif |
| ++ REG_S _SP, (29 * SZREG + MCONTEXT_GREGS)(a0) |
| ++ REG_S fp, (30 * SZREG + MCONTEXT_GREGS)(a0) |
| ++ REG_S ra, (31 * SZREG + MCONTEXT_GREGS)(a0) |
| ++ REG_S ra, MCONTEXT_PC(a0) |
| ++ |
| ++#ifdef __mips_hard_float |
| ++# if _MIPS_SIM == _ABI64 |
| ++ s.d fs0, (24 * SZREG + MCONTEXT_FPREGS)(a0) |
| ++ s.d fs1, (25 * SZREG + MCONTEXT_FPREGS)(a0) |
| ++ s.d fs2, (26 * SZREG + MCONTEXT_FPREGS)(a0) |
| ++ s.d fs3, (27 * SZREG + MCONTEXT_FPREGS)(a0) |
| ++ s.d fs4, (28 * SZREG + MCONTEXT_FPREGS)(a0) |
| ++ s.d fs5, (29 * SZREG + MCONTEXT_FPREGS)(a0) |
| ++ s.d fs6, (30 * SZREG + MCONTEXT_FPREGS)(a0) |
| ++ s.d fs7, (31 * SZREG + MCONTEXT_FPREGS)(a0) |
| ++ |
| ++# else /* _MIPS_SIM != _ABI64 */ |
| ++ s.d fs0, (20 * SZREG + MCONTEXT_FPREGS)(a0) |
| ++ s.d fs1, (22 * SZREG + MCONTEXT_FPREGS)(a0) |
| ++ s.d fs2, (24 * SZREG + MCONTEXT_FPREGS)(a0) |
| ++ s.d fs3, (26 * SZREG + MCONTEXT_FPREGS)(a0) |
| ++ s.d fs4, (28 * SZREG + MCONTEXT_FPREGS)(a0) |
| ++ s.d fs5, (30 * SZREG + MCONTEXT_FPREGS)(a0) |
| ++ |
| ++# endif /* _MIPS_SIM != _ABI64 */ |
| ++ |
| ++ cfc1 v1, fcr31 |
| ++ sw v1, MCONTEXT_FPC_CSR(a0) |
| ++#endif /* __mips_hard_float */ |
| ++ |
| ++/* rt_sigprocmask (SIG_BLOCK, NULL, &ucp->uc_sigmask, _NSIG8) */ |
| ++ li a3, _NSIG8 |
| ++ PTR_ADDU a2, a0, UCONTEXT_SIGMASK |
| ++ move a1, zero |
| ++ li a0, SIG_BLOCK |
| ++ |
| ++ li v0, SYS_ify (rt_sigprocmask) |
| ++ syscall |
| ++ bnez a3, 99f |
| ++ |
| ++#ifdef __PIC__ |
| ++ RESTORE_GP64 |
| ++ PTR_ADDIU sp, FRAMESZ |
| ++#endif |
| ++ move v0, zero |
| ++ jr ra |
| ++ |
| ++99: |
| ++#ifdef __PIC__ |
| ++ PTR_LA t9, JUMPTARGET (__syscall_error) |
| ++ RESTORE_GP64 |
| ++ PTR_ADDIU sp, FRAMESZ |
| ++ jr t9 |
| ++ |
| ++#else /* ! __PIC__ */ |
| ++ |
| ++ j JUMPTARGET (__syscall_error) |
| ++#endif /* ! __PIC__ */ |
| ++PSEUDO_END (__getcontext) |
| ++ |
| ++weak_alias (__getcontext, getcontext) |
| +diff --git a/libc/sysdeps/linux/mips/kernel_rt_sigframe.h b/libc/sysdeps/linux/mips/kernel_rt_sigframe.h |
| +new file mode 100644 |
| +index 0000000..77ffaf6 |
| +--- /dev/null |
| ++++ b/libc/sysdeps/linux/mips/kernel_rt_sigframe.h |
| +@@ -0,0 +1,10 @@ |
| ++/* Linux kernel RT signal frame. */ |
| ++typedef struct kernel_rt_sigframe |
| ++ { |
| ++ uint32_t rs_ass[4]; |
| ++ uint32_t rs_code[2]; |
| ++ siginfo_t rs_info; |
| ++ struct ucontext rs_uc; |
| ++ uint32_t rs_altcode[8] __attribute__ ((__aligned__ (1 << 7))); |
| ++ } |
| ++kernel_rt_sigframe_t; |
| +diff --git a/libc/sysdeps/linux/mips/makecontext.S b/libc/sysdeps/linux/mips/makecontext.S |
| +new file mode 100644 |
| +index 0000000..6427339 |
| +--- /dev/null |
| ++++ b/libc/sysdeps/linux/mips/makecontext.S |
| +@@ -0,0 +1,188 @@ |
| ++/* Modify saved context. |
| ++ Copyright (C) 2009 Free Software Foundation, Inc. |
| ++ This file is part of the GNU C Library. |
| ++ Contributed by Maciej W. Rozycki <macro@codesourcery.com>. |
| ++ |
| ++ 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/>. */ |
| ++ |
| ++#include <sysdep.h> |
| ++#include <sys/asm.h> |
| ++#include <sys/fpregdef.h> |
| ++#include <sys/regdef.h> |
| ++ |
| ++#include "ucontext_i.h" |
| ++ |
| ++/* int makecontext (ucontext_t *ucp, (void *func) (), int argc, ...) */ |
| ++ |
| ++ .text |
| ++LOCALSZ = 0 |
| ++ARGSZ = 0 |
| ++MASK = 0x00000000 |
| ++#ifdef __PIC__ |
| ++LOCALSZ = 1 /* save gp */ |
| ++#endif |
| ++#if _MIPS_SIM != _ABIO32 |
| ++ARGSZ = 5 /* save a3-a7 */ |
| ++# ifdef __PIC__ |
| ++MASK = 0x10000000 |
| ++# endif |
| ++#endif |
| ++FRAMESZ = (((ARGSZ + LOCALSZ) * SZREG) + ALSZ) & ALMASK |
| ++GPOFF = FRAMESZ - ((ARGSZ + 1) * SZREG) |
| ++#if _MIPS_SIM != _ABIO32 |
| ++A3OFF = FRAMESZ - (5 * SZREG) /* callee-allocated */ |
| ++A4OFF = FRAMESZ - (4 * SZREG) |
| ++A5OFF = FRAMESZ - (3 * SZREG) |
| ++A6OFF = FRAMESZ - (2 * SZREG) |
| ++A7OFF = FRAMESZ - (1 * SZREG) |
| ++NARGREGS = 8 |
| ++#else |
| ++A3OFF = FRAMESZ + (3 * SZREG) /* caller-allocated */ |
| ++NARGREGS = 4 |
| ++#endif |
| ++ |
| ++NESTED (__makecontext, FRAMESZ, ra) |
| ++ .mask MASK, -(ARGSZ * SZREG) |
| ++ .fmask 0x00000000, 0 |
| ++ |
| ++98: |
| ++#ifdef __PIC__ |
| ++ SETUP_GP |
| ++#endif |
| ++ |
| ++ PTR_ADDIU sp, -FRAMESZ |
| ++ |
| ++#ifdef __PIC__ |
| ++ SETUP_GP64 (GPOFF, __makecontext) |
| ++ SAVE_GP (GPOFF) |
| ++#endif |
| ++ |
| ++#ifdef PROF |
| ++ .set noat |
| ++ move AT, ra |
| ++ jal _mcount |
| ++ .set at |
| ++#endif |
| ++ |
| ++ /* Store args to be passed. */ |
| ++ REG_S a3, A3OFF(sp) |
| ++#if _MIPS_SIM != _ABIO32 |
| ++ REG_S a4, A4OFF(sp) |
| ++ REG_S a5, A5OFF(sp) |
| ++ REG_S a6, A6OFF(sp) |
| ++ REG_S a7, A7OFF(sp) |
| ++#endif |
| ++ |
| ++ /* Store a magic flag. */ |
| ++ li v1, 1 |
| ++ REG_S v1, (0 * SZREG + MCONTEXT_GREGS)(a0) /* zero */ |
| ++ |
| ++ /* Set up the stack. */ |
| ++ PTR_L t0, STACK_SP(a0) |
| ++ PTR_L t2, STACK_SIZE(a0) |
| ++ PTR_ADDIU t1, sp, A3OFF |
| ++ PTR_ADDU t0, t2 |
| ++ and t0, ALMASK |
| ++ blez a2, 2f /* no arguments */ |
| ++ |
| ++ /* Store register arguments. */ |
| ++ PTR_ADDIU t2, a0, MCONTEXT_GREGS + 4 * SZREG |
| ++ move t3, zero |
| ++0: |
| ++ addiu t3, 1 |
| ++ REG_L v1, (t1) |
| ++ PTR_ADDIU t1, SZREG |
| ++ REG_S v1, (t2) |
| ++ PTR_ADDIU t2, SZREG |
| ++ bgeu t3, a2, 2f /* all done */ |
| ++ bltu t3, NARGREGS, 0b /* next */ |
| ++ |
| ++ /* Make room for stack arguments. */ |
| ++ PTR_SUBU t2, a2, t3 |
| ++ PTR_SLL t2, 3 |
| ++ PTR_SUBU t0, t2 |
| ++ and t0, ALMASK |
| ++ |
| ++ /* Store stack arguments. */ |
| ++ move t2, t0 |
| ++1: |
| ++ addiu t3, 1 |
| ++ REG_L v1, (t1) |
| ++ PTR_ADDIU t1, SZREG |
| ++ REG_S v1, (t2) |
| ++ PTR_ADDIU t2, SZREG |
| ++ bltu t3, a2, 1b /* next */ |
| ++ |
| ++2: |
| ++#if _MIPS_SIM == _ABIO32 |
| ++ /* Make room for a0-a3 storage. */ |
| ++ PTR_ADDIU t0, -(NARGSAVE * SZREG) |
| ++#endif |
| ++ PTR_L v1, UCONTEXT_LINK(a0) |
| ++#ifdef __PIC__ |
| ++ PTR_ADDIU t9, 99f - 98b |
| ++#else |
| ++ PTR_LA t9, 99f |
| ++#endif |
| ++ REG_S t0, (29 * SZREG + MCONTEXT_GREGS)(a0) /* sp */ |
| ++ REG_S v1, (16 * SZREG + MCONTEXT_GREGS)(a0) /* s0 */ |
| ++#ifdef __PIC__ |
| ++ REG_S gp, (17 * SZREG + MCONTEXT_GREGS)(a0) /* s1 */ |
| ++#endif |
| ++ REG_S t9, (31 * SZREG + MCONTEXT_GREGS)(a0) /* ra */ |
| ++ REG_S a1, MCONTEXT_PC(a0) |
| ++ |
| ++#ifdef __PIC__ |
| ++ RESTORE_GP64 |
| ++ PTR_ADDIU sp, FRAMESZ |
| ++#endif |
| ++ jr ra |
| ++ |
| ++99: |
| ++#ifdef __PIC__ |
| ++ move gp, s1 |
| ++#endif |
| ++ move a0, zero |
| ++ beqz s0, 0f |
| ++ |
| ++ /* setcontext (ucp) */ |
| ++ move a0, s0 |
| ++#ifdef __PIC__ |
| ++ PTR_LA t9, JUMPTARGET (__setcontext) |
| ++ jalr t9 |
| ++# if _MIPS_SIM == _ABIO32 |
| ++ move gp, s1 |
| ++# endif |
| ++#else |
| ++ jal JUMPTARGET (__setcontext) |
| ++#endif |
| ++ move a0, v0 |
| ++ |
| ++0: |
| ++ /* exit (a0) */ |
| ++#ifdef __PIC__ |
| ++ PTR_LA t9, HIDDEN_JUMPTARGET (exit) |
| ++ jalr t9 |
| ++#else |
| ++ jal HIDDEN_JUMPTARGET (exit) |
| ++#endif |
| ++ |
| ++ /* You don't exist, you won't feel anything. */ |
| ++1: |
| ++ lb zero, (zero) |
| ++ b 1b |
| ++PSEUDO_END (__makecontext) |
| ++ |
| ++weak_alias (__makecontext, makecontext) |
| +diff --git a/libc/sysdeps/linux/mips/setcontext.S b/libc/sysdeps/linux/mips/setcontext.S |
| +new file mode 100644 |
| +index 0000000..d3cde0e |
| +--- /dev/null |
| ++++ b/libc/sysdeps/linux/mips/setcontext.S |
| +@@ -0,0 +1,191 @@ |
| ++/* Set current context. |
| ++ Copyright (C) 2009 Free Software Foundation, Inc. |
| ++ This file is part of the GNU C Library. |
| ++ Contributed by Maciej W. Rozycki <macro@codesourcery.com>. |
| ++ |
| ++ 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/>. */ |
| ++ |
| ++#include <sysdep.h> |
| ++#include <sys/asm.h> |
| ++#include <sys/fpregdef.h> |
| ++#include <sys/regdef.h> |
| ++ |
| ++#include "ucontext_i.h" |
| ++ |
| ++/* int setcontext (const ucontext_t *ucp) */ |
| ++ |
| ++ .text |
| ++LOCALSZ = 0 |
| ++ARGSZ = 0 |
| ++MASK = 0x00000000 |
| ++#ifdef __PIC__ |
| ++LOCALSZ = 1 /* save gp */ |
| ++#endif |
| ++#if _MIPS_SIM != _ABIO32 |
| ++ARGSZ = 1 /* save a0 */ |
| ++# ifdef __PIC__ |
| ++MASK = 0x10000000 |
| ++# endif |
| ++#endif |
| ++FRAMESZ = (((ARGSZ + LOCALSZ) * SZREG) + ALSZ) & ALMASK |
| ++GPOFF = FRAMESZ - ((ARGSZ + 1) * SZREG) |
| ++#if _MIPS_SIM != _ABIO32 |
| ++A0OFF = FRAMESZ - (1 * SZREG) /* callee-allocated */ |
| ++#else |
| ++A0OFF = FRAMESZ + (0 * SZREG) /* caller-allocated */ |
| ++#endif |
| ++ |
| ++NESTED (__setcontext, FRAMESZ, ra) |
| ++ .mask MASK, -(ARGSZ * SZREG) |
| ++ .fmask 0x00000000, 0 |
| ++ |
| ++#ifdef __PIC__ |
| ++ SETUP_GP |
| ++#endif |
| ++ |
| ++ PTR_ADDIU sp, -FRAMESZ |
| ++ |
| ++#ifdef __PIC__ |
| ++ SETUP_GP64 (GPOFF, __setcontext) |
| ++ SAVE_GP (GPOFF) |
| ++#endif |
| ++ |
| ++#ifdef PROF |
| ++ .set noat |
| ++ move AT, ra |
| ++ jal _mcount |
| ++ .set at |
| ++#endif |
| ++ |
| ++ /* Check for the magic flag. */ |
| ++ li v0, 1 |
| ++ REG_L v1, (0 * SZREG + MCONTEXT_GREGS)(a0) /* zero */ |
| ++ bne v0, v1, 98f |
| ++ |
| ++ REG_S a0, A0OFF(sp) |
| ++ |
| ++/* rt_sigprocmask (SIG_SETMASK, &ucp->uc_sigmask, NULL, _NSIG8) */ |
| ++ li a3, _NSIG8 |
| ++ move a2, zero |
| ++ PTR_ADDU a1, a0, UCONTEXT_SIGMASK |
| ++ li a0, SIG_SETMASK |
| ++ |
| ++ li v0, SYS_ify (rt_sigprocmask) |
| ++ syscall |
| ++ bnez a3, 99f |
| ++ |
| ++ REG_L v0, A0OFF(sp) |
| ++ |
| ++#ifdef __mips_hard_float |
| ++# if _MIPS_SIM == _ABI64 |
| ++ l.d fs0, (24 * SZREG + MCONTEXT_FPREGS)(v0) |
| ++ l.d fs1, (25 * SZREG + MCONTEXT_FPREGS)(v0) |
| ++ l.d fs2, (26 * SZREG + MCONTEXT_FPREGS)(v0) |
| ++ l.d fs3, (27 * SZREG + MCONTEXT_FPREGS)(v0) |
| ++ l.d fs4, (28 * SZREG + MCONTEXT_FPREGS)(v0) |
| ++ l.d fs5, (29 * SZREG + MCONTEXT_FPREGS)(v0) |
| ++ l.d fs6, (30 * SZREG + MCONTEXT_FPREGS)(v0) |
| ++ l.d fs7, (31 * SZREG + MCONTEXT_FPREGS)(v0) |
| ++ |
| ++# else /* _MIPS_SIM != _ABI64 */ |
| ++ l.d fs0, (20 * SZREG + MCONTEXT_FPREGS)(v0) |
| ++ l.d fs1, (22 * SZREG + MCONTEXT_FPREGS)(v0) |
| ++ l.d fs2, (24 * SZREG + MCONTEXT_FPREGS)(v0) |
| ++ l.d fs3, (26 * SZREG + MCONTEXT_FPREGS)(v0) |
| ++ l.d fs4, (28 * SZREG + MCONTEXT_FPREGS)(v0) |
| ++ l.d fs5, (30 * SZREG + MCONTEXT_FPREGS)(v0) |
| ++ |
| ++# endif /* _MIPS_SIM != _ABI64 */ |
| ++ |
| ++ lw v1, MCONTEXT_FPC_CSR(v0) |
| ++ ctc1 v1, fcr31 |
| ++#endif /* __mips_hard_float */ |
| ++ |
| ++ /* Note the contents of argument registers will be random |
| ++ unless makecontext() has been called. */ |
| ++ REG_L a0, (4 * SZREG + MCONTEXT_GREGS)(v0) |
| ++ REG_L a1, (5 * SZREG + MCONTEXT_GREGS)(v0) |
| ++ REG_L a2, (6 * SZREG + MCONTEXT_GREGS)(v0) |
| ++ REG_L a3, (7 * SZREG + MCONTEXT_GREGS)(v0) |
| ++#if _MIPS_SIM != _ABIO32 |
| ++ REG_L a4, (8 * SZREG + MCONTEXT_GREGS)(v0) |
| ++ REG_L a5, (9 * SZREG + MCONTEXT_GREGS)(v0) |
| ++ REG_L a6, (10 * SZREG + MCONTEXT_GREGS)(v0) |
| ++ REG_L a7, (11 * SZREG + MCONTEXT_GREGS)(v0) |
| ++#endif |
| ++ |
| ++ REG_L s0, (16 * SZREG + MCONTEXT_GREGS)(v0) |
| ++ REG_L s1, (17 * SZREG + MCONTEXT_GREGS)(v0) |
| ++ REG_L s2, (18 * SZREG + MCONTEXT_GREGS)(v0) |
| ++ REG_L s3, (19 * SZREG + MCONTEXT_GREGS)(v0) |
| ++ REG_L s4, (20 * SZREG + MCONTEXT_GREGS)(v0) |
| ++ REG_L s5, (21 * SZREG + MCONTEXT_GREGS)(v0) |
| ++ REG_L s6, (22 * SZREG + MCONTEXT_GREGS)(v0) |
| ++ REG_L s7, (23 * SZREG + MCONTEXT_GREGS)(v0) |
| ++#if ! defined (__PIC__) || _MIPS_SIM != _ABIO32 |
| ++ REG_L gp, (28 * SZREG + MCONTEXT_GREGS)(v0) |
| ++#endif |
| ++ REG_L sp, (29 * SZREG + MCONTEXT_GREGS)(v0) |
| ++ REG_L fp, (30 * SZREG + MCONTEXT_GREGS)(v0) |
| ++ REG_L ra, (31 * SZREG + MCONTEXT_GREGS)(v0) |
| ++ REG_L t9, MCONTEXT_PC(v0) |
| ++ |
| ++ move v0, zero |
| ++ jr t9 |
| ++ |
| ++98: |
| ++ /* This is a context obtained from a signal handler. |
| ++ Perform a full restore by pushing the context |
| ++ passed onto a simulated signal frame on the stack |
| ++ and call the signal return syscall as if a signal |
| ++ handler exited normally. */ |
| ++ PTR_ADDIU sp, -((RT_SIGFRAME_SIZE + ALSZ) & ALMASK) |
| ++ |
| ++ /* Only ucontext is referred to from rt_sigreturn, |
| ++ copy it. */ |
| ++ PTR_ADDIU t1, sp, RT_SIGFRAME_UCONTEXT |
| ++ li t3, ((UCONTEXT_SIZE + SZREG - 1) / SZREG) - 1 |
| ++0: |
| ++ REG_L t2, (a0) |
| ++ PTR_ADDIU a0, SZREG |
| ++ REG_S t2, (t1) |
| ++ PTR_ADDIU t1, SZREG |
| ++ .set noreorder |
| ++ bgtz t3, 0b |
| ++ addiu t3, -1 |
| ++ .set reorder |
| ++ |
| ++/* rt_sigreturn () -- no arguments, sp points to struct rt_sigframe. */ |
| ++ li v0, SYS_ify (rt_sigreturn) |
| ++ syscall |
| ++ |
| ++ /* Restore the stack and fall through to the error |
| ++ path. Successful rt_sigreturn never returns to |
| ++ its calling place. */ |
| ++ PTR_ADDIU sp, ((RT_SIGFRAME_SIZE + ALSZ) & ALMASK) |
| ++99: |
| ++#ifdef __PIC__ |
| ++ PTR_LA t9, JUMPTARGET (__syscall_error) |
| ++ RESTORE_GP64 |
| ++ PTR_ADDIU sp, FRAMESZ |
| ++ jr t9 |
| ++ |
| ++#else /* ! __PIC__ */ |
| ++ |
| ++ j JUMPTARGET (__syscall_error) |
| ++#endif /* ! __PIC__ */ |
| ++PSEUDO_END (__setcontext) |
| ++ |
| ++weak_alias (__setcontext, setcontext) |
| +diff --git a/libc/sysdeps/linux/mips/swapcontext.S b/libc/sysdeps/linux/mips/swapcontext.S |
| +new file mode 100644 |
| +index 0000000..c7ac19b |
| +--- /dev/null |
| ++++ b/libc/sysdeps/linux/mips/swapcontext.S |
| +@@ -0,0 +1,211 @@ |
| ++/* Save and set current context. |
| ++ Copyright (C) 2009 Free Software Foundation, Inc. |
| ++ This file is part of the GNU C Library. |
| ++ Contributed by Maciej W. Rozycki <macro@codesourcery.com>. |
| ++ |
| ++ 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/>. */ |
| ++ |
| ++#include <sysdep.h> |
| ++#include <sys/asm.h> |
| ++#include <sys/fpregdef.h> |
| ++#include <sys/regdef.h> |
| ++ |
| ++#include "ucontext_i.h" |
| ++ |
| ++/* int swapcontext (ucontext_t *oucp, const ucontext_t *ucp) */ |
| ++ |
| ++ .text |
| ++LOCALSZ = 0 |
| ++ARGSZ = 0 |
| ++MASK = 0x00000000 |
| ++#ifdef __PIC__ |
| ++LOCALSZ = 1 /* save gp */ |
| ++#endif |
| ++#if _MIPS_SIM != _ABIO32 |
| ++ARGSZ = 1 /* save a1 */ |
| ++# ifdef __PIC__ |
| ++MASK = 0x10000000 |
| ++# endif |
| ++#endif |
| ++FRAMESZ = (((ARGSZ + LOCALSZ) * SZREG) + ALSZ) & ALMASK |
| ++GPOFF = FRAMESZ - ((ARGSZ + 1) * SZREG) |
| ++#if _MIPS_SIM != _ABIO32 |
| ++A1OFF = FRAMESZ - (1 * SZREG) /* callee-allocated */ |
| ++#else |
| ++A1OFF = FRAMESZ + (1 * SZREG) /* caller-allocated */ |
| ++#endif |
| ++ |
| ++NESTED (__swapcontext, FRAMESZ, ra) |
| ++ .mask MASK, -(ARGSZ * SZREG) |
| ++ .fmask 0x00000000, 0 |
| ++ |
| ++#ifdef __PIC__ |
| ++ SETUP_GP |
| ++ |
| ++ move a2, sp |
| ++# define _SP a2 |
| ++ |
| ++# if _MIPS_SIM != _ABIO32 |
| ++ move a3, gp |
| ++# define _GP a3 |
| ++# endif |
| ++ |
| ++ PTR_ADDIU sp, -FRAMESZ |
| ++ SETUP_GP64 (GPOFF, __swapcontext) |
| ++ SAVE_GP (GPOFF) |
| ++ |
| ++#else /* ! __PIC__ */ |
| ++# define _SP sp |
| ++# define _GP gp |
| ++ |
| ++#endif /* ! __PIC__ */ |
| ++ |
| ++#ifdef PROF |
| ++ .set noat |
| ++ move AT, ra |
| ++ jal _mcount |
| ++ .set at |
| ++#endif |
| ++ |
| ++ /* Store a magic flag. */ |
| ++ li v1, 1 |
| ++ REG_S v1, (0 * SZREG + MCONTEXT_GREGS)(a0) /* zero */ |
| ++ |
| ++ REG_S s0, (16 * SZREG + MCONTEXT_GREGS)(a0) |
| ++ REG_S s1, (17 * SZREG + MCONTEXT_GREGS)(a0) |
| ++ REG_S s2, (18 * SZREG + MCONTEXT_GREGS)(a0) |
| ++ REG_S s3, (19 * SZREG + MCONTEXT_GREGS)(a0) |
| ++ REG_S s4, (20 * SZREG + MCONTEXT_GREGS)(a0) |
| ++ REG_S s5, (21 * SZREG + MCONTEXT_GREGS)(a0) |
| ++ REG_S s6, (22 * SZREG + MCONTEXT_GREGS)(a0) |
| ++ REG_S s7, (23 * SZREG + MCONTEXT_GREGS)(a0) |
| ++#if ! defined (__PIC__) || _MIPS_SIM != _ABIO32 |
| ++ REG_S _GP, (28 * SZREG + MCONTEXT_GREGS)(a0) |
| ++#endif |
| ++ REG_S _SP, (29 * SZREG + MCONTEXT_GREGS)(a0) |
| ++ REG_S fp, (30 * SZREG + MCONTEXT_GREGS)(a0) |
| ++ REG_S ra, (31 * SZREG + MCONTEXT_GREGS)(a0) |
| ++ REG_S ra, MCONTEXT_PC(a0) |
| ++ |
| ++#ifdef __mips_hard_float |
| ++# if _MIPS_SIM == _ABI64 |
| ++ s.d fs0, (24 * SZREG + MCONTEXT_FPREGS)(a0) |
| ++ s.d fs1, (25 * SZREG + MCONTEXT_FPREGS)(a0) |
| ++ s.d fs2, (26 * SZREG + MCONTEXT_FPREGS)(a0) |
| ++ s.d fs3, (27 * SZREG + MCONTEXT_FPREGS)(a0) |
| ++ s.d fs4, (28 * SZREG + MCONTEXT_FPREGS)(a0) |
| ++ s.d fs5, (29 * SZREG + MCONTEXT_FPREGS)(a0) |
| ++ s.d fs6, (30 * SZREG + MCONTEXT_FPREGS)(a0) |
| ++ s.d fs7, (31 * SZREG + MCONTEXT_FPREGS)(a0) |
| ++ |
| ++# else /* _MIPS_SIM != _ABI64 */ |
| ++ s.d fs0, (20 * SZREG + MCONTEXT_FPREGS)(a0) |
| ++ s.d fs1, (22 * SZREG + MCONTEXT_FPREGS)(a0) |
| ++ s.d fs2, (24 * SZREG + MCONTEXT_FPREGS)(a0) |
| ++ s.d fs3, (26 * SZREG + MCONTEXT_FPREGS)(a0) |
| ++ s.d fs4, (28 * SZREG + MCONTEXT_FPREGS)(a0) |
| ++ s.d fs5, (30 * SZREG + MCONTEXT_FPREGS)(a0) |
| ++ |
| ++# endif /* _MIPS_SIM != _ABI64 */ |
| ++ |
| ++ cfc1 v1, fcr31 |
| ++ sw v1, MCONTEXT_FPC_CSR(a0) |
| ++#endif /* __mips_hard_float */ |
| ++ |
| ++ REG_S a1, A1OFF(sp) |
| ++ |
| ++/* rt_sigprocmask (SIG_SETMASK, &ucp->uc_sigmask, &oucp->uc_sigmask, _NSIG8) */ |
| ++ li a3, _NSIG8 |
| ++ PTR_ADDU a2, a0, UCONTEXT_SIGMASK |
| ++ PTR_ADDU a1, a1, UCONTEXT_SIGMASK |
| ++ li a0, SIG_SETMASK |
| ++ |
| ++ li v0, SYS_ify (rt_sigprocmask) |
| ++ syscall |
| ++ bnez a3, 99f |
| ++ |
| ++ REG_L v0, A1OFF(sp) |
| ++ |
| ++#ifdef __mips_hard_float |
| ++# if _MIPS_SIM == _ABI64 |
| ++ l.d fs0, (24 * SZREG + MCONTEXT_FPREGS)(v0) |
| ++ l.d fs1, (25 * SZREG + MCONTEXT_FPREGS)(v0) |
| ++ l.d fs2, (26 * SZREG + MCONTEXT_FPREGS)(v0) |
| ++ l.d fs3, (27 * SZREG + MCONTEXT_FPREGS)(v0) |
| ++ l.d fs4, (28 * SZREG + MCONTEXT_FPREGS)(v0) |
| ++ l.d fs5, (29 * SZREG + MCONTEXT_FPREGS)(v0) |
| ++ l.d fs6, (30 * SZREG + MCONTEXT_FPREGS)(v0) |
| ++ l.d fs7, (31 * SZREG + MCONTEXT_FPREGS)(v0) |
| ++ |
| ++# else /* _MIPS_SIM != _ABI64 */ |
| ++ l.d fs0, (20 * SZREG + MCONTEXT_FPREGS)(v0) |
| ++ l.d fs1, (22 * SZREG + MCONTEXT_FPREGS)(v0) |
| ++ l.d fs2, (24 * SZREG + MCONTEXT_FPREGS)(v0) |
| ++ l.d fs3, (26 * SZREG + MCONTEXT_FPREGS)(v0) |
| ++ l.d fs4, (28 * SZREG + MCONTEXT_FPREGS)(v0) |
| ++ l.d fs5, (30 * SZREG + MCONTEXT_FPREGS)(v0) |
| ++ |
| ++# endif /* _MIPS_SIM != _ABI64 */ |
| ++ |
| ++ lw v1, MCONTEXT_FPC_CSR(v0) |
| ++ ctc1 v1, fcr31 |
| ++#endif /* __mips_hard_float */ |
| ++ |
| ++ /* Note the contents of argument registers will be random |
| ++ unless makecontext() has been called. */ |
| ++ REG_L a0, (4 * SZREG + MCONTEXT_GREGS)(v0) |
| ++ REG_L a1, (5 * SZREG + MCONTEXT_GREGS)(v0) |
| ++ REG_L a2, (6 * SZREG + MCONTEXT_GREGS)(v0) |
| ++ REG_L a3, (7 * SZREG + MCONTEXT_GREGS)(v0) |
| ++#if _MIPS_SIM != _ABIO32 |
| ++ REG_L a4, (8 * SZREG + MCONTEXT_GREGS)(v0) |
| ++ REG_L a5, (9 * SZREG + MCONTEXT_GREGS)(v0) |
| ++ REG_L a6, (10 * SZREG + MCONTEXT_GREGS)(v0) |
| ++ REG_L a7, (11 * SZREG + MCONTEXT_GREGS)(v0) |
| ++#endif |
| ++ |
| ++ REG_L s0, (16 * SZREG + MCONTEXT_GREGS)(v0) |
| ++ REG_L s1, (17 * SZREG + MCONTEXT_GREGS)(v0) |
| ++ REG_L s2, (18 * SZREG + MCONTEXT_GREGS)(v0) |
| ++ REG_L s3, (19 * SZREG + MCONTEXT_GREGS)(v0) |
| ++ REG_L s4, (20 * SZREG + MCONTEXT_GREGS)(v0) |
| ++ REG_L s5, (21 * SZREG + MCONTEXT_GREGS)(v0) |
| ++ REG_L s6, (22 * SZREG + MCONTEXT_GREGS)(v0) |
| ++ REG_L s7, (23 * SZREG + MCONTEXT_GREGS)(v0) |
| ++#if ! defined (__PIC__) || _MIPS_SIM != _ABIO32 |
| ++ REG_L gp, (28 * SZREG + MCONTEXT_GREGS)(v0) |
| ++#endif |
| ++ REG_L sp, (29 * SZREG + MCONTEXT_GREGS)(v0) |
| ++ REG_L fp, (30 * SZREG + MCONTEXT_GREGS)(v0) |
| ++ REG_L ra, (31 * SZREG + MCONTEXT_GREGS)(v0) |
| ++ REG_L t9, MCONTEXT_PC(v0) |
| ++ |
| ++ move v0, zero |
| ++ jr t9 |
| ++ |
| ++99: |
| ++#ifdef __PIC__ |
| ++ PTR_LA t9, JUMPTARGET (__syscall_error) |
| ++ RESTORE_GP64 |
| ++ PTR_ADDIU sp, FRAMESZ |
| ++ jr t9 |
| ++ |
| ++#else /* ! __PIC__ */ |
| ++ |
| ++ j JUMPTARGET (__syscall_error) |
| ++#endif /* ! __PIC__ */ |
| ++PSEUDO_END (__swapcontext) |
| ++ |
| ++weak_alias (__swapcontext, swapcontext) |
| +diff --git a/libc/sysdeps/linux/mips/ucontext_i.sym b/libc/sysdeps/linux/mips/ucontext_i.sym |
| +new file mode 100644 |
| +index 0000000..f14b886 |
| +--- /dev/null |
| ++++ b/libc/sysdeps/linux/mips/ucontext_i.sym |
| +@@ -0,0 +1,52 @@ |
| ++#include <inttypes.h> |
| ++#include <signal.h> |
| ++#include <stddef.h> |
| ++#include <sys/ucontext.h> |
| ++ |
| ++#include <kernel_rt_sigframe.h> |
| ++ |
| ++-- Constants used by the rt_sigprocmask call. |
| ++ |
| ++SIG_BLOCK |
| ++SIG_SETMASK |
| ++ |
| ++_NSIG8 (_NSIG / 8) |
| ++ |
| ++-- Offsets of the fields in the kernel rt_sigframe_t structure. |
| ++#define rt_sigframe(member) offsetof (kernel_rt_sigframe_t, member) |
| ++ |
| ++RT_SIGFRAME_UCONTEXT rt_sigframe (rs_uc) |
| ++ |
| ++RT_SIGFRAME_SIZE sizeof (kernel_rt_sigframe_t) |
| ++ |
| ++-- Offsets of the fields in the ucontext_t structure. |
| ++#define ucontext(member) offsetof (ucontext_t, member) |
| ++#define stack(member) ucontext (uc_stack.member) |
| ++#define mcontext(member) ucontext (uc_mcontext.member) |
| ++ |
| ++UCONTEXT_FLAGS ucontext (uc_flags) |
| ++UCONTEXT_LINK ucontext (uc_link) |
| ++UCONTEXT_STACK ucontext (uc_stack) |
| ++UCONTEXT_MCONTEXT ucontext (uc_mcontext) |
| ++UCONTEXT_SIGMASK ucontext (uc_sigmask) |
| ++ |
| ++STACK_SP stack (ss_sp) |
| ++STACK_SIZE stack (ss_size) |
| ++STACK_FLAGS stack (ss_flags) |
| ++ |
| ++MCONTEXT_GREGS mcontext (gregs) |
| ++MCONTEXT_FPREGS mcontext (fpregs) |
| ++MCONTEXT_MDHI mcontext (mdhi) |
| ++MCONTEXT_HI1 mcontext (hi1) |
| ++MCONTEXT_HI2 mcontext (hi2) |
| ++MCONTEXT_HI3 mcontext (hi3) |
| ++MCONTEXT_MDLO mcontext (mdlo) |
| ++MCONTEXT_LO1 mcontext (lo1) |
| ++MCONTEXT_LO2 mcontext (lo2) |
| ++MCONTEXT_LO3 mcontext (lo3) |
| ++MCONTEXT_PC mcontext (pc) |
| ++MCONTEXT_FPC_CSR mcontext (fpc_csr) |
| ++MCONTEXT_USED_MATH mcontext (used_math) |
| ++MCONTEXT_DSP mcontext (dsp) |
| ++ |
| ++UCONTEXT_SIZE sizeof (ucontext_t) |
| +diff --git a/libc/sysdeps/linux/x86_64/Makefile.arch b/libc/sysdeps/linux/x86_64/Makefile.arch |
| +index 7491d92..93b8259 100644 |
| +--- a/libc/sysdeps/linux/x86_64/Makefile.arch |
| ++++ b/libc/sysdeps/linux/x86_64/Makefile.arch |
| +@@ -20,3 +20,8 @@ ifeq ($(UCLIBC_HAS_TLS),y) |
| + SSRC += sched_getcpu.S |
| + endif |
| + endif |
| ++ |
| ++ifeq ($(UCLIBC_HAS_CONTEXT_FUNCS),y) |
| ++CSRC += makecontext.c |
| ++SSRC += setcontext.S getcontext.S swapcontext.S __start_context.S |
| ++endif |
| +diff --git a/libc/sysdeps/linux/x86_64/__start_context.S b/libc/sysdeps/linux/x86_64/__start_context.S |
| +new file mode 100644 |
| +index 0000000..9f2ee23 |
| +--- /dev/null |
| ++++ b/libc/sysdeps/linux/x86_64/__start_context.S |