authorgravatar for yangxudong@ymatrix.cnYANG Xudong <yangxudong@ymatrix.cn> 2024-08-09 08:30:57+08:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2024-08-09 00:30:57+00:00
loga9b65b6fd4021b6b303b6a4d35cfaba56aac0c32
treef5b4db2ce9476a2a419d00c9e5a64ad75ba5ac27
parenta854ce3021773a3f5cd1dce8ac6bc9eb5f4f937c
signaturebadge-check Signed by PGP key B5690EEEBB952194

std: add loongarch64 support (#20915)

Co-authored-by: Alex Rønne Petersen <alex@alexrp.com>

4 files changed, 220 insertions(+), 2 deletions(-)

CMakeLists.txt+1
......@@ -381,6 +381,7 @@ set(ZIG_STAGE2_SOURCES
381381 lib/std/Target/avr.zig
382382 lib/std/Target/bpf.zig
383383 lib/std/Target/hexagon.zig
384 lib/std/Target/loongarch.zig
384385 lib/std/Target/mips.zig
385386 lib/std/Target/msp430.zig
386387 lib/std/Target/nvptx.zig
lib/std/Thread.zig+13
......@@ -1224,6 +1224,19 @@ const LinuxThreadImpl = struct {
12241224 [len] "r" (self.mapped.len),
12251225 : "memory"
12261226 ),
1227 .loongarch64 => asm volatile (
1228 \\ or $a0, $zero, %[ptr]
1229 \\ or $a1, $zero, %[len]
1230 \\ ori $a7, $zero, 215 # SYS_munmap
1231 \\ syscall 0 # call munmap
1232 \\ ori $a0, $zero, 0
1233 \\ ori $a7, $zero, 93 # SYS_exit
1234 \\ syscall 0 # call exit
1235 :
1236 : [ptr] "r" (@intFromPtr(self.mapped.ptr)),
1237 [len] "r" (self.mapped.len),
1238 : "memory"
1239 ),
12271240 else => |cpu_arch| @compileError("Unsupported linux arch: " ++ @tagName(cpu_arch)),
12281241 }
12291242 unreachable;
lib/std/os/linux.zig+3-2
......@@ -42,6 +42,7 @@ const arch_bits = switch (native_arch) {
4242 .riscv32 => @import("linux/riscv32.zig"),
4343 .riscv64 => @import("linux/riscv64.zig"),
4444 .sparc64 => @import("linux/sparc64.zig"),
45 .loongarch64 => @import("linux/loongarch64.zig"),
4546 .mips, .mipsel => @import("linux/mips.zig"),
4647 .mips64, .mips64el => @import("linux/mips64.zig"),
4748 .powerpc, .powerpcle => @import("linux/powerpc.zig"),
......@@ -196,7 +197,7 @@ pub const MAP = switch (native_arch) {
196197 UNINITIALIZED: bool = false,
197198 _: u5 = 0,
198199 },
199 .riscv32, .riscv64 => packed struct(u32) {
200 .riscv32, .riscv64, .loongarch64 => packed struct(u32) {
200201 TYPE: MAP_TYPE,
201202 FIXED: bool = false,
202203 ANONYMOUS: bool = false,
......@@ -301,7 +302,7 @@ pub const O = switch (native_arch) {
301302 TMPFILE: bool = false,
302303 _: u9 = 0,
303304 },
304 .x86, .riscv32, .riscv64 => packed struct(u32) {
305 .x86, .riscv32, .riscv64, .loongarch64 => packed struct(u32) {
305306 ACCMODE: ACCMODE = .RDONLY,
306307 _2: u4 = 0,
307308 CREAT: bool = false,
lib/std/os/linux/loongarch64.zig created+203
......@@ -0,0 +1,203 @@
1const std = @import("../../std.zig");
2const linux = std.os.linux;
3const SYS = linux.SYS;
4const iovec = std.os.iovec;
5const uid_t = linux.uid_t;
6const gid_t = linux.gid_t;
7const stack_t = linux.stack_t;
8const sigset_t = linux.sigset_t;
9
10pub fn syscall0(number: SYS) usize {
11 return asm volatile (
12 \\ syscall 0
13 : [ret] "={$r4}" (-> usize),
14 : [number] "{$r11}" (@intFromEnum(number)),
15 : "$t0", "$t1", "$t2", "$t3", "$t4", "$t5", "$t6", "$t7", "$t8", "memory"
16 );
17}
18
19pub fn syscall1(number: SYS, arg1: usize) usize {
20 return asm volatile (
21 \\ syscall 0
22 : [ret] "={$r4}" (-> usize),
23 : [number] "{$r11}" (@intFromEnum(number)),
24 [arg1] "{$r4}" (arg1),
25 : "$t0", "$t1", "$t2", "$t3", "$t4", "$t5", "$t6", "$t7", "$t8", "memory"
26 );
27}
28
29pub fn syscall2(number: SYS, arg1: usize, arg2: usize) usize {
30 return asm volatile (
31 \\ syscall 0
32 : [ret] "={$r4}" (-> usize),
33 : [number] "{$r11}" (@intFromEnum(number)),
34 [arg1] "{$r4}" (arg1),
35 [arg2] "{$r5}" (arg2),
36 : "$t0", "$t1", "$t2", "$t3", "$t4", "$t5", "$t6", "$t7", "$t8", "memory"
37 );
38}
39
40pub fn syscall3(number: SYS, arg1: usize, arg2: usize, arg3: usize) usize {
41 return asm volatile (
42 \\ syscall 0
43 : [ret] "={$r4}" (-> usize),
44 : [number] "{$r11}" (@intFromEnum(number)),
45 [arg1] "{$r4}" (arg1),
46 [arg2] "{$r5}" (arg2),
47 [arg3] "{$r6}" (arg3),
48 : "$t0", "$t1", "$t2", "$t3", "$t4", "$t5", "$t6", "$t7", "$t8", "memory"
49 );
50}
51
52pub fn syscall4(number: SYS, arg1: usize, arg2: usize, arg3: usize, arg4: usize) usize {
53 return asm volatile (
54 \\ syscall 0
55 : [ret] "={$r4}" (-> usize),
56 : [number] "{$r11}" (@intFromEnum(number)),
57 [arg1] "{$r4}" (arg1),
58 [arg2] "{$r5}" (arg2),
59 [arg3] "{$r6}" (arg3),
60 [arg4] "{$r7}" (arg4),
61 : "$t0", "$t1", "$t2", "$t3", "$t4", "$t5", "$t6", "$t7", "$t8", "memory"
62 );
63}
64
65pub fn syscall5(number: SYS, arg1: usize, arg2: usize, arg3: usize, arg4: usize, arg5: usize) usize {
66 return asm volatile (
67 \\ syscall 0
68 : [ret] "={$r4}" (-> usize),
69 : [number] "{$r11}" (@intFromEnum(number)),
70 [arg1] "{$r4}" (arg1),
71 [arg2] "{$r5}" (arg2),
72 [arg3] "{$r6}" (arg3),
73 [arg4] "{$r7}" (arg4),
74 [arg5] "{$r8}" (arg5),
75 : "$t0", "$t1", "$t2", "$t3", "$t4", "$t5", "$t6", "$t7", "$t8", "memory"
76 );
77}
78
79pub fn syscall6(
80 number: SYS,
81 arg1: usize,
82 arg2: usize,
83 arg3: usize,
84 arg4: usize,
85 arg5: usize,
86 arg6: usize,
87) usize {
88 return asm volatile (
89 \\ syscall 0
90 : [ret] "={$r4}" (-> usize),
91 : [number] "{$r11}" (@intFromEnum(number)),
92 [arg1] "{$r4}" (arg1),
93 [arg2] "{$r5}" (arg2),
94 [arg3] "{$r6}" (arg3),
95 [arg4] "{$r7}" (arg4),
96 [arg5] "{$r8}" (arg5),
97 [arg6] "{$r9}" (arg6),
98 : "$t0", "$t1", "$t2", "$t3", "$t4", "$t5", "$t6", "$t7", "$t8", "memory"
99 );
100}
101
102pub fn clone() callconv(.Naked) usize {
103 // __clone(func, stack, flags, arg, ptid, tls, ctid)
104 // a0, a1, a2, a3, a4, a5, a6
105 // sys_clone(flags, stack, ptid, ctid, tls)
106 // a0, a1, a2, a3, a4
107 asm volatile (
108 \\ bstrins.d $a1, $zero, 3, 0 # stack to 16 align
109 \\
110 \\ # Save function pointer and argument pointer on new thread stack
111 \\ addi.d $a1, $a1, -16
112 \\ st.d $a0, $a1, 0 # save function pointer
113 \\ st.d $a3, $a1, 8 # save argument pointer
114 \\ or $a0, $a2, $zero
115 \\ or $a2, $a4, $zero
116 \\ or $a3, $a6, $zero
117 \\ or $a4, $a5, $zero
118 \\ ori $a7, $zero, 220 # SYS_clone
119 \\ syscall 0 # call clone
120 \\
121 \\ beqz $a0, 1f # whether child process
122 \\ jirl $zero, $ra, 0 # parent process return
123 \\1:
124 \\ ld.d $t8, $sp, 0 # function pointer
125 \\ ld.d $a0, $sp, 8 # argument pointer
126 \\ jirl $ra, $t8, 0 # call the user's function
127 \\ ori $a7, $zero, 93 # SYS_exit
128 \\ syscall 0 # child process exit
129 );
130}
131
132pub const restore = restore_rt;
133
134pub fn restore_rt() callconv(.Naked) noreturn {
135 asm volatile (
136 \\ or $a7, $zero, %[number]
137 \\ syscall 0
138 :
139 : [number] "r" (@intFromEnum(SYS.rt_sigreturn)),
140 : "$t0", "$t1", "$t2", "$t3", "$t4", "$t5", "$t6", "$t7", "$t8", "memory"
141 );
142}
143
144pub const blksize_t = i32;
145pub const nlink_t = u32;
146pub const time_t = i64;
147pub const mode_t = u32;
148pub const off_t = i64;
149pub const ino_t = u64;
150pub const dev_t = u32;
151pub const blkcnt_t = i64;
152
153pub const timeval = extern struct {
154 tv_sec: time_t,
155 tv_usec: i64,
156};
157
158pub const F = struct {
159 pub const DUPFD = 0;
160 pub const GETFD = 1;
161 pub const SETFD = 2;
162 pub const GETFL = 3;
163 pub const SETFL = 4;
164 pub const GETLK = 5;
165 pub const SETLK = 6;
166 pub const SETLKW = 7;
167 pub const SETOWN = 8;
168 pub const GETOWN = 9;
169 pub const SETSIG = 10;
170 pub const GETSIG = 11;
171
172 pub const RDLCK = 0;
173 pub const WRLCK = 1;
174 pub const UNLCK = 2;
175
176 pub const SETOWN_EX = 15;
177 pub const GETOWN_EX = 16;
178
179 pub const GETOWNER_UIDS = 17;
180};
181
182pub const VDSO = struct {
183 pub const CGT_SYM = "__vdso_clock_gettime";
184 pub const CGT_VER = "LINUX_5.10";
185};
186
187pub const mcontext_t = extern struct {
188 pc: u64,
189 regs: [32]u64,
190 flags: u32,
191 extcontext: [0]u64 align(16),
192};
193
194pub const ucontext_t = extern struct {
195 flags: c_ulong,
196 link: ?*ucontext_t,
197 stack: stack_t,
198 sigmask: sigset_t,
199 _pad: [1024 / 8 - @sizeOf(sigset_t)]u8,
200 mcontext: mcontext_t,
201};
202
203pub const Elf_Symndx = u32;