Merge pull request #23 from kernigh/pr-osx
new platforms osx386 and osxppc
This commit is contained in:
		
						commit
						6a77309e96
					
				
					 75 changed files with 2416 additions and 76 deletions
				
			
		| 
						 | 
				
			
			@ -9,6 +9,8 @@ vars.plats = {
 | 
			
		|||
	"linux386",
 | 
			
		||||
	"linux68k",
 | 
			
		||||
	"linuxppc",
 | 
			
		||||
	"osx386",
 | 
			
		||||
	"osxppc",
 | 
			
		||||
	"qemuppc",
 | 
			
		||||
	"pc86",
 | 
			
		||||
	"rpi",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3,9 +3,15 @@ echo ""
 | 
			
		|||
 | 
			
		||||
succeeding="$(find "$@" -size 0)"
 | 
			
		||||
notsucceeding="$(find "$@" ! -size 0)"
 | 
			
		||||
skipped="$(grep -l @@SKIPPED $notsucceeding)"
 | 
			
		||||
timedout="$(grep -l @@TIMEDOUT $notsucceeding)"
 | 
			
		||||
failed="$(grep -l @@FAIL $notsucceeding)"
 | 
			
		||||
if [ "$notsucceeding" != "" ]; then
 | 
			
		||||
	skipped="$(grep -l @@SKIPPED $notsucceeding)"
 | 
			
		||||
	timedout="$(grep -l @@TIMEDOUT $notsucceeding)"
 | 
			
		||||
	failed="$(grep -l @@FAIL $notsucceeding)"
 | 
			
		||||
else
 | 
			
		||||
	skipped=
 | 
			
		||||
	timedout=
 | 
			
		||||
	failed=
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
for a in $failed $timedout; do
 | 
			
		||||
    echo "**** $a"
 | 
			
		||||
| 
						 | 
				
			
			@ -13,11 +19,11 @@ for a in $failed $timedout; do
 | 
			
		|||
    echo ""
 | 
			
		||||
done
 | 
			
		||||
 | 
			
		||||
echo "$(echo $succeeding | wc -w) tests passed"
 | 
			
		||||
echo "$(echo $notsucceeding | wc -w) tests failed to pass"
 | 
			
		||||
echo "$(echo $skipped | wc -w) were skipped (see build log for details)"
 | 
			
		||||
echo "$(echo $timedout | wc -w) timed out"
 | 
			
		||||
echo "$(echo $failed | wc -w) failed"
 | 
			
		||||
echo "$(echo "$succeeding" | wc -w) tests passed"
 | 
			
		||||
echo "$(echo "$notsucceeding" | wc -w) tests failed to pass"
 | 
			
		||||
echo "$(echo "$skipped" | wc -w) were skipped (see build log for details)"
 | 
			
		||||
echo "$(echo "$timedout" | wc -w) timed out"
 | 
			
		||||
echo "$(echo "$failed" | wc -w) failed"
 | 
			
		||||
echo ""
 | 
			
		||||
 | 
			
		||||
if [ "$failed" != "" -o "$timedout" != "" ]; then
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -10,8 +10,8 @@ for _, plat in ipairs(vars.plats) do
 | 
			
		|||
		hdrs = {}, -- must be empty
 | 
			
		||||
		deps = {
 | 
			
		||||
			"h+emheaders",
 | 
			
		||||
			"lang/cem/libcc.ansi/headers+headers",
 | 
			
		||||
			"plat/"..plat.."/include+headers",
 | 
			
		||||
			"lang/cem/libcc.ansi/headers+pkg",
 | 
			
		||||
			"plat/"..plat.."/include+pkg",
 | 
			
		||||
		},
 | 
			
		||||
        vars = { plat = plat }
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -51,8 +51,8 @@ for _, plat in ipairs(vars.plats) do
 | 
			
		|||
		},
 | 
			
		||||
		hdrs = {}, -- must be empty
 | 
			
		||||
		deps = {
 | 
			
		||||
			"lang/cem/libcc.ansi/headers+headers",
 | 
			
		||||
			"plat/"..plat.."/include+headers",
 | 
			
		||||
			"lang/cem/libcc.ansi/headers+pkg",
 | 
			
		||||
			"plat/"..plat.."/include+pkg",
 | 
			
		||||
			"./malloc/malloc.h",
 | 
			
		||||
			"./math/localmath.h",
 | 
			
		||||
			"./stdio/loc_incl.h",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -29,8 +29,8 @@ for _, plat in ipairs(vars.plats) do
 | 
			
		|||
        },
 | 
			
		||||
		hdrs = {}, -- must be empty
 | 
			
		||||
		deps = {
 | 
			
		||||
			"lang/cem/libcc.ansi/headers+headers",
 | 
			
		||||
			"plat/"..plat.."/include+headers",
 | 
			
		||||
			"lang/cem/libcc.ansi/headers+pkg",
 | 
			
		||||
			"plat/"..plat.."/include+pkg",
 | 
			
		||||
			"h+emheaders",
 | 
			
		||||
		},
 | 
			
		||||
        vars = { plat = plat }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -17,8 +17,8 @@ for _, plat in ipairs(vars.plats) do
 | 
			
		|||
        },
 | 
			
		||||
		hdrs = {}, -- must be empty
 | 
			
		||||
		deps = {
 | 
			
		||||
			"lang/cem/libcc.ansi/headers+headers",
 | 
			
		||||
			"plat/"..plat.."/include+headers",
 | 
			
		||||
			"lang/cem/libcc.ansi/headers+pkg",
 | 
			
		||||
			"plat/"..plat.."/include+pkg",
 | 
			
		||||
			"h+emheaders",
 | 
			
		||||
		},
 | 
			
		||||
        vars = { plat = plat }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,6 +1,7 @@
 | 
			
		|||
