diff --git a/lib/libc/mingw/math/arm-common/log2.c b/lib/libc/mingw/math/arm-common/log2.c new file mode 100644 index 0000000000..42ae3eeeb7 --- /dev/null +++ b/lib/libc/mingw/math/arm-common/log2.c @@ -0,0 +1,55 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ + +#include +#include + +typedef union ieee754_double_ { + struct __attribute__((__packed__)) { + uint64_t f52 : 52; + uint64_t exp : 11; + uint64_t sgn : 1; + }; + double f; +} ieee754_double; + +typedef union ieee754_float_ { + struct __attribute__((__packed__)) { + uint32_t f23 : 23; + uint32_t exp : 8; + uint32_t sgn : 1; + }; + float f; +} ieee754_float; + +double log2(double x) +{ + ieee754_double u = { .f = x }; + if (u.sgn == 0 && u.f52 == 0 && u.exp > 0 && u.exp < 0x7ff) { + // Handle exact powers of two exactly + return (int)u.exp - 1023; + } + return log(x) / 0.69314718246459960938; +} + +float log2f(float x) +{ + ieee754_float u = { .f = x }; + if (u.sgn == 0 && u.f23 == 0 && u.exp > 0 && u.exp < 0xff) { + // Handle exact powers of two exactly + return (int)u.exp - 127; + } + return logf(x) / 0.69314718246459960938f; +} + +long double log2l(long double x) +{ +#if defined(__arm__) || defined(_ARM_) || defined(__aarch64__) || defined(_ARM64_) + return log2(x); +#else +#error Not supported on your platform yet +#endif +} diff --git a/lib/libc/mingw/math/arm-common/pow.c b/lib/libc/mingw/math/arm-common/pow.c new file mode 100644 index 0000000000..48d52b2ae0 --- /dev/null +++ b/lib/libc/mingw/math/arm-common/pow.c @@ -0,0 +1,21 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ + +#include +#include + +extern double (* __MINGW_IMP_SYMBOL(pow))(double, double); + +double pow(double x, double y) +{ + if (x == 1.0) + return 1.0; + if (y == 0.0) + return 1.0; + if (x == -1.0 && isinf(y)) + return 1.0; + return __MINGW_IMP_SYMBOL(pow)(x, y); +} diff --git a/lib/libc/mingw/math/bsd_private_base.h b/lib/libc/mingw/math/bsd_private_base.h new file mode 100644 index 0000000000..598b815cb0 --- /dev/null +++ b/lib/libc/mingw/math/bsd_private_base.h @@ -0,0 +1,148 @@ +/* +* ==================================================== +* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. +* +* Developed at SunPro, a Sun Microsystems, Inc. business. +* Permission to use, copy, modify, and distribute this +* software is freely granted, provided that this notice +* is preserved. +* ==================================================== +*/ + +#include +#include + +typedef unsigned int u_int32_t; + +typedef union +{ + double value; + struct + { + u_int32_t lsw; + u_int32_t msw; + } parts; +} ieee_double_shape_type; + +typedef union { + float value; + u_int32_t word; +} ieee_float_shape_type; + +/* Get two 32 bit ints from a double. */ + +#define EXTRACT_WORDS(ix0,ix1,d) \ +do { \ + ieee_double_shape_type ew_u; \ + ew_u.value = (d); \ + (ix0) = ew_u.parts.msw; \ + (ix1) = ew_u.parts.lsw; \ +} while (0) + +/* Get the most significant 32 bit int from a double. */ + +#define GET_HIGH_WORD(i,d) \ +do { \ + ieee_double_shape_type gh_u; \ + gh_u.value = (d); \ + (i) = gh_u.parts.msw; \ +} while (0) + +/* Get the less significant 32 bit int from a double. */ + +#define GET_LOW_WORD(i,d) \ +do { \ + ieee_double_shape_type gl_u; \ + gl_u.value = (d); \ + (i) = gl_u.parts.lsw; \ +} while (0) + +/* Set a double from two 32 bit ints. */ + +#define INSERT_WORDS(d,ix0,ix1) \ +do { \ + ieee_double_shape_type iw_u; \ + iw_u.parts.msw = (ix0); \ + iw_u.parts.lsw = (ix1); \ + (d) = iw_u.value; \ +} while (0) + +/* Set the more significant 32 bits of a double from an int. */ + +#define SET_HIGH_WORD(d,v) \ +do { \ + ieee_double_shape_type sh_u; \ + sh_u.value = (d); \ + sh_u.parts.msw = (v); \ + (d) = sh_u.value; \ +} while (0) + +/* Set the less significant 32 bits of a double from an int. */ + +#define SET_LOW_WORD(d,v) \ +do { \ + ieee_double_shape_type sl_u; \ + sl_u.value = (d); \ + sl_u.parts.lsw = (v); \ + (d) = sl_u.value; \ +} while (0) + +#define GET_FLOAT_WORD(i,d) do \ +{ \ + ieee_float_shape_type gf_u; \ + gf_u.value = (d); \ + (i) = gf_u.word; \ +} while(0) + +#define SET_FLOAT_WORD(d,i) do \ +{ \ + ieee_float_shape_type gf_u; \ + gf_u.word = (i); \ + (d) = gf_u.value; \ +} while(0) + + +#ifdef FLT_EVAL_METHOD +/* + * Attempt to get strict C99 semantics for assignment with non-C99 compilers. + */ +#if FLT_EVAL_METHOD == 0 || __GNUC__ == 0 +#define STRICT_ASSIGN(type, lval, rval) ((lval) = (rval)) +#else +#define STRICT_ASSIGN(type, lval, rval) do { \ + volatile type __lval; \ + \ + if (sizeof(type) >= sizeof(long double)) \ + (lval) = (rval); \ + else { \ + __lval = (rval); \ + (lval) = __lval; \ + } \ +} while (0) +#endif +#endif /* FLT_EVAL_METHOD */ + +/* + * Mix 0, 1 or 2 NaNs. First add 0 to each arg. This normally just turns + * signaling NaNs into quiet NaNs by setting a quiet bit. We do this + * because we want to never return a signaling NaN, and also because we + * don't want the quiet bit to affect the result. Then mix the converted + * args using the specified operation. + * + * When one arg is NaN, the result is typically that arg quieted. When both + * args are NaNs, the result is typically the quietening of the arg whose + * mantissa is largest after quietening. When neither arg is NaN, the + * result may be NaN because it is indeterminate, or finite for subsequent + * construction of a NaN as the indeterminate 0.0L/0.0L. + * + * Technical complications: the result in bits after rounding to the final + * precision might depend on the runtime precision and/or on compiler + * optimizations, especially when different register sets are used for + * different precisions. Try to make the result not depend on at least the + * runtime precision by always doing the main mixing step in long double + * precision. Try to reduce dependencies on optimizations by adding the + * the 0's in different precisions (unless everything is in long double + * precision). + */ +#define nan_mix(x, y) (nan_mix_op((x), (y), +)) +#define nan_mix_op(x, y, op) (((x) + 0.0L) op ((y) + 0)) diff --git a/lib/libc/mingw/misc/initenv.c b/lib/libc/mingw/misc/initenv.c new file mode 100644 index 0000000000..0cfad4f631 --- /dev/null +++ b/lib/libc/mingw/misc/initenv.c @@ -0,0 +1,12 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ + +#include + +static char ** local__initenv; +static wchar_t ** local__winitenv; +char *** __MINGW_IMP_SYMBOL(__initenv) = &local__initenv; +wchar_t *** __MINGW_IMP_SYMBOL(__winitenv) = &local__winitenv; diff --git a/lib/std/special/compiler_rt.zig b/lib/std/special/compiler_rt.zig index a662f87ea6..ed7f9d0c1c 100644 --- a/lib/std/special/compiler_rt.zig +++ b/lib/std/special/compiler_rt.zig @@ -576,6 +576,18 @@ comptime { }, else => {}, } + if (arch.isAARCH64()) { + const __chkstk = @import("compiler_rt/stack_probe.zig").__chkstk; + @export(__chkstk, .{ .name = "__chkstk", .linkage = strong_linkage }); + const __divti3_windows = @import("compiler_rt/divti3.zig").__divti3; + @export(__divti3_windows, .{ .name = "__divti3", .linkage = linkage }); + const __modti3 = @import("compiler_rt/modti3.zig").__modti3; + @export(__modti3, .{ .name = "__modti3", .linkage = linkage }); + const __udivti3_windows = @import("compiler_rt/udivti3.zig").__udivti3; + @export(__udivti3_windows, .{ .name = "__udivti3", .linkage = linkage }); + const __umodti3 = @import("compiler_rt/umodti3.zig").__umodti3; + @export(__umodti3, .{ .name = "__umodti3", .linkage = linkage }); + } } else { const __divti3 = @import("compiler_rt/divti3.zig").__divti3; @export(__divti3, .{ .name = "__divti3", .linkage = linkage }); diff --git a/lib/std/special/compiler_rt/stack_probe.zig b/lib/std/special/compiler_rt/stack_probe.zig index 78f8a2f8bf..db2a86bdfb 100644 --- a/lib/std/special/compiler_rt/stack_probe.zig +++ b/lib/std/special/compiler_rt/stack_probe.zig @@ -53,6 +53,19 @@ pub fn zig_probe_stack() callconv(.Naked) void { }, else => {}, } + if (comptime native_arch.isAARCH64()) { + asm volatile ( + \\ lsl x16, x15, #4 + \\ mov x17, sp + \\1: + \\ sub x17, x17, #PAGE_SIZE + \\ subs x16, x16, #PAGE_SIZE + \\ ldr xzr, [x17] + \\ b.gt 1b + \\ + \\ ret + ); + } unreachable; } diff --git a/src/mingw.zig b/src/mingw.zig index 529025c517..ca5fa6a01f 100644 --- a/src/mingw.zig +++ b/src/mingw.zig @@ -1022,6 +1022,9 @@ const mingwex_arm32_src = [_][]const u8{ }; const mingwex_arm64_src = [_][]const u8{ + "misc" ++ path.sep_str ++ "initenv.c", + "math" ++ path.sep_str ++ "arm-common" ++ path.sep_str ++ "log2.c", + "math" ++ path.sep_str ++ "arm-common" ++ path.sep_str ++ "pow.c", "math" ++ path.sep_str ++ "arm64" ++ path.sep_str ++ "_chgsignl.S", "math" ++ path.sep_str ++ "arm64" ++ path.sep_str ++ "rint.c", "math" ++ path.sep_str ++ "arm64" ++ path.sep_str ++ "rintf.c", diff --git a/test/tests.zig b/test/tests.zig index 131c9a4129..a90531c600 100644 --- a/test/tests.zig +++ b/test/tests.zig @@ -137,6 +137,14 @@ const test_targets = blk: { }, .link_libc = true, }, + TestTarget{ + .target = .{ + .cpu_arch = .aarch64, + .os_tag = .windows, + .abi = .gnu, + }, + .link_libc = true, + }, TestTarget{ .target = CrossTarget.parse(.{