aboutsummaryrefslogtreecommitdiff
path: root/std
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2019-04-01 11:31:57 -0400
committerGitHub <noreply@github.com>2019-04-01 11:31:57 -0400
commit3199792ade2dfcb88f6668849c54352e51fc1ae0 (patch)
tree886189ac1a1bfcae8124ac18684f1e180c8abb0f /std
parentc76d51de975a4e2e8b549d37161f1e0056384e0b (diff)
parentbfbfb7b3b04b9c98dd14f932b08d1c058e2c5b25 (diff)
downloadzig-3199792ade2dfcb88f6668849c54352e51fc1ae0.tar.gz
zig-3199792ade2dfcb88f6668849c54352e51fc1ae0.zip
Merge pull request #2150 from vegecode/armv7m-compiler-rt
Armv7m compiler rt
Diffstat (limited to 'std')
-rw-r--r--std/special/builtin.zig25
-rw-r--r--std/special/compiler_rt.zig157
-rw-r--r--std/special/compiler_rt/addXf3.zig38
-rw-r--r--std/special/compiler_rt/negXf2.zig21
4 files changed, 233 insertions, 8 deletions
diff --git a/std/special/builtin.zig b/std/special/builtin.zig
index 868b880dcf..3776cc22bf 100644
--- a/std/special/builtin.zig
+++ b/std/special/builtin.zig
@@ -55,6 +55,31 @@ export fn memmove(dest: ?[*]u8, src: ?[*]const u8, n: usize) ?[*]u8 {
return dest;
}
+export fn memcmp(vl: ?[*]const u8, vr: ?[*]const u8, n: usize) isize {
+ @setRuntimeSafety(false);
+
+ var index: usize = 0;
+ while (index != n) : (index += 1) {
+ const compare_val = @bitCast(i8, vl.?[index] -% vr.?[index]);
+ if (compare_val != 0) {
+ return compare_val;
+ }
+ }
+
+ return 0;
+}
+
+test "test_memcmp" {
+ const base_arr = []u8{ 1, 1, 1 };
+ const arr1 = []u8{ 1, 1, 1 };
+ const arr2 = []u8{ 1, 0, 1 };
+ const arr3 = []u8{ 1, 2, 1 };
+
+ std.testing.expect(memcmp(base_arr[0..].ptr, arr1[0..].ptr, base_arr.len) == 0);
+ std.testing.expect(memcmp(base_arr[0..].ptr, arr2[0..].ptr, base_arr.len) == 1);
+ std.testing.expect(memcmp(base_arr[0..].ptr, arr3[0..].ptr, base_arr.len) == -1);
+}
+
comptime {
if (builtin.mode != builtin.Mode.ReleaseFast and
builtin.mode != builtin.Mode.ReleaseSmall and
diff --git a/std/special/compiler_rt.zig b/std/special/compiler_rt.zig
index b62bc6dd69..193899d1af 100644
--- a/std/special/compiler_rt.zig
+++ b/std/special/compiler_rt.zig
@@ -21,7 +21,11 @@ comptime {
@export("__unordtf2", @import("compiler_rt/comparetf2.zig").__unordtf2, linkage);
+ @export("__addsf3", @import("compiler_rt/addXf3.zig").__addsf3, linkage);
+ @export("__adddf3", @import("compiler_rt/addXf3.zig").__adddf3, linkage);
@export("__addtf3", @import("compiler_rt/addXf3.zig").__addtf3, linkage);
+ @export("__subsf3", @import("compiler_rt/addXf3.zig").__subsf3, linkage);
+ @export("__subdf3", @import("compiler_rt/addXf3.zig").__subdf3, linkage);
@export("__subtf3", @import("compiler_rt/addXf3.zig").__subtf3, linkage);
@export("__mulsf3", @import("compiler_rt/mulXf3.zig").__mulsf3, linkage);
@@ -78,10 +82,62 @@ comptime {
@export("__umoddi3", __umoddi3, linkage);
@export("__udivmodsi4", __udivmodsi4, linkage);
+ @export("__negsf2", @import("compiler_rt/negXf2.zig").__negsf2, linkage);
+ @export("__negdf2", @import("compiler_rt/negXf2.zig").__negdf2, linkage);
+
if (is_arm_arch and !is_arm_64) {
@export("__aeabi_uldivmod", __aeabi_uldivmod, linkage);
@export("__aeabi_uidivmod", __aeabi_uidivmod, linkage);
@export("__aeabi_uidiv", __udivsi3, linkage);
+
+ @export("__aeabi_memcpy", __aeabi_memcpy, linkage);
+ @export("__aeabi_memcpy4", __aeabi_memcpy, linkage);
+ @export("__aeabi_memcpy8", __aeabi_memcpy, linkage);
+
+ @export("__aeabi_memmove", __aeabi_memmove, linkage);
+ @export("__aeabi_memmove4", __aeabi_memmove, linkage);
+ @export("__aeabi_memmove8", __aeabi_memmove, linkage);
+
+ @export("__aeabi_memset", __aeabi_memset, linkage);
+ @export("__aeabi_memset4", __aeabi_memset, linkage);
+ @export("__aeabi_memset8", __aeabi_memset, linkage);
+
+ @export("__aeabi_memclr", __aeabi_memclr, linkage);
+ @export("__aeabi_memclr4", __aeabi_memclr, linkage);
+ @export("__aeabi_memclr8", __aeabi_memclr, linkage);
+
+ @export("__aeabi_memcmp", __aeabi_memcmp, linkage);
+ @export("__aeabi_memcmp4", __aeabi_memcmp, linkage);
+ @export("__aeabi_memcmp8", __aeabi_memcmp, linkage);
+
+ @export("__aeabi_fneg", @import("compiler_rt/negXf2.zig").__negsf2, linkage);
+ @export("__aeabi_dneg", @import("compiler_rt/negXf2.zig").__negdf2, linkage);
+
+ @export("__aeabi_fmul", @import("compiler_rt/mulXf3.zig").__mulsf3, linkage);
+ @export("__aeabi_dmul", @import("compiler_rt/mulXf3.zig").__muldf3, linkage);
+
+ @export("__aeabi_d2h", @import("compiler_rt/truncXfYf2.zig").__truncdfhf2, linkage);
+
+ @export("__aeabi_f2ulz", @import("compiler_rt/fixunssfdi.zig").__fixunssfdi, linkage);
+ @export("__aeabi_d2ulz", @import("compiler_rt/fixunsdfdi.zig").__fixunsdfdi, linkage);
+
+ @export("__aeabi_f2lz", @import("compiler_rt/fixsfdi.zig").__fixsfdi, linkage);
+ @export("__aeabi_d2lz", @import("compiler_rt/fixdfdi.zig").__fixdfdi, linkage);
+
+ @export("__aeabi_d2uiz", @import("compiler_rt/fixunsdfsi.zig").__fixunsdfsi, linkage);
+
+ @export("__aeabi_h2f", @import("compiler_rt/extendXfYf2.zig").__extendhfsf2, linkage);
+ @export("__aeabi_f2h", @import("compiler_rt/truncXfYf2.zig").__truncsfhf2, linkage);
+
+ @export("__aeabi_fadd", @import("compiler_rt/addXf3.zig").__addsf3, linkage);
+ @export("__aeabi_dadd", @import("compiler_rt/addXf3.zig").__adddf3, linkage);
+ @export("__aeabi_fsub", @import("compiler_rt/addXf3.zig").__subsf3, linkage);
+ @export("__aeabi_dsub", @import("compiler_rt/addXf3.zig").__subdf3, linkage);
+
+ @export("__aeabi_f2uiz", @import("compiler_rt/fixunssfsi.zig").__fixunssfsi, linkage);
+
+ @export("__aeabi_f2iz", @import("compiler_rt/fixsfsi.zig").__fixsfsi, linkage);
+ @export("__aeabi_d2iz", @import("compiler_rt/fixdfsi.zig").__fixdfsi, linkage);
}
if (builtin.os == builtin.Os.windows) {
switch (builtin.arch) {
@@ -187,6 +243,17 @@ const is_arm_arch = switch (builtin.arch) {
else => false,
};
+const is_arm_32 = is_arm_arch and !is_arm_64;
+
+const use_thumb_1 = is_arm_32 and switch (builtin.arch.arm) {
+ builtin.Arch.Arm32.v6,
+ builtin.Arch.Arm32.v6m,
+ builtin.Arch.Arm32.v6k,
+ builtin.Arch.Arm32.v6t2,
+ => true,
+ else => false,
+};
+
nakedcc fn __aeabi_uidivmod() void {
@setRuntimeSafety(false);
asm volatile (
@@ -203,6 +270,96 @@ nakedcc fn __aeabi_uidivmod() void {
);
}
+nakedcc fn __aeabi_memcpy() noreturn {
+ @setRuntimeSafety(false);
+ if (use_thumb_1) {
+ asm volatile (
+ \\ push {r7, lr}
+ \\ bl memcpy
+ \\ pop {r7, pc}
+ );
+ } else {
+ asm volatile (
+ \\ b memcpy
+ );
+ }
+ unreachable;
+}
+
+nakedcc fn __aeabi_memmove() noreturn {
+ @setRuntimeSafety(false);
+ if (use_thumb_1) {
+ asm volatile (
+ \\ push {r7, lr}
+ \\ bl memmove
+ \\ pop {r7, pc}
+ );
+ } else {
+ asm volatile (
+ \\ b memmove
+ );
+ }
+ unreachable;
+}
+
+nakedcc fn __aeabi_memset() noreturn {
+ @setRuntimeSafety(false);
+ if (use_thumb_1) {
+ asm volatile (
+ \\ mov r3, r1
+ \\ mov r1, r2
+ \\ mov r2, r3
+ \\ push {r7, lr}
+ \\ b memset
+ \\ pop {r7, pc}
+ );
+ } else {
+ asm volatile (
+ \\ mov r3, r1
+ \\ mov r1, r2
+ \\ mov r2, r3
+ \\ b memset
+ );
+ }
+ unreachable;
+}
+
+nakedcc fn __aeabi_memclr() noreturn {
+ @setRuntimeSafety(false);
+ if (use_thumb_1) {
+ asm volatile (
+ \\ mov r2, r1
+ \\ movs r1, #0
+ \\ push {r7, lr}
+ \\ bl memset
+ \\ pop {r7, pc}
+ );
+ } else {
+ asm volatile (
+ \\ mov r2, r1
+ \\ movs r1, #0
+ \\ b memset
+ );
+ }
+ unreachable;
+}
+
+nakedcc fn __aeabi_memcmp() noreturn {
+ @setRuntimeSafety(false);
+ if (use_thumb_1) {
+ asm volatile (
+ \\ push {r7, lr}
+ \\ bl memcmp
+ \\ pop {r7, pc}
+ );
+ } else {
+ asm volatile (
+ \\ b memcmp
+ );
+ }
+ unreachable;
+}
+
// _chkstk (_alloca) routine - probe stack between %esp and (%esp-%eax) in 4k increments,
// then decrement %esp by %eax. Preserves all registers except %esp and flags.
// This routine is windows specific
diff --git a/std/special/compiler_rt/addXf3.zig b/std/special/compiler_rt/addXf3.zig
index c7e80e4e71..3a70461eca 100644
--- a/std/special/compiler_rt/addXf3.zig
+++ b/std/special/compiler_rt/addXf3.zig
@@ -6,27 +6,49 @@ const std = @import("std");
const builtin = @import("builtin");
const compiler_rt = @import("../compiler_rt.zig");
+pub extern fn __addsf3(a: f32, b: f32) f32 {
+ return addXf3(f32, a, b);
+}
+
+pub extern fn __adddf3(a: f64, b: f64) f64 {
+ return addXf3(f64, a, b);
+}
+
pub extern fn __addtf3(a: f128, b: f128) f128 {
return addXf3(f128, a, b);
}
+pub extern fn __subsf3(a: f32, b: f32) f32 {
+ const neg_b = @bitCast(f32, @bitCast(u32, b) ^ (u32(1) << 31));
+ return addXf3(f32, a, neg_b);
+}
+
+pub extern fn __subdf3(a: f64, b: f64) f64 {
+ const neg_b = @bitCast(f64, @bitCast(u64, b) ^ (u64(1) << 63));
+ return addXf3(f64, a, neg_b);
+}
+
pub extern fn __subtf3(a: f128, b: f128) f128 {
const neg_b = @bitCast(f128, @bitCast(u128, b) ^ (u128(1) << 127));
return addXf3(f128, a, neg_b);
}
-inline fn normalize(comptime T: type, significand: *@IntType(false, T.bit_count)) i32 {
+// TODO: restore inline keyword, see: https://github.com/ziglang/zig/issues/2154
+fn normalize(comptime T: type, significand: *@IntType(false, T.bit_count)) i32 {
const Z = @IntType(false, T.bit_count);
+ const S = @IntType(false, T.bit_count - @clz(Z(T.bit_count) - 1));
const significandBits = std.math.floatMantissaBits(T);
const implicitBit = Z(1) << significandBits;
const shift = @clz(significand.*) - @clz(implicitBit);
- significand.* <<= @intCast(u7, shift);
+ significand.* <<= @intCast(S, shift);
return 1 - shift;
}
-inline fn addXf3(comptime T: type, a: T, b: T) T {
+// TODO: restore inline keyword, see: https://github.com/ziglang/zig/issues/2154
+fn addXf3(comptime T: type, a: T, b: T) T {
const Z = @IntType(false, T.bit_count);
+ const S = @IntType(false, T.bit_count - @clz(Z(T.bit_count) - 1));
const typeWidth = T.bit_count;
const significandBits = std.math.floatMantissaBits(T);
@@ -126,8 +148,8 @@ inline fn addXf3(comptime T: type, a: T, b: T) T {
const @"align" = @intCast(Z, aExponent - bExponent);
if (@"align" != 0) {
if (@"align" < typeWidth) {
- const sticky = if (bSignificand << @intCast(u7, typeWidth - @"align") != 0) Z(1) else 0;
- bSignificand = (bSignificand >> @truncate(u7, @"align")) | sticky;
+ const sticky = if (bSignificand << @intCast(S, typeWidth - @"align") != 0) Z(1) else 0;
+ bSignificand = (bSignificand >> @truncate(S, @"align")) | sticky;
} else {
bSignificand = 1; // sticky; b is known to be non-zero.
}
@@ -141,7 +163,7 @@ inline fn addXf3(comptime T: type, a: T, b: T) T {
// and adjust the exponent:
if (aSignificand < implicitBit << 3) {
const shift = @intCast(i32, @clz(aSignificand)) - @intCast(i32, @clz(implicitBit << 3));
- aSignificand <<= @intCast(u7, shift);
+ aSignificand <<= @intCast(S, shift);
aExponent -= shift;
}
} else { // addition
@@ -163,8 +185,8 @@ inline fn addXf3(comptime T: type, a: T, b: T) T {
// Result is denormal before rounding; the exponent is zero and we
// need to shift the significand.
const shift = @intCast(Z, 1 - aExponent);
- const sticky = if (aSignificand << @intCast(u7, typeWidth - shift) != 0) Z(1) else 0;
- aSignificand = aSignificand >> @intCast(u7, shift | sticky);
+ const sticky = if (aSignificand << @intCast(S, typeWidth - shift) != 0) Z(1) else 0;
+ aSignificand = aSignificand >> @intCast(S, shift | sticky);
aExponent = 0;
}
diff --git a/std/special/compiler_rt/negXf2.zig b/std/special/compiler_rt/negXf2.zig
new file mode 100644
index 0000000000..b71a503c1d
--- /dev/null
+++ b/std/special/compiler_rt/negXf2.zig
@@ -0,0 +1,21 @@
+const std = @import("std");
+
+pub extern fn __negsf2(a: f32) f32 {
+ return negXf2(f32, a);
+}
+
+pub extern fn __negdf2(a: f64) f64 {
+ return negXf2(f64, a);
+}
+
+fn negXf2(comptime T: type, a: T) T {
+ const Z = @IntType(false, T.bit_count);
+
+ const typeWidth = T.bit_count;
+ const significandBits = std.math.floatMantissaBits(T);
+ const exponentBits = std.math.floatExponentBits(T);
+
+ const signBit = (Z(1) << (significandBits + exponentBits));
+
+ return @bitCast(T, @bitCast(Z, a) ^ signBit);
+}