authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-09-10 15:56:27-04:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2020-09-10 15:56:27-04:00
log2315331d23d1cfe38f431ec5b81e52101e01dfd7
tree7ce52b1c1034cb4ad145721218f69bc699410a59
parentea9b38c93c38e402c807b20802eb003bcc4ddc5b
parent51fcf949f97d068e917c0c3301ba63a4a305ab6e
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #5527 from shawnanastasio/ppc64le

Implement support for powerpc64{,le}

10 files changed, 822 insertions(+), 7 deletions(-)

lib/std/os/bits/linux.zig+1
...@@ -20,6 +20,7 @@ pub usingnamespace switch (builtin.arch) {...@@ -20,6 +20,7 @@ pub usingnamespace switch (builtin.arch) {
20 .arm => @import("linux/arm-eabi.zig"),20 .arm => @import("linux/arm-eabi.zig"),
21 .riscv64 => @import("linux/riscv64.zig"),21 .riscv64 => @import("linux/riscv64.zig"),
22 .mips, .mipsel => @import("linux/mips.zig"),22 .mips, .mipsel => @import("linux/mips.zig"),
23 .powerpc64, .powerpc64le => @import("linux/powerpc64.zig"),
23 else => struct {},24 else => struct {},
24};25};
2526
lib/std/os/bits/linux/powerpc64.zig created+602
...@@ -0,0 +1,602 @@
1const std = @import("../../../std.zig");
2const linux = std.os.linux;
3const socklen_t = linux.socklen_t;
4const iovec = linux.iovec;
5const iovec_const = linux.iovec_const;
6const uid_t = linux.uid_t;
7const gid_t = linux.gid_t;
8const pid_t = linux.pid_t;
9const stack_t = linux.stack_t;
10const sigset_t = linux.sigset_t;
11pub const SYS = extern enum(usize) {
12 restart_syscall = 0,
13 exit = 1,
14 fork = 2,
15 read = 3,
16 write = 4,
17 open = 5,
18 close = 6,
19 waitpid = 7,
20 creat = 8,
21 link = 9,
22 unlink = 10,
23 execve = 11,
24 chdir = 12,
25 time = 13,
26 mknod = 14,
27 chmod = 15,
28 lchown = 16,
29 sys_break = 17, // sys_ prepended to avoid clashing with keyword
30 oldstat = 18,
31 lseek = 19,
32 getpid = 20,
33 mount = 21,
34 umount = 22,
35 setuid = 23,
36 getuid = 24,
37 stime = 25,
38 ptrace = 26,
39 alarm = 27,
40 oldfstat = 28,
41 pause = 29,
42 utime = 30,
43 stty = 31,
44 gtty = 32,
45 access = 33,
46 nice = 34,
47 ftime = 35,
48 sync = 36,
49 kill = 37,
50 rename = 38,
51 mkdir = 39,
52 rmdir = 40,
53 dup = 41,
54 pipe = 42,
55 times = 43,
56 prof = 44,
57 brk = 45,
58 setgid = 46,
59 getgid = 47,
60 signal = 48,
61 geteuid = 49,
62 getegid = 50,
63 acct = 51,
64 umount2 = 52,
65 lock = 53,
66 ioctl = 54,
67 fcntl = 55,
68 mpx = 56,
69 setpgid = 57,
70 ulimit = 58,
71 oldolduname = 59,
72 umask = 60,
73 chroot = 61,
74 ustat = 62,
75 dup2 = 63,
76 getppid = 64,
77 getpgrp = 65,
78 setsid = 66,
79 sigaction = 67,
80 sgetmask = 68,
81 ssetmask = 69,
82 setreuid = 70,
83 setregid = 71,
84 sigsuspend = 72,
85 sigpending = 73,
86 sethostname = 74,
87 setrlimit = 75,
88 getrlimit = 76,
89 getrusage = 77,
90 gettimeofday = 78,
91 settimeofday = 79,
92 getgroups = 80,
93 setgroups = 81,
94 select = 82,
95 symlink = 83,
96 oldlstat = 84,
97 readlink = 85,
98 uselib = 86,
99 swapon = 87,
100 reboot = 88,
101 readdir = 89,
102 mmap = 90,
103 munmap = 91,
104 truncate = 92,
105 ftruncate = 93,
106 fchmod = 94,
107 fchown = 95,
108 getpriority = 96,
109 setpriority = 97,
110 profil = 98,
111 statfs = 99,
112 fstatfs = 100,
113 ioperm = 101,
114 socketcall = 102,
115 syslog = 103,
116 setitimer = 104,
117 getitimer = 105,
118 stat = 106,
119 lstat = 107,
120 fstat = 108,
121 olduname = 109,
122 iopl = 110,
123 vhangup = 111,
124 idle = 112,
125 vm86 = 113,
126 wait4 = 114,
127 swapoff = 115,
128 sysinfo = 116,
129 ipc = 117,
130 fsync = 118,
131 sigreturn = 119,
132 clone = 120,
133 setdomainname = 121,
134 uname = 122,
135 modify_ldt = 123,
136 adjtimex = 124,
137 mprotect = 125,
138 sigprocmask = 126,
139 create_module = 127,
140 init_module = 128,
141 delete_module = 129,
142 get_kernel_syms = 130,
143 quotactl = 131,
144 getpgid = 132,
145 fchdir = 133,
146 bdflush = 134,
147 sysfs = 135,
148 personality = 136,
149 afs_syscall = 137,
150 setfsuid = 138,
151 setfsgid = 139,
152 _llseek = 140,
153 getdents = 141,
154 _newselect = 142,
155 flock = 143,
156 msync = 144,
157 readv = 145,
158 writev = 146,
159 getsid = 147,
160 fdatasync = 148,
161 _sysctl = 149,
162 mlock = 150,
163 munlock = 151,
164 mlockall = 152,
165 munlockall = 153,
166 sched_setparam = 154,
167 sched_getparam = 155,
168 sched_setscheduler = 156,
169 sched_getscheduler = 157,
170 sched_yield = 158,
171 sched_get_priority_max = 159,
172 sched_get_priority_min = 160,
173 sched_rr_get_interval = 161,
174 nanosleep = 162,
175 mremap = 163,
176 setresuid = 164,
177 getresuid = 165,
178 query_module = 166,
179 poll = 167,
180 nfsservctl = 168,
181 setresgid = 169,
182 getresgid = 170,
183 prctl = 171,
184 rt_sigreturn = 172,
185 rt_sigaction = 173,
186 rt_sigprocmask = 174,
187 rt_sigpending = 175,
188 rt_sigtimedwait = 176,
189 rt_sigqueueinfo = 177,
190 rt_sigsuspend = 178,
191 pread64 = 179,
192 pwrite64 = 180,
193 chown = 181,
194 getcwd = 182,
195 capget = 183,
196 capset = 184,
197 sigaltstack = 185,
198 sendfile = 186,
199 getpmsg = 187,
200 putpmsg = 188,
201 vfork = 189,
202 ugetrlimit = 190,
203 readahead = 191,
204 pciconfig_read = 198,
205 pciconfig_write = 199,
206 pciconfig_iobase = 200,
207 multiplexer = 201,
208 getdents64 = 202,
209 pivot_root = 203,
210 madvise = 205,
211 mincore = 206,
212 gettid = 207,
213 tkill = 208,
214 setxattr = 209,
215 lsetxattr = 210,
216 fsetxattr = 211,
217 getxattr = 212,
218 lgetxattr = 213,
219 fgetxattr = 214,
220 listxattr = 215,
221 llistxattr = 216,
222 flistxattr = 217,
223 removexattr = 218,
224 lremovexattr = 219,
225 fremovexattr = 220,
226 futex = 221,
227 sched_setaffinity = 222,
228 sched_getaffinity = 223,
229 tuxcall = 225,
230 io_setup = 227,
231 io_destroy = 228,
232 io_getevents = 229,
233 io_submit = 230,
234 io_cancel = 231,
235 set_tid_address = 232,
236 fadvise64 = 233,
237 exit_group = 234,
238 lookup_dcookie = 235,
239 epoll_create = 236,
240 epoll_ctl = 237,
241 epoll_wait = 238,
242 remap_file_pages = 239,
243 timer_create = 240,
244 timer_settime = 241,
245 timer_gettime = 242,
246 timer_getoverrun = 243,
247 timer_delete = 244,
248 clock_settime = 245,
249 clock_gettime = 246,
250 clock_getres = 247,
251 clock_nanosleep = 248,
252 swapcontext = 249,
253 tgkill = 250,
254 utimes = 251,
255 statfs64 = 252,
256 fstatfs64 = 253,
257 rtas = 255,
258 sys_debug_setcontext = 256,
259 migrate_pages = 258,
260 mbind = 259,
261 get_mempolicy = 260,
262 set_mempolicy = 261,
263 mq_open = 262,
264 mq_unlink = 263,
265 mq_timedsend = 264,
266 mq_timedreceive = 265,
267 mq_notify = 266,
268 mq_getsetattr = 267,
269 kexec_load = 268,
270 add_key = 269,
271 request_key = 270,
272 keyctl = 271,
273 waitid = 272,
274 ioprio_set = 273,
275 ioprio_get = 274,
276 inotify_init = 275,
277 inotify_add_watch = 276,
278 inotify_rm_watch = 277,
279 spu_run = 278,
280 spu_create = 279,
281 pselect6 = 280,
282 ppoll = 281,
283 unshare = 282,
284 splice = 283,
285 tee = 284,
286 vmsplice = 285,
287 openat = 286,
288 mkdirat = 287,
289 mknodat = 288,
290 fchownat = 289,
291 futimesat = 290,
292 newfstatat = 291,
293 unlinkat = 292,
294 renameat = 293,
295 linkat = 294,
296 symlinkat = 295,
297 readlinkat = 296,
298 fchmodat = 297,
299 faccessat = 298,
300 get_robust_list = 299,
301 set_robust_list = 300,
302 move_pages = 301,
303 getcpu = 302,
304 epoll_pwait = 303,
305 utimensat = 304,
306 signalfd = 305,
307 timerfd_create = 306,
308 eventfd = 307,
309 sync_file_range2 = 308,
310 fallocate = 309,
311 subpage_prot = 310,
312 timerfd_settime = 311,
313 timerfd_gettime = 312,
314 signalfd4 = 313,
315 eventfd2 = 314,
316 epoll_create1 = 315,
317 dup3 = 316,
318 pipe2 = 317,
319 inotify_init1 = 318,
320 perf_event_open = 319,
321 preadv = 320,
322 pwritev = 321,
323 rt_tgsigqueueinfo = 322,
324 fanotify_init = 323,
325 fanotify_mark = 324,
326 prlimit64 = 325,
327 socket = 326,
328 bind = 327,
329 connect = 328,
330 listen = 329,
331 accept = 330,
332 getsockname = 331,
333 getpeername = 332,
334 socketpair = 333,
335 send = 334,
336 sendto = 335,
337 recv = 336,
338 recvfrom = 337,
339 shutdown = 338,
340 setsockopt = 339,
341 getsockopt = 340,
342 sendmsg = 341,
343 recvmsg = 342,
344 recvmmsg = 343,
345 accept4 = 344,
346 name_to_handle_at = 345,
347 open_by_handle_at = 346,
348 clock_adjtime = 347,
349 syncfs = 348,
350 sendmmsg = 349,
351 setns = 350,
352 process_vm_readv = 351,
353 process_vm_writev = 352,
354 finit_module = 353,
355 kcmp = 354,
356 sched_setattr = 355,
357 sched_getattr = 356,
358 renameat2 = 357,
359 seccomp = 358,
360 getrandom = 359,
361 memfd_create = 360,
362 bpf = 361,
363 execveat = 362,
364 switch_endian = 363,
365 userfaultfd = 364,
366 membarrier = 365,
367 mlock2 = 378,
368 copy_file_range = 379,
369 preadv2 = 380,
370 pwritev2 = 381,
371 kexec_file_load = 382,
372 statx = 383,
373 pkey_alloc = 384,
374 pkey_free = 385,
375 pkey_mprotect = 386,
376 rseq = 387,
377 io_pgetevents = 388,
378 semtimedop = 392,
379 semget = 393,
380 semctl = 394,
381 shmget = 395,
382 shmctl = 396,
383 shmat = 397,
384 shmdt = 398,
385 msgget = 399,
386 msgsnd = 400,
387 msgrcv = 401,
388 msgctl = 402,
389 pidfd_send_signal = 424,
390 io_uring_setup = 425,
391 io_uring_enter = 426,
392 io_uring_register = 427,
393 open_tree = 428,
394 move_mount = 429,
395 fsopen = 430,
396 fsconfig = 431,
397 fsmount = 432,
398 fspick = 433,
399 pidfd_open = 434,
400 clone3 = 435,
401 openat2 = 437,
402 pidfd_getfd = 438,
403
404 _,
405};
406
407pub const O_CREAT = 0o100;
408pub const O_EXCL = 0o200;
409pub const O_NOCTTY = 0o400;
410pub const O_TRUNC = 0o1000;
411pub const O_APPEND = 0o2000;
412pub const O_NONBLOCK = 0o4000;
413pub const O_DSYNC = 0o10000;
414pub const O_SYNC = 0o4010000;
415pub const O_RSYNC = 0o4010000;
416pub const O_DIRECTORY = 0o40000;
417pub const O_NOFOLLOW = 0o100000;
418pub const O_CLOEXEC = 0o2000000;
419
420pub const O_ASYNC = 0o20000;
421pub const O_DIRECT = 0o400000;
422pub const O_LARGEFILE = 0o200000;
423pub const O_NOATIME = 0o1000000;
424pub const O_PATH = 0o10000000;
425pub const O_TMPFILE = 0o20200000;
426pub const O_NDELAY = O_NONBLOCK;
427
428pub const F_DUPFD = 0;
429pub const F_GETFD = 1;
430pub const F_SETFD = 2;
431pub const F_GETFL = 3;
432pub const F_SETFL = 4;
433
434pub const F_SETOWN = 8;
435pub const F_GETOWN = 9;
436pub const F_SETSIG = 10;
437pub const F_GETSIG = 11;
438
439pub const F_GETLK = 5;
440pub const F_SETLK = 6;
441pub const F_SETLKW = 7;
442
443pub const F_RDLCK = 0;
444pub const F_WRLCK = 1;
445pub const F_UNLCK = 2;
446
447pub const LOCK_SH = 1;
448pub const LOCK_EX = 2;
449pub const LOCK_UN = 8;
450pub const LOCK_NB = 4;
451
452pub const F_SETOWN_EX = 15;
453pub const F_GETOWN_EX = 16;
454
455pub const F_GETOWNER_UIDS = 17;
456
457/// stack-like segment
458pub const MAP_GROWSDOWN = 0x0100;
459
460/// ETXTBSY
461pub const MAP_DENYWRITE = 0x0800;
462
463/// mark it as an executable
464pub const MAP_EXECUTABLE = 0x1000;
465
466/// pages are locked
467pub const MAP_LOCKED = 0x0080;
468
469/// don't check for reservations
470pub const MAP_NORESERVE = 0x0040;
471
472pub const VDSO_CGT_SYM = "__kernel_clock_gettime";
473pub const VDSO_CGT_VER = "LINUX_2.6.15";
474
475pub const Flock = extern struct {
476 l_type: i16,
477 l_whence: i16,
478 l_start: off_t,
479 l_len: off_t,
480 l_pid: pid_t,
481 __unused: [4]u8,
482};
483
484pub const msghdr = extern struct {
485 msg_name: ?*sockaddr,
486 msg_namelen: socklen_t,
487 msg_iov: [*]iovec,
488 msg_iovlen: usize,
489 msg_control: ?*c_void,
490 msg_controllen: usize,
491 msg_flags: i32,
492};
493
494pub const msghdr_const = extern struct {
495 msg_name: ?*const sockaddr,
496 msg_namelen: socklen_t,
497 msg_iov: [*]iovec_const,
498 msg_iovlen: usize,
499 msg_control: ?*c_void,
500 msg_controllen: usize,
501 msg_flags: i32,
502};
503
504pub const blksize_t = i64;
505pub const nlink_t = u64;
506pub const time_t = i64;
507pub const mode_t = u32;
508pub const off_t = i64;
509pub const ino_t = u64;
510pub const dev_t = u64;
511pub const blkcnt_t = i64;
512
513/// Renamed to Stat to not conflict with the stat function.
514/// atime, mtime, and ctime have functions to return `timespec`,
515/// because although this is a POSIX API, the layout and names of
516/// the structs are inconsistent across operating systems, and
517/// in C, macros are used to hide the differences. Here we use
518/// methods to accomplish this.
519pub const Stat = extern struct {
520 dev: dev_t,
521 ino: ino_t,
522 nlink: nlink_t,
523 mode: mode_t,
524 uid: uid_t,
525 gid: gid_t,
526 rdev: dev_t,
527 size: off_t,
528 blksize: blksize_t,
529 blocks: blkcnt_t,
530 atim: timespec,
531 mtim: timespec,
532 ctim: timespec,
533 __unused: [3]u64,
534
535 pub fn atime(self: Stat) timespec {
536 return self.atim;
537 }
538
539 pub fn mtime(self: Stat) timespec {
540 return self.mtim;
541 }
542
543 pub fn ctime(self: Stat) timespec {
544 return self.ctim;
545 }
546};
547
548pub const timespec = extern struct {
549 tv_sec: time_t,
550 tv_nsec: isize,
551};
552
553pub const timeval = extern struct {
554 tv_sec: isize,
555 tv_usec: isize,
556};
557
558pub const timezone = extern struct {
559 tz_minuteswest: i32,
560 tz_dsttime: i32,
561};
562
563pub const greg_t = u64;
564pub const gregset_t = [48]greg_t;
565pub const fpregset_t = [33]f64;
566
567/// The position of the vscr register depends on endianness.
568/// On C, macros are used to change vscr_word's offset to
569/// account for this. Here we'll just define vscr_word_le
570/// and vscr_word_be. Code must take care to use the correct one.
571pub const vrregset = extern struct {
572 vrregs: [32][4]u32 align(16),
573 vscr_word_le: u32,
574 _pad1: [2]u32,
575 vscr_word_be: u32,
576 vrsave: u32,
577 _pad2: [3]u32
578};
579pub const vrregset_t = vrregset;
580
581pub const mcontext_t = extern struct {
582 __unused: [4]u64,
583 signal: i32,
584 _pad0: i32,
585 handler: u64,
586 oldmask: u64,
587 regs: ?*c_void,
588 gp_regs: gregset_t,
589 fp_regs: fpregset_t,
590 v_regs: *vrregset_t,
591 vmx_reserve: [34+34+32+1]i64,
592};
593
594pub const ucontext_t = extern struct {
595 flags: u32,
596 link: *ucontext_t,
597 stack: stack_t,
598 sigmask: sigset_t,
599 mcontext: mcontext_t,
600};
601
602pub const Elf_Symndx = u32;
lib/std/os/linux.zig+1
...@@ -25,6 +25,7 @@ pub usingnamespace switch (builtin.arch) {...@@ -25,6 +25,7 @@ pub usingnamespace switch (builtin.arch) {
25 .arm => @import("linux/arm-eabi.zig"),25 .arm => @import("linux/arm-eabi.zig"),
26 .riscv64 => @import("linux/riscv64.zig"),26 .riscv64 => @import("linux/riscv64.zig"),
27 .mips, .mipsel => @import("linux/mips.zig"),27 .mips, .mipsel => @import("linux/mips.zig"),
28 .powerpc64, .powerpc64le => @import("linux/powerpc64.zig"),
28 else => struct {},29 else => struct {},
29};30};
30pub usingnamespace @import("bits.zig");31pub usingnamespace @import("bits.zig");
lib/std/os/linux/powerpc64.zig created+127
...@@ -0,0 +1,127 @@
1usingnamespace @import("../bits.zig");
2
3pub fn syscall0(number: SYS) usize {
4 return asm volatile (
5 \\ sc
6 \\ bns+ 1f
7 \\ neg 3, 3
8 \\ 1:
9 : [ret] "={r3}" (-> usize)
10 : [number] "{r0}" (@enumToInt(number))
11 : "memory", "cr0", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12"
12 );
13}
14
15pub fn syscall1(number: SYS, arg1: usize) usize {
16 return asm volatile (
17 \\ sc
18 \\ bns+ 1f
19 \\ neg 3, 3
20 \\ 1:
21 : [ret] "={r3}" (-> usize)
22 : [number] "{r0}" (@enumToInt(number)),
23 [arg1] "{r3}" (arg1)
24 : "memory", "cr0", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12"
25 );
26}
27
28pub fn syscall2(number: SYS, arg1: usize, arg2: usize) usize {
29 return asm volatile (
30 \\ sc
31 \\ bns+ 1f
32 \\ neg 3, 3
33 \\ 1:
34 : [ret] "={r3}" (-> usize)
35 : [number] "{r0}" (@enumToInt(number)),
36 [arg1] "{r3}" (arg1),
37 [arg2] "{r4}" (arg2)
38 : "memory", "cr0", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12"
39 );
40}
41
42pub fn syscall3(number: SYS, arg1: usize, arg2: usize, arg3: usize) usize {
43 return asm volatile (
44 \\ sc
45 \\ bns+ 1f
46 \\ neg 3, 3
47 \\ 1:
48 : [ret] "={r3}" (-> usize)
49 : [number] "{r0}" (@enumToInt(number)),
50 [arg1] "{r3}" (arg1),
51 [arg2] "{r4}" (arg2),
52 [arg3] "{r5}" (arg3)
53 : "memory", "cr0", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12"
54 );
55}
56
57pub fn syscall4(number: SYS, arg1: usize, arg2: usize, arg3: usize, arg4: usize) usize {
58 return asm volatile (
59 \\ sc
60 \\ bns+ 1f
61 \\ neg 3, 3
62 \\ 1:
63 : [ret] "={r3}" (-> usize)
64 : [number] "{r0}" (@enumToInt(number)),
65 [arg1] "{r3}" (arg1),
66 [arg2] "{r4}" (arg2),
67 [arg3] "{r5}" (arg3),
68 [arg4] "{r6}" (arg4)
69 : "memory", "cr0", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12"
70 );
71}
72
73pub fn syscall5(number: SYS, arg1: usize, arg2: usize, arg3: usize, arg4: usize, arg5: usize) usize {
74 return asm volatile (
75 \\ sc
76 \\ bns+ 1f
77 \\ neg 3, 3
78 \\ 1:
79 : [ret] "={r3}" (-> usize)
80 : [number] "{r0}" (@enumToInt(number)),
81 [arg1] "{r3}" (arg1),
82 [arg2] "{r4}" (arg2),
83 [arg3] "{r5}" (arg3),
84 [arg4] "{r6}" (arg4),
85 [arg5] "{r7}" (arg5)
86 : "memory", "cr0", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12"
87 );
88}
89
90pub fn syscall6(
91 number: SYS,
92 arg1: usize,
93 arg2: usize,
94 arg3: usize,
95 arg4: usize,
96 arg5: usize,
97 arg6: usize,
98) usize {
99 return asm volatile (
100 \\ sc
101 \\ bns+ 1f
102 \\ neg 3, 3
103 \\ 1:
104 : [ret] "={r3}" (-> usize)
105 : [number] "{r0}" (@enumToInt(number)),
106 [arg1] "{r3}" (arg1),
107 [arg2] "{r4}" (arg2),
108 [arg3] "{r5}" (arg3),
109 [arg4] "{r6}" (arg4),
110 [arg5] "{r7}" (arg5),
111 [arg6] "{r8}" (arg6)
112 : "memory", "cr0", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12"
113 );
114}
115
116/// This matches the libc clone function.
117pub extern fn clone(func: fn (arg: usize) callconv(.C) u8, stack: usize, flags: usize, arg: usize, ptid: *i32, tls: usize, ctid: *i32) usize;
118
119pub const restore = restore_rt;
120
121pub fn restore_rt() callconv(.Naked) void {
122 return asm volatile ("sc"
123 :
124 : [number] "{r0}" (@enumToInt(SYS.rt_sigreturn))
125 : "memory", "cr0", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12"
126 );
127}
lib/std/os/linux/tls.zig+10-3
...@@ -53,7 +53,7 @@ const TLSVariant = enum {...@@ -53,7 +53,7 @@ const TLSVariant = enum {
53};53};
5454
55const tls_variant = switch (builtin.arch) {55const tls_variant = switch (builtin.arch) {
56 .arm, .armeb, .aarch64, .aarch64_be, .riscv32, .riscv64, .mips, .mipsel => TLSVariant.VariantI,56 .arm, .armeb, .aarch64, .aarch64_be, .riscv32, .riscv64, .mips, .mipsel, .powerpc, .powerpc64, .powerpc64le => TLSVariant.VariantI,
57 .x86_64, .i386 => TLSVariant.VariantII,57 .x86_64, .i386 => TLSVariant.VariantII,
58 else => @compileError("undefined tls_variant for this architecture"),58 else => @compileError("undefined tls_variant for this architecture"),
59};59};
...@@ -77,12 +77,12 @@ const tls_tp_points_past_tcb = switch (builtin.arch) {...@@ -77,12 +77,12 @@ const tls_tp_points_past_tcb = switch (builtin.arch) {
77// make the generated code more efficient77// make the generated code more efficient
7878
79const tls_tp_offset = switch (builtin.arch) {79const tls_tp_offset = switch (builtin.arch) {
80 .mips, .mipsel => 0x7000,80 .mips, .mipsel, .powerpc, .powerpc64, .powerpc64le => 0x7000,
81 else => 0,81 else => 0,
82};82};
8383
84const tls_dtv_offset = switch (builtin.arch) {84const tls_dtv_offset = switch (builtin.arch) {
85 .mips, .mipsel => 0x8000,85 .mips, .mipsel, .powerpc, .powerpc64, .powerpc64le => 0x8000,
86 .riscv32, .riscv64 => 0x800,86 .riscv32, .riscv64 => 0x800,
87 else => 0,87 else => 0,
88};88};
...@@ -165,6 +165,13 @@ pub fn setThreadPointer(addr: usize) void {...@@ -165,6 +165,13 @@ pub fn setThreadPointer(addr: usize) void {
165 const rc = std.os.linux.syscall1(.set_thread_area, addr);165 const rc = std.os.linux.syscall1(.set_thread_area, addr);
166 assert(rc == 0);166 assert(rc == 0);
167 },167 },
168 .powerpc, .powerpc64, .powerpc64le => {
169 asm volatile (
170 \\ mr 13, %[addr]
171 :
172 : [addr] "r" (addr)
173 );
174 },
168 else => @compileError("Unsupported architecture"),175 else => @compileError("Unsupported architecture"),
169 }176 }
170}177}
lib/std/special/c.zig+55
...@@ -394,6 +394,61 @@ fn clone() callconv(.Naked) void {...@@ -394,6 +394,61 @@ fn clone() callconv(.Naked) void {
394 \\ syscall394 \\ syscall
395 );395 );
396 },396 },
397
398 .powerpc64, .powerpc64le => {
399 asm volatile (
400 \\ # store non-volatile regs r30, r31 on stack in order to put our
401 \\ # start func and its arg there
402 \\ stwu 30, -16(1)
403 \\ stw 31, 4(1)
404 \\ # save r3 (func) into r30, and r6(arg) into r31
405 \\ mr 30, 3
406 \\ mr 31, 6
407 \\ # create initial stack frame for new thread
408 \\ clrrwi 4, 4, 4
409 \\ li 0, 0
410 \\ stwu 0, -16(4)
411 \\ #move c into first arg
412 \\ mr 3, 5
413 \\ mr 5, 7
414 \\ mr 6, 8
415 \\ mr 7, 9
416 \\ # move syscall number into r0
417 \\ li 0, 120
418 \\ sc
419
420 \\ # check for syscall error
421 \\ bns+ 1f # jump to label 1 if no summary overflow.
422 \\ #else
423 \\ neg 3, 3 #negate the result (errno)
424 \\1:
425 \\ # compare sc result with 0
426 \\ cmpwi cr7, 3, 0
427
428 \\ # if not 0, jump to end
429 \\ bne cr7, 2f
430
431 \\ #else: we're the child
432 \\ #call funcptr: move arg (d) into r3
433 \\ mr 3, 31
434 \\ #move r30 (funcptr) into CTR reg
435 \\ mtctr 30
436 \\ # call CTR reg
437 \\ bctrl
438 \\ # mov SYS_exit into r0 (the exit param is already in r3)
439 \\ li 0, 1
440 \\ sc
441
442 \\2:
443 \\ # restore stack
444 \\ lwz 30, 0(1)
445 \\ lwz 31, 4(1)
446 \\ addi 1, 1, 16
447
448 \\ blr
449 );
450 },
451
397 else => @compileError("Implement clone() for this arch."),452 else => @compileError("Implement clone() for this arch."),
398 }453 }
399}454}
lib/std/start.zig+15
...@@ -121,6 +121,21 @@ fn _start() callconv(.Naked) noreturn {...@@ -121,6 +121,21 @@ fn _start() callconv(.Naked) noreturn {
121 : [argc] "=r" (-> [*]usize)121 : [argc] "=r" (-> [*]usize)
122 );122 );
123 },123 },
124 .powerpc64le => {
125 // Before returning the stack pointer, we have to set up a backchain
126 // and a few other registers required by the ELFv2 ABI.
127 // TODO: Support powerpc64 (big endian) on ELFv2.
128 starting_stack_ptr = asm (
129 \\ mr 4, 1
130 \\ subi 1, 1, 32
131 \\ li 5, 0
132 \\ std 5, 0(1)
133 \\ mr %[argc], 4
134 : [argc] "=r" (-> [*]usize)
135 :
136 : "r4", "r5"
137 );
138 },
124 else => @compileError("unsupported arch"),139 else => @compileError("unsupported arch"),
125 }140 }
126 // If LLVM inlines stack variables into _start, they will overwrite141 // If LLVM inlines stack variables into _start, they will overwrite
src/analyze.cpp+2-1
...@@ -1003,7 +1003,8 @@ bool want_first_arg_sret(CodeGen *g, FnTypeId *fn_type_id) {...@@ -1003,7 +1003,8 @@ bool want_first_arg_sret(CodeGen *g, FnTypeId *fn_type_id) {
1003 g->zig_target->arch == ZigLLVM_x86_64 ||1003 g->zig_target->arch == ZigLLVM_x86_64 ||
1004 target_is_arm(g->zig_target) ||1004 target_is_arm(g->zig_target) ||
1005 target_is_riscv(g->zig_target) ||1005 target_is_riscv(g->zig_target) ||
1006 target_is_wasm(g->zig_target))1006 target_is_wasm(g->zig_target) ||
1007 target_is_ppc(g->zig_target))
1007 {1008 {
1008 X64CABIClass abi_class = type_c_abi_x86_64_class(g, fn_type_id->return_type);1009 X64CABIClass abi_class = type_c_abi_x86_64_class(g, fn_type_id->return_type);
1009 return abi_class == X64CABIClass_MEMORY || abi_class == X64CABIClass_MEMORY_nobyval;1010 return abi_class == X64CABIClass_MEMORY || abi_class == X64CABIClass_MEMORY_nobyval;
src/target.cpp+8-3
...@@ -853,6 +853,9 @@ const char *arch_stack_pointer_register_name(ZigLLVM_ArchType arch) {...@@ -853,6 +853,9 @@ const char *arch_stack_pointer_register_name(ZigLLVM_ArchType arch) {
853 case ZigLLVM_riscv32:853 case ZigLLVM_riscv32:
854 case ZigLLVM_riscv64:854 case ZigLLVM_riscv64:
855 case ZigLLVM_mipsel:855 case ZigLLVM_mipsel:
856 case ZigLLVM_ppc:
857 case ZigLLVM_ppc64:
858 case ZigLLVM_ppc64le:
856 return "sp";859 return "sp";
857860
858 case ZigLLVM_wasm32:861 case ZigLLVM_wasm32:
...@@ -879,7 +882,6 @@ const char *arch_stack_pointer_register_name(ZigLLVM_ArchType arch) {...@@ -879,7 +882,6 @@ const char *arch_stack_pointer_register_name(ZigLLVM_ArchType arch) {
879 case ZigLLVM_msp430:882 case ZigLLVM_msp430:
880 case ZigLLVM_nvptx:883 case ZigLLVM_nvptx:
881 case ZigLLVM_nvptx64:884 case ZigLLVM_nvptx64:
882 case ZigLLVM_ppc64le:
883 case ZigLLVM_r600:885 case ZigLLVM_r600:
884 case ZigLLVM_renderscript32:886 case ZigLLVM_renderscript32:
885 case ZigLLVM_renderscript64:887 case ZigLLVM_renderscript64:
...@@ -893,8 +895,6 @@ const char *arch_stack_pointer_register_name(ZigLLVM_ArchType arch) {...@@ -893,8 +895,6 @@ const char *arch_stack_pointer_register_name(ZigLLVM_ArchType arch) {
893 case ZigLLVM_tce:895 case ZigLLVM_tce:
894 case ZigLLVM_tcele:896 case ZigLLVM_tcele:
895 case ZigLLVM_xcore:897 case ZigLLVM_xcore:
896 case ZigLLVM_ppc:
897 case ZigLLVM_ppc64:
898 case ZigLLVM_ve:898 case ZigLLVM_ve:
899 zig_panic("TODO populate this table with stack pointer register name for this CPU architecture");899 zig_panic("TODO populate this table with stack pointer register name for this CPU architecture");
900 }900 }
...@@ -1325,6 +1325,11 @@ bool target_is_mips(const ZigTarget *target) {...@@ -1325,6 +1325,11 @@ bool target_is_mips(const ZigTarget *target) {
1325 target->arch == ZigLLVM_mips64 || target->arch == ZigLLVM_mips64el;1325 target->arch == ZigLLVM_mips64 || target->arch == ZigLLVM_mips64el;
1326}1326}
13271327
1328bool target_is_ppc(const ZigTarget *target) {
1329 return target->arch == ZigLLVM_ppc || target->arch == ZigLLVM_ppc64 ||
1330 target->arch == ZigLLVM_ppc64le;
1331}
1332
1328unsigned target_fn_align(const ZigTarget *target) {1333unsigned target_fn_align(const ZigTarget *target) {
1329 return 16;1334 return 16;
1330}1335}
src/target.hpp+1
...@@ -95,6 +95,7 @@ ZigLLVM_OSType get_llvm_os_type(Os os_type);...@@ -95,6 +95,7 @@ ZigLLVM_OSType get_llvm_os_type(Os os_type);
9595
96bool target_is_arm(const ZigTarget *target);96bool target_is_arm(const ZigTarget *target);
97bool target_is_mips(const ZigTarget *target);97bool target_is_mips(const ZigTarget *target);
98bool target_is_ppc(const ZigTarget *target);
98bool target_allows_addr_zero(const ZigTarget *target);99bool target_allows_addr_zero(const ZigTarget *target);
99bool target_has_valgrind_support(const ZigTarget *target);100bool target_has_valgrind_support(const ZigTarget *target);
100bool target_os_is_darwin(Os os);101bool target_os_is_darwin(Os os);