diff options
| author | LemonBoy <thatlemon@gmail.com> | 2021-05-04 18:52:53 +0200 |
|---|---|---|
| committer | LemonBoy <thatlemon@gmail.com> | 2021-05-04 18:52:53 +0200 |
| commit | afbcb6209dbe6812679324aab564884085b8cf44 (patch) | |
| tree | a540fa8c049e94c1e19adfd1e17a85c7e80ca2f6 /lib/std/os | |
| parent | 4bf093f1a00e481d923452955ab9c394c30b8694 (diff) | |
| download | zig-afbcb6209dbe6812679324aab564884085b8cf44.tar.gz zig-afbcb6209dbe6812679324aab564884085b8cf44.zip | |
std: Initial bringup for Linux on Thumb2
There are some small problems here and there, mostly due to the pointers
having the lsb set and disrupting the fn alignment tests and the
`@FrameSize` implementation.
Diffstat (limited to 'lib/std/os')
| -rw-r--r-- | lib/std/os/bits/linux.zig | 2 | ||||
| -rw-r--r-- | lib/std/os/linux.zig | 1 | ||||
| -rw-r--r-- | lib/std/os/linux/thumb.zig | 168 | ||||
| -rw-r--r-- | lib/std/os/linux/tls.zig | 6 |
4 files changed, 173 insertions, 4 deletions
diff --git a/lib/std/os/bits/linux.zig b/lib/std/os/bits/linux.zig index 94da5cc99a..97cdbef782 100644 --- a/lib/std/os/bits/linux.zig +++ b/lib/std/os/bits/linux.zig @@ -18,7 +18,7 @@ pub usingnamespace switch (builtin.arch) { .i386 => @import("linux/i386.zig"), .x86_64 => @import("linux/x86_64.zig"), .aarch64 => @import("linux/arm64.zig"), - .arm => @import("linux/arm-eabi.zig"), + .arm, .thumb => @import("linux/arm-eabi.zig"), .riscv64 => @import("linux/riscv64.zig"), .sparcv9 => @import("linux/sparc64.zig"), .mips, .mipsel => @import("linux/mips.zig"), diff --git a/lib/std/os/linux.zig b/lib/std/os/linux.zig index 4a67ca7685..6c88d9eae1 100644 --- a/lib/std/os/linux.zig +++ b/lib/std/os/linux.zig @@ -23,6 +23,7 @@ pub usingnamespace switch (builtin.arch) { .x86_64 => @import("linux/x86_64.zig"), .aarch64 => @import("linux/arm64.zig"), .arm => @import("linux/arm-eabi.zig"), + .thumb => @import("linux/thumb.zig"), .riscv64 => @import("linux/riscv64.zig"), .sparcv9 => @import("linux/sparc64.zig"), .mips, .mipsel => @import("linux/mips.zig"), diff --git a/lib/std/os/linux/thumb.zig b/lib/std/os/linux/thumb.zig new file mode 100644 index 0000000000..5db9d2cbf4 --- /dev/null +++ b/lib/std/os/linux/thumb.zig @@ -0,0 +1,168 @@ +// SPDX-License-Identifier: MIT +// Copyright (c) 2015-2021 Zig Contributors +// This file is part of [zig](https://ziglang.org/), which is MIT licensed. +// The MIT license requires this copyright notice to be included in all copies +// and substantial portions of the software. +usingnamespace @import("../bits.zig"); + +// The syscall interface is identical to the ARM one but we're facing an extra +// challenge: r7, the register where the syscall number is stored, may be +// reserved for the frame pointer. +// Save and restore r7 around the syscall without touching the stack pointer not +// to break the frame chain. + +pub fn syscall0(number: SYS) usize { + @setRuntimeSafety(false); + + var buf: [2]usize = .{ @enumToInt(number), undefined }; + return asm volatile ( + \\ str r7, [%[tmp], #4] + \\ ldr r7, [%[tmp]] + \\ svc #0 + \\ ldr r7, [%[tmp], #4] + : [ret] "={r0}" (-> usize) + : [tmp] "{r1}" (buf) + : "memory" + ); +} + +pub fn syscall1(number: SYS, arg1: usize) usize { + @setRuntimeSafety(false); + + var buf: [2]usize = .{ @enumToInt(number), undefined }; + return asm volatile ( + \\ str r7, [%[tmp], #4] + \\ ldr r7, [%[tmp]] + \\ svc #0 + \\ ldr r7, [%[tmp], #4] + : [ret] "={r0}" (-> usize) + : [tmp] "{r1}" (buf), + [arg1] "{r0}" (arg1) + : "memory" + ); +} + +pub fn syscall2(number: SYS, arg1: usize, arg2: usize) usize { + @setRuntimeSafety(false); + + var buf: [2]usize = .{ @enumToInt(number), undefined }; + return asm volatile ( + \\ str r7, [%[tmp], #4] + \\ ldr r7, [%[tmp]] + \\ svc #0 + \\ ldr r7, [%[tmp], #4] + : [ret] "={r0}" (-> usize) + : [tmp] "{r2}" (buf), + [arg1] "{r0}" (arg1), + [arg2] "{r1}" (arg2) + : "memory" + ); +} + +pub fn syscall3(number: SYS, arg1: usize, arg2: usize, arg3: usize) usize { + @setRuntimeSafety(false); + + var buf: [2]usize = .{ @enumToInt(number), undefined }; + return asm volatile ( + \\ str r7, [%[tmp], #4] + \\ ldr r7, [%[tmp]] + \\ svc #0 + \\ ldr r7, [%[tmp], #4] + : [ret] "={r0}" (-> usize) + : [tmp] "{r3}" (buf), + [arg1] "{r0}" (arg1), + [arg2] "{r1}" (arg2), + [arg3] "{r2}" (arg3) + : "memory" + ); +} + +pub fn syscall4(number: SYS, arg1: usize, arg2: usize, arg3: usize, arg4: usize) usize { + @setRuntimeSafety(false); + + var buf: [2]usize = .{ @enumToInt(number), undefined }; + return asm volatile ( + \\ str r7, [%[tmp], #4] + \\ ldr r7, [%[tmp]] + \\ svc #0 + \\ ldr r7, [%[tmp], #4] + : [ret] "={r0}" (-> usize) + : [tmp] "{r4}" (buf), + [arg1] "{r0}" (arg1), + [arg2] "{r1}" (arg2), + [arg3] "{r2}" (arg3), + [arg4] "{r3}" (arg4) + : "memory" + ); +} + +pub fn syscall5(number: SYS, arg1: usize, arg2: usize, arg3: usize, arg4: usize, arg5: usize) usize { + @setRuntimeSafety(false); + + var buf: [2]usize = .{ @enumToInt(number), undefined }; + return asm volatile ( + \\ str r7, [%[tmp], #4] + \\ ldr r7, [%[tmp]] + \\ svc #0 + \\ ldr r7, [%[tmp], #4] + : [ret] "={r0}" (-> usize) + : [tmp] "{r5}" (buf), + [arg1] "{r0}" (arg1), + [arg2] "{r1}" (arg2), + [arg3] "{r2}" (arg3), + [arg4] "{r3}" (arg4), + [arg5] "{r4}" (arg5) + : "memory" + ); +} + +pub fn syscall6( + number: SYS, + arg1: usize, + arg2: usize, + arg3: usize, + arg4: usize, + arg5: usize, + arg6: usize, +) usize { + @setRuntimeSafety(false); + + var buf: [2]usize = .{ @enumToInt(number), undefined }; + return asm volatile ( + \\ str r7, [%[tmp], #4] + \\ ldr r7, [%[tmp]] + \\ svc #0 + \\ ldr r7, [%[tmp], #4] + : [ret] "={r0}" (-> usize) + : [tmp] "{r6}" (buf), + [arg1] "{r0}" (arg1), + [arg2] "{r1}" (arg2), + [arg3] "{r2}" (arg3), + [arg4] "{r3}" (arg4), + [arg5] "{r4}" (arg5), + [arg6] "{r5}" (arg6) + : "memory" + ); +} + +/// This matches the libc clone function. +pub extern fn clone(func: fn (arg: usize) callconv(.C) u8, stack: usize, flags: u32, arg: usize, ptid: *i32, tls: usize, ctid: *i32) usize; + +pub fn restore() callconv(.Naked) void { + return asm volatile ( + \\ mov r7, %[number] + \\ svc #0 + : + : [number] "I" (@enumToInt(SYS.sigreturn)) + ); +} + +pub fn restore_rt() callconv(.Naked) void { + return asm volatile ( + \\ mov r7, %[number] + \\ svc #0 + : + : [number] "I" (@enumToInt(SYS.rt_sigreturn)) + : "memory" + ); +} diff --git a/lib/std/os/linux/tls.zig b/lib/std/os/linux/tls.zig index 4a36b0d485..0830dcbfda 100644 --- a/lib/std/os/linux/tls.zig +++ b/lib/std/os/linux/tls.zig @@ -53,7 +53,7 @@ const TLSVariant = enum { }; const tls_variant = switch (builtin.arch) { - .arm, .armeb, .aarch64, .aarch64_be, .riscv32, .riscv64, .mips, .mipsel, .powerpc, .powerpc64, .powerpc64le => TLSVariant.VariantI, + .arm, .armeb, .thumb, .aarch64, .aarch64_be, .riscv32, .riscv64, .mips, .mipsel, .powerpc, .powerpc64, .powerpc64le => TLSVariant.VariantI, .x86_64, .i386, .sparcv9 => TLSVariant.VariantII, else => @compileError("undefined tls_variant for this architecture"), }; @@ -62,7 +62,7 @@ const tls_variant = switch (builtin.arch) { const tls_tcb_size = switch (builtin.arch) { // ARM EABI mandates enough space for two pointers: the first one points to // the DTV while the second one is unspecified but reserved - .arm, .armeb, .aarch64, .aarch64_be => 2 * @sizeOf(usize), + .arm, .armeb, .thumb, .aarch64, .aarch64_be => 2 * @sizeOf(usize), // One pointer-sized word that points either to the DTV or the TCB itself else => @sizeOf(usize), }; @@ -150,7 +150,7 @@ pub fn setThreadPointer(addr: usize) void { : [addr] "r" (addr) ); }, - .arm => { + .arm, .thumb => { const rc = std.os.linux.syscall1(.set_tls, addr); assert(rc == 0); }, |
