Commit a preview of osx386 and osxppc as new platforms.
These produce Mach-o executables for Mac OS X on Intel or PowerPC processors. Our code generator for PowerPC (mach/powerpc) still has bugs. Some examples seem to run, but startrek crashes. Our code generator for Intel (mach/i386) is better. There is a problem with job control. If you run paranoia or startrek, then suspend the job (^Z) and resume it ('fg' in bash), then read(2) might fail with EINTR. The larger files in this commit are - plat/osx/cvmach/cvmach.c - plat/osx/libsys/brk.c - plat/osx386/libsys/sigaction.s - plat/osxppc/libsys/sigaction.s
This commit is contained in:
parent
9017ba9dea
commit
02fb480217
|
@ -9,6 +9,8 @@ vars.plats = {
|
|||
"linux386",
|
||||
"linux68k",
|
||||
"linuxppc",
|
||||
"osx386",
|
||||
"osxppc",
|
||||
"pc86",
|
||||
"rpi",
|
||||
}
|
||||
|
|
17
plat/osx/cvmach/build.lua
Normal file
17
plat/osx/cvmach/build.lua
Normal file
|
@ -0,0 +1,17 @@
|
|||
cprogram {
|
||||
name = "cvmach",
|
||||
srcs = { "./cvmach.c" },
|
||||
deps = {
|
||||
"h+emheaders",
|
||||
-- Next line only because object.h includes ansi.h
|
||||
"modules+headers",
|
||||
"modules/src/object+lib",
|
||||
}
|
||||
}
|
||||
|
||||
installable {
|
||||
name = "pkg",
|
||||
map = {
|
||||
["$(PLATDEP)/cvmach"] = "+cvmach",
|
||||
}
|
||||
}
|
418
plat/osx/cvmach/cvmach.c
Normal file
418
plat/osx/cvmach/cvmach.c
Normal file
|
@ -0,0 +1,418 @@
|
|||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*/
|
||||
|
||||
/*
|
||||
* cvmach.c - convert ack.out to mach-o
|
||||
*
|
||||
* Mostly pinched from aelflod (util/amisc/aelflod.c), which pinched
|
||||
* from the ARM cv (mach/arm/cv/cv.c), which pinched from the m68k2 cv
|
||||
* (mach/m68k2/cv/cv.c). The code to read ack.out format using
|
||||
* liboject is pinched from the Xenix i386 cv (mach/i386/cv/cv.c).
|
||||
*/
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <out.h>
|
||||
/* Can't find #include <object.h>*/
|
||||
|
||||
/* Header and section table of ack.out */
|
||||
struct outhead outhead;
|
||||
struct outsect outsect[S_MAX];
|
||||
|
||||
int bigendian; /* Emit big-endian Mach-o? */
|
||||
int cpu_type;
|
||||
uint32_t entry; /* Virtual address of entry point */
|
||||
uint32_t sz_thread_command;
|
||||
|
||||
char *outputfile = NULL; /* Name of output file, or NULL */
|
||||
char *program; /* Name of current program: argv[0] */
|
||||
FILE *output; /* Output stream */
|
||||
#define writef(a, b, c) fwrite((a), (b), (c), output)
|
||||
|
||||
/* Segment numbers in ack.out */
|
||||
enum {
|
||||
TEXT = 0,
|
||||
ROM,
|
||||
DATA,
|
||||
BSS,
|
||||
NUM_SEGMENTS
|
||||
};
|
||||
|
||||
/* Constants from Mach headers */
|
||||
#define MH_MAGIC 0xfeedface
|
||||
#define MH_EXECUTE 2
|
||||
#define LC_SEGMENT 1
|
||||
#define LC_UNIXTHREAD 5
|
||||
|
||||
#define CPU_TYPE_X86 7
|
||||
#define CPU_SUBTYPE_X86_ALL 3
|
||||
#define x86_THREAD_STATE32 1
|
||||
#define x86_THREAD_STATE32_COUNT 16
|
||||
|
||||
#define CPU_TYPE_POWERPC 18
|
||||
#define CPU_SUBTYPE_POWERPC_ALL 0
|
||||
#define PPC_THREAD_STATE 1
|
||||
#define PPC_THREAD_STATE_COUNT 40
|
||||
|
||||
#define VM_PROT_NONE 0x0
|
||||
#define VM_PROT_READ 0x1
|
||||
#define VM_PROT_WRITE 0x2
|
||||
#define VM_PROT_EXECUTE 0x4
|
||||
|
||||
/* sizes of Mach structs */
|
||||
#define SZ_MACH_HEADER 28
|
||||
#define SZ_SEGMENT_COMMAND 56
|
||||
#define SZ_THREAD_COMMAND_BF_STATE 16
|
||||
|
||||
/* the page size for x86 and PowerPC */
|
||||
#define CV_PGSZ 4096
|
||||
/* u modulo page size */
|
||||
#define pg_mod(u) ((u) & (CV_PGSZ - 1))
|
||||
/* u rounded down to whole pages */
|
||||
#define pg_trunc(u) ((u) & ~(CV_PGSZ - 1))
|
||||
|
||||
|
||||
void usage(void)
|
||||
{
|
||||
fprintf(stderr, "Usage: %s -m<num> <inputfile> <outputfile>\n",
|
||||
program);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* Produce an error message and exit. */
|
||||
void fatal(const char* s, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
fprintf(stderr, "%s: ",program) ;
|
||||
|
||||
va_start(ap, s);
|
||||
vfprintf(stderr, s, ap);
|
||||
va_end(ap);
|
||||
|
||||
fprintf(stderr, "\n");
|
||||
|
||||
if (outputfile)
|
||||
unlink(outputfile);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
void rd_fatal(void)
|
||||
{
|
||||
fatal("read error");
|
||||
}
|
||||
|
||||
/* Calculate the result of a aligned to b (rounding up if necessary).
|
||||
* b must be a power of two. */
|
||||
uint32_t align(uint32_t a, uint32_t b)
|
||||
{
|
||||
a += b - 1;
|
||||
return a & ~(b-1);
|
||||
}
|
||||
|
||||
|
||||
/* Writes out a 32-bit value in the appropriate endianness. */
|
||||
void emit32(uint32_t value)
|
||||
{
|
||||
unsigned char buffer[4];
|
||||
|
||||
if (bigendian)
|
||||
{
|
||||
buffer[0] = (value >> 24) & 0xFF;
|
||||
buffer[1] = (value >> 16) & 0xFF;
|
||||
buffer[2] = (value >> 8) & 0xFF;
|
||||
buffer[3] = (value >> 0) & 0xFF;
|
||||
}
|
||||
else
|
||||
{
|
||||
buffer[3] = (value >> 24) & 0xFF;
|
||||
buffer[2] = (value >> 16) & 0xFF;
|
||||
buffer[1] = (value >> 8) & 0xFF;
|
||||
buffer[0] = (value >> 0) & 0xFF;
|
||||
}
|
||||
|
||||
writef(buffer, 1, sizeof(buffer));
|
||||
}
|
||||
|
||||
/* Copies the contents of a section from the input stream
|
||||
* to the output stream. */
|
||||
void emit_section(int section_nr)
|
||||
{
|
||||
struct outsect *section = &outsect[section_nr];
|
||||
size_t blocksize;
|
||||
uint32_t n = section->os_flen;
|
||||
char buffer[BUFSIZ];
|
||||
|
||||
rd_outsect(section_nr);
|
||||
while (n > 0)
|
||||
{
|
||||
blocksize = (n > BUFSIZ) ? BUFSIZ : n;
|
||||
rd_emit(buffer, (long)blocksize);
|
||||
writef(buffer, 1, blocksize);
|
||||
n -= blocksize;
|
||||
}
|
||||
|
||||
/* Zero fill any remaining space. */
|
||||
n = section->os_size - section->os_flen;
|
||||
if (n > 0)
|
||||
{
|
||||
memset(buffer, 0, BUFSIZ);
|
||||
while (n > 0)
|
||||
{
|
||||
blocksize = (n > BUFSIZ) ? BUFSIZ : n;
|
||||
writef(buffer, 1, blocksize);
|
||||
n -= blocksize;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void emit_lc_segment(char *name, uint32_t vm_ad, uint32_t vm_sz,
|
||||
uint32_t f_off, uint32_t f_sz, int prot)
|
||||
{
|
||||
char namebuf[16];
|
||||
int flags, maxprot;
|
||||
|
||||
if (prot == VM_PROT_NONE) {
|
||||
/* special values for __PAGEZERO */
|
||||
maxprot = VM_PROT_NONE;
|
||||
flags = 4; /* NORELOC */
|
||||
} else {
|
||||
maxprot = VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE;
|
||||
flags = 0;
|
||||
}
|
||||
|
||||
/* Use strncpy() to pad namebuf with '\0' bytes. */
|
||||
strncpy(namebuf, name, sizeof(namebuf));
|
||||
|
||||
emit32(LC_SEGMENT); /* command */
|
||||
emit32(SZ_SEGMENT_COMMAND); /* size of command */
|
||||
writef(namebuf, 1, sizeof(namebuf));
|
||||
emit32(vm_ad); /* vm address */
|
||||
emit32(vm_sz); /* vm size */
|
||||
emit32(f_off); /* file offset */
|
||||
emit32(f_sz); /* file size */
|
||||
emit32(maxprot); /* max protection */
|
||||
emit32(prot); /* initial protection */
|
||||
emit32(0); /* number of Mach sections */
|
||||
emit32(flags); /* flags */
|
||||
}
|
||||
|
||||
void emit_lc_unixthread(void)
|
||||
{
|
||||
int i, ireg, ts, ts_count;
|
||||
|
||||
/*
|
||||
* The thread state has ts_count registers. The ireg'th
|
||||
* register holds the entry point. We can set other registers
|
||||
* to zero. At execution time, the kernel will allocate a
|
||||
* stack and set the stack pointer.
|
||||
*/
|
||||
switch (cpu_type) {
|
||||
case CPU_TYPE_X86:
|
||||
ireg = 10; /* eip */
|
||||
ts = x86_THREAD_STATE32;
|
||||
ts_count = x86_THREAD_STATE32_COUNT;
|
||||
break;
|
||||
case CPU_TYPE_POWERPC:
|
||||
ireg = 0; /* srr0 */
|
||||
ts = PPC_THREAD_STATE;
|
||||
ts_count = PPC_THREAD_STATE_COUNT;
|
||||
break;
|
||||
}
|
||||
|
||||
emit32(LC_UNIXTHREAD); /* command */
|
||||
emit32(sz_thread_command); /* size of command */
|
||||
emit32(ts); /* thread state */
|
||||
emit32(ts_count); /* thread state count */
|
||||
for (i = 0; i < ts_count; i++) {
|
||||
if (i == ireg)
|
||||
emit32(entry);
|
||||
else
|
||||
emit32(0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
uint32_t len2, len3, mach_base, pad, sz_bf_entry, sz_load_cmds;
|
||||
int cpu_subtype, mflag = 0;
|
||||
|
||||
/* General housecleaning and setup. */
|
||||
output = stdout;
|
||||
program = argv[0];
|
||||
|
||||
/* Read in and process any flags. */
|
||||
while ((argc > 1) && (argv[1][0] == '-')) {
|
||||
switch (argv[1][1]) {
|
||||
case 'm': /* machine cpu type */
|
||||
mflag = 1;
|
||||
cpu_type = atoi(&argv[1][2]);
|
||||
break;
|
||||
case 'h': /* help */
|
||||
default:
|
||||
usage();
|
||||
}
|
||||
|
||||
argv++;
|
||||
argc--;
|
||||
}
|
||||
|
||||
if (!mflag)
|
||||
usage();
|
||||
|
||||
/* Check cpu type. */
|
||||
switch (cpu_type) {
|
||||
case CPU_TYPE_X86:
|
||||
bigendian = 0;
|
||||
cpu_subtype = CPU_SUBTYPE_X86_ALL;
|
||||
sz_thread_command = 4 * x86_THREAD_STATE32_COUNT;
|
||||
break;
|
||||
case CPU_TYPE_POWERPC:
|
||||
bigendian = 1;
|
||||
cpu_subtype = CPU_SUBTYPE_POWERPC_ALL;
|
||||
sz_thread_command = 4 * PPC_THREAD_STATE_COUNT;
|
||||
break;
|
||||
default:
|
||||
/* Can't emit LC_UNIXTHREAD for unknown cpu. */
|
||||
fatal("unknown cpu type -m%d", cpu_type);
|
||||
}
|
||||
sz_thread_command += SZ_THREAD_COMMAND_BF_STATE;
|
||||
|
||||
/* Process the rest of the arguments. */
|
||||
switch (argc) {
|
||||
case 1: /* No parameters --- read from stdin, write to stdout. */
|
||||
rd_fdopen(0);
|
||||
break;
|
||||
|
||||
case 3: /* Both input and output files specified. */
|
||||
output = fopen(argv[2], "w");
|
||||
if (!output)
|
||||
fatal("unable to open output file.");
|
||||
outputfile = argv[2];
|
||||
/* FALLTHROUGH */
|
||||
|
||||
case 2: /* Input file specified. */
|
||||
if (! rd_open(argv[1]))
|
||||
fatal("unable to open input file.");
|
||||
break;
|
||||
|
||||
default:
|
||||
usage();
|
||||
}
|
||||
|
||||
rd_ohead(&outhead);
|
||||
if (BADMAGIC(outhead))
|
||||
fatal("Not an ack object file.");
|
||||
if (outhead.oh_flags & HF_LINK)
|
||||
fatal("Contains unresolved references.");
|
||||
if (outhead.oh_nrelo > 0)
|
||||
fprintf(stderr, "Warning: relocation information present.");
|
||||
if (outhead.oh_nsect != NUM_SEGMENTS &&
|
||||
outhead.oh_nsect != NUM_SEGMENTS + 1 ) {
|
||||
fatal("Input file must have %d sections, not %ld\n",
|
||||
NUM_SEGMENTS, (long)outhead.oh_nsect);
|
||||
}
|
||||
|
||||
rd_sect(outsect, outhead.oh_nsect);
|
||||
|
||||
/*
|
||||
* 1st Mach segment: __PAGEZERO
|
||||
* 2nd Mach segment: __TEXT
|
||||
* Mach headers and load commands
|
||||
* ack TEXT
|
||||
* ack ROM
|
||||
* 3rd Mach segment: __DATA
|
||||
* ack DATA
|
||||
* ack BSS
|
||||
*/
|
||||
|
||||
/* Find entry point and check that TEXT begins there. */
|
||||
mach_base = pg_trunc(outsect[TEXT].os_base);
|
||||
sz_load_cmds = 3 * SZ_SEGMENT_COMMAND + sz_thread_command;
|
||||
sz_bf_entry = SZ_MACH_HEADER + sz_load_cmds;
|
||||
entry = mach_base + sz_bf_entry;
|
||||
if (entry != outsect[TEXT].os_base) {
|
||||
fatal("text segment must have base 0x%lx, not 0x%lx\n",
|
||||
entry, outsect[TEXT].os_base);
|
||||
}
|
||||
|
||||
/* Check that ROM can follow TEXT in 2nd Mach segment. */
|
||||
outsect[TEXT].os_size =
|
||||
align(outsect[TEXT].os_size, outsect[ROM].os_lign);
|
||||
if (outsect[ROM].os_base !=
|
||||
outsect[TEXT].os_base + outsect[TEXT].os_size)
|
||||
fatal("the rom segment must follow the text segment.");
|
||||
|
||||
/*
|
||||
* Insert padding between ROM and DATA, such that
|
||||
* pg_mod(len2) == pg_mod(outsect[DATA].os_base)
|
||||
*
|
||||
* This will allow us to map the 3rd Mach segment at the
|
||||
* beginning of a page, such that DATA is at its base.
|
||||
*/
|
||||
len2 = sz_bf_entry + outsect[TEXT].os_size + outsect[ROM].os_size;
|
||||
pad = pg_mod(outsect[DATA].os_base - len2);
|
||||
outsect[ROM].os_size += pad;
|
||||
len2 = pg_trunc(len2 + pad);
|
||||
|
||||
/* Check that BSS can follow DATA in 3rd Mach segment. */
|
||||
if (outsect[BSS].os_flen != 0)
|
||||
fatal("the bss space contains initialized data.");
|
||||
if (outsect[BSS].os_base <
|
||||
outsect[DATA].os_base + outsect[DATA].os_size)
|
||||
fatal("the bss segment must follow the data segment.");
|
||||
|
||||
len3 = outsect[BSS].os_base - pg_trunc(outsect[DATA].os_base) +
|
||||
outsect[BSS].os_size;
|
||||
|
||||
if (outhead.oh_nsect == NUM_SEGMENTS + 1) {
|
||||
if (outsect[NUM_SEGMENTS].os_base !=
|
||||
outsect[BSS].os_base + outsect[BSS].os_size)
|
||||
fatal("end segment must follow bss");
|
||||
if (outsect[NUM_SEGMENTS].os_size != 0)
|
||||
fatal("end segment must be empty");
|
||||
}
|
||||
|
||||
/* Emit the Mach header. */
|
||||
emit32(MH_MAGIC); /* magic */
|
||||
emit32(cpu_type); /* cpu type */
|
||||
emit32(cpu_subtype); /* cpu subtype */
|
||||
emit32(MH_EXECUTE); /* file type */
|
||||
emit32(4); /* number of load commands */
|
||||
emit32(sz_load_cmds); /* size of load commands */
|
||||
emit32(0); /* flags */
|
||||
|
||||
/* vm address: vm size:
|
||||
* 1st Mach segment: NULL CV_PGSZ
|
||||
* 2nd Mach segment: mach_base len2
|
||||
* 3rd Mach segment: mach_base+len2 len3
|
||||
*
|
||||
* file offset: file size:
|
||||
* 2nd Mach segment: 0 len2
|
||||
* 3rd Mach segment: len2 DATA os_size
|
||||
*/
|
||||
emit_lc_segment("__PAGEZERO", 0 /* NULL */, CV_PGSZ,
|
||||
0, 0, VM_PROT_NONE);
|
||||
emit_lc_segment("__TEXT", mach_base, len2,
|
||||
0, len2, VM_PROT_READ | VM_PROT_EXECUTE);
|
||||
emit_lc_segment("__DATA", mach_base + len2, len3,
|
||||
len2, outsect[DATA].os_size, VM_PROT_READ | VM_PROT_WRITE);
|
||||
emit_lc_unixthread();
|
||||
|
||||
/* Emit non-empty sections. */
|
||||
emit_section(TEXT);
|
||||
emit_section(ROM);
|
||||
emit_section(DATA);
|
||||
|
||||
if (ferror(output))
|
||||
fatal("write error");
|
||||
|
||||
return 0;
|
||||
}
|
14
plat/osx/include/ack/config.h
Normal file
14
plat/osx/include/ack/config.h
Normal file
|
@ -0,0 +1,14 @@
|
|||
/* $Source$
|
||||
* $State$
|
||||
* $Revision$
|
||||
*/
|
||||
|
||||
#ifndef _ACK_CONFIG_H
|
||||
#define _ACK_CONFIG_H
|
||||
|
||||
/* We're providing a time() system call rather than wanting a wrapper around
|
||||
* gettimeofday() in the libc. */
|
||||
|
||||
/* #define ACKCONF_TIME_IS_A_SYSCALL */
|
||||
|
||||
#endif
|
20
plat/osx/include/sys/mman.h
Normal file
20
plat/osx/include/sys/mman.h
Normal file
|
@ -0,0 +1,20 @@
|
|||
#ifndef _SYS_MMAN_H
|
||||
#define _SYS_MMAN_H
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#define MAP_FAILED ((void *)-1)
|
||||
|
||||
#define PROT_NONE 0x00
|
||||
#define PROT_READ 0x01
|
||||
#define PROT_WRITE 0x02
|
||||
#define PROT_EXEC 0x04
|
||||
|
||||
#define MAP_PRIVATE 0x0002
|
||||
#define MAP_FIXED 0x0010
|
||||
#define MAP_ANON 0x1000
|
||||
|
||||
void *mmap(void *, size_t, int, int, int, off_t);
|
||||
int mprotect(void *, size_t, int);
|
||||
|
||||
#endif
|
9
plat/osx/include/sys/types.h
Normal file
9
plat/osx/include/sys/types.h
Normal file
|
@ -0,0 +1,9 @@
|
|||
#ifndef _SYS_TYPES_H
|
||||
#define _SYS_TYPES_H
|
||||
|
||||
#include <stddef.h> /* for off_t, ptrdiff_t, size_t */
|
||||
|
||||
typedef int pid_t;
|
||||
typedef ptrdiff_t ssize_t;
|
||||
|
||||
#endif
|
132
plat/osx/include/unistd.h
Normal file
132
plat/osx/include/unistd.h
Normal file
|
@ -0,0 +1,132 @@
|
|||
#ifndef _UNISTD_H
|
||||
#define _UNISTD_H
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
/*
|
||||
* XXX - The following parts belong in other header files,
|
||||
* but those headers are including us!
|
||||
*/
|
||||
|
||||
/* XXX - begin sys/ioctl.h */
|
||||
|
||||
#define TIOCGETD 0x4004741a
|
||||
|
||||
int ioctl(int, unsigned long, ...);
|
||||
|
||||
/* XXX - end sys/ioctl.h */
|
||||
|
||||
/* XXX - begin sys/time.h */
|
||||
|
||||
/* Don't conflict with time_t from <time.h> */
|
||||
typedef long _libsys_time_t;
|
||||
typedef int suseconds_t;
|
||||
|
||||
struct timeval {
|
||||
_libsys_time_t tv_sec;
|
||||
suseconds_t tv_usec;
|
||||
};
|
||||
|
||||
struct timezone {
|
||||
int tz_minuteswest;
|
||||
int tz_dsttime;
|
||||
};
|
||||
|
||||
int gettimeofday(struct timeval *, struct timezone *);
|
||||
|
||||
/* XXX - end sys/time.h */
|
||||
|
||||
/* XXX - begin fcntl.h */
|
||||
|
||||
/* flags for open() */
|
||||
#define O_RDONLY 0x0000
|
||||
#define O_WRONLY 0x0001
|
||||
#define O_RDWR 0x0002
|
||||
#define O_NONBLOCK 0x0004
|
||||
#define O_APPEND 0x0008
|
||||
#define O_CREAT 0x0200
|
||||
#define O_TRUNC 0x0400
|
||||
#define O_EXCL 0x0800
|
||||
|
||||
typedef int mode_t;
|
||||
|
||||
int creat(const char *, mode_t);
|
||||
int open(const char *, int, ...);
|
||||
|
||||
/* XXX - end fcntl.h */
|
||||
|
||||
/* XXX - begin signal.h */
|
||||
|
||||
#define SIGHUP 1
|
||||
#define SIGINT 2
|
||||
#define SIGQUIT 3
|
||||
#define SIGILL 4
|
||||
#define SIGTRAP 5
|
||||
#define SIGABRT 6
|
||||
#define SIGEMT 7
|
||||
#define SIGFPE 8
|
||||
#define SIGKILL 9
|
||||
#define SIGBUS 10
|
||||
#define SIGSEGV 11
|
||||
#define SIGSYS 12
|
||||
#define SIGPIPE 13
|
||||
#define SIGALRM 14
|
||||
#define SIGTERM 15
|
||||
#define SIGURG 16
|
||||
#define SIGSTOP 17
|
||||
#define SIGTSTP 18
|
||||
#define SIGCONT 19
|
||||
#define SIGCHLD 20
|
||||
#define SIGTTIN 21
|
||||
#define SIGTTOU 22
|
||||
#define SIGIO 23
|
||||
#define SIGXCPU 24
|
||||
#define SIGXFSZ 25
|
||||
#define SIGVTALRM 26
|
||||
#define SIGPROF 27
|
||||
#define SIGWINCH 28
|
||||
#define SIGINFO 29
|
||||
#define SIGUSR1 30
|
||||
#define SIGUSR2 31
|
||||
#define _NSIG 32
|
||||
|
||||
/* sa_flags */
|
||||
#define SA_RESTART 0x0002
|
||||
|
||||
typedef void (*sig_t)(int);
|
||||
#define SIG_DFL ((sig_t)0)
|
||||
#define SIG_IGN ((sig_t)1)
|
||||
#define SIG_ERR ((sig_t)-1)
|
||||
|
||||
typedef unsigned int sigset_t;
|
||||
|
||||
struct __siginfo;
|
||||
|
||||
struct sigaction {
|
||||
union {
|
||||
void (*__sa_handler)(int);
|
||||
void (*__sa_sigaction)(int, struct __siginfo *, void *);
|
||||
} __sigaction_u;
|
||||
sigset_t sa_mask;
|
||||
int sa_flags;
|
||||
};
|
||||
#define sa_handler __sigaction_u.__sa_handler
|
||||
#define sa_sigaction __sigaction_u.__sa_sigaction
|
||||
|
||||
int kill(pid_t, int);
|
||||
int sigaction(int, const struct sigaction *, struct sigaction *);
|
||||
sig_t signal(int, sig_t);
|
||||
|
||||
/* XXX - end signal.h */
|
||||
|
||||
void _exit(int);
|
||||
int brk(void *);
|
||||
int close(int);
|
||||
pid_t getpid(void);
|
||||
int isatty(int);
|
||||
off_t lseek(int, off_t, int);
|
||||
ssize_t read(int, void *, size_t);
|
||||
void *sbrk(int);
|
||||
ssize_t write(int, const void *, size_t);
|
||||
|
||||
#endif
|
95
plat/osx/libsys/brk.c
Normal file
95
plat/osx/libsys/brk.c
Normal file
|
@ -0,0 +1,95 @@
|
|||
/*
|
||||
* This emulates brk() and sbrk() using mmap() and mprotect().
|
||||
*
|
||||
* We reserve exactly SEGMENTSZ bytes of address space by calling
|
||||
* mmap() with PROT_NONE. Then we allocate pages in our segment by
|
||||
* calling mprotect() with PROT_READ|PROT_WRITE.
|
||||
*
|
||||
* This emulation can't resize its segment. If SEGMENTSZ is too big,
|
||||
* then programs might run out of address space for other mappings.
|
||||
*/
|
||||
#include <sys/mman.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
|
||||
/*
|
||||
* PAGESZ must be correct for this system!
|
||||
* SEGMENTSZ must be a multiple of PAGESZ.
|
||||
*/
|
||||
#define PAGESZ 0x1000 /* page size for i386, powerpc */
|
||||
#define SEGMENTSZ 0x20000000
|
||||
|
||||
static char *segment;
|
||||
static char *cbreak; /* current break */
|
||||
|
||||
static void brk_init(void)
|
||||
{
|
||||
/*
|
||||
* Try exactly once to reserve our segment. If we fail, then
|
||||
* segment == MAP_FAILED and we never try again.
|
||||
*/
|
||||
if (segment == NULL) {
|
||||
segment = mmap(NULL, SEGMENTSZ, PROT_NONE,
|
||||
MAP_PRIVATE|MAP_ANON, -1, 0);
|
||||
cbreak = segment;
|
||||
}
|
||||
}
|
||||
|
||||
static int brk1(char *nbreak)
|
||||
{
|
||||
size_t sz;
|
||||
char *new, *old;
|
||||
|
||||
sz = (segment == MAP_FAILED) ? 0 : SEGMENTSZ;
|
||||
if (nbreak < segment || nbreak > segment + sz) {
|
||||
errno = ENOMEM;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Round up to page size. */
|
||||
old = (char *)(((size_t)cbreak + (PAGESZ-1)) & ~(PAGESZ-1));
|
||||
new = (char *)(((size_t)nbreak + (PAGESZ-1)) & ~(PAGESZ-1));
|
||||
|
||||
if (new > old) {
|
||||
/* Allocate pages by unprotecting them. */
|
||||
if (mprotect(old, new - old, PROT_READ|PROT_WRITE) < 0) {
|
||||
errno = ENOMEM;
|
||||
return -1;
|
||||
}
|
||||
} else if (new < old) {
|
||||
/*
|
||||
* Free pages by using MAP_FIXED to replace the
|
||||
* mapping. Ignore errors.
|
||||
*/
|
||||
mmap(new, old - new, PROT_NONE,
|
||||
MAP_PRIVATE|MAP_ANON|MAP_FIXED, -1, 0);
|
||||
}
|
||||
cbreak = nbreak;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int brk(void *addr)
|
||||
{
|
||||
brk_init();
|
||||
return brk1(addr);
|
||||
}
|
||||
|
||||
void *sbrk(int incr)
|
||||
{
|
||||
char *base, *nbreak;
|
||||
|
||||
brk_init();
|
||||
base = cbreak;
|
||||
nbreak = base + incr;
|
||||
|
||||
/* Did base + incr overflow? */
|
||||
if ((incr < 0 && nbreak > base) ||
|
||||
(incr > 0 && nbreak < base)) {
|
||||
errno = ENOMEM;
|
||||
return (void*)-1;
|
||||
}
|
||||
|
||||
if (brk1(nbreak) < 0)
|
||||
return (void*)-1;
|
||||
return base;
|
||||
}
|
6
plat/osx/libsys/creat.c
Normal file
6
plat/osx/libsys/creat.c
Normal file
|
@ -0,0 +1,6 @@
|
|||
#include <fcntl.h>
|
||||
|
||||
int creat(const char *path, mode_t mode)
|
||||
{
|
||||
open(path, O_CREAT | O_TRUNC | O_WRONLY, mode);
|
||||
}
|
7
plat/osx/libsys/isatty.c
Normal file
7
plat/osx/libsys/isatty.c
Normal file
|
@ -0,0 +1,7 @@
|
|||
#include <sys/ioctl.h>
|
||||
|
||||
int isatty(int fd)
|
||||
{
|
||||
int line_disc;
|
||||
return 0 <= ioctl(fd, TIOCGETD, &line_disc);
|
||||
}
|
16
plat/osx/libsys/signal.c
Normal file
16
plat/osx/libsys/signal.c
Normal file
|
@ -0,0 +1,16 @@
|
|||
#include <signal.h>
|
||||
|
||||
sig_t signal(int sig, sig_t func)
|
||||
{
|
||||
struct sigaction newsa, oldsa;
|
||||
int i;
|
||||
|
||||
newsa.sa_handler = func;
|
||||
newsa.sa_mask = 0; /* empty set */
|
||||
newsa.sa_flags = SA_RESTART;
|
||||
|
||||
i = sigaction(sig, &newsa, &oldsa);
|
||||
if (i < 0)
|
||||
return SIG_ERR;
|
||||
return oldsa.sa_handler;
|
||||
}
|
69
plat/osx386/boot.s
Normal file
69
plat/osx386/boot.s
Normal file
|
@ -0,0 +1,69 @@
|
|||
! plat/osx386/boot.s
|
||||
|
||||
! Declare segments (the order is important).
|
||||
|
||||
.sect .text
|
||||
.sect .rom
|
||||
.sect .data
|
||||
.sect .bss
|
||||
|
||||
.sect .text
|
||||
|
||||
begtext:
|
||||
! This code is placed at the entry point of the Mach-o
|
||||
! executable and is the first thing that runs.
|
||||
!
|
||||
! On entry, the stack looks like this:
|
||||
!
|
||||
! sp+.. NULL
|
||||
! sp+8+(4*argc) env (X quads)
|
||||
! sp+4+(4*argc) NULL
|
||||
! sp+4 argv (argc quads)
|
||||
! sp argc
|
||||
!
|
||||
! The ACK actually expects:
|
||||
!
|
||||
! sp+8 argc
|
||||
! sp+4 argv
|
||||
! sp env
|
||||
|
||||
mov eax, (esp) ! eax = argc
|
||||
lea ebx, 4(esp) ! ebx = argv
|
||||
lea ecx, (esp)(eax*4)
|
||||
add ecx, 12 ! environ
|
||||
|
||||
push ecx ! environ
|
||||
push ebx ! argc
|
||||
push eax ! argv
|
||||
push eax ! dummy, representing the return argument
|
||||
xor ebp, ebp
|
||||
|
||||
jmp __m_a_i_n
|
||||
|
||||
! This provides an emergency exit routine used by EM.
|
||||
|
||||
.define EXIT
|
||||
.extern EXIT
|
||||
EXIT:
|
||||
push 1
|
||||
jmp __exit
|
||||
|
||||
.sect rom
|
||||
begrom:
|
||||
|
||||
.sect .data
|
||||
begdata:
|
||||
|
||||
! Some magic data. All EM systems need these.
|
||||
|
||||
.sect .bss
|
||||
begbss:
|
||||
.define hol0
|
||||
.comm hol0, 8 ! line number and filename (for debugging)
|
||||
|
||||
.define _errno
|
||||
.comm _errno, 4 ! Posix errno storage
|
||||
|
||||
.define .trppc, .ignmask
|
||||
.comm .trppc, 4 ! ptr to user trap handler
|
||||
.comm .ignmask, 4 ! user trap ignore mask
|
24
plat/osx386/build-pkg.lua
Normal file
24
plat/osx386/build-pkg.lua
Normal file
|
@ -0,0 +1,24 @@
|
|||
include("plat/build.lua")
|
||||
|
||||
ackfile {
|
||||
name = "boot",
|
||||
srcs = { "./boot.s" },
|
||||
vars = { plat = "osx386" }
|
||||
}
|
||||
|
||||
build_plat_libs {
|
||||
name = "libs",
|
||||
arch = "i386",
|
||||
plat = "osx386",
|
||||
}
|
||||
|
||||
installable {
|
||||
name = "pkg",
|
||||
map = {
|
||||
"+tools",
|
||||
"+libs",
|
||||
"./include+pkg",
|
||||
["$(PLATIND)/osx386/boot.o"] = "+boot",
|
||||
["$(PLATIND)/osx386/libsys.a"] = "./libsys+lib",
|
||||
}
|
||||
}
|
9
plat/osx386/build-tools.lua
Normal file
9
plat/osx386/build-tools.lua
Normal file
|
@ -0,0 +1,9 @@
|
|||
return installable {
|
||||
name = "tools",
|
||||
map = {
|
||||
["$(PLATIND)/descr/osx386"] = "./descr",
|
||||
"plat/linux386+tools",
|
||||
"plat/osx/cvmach+pkg",
|
||||
"util/opt+pkg",
|
||||
}
|
||||
}
|
80
plat/osx386/descr
Normal file
80
plat/osx386/descr
Normal file
|
@ -0,0 +1,80 @@
|
|||
# plat/osx386/descr
|
||||
|
||||
var w=4
|
||||
var wa=4
|
||||
var p={w}
|
||||
var pa={w}
|
||||
var s=2
|
||||
var sa={s}
|
||||
var l={w}
|
||||
var la={w}
|
||||
var f={w}
|
||||
var fa={w}
|
||||
var d=8
|
||||
var da={d}
|
||||
var x=8
|
||||
var xa={x}
|
||||
var ARCH=i386
|
||||
var PLATFORM=osx386
|
||||
var PLATFORMDIR={EM}/share/ack/{PLATFORM}
|
||||
var CPP_F=-D__unix
|
||||
var ALIGN=-a0:4 -a1:4 -a2:4096 -a3:4 -b0:0x1114
|
||||
var C_LIB={PLATFORMDIR}/libc-ansi.a
|
||||
# bitfields reversed for compatibility with (g)cc.
|
||||
var CC_ALIGN=-Vr
|
||||
var OLD_C_LIB={C_LIB}
|
||||
var MACHOPT_F=-m10
|
||||
var EGO_PLAT_FLAGS=-M{EM}/share/ack/ego/{ARCH}.descr
|
||||
|
||||
# Override the setting in fe so that files compiled for osx386 can see
|
||||
# the platform-specific headers.
|
||||
|
||||
var C_INCLUDES=-I{PLATFORMDIR}/include -I{EM}/share/ack/include/ansi
|
||||
|
||||
name be
|
||||
from .m.g
|
||||
to .s
|
||||
program {EM}/lib/ack/linux386/ncg
|
||||
mapflag -gdb GF=-gdb
|
||||
args {GF?} <
|
||||
stdout
|
||||
need .e
|
||||
end
|
||||
name as
|
||||
from .s.so
|
||||
to .o
|
||||
program {EM}/lib/ack/linux386/as
|
||||
args - -o > <
|
||||
prep cond
|
||||
end
|
||||
name led
|
||||
from .o.a
|
||||
to .out
|
||||
program {EM}/lib/ack/em_led
|
||||
mapflag -l* LNAME={PLATFORMDIR}/lib*
|
||||
mapflag -fp FLOATS={EM}/{LIB}fp
|
||||
args {ALIGN} {SEPID?} \
|
||||
(.e:{HEAD}={PLATFORMDIR}/boot.o) \
|
||||
({RTS}:.ocm.b={PLATFORMDIR}/c-ansi.o) \
|
||||
({RTS}:.c={PLATFORMDIR}/c-ansi.o) \
|
||||
({RTS}:.mod={PLATFORMDIR}/modula2.o) \
|
||||
({RTS}:.p={PLATFORMDIR}/pascal.o) \
|
||||
-o > < \
|
||||
(.p:{TAIL}={PLATFORMDIR}/libpascal.a) \
|
||||
(.b:{TAIL}={PLATFORMDIR}/libbasic.a) \
|
||||
(.mod:{TAIL}={PLATFORMDIR}/libmodula2.a) \
|
||||
(.ocm:{TAIL}={PLATFORMDIR}/liboccam.a) \
|
||||
(.ocm.b.mod.c.p:{TAIL}={PLATFORMDIR}/libc.a) \
|
||||
{FLOATS?} \
|
||||
(.e:{TAIL}={PLATFORMDIR}/libem.a \
|
||||
{PLATFORMDIR}/libsys.a \
|
||||
{PLATFORMDIR}/libend.a)
|
||||
linker
|
||||
end
|
||||
name cv
|
||||
from .out
|
||||
to .exe
|
||||
program {EM}/lib/ack/cvmach
|
||||
args -m7 < >
|
||||
outfile osx386.exe
|
||||
end
|
24
plat/osx386/include/build.lua
Normal file
24
plat/osx386/include/build.lua
Normal file
|
@ -0,0 +1,24 @@
|
|||
include("plat/build.lua")
|
||||
|
||||
headermap = {}
|
||||
packagemap = {}
|
||||
|
||||
local function addheader(h)
|
||||
headermap[h] = "plat/osx/include/"..h
|
||||
packagemap["$(PLATIND)/osx386/include/"..h] = "plat/osx/include/"..h
|
||||
end
|
||||
|
||||
addheader("ack/config.h")
|
||||
addheader("sys/mman.h")
|
||||
addheader("sys/types.h")
|
||||
addheader("unistd.h")
|
||||
|
||||
acklibrary {
|
||||
name = "headers",
|
||||
hdrs = headermap
|
||||
}
|
||||
|
||||
installable {
|
||||
name = "pkg",
|
||||
map = packagemap
|
||||
}
|
5
plat/osx386/libsys/_exit.s
Normal file
5
plat/osx386/libsys/_exit.s
Normal file
|
@ -0,0 +1,5 @@
|
|||
.sect .text
|
||||
.define __exit
|
||||
__exit:
|
||||
mov eax, 1
|
||||
int 0x80
|
31
plat/osx386/libsys/build.lua
Normal file
31
plat/osx386/libsys/build.lua
Normal file
|
@ -0,0 +1,31 @@
|
|||
acklibrary {
|
||||
name = "lib",
|
||||
srcs = {
|
||||
"./_exit.s",
|
||||
"./close.s",
|
||||
"./getpid.s",
|
||||
"./gettimeofday.s",
|
||||
"./ioctl.s",
|
||||
"./kill.s",
|
||||
"./lseek.s",
|
||||
"./mmap.s",
|
||||
"./mprotect.s",
|
||||
"./open.s",
|
||||
"./read.s",
|
||||
"./set_errno.s",
|
||||
"./sigaction.s",
|
||||
"./write.s",
|
||||
"plat/linux/libsys/errno.s",
|
||||
"plat/osx/libsys/brk.c",
|
||||
"plat/osx/libsys/creat.c",
|
||||
"plat/osx/libsys/isatty.c",
|
||||
"plat/osx/libsys/signal.c",
|
||||
},
|
||||
deps = {
|
||||
"lang/cem/libcc.ansi/headers+headers",
|
||||
"plat/osx386/include+headers",
|
||||
},
|
||||
vars = {
|
||||
plat = "osx386"
|
||||
}
|
||||
}
|
7
plat/osx386/libsys/close.s
Normal file
7
plat/osx386/libsys/close.s
Normal file
|
@ -0,0 +1,7 @@
|
|||
.sect .text
|
||||
.define _close
|
||||
_close:
|
||||
mov eax, 6
|
||||
int 0x80
|
||||
jb .set_errno
|
||||
ret
|
7
plat/osx386/libsys/getpid.s
Normal file
7
plat/osx386/libsys/getpid.s
Normal file
|
@ -0,0 +1,7 @@
|
|||
.sect .text
|
||||
.define _getpid
|
||||
_getpid:
|
||||
mov eax, 20
|
||||
int 0x80
|
||||
jb .set_errno
|
||||
ret
|
7
plat/osx386/libsys/gettimeofday.s
Normal file
7
plat/osx386/libsys/gettimeofday.s
Normal file
|
@ -0,0 +1,7 @@
|
|||
.sect .text
|
||||
.define _gettimeofday
|
||||
_gettimeofday:
|
||||
mov eax, 116
|
||||
int 0x80
|
||||
jb .set_errno
|
||||
ret
|
7
plat/osx386/libsys/ioctl.s
Normal file
7
plat/osx386/libsys/ioctl.s
Normal file
|
@ -0,0 +1,7 @@
|
|||
.sect .text
|
||||
.define _ioctl
|
||||
_ioctl:
|
||||
mov eax, 54
|
||||
int 0x80
|
||||
jb .set_errno
|
||||
ret
|
7
plat/osx386/libsys/kill.s
Normal file
7
plat/osx386/libsys/kill.s
Normal file
|
@ -0,0 +1,7 @@
|
|||
.sect .text
|
||||
.define _kill
|
||||
_kill:
|
||||
mov eax, 37
|
||||
int 0x80
|
||||
jb .set_errno
|
||||
ret
|
17
plat/osx386/libsys/lseek.s
Normal file
17
plat/osx386/libsys/lseek.s
Normal file
|
@ -0,0 +1,17 @@
|
|||
.sect .text
|
||||
.define _lseek
|
||||
_lseek:
|
||||
! ack passes 4-byte off_t, but system call takes 8-byte off_t
|
||||
mov eax, esp
|
||||
push 12(eax) ! whence
|
||||
push 0 ! offset (high long)
|
||||
push 8(eax) ! offset (low long)
|
||||
push 4(eax) ! fd
|
||||
call 1f
|
||||
add esp, 16
|
||||
ret
|
||||
1:
|
||||
mov eax, 199
|
||||
int 0x80
|
||||
jb .set_errno
|
||||
ret
|
20
plat/osx386/libsys/mmap.s
Normal file
20
plat/osx386/libsys/mmap.s
Normal file
|
@ -0,0 +1,20 @@
|
|||
.sect .text
|
||||
.define _mmap
|
||||
_mmap:
|
||||
! ack passes 4-byte off_t, but system call takes 8-byte off_t
|
||||
mov eax, esp
|
||||
push 0 ! offset (high long)
|
||||
push 24(eax) ! offset (low long)
|
||||
push 20(eax) ! fd
|
||||
push 16(eax) ! flags
|
||||
push 12(eax) ! protection
|
||||
push 8(eax) ! length
|
||||
push 4(eax) ! address
|
||||
call 1f
|
||||
add esp, 28
|
||||
ret
|
||||
1:
|
||||
mov eax, 197
|
||||
int 0x80
|
||||
jb .set_errno
|
||||
ret
|
7
plat/osx386/libsys/mprotect.s
Normal file
7
plat/osx386/libsys/mprotect.s
Normal file
|
@ -0,0 +1,7 @@
|
|||
.sect .text
|
||||
.define _mprotect
|
||||
_mprotect:
|
||||
mov eax, 74
|
||||
int 0x80
|
||||
jb .set_errno
|
||||
ret
|
7
plat/osx386/libsys/open.s
Normal file
7
plat/osx386/libsys/open.s
Normal file
|
@ -0,0 +1,7 @@
|
|||
.sect .text
|
||||
.define _open
|
||||
_open:
|
||||
mov eax, 5
|
||||
int 0x80
|
||||
jb .set_errno
|
||||
ret
|
7
plat/osx386/libsys/read.s
Normal file
7
plat/osx386/libsys/read.s
Normal file
|
@ -0,0 +1,7 @@
|
|||
.sect .text
|
||||
.define _read
|
||||
_read:
|
||||
mov eax, 3
|
||||
int 0x80
|
||||
jb .set_errno
|
||||
ret
|
6
plat/osx386/libsys/set_errno.s
Normal file
6
plat/osx386/libsys/set_errno.s
Normal file
|
@ -0,0 +1,6 @@
|
|||
.sect .text
|
||||
.define .set_errno
|
||||
.set_errno:
|
||||
mov (_errno), eax
|
||||
mov eax, -1
|
||||
ret
|
59
plat/osx386/libsys/sigaction.s
Normal file
59
plat/osx386/libsys/sigaction.s
Normal file
|
@ -0,0 +1,59 @@
|
|||
! OS X, unlike FreeBSD, requires us to provide our own signal
|
||||
! trampoline. We must change the new action from a struct sigaction
|
||||
! to a bigger struct that includes the trampoline.
|
||||
|
||||
.sect .text
|
||||
.define _sigaction
|
||||
_sigaction:
|
||||
mov eax, esp
|
||||
mov ebx, 8(esp) ! ebx = ptr to new action
|
||||
cmp ebx, 0
|
||||
je 1f
|
||||
! push bigger struct
|
||||
push 8(ebx) ! sa_flags
|
||||
push 4(ebx) ! sa_mask
|
||||
push trampoline ! sa_tramp
|
||||
push 0(ebx) ! sa_handler
|
||||
mov ebx, esp
|
||||
jmp 2f
|
||||
1:
|
||||
sub esp, 16
|
||||
2:
|
||||
push 12(eax) ! ptr to old action
|
||||
push ebx ! ptr to bigger struct
|
||||
push 4(eax) ! sig
|
||||
call 3f
|
||||
add esp, 28
|
||||
ret
|
||||
3:
|
||||
mov eax, 46
|
||||
int 0x80
|
||||
jb .set_errno
|
||||
ret
|
||||
|
||||
trampoline:
|
||||
! 4(esp) = handler
|
||||
! 8(esp) = info style
|
||||
! 12(esp) = sig
|
||||
! 16(esp) = info
|
||||
! 20(esp) = context
|
||||
|
||||
! Call handler(sig, info, context)
|
||||
mov eax, esp
|
||||
push 20(eax)
|
||||
push 16(eax)
|
||||
push 12(eax)
|
||||
call 4(eax)
|
||||
add esp, 12
|
||||
|
||||
! Return from trampoline.
|
||||
mov eax, esp
|
||||
push 8(eax) ! info style
|
||||
push 20(eax) ! context
|
||||
sub esp, 4
|
||||
mov eax, 184 ! sigreturn
|
||||
int 0x80
|
||||
|
||||
! Only if sigreturn() fails:
|
||||
mov eax, 1 ! exit
|
||||
int 0x80
|
7
plat/osx386/libsys/write.s
Normal file
7
plat/osx386/libsys/write.s
Normal file
|
@ -0,0 +1,7 @@
|
|||
.sect .text
|
||||
.define _write
|
||||
_write:
|
||||
mov eax, 4
|
||||
int 0x80
|
||||
jb .set_errno
|
||||
ret
|
60
plat/osxppc/boot.s
Normal file
60
plat/osxppc/boot.s
Normal file
|
@ -0,0 +1,60 @@
|
|||
! boot.s for osx386
|
||||
|
||||
! Declare segments (the order is important).
|
||||
|
||||
.sect .text
|
||||
.sect .rom
|
||||
.sect .data
|
||||
.sect .bss
|
||||
|
||||
.sect .text
|
||||
|
||||
begtext:
|
||||
! This code is placed at the entry point of the Mach-o
|
||||
! executable and is the first thing that runs.
|
||||
!
|
||||
! On entry, the stack looks like this:
|
||||
!
|
||||
! sp+... NULL
|
||||
! sp+8+(4*argc) env (X quads)
|
||||
! sp+4+(4*argc) NULL
|
||||
! sp+4 argv (argc quads)
|
||||
! sp argc
|
||||
!
|
||||
! The ACK actually expects:
|
||||
!
|
||||
! sp+8 argc
|
||||
! sp+4 ptr to argv
|
||||
! sp ptr to env
|
||||
|
||||
lwz r3, 0(sp) ! r3 = argc
|
||||
addi r4, sp, 4 ! r4 = argv
|
||||
rlwinm r5, r3, 32-2, 2, 31 ! shift left 2 bits
|
||||
add r5, r5, r4
|
||||
addi r5, r5, 8 ! r5 = env
|
||||
|
||||
stwu r5, -4(sp)
|
||||
stwu r4, -4(sp)
|
||||
stwu r3, -4(sp)
|
||||
|
||||
b __m_a_i_n
|
||||
|
||||
.sect rom
|
||||
begrom:
|
||||
|
||||
.sect .data
|
||||
begdata:
|
||||
|
||||
! Some magic data. All EM systems need these.
|
||||
|
||||
.sect .bss
|
||||
begbss:
|
||||
.define hol0
|
||||
.comm hol0, 8 ! line number and filename (for debugging)
|
||||
|
||||
.define _errno
|
||||
.comm _errno, 4 ! Posix errno storage
|
||||
|
||||
.define .trppc, .ignmask
|
||||
.comm .trppc, 4 ! ptr to user trap handler
|
||||
.comm .ignmask, 4 ! user trap ignore mask
|
24
plat/osxppc/build-pkg.lua
Normal file
24
plat/osxppc/build-pkg.lua
Normal file
|
@ -0,0 +1,24 @@
|
|||
include("plat/build.lua")
|
||||
|
||||
ackfile {
|
||||
name = "boot",
|
||||
srcs = { "./boot.s" },
|
||||
vars = { plat = "osxppc" }
|
||||
}
|
||||
|
||||
build_plat_libs {
|
||||
name = "libs",
|
||||
arch = "powerpc",
|
||||
plat = "osxppc",
|
||||
}
|
||||
|
||||
installable {
|
||||
name = "pkg",
|
||||
map = {
|
||||
"+tools",
|
||||
"+libs",
|
||||
"./include+pkg",
|
||||
["$(PLATIND)/osxppc/boot.o"] = "+boot",
|
||||
["$(PLATIND)/osxppc/libsys.a"] = "./libsys+lib",
|
||||
}
|
||||
}
|
9
plat/osxppc/build-tools.lua
Normal file
9
plat/osxppc/build-tools.lua
Normal file
|
@ -0,0 +1,9 @@
|
|||
return installable {
|
||||
name = "tools",
|
||||
map = {
|
||||
["$(PLATIND)/descr/osxppc"] = "./descr",
|
||||
"plat/linuxppc+tools",
|
||||
"plat/osx/cvmach+pkg",
|
||||
"util/opt+pkg",
|
||||
}
|
||||
}
|
81
plat/osxppc/descr
Normal file
81
plat/osxppc/descr
Normal file
|
@ -0,0 +1,81 @@
|
|||
# plat/osxppc/descr
|
||||
|
||||
var w=4
|
||||
var wa=4
|
||||
var p={w}
|
||||
var pa={w}
|
||||
var s=2
|
||||
var sa={s}
|
||||
var l={w}
|
||||
var la={w}
|
||||
var f={w}
|
||||
var fa={w}
|
||||
var d=8
|
||||
var da={d}
|
||||
var x=8
|
||||
var xa={x}
|
||||
var ARCH=powerpc
|
||||
var PLATFORM=osxppc
|
||||
var PLATFORMDIR={EM}/share/ack/{PLATFORM}
|
||||
var CPP_F=-D__unix
|
||||
var ALIGN=-a0:4 -a1:4 -a2:4096 -a3:4 -b0:0x1174
|
||||
var C_LIB={PLATFORMDIR}/libc-ansi.a
|
||||
# bitfields reversed for compatibility with (g)cc.
|
||||
# XXX this is from linux386, might be wrong for osxppc
|
||||
var CC_ALIGN=-Vr
|
||||
var OLD_C_LIB={C_LIB}
|
||||
var MACHOPT_F=-m10
|
||||
# var EGO_PLAT_FLAGS=-M{EM}/share/ack/ego/{ARCH}.descr
|
||||
|
||||
# Override the setting in fe so that files compiled for osxppc can see
|
||||
# the platform-specific headers.
|
||||
|
||||
var C_INCLUDES=-I{PLATFORMDIR}/include -I{EM}/share/ack/include/ansi
|
||||
|
||||
name be
|
||||
from .m.g
|
||||
to .s
|
||||
program {EM}/lib/ack/linuxppc/ncg
|
||||
mapflag -gdb GF=-gdb
|
||||
args {GF?} <
|
||||
stdout
|
||||
need .e
|
||||
end
|
||||
name as
|
||||
from .s.so
|
||||
to .o
|
||||
program {EM}/lib/ack/linuxppc/as
|
||||
args - -o > <
|
||||
prep cond
|
||||
end
|
||||
name led
|
||||
from .o.a
|
||||
to .out
|
||||
program {EM}/lib/ack/em_led
|
||||
mapflag -l* LNAME={PLATFORMDIR}/lib*
|
||||
mapflag -fp FLOATS={EM}/{LIB}fp
|
||||
args {ALIGN} {SEPID?} \
|
||||
(.e:{HEAD}={PLATFORMDIR}/boot.o) \
|
||||
({RTS}:.ocm.b={PLATFORMDIR}/c-ansi.o) \
|
||||
({RTS}:.c={PLATFORMDIR}/c-ansi.o) \
|
||||
({RTS}:.mod={PLATFORMDIR}/modula2.o) \
|
||||
({RTS}:.p={PLATFORMDIR}/pascal.o) \
|
||||
-o > < \
|
||||
(.p:{TAIL}={PLATFORMDIR}/libpascal.a) \
|
||||
(.b:{TAIL}={PLATFORMDIR}/libbasic.a) \
|
||||
(.mod:{TAIL}={PLATFORMDIR}/libmodula2.a) \
|
||||
(.ocm:{TAIL}={PLATFORMDIR}/liboccam.a) \
|
||||
(.ocm.b.mod.c.p:{TAIL}={PLATFORMDIR}/libc.a) \
|
||||
{FLOATS?} \
|
||||
(.e:{TAIL}={PLATFORMDIR}/libem.a \
|
||||
{PLATFORMDIR}/libsys.a \
|
||||
{PLATFORMDIR}/libend.a)
|
||||
linker
|
||||
end
|
||||
name cv
|
||||
from .out
|
||||
to .exe
|
||||
program {EM}/lib/ack/cvmach
|
||||
args -m18 < >
|
||||
outfile osxppc.exe
|
||||
end
|
24
plat/osxppc/include/build.lua
Normal file
24
plat/osxppc/include/build.lua
Normal file
|
@ -0,0 +1,24 @@
|
|||
include("plat/build.lua")
|
||||
|
||||
headermap = {}
|
||||
packagemap = {}
|
||||
|
||||
local function addheader(h)
|
||||
headermap[h] = "plat/osx/include/"..h
|
||||
packagemap["$(PLATIND)/osxppc/include/"..h] = "plat/osx/include/"..h
|
||||
end
|
||||
|
||||
addheader("ack/config.h")
|
||||
addheader("sys/mman.h")
|
||||
addheader("sys/types.h")
|
||||
addheader("unistd.h")
|
||||
|
||||
acklibrary {
|
||||
name = "headers",
|
||||
hdrs = headermap
|
||||
}
|
||||
|
||||
installable {
|
||||
name = "pkg",
|
||||
map = packagemap
|
||||
}
|
6
plat/osxppc/libsys/_exit.s
Normal file
6
plat/osxppc/libsys/_exit.s
Normal file
|
@ -0,0 +1,6 @@
|
|||
.sect .text
|
||||
.define __exit
|
||||
__exit:
|
||||
addi r0, r0, 1 ! _exit
|
||||
lwz r3, 0(sp) ! status
|
||||
sc 0
|
31
plat/osxppc/libsys/build.lua
Normal file
31
plat/osxppc/libsys/build.lua
Normal file
|
@ -0,0 +1,31 @@
|
|||
acklibrary {
|
||||
name = "lib",
|
||||
srcs = {
|
||||
"./_exit.s",
|
||||
"./close.s",
|
||||
"./getpid.s",
|
||||
"./gettimeofday.s",
|
||||
"./ioctl.s",
|
||||
"./kill.s",
|
||||
"./lseek.s",
|
||||
"./mmap.s",
|
||||
"./mprotect.s",
|
||||
"./open.s",
|
||||
"./read.s",
|
||||
"./set_errno.s",
|
||||
"./sigaction.s",
|
||||
"./write.s",
|
||||
"plat/linuxppc/libsys/trap.s",
|
||||
"plat/osx/libsys/brk.c",
|
||||
"plat/osx/libsys/creat.c",
|
||||
"plat/osx/libsys/isatty.c",
|
||||
"plat/osx/libsys/signal.c",
|
||||
},
|
||||
deps = {
|
||||
"lang/cem/libcc.ansi/headers+headers",
|
||||
"plat/osxppc/include+headers",
|
||||
},
|
||||
vars = {
|
||||
plat = "osxppc"
|
||||
}
|
||||
}
|
8
plat/osxppc/libsys/close.s
Normal file
8
plat/osxppc/libsys/close.s
Normal file
|
@ -0,0 +1,8 @@
|
|||
.sect .text
|
||||
.define _close
|
||||
_close:
|
||||
addi r0, r0, 6 ! close
|
||||
lwz r3, 0(sp) ! fd
|
||||
sc 0
|
||||
b .set_errno
|
||||
bclr 20, 0, 0
|
7
plat/osxppc/libsys/getpid.s
Normal file
7
plat/osxppc/libsys/getpid.s
Normal file
|
@ -0,0 +1,7 @@
|
|||
.sect .text
|
||||
.define _getpid
|
||||
_getpid:
|
||||
addi r0, r0, 20 ! getpid
|
||||
sc 0
|
||||
b .set_errno
|
||||
bclr 20, 0, 0
|
9
plat/osxppc/libsys/gettimeofday.s
Normal file
9
plat/osxppc/libsys/gettimeofday.s
Normal file
|
@ -0,0 +1,9 @@
|
|||
.sect .text
|
||||
.define _gettimeofday
|
||||
_gettimeofday:
|
||||
addi r0, r0, 116 ! gettimeofday
|
||||
lwz r3, 0(sp) ! timeval pointer
|
||||
lwz r4, 4(sp) ! timezone pointer
|
||||
sc 0
|
||||
b .set_errno
|
||||
bclr 20, 0, 0
|
10
plat/osxppc/libsys/ioctl.s
Normal file
10
plat/osxppc/libsys/ioctl.s
Normal file
|
@ -0,0 +1,10 @@
|
|||
.sect .text
|
||||
.define _ioctl
|
||||
_ioctl:
|
||||
addi r0, r0, 54 ! ioctl
|
||||
lwz r3, 0(sp) ! fd
|
||||
lwz r4, 4(sp) ! command
|
||||
lwz r5, 8(sp) ! argument pointer
|
||||
sc 0
|
||||
b .set_errno
|
||||
bclr 20, 0, 0
|
9
plat/osxppc/libsys/kill.s
Normal file
9
plat/osxppc/libsys/kill.s
Normal file
|
@ -0,0 +1,9 @@
|
|||
.sect .text
|
||||
.define _kill
|
||||
_kill:
|
||||
addi r0, r0, 37 ! kill
|
||||
lwz r3, 0(sp) ! pid
|
||||
lwz r4, 4(sp) ! signal
|
||||
sc 0
|
||||
b .set_errno
|
||||
bclr 20, 0, 0
|
13
plat/osxppc/libsys/lseek.s
Normal file
13
plat/osxppc/libsys/lseek.s
Normal file
|
@ -0,0 +1,13 @@
|
|||
.sect .text
|
||||
.define _lseek
|
||||
_lseek:
|
||||
addi r0, r0, 199 ! lseek
|
||||
lwz r3, 0(sp) ! fd
|
||||
! ack passes 4-byte off_t, but system call takes 8-byte off_t
|
||||
addi r4, r0, 0 ! offset (high word)
|
||||
lwz r5, 4(sp) ! offset (low word)
|
||||
lwz r6, 8(sp) ! whence
|
||||
sc 0
|
||||
b .set_errno
|
||||
or r3, r4, r4 ! return offset (low word)
|
||||
bclr 20, 0, 0
|
15
plat/osxppc/libsys/mmap.s
Normal file
15
plat/osxppc/libsys/mmap.s
Normal file
|
@ -0,0 +1,15 @@
|
|||
.sect .text
|
||||
.define _mmap
|
||||
_mmap:
|
||||
addi r0, r0, 197 ! mmap
|
||||
lwz r3, 0(sp) ! address
|
||||
lwz r4, 4(sp) ! length
|
||||
lwz r5, 8(sp) ! protection
|
||||
lwz r6, 12(sp) ! flags
|
||||
lwz r7, 16(sp) ! fd
|
||||
! ack passes 4-byte off_t, but system call takes 8-byte off_t
|
||||
addi r8, r0, 0 ! offset (high word)
|
||||
lwz r9, 20(sp) ! offset (low word)
|
||||
sc 0
|
||||
b .set_errno
|
||||
bclr 20, 0, 0
|
10
plat/osxppc/libsys/mprotect.s
Normal file
10
plat/osxppc/libsys/mprotect.s
Normal file
|
@ -0,0 +1,10 @@
|
|||
.sect .text
|
||||
.define _mprotect
|
||||
_mprotect:
|
||||
addi r0, r0, 74 ! mprotect
|
||||
lwz r3, 0(sp) ! address
|
||||
lwz r4, 4(sp) ! length
|
||||
lwz r5, 8(sp) ! protection
|
||||
sc 0
|
||||
b .set_errno
|
||||
bclr 20, 0, 0
|
10
plat/osxppc/libsys/open.s
Normal file
10
plat/osxppc/libsys/open.s
Normal file
|
@ -0,0 +1,10 @@
|
|||
.sect .text
|
||||
.define _open
|
||||
_open:
|
||||
addi r0, r0, 5 ! open
|
||||
lwz r3, 0(sp) ! path
|
||||
lwz r4, 4(sp) ! flags
|
||||
lwz r5, 8(sp) ! mode
|
||||
sc 0
|
||||
b .set_errno
|
||||
bclr 20, 0, 0
|
10
plat/osxppc/libsys/read.s
Normal file
10
plat/osxppc/libsys/read.s
Normal file
|
@ -0,0 +1,10 @@
|
|||
.sect .text
|
||||
.define _read
|
||||
_read:
|
||||
addi r0, r0, 3 ! read
|
||||
lwz r3, 0(sp) ! fd
|
||||
lwz r4, 4(sp) ! buffer
|
||||
lwz r5, 8(sp) ! buffer size
|
||||
sc 0
|
||||
b .set_errno
|
||||
bclr 20, 0, 0
|
7
plat/osxppc/libsys/set_errno.s
Normal file
7
plat/osxppc/libsys/set_errno.s
Normal file
|
@ -0,0 +1,7 @@
|
|||
.sect .text
|
||||
.define .set_errno
|
||||
.set_errno:
|
||||
li32 r10, _errno
|
||||
stw r3, 0(r10) ! set errno
|
||||
addi r3, r0, -1 ! return -1
|
||||
bclr 20, 0, 0
|
59
plat/osxppc/libsys/sigaction.s
Normal file
59
plat/osxppc/libsys/sigaction.s
Normal file
|
@ -0,0 +1,59 @@
|
|||
#define IFTRUE 12
|
||||
#define ALWAYS 20
|
||||
#define EQ 2
|
||||
|
||||
! OS X, unlike FreeBSD, requires us to provide our own signal
|
||||
! trampoline. We must change the new action from a struct sigaction
|
||||
! to a bigger struct that includes the trampoline.
|
||||
|
||||
.sect .text
|
||||
.define _sigaction
|
||||
_sigaction:
|
||||
addi r0, r0, 46 ! sigaction
|
||||
lwz r3, 0(sp) ! sig
|
||||
lwz r4, 4(sp) ! ptr to new action
|
||||
lwz r5, 8(sp) ! ptr to old action
|
||||
or. r6, r4, r4
|
||||
bc IFTRUE, EQ, 1f ! skip if new action is NULL
|
||||
|
||||
! We may use the "red zone" from -224(sp) to 0(sp).
|
||||
addi r4, sp, -16 ! r4 = bigger struct
|
||||
lwz r7, 0(r6)
|
||||
stw r7, 0(r4) ! sa_handler
|
||||
li32 r7, trampoline
|
||||
stw r7, 4(r4) ! sa_tramp
|
||||
lwz r7, 4(r6)
|
||||
stw r7, 8(r4) ! sa_mask
|
||||
lwz r7, 8(r6)
|
||||
stw r7, 12(r4) ! sa_flags
|
||||
1:
|
||||
sc 0
|
||||
b .set_errno
|
||||
bclr 20, 0, 0
|
||||
|
||||
trampoline:
|
||||
! r3 = handler
|
||||
! r4 = info style
|
||||
! r5 = sig
|
||||
! r6 = info
|
||||
! r7 = context
|
||||
or r31, r4, r4 ! ack preserves r30, r31
|
||||
or r30, r7, r7
|
||||
|
||||
! Call handler(sig, info, context).
|
||||
mtspr ctr, r3
|
||||
stwu r7, -4(sp) ! ack expects arguments on stack
|
||||
stwu r6, -4(sp)
|
||||
stwu r5, -4(sp)
|
||||
bcctrl ALWAYS, 0, 0
|
||||
|
||||
! Return from trampoline.
|
||||
addi r0, r0, 184 ! sigreturn
|
||||
or r3, r30, r30 ! context
|
||||
or r4, r31, r31 ! info style
|
||||
sc 0
|
||||
ori r0, r0, 0 ! nop
|
||||
|
||||
! Only if sigreturn() fails:
|
||||
addi r0, r0, 1 ! exit
|
||||
sc 0
|
10
plat/osxppc/libsys/write.s
Normal file
10
plat/osxppc/libsys/write.s
Normal file
|
@ -0,0 +1,10 @@
|
|||
.sect .text
|
||||
.define _write
|
||||
_write:
|
||||
addi r0, r0, 4 ! write
|
||||
lwz r3, 0(sp) ! fd
|
||||
lwz r4, 4(sp) ! buffer
|
||||
lwz r5, 8(sp) ! buffer size
|
||||
sc 0
|
||||
b .set_errno
|
||||
bclr 20, 0, 0
|
Loading…
Reference in a new issue