authorgravatar for alex@alexrp.comAlex Rønne Petersen <alex@alexrp.com> 2025-10-19 11:50:06+02:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2025-10-19 11:50:06+02:00
log38caa4902f87f63246d8bef9596f2cb7ad8bbbda
tree06f9267cb6af6629221a32f858281ef5bbe946ef
parentc37d23f45ae6bd0db6b072180d7b84566c7dc8a2
parent08014589e291d9ffc8ba4d7abc9a669bfd0c3bec
signaturebadge-check Signed by PGP key B5690EEEBB952194

Merge pull request #25623 from alexrp/or1k

Add `or1k-linux` support (via CBE)

11 files changed, 242 insertions(+), 9 deletions(-)

lib/std/Thread.zig+12
......@@ -1288,6 +1288,18 @@ const LinuxThreadImpl = struct {
12881288 : [ptr] "r" (@intFromPtr(self.mapped.ptr)),
12891289 [len] "r" (self.mapped.len),
12901290 : .{ .memory = true }),
1291 .or1k => asm volatile (
1292 \\ l.ori r11, r0, 215 # SYS_munmap
1293 \\ l.ori r3, %[ptr]
1294 \\ l.ori r4, %[len]
1295 \\ l.sys 1
1296 \\ l.ori r11, r0, 93 # SYS_exit
1297 \\ l.ori r3, r0, r0
1298 \\ l.sys 1
1299 :
1300 : [ptr] "r" (@intFromPtr(self.mapped.ptr)),
1301 [len] "r" (self.mapped.len),
1302 : .{ .memory = true }),
12911303 .powerpc, .powerpcle, .powerpc64, .powerpc64le => asm volatile (
12921304 \\ li 0, 91 # SYS_munmap
12931305 \\ mr 3, %[ptr]
lib/std/atomic.zig+2
......@@ -445,7 +445,9 @@ pub fn cacheLineForCpu(cpu: std.Target.Cpu) u16 {
445445 => 32,
446446
447447 // - https://github.com/torvalds/linux/blob/3a7e02c040b130b5545e4b115aada7bacd80a2b6/arch/m68k/include/asm/cache.h#L10
448 // - https://github.com/torvalds/linux/blob/3a7e02c040b130b5545e4b115aada7bacd80a2b6/arch/openrisc/include/asm/cache.h#L24
448449 .m68k,
450 .or1k,
449451 => 16,
450452
451453 // - https://www.ti.com/lit/pdf/slaa498
lib/std/debug.zig+5-1
......@@ -988,6 +988,8 @@ const StackIterator = union(enum) {
988988 // On LoongArch and RISC-V, the frame pointer points to the top of the saved register area,
989989 // in which the base pointer is the first word.
990990 if (native_arch.isLoongArch() or native_arch.isRISCV()) break :off -2 * @sizeOf(usize);
991 // On OpenRISC, the frame pointer is stored below the return address.
992 if (native_arch == .or1k) break :off -2 * @sizeOf(usize);
991993 // On SPARC, the frame pointer points to the save area which holds 16 slots for the local
992994 // and incoming registers. The base pointer (i6) is stored in its customary save slot.
993995 if (native_arch.isSPARC()) break :off 14 * @sizeOf(usize);
......@@ -999,7 +1001,9 @@ const StackIterator = union(enum) {
9991001 const fp_to_ra_offset = off: {
10001002 // On LoongArch and RISC-V, the frame pointer points to the top of the saved register area,
10011003 // in which the return address is the second word.
1002 if (native_arch.isRISCV() or native_arch.isLoongArch()) break :off -1 * @sizeOf(usize);
1004 if (native_arch.isLoongArch() or native_arch.isRISCV()) break :off -1 * @sizeOf(usize);
1005 // On OpenRISC, the return address is stored below the stack parameter area.
1006 if (native_arch == .or1k) break :off -1 * @sizeOf(usize);
10031007 if (native_arch.isPowerPC64()) break :off 2 * @sizeOf(usize);
10041008 // On s390x, r14 is the link register and we need to grab it from its customary slot in the
10051009 // register save area (ELF ABI s390x Supplement §1.2.2.2).
lib/std/heap.zig+2
......@@ -832,6 +832,7 @@ const page_size_min_default: ?usize = switch (builtin.os.tag) {
832832 .loongarch32, .loongarch64 => 4 << 10,
833833 .m68k => 4 << 10,
834834 .mips, .mipsel, .mips64, .mips64el => 4 << 10,
835 .or1k => 8 << 10,
835836 .powerpc, .powerpc64, .powerpc64le, .powerpcle => 4 << 10,
836837 .riscv32, .riscv64 => 4 << 10,
837838 .s390x => 4 << 10,
......@@ -979,6 +980,7 @@ const page_size_max_default: ?usize = switch (builtin.os.tag) {
979980 .loongarch32, .loongarch64 => 64 << 10,
980981 .m68k => 8 << 10,
981982 .mips, .mipsel, .mips64, .mips64el => 64 << 10,
983 .or1k => 8 << 10,
982984 .powerpc, .powerpc64, .powerpc64le, .powerpcle => 256 << 10,
983985 .riscv32, .riscv64 => 4 << 10,
984986 .s390x => 4 << 10,
lib/std/os/linux.zig+9-5
......@@ -42,6 +42,7 @@ const arch_bits = switch (native_arch) {
4242 .gnuabin32, .muslabin32 => @import("linux/mipsn32.zig"),
4343 else => @import("linux/mips64.zig"),
4444 },
45 .or1k => @import("linux/or1k.zig"),
4546 .powerpc, .powerpcle => @import("linux/powerpc.zig"),
4647 .powerpc64, .powerpc64le => @import("linux/powerpc64.zig"),
4748 .riscv32 => @import("linux/riscv32.zig"),
......@@ -273,7 +274,7 @@ pub const MAP = switch (native_arch) {
273274 UNINITIALIZED: bool = false,
274275 _: u5 = 0,
275276 },
276 .hexagon, .m68k, .s390x => packed struct(u32) {
277 .hexagon, .m68k, .or1k, .s390x => packed struct(u32) {
277278 TYPE: MAP_TYPE,
278279 FIXED: bool = false,
279280 ANONYMOUS: bool = false,
......@@ -444,7 +445,7 @@ pub const O = switch (native_arch) {
444445 TMPFILE: bool = false,
445446 _23: u9 = 0,
446447 },
447 .hexagon, .s390x => packed struct(u32) {
448 .hexagon, .or1k, .s390x => packed struct(u32) {
448449 ACCMODE: ACCMODE = .RDONLY,
449450 _2: u4 = 0,
450451 CREAT: bool = false,
......@@ -1931,7 +1932,7 @@ pub fn sigaction(sig: u8, noalias act: ?*const Sigaction, noalias oact: ?*Sigact
19311932 const mask_size = @sizeOf(@TypeOf(ksa.mask));
19321933
19331934 if (act) |new| {
1934 if (native_arch == .hexagon or is_loongarch or is_mips or is_riscv) {
1935 if (native_arch == .hexagon or is_loongarch or is_mips or native_arch == .or1k or is_riscv) {
19351936 ksa = .{
19361937 .handler = new.handler.handler,
19371938 .flags = new.flags,
......@@ -3747,7 +3748,7 @@ pub const SA = if (is_mips) struct {
37473748 pub const ONSTACK = 0x1;
37483749 pub const NODEFER = 0x20;
37493750 pub const RESTORER = 0x04000000;
3750} else if (native_arch == .hexagon or is_loongarch or is_riscv) struct {
3751} else if (native_arch == .hexagon or is_loongarch or native_arch == .or1k or is_riscv) struct {
37513752 pub const NOCLDSTOP = 1;
37523753 pub const NOCLDWAIT = 2;
37533754 pub const SIGINFO = 4;
......@@ -5828,7 +5829,7 @@ pub const k_sigaction = switch (native_arch) {
58285829 handler: k_sigaction_funcs.handler,
58295830 mask: sigset_t,
58305831 },
5831 .hexagon, .loongarch32, .loongarch64, .riscv32, .riscv64 => extern struct {
5832 .hexagon, .loongarch32, .loongarch64, .or1k, .riscv32, .riscv64 => extern struct {
58325833 handler: k_sigaction_funcs.handler,
58335834 flags: c_ulong,
58345835 mask: sigset_t,
......@@ -6161,6 +6162,7 @@ pub const MINSIGSTKSZ = switch (native_arch) {
61616162 .mipsel,
61626163 .mips64,
61636164 .mips64el,
6165 .or1k,
61646166 .powerpc,
61656167 .powerpcle,
61666168 .riscv32,
......@@ -6195,6 +6197,7 @@ pub const SIGSTKSZ = switch (native_arch) {
61956197 .mipsel,
61966198 .mips64,
61976199 .mips64el,
6200 .or1k,
61986201 .powerpc,
61996202 .powerpcle,
62006203 .riscv32,
......@@ -9744,6 +9747,7 @@ pub const AUDIT = struct {
97449747 .gnuabin32, .muslabin32 => .MIPSEL64N32,
97459748 else => .MIPSEL64,
97469749 },
9750 .or1k => .OPENRISC,
97479751 .powerpc => .PPC,
97489752 .powerpc64 => .PPC64,
97499753 .powerpc64le => .PPC64LE,
lib/std/os/linux/or1k.zig created+173
......@@ -0,0 +1,173 @@
1const builtin = @import("builtin");
2const std = @import("../../std.zig");
3const SYS = std.os.linux.SYS;
4
5pub fn syscall0(number: SYS) u32 {
6 return asm volatile (
7 \\ l.sys 1
8 : [ret] "={r11}" (-> u32),
9 : [number] "{r11}" (@intFromEnum(number)),
10 : .{ .r3 = true, .r4 = true, .r5 = true, .r6 = true, .r7 = true, .r8 = true, .r12 = true, .r13 = true, .r15 = true, .r17 = true, .r19 = true, .r21 = true, .r23 = true, .r25 = true, .r27 = true, .r29 = true, .r31 = true, .memory = true });
11}
12
13pub fn syscall1(number: SYS, arg1: u32) u32 {
14 return asm volatile (
15 \\ l.sys 1
16 : [ret] "={r11}" (-> u32),
17 : [number] "{r11}" (@intFromEnum(number)),
18 [arg1] "{r3}" (arg1),
19 : .{ .r4 = true, .r5 = true, .r6 = true, .r7 = true, .r8 = true, .r12 = true, .r13 = true, .r15 = true, .r17 = true, .r19 = true, .r21 = true, .r23 = true, .r25 = true, .r27 = true, .r29 = true, .r31 = true, .memory = true });
20}
21
22pub fn syscall2(number: SYS, arg1: u32, arg2: u32) u32 {
23 return asm volatile (
24 \\ l.sys 1
25 : [ret] "={r11}" (-> u32),
26 : [number] "{r11}" (@intFromEnum(number)),
27 [arg1] "{r3}" (arg1),
28 [arg2] "{r4}" (arg2),
29 : .{ .r5 = true, .r6 = true, .r7 = true, .r8 = true, .r12 = true, .r13 = true, .r15 = true, .r17 = true, .r19 = true, .r21 = true, .r23 = true, .r25 = true, .r27 = true, .r29 = true, .r31 = true, .memory = true });
30}
31
32pub fn syscall3(number: SYS, arg1: u32, arg2: u32, arg3: u32) u32 {
33 return asm volatile (
34 \\ l.sys 1
35 : [ret] "={r11}" (-> u32),
36 : [number] "{r11}" (@intFromEnum(number)),
37 [arg1] "{r3}" (arg1),
38 [arg2] "{r4}" (arg2),
39 [arg3] "{r5}" (arg3),
40 : .{ .r6 = true, .r7 = true, .r8 = true, .r12 = true, .r13 = true, .r15 = true, .r17 = true, .r19 = true, .r21 = true, .r23 = true, .r25 = true, .r27 = true, .r29 = true, .r31 = true, .memory = true });
41}
42
43pub fn syscall4(number: SYS, arg1: u32, arg2: u32, arg3: u32, arg4: u32) u32 {
44 return asm volatile (
45 \\ l.sys 1
46 : [ret] "={r11}" (-> u32),
47 : [number] "{r11}" (@intFromEnum(number)),
48 [arg1] "{r3}" (arg1),
49 [arg2] "{r4}" (arg2),
50 [arg3] "{r5}" (arg3),
51 [arg4] "{r6}" (arg4),
52 : .{ .r7 = true, .r8 = true, .r12 = true, .r13 = true, .r15 = true, .r17 = true, .r19 = true, .r21 = true, .r23 = true, .r25 = true, .r27 = true, .r29 = true, .r31 = true, .memory = true });
53}
54
55pub fn syscall5(number: SYS, arg1: u32, arg2: u32, arg3: u32, arg4: u32, arg5: u32) u32 {
56 return asm volatile (
57 \\ l.sys 1
58 : [ret] "={r11}" (-> u32),
59 : [number] "{r11}" (@intFromEnum(number)),
60 [arg1] "{r3}" (arg1),
61 [arg2] "{r4}" (arg2),
62 [arg3] "{r5}" (arg3),
63 [arg4] "{r6}" (arg4),
64 [arg5] "{r7}" (arg5),
65 : .{ .r8 = true, .r12 = true, .r13 = true, .r15 = true, .r17 = true, .r19 = true, .r21 = true, .r23 = true, .r25 = true, .r27 = true, .r29 = true, .r31 = true, .memory = true });
66}
67
68pub fn syscall6(
69 number: SYS,
70 arg1: u32,
71 arg2: u32,
72 arg3: u32,
73 arg4: u32,
74 arg5: u32,
75 arg6: u32,
76) u32 {
77 return asm volatile (
78 \\ l.sys 1
79 : [ret] "={r11}" (-> u32),
80 : [number] "{r11}" (@intFromEnum(number)),
81 [arg1] "{r3}" (arg1),
82 [arg2] "{r4}" (arg2),
83 [arg3] "{r5}" (arg3),
84 [arg4] "{r6}" (arg4),
85 [arg5] "{r7}" (arg5),
86 [arg6] "{r8}" (arg6),
87 : .{ .r12 = true, .r13 = true, .r15 = true, .r17 = true, .r19 = true, .r21 = true, .r23 = true, .r25 = true, .r27 = true, .r29 = true, .r31 = true, .memory = true });
88}
89
90pub fn clone() callconv(.naked) u32 {
91 // __clone(func, stack, flags, arg, ptid, tls, ctid)
92 // r3, r4, r5, r6, r7, r8, +0
93 //
94 // syscall(SYS_clone, flags, stack, ptid, tls, ctid)
95 // r11 r3, r4, r5, r6, r7
96 asm volatile (
97 \\ # Save function pointer and argument pointer on new thread stack
98 \\ l.andi r4, r4, -4
99 \\ l.addi r4, r4, -8
100 \\ l.sw 0(r4), r3
101 \\ l.sw 4(r4), r6
102 \\
103 \\ # Shuffle (fn,sp,fl,arg,ptid,tls,ctid) to (fl,sp,ptid,tls,ctid)
104 \\ l.ori r11, r0, 220 # SYS_clone
105 \\ l.ori r3, r5, 0
106 \\ l.ori r5, r7, 0
107 \\ l.ori r6, r8, 0
108 \\ l.lwz r7, 0(r1)
109 \\ l.sys 1
110 \\ l.sfeqi r11, 0
111 \\ l.bf 1f
112 \\ l.jr r9
113 \\1:
114 );
115 if (builtin.unwind_tables != .none or !builtin.strip_debug_info) asm volatile (
116 \\ .cfi_undefined r9
117 );
118 asm volatile (
119 \\ l.ori r2, r0, 0
120 \\ l.ori r9, r0, 0
121 \\
122 \\ l.lwz r11, 0(r1)
123 \\ l.lwz r3, 4(r1)
124 \\ l.jalr r11
125 \\
126 \\ l.ori r3, r11, 0
127 \\ l.ori r11, r0, 93 # SYS_exit
128 \\ l.sys 1
129 );
130}
131
132pub const VDSO = void;
133
134pub const blksize_t = u32;
135pub const nlink_t = u32;
136pub const time_t = i32;
137pub const mode_t = u32;
138pub const off_t = i64;
139pub const ino_t = u64;
140pub const dev_t = u64;
141pub const blkcnt_t = i64;
142
143// The `stat64` definition used by the Linux kernel.
144pub const Stat = extern struct {
145 dev: dev_t,
146 ino: ino_t,
147 mode: mode_t,
148 nlink: nlink_t,
149 uid: std.os.linux.uid_t,
150 gid: std.os.linux.gid_t,
151 rdev: dev_t,
152 _pad0: [2]u32,
153 size: off_t,
154 blksize: blksize_t,
155 _pad1: u32,
156 blocks: blkcnt_t,
157 atim: std.os.linux.timespec,
158 mtim: std.os.linux.timespec,
159 ctim: std.os.linux.timespec,
160 _pad2: [2]u32,
161
162 pub fn atime(self: @This()) std.os.linux.timespec {
163 return self.atim;
164 }
165
166 pub fn mtime(self: @This()) std.os.linux.timespec {
167 return self.mtim;
168 }
169
170 pub fn ctime(self: @This()) std.os.linux.timespec {
171 return self.ctim;
172 }
173};
lib/std/os/linux/tls.zig+8
......@@ -79,6 +79,7 @@ const current_variant: Variant = switch (native_arch) {
7979 .mipsel,
8080 .mips64,
8181 .mips64el,
82 .or1k,
8283 .powerpc,
8384 .powerpcle,
8485 .powerpc64,
......@@ -285,6 +286,13 @@ pub fn setThreadPointer(addr: usize) void {
285286 const rc = @call(.always_inline, linux.syscall1, .{ .set_thread_area, addr });
286287 assert(rc == 0);
287288 },
289 .or1k => {
290 asm volatile (
291 \\ l.ori r10, %[addr], 0
292 :
293 : [addr] "r" (addr),
294 );
295 },
288296 .powerpc, .powerpcle => {
289297 asm volatile (
290298 \\ mr 2, %[addr]
lib/std/pie.zig+13
......@@ -13,6 +13,7 @@ const R_HEXAGON_RELATIVE = 35;
1313const R_LARCH_RELATIVE = 3;
1414const R_68K_RELATIVE = 22;
1515const R_MIPS_RELATIVE = 128;
16const R_OR1K_RELATIVE = 21;
1617const R_PPC_RELATIVE = 22;
1718const R_RISCV_RELATIVE = 3;
1819const R_390_RELATIVE = 12;
......@@ -29,6 +30,7 @@ const R_RELATIVE = switch (builtin.cpu.arch) {
2930 .loongarch32, .loongarch64 => R_LARCH_RELATIVE,
3031 .m68k => R_68K_RELATIVE,
3132 .mips, .mipsel, .mips64, .mips64el => R_MIPS_RELATIVE,
33 .or1k => R_OR1K_RELATIVE,
3234 .powerpc, .powerpcle, .powerpc64, .powerpc64le => R_PPC_RELATIVE,
3335 .riscv32, .riscv32be, .riscv64, .riscv64be => R_RISCV_RELATIVE,
3436 .s390x => R_390_RELATIVE,
......@@ -153,6 +155,17 @@ inline fn getDynamicSymbol() [*]const elf.Dyn {
153155 :
154156 : .{ .lr = true }),
155157 },
158 .or1k => asm volatile (
159 \\ .weak _DYNAMIC
160 \\ .hidden _DYNAMIC
161 \\ l.jal 1f
162 \\ .word _DYNAMIC - .
163 \\1:
164 \\ l.lwz %[ret], 0(r9)
165 \\ l.add %[ret], %[ret], r9
166 : [ret] "=r" (-> [*]const elf.Dyn),
167 :
168 : .{ .r9 = true }),
156169 .powerpc, .powerpcle => asm volatile (
157170 \\ .weak _DYNAMIC
158171 \\ .hidden _DYNAMIC
lib/std/start.zig+11-3
......@@ -203,6 +203,7 @@ fn _start() callconv(.naked) noreturn {
203203 .loongarch32, .loongarch64 => ".cfi_undefined 1",
204204 .m68k => ".cfi_undefined %%pc",
205205 .mips, .mipsel, .mips64, .mips64el => ".cfi_undefined $ra",
206 .or1k => ".cfi_undefined r9",
206207 .powerpc, .powerpcle, .powerpc64, .powerpc64le => ".cfi_undefined lr",
207208 .riscv32, .riscv32be, .riscv64, .riscv64be => if (builtin.zig_backend == .stage2_riscv64)
208209 ""
......@@ -253,12 +254,11 @@ fn _start() callconv(.naked) noreturn {
253254 \\ b %[posixCallMainAndExit]
254255 ,
255256 .arc =>
256 // The `arc` tag currently means ARC v1 and v2, which have an unusually low stack
257 // alignment requirement. ARC v3 increases it from 4 to 16, but we don't support v3 yet.
257 // ARC v1 and v2 had a very low stack alignment requirement of 4; v3 increased it to 16.
258258 \\ mov fp, 0
259259 \\ mov blink, 0
260260 \\ mov r0, sp
261 \\ and sp, sp, -4
261 \\ and sp, sp, -16
262262 \\ b %[posixCallMainAndExit]
263263 ,
264264 .arm, .armeb, .thumb, .thumbeb =>
......@@ -306,6 +306,14 @@ fn _start() callconv(.naked) noreturn {
306306 \\ bstrins.d $sp, $zero, 3, 0
307307 \\ b %[posixCallMainAndExit]
308308 ,
309 .or1k =>
310 // r1 = SP, r2 = FP, r9 = LR
311 \\ l.ori r2, r0, 0
312 \\ l.ori r9, r0, 0
313 \\ l.ori r3, r1, 0
314 \\ l.andi r1, r1, -4
315 \\ l.jal %[posixCallMainAndExit]
316 ,
309317 .riscv32, .riscv32be, .riscv64, .riscv64be =>
310318 \\ li fp, 0
311319 \\ li ra, 0
lib/zig.h+6
......@@ -40,6 +40,8 @@
4040#elif defined(__mips__)
4141#define zig_mips32
4242#define zig_mips
43#elif defined(__or1k__)
44#define zig_or1k
4345#elif defined(__powerpc64__)
4446#define zig_powerpc64
4547#define zig_powerpc
......@@ -390,6 +392,8 @@
390392#define zig_trap() __asm__ volatile(".word 0x0")
391393#elif defined(zig_mips)
392394#define zig_trap() __asm__ volatile(".word 0x3d")
395#elif defined(zig_or1k)
396#define zig_trap() __asm__ volatile("l.cust8")
393397#elif defined(zig_riscv)
394398#define zig_trap() __asm__ volatile("unimp")
395399#elif defined(zig_s390x)
......@@ -422,6 +426,8 @@
422426#define zig_breakpoint() __asm__ volatile("break 0x0")
423427#elif defined(zig_mips)
424428#define zig_breakpoint() __asm__ volatile("break")
429#elif defined(zig_or1k)
430#define zig_breakpoint() __asm__ volatile("l.trap 0x0")
425431#elif defined(zig_powerpc)
426432#define zig_breakpoint() __asm__ volatile("trap")
427433#elif defined(zig_riscv)
src/Sema.zig+1
......@@ -9075,6 +9075,7 @@ const calling_conventions_supporting_var_args = [_]std.builtin.CallingConvention
90759075 .m68k_gnu,
90769076 .m68k_rtd,
90779077 .msp430_eabi,
9078 .or1k_sysv,
90789079 .s390x_sysv,
90799080 .s390x_sysv_vx,
90809081 .ve_sysv,