clibrary {
 | 
			
		||||
	name = "lib",
 | 
			
		||||
	srcs = { "./*.c" },
 | 
			
		||||
	hdrs = { "./object.h" },
 | 
			
		||||
	deps = {
 | 
			
		||||
		"modules+headers",
 | 
			
		||||
		"h+local",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -4,42 +4,46 @@
 | 
			
		|||
 * See the copyright notice in the ACK home directory, in the file "Copyright".
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <ansi.h>
 | 
			
		||||
 | 
			
		||||
#ifndef __OBJECT_INCLUDED__
 | 
			
		||||
#define __OBJECT_INCLUDED__
 | 
			
		||||
 | 
			
		||||
_PROTOTYPE(int wr_open, (char *f));
 | 
			
		||||
_PROTOTYPE(void wr_close, (void));
 | 
			
		||||
_PROTOTYPE(void wr_ohead, (struct outhead *h));
 | 
			
		||||
_PROTOTYPE(void wr_sect, (struct outsect *s, unsigned int c));
 | 
			
		||||
_PROTOTYPE(void wr_outsect, (int sectno));
 | 
			
		||||
_PROTOTYPE(void wr_emit, (char *b, long c));
 | 
			
		||||
_PROTOTYPE(void wr_putc, (int c));
 | 
			
		||||
_PROTOTYPE(void wr_relo, (struct outrelo *r, unsigned int c));
 | 
			
		||||
_PROTOTYPE(void wr_name, (struct outname *n, unsigned int c));
 | 
			
		||||
_PROTOTYPE(void wr_string, (char *s, long c));
 | 
			
		||||
_PROTOTYPE(void wr_arhdr, (int fd, struct ar_hdr *a));
 | 
			
		||||
_PROTOTYPE(void wr_ranlib, (int fd, struct ranlib *r, long cnt));
 | 
			
		||||
_PROTOTYPE(void wr_int2, (int fd, int i));
 | 
			
		||||
_PROTOTYPE(void wr_long, (int fd, long l));
 | 
			
		||||
_PROTOTYPE(void wr_bytes, (int fd, char *buf, long l));
 | 
			
		||||
_PROTOTYPE(int rd_open, (char *f));
 | 
			
		||||
_PROTOTYPE(int rd_fdopen, (int f));
 | 
			
		||||
_PROTOTYPE(void rd_close, (void));
 | 
			
		||||
_PROTOTYPE(void rd_ohead, (struct outhead *h));
 | 
			
		||||
_PROTOTYPE(void rd_sect, (struct outsect *s, unsigned int c));
 | 
			
		||||
_PROTOTYPE(void rd_outsect, (int sectno));
 | 
			
		||||
_PROTOTYPE(void rd_emit, (char *b, long c));
 | 
			
		||||
_PROTOTYPE(void rd_relo, (struct outrelo *r, unsigned int c));
 | 
			
		||||
_PROTOTYPE(void rd_rew_relo, (struct outhead *head));
 | 
			
		||||
_PROTOTYPE(void rd_name, (struct outname *n, unsigned int c));
 | 
			
		||||
_PROTOTYPE(void rd_string, (char *s, long c));
 | 
			
		||||
_PROTOTYPE(int rd_arhdr, (int fd, struct ar_hdr *a));
 | 
			
		||||
_PROTOTYPE(void rd_ranlib, (int fd, struct ranlib *r, long cnt));
 | 
			
		||||
_PROTOTYPE(int rd_int2, (int fd));
 | 
			
		||||
_PROTOTYPE(long rd_long, (int fd));
 | 
			
		||||
_PROTOTYPE(void rd_bytes, (int fd, char *buf, long l));
 | 
			
		||||
_PROTOTYPE(int rd_fd, (void));
 | 
			
		||||
struct ar_hdr;
 | 
			
		||||
struct outhead;
 | 
			
		||||
struct outrelo;
 | 
			
		||||
struct outsect;
 | 
			
		||||
struct ranlib;
 | 
			
		||||
 | 
			
		||||
int wr_open(char *f);
 | 
			
		||||
void wr_close(void);
 | 
			
		||||
void wr_ohead(struct outhead *h);
 | 
			
		||||
void wr_sect(struct outsect *s, unsigned int c);
 | 
			
		||||
void wr_outsect(int sectno);
 | 
			
		||||
void wr_emit(char *b, long c);
 | 
			
		||||
void wr_putc(int c);
 | 
			
		||||
void wr_relo(struct outrelo *r, unsigned int c);
 | 
			
		||||
void wr_name(struct outname *n, unsigned int c);
 | 
			
		||||
void wr_string(char *s, long c);
 | 
			
		||||
void wr_arhdr(int fd, struct ar_hdr *a);
 | 
			
		||||
void wr_ranlib(int fd, struct ranlib *r, long cnt);
 | 
			
		||||
void wr_int2(int fd, int i);
 | 
			
		||||
void wr_long(int fd, long l);
 | 
			
		||||
void wr_bytes(int fd, char *buf, long l);
 | 
			
		||||
int rd_open(char *f);
 | 
			
		||||
int rd_fdopen(int f);
 | 
			
		||||
void rd_close(void);
 | 
			
		||||
void rd_ohead(struct outhead *h);
 | 
			
		||||
void rd_sect(struct outsect *s, unsigned int c);
 | 
			
		||||
void rd_outsect(int sectno);
 | 
			
		||||
void rd_emit(char *b, long c);
 | 
			
		||||
void rd_relo(struct outrelo *r, unsigned int c);
 | 
			
		||||
void rd_rew_relo(struct outhead *head);
 | 
			
		||||
void rd_name(struct outname *n, unsigned int c);
 | 
			
		||||
void rd_string(char *s, long c);
 | 
			
		||||
int rd_arhdr(int fd, struct ar_hdr *a);
 | 
			
		||||
void rd_ranlib(int fd, struct ranlib *r, long cnt);
 | 
			
		||||
int rd_int2(int fd);
 | 
			
		||||
long rd_long(int fd);
 | 
			
		||||
void rd_bytes(int fd, char *buf, long l);
 | 
			
		||||
int rd_fd(void);
 | 
			
		||||
 | 
			
		||||
#endif /* __OBJECT_INCLUDED__ */
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										15
									
								
								plat/osx/cvmach/build.lua
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								plat/osx/cvmach/build.lua
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,15 @@
 | 
			
		|||
cprogram {
 | 
			
		||||
	name = "cvmach",
 | 
			
		||||
	srcs = { "./cvmach.c" },
 | 
			
		||||
	deps = {
 | 
			
		||||
		"h+emheaders",
 | 
			
		||||
		"modules/src/object+lib",
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
installable {
 | 
			
		||||
	name = "pkg",
 | 
			
		||||
	map = {
 | 
			
		||||
		["$(PLATDEP)/cvmach"] = "+cvmach",
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										96
									
								
								plat/osx/cvmach/cvmach.6
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										96
									
								
								plat/osx/cvmach/cvmach.6
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,96 @@
 | 
			
		|||
.Dd December 2, 2016
 | 
			
		||||
.Dt CVMACH 6
 | 
			
		||||
.Os
 | 
			
		||||
.Sh NAME
 | 
			
		||||
.Nm cvmach
 | 
			
		||||
.Nd convert an executable file from ack.out to Mach-o
 | 
			
		||||
.Sh SYNOPSIS
 | 
			
		||||
.Cm ~em/lib/ack/cvmach
 | 
			
		||||
.Fl m Ns Ar number
 | 
			
		||||
.Oo
 | 
			
		||||
.Ar infile
 | 
			
		||||
.Op Ar outfile
 | 
			
		||||
.Oc
 | 
			
		||||
.Sh DESCRIPTION
 | 
			
		||||
The
 | 
			
		||||
.Nm
 | 
			
		||||
utility converts an executable file from
 | 
			
		||||
.Xr ack.out 5
 | 
			
		||||
format to Mach-object format.
 | 
			
		||||
It can produce Mach-o executables for Mac OS X.
 | 
			
		||||
If the
 | 
			
		||||
.Ar infile
 | 
			
		||||
or
 | 
			
		||||
.Ar outfile
 | 
			
		||||
are not given, then
 | 
			
		||||
.Nm
 | 
			
		||||
reads from standard input or writes to standard output.
 | 
			
		||||
.Pp
 | 
			
		||||
The option is required:
 | 
			
		||||
.Bl -tag -width Ds
 | 
			
		||||
.It Fl m Ns Ar number
 | 
			
		||||
Sets the CPU type in the Mach header.
 | 
			
		||||
This must be
 | 
			
		||||
.Fl m Ns Cm 7
 | 
			
		||||
for Intel i386 or
 | 
			
		||||
.Fl m Ns Cm 18
 | 
			
		||||
for PowerPC.
 | 
			
		||||
.Nm
 | 
			
		||||
doesn't know how to make Mach-o files for other CPU types.
 | 
			
		||||
.El
 | 
			
		||||
.Pp
 | 
			
		||||
The input file must have four segments:
 | 
			
		||||
TEXT, ROM, DATA and BSS, in that order.
 | 
			
		||||
.Nm
 | 
			
		||||
converts them into four Mach sections in two Mach segments.
 | 
			
		||||
TEXT and ROM go in the RX segment (Read and eXecute).
 | 
			
		||||
DATA and BSS go in the RW segment (Read and Write).
 | 
			
		||||
.Nm
 | 
			
		||||
sets the page protection so programs can't write the RX segment,
 | 
			
		||||
and can't execute the RW segment.
 | 
			
		||||
The program will begin execution at the beginning of TEXT.
 | 
			
		||||
.Pp
 | 
			
		||||
.Nm
 | 
			
		||||
also converts the symbol table.
 | 
			
		||||
.Sh DIAGNOSTICS
 | 
			
		||||
.Bl -diag
 | 
			
		||||
.It text segment must have base 0x%lx, not 0x%lx
 | 
			
		||||
TEXT must begin immediately after the Mach header and load commands.
 | 
			
		||||
The message gives the correct
 | 
			
		||||
.Ar base .
 | 
			
		||||
Relinking the program with
 | 
			
		||||
.Cm em_led Fl b Ns 0: Ns Ar base
 | 
			
		||||
would fix it.
 | 
			
		||||
.It the %s segment must follow the %s segment.
 | 
			
		||||
TEXT and ROM must be continuous in memory, because
 | 
			
		||||
.Nm
 | 
			
		||||
maps them in the same Mach segment.
 | 
			
		||||
Likewise, DATA and BSS must be contiguous.
 | 
			
		||||
There may be a small gap between TEXT and ROM, or between DATA and
 | 
			
		||||
BSS, only if the gap is necessary to align ROM or BSS.
 | 
			
		||||
.It the data and rom segments are too close.
 | 
			
		||||
DATA and ROM must not share a page in memory, because
 | 
			
		||||
.Nm
 | 
			
		||||
maps them in different Mach segments, with different page protections.
 | 
			
		||||
The page size for i386 and PowerPC is 4096 or 0x1000 bytes.
 | 
			
		||||
For example, if ROM ends at address 0x2bed,
 | 
			
		||||
then DATA may not begin at 0x2bf0, because
 | 
			
		||||
.Nm
 | 
			
		||||
can't put the page from 0x2000 to 0x2fff in both Mach segments.
 | 
			
		||||
Relinking the program with
 | 
			
		||||
.Cm em_led Fl a Ns 2:4096
 | 
			
		||||
would fix it.
 | 
			
		||||
.It the bss space contains initialized data.
 | 
			
		||||
BSS must not contain initialized data, because
 | 
			
		||||
.Nm
 | 
			
		||||
converts it to a zero-fill section.
 | 
			
		||||
.El
 | 
			
		||||
.Sh CAVEATS
 | 
			
		||||
Mac OS X 10.4 for PowerPC does not protect pages against execution.
 | 
			
		||||
All mapped pages are executable, whether or not the execute bit is set
 | 
			
		||||
in the page protection.
 | 
			
		||||
.Nm
 | 
			
		||||
can't prevent the execution of the RW segment.
 | 
			
		||||
.Sh BUGS
 | 
			
		||||
The symbol conversion preserves the name and value of each symbol, but
 | 
			
		||||
may lose other information, such as the symbol type.
 | 
			
		||||
							
								
								
									
										665
									
								
								plat/osx/cvmach/cvmach.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										665
									
								
								plat/osx/cvmach/cvmach.c
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,665 @@
 | 
			
		|||
/*
 | 
			
		||||
 * (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
 | 
			
		||||
 * libobject is pinched from the Xenix i386 cv (mach/i386/cv/cv.c).
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <fcntl.h>
 | 
			
		||||
#include <stdarg.h>
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
 | 
			
		||||
#include <out.h>
 | 
			
		||||
#include <object.h>
 | 
			
		||||
 | 
			
		||||
/* Header and section table of ack.out */
 | 
			
		||||
struct outhead	outhead;
 | 
			
		||||
struct outsect	outsect[S_MAX];
 | 
			
		||||
uint32_t ack_off_char;		/* Offset of string table in ack.out */
 | 
			
		||||
 | 
			
		||||
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_SYMTAB			2
 | 
			
		||||
#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_SECTION_HEADER		68
 | 
			
		||||
#define SZ_SYMTAB_COMMAND		24
 | 
			
		||||
#define SZ_THREAD_COMMAND_BF_STATE	16
 | 
			
		||||
#define SZ_NLIST			12
 | 
			
		||||
 | 
			
		||||
/* 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))
 | 
			
		||||
/* u rounded up to whole pages */
 | 
			
		||||
#define pg_round(u) pg_trunc((u) + (CV_PGSZ - 1))
 | 
			
		||||
 | 
			
		||||
const char zero_pg[CV_PGSZ] = { 0 };
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * machseg[0]: __PAGEZERO with address 0, size CV_PGSZ
 | 
			
		||||
 * machseg[1]: __TEXT for ack TEXT, ROM
 | 
			
		||||
 * machseg[2]: __DATA for ack DATA, BSS
 | 
			
		||||
 */
 | 
			
		||||
struct {
 | 
			
		||||
	const char	*ms_name;
 | 
			
		||||
	uint32_t	 ms_vmaddr;
 | 
			
		||||
	uint32_t	 ms_vmsize;
 | 
			
		||||
	uint32_t	 ms_fileoff;
 | 
			
		||||
	uint32_t	 ms_filesize;
 | 
			
		||||
	uint32_t	 ms_prot;
 | 
			
		||||
	uint32_t	 ms_nsects;
 | 
			
		||||
} machseg[3] = {
 | 
			
		||||
	"__PAGEZERO", 0, CV_PGSZ, 0, 0, VM_PROT_NONE, 0,
 | 
			
		||||
	"__TEXT", 0, 0, 0, 0, VM_PROT_READ | VM_PROT_EXECUTE, 2,
 | 
			
		||||
	"__DATA", 0, 0, 0, 0, VM_PROT_READ | VM_PROT_WRITE, 2,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
usage(void)
 | 
			
		||||
{
 | 
			
		||||
	fprintf(stderr, "Usage: %s -m<num> <inputfile> <outputfile>\n",
 | 
			
		||||
	    program);
 | 
			
		||||
	exit(1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Produce an error message and exit. */
 | 
			
		||||
static 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");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Returns n such that 2**n == a. */
 | 
			
		||||
static uint32_t
 | 
			
		||||
log2u(uint32_t a)
 | 
			
		||||
{
 | 
			
		||||
	uint32_t n = 0;
 | 
			
		||||
	while (a) {
 | 
			
		||||
		a >>= 1;
 | 
			
		||||
		n++;
 | 
			
		||||
	}
 | 
			
		||||
	return n - 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Writes a byte. */
 | 
			
		||||
static void
 | 
			
		||||
emit8(uint8_t value)
 | 
			
		||||
{
 | 
			
		||||
	writef(&value, 1, 1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Writes out a 16-bit value in the appropriate endianness. */
 | 
			
		||||
static void
 | 
			
		||||
emit16(uint16_t value)
 | 
			
		||||
{
 | 
			
		||||
	unsigned char buffer[2];
 | 
			
		||||
 | 
			
		||||
	if (bigendian)
 | 
			
		||||
	{
 | 
			
		||||
		buffer[0] = (value >> 8) & 0xFF;
 | 
			
		||||
		buffer[1] = (value >> 0) & 0xFF;
 | 
			
		||||
	}
 | 
			
		||||
	else
 | 
			
		||||
	{
 | 
			
		||||
		buffer[1] = (value >> 8) & 0xFF;
 | 
			
		||||
		buffer[0] = (value >> 0) & 0xFF;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	writef(buffer, 1, sizeof(buffer));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Writes out a 32-bit value in the appropriate endianness. */
 | 
			
		||||
static 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. */
 | 
			
		||||
static 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;
 | 
			
		||||
	while (n > 0)
 | 
			
		||||
	{
 | 
			
		||||
		blocksize = (n > sizeof(zero_pg)) ? sizeof(zero_pg) : n;
 | 
			
		||||
		writef(zero_pg, 1, blocksize);
 | 
			
		||||
		n -= blocksize;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
emit_lc_segment(int i)
 | 
			
		||||
{
 | 
			
		||||
	uint32_t sz;
 | 
			
		||||
	int flags, maxprot;
 | 
			
		||||
	char namebuf[16];
 | 
			
		||||
 | 
			
		||||
	if (i == 0) {
 | 
			
		||||
		/* special values for __PAGEZERO */
 | 
			
		||||
		maxprot = VM_PROT_NONE;
 | 
			
		||||
		flags = 4; /* SG_NORELOC */
 | 
			
		||||
	} else {
 | 
			
		||||
		maxprot = VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE;
 | 
			
		||||
		flags = 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * The size of this command includes the size of its section
 | 
			
		||||
	 * headers, see emit_section_header().
 | 
			
		||||
	 */
 | 
			
		||||
	sz = SZ_SEGMENT_COMMAND + machseg[i].ms_nsects * SZ_SECTION_HEADER;
 | 
			
		||||
 | 
			
		||||
	/* Use strncpy() to pad namebuf with '\0' bytes. */
 | 
			
		||||
	strncpy(namebuf, machseg[i].ms_name, sizeof(namebuf));
 | 
			
		||||
 | 
			
		||||
	emit32(LC_SEGMENT);		/* command */
 | 
			
		||||
	emit32(sz);			/* size of command */
 | 
			
		||||
	writef(namebuf, 1, sizeof(namebuf));
 | 
			
		||||
	emit32(machseg[i].ms_vmaddr);	/* vm address */
 | 
			
		||||
	emit32(machseg[i].ms_vmsize);	/* vm size */
 | 
			
		||||
	emit32(machseg[i].ms_fileoff);	/* file offset */
 | 
			
		||||
	emit32(machseg[i].ms_filesize);	/* file size */
 | 
			
		||||
	emit32(maxprot);		/* max protection */
 | 
			
		||||
	emit32(machseg[i].ms_prot);	/* initial protection */
 | 
			
		||||
	emit32(machseg[i].ms_nsects);	/* number of Mach sections */
 | 
			
		||||
	emit32(flags);			/* flags */
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
emit_section_header(int ms, const char *name, int os)
 | 
			
		||||
{
 | 
			
		||||
	uint32_t fileoff, flags;
 | 
			
		||||
	char namebuf[16];
 | 
			
		||||
 | 
			
		||||
	switch (os) {
 | 
			
		||||
	case TEXT:
 | 
			
		||||
		/* S_ATTR_PURE_INSTRUCTIONS | S_ATTR_SOME_INSTRUCTIONS */
 | 
			
		||||
		flags = 0x80000400;
 | 
			
		||||
		break;
 | 
			
		||||
	case BSS:
 | 
			
		||||
		flags = 0x1; /* S_ZEROFILL */
 | 
			
		||||
		break;
 | 
			
		||||
	default:
 | 
			
		||||
		flags = 0x0; /* S_REGULAR */
 | 
			
		||||
		break;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (os == BSS)
 | 
			
		||||
		fileoff = 0;
 | 
			
		||||
	else
 | 
			
		||||
		fileoff = machseg[ms].ms_fileoff +
 | 
			
		||||
		    (outsect[os].os_base - machseg[ms].ms_vmaddr);
 | 
			
		||||
 | 
			
		||||
	/* name of Mach section */
 | 
			
		||||
	strncpy(namebuf, name, sizeof(namebuf));
 | 
			
		||||
	writef(namebuf, 1, sizeof(namebuf));
 | 
			
		||||
	/* name of Mach segment */
 | 
			
		||||
	strncpy(namebuf, machseg[ms].ms_name, sizeof(namebuf));
 | 
			
		||||
	writef(namebuf, 1, sizeof(namebuf));
 | 
			
		||||
	emit32(outsect[os].os_base);	/* vm address */
 | 
			
		||||
	emit32(outsect[os].os_size);	/* vm size */
 | 
			
		||||
	emit32(fileoff);		/* file offset */
 | 
			
		||||
	emit32(log2u(outsect[os].os_lign)); /* alignment */
 | 
			
		||||
	emit32(0);			/* offset of relocations */
 | 
			
		||||
	emit32(0);			/* number of relocations */
 | 
			
		||||
	emit32(flags);			/* flags */
 | 
			
		||||
	emit32(0);			/* reserved */
 | 
			
		||||
	emit32(0);			/* reserved */
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
emit_lc_symtab(void)
 | 
			
		||||
{
 | 
			
		||||
	uint32_t off1, off2;
 | 
			
		||||
 | 
			
		||||
	/* Symbol table will be at next page after machseg[2]. */
 | 
			
		||||
	off1 = pg_round(machseg[2].ms_fileoff + machseg[2].ms_filesize);
 | 
			
		||||
	/* String table will be after symbol table. */
 | 
			
		||||
	off2 = off1 + 12 * outhead.oh_nname;
 | 
			
		||||
 | 
			
		||||
	emit32(LC_SYMTAB);		/* command */
 | 
			
		||||
	emit32(SZ_SYMTAB_COMMAND);	/* size of command */
 | 
			
		||||
	emit32(off1);			/* offset of symbol table */
 | 
			
		||||
	emit32(outhead.oh_nname);	/* number of symbols */
 | 
			
		||||
	emit32(off2);			/* offset of string table */
 | 
			
		||||
	emit32(1 + outhead.oh_nchar);	/* size of string table */
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static 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);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
emit_symbol(struct outname *np)
 | 
			
		||||
{
 | 
			
		||||
	uint32_t soff;
 | 
			
		||||
	uint8_t type;
 | 
			
		||||
	uint8_t sect;
 | 
			
		||||
	uint16_t desc;
 | 
			
		||||
 | 
			
		||||
	if (np->on_type & S_STB) {
 | 
			
		||||
		/* stab for debugger */
 | 
			
		||||
		type = np->on_type >> 8;
 | 
			
		||||
		desc = np->on_desc;
 | 
			
		||||
	} else {
 | 
			
		||||
		desc = 0;
 | 
			
		||||
 | 
			
		||||
		switch (np->on_type & S_TYP) {
 | 
			
		||||
		case S_UND:
 | 
			
		||||
			type = 0x0; /* N_UNDF */
 | 
			
		||||
			break;
 | 
			
		||||
		case S_ABS:
 | 
			
		||||
			type = 0x2; /* N_ABS */
 | 
			
		||||
			break;
 | 
			
		||||
		default:
 | 
			
		||||
			type = 0xe; /* N_SECT */
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (np->on_type & S_EXT)
 | 
			
		||||
			type |= 0x1; /* N_EXT */
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	switch (np->on_type & S_TYP) {
 | 
			
		||||
	case S_MIN + TEXT:
 | 
			
		||||
		sect = 1;
 | 
			
		||||
		break;
 | 
			
		||||
	case S_MIN + ROM:
 | 
			
		||||
		sect = 2;
 | 
			
		||||
		break;
 | 
			
		||||
	case S_MIN + DATA:
 | 
			
		||||
		sect = 3;
 | 
			
		||||
		break;
 | 
			
		||||
	case S_MIN + BSS:
 | 
			
		||||
	case S_MIN + NUM_SEGMENTS:
 | 
			
		||||
		sect = 4;
 | 
			
		||||
		break;
 | 
			
		||||
	default:
 | 
			
		||||
		sect = 0; /* NO_SECT */
 | 
			
		||||
		break;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * To find the symbol's name, ack.out uses an offset from the
 | 
			
		||||
	 * beginning of the file, but Mach-o uses an offset into the
 | 
			
		||||
	 * string table.  Both formats use offset 0 for a symbol with
 | 
			
		||||
	 * no name.  We will prepend a '\0' at offset 0, so every
 | 
			
		||||
	 * named symbol needs + 1.
 | 
			
		||||
	 */
 | 
			
		||||
	if (np->on_foff)
 | 
			
		||||
		soff = np->on_foff - ack_off_char + 1;
 | 
			
		||||
	else
 | 
			
		||||
		soff = 0;
 | 
			
		||||
 | 
			
		||||
	emit32(soff);
 | 
			
		||||
	emit8(type);
 | 
			
		||||
	emit8(sect);
 | 
			
		||||
	emit16(desc);
 | 
			
		||||
	emit32(np->on_valu);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
emit_symtab(void)
 | 
			
		||||
{
 | 
			
		||||
	struct outname *names, *np;
 | 
			
		||||
	int i;
 | 
			
		||||
	char *chars;
 | 
			
		||||
 | 
			
		||||
	/* Using calloc(a, b) to check if a * b would overflow. */
 | 
			
		||||
	names = calloc(outhead.oh_nname, sizeof(struct outname));
 | 
			
		||||
	if (!names)
 | 
			
		||||
		fatal("out of memory");
 | 
			
		||||
	chars = malloc(outhead.oh_nchar);
 | 
			
		||||
	if (!names || !chars)
 | 
			
		||||
		fatal("out of memory");
 | 
			
		||||
	rd_name(names, outhead.oh_nname);
 | 
			
		||||
	rd_string(chars, outhead.oh_nchar);
 | 
			
		||||
 | 
			
		||||
	ack_off_char = OFF_CHAR(outhead);
 | 
			
		||||
 | 
			
		||||
	/* Emit each symbol entry. */
 | 
			
		||||
	for (i = 0, np = names; i < outhead.oh_nname; i++, np++)
 | 
			
		||||
		emit_symbol(np);
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * Emit the string table.  The first character of a Mach-o
 | 
			
		||||
	 * string table must be '\0', so we prepend a '\0'.
 | 
			
		||||
	 */
 | 
			
		||||
	emit8(0);
 | 
			
		||||
	writef(chars, 1, outhead.oh_nchar);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
int
 | 
			
		||||
main(int argc, char *argv[])
 | 
			
		||||
{
 | 
			
		||||
	uint32_t end, pad[3], sz, sz_load_cmds;
 | 
			
		||||
	int cpu_subtype, fd, 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. */
 | 
			
		||||
		/* Use mode 0777 to allow executing the output file. */
 | 
			
		||||
		fd = open(argv[2], O_CREAT | O_TRUNC | O_WRONLY, 0777);
 | 
			
		||||
		if (fd < 0)
 | 
			
		||||
			fatal("unable to open output file.");
 | 
			
		||||
		output = fdopen(fd, "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);
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * machseg[1] will start at a page boundary and include the
 | 
			
		||||
	 * Mach header and load commands before ack TEXT and ROM.
 | 
			
		||||
	 *
 | 
			
		||||
	 * Find our entry point (immediately after the load commands)
 | 
			
		||||
	 * and check that TEXT begins there.
 | 
			
		||||
	 */
 | 
			
		||||
	machseg[1].ms_vmaddr = pg_trunc(outsect[TEXT].os_base);
 | 
			
		||||
	sz_load_cmds = 3 * SZ_SEGMENT_COMMAND + 4 * SZ_SECTION_HEADER +
 | 
			
		||||
	    SZ_SYMTAB_COMMAND + sz_thread_command;
 | 
			
		||||
	entry = machseg[1].ms_vmaddr + SZ_MACH_HEADER + sz_load_cmds;
 | 
			
		||||
	if (entry != outsect[TEXT].os_base) {
 | 
			
		||||
		fatal("text segment must have base 0x%lx, not 0x%lx"
 | 
			
		||||
		    "\n\t(suggest em_led -b0:0x%lx)",
 | 
			
		||||
		    (unsigned long)entry,
 | 
			
		||||
		    (unsigned long)outsect[TEXT].os_base,
 | 
			
		||||
		    (unsigned long)entry);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Pad for alignment between TEXT and ROM. */
 | 
			
		||||
	sz = outsect[ROM].os_base - outsect[TEXT].os_base;
 | 
			
		||||
	pad[0] = sz - outsect[TEXT].os_size;
 | 
			
		||||
	if (sz < outsect[TEXT].os_size || pad[0] >= outsect[ROM].os_lign)
 | 
			
		||||
		fatal("the rom segment must follow the text segment.");
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * Pad between ROM and DATA such that we can map machseg[2] at
 | 
			
		||||
	 * a page boundary with DATA at its correct base address.
 | 
			
		||||
	 *
 | 
			
		||||
	 * For example, if ROM ends at 0x2bed and DATA begins at
 | 
			
		||||
	 * 0x3000, then we pad to the page boundary.  If ROM ends at
 | 
			
		||||
	 * 0x2bed and DATA begins at 0x3bf0, then pad = 3 and we map
 | 
			
		||||
	 * the page twice, at both 0x2000 and 0x3000.
 | 
			
		||||
	 */
 | 
			
		||||
	end = outsect[ROM].os_base + outsect[ROM].os_size;
 | 
			
		||||
	pad[1] = pg_mod(outsect[DATA].os_base - end);
 | 
			
		||||
 | 
			
		||||
	sz = end - machseg[1].ms_vmaddr;
 | 
			
		||||
	machseg[1].ms_vmsize = machseg[1].ms_filesize = sz;
 | 
			
		||||
	machseg[2].ms_vmaddr = pg_trunc(outsect[DATA].os_base);
 | 
			
		||||
	machseg[2].ms_fileoff = pg_trunc(sz + pad[1]);
 | 
			
		||||
	if (machseg[2].ms_vmaddr < end &&
 | 
			
		||||
	    machseg[2].ms_vmaddr >= machseg[1].ms_vmaddr)
 | 
			
		||||
		fatal("the data and rom segments are too close."
 | 
			
		||||
		    "\n\t(suggest em_led -a2:%d)", (int)CV_PGSZ);
 | 
			
		||||
 | 
			
		||||
	if (outsect[BSS].os_flen != 0)
 | 
			
		||||
		fatal("the bss space contains initialized data.");
 | 
			
		||||
	sz = outsect[BSS].os_base - outsect[DATA].os_base;
 | 
			
		||||
	if (sz < outsect[DATA].os_size ||
 | 
			
		||||
	    sz - outsect[DATA].os_size >= outsect[BSS].os_lign)
 | 
			
		||||
		fatal("the bss segment must follow the data segment.");
 | 
			
		||||
 | 
			
		||||
	end = outsect[DATA].os_base + outsect[DATA].os_size;
 | 
			
		||||
	machseg[2].ms_filesize = end - machseg[2].ms_vmaddr;
 | 
			
		||||
	end = outsect[BSS].os_base + outsect[BSS].os_size;
 | 
			
		||||
	machseg[2].ms_vmsize = end - machseg[2].ms_vmaddr;
 | 
			
		||||
 | 
			
		||||
	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");
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * Pad to page boundary between BSS and symbol table.
 | 
			
		||||
	 *
 | 
			
		||||
	 * Also, some versions of Mac OS X refuse to load any
 | 
			
		||||
	 * executable smaller than 4096 bytes (1 page).
 | 
			
		||||
	 */
 | 
			
		||||
	pad[2] = pg_mod(-(uint32_t)machseg[2].ms_filesize);
 | 
			
		||||
 | 
			
		||||
	/* Emit the Mach header. */
 | 
			
		||||
	emit32(MH_MAGIC);	/* magic */
 | 
			
		||||
	emit32(cpu_type);	/* cpu type */
 | 
			
		||||
	emit32(cpu_subtype);	/* cpu subtype */
 | 
			
		||||
	emit32(MH_EXECUTE);	/* file type */
 | 
			
		||||
	emit32(5);		/* number of load commands */
 | 
			
		||||
	emit32(sz_load_cmds);	/* size of load commands */
 | 
			
		||||
	emit32(0);		/* flags */
 | 
			
		||||
 | 
			
		||||
	emit_lc_segment(0);
 | 
			
		||||
	emit_lc_segment(1);
 | 
			
		||||
	emit_section_header(1, "__text", TEXT);
 | 
			
		||||
	emit_section_header(1, "__rom", ROM);
 | 
			
		||||
	emit_lc_segment(2);
 | 
			
		||||
	emit_section_header(2, "__data", DATA);
 | 
			
		||||
	emit_section_header(2, "__bss", BSS);
 | 
			
		||||
	emit_lc_symtab();
 | 
			
		||||
	emit_lc_unixthread();
 | 
			
		||||
 | 
			
		||||
	/* Emit non-empty sections. */
 | 
			
		||||
	emit_section(TEXT);
 | 
			
		||||
	writef(zero_pg, 1, pad[0]);
 | 
			
		||||
	emit_section(ROM);
 | 
			
		||||
	writef(zero_pg, 1, pad[1]);
 | 
			
		||||
	emit_section(DATA);
 | 
			
		||||
 | 
			
		||||
	writef(zero_pg, 1, pad[2]);
 | 
			
		||||
	emit_symtab();
 | 
			
		||||
 | 
			
		||||
	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
 | 
			
		||||
							
								
								
									
										26
									
								
								plat/osx/include/build.lua
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								plat/osx/include/build.lua
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,26 @@
 | 
			
		|||
include("plat/build.lua")
 | 
			
		||||
 | 
			
		||||
headermap = {}
 | 
			
		||||
packagemap = {}
 | 
			
		||||
 | 
			
		||||
local function addheader(h)
 | 
			
		||||
	headermap[h] = "plat/osx/include/"..h
 | 
			
		||||
	packagemap["$(PLATIND)/osx/include/"..h] = "plat/osx/include/"..h
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
addheader("ack/config.h")
 | 
			
		||||
addheader("sys/dirent.h")
 | 
			
		||||
addheader("sys/mman.h")
 | 
			
		||||
addheader("sys/stat.h")
 | 
			
		||||
addheader("sys/types.h")
 | 
			
		||||
addheader("unistd.h")
 | 
			
		||||
 | 
			
		||||
acklibrary {
 | 
			
		||||
	name = "headers",
 | 
			
		||||
	hdrs = headermap
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
installable {
 | 
			
		||||
	name = "pkg",
 | 
			
		||||
	map = packagemap
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										17
									
								
								plat/osx/include/sys/dirent.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								plat/osx/include/sys/dirent.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,17 @@
 | 
			
		|||
#ifndef _SYS_DIRENT_H
 | 
			
		||||
#define _SYS_DIRENT_H
 | 
			
		||||
 | 
			
		||||
#include <sys/types.h>
 | 
			
		||||
 | 
			
		||||
struct dirent {
 | 
			
		||||
	ino_t		d_ino;
 | 
			
		||||
	unsigned short	d_reclen;
 | 
			
		||||
	unsigned char	d_type;
 | 
			
		||||
	unsigned char	d_namlen;
 | 
			
		||||
#define MAXNAMLEN 255
 | 
			
		||||
	char		d_name[MAXNAMLEN + 1];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
int getdirentries(int, char *, int, long *);
 | 
			
		||||
 | 
			
		||||
#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
 | 
			
		||||
							
								
								
									
										49
									
								
								plat/osx/include/sys/stat.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								plat/osx/include/sys/stat.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,49 @@
 | 
			
		|||
#ifndef _SYS_STAT_H
 | 
			
		||||
#define _SYS_STAT_H
 | 
			
		||||
 | 
			
		||||
#include <sys/types.h>
 | 
			
		||||
#include <sys/time.h> /* for timespec */
 | 
			
		||||
 | 
			
		||||
struct stat {
 | 
			
		||||
	dev_t		st_dev;
 | 
			
		||||
	ino_t		st_ino;
 | 
			
		||||
	mode_t		st_mode;
 | 
			
		||||
	nlink_t		st_nlink;
 | 
			
		||||
	uid_t		st_uid;
 | 
			
		||||
	gid_t		st_gid;
 | 
			
		||||
	dev_t		st_rdev;
 | 
			
		||||
	struct timespec	st_atim;
 | 
			
		||||
	struct timespec	st_mtim;
 | 
			
		||||
	struct timespec	st_ctim;
 | 
			
		||||
#define st_atime st_atim.tv_sec
 | 
			
		||||
#define st_mtime st_mtim.tv_sec
 | 
			
		||||
#define st_ctime st_ctim.tv_sec
 | 
			
		||||
	/*
 | 
			
		||||
	 * XXX - We don't have 64-bit integers, so we only expose the
 | 
			
		||||
	 * lower 32 bits of 64-bit fields.  We insert dummy fields for
 | 
			
		||||
	 * the higher 32 bits.
 | 
			
		||||
	 */
 | 
			
		||||
#if defined(__i386)
 | 
			
		||||
	off_t		st_size;
 | 
			
		||||
	off_t		_st_size_hi;
 | 
			
		||||
	blkcnt_t	st_blocks;
 | 
			
		||||
	blkcnt_t	_st_blkcnt_hi;
 | 
			
		||||
#elif defined(__powerpc)
 | 
			
		||||
	off_t		_st_size_hi;
 | 
			
		||||
	off_t		st_size;
 | 
			
		||||
	blkcnt_t	_st_blkcnt_hi;
 | 
			
		||||
	blkcnt_t	st_blkcnt;
 | 
			
		||||
#else
 | 
			
		||||
#error unknown arch
 | 
			
		||||
#endif
 | 
			
		||||
	blksize_t	st_blksize;
 | 
			
		||||
	unsigned int	st_flags;
 | 
			
		||||
	unsigned int	st_gen;
 | 
			
		||||
	unsigned int	_st_spare[5];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
int fstat(int, struct stat *);
 | 
			
		||||
int lstat(const char *, struct stat *);
 | 
			
		||||
int stat(const char *, struct stat *);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										17
									
								
								plat/osx/include/sys/types.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								plat/osx/include/sys/types.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,17 @@
 | 
			
		|||
#ifndef _SYS_TYPES_H
 | 
			
		||||
#define _SYS_TYPES_H
 | 
			
		||||
 | 
			
		||||
#include <stddef.h> /* for off_t, ptrdiff_t, size_t */
 | 
			
		||||
 | 
			
		||||
typedef int			blkcnt_t; /* XXX should have 64 bits */
 | 
			
		||||
typedef int			blksize_t;
 | 
			
		||||
typedef int			dev_t;
 | 
			
		||||
typedef unsigned int		gid_t;
 | 
			
		||||
typedef unsigned int		ino_t;
 | 
			
		||||
typedef unsigned short		mode_t;
 | 
			
		||||
typedef unsigned short		nlink_t;
 | 
			
		||||
typedef int			pid_t;
 | 
			
		||||
typedef ptrdiff_t		ssize_t;
 | 
			
		||||
typedef unsigned int		uid_t;
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										137
									
								
								plat/osx/include/unistd.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										137
									
								
								plat/osx/include/unistd.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,137 @@
 | 
			
		|||
#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 timespec {
 | 
			
		||||
	_libsys_time_t tv_sec;
 | 
			
		||||
	long tv_nsec;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
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
 | 
			
		||||
 | 
			
		||||
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);
 | 
			
		||||
 | 
			
		||||
int raise(int); /* in libc */
 | 
			
		||||
 | 
			
		||||
/* 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
 | 
			
		||||
							
								
								
									
										86
									
								
								plat/osx/libsys/brk.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										86
									
								
								plat/osx/libsys/brk.c
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,86 @@
 | 
			
		|||
/*
 | 
			
		||||
 * 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;
 | 
			
		||||
 | 
			
		||||
	brk_init();
 | 
			
		||||
	base = cbreak;
 | 
			
		||||
	if (brk1(base + incr) < 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)
 | 
			
		||||
{
 | 
			
		||||
	return 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;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										25
									
								
								plat/osx386/README
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								plat/osx386/README
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,25 @@
 | 
			
		|||
The osx386 platform
 | 
			
		||||
===================
 | 
			
		||||
 | 
			
		||||
    ack -mosx386 ...
 | 
			
		||||
 | 
			
		||||
This platform produces Mach-o executables for Intel Mac OS X.  These
 | 
			
		||||
are 32-bit executables using our i386 code generator.
 | 
			
		||||
 | 
			
		||||
See ../osxppc/README, because our osx386 platform has many of the same
 | 
			
		||||
limitations and bugs as our osxppc platform.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
Bugs
 | 
			
		||||
----
 | 
			
		||||
 | 
			
		||||
Some programs can't read the tty after using job control to suspend
 | 
			
		||||
and resume the program (with ^Z and "fg" in bash).  The read(2) system
 | 
			
		||||
call fails with EINTR.  In ACK's stdio (in libc), the error is sticky,
 | 
			
		||||
so all reads fail.  In Apple's stdio, the error is not sticky, and
 | 
			
		||||
only the next read fails.  The EINTR seems to happen only on Intel Mac
 | 
			
		||||
OS X, and not on other platforms.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
George Koehler <xkernigh@netscape.net>
 | 
			
		||||
2016-12-03
 | 
			
		||||
							
								
								
									
										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",
 | 
			
		||||
		"plat/osx/include+pkg",
 | 
			
		||||
		["$(PLATIND)/osx386/boot.o"] = "+boot",
 | 
			
		||||
		["$(PLATIND)/osx386/libsys.a"] = "./libsys+lib",
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										22
									
								
								plat/osx386/build-tools.lua
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								plat/osx386/build-tools.lua
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,22 @@
 | 
			
		|||
include("plat/build.lua")
 | 
			
		||||
 | 
			
		||||
build_as {
 | 
			
		||||
	name = "as",
 | 
			
		||||
	arch = "i386",
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
build_ncg {
 | 
			
		||||
	name = "ncg",
 | 
			
		||||
	arch = "i386",
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
return installable {
 | 
			
		||||
	name = "tools",
 | 
			
		||||
	map = {
 | 
			
		||||
		["$(PLATDEP)/osx386/as"] = "+as",
 | 
			
		||||
		["$(PLATDEP)/osx386/ncg"] = "+ncg",
 | 
			
		||||
		["$(PLATIND)/descr/osx386"] = "./descr",
 | 
			
		||||
		"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:0x123c
 | 
			
		||||
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{EM}/share/ack/osx/include -I{EM}/share/ack/include/ansi
 | 
			
		||||
 | 
			
		||||
name be
 | 
			
		||||
	from .m.g
 | 
			
		||||
	to .s
 | 
			
		||||
	program {EM}/lib/ack/{PLATFORM}/ncg
 | 
			
		||||
	mapflag -gdb GF=-gdb
 | 
			
		||||
	args {GF?} <
 | 
			
		||||
	stdout
 | 
			
		||||
	need .e
 | 
			
		||||
end
 | 
			
		||||
name as
 | 
			
		||||
	from .s.so
 | 
			
		||||
	to .o
 | 
			
		||||
	program {EM}/lib/ack/{PLATFORM}/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
 | 
			
		||||
							
								
								
									
										4
									
								
								plat/osx386/include/build.lua
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								plat/osx386/include/build.lua
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,4 @@
 | 
			
		|||
installable {
 | 
			
		||||
	name = "pkg",
 | 
			
		||||
	map = { "plat/osx/include+pkg" }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										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
 | 
			
		||||
							
								
								
									
										35
									
								
								plat/osx386/libsys/build.lua
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								plat/osx386/libsys/build.lua
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,35 @@
 | 
			
		|||
acklibrary {
 | 
			
		||||
	name = "lib",
 | 
			
		||||
	srcs = {
 | 
			
		||||
		"./_exit.s",
 | 
			
		||||
		"./close.s",
 | 
			
		||||
		"./fstat.s",
 | 
			
		||||
		"./getdirentries.s",
 | 
			
		||||
		"./getpid.s",
 | 
			
		||||
		"./gettimeofday.s",
 | 
			
		||||
		"./ioctl.s",
 | 
			
		||||
		"./kill.s",
 | 
			
		||||
		"./lseek.s",
 | 
			
		||||
		"./lstat.s",
 | 
			
		||||
		"./mmap.s",
 | 
			
		||||
		"./mprotect.s",
 | 
			
		||||
		"./open.s",
 | 
			
		||||
		"./read.s",
 | 
			
		||||
		"./set_errno.s",
 | 
			
		||||
		"./sigaction.s",
 | 
			
		||||
		"./stat.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+pkg",
 | 
			
		||||
	},
 | 
			
		||||
	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/fstat.s
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								plat/osx386/libsys/fstat.s
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,7 @@
 | 
			
		|||
.sect .text
 | 
			
		||||
.define _fstat
 | 
			
		||||
_fstat:
 | 
			
		||||
	mov eax, 189
 | 
			
		||||
	int 0x80
 | 
			
		||||
	jb .set_errno
 | 
			
		||||
	ret
 | 
			
		||||
							
								
								
									
										7
									
								
								plat/osx386/libsys/getdirentries.s
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								plat/osx386/libsys/getdirentries.s
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,7 @@
 | 
			
		|||
.sect .text
 | 
			
		||||
.define _getdirentries
 | 
			
		||||
_getdirentries:
 | 
			
		||||
	mov eax, 196
 | 
			
		||||
	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
 | 
			
		||||
							
								
								
									
										18
									
								
								plat/osx386/libsys/gettimeofday.s
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								plat/osx386/libsys/gettimeofday.s
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,18 @@
 | 
			
		|||
! The system call checks the timeval pointer but doesn't store the
 | 
			
		||||
! time there.  If the pointer wasn't NULL, then the system call
 | 
			
		||||
! returns the time in a pair of registers.
 | 
			
		||||
 | 
			
		||||
.sect .text
 | 
			
		||||
.define _gettimeofday
 | 
			
		||||
_gettimeofday:
 | 
			
		||||
	mov eax, 116
 | 
			
		||||
	int 0x80
 | 
			
		||||
	jb .set_errno
 | 
			
		||||
	mov ebx, 4(esp)		! timeval pointer
 | 
			
		||||
	test ebx, ebx
 | 
			
		||||
	je 1f
 | 
			
		||||
	mov 0(ebx), eax		! seconds
 | 
			
		||||
	mov 4(ebx), edx		! microseconds
 | 
			
		||||
1:
 | 
			
		||||
	mov eax, 0		! return 0
 | 
			
		||||
	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
 | 
			
		||||
							
								
								
									
										7
									
								
								plat/osx386/libsys/lstat.s
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								plat/osx386/libsys/lstat.s
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,7 @@
 | 
			
		|||
.sect .text
 | 
			
		||||
.define _lstat
 | 
			
		||||
_lstat:
 | 
			
		||||
	mov eax, 190
 | 
			
		||||
	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/stat.s
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								plat/osx386/libsys/stat.s
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,7 @@
 | 
			
		|||
.sect .text
 | 
			
		||||
.define _stat
 | 
			
		||||
_stat:
 | 
			
		||||
	mov eax, 188
 | 
			
		||||
	int 0x80
 | 
			
		||||
	jb .set_errno
 | 
			
		||||
	ret
 | 
			
		||||
							
								
								
									
										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
 | 
			
		||||
							
								
								
									
										110
									
								
								plat/osxppc/README
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										110
									
								
								plat/osxppc/README
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,110 @@
 | 
			
		|||
The osxppc platform
 | 
			
		||||
===================
 | 
			
		||||
 | 
			
		||||
    ack -mosxppc ...
 | 
			
		||||
 | 
			
		||||
This platform produces Mach-o executables for PowerPC Mac OS X.  You
 | 
			
		||||
can run them from the command line in the Terminal.
 | 
			
		||||
 | 
			
		||||
You *can't* link to libraries from other compilers.  These static
 | 
			
		||||
executables don't use the dynamic linker.  They don't load Apple's
 | 
			
		||||
libraries, so they can't call Carbon or Cocoa.
 | 
			
		||||
 | 
			
		||||
The executables use BSD system calls to interact with your Mac.  Our
 | 
			
		||||
libsys provides only a few system calls, enough to run a few demo
 | 
			
		||||
programs, but not much else.  Check the header files in ../osx/include
 | 
			
		||||
for the available system calls.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
Bugs
 | 
			
		||||
----
 | 
			
		||||
 | 
			
		||||
ACK didn't run on Mac OS X when this platform was added.  The only way
 | 
			
		||||
to run ack -mosxppc was as a cross compiler from another operating
 | 
			
		||||
system.
 | 
			
		||||
 | 
			
		||||
ACK doesn't have 64-bit integers, but Mac OS X uses 64-bit integers in
 | 
			
		||||
its system calls.  Our libsys converts between 32-bit and 64-bit
 | 
			
		||||
integers by setting the high bits to zero, or discarding the high
 | 
			
		||||
bits.  This affects lseek() and stat().  They report the wrong values
 | 
			
		||||
for file sizes and offsets beyond 4 gigabytes.
 | 
			
		||||
 | 
			
		||||
Our PowerPC code generator is new and probably has bugs.  Its stack
 | 
			
		||||
layout and calling conventions are not compatible with other
 | 
			
		||||
compilers.  It passes all function arguments on the stack, which is
 | 
			
		||||
slower than passing them in registers.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
Example
 | 
			
		||||
-------
 | 
			
		||||
Compile something:
 | 
			
		||||
 | 
			
		||||
    ack -mosxppc -O6 -o paranoia examples/paranoia.c
 | 
			
		||||
 | 
			
		||||
The executable has a symbol table.  If you have Apple's Xcode, try
 | 
			
		||||
 | 
			
		||||
    nm -g paranoia      # to list the global symbols
 | 
			
		||||
    otool -hl paranoia  # to check the Mach header and load commands
 | 
			
		||||
    gdb paranoia        # to debug it
 | 
			
		||||
 | 
			
		||||
Within gdb, commands like "gdb main" and "gdb '.ret'" can disassemble
 | 
			
		||||
functions.  Backtraces don't work, because our stack layout is not the
 | 
			
		||||
same as Apple's.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
Other hints
 | 
			
		||||
-----------
 | 
			
		||||
 | 
			
		||||
PowerPC Macs became obsolete after Apple's transition to Intel.  Mac
 | 
			
		||||
OS X 10.5 Leopard was the last version to run on PowerPC.  The older
 | 
			
		||||
Mac OS X 10.4 Tiger was the last version to include Classic for
 | 
			
		||||
running Mac OS 9 programs.  Our ack -mosxppc began to produce
 | 
			
		||||
executables in 2016, about 7 years after Apple released Mac OS X 10.6
 | 
			
		||||
Snow Leopard for Intel only.
 | 
			
		||||
 | 
			
		||||
Apple's Xcode included tools like gcc and gdb.  It also had manual
 | 
			
		||||
pages for some system calls, like getdirentries(2).  Some system calls
 | 
			
		||||
are like FreeBSD, some are unique to OS X.  If you want to learn how
 | 
			
		||||
to call write(2) or sigaction(2), then a manual page from another BSD
 | 
			
		||||
or Linux might be enough.
 | 
			
		||||
 | 
			
		||||
Xcode 2.5 was the last version to run on Tiger.  The "Xcode 2.5
 | 
			
		||||
Developer Tools" were a 902.9 MB download from Apple.  As of 2016, the
 | 
			
		||||
download required an Apple ID and was available at:
 | 
			
		||||
 | 
			
		||||
    https://developer.apple.com/download/more/
 | 
			
		||||
 | 
			
		||||
Older versions of Xcode came with Mac OS X.  If your version of OS X
 | 
			
		||||
came with your Mac, /Applications/Installers might contain an Xcode
 | 
			
		||||
installer.  If you upgraded OS X, your install DVD might have Xcode.
 | 
			
		||||
 | 
			
		||||
The source code at https://opensource.apple.com/ might reveal more
 | 
			
		||||
about system calls.  For 10.4.11.ppc, the kernel is in xnu-792.24.17,
 | 
			
		||||
and Libc is in Libc-391.2.10.  These files might help:
 | 
			
		||||
 | 
			
		||||
    xnu*/bsd/kern/syscalls.master
 | 
			
		||||
      master list of BSD system calls
 | 
			
		||||
    xnu*/osfmk/kern/syscall_sw.c
 | 
			
		||||
      master list of Mach traps
 | 
			
		||||
    xnu*/bsd/kern/mach_loader.c
 | 
			
		||||
      details about loading Mach-o executables
 | 
			
		||||
    xnu*/bsd/dev/ppc/unix_signal.c
 | 
			
		||||
      details about sending signals to processes
 | 
			
		||||
    xnu*/bsd/sys/*.h
 | 
			
		||||
      headers that Xcode installs as /usr/include/sys/*.h
 | 
			
		||||
    xnu*/bsd/man/man2/*.2
 | 
			
		||||
      manual pages that Xcode installs as /usr/share/man/man2/*.2
 | 
			
		||||
    Libc*/ppc/sys/SYS.h
 | 
			
		||||
    Libc*/ppc/sys/*.s
 | 
			
		||||
      assembly code (in gas syntax) for making system calls
 | 
			
		||||
 | 
			
		||||
The 10.4.11.ppc sources are wrong for Intel; use 10.4.11.x86 or 10.5
 | 
			
		||||
or newer.  10.5 moved SYS.h to xnu*/libsyscall/custom/SYS.h
 | 
			
		||||
 | 
			
		||||
The kernel maps a common page into every process, and Apple's Libc
 | 
			
		||||
uses the common page to speed up system calls like gettimeofday(2).
 | 
			
		||||
Our libsys does not use the common page.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
George Koehler <xkernigh@netscape.net>
 | 
			
		||||
2016-12-03
 | 
			
		||||
							
								
								
									
										60
									
								
								plat/osxppc/boot.s
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										60
									
								
								plat/osxppc/boot.s
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,60 @@
 | 
			
		|||
! boot.s for osxppc
 | 
			
		||||
 | 
			
		||||
! 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",
 | 
			
		||||
		"plat/osx/include+pkg",
 | 
			
		||||
		["$(PLATIND)/osxppc/boot.o"] = "+boot",
 | 
			
		||||
		["$(PLATIND)/osxppc/libsys.a"] = "./libsys+lib",
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										28
									
								
								plat/osxppc/build-tools.lua
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								plat/osxppc/build-tools.lua
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,28 @@
 | 
			
		|||
include("plat/build.lua")
 | 
			
		||||
 | 
			
		||||
build_as {
 | 
			
		||||
	name = "as",
 | 
			
		||||
	arch = "powerpc",
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
build_ncg {
 | 
			
		||||
	name = "ncg",
 | 
			
		||||
	arch = "powerpc",
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
build_top {
 | 
			
		||||
	name = "top",
 | 
			
		||||
	arch = "powerpc",
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
return installable {
 | 
			
		||||
	name = "tools",
 | 
			
		||||
	map = {
 | 
			
		||||
		["$(PLATDEP)/osxppc/as"] = "+as",
 | 
			
		||||
		["$(PLATDEP)/osxppc/ncg"] = "+ncg",
 | 
			
		||||
		["$(PLATDEP)/osxppc/top"] = "+top",
 | 
			
		||||
		["$(PLATIND)/descr/osxppc"] = "./descr",
 | 
			
		||||
		"plat/osx/cvmach+pkg",
 | 
			
		||||
		"util/opt+pkg",
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										85
									
								
								plat/osxppc/descr
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										85
									
								
								plat/osxppc/descr
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,85 @@
 | 
			
		|||
# 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:0x129c
 | 
			
		||||
var MACHOPT_F=-m3
 | 
			
		||||
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{EM}/share/ack/osx/include -I{EM}/share/ack/include/ansi
 | 
			
		||||
 | 
			
		||||
name be
 | 
			
		||||
	from .m.g
 | 
			
		||||
	to .s
 | 
			
		||||
	program {EM}/lib/ack/{PLATFORM}/ncg
 | 
			
		||||
	mapflag -gdb GF=-gdb
 | 
			
		||||
	args {GF?} <
 | 
			
		||||
	stdout
 | 
			
		||||
	need .e
 | 
			
		||||
end
 | 
			
		||||
name asopt
 | 
			
		||||
	from .s
 | 
			
		||||
	to .so
 | 
			
		||||
	program {EM}/lib/ack/{PLATFORM}/top
 | 
			
		||||
	args
 | 
			
		||||
	optimizer
 | 
			
		||||
	stdin
 | 
			
		||||
	stdout
 | 
			
		||||
end
 | 
			
		||||
name as
 | 
			
		||||
	from .s.so
 | 
			
		||||
	to .o
 | 
			
		||||
	program {EM}/lib/ack/{PLATFORM}/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
 | 
			
		||||
							
								
								
									
										4
									
								
								plat/osxppc/include/build.lua
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								plat/osxppc/include/build.lua
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,4 @@
 | 
			
		|||
installable {
 | 
			
		||||
	name = "pkg",
 | 
			
		||||
	map = { "plat/osx/include+pkg" }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										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
 | 
			
		||||
							
								
								
									
										35
									
								
								plat/osxppc/libsys/build.lua
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								plat/osxppc/libsys/build.lua
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,35 @@
 | 
			
		|||
acklibrary {
 | 
			
		||||
	name = "lib",
 | 
			
		||||
	srcs = {
 | 
			
		||||
		"./_exit.s",
 | 
			
		||||
		"./close.s",
 | 
			
		||||
		"./fstat.s",
 | 
			
		||||
		"./getdirentries.s",
 | 
			
		||||
		"./getpid.s",
 | 
			
		||||
		"./gettimeofday.s",
 | 
			
		||||
		"./ioctl.s",
 | 
			
		||||
		"./kill.s",
 | 
			
		||||
		"./lseek.s",
 | 
			
		||||
		"./lstat.s",
 | 
			
		||||
		"./mmap.s",
 | 
			
		||||
		"./mprotect.s",
 | 
			
		||||
		"./open.s",
 | 
			
		||||
		"./read.s",
 | 
			
		||||
		"./set_errno.s",
 | 
			
		||||
		"./sigaction.s",
 | 
			
		||||
		"./stat.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+pkg",
 | 
			
		||||
	},
 | 
			
		||||
	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
 | 
			
		||||
							
								
								
									
										9
									
								
								plat/osxppc/libsys/fstat.s
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								plat/osxppc/libsys/fstat.s
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,9 @@
 | 
			
		|||
.sect .text
 | 
			
		||||
.define _fstat
 | 
			
		||||
_fstat:
 | 
			
		||||
	addi r0, r0, 189	! fstat
 | 
			
		||||
	lwz r3, 0(sp)		! fd
 | 
			
		||||
	lwz r4, 4(sp)		! stat pointer
 | 
			
		||||
	sc 0
 | 
			
		||||
	b .set_errno
 | 
			
		||||
	bclr 20, 0, 0
 | 
			
		||||
							
								
								
									
										11
									
								
								plat/osxppc/libsys/getdirentries.s
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								plat/osxppc/libsys/getdirentries.s
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,11 @@
 | 
			
		|||
.sect .text
 | 
			
		||||
.define _getdirentries
 | 
			
		||||
_getdirentries:
 | 
			
		||||
	addi r0, r0, 196	! getdirentries
 | 
			
		||||
	lwz r3, 0(sp)		! fd
 | 
			
		||||
	lwz r4, 4(sp)		! buffer
 | 
			
		||||
	lwz r5, 8(sp)		! buffer size
 | 
			
		||||
	lwz r6, 12(sp)		! base pointer
 | 
			
		||||
	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
 | 
			
		||||
							
								
								
									
										19
									
								
								plat/osxppc/libsys/gettimeofday.s
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								plat/osxppc/libsys/gettimeofday.s
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,19 @@
 | 
			
		|||
! The system call checks the timeval pointer but doesn't store the
 | 
			
		||||
! time there.  If the pointer wasn't NULL, then the system call
 | 
			
		||||
! returns the time in a pair of registers.
 | 
			
		||||
 | 
			
		||||
.sect .text
 | 
			
		||||
.define _gettimeofday
 | 
			
		||||
_gettimeofday:
 | 
			
		||||
	addi r0, r0, 116	! gettimeofday
 | 
			
		||||
	lwz r3, 0(sp)		! timeval pointer
 | 
			
		||||
	lwz r4, 4(sp)		! timezone pointer
 | 
			
		||||
	or. r5, r3, r3
 | 
			
		||||
	sc 0
 | 
			
		||||
	b .set_errno
 | 
			
		||||
	bc 12, 2, 1f		! beq 1f
 | 
			
		||||
	stw r3, 0(r5)		! seconds
 | 
			
		||||
	stw r4, 4(r5)		! microseconds
 | 
			
		||||
1:
 | 
			
		||||
	addi r3, r0, 0		! return 0
 | 
			
		||||
	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
 | 
			
		||||
							
								
								
									
										9
									
								
								plat/osxppc/libsys/lstat.s
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								plat/osxppc/libsys/lstat.s
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,9 @@
 | 
			
		|||
.sect .text
 | 
			
		||||
.define _lstat
 | 
			
		||||
_lstat:
 | 
			
		||||
	addi r0, r0, 190	! lstat
 | 
			
		||||
	lwz r3, 0(sp)		! path
 | 
			
		||||
	lwz r4, 4(sp)		! stat pointer
 | 
			
		||||
	sc 0
 | 
			
		||||
	b .set_errno
 | 
			
		||||
	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
 | 
			
		||||
							
								
								
									
										9
									
								
								plat/osxppc/libsys/stat.s
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								plat/osxppc/libsys/stat.s
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,9 @@
 | 
			
		|||
.sect .text
 | 
			
		||||
.define _stat
 | 
			
		||||
_stat:
 | 
			
		||||
	addi r0, r0, 188	! stat
 | 
			
		||||
	lwz r3, 0(sp)		! path
 | 
			
		||||
	lwz r4, 4(sp)		! stat pointer
 | 
			
		||||
	sc 0
 | 
			
		||||
	b .set_errno
 | 
			
		||||
	bclr 20, 0, 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
 | 
			
		||||
| 
						 | 
				
			
			@ -22,6 +22,7 @@ end
 | 
			
		|||
build_descr("i386")
 | 
			
		||||
build_descr("i86")
 | 
			
		||||
build_descr("m68020")
 | 
			
		||||
build_descr("powerpc")
 | 
			
		||||
 | 
			
		||||
installable {
 | 
			
		||||
	name = "pkg",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										118
									
								
								util/ego/descr/powerpc.descr
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										118
									
								
								util/ego/descr/powerpc.descr
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,118 @@
 | 
			
		|||
wordsize: 4
 | 
			
		||||
pointersize: 4
 | 
			
		||||
%%RA
 | 
			
		||||
general registers: 19
 | 
			
		||||
address registers: 0
 | 
			
		||||
floating point registers: 0
 | 
			
		||||
use general as pointer: yes
 | 
			
		||||
 | 
			
		||||
register score parameters:
 | 
			
		||||
	local variable:
 | 
			
		||||
		(2 cases)
 | 
			
		||||
		pointer,general
 | 
			
		||||
			(1 size)
 | 
			
		||||
			default ->	(3,4)
 | 
			
		||||
		general,general
 | 
			
		||||
			(1 size)
 | 
			
		||||
			default ->	(3,4)
 | 
			
		||||
	address of local variable:
 | 
			
		||||
		(2 cases)
 | 
			
		||||
		pointer,general
 | 
			
		||||
			(1 size)
 | 
			
		||||
			default ->	(0,0)
 | 
			
		||||
		general,general
 | 
			
		||||
			(1 size)
 | 
			
		||||
			default ->	(0,0)
 | 
			
		||||
	constant:
 | 
			
		||||
		(2 sizes)
 | 
			
		||||
		fitbyte ->	(-1,-1)
 | 
			
		||||
		default ->	(-1,-1)
 | 
			
		||||
	double constant:
 | 
			
		||||
		(1 size)
 | 
			
		||||
		default ->	(-1,-1)
 | 
			
		||||
	address of global variable:
 | 
			
		||||
		(1 size)
 | 
			
		||||
		default ->	(2,8)
 | 
			
		||||
	address of procedure:
 | 
			
		||||
		(1 size)
 | 
			
		||||
		default ->	(-1,-1)
 | 
			
		||||
 | 
			
		||||
opening cost parameters:
 | 
			
		||||
	local variable:
 | 
			
		||||
		(2 cases)
 | 
			
		||||
		pointer
 | 
			
		||||
			(1 size)
 | 
			
		||||
			default ->	(3,4)
 | 
			
		||||
		general
 | 
			
		||||
			(1 size)
 | 
			
		||||
			default ->	(3,4)
 | 
			
		||||
	address of local variable:
 | 
			
		||||
		(2 cases)
 | 
			
		||||
		pointer
 | 
			
		||||
			(1 size)
 | 
			
		||||
			default ->	(1,4)
 | 
			
		||||
		general
 | 
			
		||||
			(1 size)
 | 
			
		||||
			general ->	(1,4)
 | 
			
		||||
	constant:
 | 
			
		||||
		(2 sizes)
 | 
			
		||||
		fitbyte ->	(1000,1000)
 | 
			
		||||
		default ->	(1000,1000)
 | 
			
		||||
	double constant:
 | 
			
		||||
		(1 size)
 | 
			
		||||
		default ->	(1000,1000)
 | 
			
		||||
	address of global variable:
 | 
			
		||||
		(1 size)
 | 
			
		||||
		default ->	(2,8)
 | 
			
		||||
	address of procedure:
 | 
			
		||||
		(1 size)
 | 
			
		||||
		default ->	(1000,1000)
 | 
			
		||||
 | 
			
		||||
register save costs:
 | 
			
		||||
	(21 cases)
 | 
			
		||||
	0 -> (0,0)
 | 
			
		||||
	1 -> (6,8)
 | 
			
		||||
	2 -> (12,16)
 | 
			
		||||
	3 -> (18,24)
 | 
			
		||||
	4 -> (24,32)
 | 
			
		||||
	5 -> (30,40)
 | 
			
		||||
	6 -> (36,48)
 | 
			
		||||
	7 -> (42,56)
 | 
			
		||||
	8 -> (48,64)
 | 
			
		||||
	9 -> (54,72)
 | 
			
		||||
	10 -> (60,80)
 | 
			
		||||
	11 -> (66,88)
 | 
			
		||||
	12 -> (72,96)
 | 
			
		||||
	13 -> (78,104)
 | 
			
		||||
	14 -> (84,112)
 | 
			
		||||
	15 -> (90,120)
 | 
			
		||||
	16 -> (96,128)
 | 
			
		||||
	17 -> (102,136)
 | 
			
		||||
	18 -> (108,144)
 | 
			
		||||
	19 -> (114,152)
 | 
			
		||||
	0 -> (0,0)
 | 
			
		||||
%%UD
 | 
			
		||||
access costs of global variables:
 | 
			
		||||
	(1 size)
 | 
			
		||||
	default ->	(5,12)
 | 
			
		||||
access costs of local variables:
 | 
			
		||||
	(1 size)
 | 
			
		||||
	default ->	(3,4)
 | 
			
		||||
%%SR
 | 
			
		||||
overflow harmful?:  no
 | 
			
		||||
array bound harmful?:  yes
 | 
			
		||||
reduce sli if shift count larger than:  0
 | 
			
		||||
%%CS
 | 
			
		||||
#include "em_mnem.h"
 | 
			
		||||
first time then space:
 | 
			
		||||
addressing modes: op_ads op_adp op_lof op_ldf op_loi op_dch op_lpb -1
 | 
			
		||||
		  op_ads op_adp op_lof op_ldf op_loi op_dch op_lpb -1
 | 
			
		||||
cheap operations: op_cii op_ciu op_cui op_cuu op_cmi op_cmu op_cmp -1 
 | 
			
		||||
		  op_cii op_ciu op_cui op_cuu op_cmi op_cmu op_cmp -1
 | 
			
		||||
lexical tresholds: 1 1
 | 
			
		||||
indirection limit: 8
 | 
			
		||||
do not eliminate sli if index on shiftcounts:	-1
 | 
			
		||||
						-1
 | 
			
		||||
forbidden operators: -1 -1
 | 
			
		||||
%%SP
 | 
			
		||||
global stack pollution allowed?: yes
 | 
			
		||||
| 
						 | 
				
			
			@ -11,6 +11,7 @@ static char rcsid[] = "$Id$";
 | 
			
		|||
 */
 | 
			
		||||
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
#include <out.h>
 | 
			
		||||
#include "const.h"
 | 
			
		||||
#include "debug.h"
 | 
			
		||||
| 
						 | 
				
			
			@ -29,15 +30,16 @@ int		Verbose = 0;
 | 
			
		|||
 | 
			
		||||
static			initializations();
 | 
			
		||||
static			first_pass();
 | 
			
		||||
static long		number();
 | 
			
		||||
static			setlign();
 | 
			
		||||
static			setbase();
 | 
			
		||||
static uint32_t		number(const char *);
 | 
			
		||||
static void		setlign(int, uint32_t);
 | 
			
		||||
static void		setbase(int, uint32_t);
 | 
			
		||||
static struct outname	*makename();
 | 
			
		||||
static			pass1();
 | 
			
		||||
static			evaluate();
 | 
			
		||||
static void norm_commons();
 | 
			
		||||
static void		norm_commons();
 | 
			
		||||
static			complete_sections();
 | 
			
		||||
static void change_names();
 | 
			
		||||
static void		change_names();
 | 
			
		||||
static bool		setbit();
 | 
			
		||||
static bool		tstbit();
 | 
			
		||||
static			second_pass();
 | 
			
		||||
static			pass2();
 | 
			
		||||
| 
						 | 
				
			
			@ -251,12 +253,11 @@ first_pass(argv)
 | 
			
		|||
 * else if it starts with 0, it's octal,
 | 
			
		||||
 * else it's decimal.
 | 
			
		||||
 */
 | 
			
		||||
static long
 | 
			
		||||
number(s)
 | 
			
		||||
	register char	*s;
 | 
			
		||||
static uint32_t
 | 
			
		||||
number(const char *s)
 | 
			
		||||
{
 | 
			
		||||
	register int	digit;
 | 
			
		||||
	register long	value = 0;
 | 
			
		||||
	register uint32_t value = 0;
 | 
			
		||||
	register int	radix = 10;
 | 
			
		||||
 | 
			
		||||
	if (*s == '0') {
 | 
			
		||||
| 
						 | 
				
			
			@ -291,22 +292,17 @@ number(s)
 | 
			
		|||
 * not. Only one base may be given. The same applies for alignments.
 | 
			
		||||
 */
 | 
			
		||||
static char	basemap[MAXSECT / WIDTH];
 | 
			
		||||
static long	sect_base[MAXSECT];
 | 
			
		||||
static uint32_t	sect_base[MAXSECT];
 | 
			
		||||
static char	lignmap[MAXSECT / WIDTH];
 | 
			
		||||
static long	sect_lign[MAXSECT];
 | 
			
		||||
static uint32_t	sect_lign[MAXSECT];
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
/*
 | 
			
		||||
 * Set the alignment of section `sectno' to `lign', if this doesn't
 | 
			
		||||
 * conflict with earlier alignment.
 | 
			
		||||
 */
 | 
			
		||||
static
 | 
			
		||||
setlign(sectno, lign)
 | 
			
		||||
	register int	sectno;
 | 
			
		||||
	register long	lign;
 | 
			
		||||
static void
 | 
			
		||||
setlign(int sectno, uint32_t lign)
 | 
			
		||||
{
 | 
			
		||||
	extern bool	setbit();
 | 
			
		||||
 | 
			
		||||
	if (setbit(sectno, lignmap) && sect_lign[sectno] != lign)
 | 
			
		||||
		fatal("section has different alignments");
 | 
			
		||||
	if (lign == (long)0)
 | 
			
		||||
| 
						 | 
				
			
			@ -318,13 +314,9 @@ setlign(sectno, lign)
 | 
			
		|||
 * Set the base of section `sectno' to `base', if no other base has been
 | 
			
		||||
 * given yet.
 | 
			
		||||
 */
 | 
			
		||||
static
 | 
			
		||||
setbase(sectno, base)
 | 
			
		||||
	register int	sectno;
 | 
			
		||||
	register long	base;
 | 
			
		||||
static void
 | 
			
		||||
setbase(int sectno, uint32_t base)
 | 
			
		||||
{
 | 
			
		||||
	extern bool	setbit();
 | 
			
		||||
 | 
			
		||||
	if (setbit(sectno, basemap) && sect_base[sectno] != base)
 | 
			
		||||
		fatal("section has different bases");
 | 
			
		||||
	sect_base[sectno] = base;
 | 
			
		||||
| 
						 | 
				
			
			@ -459,8 +451,8 @@ struct orig	relorig[MAXSECT];
 | 
			
		|||
static
 | 
			
		||||
complete_sections()
 | 
			
		||||
{
 | 
			
		||||
	register long	base = 0;
 | 
			
		||||
	register long	foff;
 | 
			
		||||
	register uint32_t base = 0;
 | 
			
		||||
	register uint32_t foff;
 | 
			
		||||
	register struct outsect *sc;
 | 
			
		||||
	register int	sectindex;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		
		Reference in a new issue