Commit a9b65b6fd4

YANG Xudong <yangxudong@ymatrix.cn>
2024-08-09 02:30:57
std: add loongarch64 support (#20915)
Co-authored-by: Alex Rønne Petersen <alex@alexrp.com>
1 parent a854ce3
Changed files (4)
lib/std/os/linux/loongarch64.zig
@@ -0,0 +1,203 @@
+const std = @import("../../std.zig");
+const linux = std.os.linux;
+const SYS = linux.SYS;
+const iovec = std.os.iovec;
+const uid_t = linux.uid_t;
+const gid_t = linux.gid_t;
+const stack_t = linux.stack_t;
+const sigset_t = linux.sigset_t;
+
+pub fn syscall0(number: SYS) usize {
+    return asm volatile (
+        \\ syscall 0
+        : [ret] "={$r4}" (-> usize),
+        : [number] "{$r11}" (@intFromEnum(number)),
+        : "$t0", "$t1", "$t2", "$t3", "$t4", "$t5", "$t6", "$t7", "$t8", "memory"
+    );
+}
+
+pub fn syscall1(number: SYS, arg1: usize) usize {
+    return asm volatile (
+        \\ syscall 0
+        : [ret] "={$r4}" (-> usize),
+        : [number] "{$r11}" (@intFromEnum(number)),
+          [arg1] "{$r4}" (arg1),
+        : "$t0", "$t1", "$t2", "$t3", "$t4", "$t5", "$t6", "$t7", "$t8", "memory"
+    );
+}
+
+pub fn syscall2(number: SYS, arg1: usize, arg2: usize) usize {
+    return asm volatile (
+        \\ syscall 0
+        : [ret] "={$r4}" (-> usize),
+        : [number] "{$r11}" (@intFromEnum(number)),
+          [arg1] "{$r4}" (arg1),
+          [arg2] "{$r5}" (arg2),
+        : "$t0", "$t1", "$t2", "$t3", "$t4", "$t5", "$t6", "$t7", "$t8", "memory"
+    );
+}
+
+pub fn syscall3(number: SYS, arg1: usize, arg2: usize, arg3: usize) usize {
+    return asm volatile (
+        \\ syscall 0
+        : [ret] "={$r4}" (-> usize),
+        : [number] "{$r11}" (@intFromEnum(number)),
+          [arg1] "{$r4}" (arg1),
+          [arg2] "{$r5}" (arg2),
+          [arg3] "{$r6}" (arg3),
+        : "$t0", "$t1", "$t2", "$t3", "$t4", "$t5", "$t6", "$t7", "$t8", "memory"
+    );
+}
+
+pub fn syscall4(number: SYS, arg1: usize, arg2: usize, arg3: usize, arg4: usize) usize {
+    return asm volatile (
+        \\ syscall 0
+        : [ret] "={$r4}" (-> usize),
+        : [number] "{$r11}" (@intFromEnum(number)),
+          [arg1] "{$r4}" (arg1),
+          [arg2] "{$r5}" (arg2),
+          [arg3] "{$r6}" (arg3),
+          [arg4] "{$r7}" (arg4),
+        : "$t0", "$t1", "$t2", "$t3", "$t4", "$t5", "$t6", "$t7", "$t8", "memory"
+    );
+}
+
+pub fn syscall5(number: SYS, arg1: usize, arg2: usize, arg3: usize, arg4: usize, arg5: usize) usize {
+    return asm volatile (
+        \\ syscall 0
+        : [ret] "={$r4}" (-> usize),
+        : [number] "{$r11}" (@intFromEnum(number)),
+          [arg1] "{$r4}" (arg1),
+          [arg2] "{$r5}" (arg2),
+          [arg3] "{$r6}" (arg3),
+          [arg4] "{$r7}" (arg4),
+          [arg5] "{$r8}" (arg5),
+        : "$t0", "$t1", "$t2", "$t3", "$t4", "$t5", "$t6", "$t7", "$t8", "memory"
+    );
+}
+
+pub fn syscall6(
+    number: SYS,
+    arg1: usize,
+    arg2: usize,
+    arg3: usize,
+    arg4: usize,
+    arg5: usize,
+    arg6: usize,
+) usize {
+    return asm volatile (
+        \\ syscall 0
+        : [ret] "={$r4}" (-> usize),
+        : [number] "{$r11}" (@intFromEnum(number)),
+          [arg1] "{$r4}" (arg1),
+          [arg2] "{$r5}" (arg2),
+          [arg3] "{$r6}" (arg3),
+          [arg4] "{$r7}" (arg4),
+          [arg5] "{$r8}" (arg5),
+          [arg6] "{$r9}" (arg6),
+        : "$t0", "$t1", "$t2", "$t3", "$t4", "$t5", "$t6", "$t7", "$t8", "memory"
+    );
+}
+
+pub fn clone() callconv(.Naked) usize {
+    // __clone(func, stack, flags, arg, ptid, tls, ctid)
+    //           a0,    a1,    a2,  a3,   a4,  a5,   a6
+    // sys_clone(flags, stack, ptid, ctid, tls)
+    //              a0,    a1,   a2,   a3,  a4
+    asm volatile (
+        \\ bstrins.d $a1, $zero, 3, 0   # stack to 16 align
+        \\
+        \\ # Save function pointer and argument pointer on new thread stack
+        \\ addi.d  $a1, $a1, -16
+        \\ st.d    $a0, $a1, 0     # save function pointer
+        \\ st.d    $a3, $a1, 8     # save argument pointer
+        \\ or      $a0, $a2, $zero
+        \\ or      $a2, $a4, $zero
+        \\ or      $a3, $a6, $zero
+        \\ or      $a4, $a5, $zero
+        \\ ori     $a7, $zero, 220 # SYS_clone
+        \\ syscall 0               # call clone
+        \\
+        \\ beqz    $a0, 1f         # whether child process
+        \\ jirl    $zero, $ra, 0   # parent process return
+        \\1:
+        \\ ld.d    $t8, $sp, 0     # function pointer
+        \\ ld.d    $a0, $sp, 8     # argument pointer
+        \\ jirl    $ra, $t8, 0     # call the user's function
+        \\ ori     $a7, $zero, 93  # SYS_exit
+        \\ syscall 0               # child process exit
+    );
+}
+
+pub const restore = restore_rt;
+
+pub fn restore_rt() callconv(.Naked) noreturn {
+    asm volatile (
+        \\ or $a7, $zero, %[number]
+        \\ syscall 0
+        :
+        : [number] "r" (@intFromEnum(SYS.rt_sigreturn)),
+        : "$t0", "$t1", "$t2", "$t3", "$t4", "$t5", "$t6", "$t7", "$t8", "memory"
+    );
+}
+
+pub const blksize_t = i32;
+pub const nlink_t = u32;
+pub const time_t = i64;
+pub const mode_t = u32;
+pub const off_t = i64;
+pub const ino_t = u64;
+pub const dev_t = u32;
+pub const blkcnt_t = i64;
+
+pub const timeval = extern struct {
+    tv_sec: time_t,
+    tv_usec: i64,
+};
+
+pub const F = struct {
+    pub const DUPFD = 0;
+    pub const GETFD = 1;
+    pub const SETFD = 2;
+    pub const GETFL = 3;
+    pub const SETFL = 4;
+    pub const GETLK = 5;
+    pub const SETLK = 6;
+    pub const SETLKW = 7;
+    pub const SETOWN = 8;
+    pub const GETOWN = 9;
+    pub const SETSIG = 10;
+    pub const GETSIG = 11;
+
+    pub const RDLCK = 0;
+    pub const WRLCK = 1;
+    pub const UNLCK = 2;
+
+    pub const SETOWN_EX = 15;
+    pub const GETOWN_EX = 16;
+
+    pub const GETOWNER_UIDS = 17;
+};
+
+pub const VDSO = struct {
+    pub const CGT_SYM = "__vdso_clock_gettime";
+    pub const CGT_VER = "LINUX_5.10";
+};
+
+pub const mcontext_t = extern struct {
+    pc: u64,
+    regs: [32]u64,
+    flags: u32,
+    extcontext: [0]u64 align(16),
+};
+
+pub const ucontext_t = extern struct {
+    flags: c_ulong,
+    link: ?*ucontext_t,
+    stack: stack_t,
+    sigmask: sigset_t,
+    _pad: [1024 / 8 - @sizeOf(sigset_t)]u8,
+    mcontext: mcontext_t,
+};
+
+pub const Elf_Symndx = u32;
lib/std/os/linux.zig
@@ -42,6 +42,7 @@ const arch_bits = switch (native_arch) {
     .riscv32 => @import("linux/riscv32.zig"),
     .riscv64 => @import("linux/riscv64.zig"),
     .sparc64 => @import("linux/sparc64.zig"),
+    .loongarch64 => @import("linux/loongarch64.zig"),
     .mips, .mipsel => @import("linux/mips.zig"),
     .mips64, .mips64el => @import("linux/mips64.zig"),
     .powerpc, .powerpcle => @import("linux/powerpc.zig"),
@@ -196,7 +197,7 @@ pub const MAP = switch (native_arch) {
         UNINITIALIZED: bool = false,
         _: u5 = 0,
     },
-    .riscv32, .riscv64 => packed struct(u32) {
+    .riscv32, .riscv64, .loongarch64 => packed struct(u32) {
         TYPE: MAP_TYPE,
         FIXED: bool = false,
         ANONYMOUS: bool = false,
@@ -301,7 +302,7 @@ pub const O = switch (native_arch) {
         TMPFILE: bool = false,
         _: u9 = 0,
     },
-    .x86, .riscv32, .riscv64 => packed struct(u32) {
+    .x86, .riscv32, .riscv64, .loongarch64 => packed struct(u32) {
         ACCMODE: ACCMODE = .RDONLY,
         _2: u4 = 0,
         CREAT: bool = false,
lib/std/Thread.zig
@@ -1224,6 +1224,19 @@ const LinuxThreadImpl = struct {
                       [len] "r" (self.mapped.len),
                     : "memory"
                 ),
+                .loongarch64 => asm volatile (
+                    \\ or      $a0, $zero, %[ptr]
+                    \\ or      $a1, $zero, %[len]
+                    \\ ori     $a7, $zero, 215     # SYS_munmap
+                    \\ syscall 0                   # call munmap
+                    \\ ori     $a0, $zero, 0
+                    \\ ori     $a7, $zero, 93      # SYS_exit
+                    \\ syscall 0                   # call exit
+                    :
+                    : [ptr] "r" (@intFromPtr(self.mapped.ptr)),
+                      [len] "r" (self.mapped.len),
+                    : "memory"
+                ),
                 else => |cpu_arch| @compileError("Unsupported linux arch: " ++ @tagName(cpu_arch)),
             }
             unreachable;
CMakeLists.txt
@@ -381,6 +381,7 @@ set(ZIG_STAGE2_SOURCES
     lib/std/Target/avr.zig
     lib/std/Target/bpf.zig
     lib/std/Target/hexagon.zig
+    lib/std/Target/loongarch.zig
     lib/std/Target/mips.zig
     lib/std/Target/msp430.zig
     lib/std/Target/nvptx.zig