Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

loongarch: add loongarch64 support #20915

Merged
merged 19 commits into from
Aug 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 @@ -195,7 +196,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 @@ -300,7 +301,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";
yxd-ym marked this conversation as resolved.
Show resolved Hide resolved
};

pub const mcontext_t = extern struct {
yxd-ym marked this conversation as resolved.
Show resolved Hide resolved
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,
yxd-ym marked this conversation as resolved.
Show resolved Hide resolved
};

pub const Elf_Symndx = u32;