Skip to content

Commit

Permalink
std: add loongarch64 support (ziglang#20915)
Browse files Browse the repository at this point in the history
Co-authored-by: Alex Rønne Petersen <[email protected]>
  • Loading branch information
2 people authored and SammyJames committed Aug 13, 2024
1 parent e672e3f commit 1c4125b
Show file tree
Hide file tree
Showing 4 changed files with 220 additions and 2 deletions.
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
13 changes: 13 additions & 0 deletions lib/std/Thread.zig
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
5 changes: 3 additions & 2 deletions lib/std/os/linux.zig
Original file line number Diff line number Diff line change
Expand Up @@ -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"),
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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,
Expand Down
203 changes: 203 additions & 0 deletions lib/std/os/linux/loongarch64.zig
Original file line number Diff line number Diff line change
@@ -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;

0 comments on commit 1c4125b

Please sign in to comment.