From 02fb48021773ae40a9781a45649ded39d02d1089 Mon Sep 17 00:00:00 2001 From: George Koehler Date: Sun, 2 Oct 2016 14:58:05 -0400 Subject: [PATCH 001/173] Commit a preview of osx386 and osxppc as new platforms. These produce Mach-o executables for Mac OS X on Intel or PowerPC processors. Our code generator for PowerPC (mach/powerpc) still has bugs. Some examples seem to run, but startrek crashes. Our code generator for Intel (mach/i386) is better. There is a problem with job control. If you run paranoia or startrek, then suspend the job (^Z) and resume it ('fg' in bash), then read(2) might fail with EINTR. The larger files in this commit are - plat/osx/cvmach/cvmach.c - plat/osx/libsys/brk.c - plat/osx386/libsys/sigaction.s - plat/osxppc/libsys/sigaction.s --- build.lua | 2 + plat/osx/cvmach/build.lua | 17 ++ plat/osx/cvmach/cvmach.c | 418 ++++++++++++++++++++++++++++++ plat/osx/include/ack/config.h | 14 + plat/osx/include/sys/mman.h | 20 ++ plat/osx/include/sys/types.h | 9 + plat/osx/include/unistd.h | 132 ++++++++++ plat/osx/libsys/brk.c | 95 +++++++ plat/osx/libsys/creat.c | 6 + plat/osx/libsys/isatty.c | 7 + plat/osx/libsys/signal.c | 16 ++ plat/osx386/boot.s | 69 +++++ plat/osx386/build-pkg.lua | 24 ++ plat/osx386/build-tools.lua | 9 + plat/osx386/descr | 80 ++++++ plat/osx386/include/build.lua | 24 ++ plat/osx386/libsys/_exit.s | 5 + plat/osx386/libsys/build.lua | 31 +++ plat/osx386/libsys/close.s | 7 + plat/osx386/libsys/getpid.s | 7 + plat/osx386/libsys/gettimeofday.s | 7 + plat/osx386/libsys/ioctl.s | 7 + plat/osx386/libsys/kill.s | 7 + plat/osx386/libsys/lseek.s | 17 ++ plat/osx386/libsys/mmap.s | 20 ++ plat/osx386/libsys/mprotect.s | 7 + plat/osx386/libsys/open.s | 7 + plat/osx386/libsys/read.s | 7 + plat/osx386/libsys/set_errno.s | 6 + plat/osx386/libsys/sigaction.s | 59 +++++ plat/osx386/libsys/write.s | 7 + plat/osxppc/boot.s | 60 +++++ plat/osxppc/build-pkg.lua | 24 ++ plat/osxppc/build-tools.lua | 9 + plat/osxppc/descr | 81 ++++++ plat/osxppc/include/build.lua | 24 ++ plat/osxppc/libsys/_exit.s | 6 + plat/osxppc/libsys/build.lua | 31 +++ plat/osxppc/libsys/close.s | 8 + plat/osxppc/libsys/getpid.s | 7 + plat/osxppc/libsys/gettimeofday.s | 9 + plat/osxppc/libsys/ioctl.s | 10 + plat/osxppc/libsys/kill.s | 9 + plat/osxppc/libsys/lseek.s | 13 + plat/osxppc/libsys/mmap.s | 15 ++ plat/osxppc/libsys/mprotect.s | 10 + plat/osxppc/libsys/open.s | 10 + plat/osxppc/libsys/read.s | 10 + plat/osxppc/libsys/set_errno.s | 7 + plat/osxppc/libsys/sigaction.s | 59 +++++ plat/osxppc/libsys/write.s | 10 + 51 files changed, 1555 insertions(+) create mode 100644 plat/osx/cvmach/build.lua create mode 100644 plat/osx/cvmach/cvmach.c create mode 100644 plat/osx/include/ack/config.h create mode 100644 plat/osx/include/sys/mman.h create mode 100644 plat/osx/include/sys/types.h create mode 100644 plat/osx/include/unistd.h create mode 100644 plat/osx/libsys/brk.c create mode 100644 plat/osx/libsys/creat.c create mode 100644 plat/osx/libsys/isatty.c create mode 100644 plat/osx/libsys/signal.c create mode 100644 plat/osx386/boot.s create mode 100644 plat/osx386/build-pkg.lua create mode 100644 plat/osx386/build-tools.lua create mode 100644 plat/osx386/descr create mode 100644 plat/osx386/include/build.lua create mode 100644 plat/osx386/libsys/_exit.s create mode 100644 plat/osx386/libsys/build.lua create mode 100644 plat/osx386/libsys/close.s create mode 100644 plat/osx386/libsys/getpid.s create mode 100644 plat/osx386/libsys/gettimeofday.s create mode 100644 plat/osx386/libsys/ioctl.s create mode 100644 plat/osx386/libsys/kill.s create mode 100644 plat/osx386/libsys/lseek.s create mode 100644 plat/osx386/libsys/mmap.s create mode 100644 plat/osx386/libsys/mprotect.s create mode 100644 plat/osx386/libsys/open.s create mode 100644 plat/osx386/libsys/read.s create mode 100644 plat/osx386/libsys/set_errno.s create mode 100644 plat/osx386/libsys/sigaction.s create mode 100644 plat/osx386/libsys/write.s create mode 100644 plat/osxppc/boot.s create mode 100644 plat/osxppc/build-pkg.lua create mode 100644 plat/osxppc/build-tools.lua create mode 100644 plat/osxppc/descr create mode 100644 plat/osxppc/include/build.lua create mode 100644 plat/osxppc/libsys/_exit.s create mode 100644 plat/osxppc/libsys/build.lua create mode 100644 plat/osxppc/libsys/close.s create mode 100644 plat/osxppc/libsys/getpid.s create mode 100644 plat/osxppc/libsys/gettimeofday.s create mode 100644 plat/osxppc/libsys/ioctl.s create mode 100644 plat/osxppc/libsys/kill.s create mode 100644 plat/osxppc/libsys/lseek.s create mode 100644 plat/osxppc/libsys/mmap.s create mode 100644 plat/osxppc/libsys/mprotect.s create mode 100644 plat/osxppc/libsys/open.s create mode 100644 plat/osxppc/libsys/read.s create mode 100644 plat/osxppc/libsys/set_errno.s create mode 100644 plat/osxppc/libsys/sigaction.s create mode 100644 plat/osxppc/libsys/write.s diff --git a/build.lua b/build.lua index 05a4eafcd..65ae6cb26 100644 --- a/build.lua +++ b/build.lua @@ -9,6 +9,8 @@ vars.plats = { "linux386", "linux68k", "linuxppc", + "osx386", + "osxppc", "pc86", "rpi", } diff --git a/plat/osx/cvmach/build.lua b/plat/osx/cvmach/build.lua new file mode 100644 index 000000000..ae4a18ecb --- /dev/null +++ b/plat/osx/cvmach/build.lua @@ -0,0 +1,17 @@ +cprogram { + name = "cvmach", + srcs = { "./cvmach.c" }, + deps = { + "h+emheaders", + -- Next line only because object.h includes ansi.h + "modules+headers", + "modules/src/object+lib", + } +} + +installable { + name = "pkg", + map = { + ["$(PLATDEP)/cvmach"] = "+cvmach", + } +} diff --git a/plat/osx/cvmach/cvmach.c b/plat/osx/cvmach/cvmach.c new file mode 100644 index 000000000..12a48696d --- /dev/null +++ b/plat/osx/cvmach/cvmach.c @@ -0,0 +1,418 @@ +/* + * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands. + * See the copyright notice in the ACK home directory, in the file "Copyright". + */ + +/* + * cvmach.c - convert ack.out to mach-o + * + * Mostly pinched from aelflod (util/amisc/aelflod.c), which pinched + * from the ARM cv (mach/arm/cv/cv.c), which pinched from the m68k2 cv + * (mach/m68k2/cv/cv.c). The code to read ack.out format using + * liboject is pinched from the Xenix i386 cv (mach/i386/cv/cv.c). + */ + +#include +#include +#include +#include +#include + +#include +/* Can't find #include */ + +/* Header and section table of ack.out */ +struct outhead outhead; +struct outsect outsect[S_MAX]; + +int bigendian; /* Emit big-endian Mach-o? */ +int cpu_type; +uint32_t entry; /* Virtual address of entry point */ +uint32_t sz_thread_command; + +char *outputfile = NULL; /* Name of output file, or NULL */ +char *program; /* Name of current program: argv[0] */ +FILE *output; /* Output stream */ +#define writef(a, b, c) fwrite((a), (b), (c), output) + +/* Segment numbers in ack.out */ +enum { + TEXT = 0, + ROM, + DATA, + BSS, + NUM_SEGMENTS +}; + +/* Constants from Mach headers */ +#define MH_MAGIC 0xfeedface +#define MH_EXECUTE 2 +#define LC_SEGMENT 1 +#define LC_UNIXTHREAD 5 + +#define CPU_TYPE_X86 7 +#define CPU_SUBTYPE_X86_ALL 3 +#define x86_THREAD_STATE32 1 +#define x86_THREAD_STATE32_COUNT 16 + +#define CPU_TYPE_POWERPC 18 +#define CPU_SUBTYPE_POWERPC_ALL 0 +#define PPC_THREAD_STATE 1 +#define PPC_THREAD_STATE_COUNT 40 + +#define VM_PROT_NONE 0x0 +#define VM_PROT_READ 0x1 +#define VM_PROT_WRITE 0x2 +#define VM_PROT_EXECUTE 0x4 + +/* sizes of Mach structs */ +#define SZ_MACH_HEADER 28 +#define SZ_SEGMENT_COMMAND 56 +#define SZ_THREAD_COMMAND_BF_STATE 16 + +/* the page size for x86 and PowerPC */ +#define CV_PGSZ 4096 +/* u modulo page size */ +#define pg_mod(u) ((u) & (CV_PGSZ - 1)) +/* u rounded down to whole pages */ +#define pg_trunc(u) ((u) & ~(CV_PGSZ - 1)) + + +void usage(void) +{ + fprintf(stderr, "Usage: %s -m \n", + program); + exit(1); +} + +/* Produce an error message and exit. */ +void fatal(const char* s, ...) +{ + va_list ap; + + fprintf(stderr, "%s: ",program) ; + + va_start(ap, s); + vfprintf(stderr, s, ap); + va_end(ap); + + fprintf(stderr, "\n"); + + if (outputfile) + unlink(outputfile); + exit(1); +} + +void rd_fatal(void) +{ + fatal("read error"); +} + +/* Calculate the result of a aligned to b (rounding up if necessary). + * b must be a power of two. */ +uint32_t align(uint32_t a, uint32_t b) +{ + a += b - 1; + return a & ~(b-1); +} + + +/* Writes out a 32-bit value in the appropriate endianness. */ +void emit32(uint32_t value) +{ + unsigned char buffer[4]; + + if (bigendian) + { + buffer[0] = (value >> 24) & 0xFF; + buffer[1] = (value >> 16) & 0xFF; + buffer[2] = (value >> 8) & 0xFF; + buffer[3] = (value >> 0) & 0xFF; + } + else + { + buffer[3] = (value >> 24) & 0xFF; + buffer[2] = (value >> 16) & 0xFF; + buffer[1] = (value >> 8) & 0xFF; + buffer[0] = (value >> 0) & 0xFF; + } + + writef(buffer, 1, sizeof(buffer)); +} + +/* Copies the contents of a section from the input stream + * to the output stream. */ +void emit_section(int section_nr) +{ + struct outsect *section = &outsect[section_nr]; + size_t blocksize; + uint32_t n = section->os_flen; + char buffer[BUFSIZ]; + + rd_outsect(section_nr); + while (n > 0) + { + blocksize = (n > BUFSIZ) ? BUFSIZ : n; + rd_emit(buffer, (long)blocksize); + writef(buffer, 1, blocksize); + n -= blocksize; + } + + /* Zero fill any remaining space. */ + n = section->os_size - section->os_flen; + if (n > 0) + { + memset(buffer, 0, BUFSIZ); + while (n > 0) + { + blocksize = (n > BUFSIZ) ? BUFSIZ : n; + writef(buffer, 1, blocksize); + n -= blocksize; + } + } +} + +void emit_lc_segment(char *name, uint32_t vm_ad, uint32_t vm_sz, + uint32_t f_off, uint32_t f_sz, int prot) +{ + char namebuf[16]; + int flags, maxprot; + + if (prot == VM_PROT_NONE) { + /* special values for __PAGEZERO */ + maxprot = VM_PROT_NONE; + flags = 4; /* NORELOC */ + } else { + maxprot = VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE; + flags = 0; + } + + /* Use strncpy() to pad namebuf with '\0' bytes. */ + strncpy(namebuf, name, sizeof(namebuf)); + + emit32(LC_SEGMENT); /* command */ + emit32(SZ_SEGMENT_COMMAND); /* size of command */ + writef(namebuf, 1, sizeof(namebuf)); + emit32(vm_ad); /* vm address */ + emit32(vm_sz); /* vm size */ + emit32(f_off); /* file offset */ + emit32(f_sz); /* file size */ + emit32(maxprot); /* max protection */ + emit32(prot); /* initial protection */ + emit32(0); /* number of Mach sections */ + emit32(flags); /* flags */ +} + +void emit_lc_unixthread(void) +{ + int i, ireg, ts, ts_count; + + /* + * The thread state has ts_count registers. The ireg'th + * register holds the entry point. We can set other registers + * to zero. At execution time, the kernel will allocate a + * stack and set the stack pointer. + */ + switch (cpu_type) { + case CPU_TYPE_X86: + ireg = 10; /* eip */ + ts = x86_THREAD_STATE32; + ts_count = x86_THREAD_STATE32_COUNT; + break; + case CPU_TYPE_POWERPC: + ireg = 0; /* srr0 */ + ts = PPC_THREAD_STATE; + ts_count = PPC_THREAD_STATE_COUNT; + break; + } + + emit32(LC_UNIXTHREAD); /* command */ + emit32(sz_thread_command); /* size of command */ + emit32(ts); /* thread state */ + emit32(ts_count); /* thread state count */ + for (i = 0; i < ts_count; i++) { + if (i == ireg) + emit32(entry); + else + emit32(0); + } +} + + +int main(int argc, char *argv[]) +{ + uint32_t len2, len3, mach_base, pad, sz_bf_entry, sz_load_cmds; + int cpu_subtype, mflag = 0; + + /* General housecleaning and setup. */ + output = stdout; + program = argv[0]; + + /* Read in and process any flags. */ + while ((argc > 1) && (argv[1][0] == '-')) { + switch (argv[1][1]) { + case 'm': /* machine cpu type */ + mflag = 1; + cpu_type = atoi(&argv[1][2]); + break; + case 'h': /* help */ + default: + usage(); + } + + argv++; + argc--; + } + + if (!mflag) + usage(); + + /* Check cpu type. */ + switch (cpu_type) { + case CPU_TYPE_X86: + bigendian = 0; + cpu_subtype = CPU_SUBTYPE_X86_ALL; + sz_thread_command = 4 * x86_THREAD_STATE32_COUNT; + break; + case CPU_TYPE_POWERPC: + bigendian = 1; + cpu_subtype = CPU_SUBTYPE_POWERPC_ALL; + sz_thread_command = 4 * PPC_THREAD_STATE_COUNT; + break; + default: + /* Can't emit LC_UNIXTHREAD for unknown cpu. */ + fatal("unknown cpu type -m%d", cpu_type); + } + sz_thread_command += SZ_THREAD_COMMAND_BF_STATE; + + /* Process the rest of the arguments. */ + switch (argc) { + case 1: /* No parameters --- read from stdin, write to stdout. */ + rd_fdopen(0); + break; + + case 3: /* Both input and output files specified. */ + output = fopen(argv[2], "w"); + if (!output) + fatal("unable to open output file."); + outputfile = argv[2]; + /* FALLTHROUGH */ + + case 2: /* Input file specified. */ + if (! rd_open(argv[1])) + fatal("unable to open input file."); + break; + + default: + usage(); + } + + rd_ohead(&outhead); + if (BADMAGIC(outhead)) + fatal("Not an ack object file."); + if (outhead.oh_flags & HF_LINK) + fatal("Contains unresolved references."); + if (outhead.oh_nrelo > 0) + fprintf(stderr, "Warning: relocation information present."); + if (outhead.oh_nsect != NUM_SEGMENTS && + outhead.oh_nsect != NUM_SEGMENTS + 1 ) { + fatal("Input file must have %d sections, not %ld\n", + NUM_SEGMENTS, (long)outhead.oh_nsect); + } + + rd_sect(outsect, outhead.oh_nsect); + + /* + * 1st Mach segment: __PAGEZERO + * 2nd Mach segment: __TEXT + * Mach headers and load commands + * ack TEXT + * ack ROM + * 3rd Mach segment: __DATA + * ack DATA + * ack BSS + */ + + /* Find entry point and check that TEXT begins there. */ + mach_base = pg_trunc(outsect[TEXT].os_base); + sz_load_cmds = 3 * SZ_SEGMENT_COMMAND + sz_thread_command; + sz_bf_entry = SZ_MACH_HEADER + sz_load_cmds; + entry = mach_base + sz_bf_entry; + if (entry != outsect[TEXT].os_base) { + fatal("text segment must have base 0x%lx, not 0x%lx\n", + entry, outsect[TEXT].os_base); + } + + /* Check that ROM can follow TEXT in 2nd Mach segment. */ + outsect[TEXT].os_size = + align(outsect[TEXT].os_size, outsect[ROM].os_lign); + if (outsect[ROM].os_base != + outsect[TEXT].os_base + outsect[TEXT].os_size) + fatal("the rom segment must follow the text segment."); + + /* + * Insert padding between ROM and DATA, such that + * pg_mod(len2) == pg_mod(outsect[DATA].os_base) + * + * This will allow us to map the 3rd Mach segment at the + * beginning of a page, such that DATA is at its base. + */ + len2 = sz_bf_entry + outsect[TEXT].os_size + outsect[ROM].os_size; + pad = pg_mod(outsect[DATA].os_base - len2); + outsect[ROM].os_size += pad; + len2 = pg_trunc(len2 + pad); + + /* Check that BSS can follow DATA in 3rd Mach segment. */ + if (outsect[BSS].os_flen != 0) + fatal("the bss space contains initialized data."); + if (outsect[BSS].os_base < + outsect[DATA].os_base + outsect[DATA].os_size) + fatal("the bss segment must follow the data segment."); + + len3 = outsect[BSS].os_base - pg_trunc(outsect[DATA].os_base) + + outsect[BSS].os_size; + + if (outhead.oh_nsect == NUM_SEGMENTS + 1) { + if (outsect[NUM_SEGMENTS].os_base != + outsect[BSS].os_base + outsect[BSS].os_size) + fatal("end segment must follow bss"); + if (outsect[NUM_SEGMENTS].os_size != 0) + fatal("end segment must be empty"); + } + + /* Emit the Mach header. */ + emit32(MH_MAGIC); /* magic */ + emit32(cpu_type); /* cpu type */ + emit32(cpu_subtype); /* cpu subtype */ + emit32(MH_EXECUTE); /* file type */ + emit32(4); /* number of load commands */ + emit32(sz_load_cmds); /* size of load commands */ + emit32(0); /* flags */ + + /* vm address: vm size: + * 1st Mach segment: NULL CV_PGSZ + * 2nd Mach segment: mach_base len2 + * 3rd Mach segment: mach_base+len2 len3 + * + * file offset: file size: + * 2nd Mach segment: 0 len2 + * 3rd Mach segment: len2 DATA os_size + */ + emit_lc_segment("__PAGEZERO", 0 /* NULL */, CV_PGSZ, + 0, 0, VM_PROT_NONE); + emit_lc_segment("__TEXT", mach_base, len2, + 0, len2, VM_PROT_READ | VM_PROT_EXECUTE); + emit_lc_segment("__DATA", mach_base + len2, len3, + len2, outsect[DATA].os_size, VM_PROT_READ | VM_PROT_WRITE); + emit_lc_unixthread(); + + /* Emit non-empty sections. */ + emit_section(TEXT); + emit_section(ROM); + emit_section(DATA); + + if (ferror(output)) + fatal("write error"); + + return 0; +} diff --git a/plat/osx/include/ack/config.h b/plat/osx/include/ack/config.h new file mode 100644 index 000000000..af4a90ed2 --- /dev/null +++ b/plat/osx/include/ack/config.h @@ -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 diff --git a/plat/osx/include/sys/mman.h b/plat/osx/include/sys/mman.h new file mode 100644 index 000000000..5a844c4b6 --- /dev/null +++ b/plat/osx/include/sys/mman.h @@ -0,0 +1,20 @@ +#ifndef _SYS_MMAN_H +#define _SYS_MMAN_H + +#include + +#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 diff --git a/plat/osx/include/sys/types.h b/plat/osx/include/sys/types.h new file mode 100644 index 000000000..a9fb63277 --- /dev/null +++ b/plat/osx/include/sys/types.h @@ -0,0 +1,9 @@ +#ifndef _SYS_TYPES_H +#define _SYS_TYPES_H + +#include /* for off_t, ptrdiff_t, size_t */ + +typedef int pid_t; +typedef ptrdiff_t ssize_t; + +#endif diff --git a/plat/osx/include/unistd.h b/plat/osx/include/unistd.h new file mode 100644 index 000000000..24eaf4e54 --- /dev/null +++ b/plat/osx/include/unistd.h @@ -0,0 +1,132 @@ +#ifndef _UNISTD_H +#define _UNISTD_H + +#include + +/* + * 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 */ +typedef long _libsys_time_t; +typedef int suseconds_t; + +struct timeval { + _libsys_time_t tv_sec; + suseconds_t tv_usec; +}; + +struct timezone { + int tz_minuteswest; + int tz_dsttime; +}; + +int gettimeofday(struct timeval *, struct timezone *); + +/* XXX - end sys/time.h */ + +/* XXX - begin fcntl.h */ + +/* flags for open() */ +#define O_RDONLY 0x0000 +#define O_WRONLY 0x0001 +#define O_RDWR 0x0002 +#define O_NONBLOCK 0x0004 +#define O_APPEND 0x0008 +#define O_CREAT 0x0200 +#define O_TRUNC 0x0400 +#define O_EXCL 0x0800 + +typedef int mode_t; + +int creat(const char *, mode_t); +int open(const char *, int, ...); + +/* XXX - end fcntl.h */ + +/* XXX - begin signal.h */ + +#define SIGHUP 1 +#define SIGINT 2 +#define SIGQUIT 3 +#define SIGILL 4 +#define SIGTRAP 5 +#define SIGABRT 6 +#define SIGEMT 7 +#define SIGFPE 8 +#define SIGKILL 9 +#define SIGBUS 10 +#define SIGSEGV 11 +#define SIGSYS 12 +#define SIGPIPE 13 +#define SIGALRM 14 +#define SIGTERM 15 +#define SIGURG 16 +#define SIGSTOP 17 +#define SIGTSTP 18 +#define SIGCONT 19 +#define SIGCHLD 20 +#define SIGTTIN 21 +#define SIGTTOU 22 +#define SIGIO 23 +#define SIGXCPU 24 +#define SIGXFSZ 25 +#define SIGVTALRM 26 +#define SIGPROF 27 +#define SIGWINCH 28 +#define SIGINFO 29 +#define SIGUSR1 30 +#define SIGUSR2 31 +#define _NSIG 32 + +/* sa_flags */ +#define SA_RESTART 0x0002 + +typedef void (*sig_t)(int); +#define SIG_DFL ((sig_t)0) +#define SIG_IGN ((sig_t)1) +#define SIG_ERR ((sig_t)-1) + +typedef unsigned int sigset_t; + +struct __siginfo; + +struct sigaction { + union { + void (*__sa_handler)(int); + void (*__sa_sigaction)(int, struct __siginfo *, void *); + } __sigaction_u; + sigset_t sa_mask; + int sa_flags; +}; +#define sa_handler __sigaction_u.__sa_handler +#define sa_sigaction __sigaction_u.__sa_sigaction + +int kill(pid_t, int); +int sigaction(int, const struct sigaction *, struct sigaction *); +sig_t signal(int, sig_t); + +/* XXX - end signal.h */ + +void _exit(int); +int brk(void *); +int close(int); +pid_t getpid(void); +int isatty(int); +off_t lseek(int, off_t, int); +ssize_t read(int, void *, size_t); +void *sbrk(int); +ssize_t write(int, const void *, size_t); + +#endif diff --git a/plat/osx/libsys/brk.c b/plat/osx/libsys/brk.c new file mode 100644 index 000000000..a732cac1c --- /dev/null +++ b/plat/osx/libsys/brk.c @@ -0,0 +1,95 @@ +/* + * This emulates brk() and sbrk() using mmap() and mprotect(). + * + * We reserve exactly SEGMENTSZ bytes of address space by calling + * mmap() with PROT_NONE. Then we allocate pages in our segment by + * calling mprotect() with PROT_READ|PROT_WRITE. + * + * This emulation can't resize its segment. If SEGMENTSZ is too big, + * then programs might run out of address space for other mappings. + */ +#include +#include +#include + +/* + * PAGESZ must be correct for this system! + * SEGMENTSZ must be a multiple of PAGESZ. + */ +#define PAGESZ 0x1000 /* page size for i386, powerpc */ +#define SEGMENTSZ 0x20000000 + +static char *segment; +static char *cbreak; /* current break */ + +static void brk_init(void) +{ + /* + * Try exactly once to reserve our segment. If we fail, then + * segment == MAP_FAILED and we never try again. + */ + if (segment == NULL) { + segment = mmap(NULL, SEGMENTSZ, PROT_NONE, + MAP_PRIVATE|MAP_ANON, -1, 0); + cbreak = segment; + } +} + +static int brk1(char *nbreak) +{ + size_t sz; + char *new, *old; + + sz = (segment == MAP_FAILED) ? 0 : SEGMENTSZ; + if (nbreak < segment || nbreak > segment + sz) { + errno = ENOMEM; + return -1; + } + + /* Round up to page size. */ + old = (char *)(((size_t)cbreak + (PAGESZ-1)) & ~(PAGESZ-1)); + new = (char *)(((size_t)nbreak + (PAGESZ-1)) & ~(PAGESZ-1)); + + if (new > old) { + /* Allocate pages by unprotecting them. */ + if (mprotect(old, new - old, PROT_READ|PROT_WRITE) < 0) { + errno = ENOMEM; + return -1; + } + } else if (new < old) { + /* + * Free pages by using MAP_FIXED to replace the + * mapping. Ignore errors. + */ + mmap(new, old - new, PROT_NONE, + MAP_PRIVATE|MAP_ANON|MAP_FIXED, -1, 0); + } + cbreak = nbreak; + return 0; +} + +int brk(void *addr) +{ + brk_init(); + return brk1(addr); +} + +void *sbrk(int incr) +{ + char *base, *nbreak; + + brk_init(); + base = cbreak; + nbreak = base + incr; + + /* Did base + incr overflow? */ + if ((incr < 0 && nbreak > base) || + (incr > 0 && nbreak < base)) { + errno = ENOMEM; + return (void*)-1; + } + + if (brk1(nbreak) < 0) + return (void*)-1; + return base; +} diff --git a/plat/osx/libsys/creat.c b/plat/osx/libsys/creat.c new file mode 100644 index 000000000..df2c82275 --- /dev/null +++ b/plat/osx/libsys/creat.c @@ -0,0 +1,6 @@ +#include + +int creat(const char *path, mode_t mode) +{ + open(path, O_CREAT | O_TRUNC | O_WRONLY, mode); +} diff --git a/plat/osx/libsys/isatty.c b/plat/osx/libsys/isatty.c new file mode 100644 index 000000000..1da6509df --- /dev/null +++ b/plat/osx/libsys/isatty.c @@ -0,0 +1,7 @@ +#include + +int isatty(int fd) +{ + int line_disc; + return 0 <= ioctl(fd, TIOCGETD, &line_disc); +} diff --git a/plat/osx/libsys/signal.c b/plat/osx/libsys/signal.c new file mode 100644 index 000000000..0c1e12624 --- /dev/null +++ b/plat/osx/libsys/signal.c @@ -0,0 +1,16 @@ +#include + +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; +} diff --git a/plat/osx386/boot.s b/plat/osx386/boot.s new file mode 100644 index 000000000..0db4bc715 --- /dev/null +++ b/plat/osx386/boot.s @@ -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 diff --git a/plat/osx386/build-pkg.lua b/plat/osx386/build-pkg.lua new file mode 100644 index 000000000..8c129c8e7 --- /dev/null +++ b/plat/osx386/build-pkg.lua @@ -0,0 +1,24 @@ +include("plat/build.lua") + +ackfile { + name = "boot", + srcs = { "./boot.s" }, + vars = { plat = "osx386" } +} + +build_plat_libs { + name = "libs", + arch = "i386", + plat = "osx386", +} + +installable { + name = "pkg", + map = { + "+tools", + "+libs", + "./include+pkg", + ["$(PLATIND)/osx386/boot.o"] = "+boot", + ["$(PLATIND)/osx386/libsys.a"] = "./libsys+lib", + } +} diff --git a/plat/osx386/build-tools.lua b/plat/osx386/build-tools.lua new file mode 100644 index 000000000..097cb94d3 --- /dev/null +++ b/plat/osx386/build-tools.lua @@ -0,0 +1,9 @@ +return installable { + name = "tools", + map = { + ["$(PLATIND)/descr/osx386"] = "./descr", + "plat/linux386+tools", + "plat/osx/cvmach+pkg", + "util/opt+pkg", + } +} diff --git a/plat/osx386/descr b/plat/osx386/descr new file mode 100644 index 000000000..f1ba978ef --- /dev/null +++ b/plat/osx386/descr @@ -0,0 +1,80 @@ +# plat/osx386/descr + +var w=4 +var wa=4 +var p={w} +var pa={w} +var s=2 +var sa={s} +var l={w} +var la={w} +var f={w} +var fa={w} +var d=8 +var da={d} +var x=8 +var xa={x} +var ARCH=i386 +var PLATFORM=osx386 +var PLATFORMDIR={EM}/share/ack/{PLATFORM} +var CPP_F=-D__unix +var ALIGN=-a0:4 -a1:4 -a2:4096 -a3:4 -b0:0x1114 +var C_LIB={PLATFORMDIR}/libc-ansi.a +# bitfields reversed for compatibility with (g)cc. +var CC_ALIGN=-Vr +var OLD_C_LIB={C_LIB} +var MACHOPT_F=-m10 +var EGO_PLAT_FLAGS=-M{EM}/share/ack/ego/{ARCH}.descr + +# Override the setting in fe so that files compiled for osx386 can see +# the platform-specific headers. + +var C_INCLUDES=-I{PLATFORMDIR}/include -I{EM}/share/ack/include/ansi + +name be + from .m.g + to .s + program {EM}/lib/ack/linux386/ncg + mapflag -gdb GF=-gdb + args {GF?} < + stdout + need .e +end +name as + from .s.so + to .o + program {EM}/lib/ack/linux386/as + args - -o > < + prep cond +end +name led + from .o.a + to .out + program {EM}/lib/ack/em_led + mapflag -l* LNAME={PLATFORMDIR}/lib* + mapflag -fp FLOATS={EM}/{LIB}fp + args {ALIGN} {SEPID?} \ + (.e:{HEAD}={PLATFORMDIR}/boot.o) \ + ({RTS}:.ocm.b={PLATFORMDIR}/c-ansi.o) \ + ({RTS}:.c={PLATFORMDIR}/c-ansi.o) \ + ({RTS}:.mod={PLATFORMDIR}/modula2.o) \ + ({RTS}:.p={PLATFORMDIR}/pascal.o) \ + -o > < \ + (.p:{TAIL}={PLATFORMDIR}/libpascal.a) \ + (.b:{TAIL}={PLATFORMDIR}/libbasic.a) \ + (.mod:{TAIL}={PLATFORMDIR}/libmodula2.a) \ + (.ocm:{TAIL}={PLATFORMDIR}/liboccam.a) \ + (.ocm.b.mod.c.p:{TAIL}={PLATFORMDIR}/libc.a) \ + {FLOATS?} \ + (.e:{TAIL}={PLATFORMDIR}/libem.a \ + {PLATFORMDIR}/libsys.a \ + {PLATFORMDIR}/libend.a) + linker +end +name cv + from .out + to .exe + program {EM}/lib/ack/cvmach + args -m7 < > + outfile osx386.exe +end diff --git a/plat/osx386/include/build.lua b/plat/osx386/include/build.lua new file mode 100644 index 000000000..420518f66 --- /dev/null +++ b/plat/osx386/include/build.lua @@ -0,0 +1,24 @@ +include("plat/build.lua") + +headermap = {} +packagemap = {} + +local function addheader(h) + headermap[h] = "plat/osx/include/"..h + packagemap["$(PLATIND)/osx386/include/"..h] = "plat/osx/include/"..h +end + +addheader("ack/config.h") +addheader("sys/mman.h") +addheader("sys/types.h") +addheader("unistd.h") + +acklibrary { + name = "headers", + hdrs = headermap +} + +installable { + name = "pkg", + map = packagemap +} diff --git a/plat/osx386/libsys/_exit.s b/plat/osx386/libsys/_exit.s new file mode 100644 index 000000000..80d30134b --- /dev/null +++ b/plat/osx386/libsys/_exit.s @@ -0,0 +1,5 @@ +.sect .text +.define __exit +__exit: + mov eax, 1 + int 0x80 diff --git a/plat/osx386/libsys/build.lua b/plat/osx386/libsys/build.lua new file mode 100644 index 000000000..a5356ee6c --- /dev/null +++ b/plat/osx386/libsys/build.lua @@ -0,0 +1,31 @@ +acklibrary { + name = "lib", + srcs = { + "./_exit.s", + "./close.s", + "./getpid.s", + "./gettimeofday.s", + "./ioctl.s", + "./kill.s", + "./lseek.s", + "./mmap.s", + "./mprotect.s", + "./open.s", + "./read.s", + "./set_errno.s", + "./sigaction.s", + "./write.s", + "plat/linux/libsys/errno.s", + "plat/osx/libsys/brk.c", + "plat/osx/libsys/creat.c", + "plat/osx/libsys/isatty.c", + "plat/osx/libsys/signal.c", + }, + deps = { + "lang/cem/libcc.ansi/headers+headers", + "plat/osx386/include+headers", + }, + vars = { + plat = "osx386" + } +} diff --git a/plat/osx386/libsys/close.s b/plat/osx386/libsys/close.s new file mode 100644 index 000000000..295b90ad1 --- /dev/null +++ b/plat/osx386/libsys/close.s @@ -0,0 +1,7 @@ +.sect .text +.define _close +_close: + mov eax, 6 + int 0x80 + jb .set_errno + ret diff --git a/plat/osx386/libsys/getpid.s b/plat/osx386/libsys/getpid.s new file mode 100644 index 000000000..150791bb4 --- /dev/null +++ b/plat/osx386/libsys/getpid.s @@ -0,0 +1,7 @@ +.sect .text +.define _getpid +_getpid: + mov eax, 20 + int 0x80 + jb .set_errno + ret diff --git a/plat/osx386/libsys/gettimeofday.s b/plat/osx386/libsys/gettimeofday.s new file mode 100644 index 000000000..3a4c2229f --- /dev/null +++ b/plat/osx386/libsys/gettimeofday.s @@ -0,0 +1,7 @@ +.sect .text +.define _gettimeofday +_gettimeofday: + mov eax, 116 + int 0x80 + jb .set_errno + ret diff --git a/plat/osx386/libsys/ioctl.s b/plat/osx386/libsys/ioctl.s new file mode 100644 index 000000000..5b13e2cfb --- /dev/null +++ b/plat/osx386/libsys/ioctl.s @@ -0,0 +1,7 @@ +.sect .text +.define _ioctl +_ioctl: + mov eax, 54 + int 0x80 + jb .set_errno + ret diff --git a/plat/osx386/libsys/kill.s b/plat/osx386/libsys/kill.s new file mode 100644 index 000000000..8fdce95fd --- /dev/null +++ b/plat/osx386/libsys/kill.s @@ -0,0 +1,7 @@ +.sect .text +.define _kill +_kill: + mov eax, 37 + int 0x80 + jb .set_errno + ret diff --git a/plat/osx386/libsys/lseek.s b/plat/osx386/libsys/lseek.s new file mode 100644 index 000000000..22543b2eb --- /dev/null +++ b/plat/osx386/libsys/lseek.s @@ -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 diff --git a/plat/osx386/libsys/mmap.s b/plat/osx386/libsys/mmap.s new file mode 100644 index 000000000..e39ea777a --- /dev/null +++ b/plat/osx386/libsys/mmap.s @@ -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 diff --git a/plat/osx386/libsys/mprotect.s b/plat/osx386/libsys/mprotect.s new file mode 100644 index 000000000..641173a16 --- /dev/null +++ b/plat/osx386/libsys/mprotect.s @@ -0,0 +1,7 @@ +.sect .text +.define _mprotect +_mprotect: + mov eax, 74 + int 0x80 + jb .set_errno + ret diff --git a/plat/osx386/libsys/open.s b/plat/osx386/libsys/open.s new file mode 100644 index 000000000..154c00506 --- /dev/null +++ b/plat/osx386/libsys/open.s @@ -0,0 +1,7 @@ +.sect .text +.define _open +_open: + mov eax, 5 + int 0x80 + jb .set_errno + ret diff --git a/plat/osx386/libsys/read.s b/plat/osx386/libsys/read.s new file mode 100644 index 000000000..ccd3f8162 --- /dev/null +++ b/plat/osx386/libsys/read.s @@ -0,0 +1,7 @@ +.sect .text +.define _read +_read: + mov eax, 3 + int 0x80 + jb .set_errno + ret diff --git a/plat/osx386/libsys/set_errno.s b/plat/osx386/libsys/set_errno.s new file mode 100644 index 000000000..ff0823483 --- /dev/null +++ b/plat/osx386/libsys/set_errno.s @@ -0,0 +1,6 @@ +.sect .text +.define .set_errno +.set_errno: + mov (_errno), eax + mov eax, -1 + ret diff --git a/plat/osx386/libsys/sigaction.s b/plat/osx386/libsys/sigaction.s new file mode 100644 index 000000000..2909cbe02 --- /dev/null +++ b/plat/osx386/libsys/sigaction.s @@ -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 diff --git a/plat/osx386/libsys/write.s b/plat/osx386/libsys/write.s new file mode 100644 index 000000000..a32d4d78a --- /dev/null +++ b/plat/osx386/libsys/write.s @@ -0,0 +1,7 @@ +.sect .text +.define _write +_write: + mov eax, 4 + int 0x80 + jb .set_errno + ret diff --git a/plat/osxppc/boot.s b/plat/osxppc/boot.s new file mode 100644 index 000000000..a1ee67166 --- /dev/null +++ b/plat/osxppc/boot.s @@ -0,0 +1,60 @@ +! boot.s for osx386 + +! Declare segments (the order is important). + +.sect .text +.sect .rom +.sect .data +.sect .bss + +.sect .text + +begtext: + ! This code is placed at the entry point of the Mach-o + ! executable and is the first thing that runs. + ! + ! On entry, the stack looks like this: + ! + ! sp+... NULL + ! sp+8+(4*argc) env (X quads) + ! sp+4+(4*argc) NULL + ! sp+4 argv (argc quads) + ! sp argc + ! + ! The ACK actually expects: + ! + ! sp+8 argc + ! sp+4 ptr to argv + ! sp ptr to env + + lwz r3, 0(sp) ! r3 = argc + addi r4, sp, 4 ! r4 = argv + rlwinm r5, r3, 32-2, 2, 31 ! shift left 2 bits + add r5, r5, r4 + addi r5, r5, 8 ! r5 = env + + stwu r5, -4(sp) + stwu r4, -4(sp) + stwu r3, -4(sp) + + b __m_a_i_n + +.sect rom +begrom: + +.sect .data +begdata: + +! Some magic data. All EM systems need these. + +.sect .bss +begbss: +.define hol0 +.comm hol0, 8 ! line number and filename (for debugging) + +.define _errno +.comm _errno, 4 ! Posix errno storage + +.define .trppc, .ignmask +.comm .trppc, 4 ! ptr to user trap handler +.comm .ignmask, 4 ! user trap ignore mask diff --git a/plat/osxppc/build-pkg.lua b/plat/osxppc/build-pkg.lua new file mode 100644 index 000000000..d6f6d5558 --- /dev/null +++ b/plat/osxppc/build-pkg.lua @@ -0,0 +1,24 @@ +include("plat/build.lua") + +ackfile { + name = "boot", + srcs = { "./boot.s" }, + vars = { plat = "osxppc" } +} + +build_plat_libs { + name = "libs", + arch = "powerpc", + plat = "osxppc", +} + +installable { + name = "pkg", + map = { + "+tools", + "+libs", + "./include+pkg", + ["$(PLATIND)/osxppc/boot.o"] = "+boot", + ["$(PLATIND)/osxppc/libsys.a"] = "./libsys+lib", + } +} diff --git a/plat/osxppc/build-tools.lua b/plat/osxppc/build-tools.lua new file mode 100644 index 000000000..d19d25e19 --- /dev/null +++ b/plat/osxppc/build-tools.lua @@ -0,0 +1,9 @@ +return installable { + name = "tools", + map = { + ["$(PLATIND)/descr/osxppc"] = "./descr", + "plat/linuxppc+tools", + "plat/osx/cvmach+pkg", + "util/opt+pkg", + } +} diff --git a/plat/osxppc/descr b/plat/osxppc/descr new file mode 100644 index 000000000..3ee01752d --- /dev/null +++ b/plat/osxppc/descr @@ -0,0 +1,81 @@ +# plat/osxppc/descr + +var w=4 +var wa=4 +var p={w} +var pa={w} +var s=2 +var sa={s} +var l={w} +var la={w} +var f={w} +var fa={w} +var d=8 +var da={d} +var x=8 +var xa={x} +var ARCH=powerpc +var PLATFORM=osxppc +var PLATFORMDIR={EM}/share/ack/{PLATFORM} +var CPP_F=-D__unix +var ALIGN=-a0:4 -a1:4 -a2:4096 -a3:4 -b0:0x1174 +var C_LIB={PLATFORMDIR}/libc-ansi.a +# bitfields reversed for compatibility with (g)cc. +# XXX this is from linux386, might be wrong for osxppc +var CC_ALIGN=-Vr +var OLD_C_LIB={C_LIB} +var MACHOPT_F=-m10 +# var EGO_PLAT_FLAGS=-M{EM}/share/ack/ego/{ARCH}.descr + +# Override the setting in fe so that files compiled for osxppc can see +# the platform-specific headers. + +var C_INCLUDES=-I{PLATFORMDIR}/include -I{EM}/share/ack/include/ansi + +name be + from .m.g + to .s + program {EM}/lib/ack/linuxppc/ncg + mapflag -gdb GF=-gdb + args {GF?} < + stdout + need .e +end +name as + from .s.so + to .o + program {EM}/lib/ack/linuxppc/as + args - -o > < + prep cond +end +name led + from .o.a + to .out + program {EM}/lib/ack/em_led + mapflag -l* LNAME={PLATFORMDIR}/lib* + mapflag -fp FLOATS={EM}/{LIB}fp + args {ALIGN} {SEPID?} \ + (.e:{HEAD}={PLATFORMDIR}/boot.o) \ + ({RTS}:.ocm.b={PLATFORMDIR}/c-ansi.o) \ + ({RTS}:.c={PLATFORMDIR}/c-ansi.o) \ + ({RTS}:.mod={PLATFORMDIR}/modula2.o) \ + ({RTS}:.p={PLATFORMDIR}/pascal.o) \ + -o > < \ + (.p:{TAIL}={PLATFORMDIR}/libpascal.a) \ + (.b:{TAIL}={PLATFORMDIR}/libbasic.a) \ + (.mod:{TAIL}={PLATFORMDIR}/libmodula2.a) \ + (.ocm:{TAIL}={PLATFORMDIR}/liboccam.a) \ + (.ocm.b.mod.c.p:{TAIL}={PLATFORMDIR}/libc.a) \ + {FLOATS?} \ + (.e:{TAIL}={PLATFORMDIR}/libem.a \ + {PLATFORMDIR}/libsys.a \ + {PLATFORMDIR}/libend.a) + linker +end +name cv + from .out + to .exe + program {EM}/lib/ack/cvmach + args -m18 < > + outfile osxppc.exe +end diff --git a/plat/osxppc/include/build.lua b/plat/osxppc/include/build.lua new file mode 100644 index 000000000..375c99535 --- /dev/null +++ b/plat/osxppc/include/build.lua @@ -0,0 +1,24 @@ +include("plat/build.lua") + +headermap = {} +packagemap = {} + +local function addheader(h) + headermap[h] = "plat/osx/include/"..h + packagemap["$(PLATIND)/osxppc/include/"..h] = "plat/osx/include/"..h +end + +addheader("ack/config.h") +addheader("sys/mman.h") +addheader("sys/types.h") +addheader("unistd.h") + +acklibrary { + name = "headers", + hdrs = headermap +} + +installable { + name = "pkg", + map = packagemap +} diff --git a/plat/osxppc/libsys/_exit.s b/plat/osxppc/libsys/_exit.s new file mode 100644 index 000000000..6ffe502d5 --- /dev/null +++ b/plat/osxppc/libsys/_exit.s @@ -0,0 +1,6 @@ +.sect .text +.define __exit +__exit: + addi r0, r0, 1 ! _exit + lwz r3, 0(sp) ! status + sc 0 diff --git a/plat/osxppc/libsys/build.lua b/plat/osxppc/libsys/build.lua new file mode 100644 index 000000000..a595ed0fa --- /dev/null +++ b/plat/osxppc/libsys/build.lua @@ -0,0 +1,31 @@ +acklibrary { + name = "lib", + srcs = { + "./_exit.s", + "./close.s", + "./getpid.s", + "./gettimeofday.s", + "./ioctl.s", + "./kill.s", + "./lseek.s", + "./mmap.s", + "./mprotect.s", + "./open.s", + "./read.s", + "./set_errno.s", + "./sigaction.s", + "./write.s", + "plat/linuxppc/libsys/trap.s", + "plat/osx/libsys/brk.c", + "plat/osx/libsys/creat.c", + "plat/osx/libsys/isatty.c", + "plat/osx/libsys/signal.c", + }, + deps = { + "lang/cem/libcc.ansi/headers+headers", + "plat/osxppc/include+headers", + }, + vars = { + plat = "osxppc" + } +} diff --git a/plat/osxppc/libsys/close.s b/plat/osxppc/libsys/close.s new file mode 100644 index 000000000..a799b5e9d --- /dev/null +++ b/plat/osxppc/libsys/close.s @@ -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 diff --git a/plat/osxppc/libsys/getpid.s b/plat/osxppc/libsys/getpid.s new file mode 100644 index 000000000..36525cf43 --- /dev/null +++ b/plat/osxppc/libsys/getpid.s @@ -0,0 +1,7 @@ +.sect .text +.define _getpid +_getpid: + addi r0, r0, 20 ! getpid + sc 0 + b .set_errno + bclr 20, 0, 0 diff --git a/plat/osxppc/libsys/gettimeofday.s b/plat/osxppc/libsys/gettimeofday.s new file mode 100644 index 000000000..c01bf5bae --- /dev/null +++ b/plat/osxppc/libsys/gettimeofday.s @@ -0,0 +1,9 @@ +.sect .text +.define _gettimeofday +_gettimeofday: + addi r0, r0, 116 ! gettimeofday + lwz r3, 0(sp) ! timeval pointer + lwz r4, 4(sp) ! timezone pointer + sc 0 + b .set_errno + bclr 20, 0, 0 diff --git a/plat/osxppc/libsys/ioctl.s b/plat/osxppc/libsys/ioctl.s new file mode 100644 index 000000000..685ba8499 --- /dev/null +++ b/plat/osxppc/libsys/ioctl.s @@ -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 diff --git a/plat/osxppc/libsys/kill.s b/plat/osxppc/libsys/kill.s new file mode 100644 index 000000000..4c7d5566f --- /dev/null +++ b/plat/osxppc/libsys/kill.s @@ -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 diff --git a/plat/osxppc/libsys/lseek.s b/plat/osxppc/libsys/lseek.s new file mode 100644 index 000000000..129b08a8d --- /dev/null +++ b/plat/osxppc/libsys/lseek.s @@ -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 diff --git a/plat/osxppc/libsys/mmap.s b/plat/osxppc/libsys/mmap.s new file mode 100644 index 000000000..f2ec5e28b --- /dev/null +++ b/plat/osxppc/libsys/mmap.s @@ -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 diff --git a/plat/osxppc/libsys/mprotect.s b/plat/osxppc/libsys/mprotect.s new file mode 100644 index 000000000..fbea70251 --- /dev/null +++ b/plat/osxppc/libsys/mprotect.s @@ -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 diff --git a/plat/osxppc/libsys/open.s b/plat/osxppc/libsys/open.s new file mode 100644 index 000000000..1d066c7ad --- /dev/null +++ b/plat/osxppc/libsys/open.s @@ -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 diff --git a/plat/osxppc/libsys/read.s b/plat/osxppc/libsys/read.s new file mode 100644 index 000000000..849da5932 --- /dev/null +++ b/plat/osxppc/libsys/read.s @@ -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 diff --git a/plat/osxppc/libsys/set_errno.s b/plat/osxppc/libsys/set_errno.s new file mode 100644 index 000000000..e406865a6 --- /dev/null +++ b/plat/osxppc/libsys/set_errno.s @@ -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 diff --git a/plat/osxppc/libsys/sigaction.s b/plat/osxppc/libsys/sigaction.s new file mode 100644 index 000000000..f330c88a5 --- /dev/null +++ b/plat/osxppc/libsys/sigaction.s @@ -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 diff --git a/plat/osxppc/libsys/write.s b/plat/osxppc/libsys/write.s new file mode 100644 index 000000000..48f59cd72 --- /dev/null +++ b/plat/osxppc/libsys/write.s @@ -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 From 7f94e971fd5f967e5efe58cd107625f4caad1e88 Mon Sep 17 00:00:00 2001 From: George Koehler Date: Tue, 8 Nov 2016 15:22:09 -0500 Subject: [PATCH 002/173] Remove trailing whitespace in plat/osx* Also fix a comment. --- plat/osx/cvmach/cvmach.c | 10 +++++----- plat/osx/include/ack/config.h | 2 +- plat/osx386/boot.s | 14 +++++++------- plat/osxppc/boot.s | 10 +++++----- 4 files changed, 18 insertions(+), 18 deletions(-) diff --git a/plat/osx/cvmach/cvmach.c b/plat/osx/cvmach/cvmach.c index 12a48696d..f223fa6f7 100644 --- a/plat/osx/cvmach/cvmach.c +++ b/plat/osx/cvmach/cvmach.c @@ -115,13 +115,13 @@ uint32_t align(uint32_t a, uint32_t b) a += b - 1; return a & ~(b-1); } - + /* Writes out a 32-bit value in the appropriate endianness. */ void emit32(uint32_t value) { unsigned char buffer[4]; - + if (bigendian) { buffer[0] = (value >> 24) & 0xFF; @@ -136,7 +136,7 @@ void emit32(uint32_t value) buffer[1] = (value >> 8) & 0xFF; buffer[0] = (value >> 0) & 0xFF; } - + writef(buffer, 1, sizeof(buffer)); } @@ -177,7 +177,7 @@ void emit_lc_segment(char *name, uint32_t vm_ad, uint32_t vm_sz, { char namebuf[16]; int flags, maxprot; - + if (prot == VM_PROT_NONE) { /* special values for __PAGEZERO */ maxprot = VM_PROT_NONE; @@ -247,7 +247,7 @@ int main(int argc, char *argv[]) /* 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]) { diff --git a/plat/osx/include/ack/config.h b/plat/osx/include/ack/config.h index af4a90ed2..9f58a3941 100644 --- a/plat/osx/include/ack/config.h +++ b/plat/osx/include/ack/config.h @@ -8,7 +8,7 @@ /* We're providing a time() system call rather than wanting a wrapper around * gettimeofday() in the libc. */ - + /* #define ACKCONF_TIME_IS_A_SYSCALL */ #endif diff --git a/plat/osx386/boot.s b/plat/osx386/boot.s index 0db4bc715..f3ad75fd2 100644 --- a/plat/osx386/boot.s +++ b/plat/osx386/boot.s @@ -26,28 +26,28 @@ begtext: ! 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: @@ -66,4 +66,4 @@ begbss: .define .trppc, .ignmask .comm .trppc, 4 ! ptr to user trap handler -.comm .ignmask, 4 ! user trap ignore mask +.comm .ignmask, 4 ! user trap ignore mask diff --git a/plat/osxppc/boot.s b/plat/osxppc/boot.s index a1ee67166..f99e70e2d 100644 --- a/plat/osxppc/boot.s +++ b/plat/osxppc/boot.s @@ -1,4 +1,4 @@ -! boot.s for osx386 +! boot.s for osxppc ! Declare segments (the order is important). @@ -30,13 +30,13 @@ begtext: 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 + 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 @@ -57,4 +57,4 @@ begbss: .define .trppc, .ignmask .comm .trppc, 4 ! ptr to user trap handler -.comm .ignmask, 4 ! user trap ignore mask +.comm .ignmask, 4 ! user trap ignore mask From ed7fb69f7953a071c62b44e0593b101691111a44 Mon Sep 17 00:00:00 2001 From: George Koehler Date: Tue, 8 Nov 2016 15:35:02 -0500 Subject: [PATCH 003/173] Add the missing return in plat/osx/libsys/creat.c Before now, it might have worked by accident if the return value from open() stayed in the function return area. --- plat/osx/libsys/creat.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plat/osx/libsys/creat.c b/plat/osx/libsys/creat.c index df2c82275..3a350e357 100644 --- a/plat/osx/libsys/creat.c +++ b/plat/osx/libsys/creat.c @@ -2,5 +2,5 @@ int creat(const char *path, mode_t mode) { - open(path, O_CREAT | O_TRUNC | O_WRONLY, mode); + return open(path, O_CREAT | O_TRUNC | O_WRONLY, mode); } From 0d0495e818d840d89bb025415fc18e0ed9d8d4a6 Mon Sep 17 00:00:00 2001 From: George Koehler Date: Tue, 8 Nov 2016 17:13:51 -0500 Subject: [PATCH 004/173] Install only 1 copy, not 2 copies, of osx headers. Before this commit, the headers in plat/osx/include got installed twice into PLATIND/osx386/include and PLATIND/osxppc/include. This commit installs them once into PLATIND/osx/include and changes both descr files to find them. Several rules in lang/ depend on plat/osx386/include+headers or plat/osxppc/include+headers. They each become a simplerule that depends on plat/osx/include+headers. --- plat/osx/include/build.lua | 24 ++++++++++++++++++++++++ plat/osx386/build-pkg.lua | 2 +- plat/osx386/descr | 2 +- plat/osx386/include/build.lua | 27 +++++---------------------- plat/osxppc/build-pkg.lua | 2 +- plat/osxppc/descr | 2 +- plat/osxppc/include/build.lua | 27 +++++---------------------- 7 files changed, 38 insertions(+), 48 deletions(-) create mode 100644 plat/osx/include/build.lua diff --git a/plat/osx/include/build.lua b/plat/osx/include/build.lua new file mode 100644 index 000000000..7eb73f3aa --- /dev/null +++ b/plat/osx/include/build.lua @@ -0,0 +1,24 @@ +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/mman.h") +addheader("sys/types.h") +addheader("unistd.h") + +acklibrary { + name = "headers", + hdrs = headermap +} + +installable { + name = "pkg", + map = packagemap +} diff --git a/plat/osx386/build-pkg.lua b/plat/osx386/build-pkg.lua index 8c129c8e7..6dfe1561c 100644 --- a/plat/osx386/build-pkg.lua +++ b/plat/osx386/build-pkg.lua @@ -17,7 +17,7 @@ installable { map = { "+tools", "+libs", - "./include+pkg", + "plat/osx/include+pkg", ["$(PLATIND)/osx386/boot.o"] = "+boot", ["$(PLATIND)/osx386/libsys.a"] = "./libsys+lib", } diff --git a/plat/osx386/descr b/plat/osx386/descr index f1ba978ef..e404e7a34 100644 --- a/plat/osx386/descr +++ b/plat/osx386/descr @@ -29,7 +29,7 @@ var EGO_PLAT_FLAGS=-M{EM}/share/ack/ego/{ARCH}.descr # Override the setting in fe so that files compiled for osx386 can see # the platform-specific headers. -var C_INCLUDES=-I{PLATFORMDIR}/include -I{EM}/share/ack/include/ansi +var C_INCLUDES=-I{EM}/share/ack/osx/include -I{EM}/share/ack/include/ansi name be from .m.g diff --git a/plat/osx386/include/build.lua b/plat/osx386/include/build.lua index 420518f66..164e2b44a 100644 --- a/plat/osx386/include/build.lua +++ b/plat/osx386/include/build.lua @@ -1,24 +1,7 @@ -include("plat/build.lua") - -headermap = {} -packagemap = {} - -local function addheader(h) - headermap[h] = "plat/osx/include/"..h - packagemap["$(PLATIND)/osx386/include/"..h] = "plat/osx/include/"..h -end - -addheader("ack/config.h") -addheader("sys/mman.h") -addheader("sys/types.h") -addheader("unistd.h") - -acklibrary { +simplerule { name = "headers", - hdrs = headermap -} - -installable { - name = "pkg", - map = packagemap + deps = { "plat/osx/include+headers" }, + ins = {}, + outs = {}, + commands = {}, } diff --git a/plat/osxppc/build-pkg.lua b/plat/osxppc/build-pkg.lua index d6f6d5558..c94ad6ef0 100644 --- a/plat/osxppc/build-pkg.lua +++ b/plat/osxppc/build-pkg.lua @@ -17,7 +17,7 @@ installable { map = { "+tools", "+libs", - "./include+pkg", + "plat/osx/include+pkg", ["$(PLATIND)/osxppc/boot.o"] = "+boot", ["$(PLATIND)/osxppc/libsys.a"] = "./libsys+lib", } diff --git a/plat/osxppc/descr b/plat/osxppc/descr index 3ee01752d..7e8770428 100644 --- a/plat/osxppc/descr +++ b/plat/osxppc/descr @@ -30,7 +30,7 @@ var MACHOPT_F=-m10 # Override the setting in fe so that files compiled for osxppc can see # the platform-specific headers. -var C_INCLUDES=-I{PLATFORMDIR}/include -I{EM}/share/ack/include/ansi +var C_INCLUDES=-I{EM}/share/ack/osx/include -I{EM}/share/ack/include/ansi name be from .m.g diff --git a/plat/osxppc/include/build.lua b/plat/osxppc/include/build.lua index 375c99535..164e2b44a 100644 --- a/plat/osxppc/include/build.lua +++ b/plat/osxppc/include/build.lua @@ -1,24 +1,7 @@ -include("plat/build.lua") - -headermap = {} -packagemap = {} - -local function addheader(h) - headermap[h] = "plat/osx/include/"..h - packagemap["$(PLATIND)/osxppc/include/"..h] = "plat/osx/include/"..h -end - -addheader("ack/config.h") -addheader("sys/mman.h") -addheader("sys/types.h") -addheader("unistd.h") - -acklibrary { +simplerule { name = "headers", - hdrs = headermap -} - -installable { - name = "pkg", - map = packagemap + deps = { "plat/osx/include+headers" }, + ins = {}, + outs = {}, + commands = {}, } From 7347cc64e47415f9212c1dfb9c0fe9b86e981104 Mon Sep 17 00:00:00 2001 From: George Koehler Date: Fri, 11 Nov 2016 17:05:50 -0500 Subject: [PATCH 005/173] Pass DEFAULT_PLATFORM to ackbuilder so util/ack sees it. --- Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/Makefile b/Makefile index 635650bc4..febd87aff 100644 --- a/Makefile +++ b/Makefile @@ -88,6 +88,7 @@ $(BUILDDIR)/build.$(BUILDSYSTEM): first/ackbuilder.lua Makefile $(BUILD_FILES) $ @$(LUA) first/ackbuilder.lua \ first/build.lua build.lua \ --$(BUILDSYSTEM) \ + DEFAULT_PLATFORM=$(DEFAULT_PLATFORM) \ OBJDIR=$(OBJDIR) \ BINDIR=$(BINDIR) \ LIBDIR=$(LIBDIR) \ From 7b3f870f6385f60b9cae18241b3ae058f890b986 Mon Sep 17 00:00:00 2001 From: George Koehler Date: Fri, 11 Nov 2016 17:06:25 -0500 Subject: [PATCH 006/173] Don't build mktables.c in the ack binary. It only worked by accident because main() in main.c was found before main() in mktables.c. Also add build dependencies on the local *.h files. --- util/ack/build.lua | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/util/ack/build.lua b/util/ack/build.lua index 4394484b4..cb9b66fd4 100644 --- a/util/ack/build.lua +++ b/util/ack/build.lua @@ -18,12 +18,28 @@ normalrule { cprogram { name = "ack", srcs = { - "./*.c", + "./data.c", + "./files.c", + "./grows.c", + "./list.c", + "./main.c", + "./rmach.c", + "./run.c", + "./scan.c", + "./svars.c", + "./trans.c", + "./util.c", "+tables", }, deps = { "h+emheaders", "h+local", + "./ack.h", + "./data.h", + "./dmach.h", + "./grows.h", + "./list.h", + "./trans.h", } } From 65278bc9a9ffe8a924c616765afea3bf4e3728d5 Mon Sep 17 00:00:00 2001 From: George Koehler Date: Sat, 12 Nov 2016 21:12:45 -0500 Subject: [PATCH 007/173] In util/ack, add prototypes and static to functions. Declare most functions before using them. I declare some functions in ack.h and some in trans.h (because trans.h declares type trf). I leave declarations of scanb() and scanvars() in .c files because they need type growstring. (I can't #include "grows.h" in another header file as long as grows.h doesn't guard against multiple inclusion.) Functions used within one file become static. I remove a few tiny functions. I move a few functions or declarations to more convenient places. Some functions now return void instead of a garbage int. I feel that keyword "register" is obsolete, so I removed it from where I was editing. This commit doesn't touch mktables.c --- util/ack/ack.h | 41 +++++++++++++------- util/ack/data.h | 2 +- util/ack/files.c | 39 ++++++++++--------- util/ack/grows.c | 13 +++---- util/ack/grows.h | 10 ++--- util/ack/list.c | 6 +-- util/ack/list.h | 4 ++ util/ack/main.c | 65 ++++++++++++++++++-------------- util/ack/rmach.c | 38 +++++++++---------- util/ack/run.c | 16 +++++--- util/ack/scan.c | 22 ++++++----- util/ack/svars.c | 13 +++---- util/ack/trans.c | 98 ++++++++++++++++++++---------------------------- util/ack/trans.h | 23 ++++++++++++ util/ack/util.c | 48 ++++++++---------------- 15 files changed, 230 insertions(+), 208 deletions(-) diff --git a/util/ack/ack.h b/util/ack/ack.h index 0877a8c0d..bbf3da58d 100644 --- a/util/ack/ack.h +++ b/util/ack/ack.h @@ -6,6 +6,8 @@ #define RCS_ACK "$Id$" #endif +#include /* size_t, free() */ + /****************************************************************************/ /* User settable options */ /****************************************************************************/ @@ -61,20 +63,33 @@ typedef struct { #define p_cont(elem) ((path *)l_content(elem)) -/* Return values of setpath() */ -enum f_path { F_OK, F_NOMATCH, F_NOPATH } ; - /* Own routines */ -enum f_path getpath(); -enum f_path scan_end(); -extern void noodstop(); -extern char *getvar(); -extern char *keeps(); -extern char *basename(); -extern char *skipblank(); -extern char *firstblank(); -extern char *getcore(); -extern char *changecore(); + +/* rmach.c */ +void setlist(char *); + +/* svars.c */ +void setsvar(char *, char *); +void setpvar(char *, char *(*)(void)); +char *getvar(const char *); + +/* util.c */ +char *ack_basename(const char *); +void clr_noscan(char *); +char *skipblank(char *); +char *firstblank(char *); +void fatal(const char *, ...); +void vprint(const char *, ...); +#ifdef DEBUG +void prns(const char *); +#endif +void fuerror(const char *, ...); +void werror(const char *, ...); +void quit(int); +char *keeps(const char *); +#define throws(str) free(str) +void *getcore(size_t); +void *changecore(void *, size_t); #define freecore(area) free(area) #define DEBUG 1 /* Allow debugging of Ack */ diff --git a/util/ack/data.h b/util/ack/data.h index d6ae07855..ea845c4f7 100644 --- a/util/ack/data.h +++ b/util/ack/data.h @@ -48,4 +48,4 @@ EXTERN path in; /* The current single input pathname */ EXTERN path out; /* The current output pathname */ EXTERN path orig; /* The original input path */ EXTERN char *p_basename; /* The current basename */ -EXTERN char *p_suffix; /* The current input suffix */ +EXTERN const char *p_suffix; /* The current input suffix */ diff --git a/util/ack/files.c b/util/ack/files.c index f2dbc8ed2..e149b90f7 100644 --- a/util/ack/files.c +++ b/util/ack/files.c @@ -16,7 +16,7 @@ static char rcs_id[] = "$Id$" ; #endif -char *add_u(part,ptr) char *ptr ; { +static char *add_u(int part, char *ptr) { if ( part>=26 ) { ptr=add_u(part/26-1,ptr) ; } @@ -24,7 +24,7 @@ char *add_u(part,ptr) char *ptr ; { return ptr+1 ; } -char *unique() { +static char *unique(void) { /* Get the next unique part of the internal filename */ static int u_next = 0 ; static char buf[10] ; @@ -36,7 +36,7 @@ char *unique() { return buf ; } -setfiles(phase) register trf *phase ; { +int setfiles(trf *phase) { /* Set the out structure according to the in structure, the transformation and some global data */ growstring pathname ; @@ -94,18 +94,7 @@ setfiles(phase) register trf *phase ; { return 1 ; } -disc_files(phase) trf *phase ; { - path temp ; - - if ( !phase->t_combine ) { - file_final(&in) ; - } else { - disc_inputs(phase) ; - } - temp=in ; in=out ; out=temp ; -} - -file_final(file) path *file ; { +static void file_final(path *file) { if ( file->p_path ) { if ( !file->p_keep && t_flag<=1 ) { if ( unlink(file->p_path)!=0 ) { @@ -119,7 +108,18 @@ file_final(file) path *file ; { file->p_keep=NO ; } -disc_inputs(phase) trf *phase ; { +void disc_files(trf *phase) { + path temp ; + + if ( !phase->t_combine ) { + file_final(&in) ; + } else { + disc_inputs(phase) ; + } + temp=in ; in=out ; out=temp ; +} + +void disc_inputs(trf *phase) { /* Remove all the input files of this phase */ /* Only for combiners */ register path *l_in ; @@ -132,7 +132,7 @@ disc_inputs(phase) trf *phase ; { l_clear(&phase->t_inputs) ; } -rmfile(file) path *file ; { +void rmfile(path *file) { /* Remove a file, do not complain when is does not exist */ if ( file->p_path ) { if ( t_flag<=1 ) unlink(file->p_path) ; @@ -143,8 +143,7 @@ rmfile(file) path *file ; { } } -void -rmtemps() { +void rmtemps(void) { /* Called in case of disaster, always remove the current output file! */ register list_elem *elem ; @@ -159,7 +158,7 @@ rmtemps() { } } -add_input(file,phase) path *file ; trf *phase ; { +void add_input(path *file, trf *phase) { register path *store ; #ifdef DEBUG if ( debug ) { diff --git a/util/ack/grows.c b/util/ack/grows.c index 81c3c002d..a74e27731 100644 --- a/util/ack/grows.c +++ b/util/ack/grows.c @@ -19,7 +19,7 @@ static char rcs_id[] = "$Id$" ; static char rcs_grows[] = RCS_GROWS ; #endif -gr_add(id,c) register growstring *id ; char c ; { +int gr_add(growstring *id, int c) { if ( id->gr_size==id->gr_max) { if ( id->gr_size==0 ) { /* The first time */ id->gr_max= 2*GR_MORE ; @@ -32,8 +32,8 @@ gr_add(id,c) register growstring *id ; char c ; { *(id->gr_string+id->gr_size++)= c ; } -gr_cat(id,string) growstring *id ; char *string ; { - register char *ptr ; +int gr_cat(growstring *id, const char *string) { + const char *ptr ; #ifdef DEBUG if ( id->gr_size && *(id->gr_string+id->gr_size-1) ) { @@ -50,8 +50,7 @@ gr_cat(id,string) growstring *id ; char *string ; { } } -void -gr_throw(id) register growstring *id ; { +void gr_throw(growstring *id) { /* Throw the string away */ if ( id->gr_max==0 ) return ; freecore(id->gr_string) ; @@ -60,11 +59,11 @@ gr_throw(id) register growstring *id ; { id->gr_size=0 ; } -gr_init(id) growstring *id ; { +void gr_init(growstring *id) { id->gr_size=0 ; id->gr_max=0 ; } -char *gr_final(id) growstring *id ; { +char *gr_final(growstring *id) { /* Throw away the bookkeeping, adjust the string to its final length and return a pointer to a string to be get rid of with throws diff --git a/util/ack/grows.h b/util/ack/grows.h index 9b9511049..04f95aa59 100644 --- a/util/ack/grows.h +++ b/util/ack/grows.h @@ -20,8 +20,8 @@ typedef struct { /* Routines used */ -extern void gr_throw() ; /* To free the core */ -extern int gr_add() ; /* To add one character */ -extern int gr_cat() ; /* concatenate the contents and the string */ -extern int gr_init() ; /* Initialize the bookkeeping */ -extern char *gr_final() ; /* Transform to a stable storage string */ +void gr_throw(growstring *) ; /* To free the core */ +int gr_add(growstring *, int) ; /* To add one character */ +int gr_cat(growstring *, const char *) ; /* To append a string */ +void gr_init(growstring *) ; /* Initialize the bookkeeping */ +char *gr_final(growstring *) ; /* Move to a stable storage string */ diff --git a/util/ack/list.c b/util/ack/list.c index 278f55580..5370e96cb 100644 --- a/util/ack/list.c +++ b/util/ack/list.c @@ -33,7 +33,7 @@ Routines: */ -l_add(header,string) list_head *header ; char *string ; { +void l_add(list_head *header, char *string) { register list_elem *new; /* NOSTRICT */ @@ -49,7 +49,7 @@ l_add(header,string) list_head *header ; char *string ; { header->ca_last= new ; } -l_clear(header) list_head *header ; { +void l_clear(list_head *header) { register list_elem *old, *next; for ( old=header->ca_first ; old ; old= next ) { next= old->ca_next ; @@ -59,7 +59,7 @@ l_clear(header) list_head *header ; { header->ca_last = (list_elem *) 0 ; } -l_throw(header) list_head *header ; { +void l_throw(list_head *header) { register list_elem *old, *next; for ( old=header->ca_first ; old ; old= next ) { throws(l_content(*old)) ; diff --git a/util/ack/list.h b/util/ack/list.h index 3e6d55170..f96d8ce15 100644 --- a/util/ack/list.h +++ b/util/ack/list.h @@ -29,3 +29,7 @@ typedef struct ca_elem list_elem ; /* The decl. for elements */ /* To be used for scanning lists, ptr is the running variable */ #define scanlist(elem,ptr) \ for ( ptr= elem ; ptr; ptr= l_next(*ptr) ) + +void l_add(list_head *, char *); +void l_clear(list_head *); +void l_throw(list_head *); diff --git a/util/ack/main.c b/util/ack/main.c index 99e27dceb..539f42180 100644 --- a/util/ack/main.c +++ b/util/ack/main.c @@ -22,11 +22,20 @@ static char rcs_ack[] = RCS_ACK ; static int sigs[] = { SIGINT, SIGHUP, SIGTERM, 0 } ; static int arg_count; -extern char *getenv(); +static char *srcvar(void); +static char *getsuffix(void); +static void varinit(void); +static void vieuwargs(int, char **); +static void firstarg(char *); +static int process(char *); +static int startrf(trf *); +static void block(trf *); +static int mayprep(void); +static void scanneeds(void); +static void setneeds(const char *, int); +static void noodstop(int); -void vieuwargs(); - -main(argc,argv) char **argv ; { +int main(int argc, char **argv) { register list_elem *elem ; register char *frontend ; register int *n_sig ; @@ -102,7 +111,7 @@ main(argc,argv) char **argv ; { orig.p_path=phase->t_origname ; if ( p_basename ) throws(p_basename) ; if ( orig.p_path ) { - p_basename= keeps(basename(orig.p_path)) ; + p_basename= keeps(ack_basename(orig.p_path)) ; } else { p_basename=0 ; } @@ -115,15 +124,15 @@ main(argc,argv) char **argv ; { exit(0) ; } -char *srcvar() { +static char *srcvar(void) { return orig.p_path ; } -char *getsuffix() { +static char *getsuffix(void) { return strrchr(orig.p_path, SUFCHAR) ; } -varinit() { +static void varinit(void) { /* initialize the string variables */ register char *envstr ; extern char *em_dir; @@ -138,8 +147,7 @@ varinit() { /************************* flag processing ***********************/ -void -vieuwargs(argc,argv) char **argv ; { +void vieuwargs(int argc, char **argv) { register char *argp; register int nextarg ; register int eaten ; @@ -206,14 +214,16 @@ vieuwargs(argc,argv) char **argv ; { case 'r': if ( argp[2]!=SUFCHAR ) { error("-r must be followed by %c",SUFCHAR) ; } - keeptail(&argp[2]); eaten=1 ; + l_add(&tail_list, &argp[2]) ; + eaten=1 ; break ; case '.': if ( rts ) { if ( strcmp(rts,&argp[1])!=0 ) fuerror("Two run-time systems?") ; } else { rts= &argp[1] ; - keephead(rts) ; keeptail(rts) ; + l_add(&head_list, rts) ; + l_add(&tail_list, rts) ; } eaten=1 ; break ; @@ -238,7 +248,7 @@ vieuwargs(argc,argv) char **argv ; { register char *tokeep ; tokeep=keeps(argp) ; if ( argp[1]=='R' ) { - do_Rflag(tokeep); + l_add(&R_list, tokeep) ; } else { *tokeep |= NO_SCAN ; } @@ -251,7 +261,7 @@ vieuwargs(argc,argv) char **argv ; { return ; } -firstarg(argp) register char *argp ; { +static void firstarg(char *argp) { register char *name ; name=strrchr(argp,'/') ; @@ -265,7 +275,7 @@ firstarg(argp) register char *argp ; { /************************* argument processing ***********************/ -process(arg) char *arg ; { +static int process(char *arg) { /* Process files & library arguments */ trf *phase ; register trf *tmp ; @@ -282,7 +292,7 @@ process(arg) char *arg ; { return 1 ; } if ( p_basename ) throws(p_basename) ; - p_basename= keeps(basename(arg)) ; + p_basename= keeps(ack_basename(arg)) ; /* Try to find a path through the transformations */ switch( getpath(&phase) ) { case F_NOPATH : @@ -325,7 +335,7 @@ process(arg) char *arg ; { return startrf(phase) ; } -int startrf(first) trf *first ; { +static int startrf(trf *first) { /* Start the transformations at the indicated phase */ register trf *phase ; @@ -397,7 +407,7 @@ if ( debug ) vprint("Transformation sequence complete for %s\n", return 1 ; } -block(first) trf *first ; { +static void block(trf *first) { /* One of the input files of this phase could not be produced, block all combiners taking their input from this one. */ @@ -406,7 +416,8 @@ block(first) trf *first ; { if ( phase->t_combine ) phase->t_blocked=YES ; } } -mayprep() { + +static int mayprep(void) { int file ; char fc ; file=open(in.p_path,0); @@ -416,15 +427,7 @@ mayprep() { return fc=='#' ; } -keephead(suffix) char *suffix ; { - l_add(&head_list, suffix) ; -} - -keeptail(suffix) char *suffix ; { - l_add(&tail_list, suffix) ; -} - -scanneeds() { +static void scanneeds(void) { register list_elem *elem ; scanlist(l_first(head_list), elem) { setneeds(l_content(*elem),0) ; } l_clear(&head_list) ; @@ -432,7 +435,7 @@ scanneeds() { l_clear(&tail_list) ; } -setneeds(suffix,tail) char *suffix ; { +static void setneeds(const char *suffix, int tail) { trf *phase ; p_suffix= suffix ; @@ -456,3 +459,7 @@ setneeds(suffix,tail) char *suffix ; { break ; } } + +static void noodstop(int sig) { + quit(-3) ; +} diff --git a/util/ack/rmach.c b/util/ack/rmach.c index 1e33e8713..4b3061be4 100644 --- a/util/ack/rmach.c +++ b/util/ack/rmach.c @@ -47,19 +47,21 @@ static char rcs_dmach[] = RCS_DMACH ; #define CALL "callname" #define END "end" -extern growstring scanb(); -extern growstring scanvars(); +/* trans.c */ +growstring scanb(const char *) ; +growstring scanvars(const char *) ; + +static void intrf(void) ; +static void open_in(char *) ; +static void close_in(void) ; +static int getinchar(void) ; +static int getln(void) ; -int getln() ; -int getinchar() ; static char *ty_name ; static char *bol ; - -void open_in(); - static char *inname ; -setlist(name) char *name ; { +void setlist(char *name) { /* Name is sought in the internal tables, if not present, the a file of that name is sought in first the current and then the EM Lib directory @@ -92,9 +94,7 @@ setlist(name) char *name ; { #endif } -static int inoptlist(nm) - char *nm ; -{ +static int inoptlist(char *nm) { register char *p=Optlist ; while ( p && *p ) { @@ -107,7 +107,7 @@ static int inoptlist(nm) return 0; } -intrf() { +static void intrf(void) { register trf *new ; growstring bline ; int twice ; @@ -234,7 +234,8 @@ intrf() { rts, new->t_rts) ; } rts= new->t_rts ; - keephead(rts) ; keeptail(rts) ; + l_add(&head_list, rts) ; + l_add(&tail_list, rts) ; } #ifdef DEBUG if ( debug>=3 ) { @@ -264,8 +265,7 @@ static FILE *infile ; static char *inptr ; char *em_dir = EM_DIR; -void -open_in(name) register char *name ; { +static void open_in(char *name) { register dmach *cmac ; gr_init(&rline) ; @@ -298,12 +298,12 @@ open_in(name) register char *name ; { } } -close_in() { +static void close_in(void) { if ( !incore ) fclose(infile) ; gr_throw(&rline) ; } -char *readline() { +static char *readline(void) { /* Get a line from the input, return 0 if at end, The line is stored in a volatile buffer, @@ -355,7 +355,7 @@ char *readline() { } } -int getinchar() { +static int getinchar(void) { register int token ; if ( incore ) { @@ -369,7 +369,7 @@ int getinchar() { return token ; } -int getln() { +static int getln(void) { register char *c_ptr ; do { diff --git a/util/ack/run.c b/util/ack/run.c index 8d0481a58..87d8745a0 100644 --- a/util/ack/run.c +++ b/util/ack/run.c @@ -5,6 +5,7 @@ */ #include +#include #include #include "ack.h" #include "list.h" @@ -19,13 +20,17 @@ static char rcs_id[] = "$Id$" ; #define ARG_MORE 40 /* The size of args chunks to allocate */ -extern growstring scanvars(); +/* trans.c */ +growstring scanvars(const char *); + +static int run_exec(trf *, const char *); +static void x_arg(char *); static char **arglist ; /* The first argument */ static unsigned argcount ; /* The current number of arguments */ static unsigned argmax; /* The maximum number of arguments so far */ -int runphase(phase) register trf *phase ; { +int runphase(trf *phase) { register list_elem *elem ; char *prog ; int result ; growstring bline ; @@ -70,10 +75,11 @@ int runphase(phase) register trf *phase ; { return result ; } -int run_exec(phase,prog) trf *phase ; char *prog ; { +static int run_exec(trf *phase, const char *prog) { int status, child, waitchild ; - do_flush(); + fflush(stdout) ; + fflush(stderr) ; while ( (child=fork())== -1 ) ; if ( child ) { /* The parent */ @@ -136,7 +142,7 @@ int run_exec(phase,prog) trf *phase ; char *prog ; { /*NOTREACHED*/ } -x_arg(string) char *string ; { +static void x_arg(char *string) { /* Add one execute argument to the argument vector */ if ( argcount==argmax ) { if ( argmax==0 ) { diff --git a/util/ack/scan.c b/util/ack/scan.c index d020e6a5b..3aaab8492 100644 --- a/util/ack/scan.c +++ b/util/ack/scan.c @@ -15,9 +15,14 @@ static char rcs_id[] = "$Id$" ; #endif -void try(); +static void start_scan(void); +static void try(list_elem *, const char *); +static void scan_found(void); +static int satisfy(trf *, const char *); +static enum f_path scan_end(trf **); +static void find_cpp(void); -enum f_path getpath(first) register trf **first ; { +enum f_path getpath(trf **first) { /* Try to find a transformation path */ start_scan(); @@ -49,7 +54,7 @@ static int suf_found; /* Was the suffix at least recognized ? */ /******************** The hard work ********************/ -start_scan() { +static void start_scan(void) { register list_elem *scan ; scanlist(l_first(tr_list),scan) { @@ -63,8 +68,7 @@ start_scan() { last_ocount= 0 ; } -void -try(f_scan,suffix) list_elem *f_scan; char *suffix; { +static void try(list_elem *f_scan, const char *suffix) { register list_elem *scan ; register trf *trafo ; /* Try to find a transformation path starting at f_scan for a @@ -134,7 +138,7 @@ try(f_scan,suffix) list_elem *f_scan; char *suffix; { } } -scan_found() { +static void scan_found(void) { register list_elem *scan; int ncount, ocount, pcount ; @@ -182,7 +186,7 @@ scan_found() { } } -int satisfy(trafo,suffix) register trf *trafo; char *suffix ; { +static int satisfy(trf *trafo, const char *suffix) { register char *f_char, *l_char ; /* Check whether this transformation is present for the current machine and the parameter suffix is among @@ -207,7 +211,7 @@ int satisfy(trafo,suffix) register trf *trafo; char *suffix ; { return 0 ; } -enum f_path scan_end(first) trf **first ; { /* Finalization */ +static enum f_path scan_end(trf **first) { /* Finalization */ /* Return value indicating whether a transformation was found */ /* Set the flags for the transformation up to, but not including, the combiner @@ -248,7 +252,7 @@ enum f_path scan_end(first) trf **first ; { /* Finalization */ return F_OK ; } -find_cpp() { +static void find_cpp(void) { register list_elem *elem ; scanlist( l_first(tr_list), elem ) { if ( t_cont(*elem)->t_isprep ) { diff --git a/util/ack/svars.c b/util/ack/svars.c index 2d7e4b42c..38e8f95b9 100644 --- a/util/ack/svars.c +++ b/util/ack/svars.c @@ -44,9 +44,6 @@ static char rcs_id[] = "$Id$" ; */ -extern char *getcore(); -extern fatal(); - struct vars { char *v_name; enum { routine, string } v_type; @@ -60,7 +57,7 @@ struct vars { static struct vars *v_first ; -static struct vars *newvar(name) char *name; { +static struct vars *newvar(char *name) { register struct vars *new ; for ( new=v_first ; new ; new= new->v_next ) { @@ -72,14 +69,14 @@ static struct vars *newvar(name) char *name; { return new ; } } - new= (struct vars *)getcore( (unsigned)sizeof (struct vars)); + new= (struct vars *)getcore(sizeof (struct vars)); new->v_name= name ; new->v_next= v_first ; v_first= new ; return new ; } -setsvar(name,str) char *name, *str ; { +void setsvar(char *name, char *str) { register struct vars *new ; new= newvar(name); @@ -90,7 +87,7 @@ setsvar(name,str) char *name, *str ; { new->v_value.v_string= str; } -setpvar(name,rout) char *name, *(*rout)() ; { +void setpvar(char *name, char *(*rout)(void)) { register struct vars *new ; new= newvar(name); @@ -101,7 +98,7 @@ setpvar(name,rout) char *name, *(*rout)() ; { new->v_value.v_routine= rout; } -char *getvar(name) char *name ; { +char *getvar(const char *name) { register struct vars *scan ; for ( scan=v_first ; scan ; scan= scan->v_next ) { diff --git a/util/ack/trans.c b/util/ack/trans.c index 3cb2d7ea8..92e54ae9e 100644 --- a/util/ack/trans.c +++ b/util/ack/trans.c @@ -26,13 +26,15 @@ static int touch_head= NO ; static growstring tail ; static int touch_tail= NO ; -char *headvar(),*tailvar() ; +static char *headvar(void); +static char *tailvar(void); +static void set_Rflag(char *); +static void condit(growstring *, list_head *, list_head *, char *); +static int mapflag(list_head *, const char *); +static int mapexpand(char *, const char *); +static void getcallargs(trf *); -void condit(); -void doassign(); -void set_Rflag(); - -int transform(phase) register trf *phase ; { +int transform(trf *phase) { int ok ; if ( !setfiles(phase) ) { @@ -45,12 +47,13 @@ int transform(phase) register trf *phase ; { /* Free the space occupied by the arguments, except for the linker, since we are bound to exit soon and do not foresee further need of memory space */ - if ( !phase->t_linker ) discardargs(phase) ; + if ( !phase->t_linker ) + l_throw(&phase->t_args) ; disc_files(phase) ; return ok ; } -getmapflags(phase) register trf *phase ; { +void getmapflags(trf *phase) { register path *l_in ; register list_elem *elem ; int scanned ; @@ -110,16 +113,12 @@ getmapflags(phase) register trf *phase ; { } -do_Rflag(argp) char *argp ; { - l_add(&R_list,argp) ; -} - -char *headvar() { +static char *headvar(void) { if ( !touch_head) return "" ; return gr_start(head) ; } -add_head(str) char *str; { +void add_head(const char *str) { if ( !touch_head) { gr_init(&head) ; touch_head=YES ; @@ -127,12 +126,12 @@ add_head(str) char *str; { gr_cat(&head,str) ; } -char *tailvar() { +static char *tailvar(void) { if ( !touch_tail ) return "" ; return gr_start(tail) ; } -add_tail(str) char *str ; { +void add_tail(const char *str) { if ( !touch_tail ) { gr_init(&tail) ; touch_tail=YES ; @@ -141,7 +140,7 @@ add_tail(str) char *str ; { } -transini() { +void transini(void) { register list_elem *elem ; register trf *phase ; @@ -157,8 +156,7 @@ transini() { setpvar(keeps(TAIL),tailvar) ; } -void -set_Rflag(argp) register char *argp ; { +static void set_Rflag(char *argp) { register char *eos ; register list_elem *prog ; register int length ; @@ -206,12 +204,12 @@ set_Rflag(argp) register char *argp ; { /* */ /**************************************************************************/ -growstring scanb(line) char *line ; { +growstring scanb(const char *line) { /* Scan a line for backslashes, setting the NO_SCAN bit in characters preceded by a backslash. */ - register char *in_c ; - register int token ; + const char *in_c ; + int token ; growstring result ; enum { TEXT, ESCAPED } state = TEXT ; @@ -237,7 +235,7 @@ growstring scanb(line) char *line ; { return result ; } -growstring scanvars(line) char *line ; { +growstring scanvars(const char *line) { /* Scan a line variable replacements started by S_VAR. Two sequences exist: S_VAR name E_VAR, S_VAR name A_VAR text E_VAR. neither name nor text may contain further replacements. @@ -248,11 +246,10 @@ growstring scanvars(line) char *line ; { This to allow later recognition in mapflags, where B_SLASH would be preventing any recognition. */ - register char *in_c ; - register int token ; - growstring result ; - growstring name ; - register char *tr ; + const char *in_c ; + int token ; + growstring result, name ; + char *tr ; enum { TEXT, FIRST, NAME, SKIP, COPY } state = TEXT ; gr_init(&result) ; gr_init(&name) ; @@ -331,7 +328,7 @@ growstring scanvars(line) char *line ; { return result ; } -growstring scanexpr(line) char *line ; { +static growstring scanexpr(const char *line) { /* Scan a line for conditional or flag expressions, dependent on the type. The format is S_EXPR suflist M_EXPR suflist T_EXPR tail C_EXPR @@ -339,11 +336,9 @@ growstring scanexpr(line) char *line ; { growstring for futher treatment. Nesting is not allowed. */ - register char *in_c ; - char *heads ; - register int token ; - growstring sufs, tailval ; - growstring result ; + const char *in_c, *heads ; + int token ; + growstring sufs, tailval, result ; static list_head fsuff, lsuff ; enum { TEXT, FDOT, FSUF, LDOT, LSUF, FTAIL } state = TEXT ; @@ -418,10 +413,8 @@ growstring scanexpr(line) char *line ; { return result ; } -void -condit(line,fsuff,lsuff,tailval) growstring *line ; - list_head *fsuff, *lsuff; - char *tailval ; +static void condit(growstring *line, list_head *fsuff, list_head *lsuff, + char *tailval) { register list_elem *first ; register list_elem *last ; @@ -446,7 +439,7 @@ condit(line,fsuff,lsuff,tailval) growstring *line ; #endif } -int mapflag(maplist,cflag) list_head *maplist ; char *cflag ; { +static int mapflag(list_head *maplist, const char *cflag) { /* Expand a flag expression */ /* The flag "cflag" is checked for each of the mapflags. A mapflag entry has the form @@ -468,12 +461,9 @@ int mapflag(maplist,cflag) list_head *maplist ; char *cflag ; { return 0 ; } -int mapexpand(mapentry,cflag) - char *mapentry, *cflag ; -{ - register char *star ; - register char *ptr ; - register char *space ; +static int mapexpand(char *mapentry, const char *cflag) { + const char *star ; + char *ptr, *space ; int length ; star=strchr(mapentry,STAR) ; @@ -510,10 +500,9 @@ int mapexpand(mapentry,cflag) return 1 ; } -void -doassign(line,star,length) char *line, *star ; { +void doassign(const char *line, const char *star, int length) { growstring varval, name, temp ; - register char *ptr ; + const char *ptr ; gr_init(&varval) ; gr_init(&name) ; @@ -544,7 +533,7 @@ doassign(line,star,length) char *line, *star ; { #define ISBLANK(c) ( (c)==SPACE || (c)==TAB ) -unravel(line,action) char *line ; int (*action)() ; { +static void unravel(char *line, void (*action)(char *)) { /* Unravel the line, get arguments a la shell */ /* each argument is handled to action */ /* The input string is left intact */ @@ -581,7 +570,7 @@ unravel(line,action) char *line ; int (*action)() ; { } } -char *c_rep(string,place,rep) char *string, *place, *rep ; { +static char *c_rep(char *string, char *place, char *rep) { /* Produce a string in stable storage produced from 'string' with the character at place replaced by rep */ @@ -605,8 +594,7 @@ char *c_rep(string,place,rep) char *string, *place, *rep ; { static list_head *curargs ; static list_head *comb_args ; -void -addargs(string) char *string ; { +static void addargs(char *string) { register char *temp, *repc ; register list_elem *elem ; @@ -653,7 +641,7 @@ addargs(string) char *string ; { l_add(curargs,temp) ; } -getcallargs(phase) register trf *phase ; { +static void getcallargs(trf *phase) { growstring arg1, arg2 ; arg1= scanvars(phase->t_argd) ; @@ -670,7 +658,3 @@ getcallargs(phase) register trf *phase ; { unravel( gr_start(arg2), addargs ) ; gr_throw(&arg2) ; } - -discardargs(phase) register trf *phase ; { - l_throw(&phase->t_args) ; -} diff --git a/util/ack/trans.h b/util/ack/trans.h index 70be80832..54086a563 100644 --- a/util/ack/trans.h +++ b/util/ack/trans.h @@ -44,3 +44,26 @@ struct transform { } ; #define t_cont(elem) ((trf *)l_content(elem)) + +/* files.c */ +int setfiles(trf *); +void disc_files(trf *); +void disc_inputs(trf *); +void rmfile(path *); +void rmtemps(void); +void add_input(path *, trf *); + +/* run.c */ +int runphase(trf *); + +/* scan.c */ +enum f_path { F_OK, F_NOMATCH, F_NOPATH } ; +enum f_path getpath(trf **); + +/* trans.c */ +int transform(trf *); +void getmapflags(trf *); +void add_head(const char *); +void add_tail(const char *); +void transini(void); +void doassign(const char *, const char *, int); diff --git a/util/ack/util.c b/util/ack/util.c index 419f087e3..caad71cdd 100644 --- a/util/ack/util.c +++ b/util/ack/util.c @@ -32,15 +32,11 @@ extern int n_error; # define STDOUT stderr #endif -void fuerror(const char* fmt, ...); -void werror(const char* fmt, ...); - -char *basename(string) char *string ; { +char *ack_basename(const char *string) { static char retval[256] ; - char *last_dot, *last_start ; - register char *store; - register char *fetch ; - register int ctoken ; + const char *last_dot, *last_start, *fetch ; + char *store ; + int ctoken ; last_dot= (char *)0 ; last_start= string ; @@ -65,21 +61,21 @@ out: return retval ; } -clr_noscan(str) char *str ; { +void clr_noscan(char *str) { register char *ptr ; for ( ptr=str ; *ptr ; ptr++ ) { *ptr&= ~NO_SCAN ; } } -char *skipblank(str) char *str ; { +char *skipblank(char *str) { register char *ptr ; for ( ptr=str ; *ptr==SPACE || *ptr==TAB ; ptr++ ) ; return ptr ; } -char *firstblank(str) char *str ; { +char *firstblank(char *str) { register char *ptr ; for ( ptr=str ; *ptr && *ptr!=SPACE && *ptr!=TAB ; ptr++ ) ; @@ -110,7 +106,7 @@ void vprint(const char* fmt, ...) } #ifdef DEBUG -prns(s) register char *s ; { +void prns(const char *s) { for ( ; *s ; s++ ) { putc((*s&0377)&~NO_SCAN,STDOUT) ; } @@ -153,48 +149,36 @@ void error(const char *fmt, ...) { va_end(ap); } -do_flush() { - fflush(stdout) ; - fflush(stderr) ; -} - -void -noodstop() { - quit(-3) ; -} - -quit(code) { +void quit(int code) { rmtemps(); exit(code); } + /****** char *keeps(string) Keep the string in stable storage. throws(string) Remove the string stored by keep from stable storage. + throws() is now a macro in ack.h. ***********/ -char *keeps(str) char *str ; { +char *keeps(const char *str) { register char *result ; result= getcore( (unsigned)(strlen(str)+1) ) ; if ( !result ) fatal("Out of core") ; return strcpy(result,str) ; } -throws(str) char *str ; { - freecore(str) ; -} - -char *getcore(size) unsigned size ; { - register char *retptr ; +void *getcore(size_t size) { + void *retptr ; retptr= calloc(1,size) ; if ( !retptr ) fatal("Out of memory") ; return retptr ; } -char *changecore(ptr,size) char *ptr ; unsigned size ; { - register char *retptr ; +void *changecore(void *ptr, size_t size) { + void *retptr ; retptr= realloc(ptr,size) ; if ( !retptr ) fatal("Out of memory") ; From e617f425032bccafe36657dcf615a6abaf026fd3 Mon Sep 17 00:00:00 2001 From: George Koehler Date: Sun, 13 Nov 2016 11:55:09 -0500 Subject: [PATCH 008/173] Don't print a string after possibly freeing it. new= newvar(name) takes ownership of the string and might free its memory. Don't print name. Do print new->v_name. Also #include for strcmp(). --- util/ack/svars.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/util/ack/svars.c b/util/ack/svars.c index 38e8f95b9..e540e5d02 100644 --- a/util/ack/svars.c +++ b/util/ack/svars.c @@ -4,6 +4,7 @@ * */ +#include #include "ack.h" #ifndef NORCSID @@ -81,7 +82,7 @@ void setsvar(char *name, char *str) { new= newvar(name); #ifdef DEBUG - if ( debug>=2 ) vprint("%s=%s\n", name, str) ; + if ( debug>=2 ) vprint("%s=%s\n", new->v_name, str) ; #endif new->v_type= string; new->v_value.v_string= str; @@ -92,7 +93,7 @@ void setpvar(char *name, char *(*rout)(void)) { new= newvar(name); #ifdef DEBUG - if ( debug>=2 ) vprint("%s= (*%o)()\n",name,rout) ; + if ( debug>=2 ) vprint("%s= (*%o)()\n", new->v_name, rout) ; #endif new->v_type= routine; new->v_value.v_routine= rout; From fafc8a0b8a3041beb410ed04219c5e20c5f6572f Mon Sep 17 00:00:00 2001 From: George Koehler Date: Sun, 13 Nov 2016 12:45:01 -0500 Subject: [PATCH 009/173] Don't retry fork() in a loop. If fork() fails, then report a fatal error. Don't spin the cpu retrying fork() until it succeeds. It can fail when we reach a limit on the number of processes. Spinning on the cpu would slow down other processes when we want them to exit. This would get bad if we had a parallel build with multiple ack processes spinning. --- util/ack/run.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/util/ack/run.c b/util/ack/run.c index 87d8745a0..6b5b69fcd 100644 --- a/util/ack/run.c +++ b/util/ack/run.c @@ -80,7 +80,10 @@ static int run_exec(trf *phase, const char *prog) { fflush(stdout) ; fflush(stderr) ; - while ( (child=fork())== -1 ) ; + child= fork() ; + if ( child== - 1) { + fatal("Cannot fork %s", prog) ; + } if ( child ) { /* The parent */ do { From 07b04c64c8d8c4db0365763aa9be1696fc47cdd5 Mon Sep 17 00:00:00 2001 From: George Koehler Date: Mon, 14 Nov 2016 23:33:44 -0500 Subject: [PATCH 010/173] Let ack(1) compile files with non-ASCII names. This commit changes how ack(1) parses backslashes in its descr files. Before this commit, ack set the high bit of each character escaped by a backslash, and later cleared all high bits in command arguments, but this lost the high bits in non-ASCII filenames. After this commit, ack keeps backslashes in strings while processing them. Functions scanvars(), scanexpr(), doassign(), unravel(), addargs() now understand backslashes. I remove from ack_basename() the warning about non-ASCII characters. This commit makes some incompatible changes for backslashes in descr files. None of our descr files uses backslashes, except for those backslashes that continue lines, and there are no changes for those backslashes. The problem with non-ASCII filenames had its cause in a feature that we weren't using. With this commit, ack now understands backslashes after the = sign in both "var NAME=value" and "mapflag -flag NAME=value". Before, ack never scanned backslashes in "var" lines, so "var A=\{B}" failed to prevent expansion of B. Now it does. Before, ack did scan for backslashes in the "-flag NAME=" part of "mapflag" lines. Now it doesn't, so it is no longer possible to map a flag that contains a literal space, tab, or star "*". I removed the expansion of "{{" to "{". One can use "\{" for a literal "{", and "\{" now works in "var" lines. Before and now, ack never expanded "{" in flags for "mapflag", so the correct way to map a literal flag "-{" remains "mapflag -{ ...", not "mapflag -{{ ...". (The other way "mapflag -\{ ..." stops working with this commit.) Backslashes in strange places, like "{NA\ME}", probably have different behavior now. Backslashes in "program" lines now work. Before, ack scanned for backslashes there but forgot to clear the high bits later. Escaping < or > as \< or \> now works, and prevents substitution of the input or output file paths. Before, ack only expanded the first < or > in each argument. Now, it expands every unescaped < or > in an argument, but this is an accident of how I rewrote the code. I don't suggest to put more than one each of < or > in a command. The code no longer optimizes away its recursive calls when the argument is "<". The code continues to set or clear the high bit NO_SCAN on the first characters of flags. This doesn't seem to be a problem, because flags usually begin with an ASCII hyphen '-'. --- util/ack/ack.h | 4 - util/ack/rmach.c | 20 +-- util/ack/run.c | 14 +-- util/ack/trans.c | 321 +++++++++++++++++++++++++++-------------------- util/ack/util.c | 19 --- 5 files changed, 197 insertions(+), 181 deletions(-) diff --git a/util/ack/ack.h b/util/ack/ack.h index bbf3da58d..01eec8212 100644 --- a/util/ack/ack.h +++ b/util/ack/ack.h @@ -75,14 +75,10 @@ char *getvar(const char *); /* util.c */ char *ack_basename(const char *); -void clr_noscan(char *); char *skipblank(char *); char *firstblank(char *); void fatal(const char *, ...); void vprint(const char *, ...); -#ifdef DEBUG -void prns(const char *); -#endif void fuerror(const char *, ...); void werror(const char *, ...); void quit(int); diff --git a/util/ack/rmach.c b/util/ack/rmach.c index 4b3061be4..13f904a38 100644 --- a/util/ack/rmach.c +++ b/util/ack/rmach.c @@ -47,10 +47,6 @@ static char rcs_dmach[] = RCS_DMACH ; #define CALL "callname" #define END "end" -/* trans.c */ -growstring scanb(const char *) ; -growstring scanvars(const char *) ; - static void intrf(void) ; static void open_in(char *) ; static void close_in(void) ; @@ -108,8 +104,8 @@ static int inoptlist(char *nm) { } static void intrf(void) { + /* Read in trf (transformation) */ register trf *new ; - growstring bline ; int twice ; int name_seen=0 ; @@ -130,20 +126,14 @@ static void intrf(void) { } else if ( strcmp(ty_name,PROG)==0 ) { if ( new->t_prog ) twice=YES ; - bline= scanb(bol); /* Scan for \ */ - new->t_prog= gr_final(&bline); + new->t_prog= keeps(bol); } else if ( strcmp(ty_name,MAPF)==0 ) { - /* First read the mapflags line - and scan for backslashes */ - bline= scanb(bol) ; - l_add(&new->t_mapf,gr_final(&bline)) ; + l_add(&new->t_mapf,keeps(bol)) ; } else if ( strcmp(ty_name,ARGS)==0 ) { if ( new->t_argd ) twice=YES ; - bline= scanb(bol) ; - new->t_argd= keeps(gr_start(bline)) ; - gr_throw(&bline) ; + new->t_argd= keeps(bol) ; } else if ( strcmp(ty_name,STD_IN)==0 ) { if ( new->t_stdin ) twice=YES ; @@ -242,7 +232,7 @@ static void intrf(void) { register list_elem *elem ; vprint("%s: from %s to %s '%s'\n", new->t_name,new->t_in ? new->t_in : "(null)",new->t_out,new->t_prog) ; - vprint("\targs: ") ; prns(new->t_argd) ; + vprint("\targs: %s",new->t_argd) ; scanlist( l_first(new->t_mapf), elem ) { vprint("\t%s\n",l_content(*elem)) ; } diff --git a/util/ack/run.c b/util/ack/run.c index 6b5b69fcd..ed88d66c7 100644 --- a/util/ack/run.c +++ b/util/ack/run.c @@ -20,9 +20,6 @@ static char rcs_id[] = "$Id$" ; #define ARG_MORE 40 /* The size of args chunks to allocate */ -/* trans.c */ -growstring scanvars(const char *); - static int run_exec(trf *, const char *); static void x_arg(char *); @@ -32,11 +29,9 @@ static unsigned argmax; /* The maximum number of arguments so far */ int runphase(trf *phase) { register list_elem *elem ; - char *prog ; int result ; - growstring bline ; + char *prog ; int result ; - bline=scanvars(phase->t_prog) ; - prog=gr_final(&bline) ; + prog=phase->t_prog ; if ( v_flag || debug ) { if ( v_flag==1 && !debug ) { vprint("%s",phase->t_name) ; @@ -70,9 +65,8 @@ int runphase(trf *phase) { x_arg(l_content(*elem)) ; } x_arg( (char *)0 ) ; - result=run_exec(phase,prog) ; - throws(prog) ; - return result ; + result=run_exec(phase,prog) ; + return result ; } static int run_exec(trf *phase, const char *prog) { diff --git a/util/ack/trans.c b/util/ack/trans.c index 92e54ae9e..98a75a066 100644 --- a/util/ack/trans.c +++ b/util/ack/trans.c @@ -33,6 +33,8 @@ static void condit(growstring *, list_head *, list_head *, char *); static int mapflag(list_head *, const char *); static int mapexpand(char *, const char *); static void getcallargs(trf *); +static growstring without_bslash(const char *); +static void getprogram(trf *); int transform(trf *phase) { int ok ; @@ -42,6 +44,7 @@ int transform(trf *phase) { return 0 ; } getcallargs(phase) ; + getprogram(phase) ; ok= runphase(phase) ; if ( !ok ) rmfile(&out) ; /* Free the space occupied by the arguments, @@ -78,8 +81,9 @@ void getmapflags(trf *phase) { scanlist(l_first(phase->t_inputs),elem) { l_in = p_cont(*elem) ; if ( mapflag(&(phase->t_mapf),l_in->p_path) ) { - ptr= keeps(getvar(LIBVAR)) ; - clr_noscan(ptr) ; + growstring temp; + temp= without_bslash(getvar(LIBVAR)) ; + ptr= gr_final(&temp); #ifdef DEBUG if ( debug >=4 ) { vprint("phase %s, library %s(%s)\n", @@ -204,71 +208,47 @@ static void set_Rflag(char *argp) { /* */ /**************************************************************************/ -growstring scanb(const char *line) { - /* Scan a line for backslashes, setting the NO_SCAN bit in characters - preceded by a backslash. - */ - const char *in_c ; - int token ; - growstring result ; - enum { TEXT, ESCAPED } state = TEXT ; - - gr_init(&result) ; - for ( in_c= line ; *in_c ; in_c++ ) { - token= *in_c&0377 ; - switch( state ) { - case TEXT : - if ( token==BSLASH ) { - state= ESCAPED ; - } else { - gr_add(&result,token) ; - } - break ; - case ESCAPED : - gr_add(&result,token|NO_SCAN) ; - state=TEXT ; - break ; - } - } - gr_add(&result,0) ; - if ( state!=TEXT ) werror("flag line ends with %c",BSLASH) ; - return result ; -} - -growstring scanvars(const char *line) { +static growstring scanvars(const char *line) { /* Scan a line variable replacements started by S_VAR. - Two sequences exist: S_VAR name E_VAR, S_VAR name A_VAR text E_VAR. + Two sequences exist: S_VAR name C_VAR, S_VAR name A_VAR text C_VAR. neither name nor text may contain further replacements. In the first form an error message is issued if the name is not present in the variables, the second form produces text in that case. - The sequence S_VAR S_VAR is transformed into S_VAR. - This to allow later recognition in mapflags, where B_SLASH - would be preventing any recognition. */ const char *in_c ; - int token ; + int token, token_r ; growstring result, name ; char *tr ; enum { TEXT, FIRST, NAME, SKIP, COPY } state = TEXT ; + int escaped = NO; gr_init(&result) ; gr_init(&name) ; for ( in_c= line ; *in_c ; in_c++ ) { token= *in_c&0377 ; + token_r= (escaped ? 0 : token); + + /* A backslash escapes the next character. */ + if ( token_r==BSLASH ) { + if ( state==TEXT || state==COPY ) { + /* Keep BSLASH for later scans. */ + gr_add(&result,token) ; + } + escaped= YES; + continue; + } + escaped= NO; + switch( state ) { case TEXT : - if ( token==S_VAR ) { + if ( token_r==S_VAR ) { state= FIRST ; } else { gr_add(&result,token) ; } break ; case FIRST : - switch ( token ) { - case S_VAR : - state= TEXT ; - gr_add(&result,token) ; - break ; + switch ( token_r ) { case A_VAR : case C_VAR : fatal("empty string variable name") ; @@ -279,7 +259,7 @@ growstring scanvars(const char *line) { } break ; case NAME: - switch ( token ) { + switch ( token_r ) { case A_VAR : gr_add(&name,0) ; if ( tr=getvar(gr_start(name)) ) { @@ -311,16 +291,17 @@ growstring scanvars(const char *line) { } break ; case SKIP : - if ( token==C_VAR ) state= TEXT ; + if ( token_r==C_VAR ) state= TEXT ; break ; case COPY : - if ( token==C_VAR ) state= TEXT ; else { + if ( token_r==C_VAR ) state= TEXT ; else { gr_add(&result,token) ; } break ; } } gr_add(&result,0) ; + if ( escaped ) werror("flag line ends with %c",BSLASH) ; if ( state!=TEXT ) { werror("flag line misses %c",C_VAR) ; gr_throw(&name) ; @@ -332,68 +313,80 @@ static growstring scanexpr(const char *line) { /* Scan a line for conditional or flag expressions, dependent on the type. The format is S_EXPR suflist M_EXPR suflist T_EXPR tail C_EXPR - the head and tail are passed to treat, together with the + the head and tail are passed to condit(), together with the growstring for futher treatment. Nesting is not allowed. */ const char *in_c, *heads ; - int token ; + int token, token_r ; growstring sufs, tailval, result ; static list_head fsuff, lsuff ; enum { TEXT, FDOT, FSUF, LDOT, LSUF, FTAIL } state = TEXT ; + int escaped = NO; gr_init(&result) ; gr_init(&sufs) ; gr_init(&tailval) ; for ( in_c= line ; *in_c ; in_c++ ) { token= *in_c&0377 ; + token_r= (escaped ? 0 : token); + + /* A backslash escapes the next character. */ + if ( token_r==BSLASH ) { + if ( state==TEXT || state==FTAIL ) { + /* Keep BSLASH for later scans. */ + gr_add(&result,token) ; + } + escaped= YES; + continue; + } + escaped= NO; + switch( state ) { case TEXT : - if ( token==S_EXPR ) { + if ( token_r==S_EXPR ) { state= FDOT ; heads=in_c ; } else gr_add(&result,token) ; break ; case FDOT : - if ( token==M_EXPR ) { + if ( token_r==M_EXPR ) { state=LDOT ; break ; } - token &= ~NO_SCAN ; if ( token!=SUFCHAR ) { error("Missing %c in expression",SUFCHAR) ; } gr_add(&sufs,token) ; state=FSUF ; break ; case FSUF : - if ( token==M_EXPR || (token&~NO_SCAN)==SUFCHAR) { + if ( token_r==M_EXPR || token==SUFCHAR ) { gr_add(&sufs,0) ; l_add(&fsuff,gr_final(&sufs)) ; } - if ( token==M_EXPR ) { + if ( token_r==M_EXPR ) { state=LDOT ; - } else gr_add(&sufs,token&~NO_SCAN) ; + } else gr_add(&sufs,token) ; break ; case LDOT : - if ( token==T_EXPR ) { + if ( token_r==T_EXPR ) { state=FTAIL ; break ; } - token &= ~NO_SCAN ; if ( token!=SUFCHAR ) { error("Missing %c in expression",SUFCHAR) ; } gr_add(&sufs,token) ; state=LSUF ; break ; case LSUF : - if ( token==T_EXPR || (token&~NO_SCAN)==SUFCHAR) { + if ( token_r==T_EXPR || token==SUFCHAR) { gr_add(&sufs,0) ; l_add(&lsuff,gr_final(&sufs)) ; } - if ( token==T_EXPR ) { + if ( token_r==T_EXPR ) { state=FTAIL ; - } else gr_add(&sufs,token&~NO_SCAN) ; + } else gr_add(&sufs,token) ; break ; case FTAIL : - if ( token==C_EXPR ) { + if ( token_r==C_EXPR ) { /* Found one !! */ gr_add(&tailval,0) ; condit(&result,&fsuff,&lsuff,gr_start(tailval)) ; @@ -503,6 +496,7 @@ static int mapexpand(char *mapentry, const char *cflag) { void doassign(const char *line, const char *star, int length) { growstring varval, name, temp ; const char *ptr ; + int escaped = NO ; gr_init(&varval) ; gr_init(&name) ; @@ -517,12 +511,21 @@ void doassign(const char *line, const char *star, int length) { } temp= scanvars(ptr+1) ; for ( ptr=gr_start(temp); *ptr; ptr++ ) switch ( *ptr ) { + case BSLASH : + escaped= YES ; + gr_add(&varval,*ptr) ; + break ; case STAR : - if ( star ) { - while ( length-- ) gr_add(&varval,*star++|NO_SCAN) ; + if ( star && !escaped ) { + while ( length-- ) { + gr_add(&varval,BSLASH) ; + gr_add(&varval,*star++) ; + } break ; } + /* FALLTHROUGH */ default : + escaped= NO ; gr_add(&varval,*ptr) ; break ; } @@ -533,15 +536,16 @@ void doassign(const char *line, const char *star, int length) { #define ISBLANK(c) ( (c)==SPACE || (c)==TAB ) -static void unravel(char *line, void (*action)(char *)) { +static void unravel(const char *line, void (*action)(char *)) { /* Unravel the line, get arguments a la shell */ /* each argument is handled to action */ /* The input string is left intact */ - register char *in_c ; - register int token ; - enum { BLANK, ARG } state = BLANK ; + const char *in_c ; + int token ; + enum { BLANK, ARG, ESCAPED } state = BLANK ; growstring argum ; + /* Loop for each character of line, including final '\0' */ in_c=line ; for (;;) { token= *in_c&0377 ; @@ -549,9 +553,13 @@ static void unravel(char *line, void (*action)(char *)) { case BLANK : if ( token==0 ) break ; if ( !ISBLANK(token) ) { - state= ARG ; gr_init(&argum) ; - gr_add(&argum,token&~NO_SCAN) ; + gr_add(&argum,token) ; + if ( token == BSLASH ) { + state= ESCAPED ; + } else { + state= ARG ; + } } break ; case ARG : @@ -561,84 +569,94 @@ static void unravel(char *line, void (*action)(char *)) { gr_throw(&argum) ; state=BLANK ; } else { - gr_add(&argum,token&~NO_SCAN) ; + gr_add(&argum,token) ; + if ( token == BSLASH ) state= ESCAPED ; } break ; + case ESCAPED : + gr_add(&argum,token) ; + state= ARG ; + break ; } if ( token == 0 ) break ; in_c++ ; } } -static char *c_rep(char *string, char *place, char *rep) { - /* Produce a string in stable storage produced from 'string' - with the character at place replaced by rep - */ - growstring name ; - register char *nc ; - register char *xc ; - - gr_init(&name) ; - for ( nc=string ; *nc && ncp_path)) ; + gr_init(&argum); + for ( in_c= prefix1 ; *in_c ; in_c++ ) { + gr_add(&argum,*in_c) ; + } + for ( in_c= prefix2 ; *in_c ; in_c++ ) { + gr_add(&argum,*in_c) ; + } + for ( in_c= string ; *in_c ; in_c++ ) { + token= *in_c&0377 ; + if ( escaped ) { + /* Strip BSLASH, keep escaped character. */ + gr_add(&argum,token) ; + escaped= NO ; + continue; + } + switch ( token ) { + case BSLASH: + escaped= YES ; + break; + case C_IN: /* Input file */ + if ( in.p_path ) { /* Not for the combiners */ + for ( tr= in.p_path ; *tr; tr++ ) { + gr_add(&argum,*tr); } + } else { /* For the combiners */ + gr_add(&argum,0); + tr= gr_final(&argum); + in_c++; + scanlist( l_first(*comb_args), elem ) { + char *p = p_cont(*elem)->p_path ; + addargs3(tr,p,in_c) ; + } + throws(tr); + return; } - return ; - } - if ( in.p_path ) { /* Not for the combiners */ - temp=c_rep(string,repc,in.p_path) ; - addargs(temp) ; - throws(temp) ; - } else { /* For the combiners */ - scanlist( l_first(*comb_args), elem ) { - temp=c_rep(string,repc,p_cont(*elem)->p_path); - addargs(temp) ; - throws(temp) ; - } - } - return ; - } - repc=strchr(string,C_OUT) ; - if ( repc ) { - /* replace the outfile token as with the infile token */ + break; + case C_OUT: /* Output file */ #ifdef DEBUG - if ( !out.p_path ) fatal("missing output filename") ; + if ( !out.p_path ) fatal("missing output filename") ; #endif - temp=c_rep(string,repc,out.p_path) ; - addargs(temp) ; - throws(temp) ; - return ; + for ( tr= out.p_path ; *tr ; tr++ ) { + gr_add(&argum,*tr) ; + } + break; + default: + gr_add(&argum,token) ; + break; + } } - temp= keeps(string) ; - clr_noscan(temp) ; - l_add(curargs,temp) ; + gr_add(&argum,0) ; + tr= gr_final(&argum) ; + l_add(curargs,tr) ; +} + +static void addargs(char *string) { + addargs3("", "", string) ; } static void getcallargs(trf *phase) { @@ -646,11 +664,11 @@ static void getcallargs(trf *phase) { arg1= scanvars(phase->t_argd) ; #ifdef DEBUG - if ( debug>=3 ) { vprint("\tvars: ") ; prns(gr_start(arg1)) ; } + if ( debug>=3 ) vprint("\tvars: %s", gr_start(arg1)) ; #endif arg2= scanexpr(gr_start(arg1)) ; #ifdef DEBUG - if ( debug>=3 ) { vprint("\texpr: ") ; prns(gr_start(arg2)) ; } + if ( debug>=3 ) vprint("\texpr: %s", gr_start(arg2)) ; #endif gr_throw(&arg1) ; curargs= &phase->t_args ; @@ -658,3 +676,40 @@ static void getcallargs(trf *phase) { unravel( gr_start(arg2), addargs ) ; gr_throw(&arg2) ; } + +static growstring without_bslash(const char *string) { + /* Strip backslashes from a copy of the string. */ + growstring result; + const char *in_c ; + int token ; + int escaped = NO ; + + gr_init(&result) ; + for ( in_c= string ; *in_c ; in_c++ ) { + token= *in_c&0377 ; + if ( token==BSLASH && !escaped ) { + escaped= YES ; + } else { + gr_add(&result,token); + escaped= NO ; + } + } + gr_add(&result,0); + return result; +} + +static void getprogram(trf *phase) { + growstring prog1, prog2 ; + const char *in_c ; + int token ; + int escaped = NO ; + + /* Expand string variables in program name. */ + prog1= scanvars(phase->t_prog) ; + throws(phase->t_prog) ; + + /* Strip backslashes. */ + prog2= without_bslash(gr_start(prog1)); + gr_throw(&prog1); + phase->t_prog= gr_final(&prog2); +} diff --git a/util/ack/util.c b/util/ack/util.c index caad71cdd..b3754f28e 100644 --- a/util/ack/util.c +++ b/util/ack/util.c @@ -46,9 +46,6 @@ char *ack_basename(const char *string) { case '/' : last_start=fetch+1 ; break ; case 0 : goto out ; } - if ( !isascii(ctoken) || !isprint(ctoken) ) { - werror("non-ascii characters in argument %s",string) ; - } } out: if ( ! *last_start ) fuerror("empty filename \"%s\"",string) ; @@ -61,13 +58,6 @@ out: return retval ; } -void clr_noscan(char *str) { - register char *ptr ; - for ( ptr=str ; *ptr ; ptr++ ) { - *ptr&= ~NO_SCAN ; - } -} - char *skipblank(char *str) { register char *ptr ; @@ -105,15 +95,6 @@ void vprint(const char* fmt, ...) va_end(ap); } -#ifdef DEBUG -void prns(const char *s) { - for ( ; *s ; s++ ) { - putc((*s&0377)&~NO_SCAN,STDOUT) ; - } - putc('\n',STDOUT) ; -} -#endif - /* VARARGS1 */ void fuerror(const char *fmt, ...) { /* Fatal user error */ From 486c5162422f0f89aa3b89a91c4cc849bede0fe4 Mon Sep 17 00:00:00 2001 From: George Koehler Date: Tue, 15 Nov 2016 11:58:13 -0500 Subject: [PATCH 011/173] Stop trying to remove core dumps. unlink("core") doesn't work with OpenBSD, where core dumps have names like "ncg.core". Users who don't want core dumps can turn them off with "ulimit -c 0" in sh(1). Then the system doesn't write a core dump. That's better than writing core then unlinking it. --- util/ack/ack.1.X | 2 +- util/ack/run.c | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/util/ack/ack.1.X b/util/ack/ack.1.X index 689992ac7..1e35bca81 100644 --- a/util/ack/ack.1.X +++ b/util/ack/ack.1.X @@ -100,7 +100,7 @@ Note: \fIack\fP refuses to overwrite argument \fI.e\fP files. .IP \-t Preserve all intermediate files. If two \fB\-t\fP are used, -\fIack\fP also preserves core dumps and output of failed transformations. +\fIack\fP also preserves output of failed transformations. .IP \-w Suppress all warning messages. diff --git a/util/ack/run.c b/util/ack/run.c index ed88d66c7..32cb59fe5 100644 --- a/util/ack/run.c +++ b/util/ack/run.c @@ -87,8 +87,6 @@ static int run_exec(trf *phase, const char *prog) { } } while ( waitchild!=child) ; if ( status ) { - if ( status&0200 && (status&0177)!=SIGQUIT && - t_flag<=1 ) unlink("core") ; switch ( status&0177 ) { case 0 : break ; From 6e31d46d6f353931d192d1a4dd3277f332cbc980 Mon Sep 17 00:00:00 2001 From: George Koehler Date: Sat, 19 Nov 2016 19:23:42 -0500 Subject: [PATCH 012/173] Fix my typo to put symbol "begrom" in correct section. --- plat/osx386/boot.s | 2 +- plat/osxppc/boot.s | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/plat/osx386/boot.s b/plat/osx386/boot.s index f3ad75fd2..932a716e9 100644 --- a/plat/osx386/boot.s +++ b/plat/osx386/boot.s @@ -48,7 +48,7 @@ EXIT: push 1 jmp __exit -.sect rom +.sect .rom begrom: .sect .data diff --git a/plat/osxppc/boot.s b/plat/osxppc/boot.s index f99e70e2d..e96198eb4 100644 --- a/plat/osxppc/boot.s +++ b/plat/osxppc/boot.s @@ -39,7 +39,7 @@ begtext: b __m_a_i_n -.sect rom +.sect .rom begrom: .sect .data From 88c2ea63aa5ea3d4ca5b8e17067fceb377270f03 Mon Sep 17 00:00:00 2001 From: George Koehler Date: Sun, 20 Nov 2016 11:38:16 -0500 Subject: [PATCH 013/173] Use uint32_t in util/led/main.c This uses uint32_t for the base, file offset, and alignment of each section, to be consistent with the usage of uint32_t in h/out.h Also declare setbit() as static. --- util/led/main.c | 40 ++++++++++++++++------------------------ 1 file changed, 16 insertions(+), 24 deletions(-) diff --git a/util/led/main.c b/util/led/main.c index 426438ec6..7b0fced7a 100644 --- a/util/led/main.c +++ b/util/led/main.c @@ -11,6 +11,7 @@ static char rcsid[] = "$Id$"; */ #include +#include #include #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 norm_commons(); static complete_sections(); static change_names(); +static bool setbit(); static bool tstbit(); static second_pass(); static pass2(); @@ -249,12 +251,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') { @@ -289,22 +290,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) @@ -316,13 +312,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; @@ -457,8 +449,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; From 19310d2521ddf88e896ecf9c4ee5a1fe7fe9aab8 Mon Sep 17 00:00:00 2001 From: George Koehler Date: Tue, 22 Nov 2016 11:13:14 -0500 Subject: [PATCH 014/173] Make possible to #include . This header declares functions in libobject. Our programs never included object.h, but called functions in libobject without declaring them. So, our build system never put object.h in the include path; any #include would fail to find the header. With this commit, a program may #include if it has modules/src/object+lib in its deps. Declare structs in object.h so we can use them in prototypes without gcc warning, "'struct whatever' declared inside parameter list". Remove inclusion of ansi.h from object.h. Programs would need to depend on modules+headers to get ansi.h in the include path. --- modules/src/object/build.lua | 1 + modules/src/object/object.h | 72 +++++++++++++++++++----------------- 2 files changed, 39 insertions(+), 34 deletions(-) diff --git a/modules/src/object/build.lua b/modules/src/object/build.lua index c30c7e54a..6a8bea04e 100644 --- a/modules/src/object/build.lua +++ b/modules/src/object/build.lua @@ -1,6 +1,7 @@ clibrary { name = "lib", srcs = { "./*.c" }, + hdrs = { "./object.h" }, deps = { "modules+headers", "h+local", diff --git a/modules/src/object/object.h b/modules/src/object/object.h index 68a5ea99f..d6c218a2a 100644 --- a/modules/src/object/object.h +++ b/modules/src/object/object.h @@ -4,42 +4,46 @@ * See the copyright notice in the ACK home directory, in the file "Copyright". */ -#include - #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__ */ From 98f2273d97b85f55aa950b1d439714c054cf2d32 Mon Sep 17 00:00:00 2001 From: George Koehler Date: Tue, 22 Nov 2016 17:16:30 -0500 Subject: [PATCH 015/173] Teach cvmach to emit the symbol table. This preserves the name and value of every symbol. The type and other info of a symbol might be lost. In gdb, one can now "disas main" or "disas '.ret'" to disassemble functions by name. Most symbols are in sections, so I also teach cvmach to emit the Mach section headers. The entry point in plat/osx*/descr moves down to make room for the section headers and LC_SYMTAB. I fix some bugs in calculations of cvmach. They were wrong if ROM had a greater alignment than TEXT, or if DATA did not start on a page boundary. I introduce machseg[] to simplify the mess of variables in main(). I declare most functions as static. Also, cvmach becomes the first program to #include . --- plat/osx/cvmach/build.lua | 2 - plat/osx/cvmach/cvmach.c | 418 ++++++++++++++++++++++++++++++-------- plat/osx386/descr | 2 +- plat/osxppc/descr | 2 +- 4 files changed, 332 insertions(+), 92 deletions(-) diff --git a/plat/osx/cvmach/build.lua b/plat/osx/cvmach/build.lua index ae4a18ecb..8076546c1 100644 --- a/plat/osx/cvmach/build.lua +++ b/plat/osx/cvmach/build.lua @@ -3,8 +3,6 @@ cprogram { srcs = { "./cvmach.c" }, deps = { "h+emheaders", - -- Next line only because object.h includes ansi.h - "modules+headers", "modules/src/object+lib", } } diff --git a/plat/osx/cvmach/cvmach.c b/plat/osx/cvmach/cvmach.c index f223fa6f7..0b5b6bf80 100644 --- a/plat/osx/cvmach/cvmach.c +++ b/plat/osx/cvmach/cvmach.c @@ -4,12 +4,12 @@ */ /* - * cvmach.c - convert ack.out to mach-o + * cvmach.c - convert ack.out to Mach-o * * Mostly pinched from aelflod (util/amisc/aelflod.c), which pinched * from the ARM cv (mach/arm/cv/cv.c), which pinched from the m68k2 cv * (mach/m68k2/cv/cv.c). The code to read ack.out format using - * liboject is pinched from the Xenix i386 cv (mach/i386/cv/cv.c). + * libobject is pinched from the Xenix i386 cv (mach/i386/cv/cv.c). */ #include @@ -19,11 +19,12 @@ #include #include -/* Can't find #include */ +#include /* 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; @@ -48,6 +49,7 @@ enum { #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 @@ -68,7 +70,10 @@ enum { /* 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 @@ -76,9 +81,33 @@ enum { #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, +}; -void usage(void) +static void +usage(void) { fprintf(stderr, "Usage: %s -m \n", program); @@ -86,7 +115,8 @@ void usage(void) } /* Produce an error message and exit. */ -void fatal(const char* s, ...) +static void +fatal(const char* s, ...) { va_list ap; @@ -103,22 +133,54 @@ void fatal(const char* s, ...) exit(1); } -void rd_fatal(void) +void +rd_fatal(void) { fatal("read error"); } -/* Calculate the result of a aligned to b (rounding up if necessary). - * b must be a power of two. */ -uint32_t align(uint32_t a, uint32_t b) +/* Returns n such that 2**n == a. */ +static uint32_t +log2u(uint32_t a) { - a += b - 1; - return a & ~(b-1); + 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. */ -void emit32(uint32_t value) +static void +emit32(uint32_t value) { unsigned char buffer[4]; @@ -142,7 +204,8 @@ void emit32(uint32_t value) /* Copies the contents of a section from the input stream * to the output stream. */ -void emit_section(int section_nr) +static void +emit_section(int section_nr) { struct outsect *section = &outsect[section_nr]; size_t blocksize; @@ -160,50 +223,114 @@ void emit_section(int section_nr) /* Zero fill any remaining space. */ n = section->os_size - section->os_flen; - if (n > 0) + while (n > 0) { - memset(buffer, 0, BUFSIZ); - while (n > 0) - { - blocksize = (n > BUFSIZ) ? BUFSIZ : n; - writef(buffer, 1, blocksize); - n -= blocksize; - } + blocksize = (n > sizeof(zero_pg)) ? sizeof(zero_pg) : n; + writef(zero_pg, 1, blocksize); + n -= blocksize; } } -void emit_lc_segment(char *name, uint32_t vm_ad, uint32_t vm_sz, - uint32_t f_off, uint32_t f_sz, int prot) +static void +emit_lc_segment(int i) { - char namebuf[16]; + uint32_t sz; int flags, maxprot; + char namebuf[16]; - if (prot == VM_PROT_NONE) { + if (i == 0) { /* special values for __PAGEZERO */ maxprot = VM_PROT_NONE; - flags = 4; /* NORELOC */ + 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, name, sizeof(namebuf)); + strncpy(namebuf, machseg[i].ms_name, sizeof(namebuf)); emit32(LC_SEGMENT); /* command */ - emit32(SZ_SEGMENT_COMMAND); /* size of command */ + emit32(sz); /* size of command */ writef(namebuf, 1, sizeof(namebuf)); - emit32(vm_ad); /* vm address */ - emit32(vm_sz); /* vm size */ - emit32(f_off); /* file offset */ - emit32(f_sz); /* file size */ + emit32(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(prot); /* initial protection */ - emit32(0); /* number of Mach sections */ + emit32(machseg[i].ms_prot); /* initial protection */ + emit32(machseg[i].ms_nsects); /* number of Mach sections */ emit32(flags); /* flags */ } -void emit_lc_unixthread(void) +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; @@ -238,10 +365,111 @@ void emit_lc_unixthread(void) } } - -int main(int argc, char *argv[]) +static void +emit_symbol(struct outname *np) { - uint32_t len2, len3, mach_base, pad, sz_bf_entry, sz_load_cmds; + 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, mflag = 0; /* General housecleaning and setup. */ @@ -323,54 +551,62 @@ int main(int argc, char *argv[]) rd_sect(outsect, outhead.oh_nsect); /* - * 1st Mach segment: __PAGEZERO - * 2nd Mach segment: __TEXT - * Mach headers and load commands - * ack TEXT - * ack ROM - * 3rd Mach segment: __DATA - * ack DATA - * ack BSS + * 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. */ - - /* Find entry point and check that TEXT begins there. */ - mach_base = pg_trunc(outsect[TEXT].os_base); - sz_load_cmds = 3 * SZ_SEGMENT_COMMAND + sz_thread_command; - sz_bf_entry = SZ_MACH_HEADER + sz_load_cmds; - entry = mach_base + sz_bf_entry; + 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", - 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); } - /* Check that ROM can follow TEXT in 2nd Mach segment. */ - outsect[TEXT].os_size = - align(outsect[TEXT].os_size, outsect[ROM].os_lign); - if (outsect[ROM].os_base != - outsect[TEXT].os_base + outsect[TEXT].os_size) + /* 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."); /* - * Insert padding between ROM and DATA, such that - * pg_mod(len2) == pg_mod(outsect[DATA].os_base) + * Pad between ROM and DATA such that we can map machseg[2] at + * a page boundary with DATA at its correct base address. * - * This will allow us to map the 3rd Mach segment at the - * beginning of a page, such that DATA is at its base. + * 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. */ - len2 = sz_bf_entry + outsect[TEXT].os_size + outsect[ROM].os_size; - pad = pg_mod(outsect[DATA].os_base - len2); - outsect[ROM].os_size += pad; - len2 = pg_trunc(len2 + pad); + 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); - /* Check that BSS can follow DATA in 3rd Mach segment. */ if (outsect[BSS].os_flen != 0) fatal("the bss space contains initialized data."); - if (outsect[BSS].os_base < - outsect[DATA].os_base + outsect[DATA].os_size) + 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."); - len3 = outsect[BSS].os_base - pg_trunc(outsect[DATA].os_base) + - outsect[BSS].os_size; + 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 != @@ -380,37 +616,43 @@ int main(int argc, char *argv[]) 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(4); /* number of load commands */ + emit32(5); /* number of load commands */ emit32(sz_load_cmds); /* size of load commands */ emit32(0); /* flags */ - /* vm address: vm size: - * 1st Mach segment: NULL CV_PGSZ - * 2nd Mach segment: mach_base len2 - * 3rd Mach segment: mach_base+len2 len3 - * - * file offset: file size: - * 2nd Mach segment: 0 len2 - * 3rd Mach segment: len2 DATA os_size - */ - emit_lc_segment("__PAGEZERO", 0 /* NULL */, CV_PGSZ, - 0, 0, VM_PROT_NONE); - emit_lc_segment("__TEXT", mach_base, len2, - 0, len2, VM_PROT_READ | VM_PROT_EXECUTE); - emit_lc_segment("__DATA", mach_base + len2, len3, - len2, outsect[DATA].os_size, VM_PROT_READ | VM_PROT_WRITE); + emit_lc_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"); diff --git a/plat/osx386/descr b/plat/osx386/descr index e404e7a34..9e4cf2577 100644 --- a/plat/osx386/descr +++ b/plat/osx386/descr @@ -18,7 +18,7 @@ var ARCH=i386 var PLATFORM=osx386 var PLATFORMDIR={EM}/share/ack/{PLATFORM} var CPP_F=-D__unix -var ALIGN=-a0:4 -a1:4 -a2:4096 -a3:4 -b0:0x1114 +var 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 diff --git a/plat/osxppc/descr b/plat/osxppc/descr index 7e8770428..130d2bd25 100644 --- a/plat/osxppc/descr +++ b/plat/osxppc/descr @@ -18,7 +18,7 @@ var ARCH=powerpc var PLATFORM=osxppc var PLATFORMDIR={EM}/share/ack/{PLATFORM} var CPP_F=-D__unix -var ALIGN=-a0:4 -a1:4 -a2:4096 -a3:4 -b0:0x1174 +var ALIGN=-a0:4 -a1:4 -a2:4096 -a3:4 -b0:0x129c var C_LIB={PLATFORMDIR}/libc-ansi.a # bitfields reversed for compatibility with (g)cc. # XXX this is from linux386, might be wrong for osxppc From b6b707d9df40d8bdebce51281d610f264f03e0d9 Mon Sep 17 00:00:00 2001 From: George Koehler Date: Wed, 23 Nov 2016 13:25:55 -0500 Subject: [PATCH 016/173] Make working gettimeofday() for Mac OS X. The system call puts the time in a pair of registers, not in the timeval structure. Add code to move the time to the structure, so programs see the correct time, not garbage. This fixes our example programs that use the time as a random seed. --- plat/osx386/libsys/gettimeofday.s | 11 +++++++++++ plat/osxppc/libsys/gettimeofday.s | 10 ++++++++++ 2 files changed, 21 insertions(+) diff --git a/plat/osx386/libsys/gettimeofday.s b/plat/osx386/libsys/gettimeofday.s index 3a4c2229f..43aff5fa9 100644 --- a/plat/osx386/libsys/gettimeofday.s +++ b/plat/osx386/libsys/gettimeofday.s @@ -1,7 +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 diff --git a/plat/osxppc/libsys/gettimeofday.s b/plat/osxppc/libsys/gettimeofday.s index c01bf5bae..178d17fdd 100644 --- a/plat/osxppc/libsys/gettimeofday.s +++ b/plat/osxppc/libsys/gettimeofday.s @@ -1,9 +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 From ed181a8d2015ad0d90d0ec21d64ad2822473591e Mon Sep 17 00:00:00 2001 From: David Given Date: Fri, 25 Nov 2016 20:01:43 +0100 Subject: [PATCH 017/173] Ansify Paranoia, because I was getting annoyed by all the compiler warnings on every build. --- examples/paranoia.c | 141 ++++++++++++++++++++++---------------------- 1 file changed, 70 insertions(+), 71 deletions(-) diff --git a/examples/paranoia.c b/examples/paranoia.c index f7020f71e..8a25800d9 100644 --- a/examples/paranoia.c +++ b/examples/paranoia.c @@ -15,6 +15,7 @@ This is a public domain adventure and may not be sold for profit */ +#include #include #define MOXIE 13 @@ -32,7 +33,9 @@ int plato_clone=3; int blast_door=0; int killer_count=0; -char get_char() +void character(void); + +char get_char(void) { char c; fflush(stdout); @@ -41,7 +44,7 @@ char get_char() return c; } -more() +void more(void) { printf("---------- More ----------"); #ifdef DEBUG @@ -55,8 +58,7 @@ more() }; } -new_clone(resume) -int resume; +int new_clone(int resume) { printf("\nClone %d just died.\n",clone); if (++clone>6) @@ -75,15 +77,14 @@ int resume; } } -dice_roll(number,faces) -int number, faces; +int dice_roll(int number, int faces) { int i,total=0; for(i=number;i>0;i--) total+= rand()%faces+1; return total; } -instructions() +void instructions(void) { printf("\n\n\n\nWelcome to Paranoia!\n\n"); printf("HOW TO PLAY:\n\n"); @@ -104,7 +105,7 @@ instructions() printf(" If not, you can try again later.\n"); } -character() +void character(void) { printf("===============================================================================\n"); printf("The Character : Philo-R-DMD %d\n", clone); @@ -130,9 +131,7 @@ character() printf("===============================================================================\n"); } -choose(a,aptr,b,bptr) -int a,b; -char *aptr, *bptr; +int choose(int a, char* aptr, int b, char* bptr) { printf("\nSelect \'a\' or \'b\' :\n"); printf(" a - %s.\n b - %s.\n", aptr, bptr); @@ -140,7 +139,7 @@ char *aptr, *bptr; else return b; } -page1() +int page1(void) { printf(" You wake up face down on the red and pink checked E-Z-Kleen linoleum floor.\n"); printf(" You recognise the pattern, it\'s the type preferred in the internal security\nbriefing cells. When you finally look around you, you see that you are alone\n"); @@ -148,7 +147,7 @@ page1() return 57; } -page2() +int page2(void) { printf("\"Greetings,\" says the kindly Internal Security self incrimination expert who\n"); printf("meets you at the door, \"How are we doing today?\" He offers you a doughnut\n"); @@ -166,7 +165,7 @@ page2() else return new_clone(32); } -page3() +int page3(void) { printf("You walk to the nearest Computer terminal and request more information about\n"); printf("Christmas. The Computer says, \"That is an A-1 ULTRAVIOLET ONLY IMMEDIATE\n"); @@ -174,7 +173,7 @@ page3() return choose(4,"You give your correct clearance",5,"You lie and claim Ultraviolet clearance"); } -page4() +int page4(void) { printf("\"That is classified information, Troubleshooter, thank you for your inquiry.\n"); printf(" Please report to an Internal Security self incrimination station as soon as\n"); @@ -182,7 +181,7 @@ page4() return 9; } -page5() +int page5(void) { printf("The computer says, \"Troubleshooter, you are not wearing the correct colour\n"); printf("uniform. You must put on an Ultraviolet uniform immediately. I have seen to\n"); @@ -193,7 +192,7 @@ page5() return choose(6, "You open the package and put on the uniform", 7, "You finally come to your senses and run for it"); } -page6() +int page6(void) { printf("The uniform definitely makes you look snappy and pert. It really looks\n"); printf("impressive, and even has the new lopsided lapel fashion that you admire so\n"); @@ -205,7 +204,7 @@ page6() return 8; } -page7() +int page7(void) { printf("The corridor lights dim and are replaced by red battle lamps as the Security\n"); printf("Breach alarms howl all around you. You run headlong down the corridor and\n"); @@ -232,7 +231,7 @@ page7() return 8; } -page8() +int page8(void) { printf("\"Now, about your question, citizen. Christmas was an old world marketing ploy\n"); printf("to induce lower clearance citizens to purchase vast quantities of goods, thus\n"); @@ -249,7 +248,7 @@ page8() return 10; } -page9() +int page9(void) { int choice; printf("As you walk toward the tubecar that will take you to GDH7-beta, you pass one\n"); @@ -262,7 +261,7 @@ page9() return choice; } -page10() +int page10(void) { int choice; printf("You stroll briskly down the corridor, up a ladder, across an unrailed catwalk,\n"); @@ -290,7 +289,7 @@ page10() } } -page11() +int page11(void) { printf("The printing on the folder says \"Experimental Self Briefing.\"\n"); printf("You open it and begin to read the following:\n"); @@ -321,7 +320,7 @@ page11() return choose(3,"You wish to ask The Computer for more information about Christmas",10,"You have decided to go directly to Goods Distribution Hall 7-beta"); } -page12() +int page12(void) { printf("You walk up to the door and push the button labelled \"push to exit.\"\n"); printf("Within seconds a surly looking guard shoves his face into the small plexiglass\n"); @@ -333,7 +332,7 @@ page12() return choose(11,"You sit down at the table and read the Orange packet",57,"You stare around the room some more"); } -page13() +int page13(void) { printf("You step into the shiny plasteel tubecar, wondering why the shape has always\n"); printf("reminded you of bullets. The car shoots forward the instant your feet touch\n"); @@ -346,7 +345,7 @@ page13() return 14; } -page14() +int page14(void) { printf("You manage to pull yourself out of the tubecar and look around. Before you is\n"); printf("one of the most confusing things you have ever seen, a hallway that is\n"); @@ -360,7 +359,7 @@ page14() return 22; } -page15() +int page15(void) { printf("You are set upon by a runty robot with a queer looking face and two pointy\n"); printf("rubber ears poking from beneath a tattered cap. \"Hey mister,\" it says,\n"); @@ -384,7 +383,7 @@ page15() } } -page16() +int page16(void) { printf("The doll is a good buy for fifty credits; it will make a fine Christmas present\n"); printf("for one of your friends. After the sale the robot rolls away. You can use\n"); @@ -395,7 +394,7 @@ page16() return 22; } -page17() +int page17(void) { int i, robot_hp=15; printf("You whip out your laser and shoot the robot, but not before it squeezes the\n"); @@ -432,7 +431,7 @@ page17() return 22; } -page18() +int page18(void) { printf("You walk to the centre of the hall, ogling like an infrared fresh from the\n"); printf("clone vats. Towering before you is the most unearthly thing you have ever\n"); @@ -448,7 +447,7 @@ page18() else return 20; } -page19() +int page19(void) { printf("Quickly you regain your balance, whirl and fire your laser into the Ultraviolet\n"); printf("citizen behind you. For a moment your heart leaps to your throat, then you\n"); @@ -461,7 +460,7 @@ page19() return choose(34,"You search the body, keeping an eye open for Internal Security",22,"You run away like the cowardly dog you are"); } -page20() +int page20(void) { printf("Oh no! you can\'t keep your balance. You\'re falling, falling head first into\n"); printf("the Christmas beast\'s gaping maw. It\'s a valiant struggle; you think you are\n"); @@ -473,7 +472,7 @@ page20() return 22; } -page21() +int page21(void) { printf("You have been wasting the leading citizens of Alpha Complex at a prodigious\n"); printf("rate. This has not gone unnoticed by the Internal Security squad at GDH7-beta.\n"); @@ -482,7 +481,7 @@ page21() return new_clone(45); } -page22() +int page22(void) { printf("You are searching Goods Distribution Hall 7-beta.\n"); switch(dice_roll(1,4)) @@ -494,7 +493,7 @@ page22() } } -page23() +int page23(void) { printf("You go to the nearest computer terminal and declare yourself a mutant.\n"); printf("\"A mutant, he\'s a mutant,\" yells a previously unnoticed infrared who had\n"); @@ -503,7 +502,7 @@ page23() return choose(28,"You tell them that it was really only a bad joke",24,"You want to fight it out, one against twelve"); } -page24() +int page24(void) { printf("Golly, I never expected someone to pick this. I haven\'t even designed\n"); printf("the 12 citizens who are going to make a sponge out of you. Tell you what,\n"); @@ -511,7 +510,7 @@ page24() return choose(28,"You change your mind and say it was only a bad joke",25,"You REALLY want to shoot it out"); } -page25() +int page25(void) { printf("Boy, you really can\'t take a hint!\n"); printf("They\'re closing in. Their trigger fingers are twitching, they\'re about to\n"); @@ -519,7 +518,7 @@ page25() return choose(28,"You tell them it was all just a bad joke",26,"You are going to shoot"); } -page26() +int page26(void) { printf("You can read the cold, sober hatred in their eyes (They really didn\'t think\n"); printf("it was funny), as they tighten the circle around you. One of them shoves a\n"); @@ -529,19 +528,19 @@ page26() return new_clone(32); } -page27() +int page27(void) { /* doesn't exist. Can't happen with computer version. designed to catch dice cheats */ } -page28() +int page28(void) { printf("They don\'t think it\'s funny.\n"); return 26; } -page29() +int page29(void) { printf("\"Psst, hey citizen, come here. Pssfft,\" you hear. When you peer around\n"); printf("you can see someone\'s dim outline in the shadows. \"I got some information\n"); @@ -559,7 +558,7 @@ page29() } } -page30() +int page30(void) { printf("You step into the shadows and offer the man a thirty credit bill. \"Just drop\n"); printf("it on the floor,\" he says. \"So you\'re looking for the Master Retailer, pssfft?\n"); @@ -586,7 +585,7 @@ page30() } } -page31() +int page31(void) { printf("Like any good troubleshooter you make the least expensive decision and threaten\n"); printf("him for information. With lightning like reflexes you whip out your laser and\n"); @@ -599,7 +598,7 @@ page31() return choose(30,"You pay the 30 credits",22,"You pssfft go away stupid"); } -page32() +int page32(void) { printf("Finally it\'s your big chance to prove that you\'re as good a troubleshooter\n"); printf("as your previous clone. You walk briskly to mission briefing and pick up your\n"); @@ -609,7 +608,7 @@ page32() return 22; } -page33() +int page33(void) { blast_door=1; printf("You release the megabolts on the blast door, then strain against it with your\n"); @@ -622,7 +621,7 @@ page33() else return 36; } -page34() +int page34(void) { printf("You have found a sealed envelope on the body. You open it and read:\n"); printf("\"WARNING: Ultraviolet Clearance ONLY. DO NOT READ.\n"); @@ -650,7 +649,7 @@ page34() return choose(46,"You rush off to the nearest computer terminal to expose the commies",22,"You wander off to look for more evidence"); } -page35() +int page35(void) { printf("\"Oh master,\" you hear through the gun barrel, \"where have you been? It is\n"); printf("time for the great Christmas gifting ceremony. You had better hurry and get\n"); @@ -669,7 +668,7 @@ page35() return new_clone(32); } -page36() +int page36(void) { printf("\"Congratulations, troubleshooter, you have successfully found the lair of the\n"); printf("Master Retailer and completed the Troubleshooter Training Course test mission,\"\n"); @@ -692,7 +691,7 @@ page36() } } -page37() +int page37(void) { printf("\"Come with me please, Troubleshooter,\" says the Green clearance technician\n"); printf("after he has dislodged your head from the cannon. \"You have been participating\n"); @@ -708,7 +707,7 @@ page37() return 38; } -page38() +int page38(void) { printf("\"I am Plato-B-PHI%d, head of mutant propaganda here at the training course.\n",plato_clone); printf("If you have any questions about mutants please come to me. Today I will be\n"); @@ -725,7 +724,7 @@ page38() return choose(39,"You volunteer for the test",40,"You duck behind a chair and hope the instructor doesn\'t notice you"); } -page39() +int page39(void) { printf("You bravely volunteer to test the mutant detection gun. You stand up and walk\n"); printf("down the steps to the podium, passing a very relieved Troubleshooter along the\n"); @@ -743,7 +742,7 @@ page39() return 41; } -page40() +int page40(void) { printf("You breathe a sigh of relief as Plato-B-PHI picks on the other Troubleshooter.\n"); printf("\"You down here in the front,\" says the instructor pointing at the other\n"); @@ -775,7 +774,7 @@ page40() } } -page41() +int page41(void) { printf("You stumble down the hallway of the Troubleshooter Training Course looking for\n"); printf("your next class. Up ahead you see one of the instructors waving to you. When\n"); @@ -789,7 +788,7 @@ page41() return choose(42,"You respond with the proper Illuminati code phrase, \"Ewige Blumenkraft\"",43,"You ignore this secret society contact"); } -page42() +int page42(void) { printf("\"Aha, so you are a member of the elitist Illuminati secret society,\" he says\n"); printf("loudly, \"that is most interesting.\" He turns to the large class already\n"); @@ -799,7 +798,7 @@ page42() return choose(51,"You run for it",52,"You wait for the guard"); } -page43() +int page43(void) { printf("You sit through a long lecture on how to recognise and infiltrate secret\n"); printf("societies, with an emphasis on mimicking secret handshakes. The basic theory,\n"); @@ -815,7 +814,7 @@ page43() return choose(44,"You go looking for a computer terminal",55,"You go to the graduation ceremony immediately"); } -page44() +int page44(void) { printf("You walk down to a semi-secluded part of the training course complex and\n"); printf("activate a computer terminal. \"AT YOUR SERVICE\" reads the computer screen.\n"); @@ -833,7 +832,7 @@ page44() } } -page45() +int page45(void) { printf("\"Hrank Hrank,\" snorts the alarm in your living quarters. Something is up.\n"); printf("You look at the monitor above the bathroom mirror and see the message you have\n"); @@ -847,7 +846,7 @@ page45() return 10; } -page46() +int page46(void) { printf("\"Why do you ask about the communists, Troubleshooter? It is not in the\n"); printf("interest of your continued survival to be asking about such topics,\" says\n"); @@ -855,7 +854,7 @@ page46() return choose(53,"You insist on talking about the communists",54,"You change the subject"); } -page47() +int page47(void) { printf("The Computer orders the entire Vulture squadron to terminate the Troubleshooter\n"); printf("Training Course. Unfortunately you too are terminated for possessing\n"); @@ -867,7 +866,7 @@ page47() return 0; } -page48() +int page48(void) { printf("The tubecar shoots forward as you enter, slamming you back into a pile of\n"); printf("garbage. The front end rotates upward and you, the garbage and the garbage\n"); @@ -877,14 +876,14 @@ page48() return new_clone(45); } -page49() +int page49(void) { printf("The instructor drags your inert body into a specimen detainment cage.\n"); printf("\"He\'ll make a good subject for tomorrow\'s mutant dissection class,\" you hear.\n"); return new_clone(32); } -page50() +int page50(void) { printf("You put down the other Troubleshooter, and then wisely decide to drill a few\n"); printf("holes in the instructor as well; the only good witness is a dead witness.\n"); @@ -893,27 +892,27 @@ page50() return 41; } -page51() +int page51(void) { printf("You run for it, but you don\'t run far. Three hundred strange and exotic\n"); printf("weapons turn you into a freeze dried cloud of soot.\n"); return new_clone(32); } -page52() +int page52(void) { printf("You wisely wait until the instructor returns with a Blue Internal Security\n"); printf("guard. The guard leads you to an Internal Security self incrimination station.\n"); return 2; } -page53() +int page53(void) { printf("You tell The Computer about:\n"); return choose(47,"The commies who have infiltrated the Troubleshooter Training Course\n and the impending People\'s Revolution",54,"Something less dangerous"); } -page54() +int page54(void) { printf("\"Do not try to change the subject, Troubleshooter,\" says The Computer.\n"); printf("\"It is a serious crime to ask about the communists. You will be terminated\n"); @@ -927,7 +926,7 @@ page54() else return new_clone(32); } -page55() +int page55(void) { printf("You and 300 other excited graduates are marched from the lecture hall and into\n"); printf("a large auditorium for the graduation exercise. The auditorium is\n"); @@ -955,7 +954,7 @@ page55() return 0; } -page56() +int page56(void) { printf("That familiar strange feeling of deja\'vu envelops you again. It is hard to\n"); printf("say, but whatever is on the other side of the door does not seem to be intended\n"); @@ -963,15 +962,14 @@ page56() return choose(33,"You open the door and step through",22,"You go looking for more information"); } -page57() +int page57(void) { printf("In the centre of the room is a table and a single chair. There is an Orange\n"); printf("folder on the table top, but you can\'t make out the lettering on it.\n"); return choose(11,"You sit down and read the folder",12,"You leave the room"); } -next_page(this_page) -int this_page; +int next_page(int this_page) { printf("\n"); switch (this_page) @@ -1038,10 +1036,11 @@ int this_page; } } -main() +int main(int argc, const char* argv[]) { /* srand(time(0)); */ instructions(); more(); character(); more(); while((page=next_page(page))!=0) more(); + return 0; } From bfa8e501a3c37b4b0cb8a9cda9390ba12e6c86fe Mon Sep 17 00:00:00 2001 From: David Given Date: Fri, 25 Nov 2016 20:28:41 +0100 Subject: [PATCH 018/173] Make pc86 echo console output to the serial port, so qemu can pipe it to stdout. --- plat/pc86/README | 3 +++ plat/pc86/libsys/_sys_rawwrite.s | 9 +++++++++ 2 files changed, 12 insertions(+) diff --git a/plat/pc86/README b/plat/pc86/README index 689c70844..dcbe0ba27 100644 --- a/plat/pc86/README +++ b/plat/pc86/README @@ -23,6 +23,9 @@ are stubs required to make the demo apps link. File descriptors 0, 1 and 2 represent the console. All reads block. There's enough TTY emulation to allow \n conversion and local echo (but it can't be turned off). +Console output is echoed to the serial port (without any setup). This is used +by qemu for running tests. + Example command line ==================== diff --git a/plat/pc86/libsys/_sys_rawwrite.s b/plat/pc86/libsys/_sys_rawwrite.s index 75f75aae1..ae477c6d2 100644 --- a/plat/pc86/libsys/_sys_rawwrite.s +++ b/plat/pc86/libsys/_sys_rawwrite.s @@ -21,9 +21,18 @@ __sys_rawwrite: push bp mov bp, sp + ! Write to the BIOS console. + movb al, 4(bp) movb ah, 0x0E mov bx, 0x0007 int 0x10 + + ! Also write to the serial port (used by the test suite). + + movb ah, 0x01 + xor dx, dx + int 0x14 + jmp .cret \ No newline at end of file From 5f66f06dc69ee8b89fc3dfce8a7d0ec6f7c8753d Mon Sep 17 00:00:00 2001 From: David Given Date: Fri, 25 Nov 2016 21:02:51 +0100 Subject: [PATCH 019/173] Refactored the tests to make the generic across different plats. --- plat/qemuppc/tests/build.lua | 54 ++---------------- {plat/qemuppc/tests => tests/plat}/_dummy.c | 0 {plat/qemuppc/tests => tests/plat}/brk_c.c | 0 tests/plat/build.lua | 57 +++++++++++++++++++ {plat/qemuppc/tests => tests/plat}/calloc_c.c | 0 {plat/qemuppc/tests => tests/plat}/csa_e.c | 0 {plat/qemuppc/tests => tests/plat}/csb_e.c | 0 .../tests => tests/plat}/doublecmp_e.c | 0 .../tests => tests/plat}/from_d_to_si_e.c | 0 .../tests => tests/plat}/from_d_to_ui_e.c | 0 .../tests => tests/plat}/from_si_to_d_e.c | 0 .../tests => tests/plat}/from_ui_to_d_e.c | 0 {plat/qemuppc/tests => tests/plat}/inn_e.e | 0 {plat/qemuppc/tests => tests/plat}/intadd_e.c | 0 {plat/qemuppc/tests => tests/plat}/intcmp_e.c | 0 {plat/qemuppc/tests => tests/plat}/intdiv_e.c | 0 {plat/qemuppc/tests => tests/plat}/intrem_e.c | 0 .../qemuppc/tests => tests/plat}/intshift_e.c | 0 {plat/qemuppc/tests => tests/plat}/intsub_e.c | 0 .../tests => tests/plat}/lib/build.lua | 0 {plat/qemuppc/tests => tests/plat}/lib/test.c | 0 {plat/qemuppc/tests => tests/plat}/lib/test.h | 0 .../tests => tests/plat}/newdispose_p.p | 0 .../tests => tests/plat}/testdriver.sh | 0 24 files changed, 63 insertions(+), 48 deletions(-) rename {plat/qemuppc/tests => tests/plat}/_dummy.c (100%) rename {plat/qemuppc/tests => tests/plat}/brk_c.c (100%) create mode 100644 tests/plat/build.lua rename {plat/qemuppc/tests => tests/plat}/calloc_c.c (100%) rename {plat/qemuppc/tests => tests/plat}/csa_e.c (100%) rename {plat/qemuppc/tests => tests/plat}/csb_e.c (100%) rename {plat/qemuppc/tests => tests/plat}/doublecmp_e.c (100%) rename {plat/qemuppc/tests => tests/plat}/from_d_to_si_e.c (100%) rename {plat/qemuppc/tests => tests/plat}/from_d_to_ui_e.c (100%) rename {plat/qemuppc/tests => tests/plat}/from_si_to_d_e.c (100%) rename {plat/qemuppc/tests => tests/plat}/from_ui_to_d_e.c (100%) rename {plat/qemuppc/tests => tests/plat}/inn_e.e (100%) rename {plat/qemuppc/tests => tests/plat}/intadd_e.c (100%) rename {plat/qemuppc/tests => tests/plat}/intcmp_e.c (100%) rename {plat/qemuppc/tests => tests/plat}/intdiv_e.c (100%) rename {plat/qemuppc/tests => tests/plat}/intrem_e.c (100%) rename {plat/qemuppc/tests => tests/plat}/intshift_e.c (100%) rename {plat/qemuppc/tests => tests/plat}/intsub_e.c (100%) rename {plat/qemuppc/tests => tests/plat}/lib/build.lua (100%) rename {plat/qemuppc/tests => tests/plat}/lib/test.c (100%) rename {plat/qemuppc/tests => tests/plat}/lib/test.h (100%) rename {plat/qemuppc/tests => tests/plat}/newdispose_p.p (100%) rename {plat/qemuppc/tests => tests/plat}/testdriver.sh (100%) diff --git a/plat/qemuppc/tests/build.lua b/plat/qemuppc/tests/build.lua index f0c2993c4..6581d93ef 100644 --- a/plat/qemuppc/tests/build.lua +++ b/plat/qemuppc/tests/build.lua @@ -1,49 +1,7 @@ -include("plat/build.lua") +include("tests/plat/build.lua") -local qemu = "qemu-system-ppc" -local tests = {} - -if os.execute("which "..qemu.." > /dev/null") ~= 0 then - print("warning: skipping tests which require ", qemu) -else - local testcases = filenamesof("./*.c", "./*.s", "./*.e", "./*.p") - - for _, f in ipairs(testcases) do - local fs = replace(basename(f), "%..$", "") - local _, _, lang = fs:find("_(.)$") - if not lang then - lang = "e" - end - - local bin = ackprogram { - name = fs.."_bin", - srcs = { f }, - deps = { "plat/qemuppc/tests/lib+lib" }, - vars = { - plat = "qemuppc", - lang = lang, - ackcflags = "-O0" - } - } - - tests[#tests+1] = normalrule { - name = fs, - outleaves = { "stamp" }, - ins = { - bin, - "./testdriver.sh" - }, - commands = { - "%{ins[2]} "..qemu.." %{ins[1]} 5", - "touch %{outs}" - } - } - end -end - -normalrule { - name = "tests", - outleaves = { "stamp" }, - ins = tests, - commands = { "touch %{outs}" } -} \ No newline at end of file +plat_testsuite { + name = "tests", + plat = "qemuppc", + method = "qemu-system-ppc" +} diff --git a/plat/qemuppc/tests/_dummy.c b/tests/plat/_dummy.c similarity index 100% rename from plat/qemuppc/tests/_dummy.c rename to tests/plat/_dummy.c diff --git a/plat/qemuppc/tests/brk_c.c b/tests/plat/brk_c.c similarity index 100% rename from plat/qemuppc/tests/brk_c.c rename to tests/plat/brk_c.c diff --git a/tests/plat/build.lua b/tests/plat/build.lua new file mode 100644 index 000000000..23685ba40 --- /dev/null +++ b/tests/plat/build.lua @@ -0,0 +1,57 @@ +include("plat/build.lua") + +definerule("plat_testsuite", + { + plat = { type="string" }, + method = { type="string" }, + }, + function(e) + -- Remember this is executed from the caller's directory; local + -- target names will resolve there. + local testfiles = filenamesof( + "tests/plat/*.c", + "tests/plat/*.e", + "tests/plat/*.p" + ) + + local tests = {} + for _, f in ipairs(testfiles) do + local fs = replace(basename(f), "%..$", "") + local _, _, lang = fs:find("_(.)$") + if not lang then + lang = "e" + end + + local bin = ackprogram { + name = fs.."_bin", + srcs = { f }, + deps = { "tests/plat/lib+lib" }, + vars = { + plat = e.plat, + lang = lang, + ackcflags = "-O0" + } + } + + tests[#tests+1] = normalrule { + name = fs, + outleaves = { "stamp" }, + ins = { + bin, + "tests/plat/testdriver.sh" + }, + commands = { + "%{ins[2]} "..e.method.." %{ins[1]} 5", + "touch %{outs}" + } + } + end + + return normalrule { + name = e.name, + outleaves = { "stamp" }, + ins = tests, + commands = { "touch %{outs}" } + } + end +) \ No newline at end of file diff --git a/plat/qemuppc/tests/calloc_c.c b/tests/plat/calloc_c.c similarity index 100% rename from plat/qemuppc/tests/calloc_c.c rename to tests/plat/calloc_c.c diff --git a/plat/qemuppc/tests/csa_e.c b/tests/plat/csa_e.c similarity index 100% rename from plat/qemuppc/tests/csa_e.c rename to tests/plat/csa_e.c diff --git a/plat/qemuppc/tests/csb_e.c b/tests/plat/csb_e.c similarity index 100% rename from plat/qemuppc/tests/csb_e.c rename to tests/plat/csb_e.c diff --git a/plat/qemuppc/tests/doublecmp_e.c b/tests/plat/doublecmp_e.c similarity index 100% rename from plat/qemuppc/tests/doublecmp_e.c rename to tests/plat/doublecmp_e.c diff --git a/plat/qemuppc/tests/from_d_to_si_e.c b/tests/plat/from_d_to_si_e.c similarity index 100% rename from plat/qemuppc/tests/from_d_to_si_e.c rename to tests/plat/from_d_to_si_e.c diff --git a/plat/qemuppc/tests/from_d_to_ui_e.c b/tests/plat/from_d_to_ui_e.c similarity index 100% rename from plat/qemuppc/tests/from_d_to_ui_e.c rename to tests/plat/from_d_to_ui_e.c diff --git a/plat/qemuppc/tests/from_si_to_d_e.c b/tests/plat/from_si_to_d_e.c similarity index 100% rename from plat/qemuppc/tests/from_si_to_d_e.c rename to tests/plat/from_si_to_d_e.c diff --git a/plat/qemuppc/tests/from_ui_to_d_e.c b/tests/plat/from_ui_to_d_e.c similarity index 100% rename from plat/qemuppc/tests/from_ui_to_d_e.c rename to tests/plat/from_ui_to_d_e.c diff --git a/plat/qemuppc/tests/inn_e.e b/tests/plat/inn_e.e similarity index 100% rename from plat/qemuppc/tests/inn_e.e rename to tests/plat/inn_e.e diff --git a/plat/qemuppc/tests/intadd_e.c b/tests/plat/intadd_e.c similarity index 100% rename from plat/qemuppc/tests/intadd_e.c rename to tests/plat/intadd_e.c diff --git a/plat/qemuppc/tests/intcmp_e.c b/tests/plat/intcmp_e.c similarity index 100% rename from plat/qemuppc/tests/intcmp_e.c rename to tests/plat/intcmp_e.c diff --git a/plat/qemuppc/tests/intdiv_e.c b/tests/plat/intdiv_e.c similarity index 100% rename from plat/qemuppc/tests/intdiv_e.c rename to tests/plat/intdiv_e.c diff --git a/plat/qemuppc/tests/intrem_e.c b/tests/plat/intrem_e.c similarity index 100% rename from plat/qemuppc/tests/intrem_e.c rename to tests/plat/intrem_e.c diff --git a/plat/qemuppc/tests/intshift_e.c b/tests/plat/intshift_e.c similarity index 100% rename from plat/qemuppc/tests/intshift_e.c rename to tests/plat/intshift_e.c diff --git a/plat/qemuppc/tests/intsub_e.c b/tests/plat/intsub_e.c similarity index 100% rename from plat/qemuppc/tests/intsub_e.c rename to tests/plat/intsub_e.c diff --git a/plat/qemuppc/tests/lib/build.lua b/tests/plat/lib/build.lua similarity index 100% rename from plat/qemuppc/tests/lib/build.lua rename to tests/plat/lib/build.lua diff --git a/plat/qemuppc/tests/lib/test.c b/tests/plat/lib/test.c similarity index 100% rename from plat/qemuppc/tests/lib/test.c rename to tests/plat/lib/test.c diff --git a/plat/qemuppc/tests/lib/test.h b/tests/plat/lib/test.h similarity index 100% rename from plat/qemuppc/tests/lib/test.h rename to tests/plat/lib/test.h diff --git a/plat/qemuppc/tests/newdispose_p.p b/tests/plat/newdispose_p.p similarity index 100% rename from plat/qemuppc/tests/newdispose_p.p rename to tests/plat/newdispose_p.p diff --git a/plat/qemuppc/tests/testdriver.sh b/tests/plat/testdriver.sh similarity index 100% rename from plat/qemuppc/tests/testdriver.sh rename to tests/plat/testdriver.sh From 8a58614aefa70c0805186d3c08a80876173c57a2 Mon Sep 17 00:00:00 2001 From: David Given Date: Sat, 26 Nov 2016 11:23:25 +0100 Subject: [PATCH 020/173] Rework the tests to run on pc86; lots of test fixes for the brk() test, which was nearly useless; lots of fixes to qemuppc and pc86 sbrk(), which was broken; change the pc86 console to echo output to the serial port (needed for running tests on qemu). --- .travis.yml | 1 + build.lua | 1 + plat/pc86/boot.s | 11 +++++++---- plat/pc86/include/unistd.h | 1 + plat/pc86/libsys/brk.c | 22 +++++++++++++++++++--- plat/pc86/tests/build.lua | 7 +++++++ plat/qemuppc/libsys/brk.c | 17 +++++++++++++++-- tests/plat/_dummy.c | 1 + tests/plat/brk_c.c | 32 +++++++++++++++++++++++++++----- tests/plat/build.lua | 9 ++++++++- tests/plat/from_d_to_si_e.c | 9 +++++---- tests/plat/from_d_to_ui_e.c | 5 +++-- tests/plat/from_si_to_d_e.c | 9 +++++---- tests/plat/from_ui_to_d_e.c | 5 +++-- tests/plat/inn_e.e | 34 +++++++++++++++++++++------------- tests/plat/intshift_e.c | 9 +++++---- tests/plat/intsub_e.c | 7 ++++--- tests/plat/lib/build.lua | 1 - tests/plat/lib/test.c | 2 +- tests/plat/lib/test.h | 2 +- tests/plat/testdriver.sh | 25 ++++++++++++++++++++----- 21 files changed, 155 insertions(+), 55 deletions(-) create mode 100644 plat/pc86/tests/build.lua diff --git a/.travis.yml b/.travis.yml index c6e2f5913..9db308dea 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,6 +8,7 @@ addons: packages: - ed - openbios-ppc + - qemu-system-i386 git: depth: 10 diff --git a/build.lua b/build.lua index cc550cb9e..584449834 100644 --- a/build.lua +++ b/build.lua @@ -15,6 +15,7 @@ vars.plats = { } vars.plats_with_tests = { "qemuppc", + "pc86", } local plat_packages = {} diff --git a/plat/pc86/boot.s b/plat/pc86/boot.s index 534809697..51b288e75 100644 --- a/plat/pc86/boot.s +++ b/plat/pc86/boot.s @@ -23,7 +23,7 @@ ! If you ever need to change the boot code, this needs adjusting. I recommend ! a hex editor. -PADDING = 0xB7 +PADDING = 0xB3 ! Some definitions. @@ -271,9 +271,12 @@ finished: ! Push standard parameters onto the stack and go. - push envp ! envp - push argv ! argv - push 1 ! argc + mov ax, envp + push ax + mov ax, argv + push ax + mov ax, 1 + push ax call __m_a_i_n ! fall through into the exit routine. diff --git a/plat/pc86/include/unistd.h b/plat/pc86/include/unistd.h index ea4f51c0f..174c43ad0 100644 --- a/plat/pc86/include/unistd.h +++ b/plat/pc86/include/unistd.h @@ -37,6 +37,7 @@ extern char** environ; extern void _exit(int); extern pid_t getpid(void); +extern int brk(void* addr); extern void* sbrk(int increment); extern int isatty(int d); extern off_t lseek(int fildes, off_t offset, int whence); diff --git a/plat/pc86/libsys/brk.c b/plat/pc86/libsys/brk.c index 952a9c747..293703234 100644 --- a/plat/pc86/libsys/brk.c +++ b/plat/pc86/libsys/brk.c @@ -22,7 +22,10 @@ int brk(void* newend) if ((p > (&dummy - STACK_BUFFER)) || (p < _end)) + { + errno = ENOMEM; return -1; + } current = p; return 0; @@ -31,13 +34,26 @@ int brk(void* newend) void* sbrk(int increment) { char* old; - + char* new; + if (increment == 0) return current; old = current; - if (brk(old + increment) < 0) - return OUT_OF_MEMORY; + + new = old + increment; + + if ((increment > 0) && (new <= old)) + goto out_of_memory; + else if ((increment < 0) && (new >= old)) + goto out_of_memory; + + if (brk(new) < 0) + goto out_of_memory; return old; + +out_of_memory: + errno = ENOMEM; + return OUT_OF_MEMORY; } diff --git a/plat/pc86/tests/build.lua b/plat/pc86/tests/build.lua new file mode 100644 index 000000000..fe871e450 --- /dev/null +++ b/plat/pc86/tests/build.lua @@ -0,0 +1,7 @@ +include("tests/plat/build.lua") + +plat_testsuite { + name = "tests", + plat = "pc86", + method = "qemu-system-i386" +} diff --git a/plat/qemuppc/libsys/brk.c b/plat/qemuppc/libsys/brk.c index 118bda3cf..7d49fa960 100644 --- a/plat/qemuppc/libsys/brk.c +++ b/plat/qemuppc/libsys/brk.c @@ -34,13 +34,26 @@ int brk(void* newend) void* sbrk(int increment) { char* old; + char* new; if (increment == 0) return current; old = current; - if (brk(old + increment) < 0) - return OUT_OF_MEMORY; + + new = old + increment; + + if ((increment > 0) && (new <= old)) + goto out_of_memory; + else if ((increment < 0) && (new >= old)) + goto out_of_memory; + + if (brk(new) < 0) + goto out_of_memory; return old; + +out_of_memory: + errno = ENOMEM; + return OUT_OF_MEMORY; } diff --git a/tests/plat/_dummy.c b/tests/plat/_dummy.c index 48104b5aa..a4693300f 100644 --- a/tests/plat/_dummy.c +++ b/tests/plat/_dummy.c @@ -6,3 +6,4 @@ void _m_a_i_n(void) ASSERT(0 == 0); finished(); } + diff --git a/tests/plat/brk_c.c b/tests/plat/brk_c.c index aa0f7ef99..9a07c7d3b 100644 --- a/tests/plat/brk_c.c +++ b/tests/plat/brk_c.c @@ -7,9 +7,11 @@ int main(int argc, const char* argv[]) { - void* p; + char* o; + char* p; - ASSERT(-1 == (intptr_t)brk((void*)0xffffffff)); + errno = 0; + ASSERT(-1 == brk((void*)-1)); ASSERT(ENOMEM == errno); p = sbrk(0); @@ -19,9 +21,29 @@ int main(int argc, const char* argv[]) ASSERT(p != sbrk(-8)); ASSERT(p == sbrk(0)); - /* We assume the test environment has less than 2GB of RAM. */ - ASSERT(-1 == (intptr_t)sbrk(INT_MAX)); - ASSERT(-1 == (intptr_t)sbrk(INT_MIN)); + errno = 0; + o = sbrk(INT_MAX); + if (o == (char*)-1) + ASSERT(ENOMEM == errno); + else + { + ASSERT(0 == errno); + p = sbrk(0); + ASSERT(p > o); + brk(o); + } + + errno = 0; + o = sbrk(INT_MIN); + if (o == (char*)-1) + ASSERT(ENOMEM == errno); + else + { + ASSERT(0 == errno); + p = sbrk(0); + ASSERT(p < o); + brk(o); + } finished(); } diff --git a/tests/plat/build.lua b/tests/plat/build.lua index 23685ba40..3873ed9a5 100644 --- a/tests/plat/build.lua +++ b/tests/plat/build.lua @@ -14,6 +14,13 @@ definerule("plat_testsuite", "tests/plat/*.p" ) + acklibrary { + name = "lib", + srcs = { "tests/plat/lib/test.c" }, + hdrs = { "tests/plat/lib/test.h" }, + vars = { plat = e.plat }, + } + local tests = {} for _, f in ipairs(testfiles) do local fs = replace(basename(f), "%..$", "") @@ -25,7 +32,7 @@ definerule("plat_testsuite", local bin = ackprogram { name = fs.."_bin", srcs = { f }, - deps = { "tests/plat/lib+lib" }, + deps = { "+lib" }, vars = { plat = e.plat, lang = lang, diff --git a/tests/plat/from_d_to_si_e.c b/tests/plat/from_d_to_si_e.c index 8c7e31c3e..7f51e6c5b 100644 --- a/tests/plat/from_d_to_si_e.c +++ b/tests/plat/from_d_to_si_e.c @@ -1,11 +1,12 @@ +#include #include "test.h" /* Constants in globals to defeat constant folding. */ double one = 1.0; double zero = 0.0; double minusone = -1.0; -double big = 2147483647.0; -double minusbig = -2147483648.0; +double big = (double)INT_MAX; +double minusbig = (double)INT_MIN; /* Bypasses the CRT, so there's no stdio or BSS initialisation. */ void _m_a_i_n(void) @@ -13,8 +14,8 @@ void _m_a_i_n(void) ASSERT((int)zero == 0); ASSERT((int)one == 1); ASSERT((int)minusone == -1); - ASSERT((int)big == 2147483647); - ASSERT((int)minusbig == -2147483648); + ASSERT((int)big == INT_MAX); + ASSERT((int)minusbig == INT_MIN); finished(); } \ No newline at end of file diff --git a/tests/plat/from_d_to_ui_e.c b/tests/plat/from_d_to_ui_e.c index b16667502..811780b87 100644 --- a/tests/plat/from_d_to_ui_e.c +++ b/tests/plat/from_d_to_ui_e.c @@ -1,16 +1,17 @@ +#include #include "test.h" /* Constants in globals to defeat constant folding. */ double one = 1.0; double zero = 0.0; -double big = 4294967295.0; +double big = (double)UINT_MAX; /* Bypasses the CRT, so there's no stdio or BSS initialisation. */ void _m_a_i_n(void) { ASSERT((unsigned int)zero == 0); ASSERT((unsigned int)one == 1); - ASSERT((unsigned int)big == 4294967295); + ASSERT((unsigned int)big == UINT_MAX); finished(); } \ No newline at end of file diff --git a/tests/plat/from_si_to_d_e.c b/tests/plat/from_si_to_d_e.c index e81c2f7c2..b6c7a25ba 100644 --- a/tests/plat/from_si_to_d_e.c +++ b/tests/plat/from_si_to_d_e.c @@ -1,11 +1,12 @@ +#include #include "test.h" /* Constants in globals to defeat constant folding. */ int one = 1; int zero = 0; int minusone = -1; -int big = 0x7fffffff; -int minusbig = -0x8000000; +int big = INT_MAX; +int minusbig = INT_MIN; /* Bypasses the CRT, so there's no stdio or BSS initialisation. */ void _m_a_i_n(void) @@ -13,8 +14,8 @@ void _m_a_i_n(void) ASSERT((double)zero == 0.0); ASSERT((double)one == 1.0); ASSERT((double)minusone == -1.0); - ASSERT((double)big == 2147483647.0); - /* ASSERT((double)minusbig == -2147483648.0); FIXME: fails for now */ + ASSERT((double)big == (double)INT_MAX); + /* ASSERT((double)minusbig == (double)INT_MIN); FIXME: fails for now */ finished(); } \ No newline at end of file diff --git a/tests/plat/from_ui_to_d_e.c b/tests/plat/from_ui_to_d_e.c index a3517b24c..b8e017c99 100644 --- a/tests/plat/from_ui_to_d_e.c +++ b/tests/plat/from_ui_to_d_e.c @@ -1,16 +1,17 @@ +#include #include "test.h" /* Constants in globals to defeat constant folding. */ unsigned int one_u = 1; unsigned int zero_u = 0; -unsigned int big_u = 0xffffffff; +unsigned int big_u = UINT_MAX; /* Bypasses the CRT, so there's no stdio or BSS initialisation. */ void _m_a_i_n(void) { ASSERT((double)zero_u == 0.0); ASSERT((double)one_u == 1.0); - ASSERT((double)big_u == 4294967295.0); + ASSERT((double)big_u == (double)UINT_MAX); finished(); } \ No newline at end of file diff --git a/tests/plat/inn_e.e b/tests/plat/inn_e.e index 4e53b35c5..7d27abf42 100644 --- a/tests/plat/inn_e.e +++ b/tests/plat/inn_e.e @@ -1,5 +1,5 @@ # - mes 2, 4, 4 + mes 2, EM_WSIZE, EM_PSIZE exp $_m_a_i_n pro $_m_a_i_n, 0 @@ -10,12 +10,12 @@ rom 0I1, 0I1, 0I1, 0I1 loe .1 loc 1 /* bit number */ - inn 4 + inn EM_WSIZE zeq *1 loc __LINE__ cal $fail - ass 4 + ass EM_WSIZE 1 /* Test existent bit */ @@ -24,12 +24,12 @@ rom 2I1, 0I1, 0I1, 0I1 loe .2 loc 1 /* bit number */ - inn 4 + inn EM_WSIZE zne *2 loc __LINE__ cal $fail - ass 4 + ass EM_WSIZE 2 /* Test non-existent high bit */ @@ -38,36 +38,44 @@ rom 0I1, 0I1, 0I1, 0I1 rom 0I1, 0I1, 0I1, 0I1 .31 - rom 33 /* to defeat constant folding */ + rom (EM_WSIZE*8)+1 /* to defeat constant folding */ lae .3 - loi 8 + loi EM_WSIZE*2 loe .31 /* bit number */ - inn 8 + inn EM_WSIZE*2 zeq *3 loc __LINE__ cal $fail - ass 4 + ass EM_WSIZE 3 /* Test existent high bit */ .4 +#if EM_WSIZE == 2 + rom 0I1, 0I1 + rom 2I1, 0I1 +#elif EM_WSIZE == 4 rom 0I1, 0I1, 0I1, 0I1 rom 2I1, 0I1, 0I1, 0I1 +#else + #error Unknown word size +#endif + .41 - rom 33 /* to defeat constant folding */ + rom (EM_WSIZE*8)+1 /* to defeat constant folding */ lae .4 - loi 8 + loi EM_WSIZE*2 loe .41 /* bit number */ - inn 8 + inn EM_WSIZE*2 zne *4 loc __LINE__ cal $fail - ass 4 + ass EM_WSIZE 4 cal $finished diff --git a/tests/plat/intshift_e.c b/tests/plat/intshift_e.c index dd280142c..3cc6d52f9 100644 --- a/tests/plat/intshift_e.c +++ b/tests/plat/intshift_e.c @@ -1,3 +1,4 @@ +#include #include "test.h" /* Constants in globals to defeat constant folding. */ @@ -25,8 +26,8 @@ void _m_a_i_n(void) ASSERT(((unsigned int)one >>(unsigned int)zero) == 1); ASSERT(((unsigned int)one >>(unsigned int)one) == 0); - ASSERT(((unsigned int)minusone>>(unsigned int)zero) == 0xffffffff); - ASSERT(((unsigned int)minusone>>(unsigned int)one) == 0x7fffffff); + ASSERT(((unsigned int)minusone>>(unsigned int)zero) == UINT_MAX); + ASSERT(((unsigned int)minusone>>(unsigned int)one) == (UINT_MAX>>1)); ASSERT((one <<0) == 1); ASSERT((one <<1) == 2); @@ -45,8 +46,8 @@ void _m_a_i_n(void) ASSERT(((unsigned int)one >>(unsigned int)0) == 1); ASSERT(((unsigned int)one >>(unsigned int)1) == 0); - ASSERT(((unsigned int)minusone>>(unsigned int)0) == 0xffffffff); - ASSERT(((unsigned int)minusone>>(unsigned int)1) == 0x7fffffff); + ASSERT(((unsigned int)minusone>>(unsigned int)0) == UINT_MAX); + ASSERT(((unsigned int)minusone>>(unsigned int)1) == (UINT_MAX>>1)); finished(); } \ No newline at end of file diff --git a/tests/plat/intsub_e.c b/tests/plat/intsub_e.c index 72ba0ff08..d8f67d3a3 100644 --- a/tests/plat/intsub_e.c +++ b/tests/plat/intsub_e.c @@ -1,3 +1,4 @@ +#include #include "test.h" /* Constants in globals to defeat constant folding. */ @@ -19,13 +20,13 @@ void _m_a_i_n(void) ASSERT((1 - two) == -1); ASSERT(((unsigned int)two - (unsigned int)one) == 1); - ASSERT(((unsigned int)one - (unsigned int)two) == 0xffffffff); + ASSERT(((unsigned int)one - (unsigned int)two) == UINT_MAX); ASSERT(((unsigned int)two - (unsigned int)1) == 1); - ASSERT(((unsigned int)one - (unsigned int)2) == 0xffffffff); + ASSERT(((unsigned int)one - (unsigned int)2) == UINT_MAX); ASSERT(((unsigned int)2 - (unsigned int)one) == 1); - ASSERT(((unsigned int)1 - (unsigned int)two) == 0xffffffff); + ASSERT(((unsigned int)1 - (unsigned int)two) == UINT_MAX); finished(); } \ No newline at end of file diff --git a/tests/plat/lib/build.lua b/tests/plat/lib/build.lua index cb6b5cbea..be9928c84 100644 --- a/tests/plat/lib/build.lua +++ b/tests/plat/lib/build.lua @@ -4,5 +4,4 @@ acklibrary { name = "lib", srcs = { "./test.c" }, hdrs = { "./test.h" }, - vars = { plat = "qemuppc" } } diff --git a/tests/plat/lib/test.c b/tests/plat/lib/test.c index 33d72f3ce..d05417326 100644 --- a/tests/plat/lib/test.c +++ b/tests/plat/lib/test.c @@ -25,7 +25,7 @@ void writehex(uint32_t code) void fail(uint32_t code) { - write(1, "@@FAIL on line 0x", 7); + write(1, "@@FAIL 0x", 10); writehex(code); write(1, "\n", 1); } diff --git a/tests/plat/lib/test.h b/tests/plat/lib/test.h index 96537a2cb..db16506f9 100644 --- a/tests/plat/lib/test.h +++ b/tests/plat/lib/test.h @@ -9,6 +9,6 @@ extern void writehex(uint32_t code); extern void fail(uint32_t code); #define ASSERT(condition) \ - if (!(condition)) fail(__LINE__) + do { if (!(condition)) fail(__LINE__); } while(0) #endif diff --git a/tests/plat/testdriver.sh b/tests/plat/testdriver.sh index 3424e9626..29d9063eb 100755 --- a/tests/plat/testdriver.sh +++ b/tests/plat/testdriver.sh @@ -1,5 +1,5 @@ #!/bin/sh -qemu=$1 +method=$1 img=$2 timeout=$3 @@ -13,10 +13,25 @@ trap "rm -f $result" EXIT pidfile=/tmp/$$.testdriver.pid trap "rm -f $pidfile" EXIT -( $qemu -nographic -kernel $img 2>&1 & echo $! > $pidfile ) \ - | tee $result \ - | ( timeout $timeout grep -l -q @@FINISHED ; echo ) \ - | ( read dummy && kill $(cat $pidfile) ) +case $method in + qemu-system-*) + if ! hash $method 2>/dev/null; then + echo "Warning: $method not installed, skipping test" + exit 0 + fi + + case $method in + qemu-system-i386) img="-drive file=$img,if=floppy,format=raw" ;; + qemu-system-ppc) img="-kernel $img" ;; + esac + + ( $method -nographic $img 2>&1 & echo $! > $pidfile ) \ + | tee $result \ + | ( timeout $timeout grep -l -q @@FINISHED ; echo ) \ + | ( read dummy && kill $(cat $pidfile) ) + + ;; +esac ( grep -q @@FAIL $result || ! grep -q @@FINISHED $result ) && cat $result && exit 1 exit 0 \ No newline at end of file From 90e3d45c696130a99a82a889030079db84edd12b Mon Sep 17 00:00:00 2001 From: David Given Date: Sat, 26 Nov 2016 11:29:57 +0100 Subject: [PATCH 021/173] Travis only whitelists the -x86 version of qemu. --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 9db308dea..a73c139d8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,7 +8,7 @@ addons: packages: - ed - openbios-ppc - - qemu-system-i386 + - qemu-system-x86 git: depth: 10 From cf33bd6cc46adf0abd6004898305fb87a4e3ed1d Mon Sep 17 00:00:00 2001 From: David Given Date: Sat, 26 Nov 2016 11:56:17 +0100 Subject: [PATCH 022/173] Enable tests for linuxppc via qemu-ppc. --- build.lua | 1 + plat/linux/libsys/sbrk.c | 21 +++++++++++++-------- plat/linuxppc/tests/build.lua | 7 +++++++ tests/plat/brk_c.c | 4 ---- tests/plat/lib/test.c | 1 + tests/plat/testdriver.sh | 14 ++++++++++++++ 6 files changed, 36 insertions(+), 12 deletions(-) create mode 100644 plat/linuxppc/tests/build.lua diff --git a/build.lua b/build.lua index 584449834..2b5ec62a0 100644 --- a/build.lua +++ b/build.lua @@ -14,6 +14,7 @@ vars.plats = { "rpi", } vars.plats_with_tests = { + "linuxppc", "qemuppc", "pc86", } diff --git a/plat/linux/libsys/sbrk.c b/plat/linux/libsys/sbrk.c index 7aeeecb86..f790a17cb 100644 --- a/plat/linux/libsys/sbrk.c +++ b/plat/linux/libsys/sbrk.c @@ -26,7 +26,6 @@ void* sbrk(int increment) { char* old; char* new; - char* actual; if (!current) current = (char*) _syscall(__NR_brk, 0, 0, 0); @@ -35,15 +34,21 @@ void* sbrk(int increment) return current; old = current; + new = old + increment; - actual = (char*) _syscall(__NR_brk, (quad) new, 0, 0); - if (actual < new) - { - errno = ENOMEM; - return OUT_OF_MEMORY; - } + if ((increment > 0) && (new <= old)) + goto out_of_memory; + else if ((increment < 0) && (new >= old)) + goto out_of_memory; + + if (brk(new) < 0) + goto out_of_memory; - current = actual; return old; + +out_of_memory: + errno = ENOMEM; + return OUT_OF_MEMORY; } + diff --git a/plat/linuxppc/tests/build.lua b/plat/linuxppc/tests/build.lua new file mode 100644 index 000000000..7601ab0be --- /dev/null +++ b/plat/linuxppc/tests/build.lua @@ -0,0 +1,7 @@ +include("tests/plat/build.lua") + +plat_testsuite { + name = "tests", + plat = "linuxppc", + method = "qemu-ppc" +} diff --git a/tests/plat/brk_c.c b/tests/plat/brk_c.c index 9a07c7d3b..434cec50b 100644 --- a/tests/plat/brk_c.c +++ b/tests/plat/brk_c.c @@ -10,10 +10,6 @@ int main(int argc, const char* argv[]) char* o; char* p; - errno = 0; - ASSERT(-1 == brk((void*)-1)); - ASSERT(ENOMEM == errno); - p = sbrk(0); ASSERT(p == sbrk(0)); ASSERT(p == sbrk(8)); diff --git a/tests/plat/lib/test.c b/tests/plat/lib/test.c index d05417326..df00e1089 100644 --- a/tests/plat/lib/test.c +++ b/tests/plat/lib/test.c @@ -6,6 +6,7 @@ void finished(void) { static const char s[] = "@@FINISHED\n"; write(1, s, sizeof(s)); + _exit(0); } void writehex(uint32_t code) diff --git a/tests/plat/testdriver.sh b/tests/plat/testdriver.sh index 29d9063eb..f5ca187a3 100755 --- a/tests/plat/testdriver.sh +++ b/tests/plat/testdriver.sh @@ -31,6 +31,20 @@ case $method in | ( read dummy && kill $(cat $pidfile) ) ;; + + qemu-*) + if ! hash $method 2>/dev/null; then + echo "Warning: $method not installed, skipping test" + exit 0 + fi + + $method $img > $result + ;; + + *) + echo "Error: $method not known by testdriver" + exit 1 + ;; esac ( grep -q @@FAIL $result || ! grep -q @@FINISHED $result ) && cat $result && exit 1 From 98c761d5c03ef07aa9fd2611fba090ce50fcb6e3 Mon Sep 17 00:00:00 2001 From: David Given Date: Sat, 26 Nov 2016 11:58:02 +0100 Subject: [PATCH 023/173] Enable tests for linux386 via qemu-i386. --- build.lua | 1 + plat/linux386/tests/build.lua | 7 +++++++ 2 files changed, 8 insertions(+) create mode 100644 plat/linux386/tests/build.lua diff --git a/build.lua b/build.lua index 2b5ec62a0..607a83a3b 100644 --- a/build.lua +++ b/build.lua @@ -14,6 +14,7 @@ vars.plats = { "rpi", } vars.plats_with_tests = { + "linux386", "linuxppc", "qemuppc", "pc86", diff --git a/plat/linux386/tests/build.lua b/plat/linux386/tests/build.lua new file mode 100644 index 000000000..afd12fdce --- /dev/null +++ b/plat/linux386/tests/build.lua @@ -0,0 +1,7 @@ +include("tests/plat/build.lua") + +plat_testsuite { + name = "tests", + plat = "linux386", + method = "qemu-i386" +} From dff67447fed9ae242a60207940921dd3abc1e784 Mon Sep 17 00:00:00 2001 From: David Given Date: Sat, 26 Nov 2016 12:00:59 +0100 Subject: [PATCH 024/173] qmu-system-x86 isn't in Travis' repository? Let's try qemu-user. --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index a73c139d8..6f2e25efd 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,7 +8,7 @@ addons: packages: - ed - openbios-ppc - - qemu-system-x86 + - qemu-user git: depth: 10 From a9a0b37b1491ad9691206c01f0c359aeb2751c57 Mon Sep 17 00:00:00 2001 From: David Given Date: Sat, 26 Nov 2016 12:07:08 +0100 Subject: [PATCH 025/173] Plats which use aelflod need to depend on it. --- plat/linux386/build-tools.lua | 1 + plat/linux68k/build-tools.lua | 1 + plat/linuxppc/build-tools.lua | 1 + 3 files changed, 3 insertions(+) diff --git a/plat/linux386/build-tools.lua b/plat/linux386/build-tools.lua index d711f85fd..31b8a7388 100644 --- a/plat/linux386/build-tools.lua +++ b/plat/linux386/build-tools.lua @@ -16,6 +16,7 @@ return installable { ["$(PLATDEP)/linux386/as"] = "+as", ["$(PLATDEP)/linux386/ncg"] = "+ncg", ["$(PLATIND)/descr/linux386"] = "./descr", + "util/amisc+aelflod-pkg", "util/opt+pkg", } } diff --git a/plat/linux68k/build-tools.lua b/plat/linux68k/build-tools.lua index 944e57f47..03d659a15 100644 --- a/plat/linux68k/build-tools.lua +++ b/plat/linux68k/build-tools.lua @@ -16,6 +16,7 @@ return installable { ["$(PLATDEP)/linux68k/as"] = "+as", ["$(PLATDEP)/linux68k/ncg"] = "+ncg", ["$(PLATIND)/descr/linux68k"] = "./descr", + "util/amisc+aelflod-pkg", "util/opt+pkg", } } diff --git a/plat/linuxppc/build-tools.lua b/plat/linuxppc/build-tools.lua index ce1a163d8..e48524cc9 100644 --- a/plat/linuxppc/build-tools.lua +++ b/plat/linuxppc/build-tools.lua @@ -28,6 +28,7 @@ return installable { ["$(PLATDEP)/linuxppc/mcg"] = "+mcg", ["$(PLATDEP)/linuxppc/top"] = "+top", ["$(PLATIND)/descr/linuxppc"] = "./descr", + "util/amisc+aelflod-pkg", "util/opt+pkg", } } From a596973f283ae7abba642ec4e246410fbe6d3442 Mon Sep 17 00:00:00 2001 From: David Given Date: Sat, 26 Nov 2016 12:52:09 +0100 Subject: [PATCH 026/173] OSX doesn't work; let's not bother building it. --- .travis.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 6f2e25efd..765b5cea1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,7 +1,6 @@ matrix: include: - os: linux - - os: osx addons: apt: From 2dc083f436cf611f743440982cd45c3080868ba5 Mon Sep 17 00:00:00 2001 From: David Given Date: Sat, 26 Nov 2016 12:53:36 +0100 Subject: [PATCH 027/173] Use command -v rather than hash to detect commands (command is Posix and works on OpenBSD). --- tests/plat/testdriver.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/plat/testdriver.sh b/tests/plat/testdriver.sh index f5ca187a3..1c57ee163 100755 --- a/tests/plat/testdriver.sh +++ b/tests/plat/testdriver.sh @@ -15,7 +15,7 @@ trap "rm -f $pidfile" EXIT case $method in qemu-system-*) - if ! hash $method 2>/dev/null; then + if ! command -v $method 2>/dev/null; then echo "Warning: $method not installed, skipping test" exit 0 fi @@ -33,7 +33,7 @@ case $method in ;; qemu-*) - if ! hash $method 2>/dev/null; then + if ! command -v $method 2>/dev/null; then echo "Warning: $method not installed, skipping test" exit 0 fi @@ -48,4 +48,4 @@ case $method in esac ( grep -q @@FAIL $result || ! grep -q @@FINISHED $result ) && cat $result && exit 1 -exit 0 \ No newline at end of file +exit 0 From 4633ca0886abd770879b50d22b746cd85f0d5ae2 Mon Sep 17 00:00:00 2001 From: David Given Date: Sat, 26 Nov 2016 19:25:02 +0100 Subject: [PATCH 028/173] Updated the README. --- README | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/README b/README index 701581f17..830c86cfc 100644 --- a/README +++ b/README @@ -2,7 +2,7 @@ =================================== © 1987-2005 Vrije Universiteit, Amsterdam - 2016-08-02 + 2016-11-26 INTRODUCTION @@ -19,6 +19,7 @@ probably broken. However, what's there should be sufficient to get things done and to evaluate how the full 6.1 release should work. + SUPPORT ======= @@ -31,10 +32,12 @@ Platforms: pc86 produces bootable floppy disk images for 8086 PCs linux386 produces ELF executables for PC Linux systems linux68k produces ELF executables for m68020 Linux systems +linuxppc produces ELF executables for PowerPC Linux systems cpm produces i80 CP/M .COM files rpi produces Raspberry Pi GPU binaries + INSTALLATION ============ @@ -55,6 +58,11 @@ Requirements: - (optionally) ninja; if you've got this, this will be autodetected and give you faster builds. +- (optionally) the qemu suite: if you have this installed, the build system + will detect it automatically and run the test suites for the supported + architectures. Get both the qemu-system-* platform emulators and the qemu-* + userland emulators (only works on Linux). + - about 40MB free in /tmp (or some other temporary directory). - about 6MB in the target directory. @@ -89,6 +97,7 @@ Instructions: The ACK should now be ready to use. + USAGE ===== @@ -155,6 +164,8 @@ There are some things you should be aware of. interpreter and the assembler-linkers. Only some of it builds. Look for build.lua files. + + DISCLAIMER ========== @@ -177,6 +188,6 @@ You can find the mailing list on the project's web site: Please enjoy. -David Given (dtrg on Sourceforge) +David Given (davidgiven on Github) dg@cowlark.com -2016-08-02 +2016-11-26 From 4f446467c867e25a50a340a89dbc59cb8b8063f2 Mon Sep 17 00:00:00 2001 From: David Given Date: Sat, 26 Nov 2016 21:50:56 +0100 Subject: [PATCH 029/173] Suppress spurious message when testdriver probes for a testing method. --- tests/plat/testdriver.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/plat/testdriver.sh b/tests/plat/testdriver.sh index 1c57ee163..272c6b2b7 100755 --- a/tests/plat/testdriver.sh +++ b/tests/plat/testdriver.sh @@ -15,7 +15,7 @@ trap "rm -f $pidfile" EXIT case $method in qemu-system-*) - if ! command -v $method 2>/dev/null; then + if ! command -v $method >/dev/null 2>&1 ; then echo "Warning: $method not installed, skipping test" exit 0 fi @@ -33,7 +33,7 @@ case $method in ;; qemu-*) - if ! command -v $method 2>/dev/null; then + if ! command -v $method >/dev/null 2>&1 ; then echo "Warning: $method not installed, skipping test" exit 0 fi From a69045c0e444c1c779a0768bfecef7bb4f575148 Mon Sep 17 00:00:00 2001 From: David Given Date: Sun, 27 Nov 2016 11:37:25 +0100 Subject: [PATCH 030/173] Import aap@github's B compiler. --- lang/b/distr/LICENSE | 22 + lang/b/distr/Makefile | 15 + lang/b/distr/README.md | 53 ++ lang/b/distr/abc | 95 +++ lang/b/distr/b.h | 164 ++++ lang/b/distr/b0.c | 1277 +++++++++++++++++++++++++++++ lang/b/distr/b1.c | 334 ++++++++ lang/b/distr/brt.s | 151 ++++ lang/b/distr/examples/1_var.b | 7 + lang/b/distr/examples/2_ext.b | 9 + lang/b/distr/examples/3_fun.b | 13 + lang/b/distr/examples/4_goto.b | 7 + lang/b/distr/examples/5_while.b | 10 + lang/b/distr/examples/printargs.b | 10 + lang/b/distr/lib.b | 111 +++ lang/b/distr/link.ld | 21 + 16 files changed, 2299 insertions(+) create mode 100644 lang/b/distr/LICENSE create mode 100644 lang/b/distr/Makefile create mode 100644 lang/b/distr/README.md create mode 100755 lang/b/distr/abc create mode 100644 lang/b/distr/b.h create mode 100644 lang/b/distr/b0.c create mode 100644 lang/b/distr/b1.c create mode 100644 lang/b/distr/brt.s create mode 100644 lang/b/distr/examples/1_var.b create mode 100644 lang/b/distr/examples/2_ext.b create mode 100644 lang/b/distr/examples/3_fun.b create mode 100644 lang/b/distr/examples/4_goto.b create mode 100644 lang/b/distr/examples/5_while.b create mode 100644 lang/b/distr/examples/printargs.b create mode 100644 lang/b/distr/lib.b create mode 100644 lang/b/distr/link.ld diff --git a/lang/b/distr/LICENSE b/lang/b/distr/LICENSE new file mode 100644 index 000000000..db5ca3b4b --- /dev/null +++ b/lang/b/distr/LICENSE @@ -0,0 +1,22 @@ +The MIT License (MIT) + +Copyright (c) 2013-2016 aap + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + diff --git a/lang/b/distr/Makefile b/lang/b/distr/Makefile new file mode 100644 index 000000000..283848647 --- /dev/null +++ b/lang/b/distr/Makefile @@ -0,0 +1,15 @@ +CFLAGS=-Wall -Wextra +b: b0.o b1.o + cc b0.o b1.o -o b +b0.o: b0.c b.h +b1.o: b1.c b.h + +libs: + ./abc -c brt.s lib.b + +install: b abc + cp abc $(HOME)/bin + +%.o: %.s + as --32 $^ -o $@ + diff --git a/lang/b/distr/README.md b/lang/b/distr/README.md new file mode 100644 index 000000000..d2ab5faf4 --- /dev/null +++ b/lang/b/distr/README.md @@ -0,0 +1,53 @@ +A B Compiler +============ + +abc is a compiler for the [B Programming Language](http://en.wikipedia.org/wiki/B_(programming_language)) that targets x86\_32 processors. It is currently tested under Linux but should work (or at least be easily ported) to other UNIX-like systems. The code is based on [an early C compiler (last1120c)](http://www.cs.bell-labs.com/who/dmr/primevalC.html) by Dennis Ritchie. + +Documentation +------------- + +* [The Programming Language B](http://9p.io/cm/cs/who/dmr/bintro.html) + +* [B Reference by Ken Thompson](http://9p.io/cm/cs/who/dmr/kbman.html) describes a presumably earlier variant of B, which is slightly different from the one described above. The compiler cannot understand it, but I plan to implement a compatibility mode (the differences are minor). + +Implementation +-------------- + +Since B was first implemented for machines with word addressing, some hacking was required to make it work on the byte addressed x86. Addresses filled in by the linker are always byte addresses, so pointers to these addresses are collectively stored at the end of the .data section and are then converted to word addresses at runtime, before main() is called. + +The generated assembly is *very* inefficient, not even constant expressions are reduced at compile time. Also I/O is currently not buffered. + +How to use +---------- + +The installation requires a little configuration: +'abc' is a frontend for the actual compiler which feels somewhat like gcc (it also handles assembling and linking). Before you can use it, set it's BDIR variable to the directory of the B compiler. +In the Makefile, change the directory of the 'install' rule to wherever you want your 'abc' file to reside. +Then type + + make install libs + +which compiles the compiler 'b', installs the 'abc' frontend and compiles the B runtime and library (brt.o and lib.o). + +To compile and link a B program, simply type + + abc -o outfile file1.b [file2.b ...] + +If you want to compile and assemble only: + + abc -c file1.b [file2.b ...] + +or generate only the assembly: + + abc -S file1.b [file2.b ...] + +Examples of B programs are in the 'examples' directory, they are mostly from Brian Kernighan's tutorial. + +Bugs +---- + +Since command line parameters aren't passed word-aligned, B can't handle them easily. brt.s copies the strings to another location and aligns them, the space is not dynamically allocated however and only 256 bytes are available by default. + +The library is incomplete but has some of the most important functions. + +I have only tested the compiler on an x86\_64 gentoo system. diff --git a/lang/b/distr/abc b/lang/b/distr/abc new file mode 100755 index 000000000..21cdda485 --- /dev/null +++ b/lang/b/distr/abc @@ -0,0 +1,95 @@ +#!/bin/sh +BDIR="$HOME/abc" +objs="$BDIR/brt.o $BDIR/lib.o" +BC="$BDIR/b" + +# compile in.b [out.s] +compile() { + if [ "${1##*.}" != "b" ]; then + echo "Error: can only compile b files" >&2 + exit 1 + fi + cout=$2 + [ "$cout" != "" ] || cout=${1%b}s + tmp1=`mktemp`; tmp2=`mktemp` + $BC $1 $tmp2 $tmp1 + retval=$? + cat $tmp1 $tmp2 > $cout + rm $tmp1 $tmp2 + [ $retval -eq 0 ] || rm $cout && return $retval + echo $cout + return $retval +} + +# assemble in.{sb} [out.o] +assemble() { + atmp="" + ain=$1 + aout=$2; + if [ "${1##*.}" = "b" ]; then + [ "$aout" != "" ] || aout=${ain%b}o + ain=`mktemp --suffix=.s` + compile $1 $ain >/dev/null || return 1 + atmp="foo" + elif [ "${1##*.}" = "s" ]; then + [ "$aout" != "" ] || aout=${ain%s}o + else + echo "Error: can only compile b and s files" >&2 + exit 1 + fi + as --32 -g $ain -o $aout + [ "$atmp" != "" ] && rm $ain + echo $aout +} + +out="" +action="link" +while getopts "o:Sc" o +do case "$o" in + o) out="$OPTARG";; + S) action=compile;; + c) action=assemble;; + esac +done +shift $(($OPTIND - 1)) + +# ignore -o option if more than one file given and not linking objs +if [ $# -gt 1 ]; then + if [ "$action" != "link" ]; then + out="" + fi +fi + +[ $# -ne 1 ] && havelist=yes +tmpobjs="" +for i in $@; do + if [ "$action" != "link" ]; then + [ "$havelist" = "yes" ] && echo $i: + $action $i $out >/dev/null + [ $? -eq 0 ] || break=1 + else + if [ "${i##*.}" = "o" ]; then + objs="$objs $i" + else + [ "$havelist" = "yes" ] && echo $i: + ltmp=`mktemp --suffix=.o` + tmpobjs="$tmpobjs $ltmp" + assemble $i $ltmp >/dev/null + [ $? -eq 0 ] || break=1 + fi + fi +done +if [ $break ]; then + [ "$tmpobjs" = "" ] || rm $tmpobjs + echo "Error" >&2 + exit 1 +fi +if [ "$action" = "link" ]; then + if [ "$out" = "" ]; then + out="-o a.out" + else + out="-o $out" + fi + ld -m elf_i386 -T $BDIR/link.ld $out $objs $tmpobjs + rm $tmpobjs +fi diff --git a/lang/b/distr/b.h b/lang/b/distr/b.h new file mode 100644 index 000000000..9aae94601 --- /dev/null +++ b/lang/b/distr/b.h @@ -0,0 +1,164 @@ +#include +#include +#include + +#define NCPS 8 /* chars per symbol */ +#define NCPW 4 /* chars per word */ +#define ALIGN 4 /* Passed directly to the assembler's .align */ +#define HSHSIZ 400 /* hash table size */ +#define SWSIZ 230 /* switch table size */ +#define CMSIZ 40 /* symbol stack size */ +#define SSIZE 20 /* operator and precedence stack size */ +#define OSSIZ 300*8 /* space for expression tree */ + +#define EOS 04 /* end of string marker */ + +/* + * Holds a B symbol. + * class is one of the storage classes below. + * offset is used depending on class. + */ +struct hshtab { + int class; + int offset; + int dim; + struct hshtab *next; + char name[NCPS+1]; +}; + +struct tnode { + int op; + int value; + struct tnode *tr1; + struct tnode *tr2; +}; + +struct swtab { + int swlab; + int swval; +}; + +struct hshtab hshtab[HSHSIZ]; +int hshused; +int eof; +int peekc; +char ctab[128]; +struct hshtab *bsym; +struct hshtab *paraml, *parame; +int cval; +int isn; +char symbuf[NCPS+1]; +FILE *sbufp; +int stack; +struct tnode **cp; +int *space; +int ospace[OSSIZ]; +int retlab; +int nerror; +struct swtab swtab[SWSIZ]; +struct swtab *swp; +int deflab; +extern int contlab; +extern int brklab; + +extern int opdope[]; +extern int line; +extern int peeksym, peeksym2; + +void error(char *s, ...); +void printtoken(int tok, FILE *out); +struct tnode * block(int op, int value, struct tnode *tr1, struct tnode *tr2); +void rcexpr(struct tnode *tr); +void cbranch(struct tnode *t, int lab, int val); +void jump(int lab); +void label(int l); + +#define EOFC 0 +#define SEMI 1 +#define LBRACE 2 +#define RBRACE 3 +#define LBRACK 4 +#define RBRACK 5 +#define LPARN 6 +#define RPARN 7 +#define COLON 8 +#define COMMA 9 + +#define MCALL 15 +#define CALL 16 +#define DECBEF 17 +#define INCBEF 18 +#define DECAFT 19 +#define INCAFT 20 +#define EXCLA 21 +#define NEG 22 +#define AMPER 23 +#define STAR 24 +#define QUEST 25 + +#define PLUS 30 +#define MINUS 31 +#define MOD 32 +#define TIMES 33 +#define DIVIDE 34 +#define OR 35 +#define AND 36 +#define LSHIFT 37 +#define RSHIFT 38 +#define EQUAL 39 +#define NEQUAL 40 +#define LESSEQ 41 +#define LESS 42 +#define GREATEQ 43 +#define GREAT 44 + +#define ASSIGN 49 +#define ASPLUS 50 +#define ASMINUS 51 +#define ASMOD 52 +#define ASTIMES 53 +#define ASDIV 54 +#define ASOR 55 +#define ASAND 56 +#define ASLSH 57 +#define ASRSH 58 +#define ASEQUAL 59 +#define ASNEQL 60 +#define ASLEQ 61 +#define ASLESS 62 +#define ASGTQ 63 +#define ASGREAT 64 + +#define CON 65 +#define STRING 66 +#define NAME 67 +#define KEYW 68 + +#define SQUOTE 121 +#define DQUOTE 122 +#define NEWLN 123 +#define SPACE 124 +#define LETTER 125 +#define DIGIT 126 +#define UNKN 127 + +#define SEOF 200 + +/* storage classes */ +#define AUTO 1 +#define EXTERN 2 +#define INTERN 3 +#define ARG 4 +#define KEYWF 5 + +/* keywords */ +#define CASE 3 +#define IF 4 +#define ELSE 5 +#define WHILE 6 +#define SWITCH 7 +#define GOTO 8 +#define RETURN 9 +#define DEFAULT 10 +#define BREAK 11 + diff --git a/lang/b/distr/b0.c b/lang/b/distr/b0.c new file mode 100644 index 000000000..424e1afdb --- /dev/null +++ b/lang/b/distr/b0.c @@ -0,0 +1,1277 @@ +#include "b.h" + +void extdef(void); +struct hshtab * lookup(void); +void blkhed(void); +void blkend(void); +void retseq(void); +void statement(int d); +struct tnode * tree(void); +void errflush(int o); + +int line = 1; +int peeksym = -1, peeksym2 = -1;; +int contlab = -1; +int brklab = -1; + +void +init(char *s, int val) +{ + char *sp; + struct hshtab *np; + + sp = symbuf; + while (sp < symbuf+NCPS+1) + if ((*sp++ = *s++) == '\0') + s--; + np = lookup(); + np->class = KEYWF; + np->offset = val; +} + +int +main(int argc, char *argv[]) +{ + if (argc < 3) { + error("Arg count"); + exit(1); + } + if (freopen(argv[1], "r", stdin) == NULL) { + error("Can't find %s", argv[1]); + exit(1); + } + if ((sbufp=fopen(argv[2], "w")) == NULL) { + error("Can't create %s", argv[2]); + exit(1); + } + if (argc > 3) { + if (freopen(argv[3], "w", stdout) == NULL) { + error("Can't create %s", argv[2]); + exit(1); + } + } + init("auto", AUTO); + init("extrn", EXTERN); + init("case", CASE); + init("if", IF); + init("else", ELSE); + init("while", WHILE); + init("switch", SWITCH); + init("goto", GOTO); + init("return", RETURN); + init("default", DEFAULT); + init("break", BREAK); + fprintf(sbufp, "\t.data\n"); + while (!eof) { + extdef(); + blkend(); + } + return nerror != 0; +} + +/* + * Lexer + */ + +int +spnextchar(void) +{ + int c; + + if ((c = peekc) == 0) + c = getchar(); + if (c == '\t') + c = ' '; + else if (c == '\n') { + c = ' '; + line++; + } + peekc = c; + return c; +} + +int +nextchar(void) +{ + while (spnextchar() == ' ') + peekc = 0; + return peekc; +} + +int +subseq(int c, int a, int b) +{ + if (spnextchar() != c) + return a; + peekc = 0; + return b; +} + +/* Only decimal and octal bases, could extend */ +int +getnum(void) +{ + int base; + int c; + + base = 10; + cval = 0; + if ((c=spnextchar()) == '0') + base = 8; + for (; ctab[c] == DIGIT; c = getchar()) + cval = cval*base + c-'0'; + peekc = c; + return CON; +} + +int +mapch(char c) +{ + int a; + + if ((a=getchar()) == c) + return -1; + switch (a) { + + case '\n': + case '\0': + error("Nonterminated string"); + peekc = a; + return -1; + + case '*': + switch (a=getchar()) { + + case 't': + return('\t'); + + case 'n': + return('\n'); + + case '0': + return('\0'); + + case '(': + return('{'); + + case ')': + return('}'); + + case 'e': + return(EOS); + + case '\n': + line++; + return('\n'); + } + } + return a; +} + +int +getcc(void) +{ + char *cp; + int c, cc; + + cval = 0; + cc = 0; + cp = (char*) &cval; + while ((c = mapch('\'')) >= 0) + if (cc++ < NCPW) + *cp++ = c; + if (cc > NCPW) + error("Long character constant"); + return CON; +} + +int +getstr(void) +{ + int c; + int i; + + fprintf(sbufp, "\t.align 4\n"); + fprintf(sbufp, "L%d:", cval = isn++); + if ((c = mapch('"')) >= 0) + fprintf(sbufp, "\t.byte %04o", c); + for (i = 2; (c = mapch('"')) >= 0; i++) + fprintf(sbufp, ",%04o", c); + fprintf(sbufp, ",04"); + while ((i++%4) != 0) + fprintf(sbufp, ",00"); + fprintf(sbufp, "\n"); + return STRING; +} + +struct hshtab * +lookup(void) +{ + int i; + char *sp, *np; + struct hshtab *rp; + + i = 0; + sp = symbuf; + while (sp < symbuf+NCPS) + i += *sp++&0177; + rp = &hshtab[i%HSHSIZ]; + while (*(np = rp->name)) { + for (sp=symbuf; sp < symbuf+NCPS;) + if (*np++ != *sp++) + goto no; + return rp; + no: + if (++rp >= &hshtab[HSHSIZ]) + rp = hshtab; + } + if (++hshused > HSHSIZ) { + error("Symbol table overflow"); + exit(1); + } + rp->class = 0; + rp->offset = 0; + rp->dim = 0; + sp = symbuf; + for (np = rp->name; sp < symbuf+NCPS+1;) + *np++ = *sp++; + return rp; +} + +/* + * Symbol peeking with one peeksym doesn't work if an ASSIGN is only peeked, + * since it itself peeks a symbol, which is then overwritten. + */ + +/* Note: does not push bsyms !! */ +int +pushsym(int sym) +{ + if (peeksym < 0) + peeksym = sym; + else if (peeksym2 < 0) { + peeksym2 = peeksym; + peeksym = sym; + } else + error("Cannot push more than two symbols\n"); + return sym; +} + +int +symbol(void) +{ + int c; + char *sp; + + if (peeksym >= 0) { + c = peeksym; + peeksym = peeksym2; + peeksym2 = -1; + return c; + } + if (peekc) { + c = peekc; + peekc = 0; + } else + if (eof) + return EOFC; + else + c = getchar(); + if (c==EOF) { + eof++; + return(EOFC); + } + +loop: + switch (ctab[c]) { + + case NEWLN: + line++; + + case SPACE: + c = getchar(); + goto loop; + + case PLUS: + return subseq(c,PLUS,INCBEF); + + case MINUS: + return subseq(c,MINUS,DECBEF); + + case LESS: + if (subseq(c,0,1)) + return LSHIFT; + return subseq('=', LESS, LESSEQ); + + case GREAT: + if (subseq(c,0,1)) + return RSHIFT; + return subseq('=', GREAT, GREATEQ); + + case ASSIGN: + if (subseq(' ',0,1)) + return ASSIGN; + /* avoid peeking a name, which could overwrite + * an already set bsym. */ + if (ctab[peekc = spnextchar()] == LETTER) + return ASSIGN; + c = symbol(); + if (PLUS <= c && c <= GREAT) + return c + ASPLUS-PLUS; + if (c == ASSIGN) + return EQUAL; + pushsym(c); + return ASSIGN; + + case EXCLA: + return subseq('=',EXCLA,NEQUAL); + + case DIVIDE: + if (subseq('*',1,0)) + return DIVIDE; + while ((c = spnextchar()) != EOFC) { + peekc = 0; + if (c == '*') { + if (spnextchar() == '/') { + peekc = 0; + c = getchar(); + goto loop; + } + } + } + eof++; + error("Nonterminated comment"); + return EOFC; + + case DIGIT: + peekc = c; + return getnum(); + + case SQUOTE: + return(getcc()); + + case DQUOTE: + return(getstr()); + + case LETTER: + sp = symbuf; + while (ctab[c] == LETTER || ctab[c] == DIGIT) { + if (sp < symbuf+NCPS) + *sp++ = c; + c = getchar(); + } + while (sp < symbuf+NCPS+1) + *sp++ = '\0'; + peekc = c; + bsym = lookup(); + if (bsym->class == KEYWF) { + cval = bsym->offset; + return KEYW; + } + return NAME; + + case UNKN: + error("Unknown character"); + c = getchar(); + goto loop; + } + return (ctab[c]); +} + +/* + * Declarations and Definitions + */ + +/* Declares a list of names to be of storage class "kw". */ +void +declare(int kw) +{ + int o; + + while ((o = symbol()) == NAME) { + if (bsym->class) + error("%s redeclared", bsym->name); + bsym->class = kw; + while ((o = symbol()) == LBRACK) { + if ((o = symbol()) == CON) { + if (bsym->dim) + error("Bad vector"); + bsym->dim = cval + 1; + o = symbol(); + } + if (o != RBRACK) + goto syntax; + } + if (kw == ARG) { + bsym->next = NULL; + if (!paraml) + paraml = bsym; + else + parame->next = bsym; + parame = bsym; + } + if (o != COMMA) + break; + } + if ((o == SEMI && kw != ARG) || (o == RPARN && kw == ARG)) + return; +syntax: + error("Declaration syntax"); + errflush(o); +} + +void +declist(void) +{ + int o; + + while ((o = symbol()) == KEYW && (cval == AUTO || cval == EXTERN)) + declare(cval); + pushsym(o); +} + +void +function(void) +{ + printf("\tpush\t%%ebp\n"); + printf("\tmov\t%%esp,%%ebp\n"); + + declare(ARG); + statement(1); + retseq(); +} + +void +global(char *s) +{ + printf("\t.globl\t_%s\n", s); + printf("\t.data\n"); + printf("\t.align %d\n", ALIGN); +} + +void +bsymb(char *s, int und) +{ + printf("\t.section .bsymb; .long %s%s; .data\n", und?"_":"", s); +} + +void +extdef(void) +{ + int o, dim, i; + char *bs; + + if ((o = symbol()) == EOFC || o == SEMI) + return; + if (o != NAME) + goto syntax; + bs = bsym->name; + i = dim = 0; + switch(o = symbol()) { + + case SEMI: + printf("\t.comm\t_%s,%d,%d\n", bs, NCPW, ALIGN); + goto done; + + /* init */ + case CON: + case STRING: + global(bs); + if (o == STRING) + bsymb(bs,1); + printf("_%s:", bs); + pushsym(o); + goto init; + + /* vector */ + case LBRACK: + if ((o=symbol()) == CON) { + dim = cval + 1; + o=symbol(); + } + if (o != RBRACK) + goto syntax; + global(bs); + if ((o=symbol()) == SEMI) { + printf("\t.comm\tL%d,%d,%d\n", isn, dim*NCPW, ALIGN); + bsymb(bs,1); + printf("_%s:\t.long L%d\n", bs, isn++); + goto done; + } + bsymb(bs,1); + printf("_%s:\t.long 1f\n1:", bs); + pushsym(o); + + init: + do { + if ((o=symbol()) != CON && o != STRING && o != NAME) + goto syntax; + if (o == NAME) { + bsymb("1f",0); + printf("1:\t.long _%s\n", bsym->name); + } else + printf("\t.long %s%d\n", o==STRING?"L":"",cval); + i++; + } while ((o=symbol()) == COMMA); + dim = (i > dim) ? i : dim; + if (dim - i) + printf("\t.zero %d\n", (dim-i)*NCPW); + if (o == SEMI) + goto done; + goto syntax; + + /* function */ + case LPARN: + global(bs); + bsymb(bs,1); + printf("_%s:\t.long 1f\n", bs); + printf("\t.text\n\t.align 4\n1:"); + function(); + done: + printf("\n"); + return; + + case EOFC: + return; + } +syntax: + error("External definition syntax"); + printtoken(o, stderr); + errflush(o); + statement(0); +} + +void +setstk(int a) +{ + int dif; + + dif = stack-a; + stack = a; + if (dif) + printf("\tsub\t$%d, %%esp\n", dif); +} + +void +defvec(void) +{ + stack -= NCPW; + printf("\tmov\t%%esp,%%eax\n"); + printf("\tshr\t$2,%%eax\n"); + printf("\tpush\t%%eax\n"); +} + +void +blkhed(void) +{ + int al, pl; + struct hshtab *bs; + + declist(); + stack = al = -4; + pl = 8; + while (paraml) { + paraml = (bs = paraml)->next; + bs->offset = pl; + pl += NCPW; + } + for (bs = hshtab; bs < &hshtab[HSHSIZ]; bs++) + if (bs->name[0]) { + if (bs->class == AUTO) { + bs->offset = al; + if (bs->dim) { + al -= bs->dim*NCPW; + setstk(al); + defvec(); + bs->offset = al; + } + al -= NCPW; + } else if (bs->class == ARG) + bs->class = AUTO; + } + setstk(al); +} + +void +blkend(void) +{ + struct hshtab *np; + + for (np = hshtab; np < &hshtab[HSHSIZ]; np++) + if (np->class != KEYWF) { + np->name[0] = '\0'; + hshused--; + } +} + +/* + * Statements and Expressions + */ + +struct tnode * +pexpr(void) +{ + struct tnode *t; + int o; + + if ((o = symbol()) != LPARN) + goto syntax; + t = tree(); + if ((o = symbol()) != RPARN) + goto syntax; + return t; +syntax: + error("Statement syntax"); + errflush(o); + return NULL; +} + +void +label(int l) +{ + printf("L%d:\n", l); +} + +void +retseq(void) +{ + printf("\tjmp\tretrn\n"); +} + +/* Jump to "lab", if the expression "t" evaluated to "val". */ +void +cbranch(struct tnode *t, int lab, int val) +{ + rcexpr(t); + if (val == 0) + printf("\ttest\t%%eax,%%eax\n"); + else + printf("\tcmp\t%%eax,$%d\n", val); + printf("\tje\tL%d\n", lab); +} + +void +jump(int lab) +{ + printf("\tjmp\tL%d\n", lab); +} + +void +pswitch(void) +{ + struct swtab *sswp; + int dl, swlab; + + sswp = swp; + if (swp == NULL) + swp = swtab; + swlab = isn++; + printf("\tmov\t$L%d,%%ebx\n", swlab); + printf("\tjmp\tbswitch\n"); + dl = deflab; + deflab = 0; + statement(0); + if (!deflab) { + deflab = isn++; + label(deflab); + } + printf("L%d:\n\t.data\nL%d:", brklab, swlab); + while (swp > sswp && swp > swtab) { + --swp; + printf("\t.long %d,L%d\n", swp->swval, swp->swlab); + } + printf("\t.long L%d,0\n", deflab); + printf("\t.text\n"); + deflab = dl; + swp = sswp; +} + +void +statement(int d) +{ + int o, o1, o2; + +stmt: + if ((o = symbol()) == LBRACE) { + if (d) + blkhed(); + while (!eof) { + if ((o = symbol()) == RBRACE) + goto bend; + pushsym(o); + statement(0); + } + error("Missing '}'"); + bend: + return; + } else { + pushsym(o); + if (d) + blkhed(); + } + + switch (o = symbol()) { + + case EOFC: + error("Unexpected EOF"); + + case SEMI: + case RBRACE: + return; + + case KEYW: + switch (cval) { + case GOTO: + if ((o = symbol()) != NAME) + goto syntax; + jump(bsym->offset); + goto semi; + + case RETURN: + if (pushsym(symbol()) == LPARN) + rcexpr(pexpr()); + retseq(); + goto semi; + + case IF: + cbranch(pexpr(), o1=isn++, 0); + statement(0); + if ((o = symbol()) == KEYW && cval == ELSE) { + jump(o2 = isn++); + label(o1); + statement(0); + label(o2); + return; + } + pushsym(o); + label(o1); + return; + + case WHILE: + o1 = contlab; + o2 = brklab; + label(contlab = isn++); + cbranch(pexpr(), brklab=isn++, 0); + statement(0); + jump(contlab); + label(brklab); + contlab = o1; + brklab = o2; + return; + + case BREAK: + if (brklab < 0) + error("Nothing to break from"); + jump(brklab); + goto semi; + + /* Not part of B, but very easy to implement */ +/* + case CONTINUE: + if (contlab < 0) + error("Nothing to continue"); + jump(contlab); + goto semi; +*/ + + case SWITCH: + o1 = brklab; + brklab = isn++; + rcexpr(pexpr()); +/* rcexpr(tree()); */ + pswitch(); + brklab = o1; + return; + + case CASE: + if ((o = symbol()) != CON) + goto syntax; + if ((o = symbol()) != COLON) + goto syntax; + if (swp == NULL) { + error("Case not in switch"); + goto stmt; + } + if (swp >= swtab+SWSIZ) + error("Switch table overflow"); + else { + swp->swlab = isn; + (swp++)->swval = cval; + label(isn++); + } + goto stmt; + + case DEFAULT: + if (swp == NULL) + error("Default not in switch"); + if ((o = symbol()) != COLON) + goto syntax; + deflab = isn++; + label(deflab); + goto stmt; + } + + error("Unknown keyword"); + goto syntax; + + case NAME: + if (peekc == ':') { + peekc = 0; + if (bsym->class) { + error("Redefinition"); + goto stmt; + } + bsym->class = INTERN; + bsym->offset = isn++; + label(bsym->offset); + goto stmt; + } + } + pushsym(o); + rcexpr(tree()); + goto semi; + +semi: + if ((o = symbol()) != SEMI) + goto syntax; + return; + +syntax: + error("Statement syntax"); + errflush(o); + goto stmt; +} + +struct tnode * +block(int op, int value, struct tnode *tr1, struct tnode *tr2) +{ + struct tnode t; + int n; + int *p, *ap; + + p = space; + t.op = op; + t.value = value; + t.tr1 = tr1; + t.tr2 = tr2; + ap = (int*) &t; + n = (sizeof(struct tnode)+sizeof(int)-1) & ~sizeof(int); + if (space+n >= &ospace[OSSIZ]) { + error("Expression overflow 1"); + exit(1); + } + while (n--) + *space++ = *ap++; + return (struct tnode *) p; +} + +void +chklval(struct tnode *p) +{ + if (p->op != NAME && p->op != STAR) + error("Lvalue required"); +} + +void +build(int op) +{ + struct tnode *p1, *p2; + int dope; + + /* a[i] -> *(a+i) */ + if (op == LBRACK) { + build(PLUS); + op = STAR; + } + dope = opdope[op]; + if (dope&01) + p2 = *--cp; + p1 = *--cp; + switch (op) { + case QUEST: + if (p2->op != COLON) + error("Illegal conditional"); + break; + + case AMPER: + if (p1->op == STAR) { + *cp++ = p1->tr1; + return; + } + if (p1->op == NAME) { + *cp++ = block(op,0,p1,NULL); + return; + } + error("Illegal lvalue"); + } + if (dope&02) + chklval(p1); + if (dope&01) + *cp++ = block(op,0,p1,p2); + else + *cp++ = block(op,0,p1,NULL); +} + +struct tnode * +tree(void) +{ + struct tnode *cmst[CMSIZ]; + int opst[SSIZE], prst[SSIZE]; + int *op, *pp; + int andflg; + int o, os; + int p, ps; + + space = ospace; + op = opst; + pp = prst; + cp = cmst; + *op = SEOF; + *pp = 06; + andflg = 0; + +advanc: + switch (o=symbol()) { + case NAME: + if (pushsym(symbol()) == LPARN) { /* function */ + bsym->class = EXTERN; + } else if (bsym->class == 0) { + error("%s undefined", bsym->name); + bsym->class = EXTERN; + } + *cp++ = block(NAME,0,(struct tnode *)bsym,NULL); + goto tand; + + case STRING: + *cp++ = block(STRING,cval,NULL,NULL); + goto tand; + + case CON: + caseCON: + *cp++ = block(CON,cval,NULL,NULL); + goto tand; + +tand: + if (cp >= &cmst[CMSIZ]) { + error("Expression overflow 2"); + exit(1); + } + if (andflg) + goto syntax; + andflg = 1; + goto advanc; + + case DECBEF: + case INCBEF: + if (andflg) + o += 2; + goto oponst; + + case EXCLA: + if (andflg) + goto syntax; + goto oponst; + + case MINUS: + if (!andflg) { + if (pushsym(symbol()) == CON) { + symbol(); + cval = -cval; + goto caseCON; + } + o = NEG; + } + andflg = 0; + goto oponst; + + case AND: + case TIMES: + if (andflg) + andflg = 0; + else + if (o == AND) + o = AMPER; + else + o = STAR; + goto oponst; + + case LPARN: + if (andflg) { + o = symbol(); + if (o == RPARN) + o = MCALL; + else { + pushsym(o); + o = CALL; + andflg = 0; + } + } + goto oponst; + + case RPARN: + case RBRACK: + if (!andflg) + goto syntax; + goto oponst; + } + + if (!andflg) + goto syntax; + andflg = 0; + +oponst: + p = (opdope[o]>>9) & 077; +opon1: + ps = *pp; + if (p > ps || (p == ps && (opdope[o]&0200))) { /* right-assoc */ + switch (o) { + case LPARN: + case LBRACK: + case CALL: + p = 04; + } + if (op >= &opst[SSIZE]) { + error("Expression overflow 3"); + exit(1); + } + *++op = o; + *++pp = p; + goto advanc; + } + --pp; + switch (os = *op--) { + case SEOF: + pushsym(o); + return(*--cp); + + case CALL: + if (o != RPARN) + goto syntax; + build(os); + goto advanc; + + case MCALL: + *cp++ = NULL; + os = CALL; + goto fbuild; + + case LPARN: + if (o != RPARN) + goto syntax; + goto advanc; + + case LBRACK: + if (o != RBRACK) + goto syntax; + build(LBRACK); + goto advanc; + + } +fbuild: + build(os); + goto opon1; +syntax: + error("Expression syntax"); + errflush(o); + return NULL; +} + +void +error(char *s, ...) +{ + va_list args; + + va_start(args, s); + nerror++; + fprintf(stderr, "%d: ", line); + vfprintf(stderr, s, args); + putc('\n', stderr); + va_end(args); +} + +void +errflush(int o) +{ + while (o > RBRACE) /* ; { } */ + o = symbol(); + pushsym(o); +} + +/* + * 000001 binary + * 000002 need lvalue + * 000004 relational + * 000010 assignment + * 000100 commutative + * 000200 right-assoc + * 0XX000 precedence + */ +int opdope[] = { + 000000, /* EOFC */ + 000000, /* ; */ + 000000, /* { */ + 000000, /* } */ + 036000, /* [ */ + 002000, /* ] */ + 036000, /* ( */ + 002000, /* ) */ + 014201, /* : */ + 007001, /* , */ + 000000, /* 10 */ + 000000, /* 11 */ + 000000, /* 12 */ + 000000, /* 13 */ + 000000, /* 14 */ + 036001, /* mcall */ + 036001, /* call */ + 034202, /* ++a */ + 034202, /* a++ */ + 034202, /* --a */ + 034202, /* a-- */ + 034200, /* !un */ + 034200, /* -un */ + 034200, /* &un */ + 034200, /* *un */ + 014201, /* ? */ + 000000, /* 26 */ + 000000, /* 27 */ + 000000, /* 28 */ + 000000, /* 29 */ + 030101, /* + */ + 030001, /* - */ + 032001, /* % */ + 032101, /* * */ + 032001, /* / */ + 016101, /* | */ + 020101, /* & */ + 026001, /* << */ + 026001, /* >> */ + 022105, /* == */ + 022105, /* != */ + 024005, /* <= */ + 024005, /* < */ + 024005, /* >= */ + 024005, /* > */ + 000000, /* 45 */ + 000000, /* 46 */ + 000000, /* 47 */ + 000000, /* 48 */ + 012013, /* = */ + 012213, /* =+ */ + 012213, /* =- */ + 012213, /* =% */ + 012213, /* =* */ + 012213, /* =/ */ + 012213, /* =| */ + 012213, /* =& */ + 012213, /* =<< */ + 012213, /* =>> */ + 012213, /* === */ + 012213, /* =!= */ + 012213, /* =<= */ + 012213, /* =< */ + 012213, /* =>= */ + 012213, /* => */ + 000000, /* CON */ + 000000, /* STRING */ + 000000 /* NAME */ +}; + +char ctab[128] = { + EOFC, UNKN, UNKN, UNKN, UNKN, UNKN, UNKN, UNKN, + LETTER, SPACE, NEWLN, SPACE, SPACE, UNKN, UNKN, UNKN, + UNKN, UNKN, UNKN, UNKN, UNKN, UNKN, UNKN, UNKN, + UNKN, UNKN, UNKN, UNKN, UNKN, UNKN, UNKN, UNKN, + SPACE, EXCLA, DQUOTE, UNKN, UNKN, MOD, AND, SQUOTE, + LPARN, RPARN, TIMES, PLUS, COMMA, MINUS, UNKN, DIVIDE, + DIGIT, DIGIT, DIGIT, DIGIT, DIGIT, DIGIT, DIGIT, DIGIT, + DIGIT, DIGIT, COLON, SEMI, LESS, ASSIGN, GREAT, QUEST, + UNKN, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, + LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, + LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, + LETTER, LETTER, LETTER, LBRACK, UNKN, RBRACK, UNKN, LETTER, + UNKN, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, + LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, + LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, + LETTER, LETTER, LETTER, LBRACE, OR, RBRACE, UNKN, UNKN +}; + +/* debug function */ +void printtoken(int tok, FILE *out) +{ + static char *strtab[128]; + strtab[0] = "EOFC"; + strtab[1] = "SEMI"; + strtab[2] = "LBRACE"; + strtab[3] = "RBRACE"; + strtab[4] = "LBRACK"; + strtab[5] = "RBRACK"; + strtab[6] = "LPARN"; + strtab[7] = "RPARN"; + strtab[8] = "COLON"; + strtab[9] = "COMMA"; + + strtab[15] = "MCALL"; + strtab[16] = "CALL"; + strtab[17] = "DECBEF"; + strtab[18] = "INCBEF"; + strtab[19] = "DECAFT"; + strtab[20] = "INCAFT"; + strtab[21] = "EXCLA"; + strtab[22] = "NEG"; + strtab[23] = "AMPER"; + strtab[24] = "STAR"; + strtab[25] = "QUEST"; + + strtab[30] = "PLUS"; + strtab[31] = "MINUS"; + strtab[32] = "MOD"; + strtab[33] = "TIMES"; + strtab[34] = "DIVIDE"; + strtab[35] = "OR"; + strtab[36] = "AND"; + strtab[37] = "LSHIFT"; + strtab[38] = "RSHIFT"; + strtab[39] = "EQUAL"; + strtab[40] = "NEQUAL"; + strtab[41] = "LESSEQ"; + strtab[42] = "LESS"; + strtab[43] = "GREATEQ"; + strtab[44] = "GREAT"; + + strtab[49] = "ASSIGN"; + strtab[50] = "ASPLUS"; + strtab[51] = "ASMINUS"; + strtab[52] = "ASMOD"; + strtab[53] = "ASTIMES"; + strtab[54] = "ASDIV"; + strtab[55] = "ASOR"; + strtab[56] = "ASAND"; + strtab[57] = "ASLSH"; + strtab[58] = "ASRSH"; + strtab[59] = "ASEQUAL"; + strtab[60] = "ASNEQL"; + strtab[61] = "ASLEQ"; + strtab[62] = "ASLESS"; + strtab[63] = "ASGTQ"; + strtab[64] = "ASGREAT"; + + strtab[65] = "CON"; + strtab[66] = "STRING"; + strtab[67] = "NAME"; + strtab[68] = "KEYW"; + + strtab[127] = "UNKN"; + + if (tok == CON || tok == STRING) { + fprintf(out, "%s(%d) ", strtab[tok], cval); + return; + } + if (tok == NAME) { + fprintf(out, "%s(%s) ", strtab[tok], symbuf); + return; + } + + fprintf(out, "%s ", strtab[tok]); +} + diff --git a/lang/b/distr/b1.c b/lang/b/distr/b1.c new file mode 100644 index 000000000..6295810ab --- /dev/null +++ b/lang/b/distr/b1.c @@ -0,0 +1,334 @@ +#include "b.h" + +/* + * Code generation (x86 assembly) + */ + +void +push(void) +{ + printf("\tpush\t%%eax\n"); +} + +void +pop(char *s) +{ + printf("\tpop\t%%%s\n", s); +} + +void +binary(struct tnode *tr) +{ + rcexpr(tr->tr1); + push(); + rcexpr(tr->tr2); +} + +int +pushargs(struct tnode *tr) +{ + int stk; + + if (tr == NULL) + return 0; + if (tr->op == COMMA) { + rcexpr(tr->tr2); + push(); + stk = pushargs(tr->tr1); + return stk+NCPW; + } + rcexpr(tr); + push(); + return NCPW; +} + +void +lvalexp(struct tnode *tr) +{ + struct hshtab *bs; + char memloc[64]; + + switch (tr->op) { + + case DECBEF: + case INCBEF: + case DECAFT: + case INCAFT: + if (tr->tr1->op == STAR) { + rcexpr(tr->tr1->tr1); + printf("\tmov\t%%eax,%%ebx\n"); + sprintf(memloc,"(,%%ebx,4)"); + } else { /* NAME, checked in "build" */ + bs = (struct hshtab *) tr->tr1->tr1; + if (bs->class == EXTERN) + sprintf(memloc,"_%s", bs->name); + else if (bs->class == AUTO) + sprintf(memloc,"%d(%%ebp)", bs->offset); + else + goto classerror; + } + if (tr->op == DECBEF || tr->op == INCBEF) { + printf("\t%s\t%s\n", tr->op == DECBEF ? "decl" : "incl", + memloc); + printf("\tmov\t%s,%%eax\n", memloc); + } else { + printf("\tmov\t%s,%%eax\n", memloc); + printf("\t%s\t%s\n", tr->op == DECAFT ? "decl" : "incl", + memloc); + } + return; + + case ASSIGN: + rcexpr(tr->tr2); + if (tr->tr1->op == STAR) { + push(); + rcexpr(tr->tr1->tr1); + pop("ebx"); + printf("\tmov\t%%ebx,(,%%eax,4)\n"); + } else { /* NAME */ + bs = (struct hshtab *) tr->tr1->tr1; + if (bs->class == EXTERN) + printf("\tmov\t%%eax,_%s\n", bs->name); + else if (bs->class == AUTO) + printf("\tmov\t%%eax,%d(%%ebp)\n", bs->offset); + else + goto classerror; + } + return; + + case ASPLUS: + case ASMINUS: + case ASMOD: + case ASTIMES: + case ASDIV: + case ASOR: + case ASAND: + case ASLSH: + case ASRSH: + case ASEQUAL: + case ASNEQL: + case ASLEQ: + case ASLESS: + case ASGTQ: + case ASGREAT: + tr->op -= ASPLUS-PLUS; + rcexpr(block(ASSIGN,0,tr->tr1,tr)); + return; + } + +classerror: + error("Storage class"); +} + +void +rcexpr(struct tnode *tr) +{ + int o1, o2; + int stk; + struct hshtab *bs; + + if (tr == NULL) + return; + + if (opdope[tr->op]&02) { + lvalexp(tr); + return; + } + + switch (tr->op) { + + case CON: + printf("\tmov\t$%d,%%eax\n", tr->value); + return; + + case STRING: + printf("\tmov\t$L%d,%%eax\n", tr->value); + printf("\tshr\t$2,%%eax\n"); + return; + + case NAME: /* only rvalue */ + bs = (struct hshtab *) tr->tr1; + if (bs->class == EXTERN) + printf("\tmov\t_%s,%%eax\n", bs->name); + else if (bs->class == AUTO) + printf("\tmov\t%d(%%ebp),%%eax\n", bs->offset); + else + goto classerror; + return; + + case CALL: + stk = pushargs(tr->tr2); + rcexpr(tr->tr1); + printf("\tshl\t$2,%%eax\n"); + printf("\tcall\t*%%eax\n"); + if (stk) + printf("\tadd\t$%d,%%esp\n",stk); + return; + + case AMPER: + bs = (struct hshtab *) tr->tr1->tr1; + if (bs->class == EXTERN) { + printf("\tmov\t$_%s,%%eax\n", bs->name); + printf("\tshr\t$2,%%eax\n"); + } else if (bs->class == AUTO) { + printf("\tlea\t%d(%%ebp),%%eax\n", bs->offset); + printf("\tshr\t$2,%%eax\n"); + } else + goto classerror; + return; + + case STAR: /* only rvalue */ + rcexpr(tr->tr1); + printf("\tmov\t(,%%eax,4),%%eax\n"); + return; + + case PLUS: + binary(tr); + pop("ebx"); + printf("\tadd\t%%ebx,%%eax\n"); + return; + + case MINUS: + binary(tr); + printf("\tmov\t%%eax,%%ebx\n"); + pop("eax"); + printf("\tsub\t%%ebx,%%eax\n"); + return; + + case TIMES: + binary(tr); + pop("ebx"); + printf("\tmul\t%%ebx\n"); + return; + + case DIVIDE: + binary(tr); + printf("\tmov\t%%eax,%%ebx\n"); + pop("eax"); + printf("\txor\t%%edx,%%edx\n"); + printf("\tdiv\t%%ebx\n"); + return; + + case MOD: + binary(tr); + printf("\tmov\t%%eax,%%ebx\n"); + pop("eax"); + printf("\txor\t%%edx,%%edx\n"); + printf("\tdiv\t%%ebx\n"); + printf("\tmov\t%%edx,%%eax\n"); + return; + + case AND: + binary(tr); + pop("ebx"); + printf("\tand\t%%ebx,%%eax\n"); + return; + + case OR: + binary(tr); + pop("ebx"); + printf("\tor\t%%ebx,%%eax\n"); + return; + + case LSHIFT: + binary(tr); + printf("\tmov\t%%eax,%%ecx\n"); + pop("eax"); + printf("\tshl\t%%cl,%%eax\n"); + return; + + case RSHIFT: + binary(tr); + printf("\tmov\t%%eax,%%ecx\n"); + pop("eax"); + printf("\tshr\t%%cl,%%eax\n"); + return; + + case EQUAL: + case NEQUAL: + case LESS: + case LESSEQ: + case GREAT: + case GREATEQ: + binary(tr); + pop("ebx"); + printf("\tcmp\t%%eax,%%ebx\n"); + switch (tr->op) { + case EQUAL: + printf("\tsete\t%%al\n"); + break; + case NEQUAL: + printf("\tsetne\t%%al\n"); + break; + case LESS: + printf("\tsetl\t%%al\n"); + break; + case LESSEQ: + printf("\tsetle\t%%al\n"); + break; + case GREAT: + printf("\tsetg\t%%al\n"); + break; + case GREATEQ: + printf("\tsetge\t%%al\n"); + break; + } + printf("\tmovzb\t%%al,%%eax\n"); + return; + + case EXCLA: + rcexpr(tr->tr1); + printf("\ttest\t%%eax,%%eax\n"); + printf("\tsete\t%%al\n"); + printf("\tmovzb\t%%al,%%eax\n"); + return; + + case NEG: + rcexpr(tr->tr1); + printf("\tneg\t%%eax\n"); + return; + + case QUEST: + cbranch(tr->tr1, o1=isn++, 0); + rcexpr(tr->tr2->tr1); + jump(o2 = isn++); + label(o1); + rcexpr(tr->tr2->tr2); + label(o2); + return; + + default: + error("Can't print tree (op: %d)", tr->op); + } + +classerror: + error("Storage class"); +} + +/* Prints the tree in RPN, for debugging */ +/* +void +rcexpr(struct tnode *tr) +{ + struct hshtab *bs; + + if (tr == NULL) + printf("(NULL) "); + else if (tr->op == CON) + printf("%d ", tr->value); + else if (tr->op == STRING) + printf("s(L%d) ", tr->value); + else if (tr->op == NAME) { + bs = (struct hshtab *)tr->tr1; + if (bs->class == AUTO) + printf("%s(%d) ", bs->name, bs->offset); + else + printf("%s ", bs->name); + } else { + rcexpr(tr->tr1); + if (opdope[tr->op]&01) + rcexpr(tr->tr2); + printtoken(tr->op, stdout); + } +} +*/ diff --git a/lang/b/distr/brt.s b/lang/b/distr/brt.s new file mode 100644 index 000000000..18f4fb351 --- /dev/null +++ b/lang/b/distr/brt.s @@ -0,0 +1,151 @@ + .globl _argv + .data + .align 4 + .comm argstr,256,4 +_argv: .long 0 + + .text + .globl start +start: + # clear bss (could be done better) + # is it actually necessary? + mov $__bss,%eax +1: + movb $0,(%eax) + inc %eax + cmp $__ebss,%eax + jbe 1b + + # copy command line args (can't use them directly, not aligned) + mov %esp,%eax + shr $2,%eax + mov %eax,_argv + mov (%esp),%ecx # number of arguments + mov $argstr,%edi +1: + mov (%esp,%ecx,4),%esi + mov %edi,%eax + shr $2,%eax + mov %eax,(%esp,%ecx,4) + call cpystr + loop 1b + + call bsymbs + mov _main,%eax + shl $2,%eax + call *%eax + mov %eax,%ebx + mov $1,%eax + int $0x80 + +# copy string from esi to edi and convert '\0' to B's '*e', align edi +cpystr: + mov (%esi),%al + test %al,%al + jz 1f + mov %al,(%edi) + inc %edi + inc %esi + jmp cpystr +1: + movb $04,(%edi) + inc %edi + add $3,%edi + and $~3,%edi + ret + +# shift addresses filled in by the linker 2 bits to the right +# so B only ever sees word addresses +bsymbs: + mov $__bsymb,%eax +1: + cmp $__ebsymb,%eax + jge 1f + mov (%eax),%ebx + mov (%ebx),%ecx + shr $2,%ecx + mov %ecx,(%ebx) + add $4,%eax + jmp 1b +1: + ret + + .globl retrn +retrn: + mov %ebp,%esp + pop %ebp + ret + +# handle switch table: +# eax has the value, ebx the address of the switch table + .globl bswitch +bswitch: + xor %ecx,%ecx +1: + mov (%ebx,%ecx,8),%edx + mov 4(%ebx,%ecx,8),%edi + test %edi,%edi + jz 1f # default (last in table) + cmp %eax,%edx + je 2f + inc %ecx + jmp 1b +1: + jmp *%edx +2: + jmp *%edi + +# +# Library functions in assembly +# + .globl _exit + .data + .align 4 + .section .bsymb; .long _exit; .data +_exit: .long 1f + .text + .align 4 +1: mov $1,%eax + mov $0,%ebx + int $0x80 + + .globl _write + .data + .align 4 + .section .bsymb; .long _write; .data +_write: .long 1f + .text + .align 4 +1: mov 4(%esp),%ebx + mov 8(%esp),%ecx + shl $2,%ecx + mov 12(%esp),%edx + mov $4,%eax + int $0x80 + ret + + .globl _read + .data + .align 4 + .section .bsymb; .long _read; .data +_read: .long 1f + .text + .align 4 +1: mov 4(%esp),%ebx + mov 8(%esp),%ecx + shl $2,%ecx + mov 12(%esp),%edx + mov $3,%eax + int $0x80 + ret + + .globl _inv + .data + .align 4 + .section .bsymb; .long _inv; .data +_inv: .long 1f + .text + .align 4 +1: mov 4(%esp),%eax + not %eax + ret diff --git a/lang/b/distr/examples/1_var.b b/lang/b/distr/examples/1_var.b new file mode 100644 index 000000000..aa315442f --- /dev/null +++ b/lang/b/distr/examples/1_var.b @@ -0,0 +1,7 @@ +main() { + auto a, b, c, sum; + + a = 1; b = 2; c = 3; + sum = a+b+c; + putnumb(sum); +} diff --git a/lang/b/distr/examples/2_ext.b b/lang/b/distr/examples/2_ext.b new file mode 100644 index 000000000..a8deac665 --- /dev/null +++ b/lang/b/distr/examples/2_ext.b @@ -0,0 +1,9 @@ +main() { + extrn a, b, c; + putchar(a); putchar(b); putchar(c); putchar('!*n'); +} + +a 'hell'; +b 'o, w'; +c 'orld'; + diff --git a/lang/b/distr/examples/3_fun.b b/lang/b/distr/examples/3_fun.b new file mode 100644 index 000000000..16d740964 --- /dev/null +++ b/lang/b/distr/examples/3_fun.b @@ -0,0 +1,13 @@ +main() { + extrn a, b, c, d; + put2char(a,b); + put2char(c,d); +} + +put2char(x,y) { +putchar(x); +putchar(y); +} + +a 'hell'; b 'o, w'; c 'orld'; d '!*n'; + diff --git a/lang/b/distr/examples/4_goto.b b/lang/b/distr/examples/4_goto.b new file mode 100644 index 000000000..2d5256afc --- /dev/null +++ b/lang/b/distr/examples/4_goto.b @@ -0,0 +1,7 @@ +main() { + auto c; +read: + c= getchar(); + putchar(c); + if(c != '*n') goto read; +} diff --git a/lang/b/distr/examples/5_while.b b/lang/b/distr/examples/5_while.b new file mode 100644 index 000000000..13baa0cac --- /dev/null +++ b/lang/b/distr/examples/5_while.b @@ -0,0 +1,10 @@ +main() { + auto c; + while (1) { + while ( (c=getchar()) != ' ') + if (putchar(c) == '*n') exit(); + putchar( '*n' ); + while ( (c=getchar()) == ' '); /* skip blanks */ + if (putchar(c)=='*n') exit(); + } +} diff --git a/lang/b/distr/examples/printargs.b b/lang/b/distr/examples/printargs.b new file mode 100644 index 000000000..444932054 --- /dev/null +++ b/lang/b/distr/examples/printargs.b @@ -0,0 +1,10 @@ +main() { + extrn argv; + auto i; + + i = 1; + printf("%d args:*n", argv[0]); + while (i <= argv[0]) + printf("%s*n", argv[i++]); + return(0); +} diff --git a/lang/b/distr/lib.b b/lang/b/distr/lib.b new file mode 100644 index 000000000..9e274eb92 --- /dev/null +++ b/lang/b/distr/lib.b @@ -0,0 +1,111 @@ +char(s, n) + return((s[n/4]>>8*(n%4))&0377); /* s[n/4] */ + +lchar(s, n, char) { + auto i; + i = 8*(n%4); + char = (char&0377)<> 8; + } + write(1, &char, 4-i); + return(char); +} + +getchar() { + auto char; + + char = 0; + read(1, &char, 1); + return(char); +} + +printn(n,b) { + extrn putchar; + auto a; + + if (a = n/b) + printn(a, b); + putchar(char("0123456789ABCDEF", n%b)); +} + +putnumb(n) { + printn(n,10); + putchar('*n'); +} + +putstr(s) { + auto c, i; + + i = 0; + while ((c = char(s,i++)) != '*e') + putchar(c); +} + +getstr(s) { + auto c, i; + + while ((c = getchar()) != '*n') + lchar(s,i++,c); + lchar(s,i,'*e'); + return(s); +} + +printf(fmt, x1,x2,x3,x4,x5,x6,x7,x8,x9) { + extrn printn, char, putchar; + auto adx, x, c, i, j; + + i = 0; + adx = &x1; +loop: + while((c=char(fmt,i++)) != '%') { + if(c == '*e') + return; + putchar(c); + } + x = *adx++; + switch (c = char(fmt,i++)) { + + case 'd': + case 'o': + if(x < 0) { + x = -x; + putchar('-'); + } + printn(x, c=='o'?8:10); + goto loop; + + case 'x': + if(x < 0) { + x = -x; + putchar('-'); + } + printn(x, 16); + goto loop; + + case 'c': + putchar(x); + goto loop; + + case 's': + j = 0; + while((c=char(x,j++)) != '*e') + putchar(c); + goto loop; + } + putchar('%'); + i--; + adx--; + goto loop; +} + diff --git a/lang/b/distr/link.ld b/lang/b/distr/link.ld new file mode 100644 index 000000000..fd0fb71ce --- /dev/null +++ b/lang/b/distr/link.ld @@ -0,0 +1,21 @@ +OUTPUT_FORMAT("elf32-i386") +OUTPUT_ARCH(i386) + +ENTRY(start) + +SECTIONS +{ + . = 0x400000; + .text : { *(.text) } + . = 0x8000000; + .data : { + *(.data) + __bsymb = .; + *(.bsymb) + __ebsymb = .; + } + . = ALIGN(16); + __bss = .; + .bss : { *(.bss) } + __ebss = .; +} From cfc723250f05efa6b6b2f87572f725e94a5a1853 Mon Sep 17 00:00:00 2001 From: David Given Date: Sun, 27 Nov 2016 11:58:59 +0100 Subject: [PATCH 031/173] Initial EM-ification; start threading word size stuff through the code. --- build.lua | 1 + lang/b/{distr => }/LICENSE | 0 lang/b/{distr => }/README.md | 0 lang/b/{distr => compiler}/b.h | 2 + lang/b/{distr => compiler}/b0.c | 68 ++++++++++++++++++++------------- lang/b/{distr => compiler}/b1.c | 0 lang/b/compiler/build.lua | 21 ++++++++++ 7 files changed, 65 insertions(+), 27 deletions(-) rename lang/b/{distr => }/LICENSE (100%) rename lang/b/{distr => }/README.md (100%) rename lang/b/{distr => compiler}/b.h (98%) rename lang/b/{distr => compiler}/b0.c (96%) rename lang/b/{distr => compiler}/b1.c (100%) create mode 100644 lang/b/compiler/build.lua diff --git a/build.lua b/build.lua index 607a83a3b..dc9c0e03d 100644 --- a/build.lua +++ b/build.lua @@ -36,6 +36,7 @@ installable { "lang/cem/cemcom.ansi+pkg", "lang/m2/comp+pkg", "lang/pc/comp+pkg", + "lang/b/compiler+pkg", "util/ack+pkg", "util/amisc+pkg", "util/arch+pkg", diff --git a/lang/b/distr/LICENSE b/lang/b/LICENSE similarity index 100% rename from lang/b/distr/LICENSE rename to lang/b/LICENSE diff --git a/lang/b/distr/README.md b/lang/b/README.md similarity index 100% rename from lang/b/distr/README.md rename to lang/b/README.md diff --git a/lang/b/distr/b.h b/lang/b/compiler/b.h similarity index 98% rename from lang/b/distr/b.h rename to lang/b/compiler/b.h index 9aae94601..9e108325f 100644 --- a/lang/b/distr/b.h +++ b/lang/b/compiler/b.h @@ -1,6 +1,7 @@ #include #include #include +#include #define NCPS 8 /* chars per symbol */ #define NCPW 4 /* chars per word */ @@ -38,6 +39,7 @@ struct swtab { int swval; }; +extern int wordsize; struct hshtab hshtab[HSHSIZ]; int hshused; int eof; diff --git a/lang/b/distr/b0.c b/lang/b/compiler/b0.c similarity index 96% rename from lang/b/distr/b0.c rename to lang/b/compiler/b0.c index 424e1afdb..25aa59c6b 100644 --- a/lang/b/distr/b0.c +++ b/lang/b/compiler/b0.c @@ -14,6 +14,8 @@ int peeksym = -1, peeksym2 = -1;; int contlab = -1; int brklab = -1; +int wordsize = 4; + void init(char *s, int val) { @@ -32,24 +34,37 @@ init(char *s, int val) int main(int argc, char *argv[]) { - if (argc < 3) { - error("Arg count"); - exit(1); - } - if (freopen(argv[1], "r", stdin) == NULL) { - error("Can't find %s", argv[1]); - exit(1); - } - if ((sbufp=fopen(argv[2], "w")) == NULL) { - error("Can't create %s", argv[2]); - exit(1); - } - if (argc > 3) { - if (freopen(argv[3], "w", stdout) == NULL) { - error("Can't create %s", argv[2]); - exit(1); + + for (;;) { + int opt = getopt(argc, argv, "-w:i:o:"); + if (opt == -1) + break; + + switch (opt) { + case 'w': + wordsize = atoi(optarg); + break; + + case 'i': + if (freopen(optarg, "r", stdin) == NULL) { + error("Can't find %s", optarg); + exit(1); + } + break; + + case 'o': + if (freopen(optarg, "w", stdout) == NULL) { + error("Can't create %s", optarg); + exit(1); + } + break; + + derfault: + error("Usage: em_b [-w wordsize] [-i inputfile] [-o outputfile]"); + exit(1); } } + init("auto", AUTO); init("extrn", EXTERN); init("case", CASE); @@ -61,7 +76,6 @@ main(int argc, char *argv[]) init("return", RETURN); init("default", DEFAULT); init("break", BREAK); - fprintf(sbufp, "\t.data\n"); while (!eof) { extdef(); blkend(); @@ -191,16 +205,16 @@ getstr(void) int c; int i; - fprintf(sbufp, "\t.align 4\n"); - fprintf(sbufp, "L%d:", cval = isn++); + printf("\t.align %d\n", wordsize); + printf("L%d:", cval = isn++); if ((c = mapch('"')) >= 0) - fprintf(sbufp, "\t.byte %04o", c); + printf("\t.byte %04o", c); for (i = 2; (c = mapch('"')) >= 0; i++) - fprintf(sbufp, ",%04o", c); - fprintf(sbufp, ",04"); + printf(",%04o", c); + printf(",04"); while ((i++%4) != 0) - fprintf(sbufp, ",00"); - fprintf(sbufp, "\n"); + printf(",00"); + printf("\n"); return STRING; } @@ -525,7 +539,7 @@ extdef(void) global(bs); bsymb(bs,1); printf("_%s:\t.long 1f\n", bs); - printf("\t.text\n\t.align 4\n1:"); + printf("\t.text\n\t.align %s\n1:", wordsize); function(); done: printf("\n"); @@ -568,8 +582,8 @@ blkhed(void) struct hshtab *bs; declist(); - stack = al = -4; - pl = 8; + stack = al = -wordsize; + pl = wordsize*2; while (paraml) { paraml = (bs = paraml)->next; bs->offset = pl; diff --git a/lang/b/distr/b1.c b/lang/b/compiler/b1.c similarity index 100% rename from lang/b/distr/b1.c rename to lang/b/compiler/b1.c diff --git a/lang/b/compiler/build.lua b/lang/b/compiler/build.lua new file mode 100644 index 000000000..76fac395f --- /dev/null +++ b/lang/b/compiler/build.lua @@ -0,0 +1,21 @@ + +cprogram { + name = "em_b", + srcs = { + "./*.c", + }, + deps = { + "modules+headers", + "modules/src/em_code+lib_k", + "modules/src/em_data+lib", + "modules/src/em_mes+lib", + } +} + +installable { + name = "pkg", + map = { + ["$(PLATDEP)/em_b"] = "+em_b" + } +} + From 707585b67d238b8943bc2d5be0f0bcd75ee5f1a9 Mon Sep 17 00:00:00 2001 From: David Given Date: Sun, 27 Nov 2016 20:28:19 +0100 Subject: [PATCH 032/173] Perform initial (i.e. feature complete and compiling, but not necessarily working) port of the B compiler to EM. --- lang/b/compiler/b.h | 12 +- lang/b/compiler/b0.c | 258 ++++++++++++++++++++++---------------- lang/b/compiler/b1.c | 179 +++++++++++++------------- lang/b/compiler/build.lua | 7 +- 4 files changed, 261 insertions(+), 195 deletions(-) diff --git a/lang/b/compiler/b.h b/lang/b/compiler/b.h index 9e108325f..61548b6e8 100644 --- a/lang/b/compiler/b.h +++ b/lang/b/compiler/b.h @@ -1,11 +1,11 @@ #include #include #include +#include #include +#include #define NCPS 8 /* chars per symbol */ -#define NCPW 4 /* chars per word */ -#define ALIGN 4 /* Passed directly to the assembler's .align */ #define HSHSIZ 400 /* hash table size */ #define SWSIZ 230 /* switch table size */ #define CMSIZ 40 /* symbol stack size */ @@ -40,6 +40,7 @@ struct swtab { }; extern int wordsize; +int paramsize; struct hshtab hshtab[HSHSIZ]; int hshused; int eof; @@ -71,9 +72,12 @@ void error(char *s, ...); void printtoken(int tok, FILE *out); struct tnode * block(int op, int value, struct tnode *tr1, struct tnode *tr2); void rcexpr(struct tnode *tr); -void cbranch(struct tnode *t, int lab, int val); +void cbranch(struct tnode *t, int lab); void jump(int lab); -void label(int l); +void fnlabel(int l); +void tonativeaddr(void); +void fromnativeaddr(void); +char* manglename(char* name, char prefix); #define EOFC 0 #define SEMI 1 diff --git a/lang/b/compiler/b0.c b/lang/b/compiler/b0.c index 25aa59c6b..abbeeba32 100644 --- a/lang/b/compiler/b0.c +++ b/lang/b/compiler/b0.c @@ -4,7 +4,6 @@ void extdef(void); struct hshtab * lookup(void); void blkhed(void); void blkend(void); -void retseq(void); void statement(int d); struct tnode * tree(void); void errflush(int o); @@ -15,6 +14,9 @@ int contlab = -1; int brklab = -1; int wordsize = 4; +int bsymb_part; +int code_part; +int string_part; void init(char *s, int val) @@ -76,10 +78,33 @@ main(int argc, char *argv[]) init("return", RETURN); init("default", DEFAULT); init("break", BREAK); + + C_init(wordsize, wordsize); + C_open(NULL); + C_magic(); + C_ms_emx(wordsize, wordsize); + bsymb_part = 0; + string_part = 0; + code_part = C_getid(); + C_beginpart(code_part); while (!eof) { extdef(); blkend(); } + C_endpart(code_part); + C_insertpart(code_part); + + if (string_part) + C_insertpart(string_part); + + C_exp("bsymb_start"); + C_exp("bsymb_end"); + if (bsymb_part) + C_insertpart(bsymb_part); + C_df_dnam("bsymb_end"); + + C_close(); + return nerror != 0; } @@ -192,9 +217,9 @@ getcc(void) cc = 0; cp = (char*) &cval; while ((c = mapch('\'')) >= 0) - if (cc++ < NCPW) + if (cc++ < wordsize) *cp++ = c; - if (cc > NCPW) + if (cc > wordsize) error("Long character constant"); return CON; } @@ -204,17 +229,31 @@ getstr(void) { int c; int i; + char b; + int partid; - printf("\t.align %d\n", wordsize); - printf("L%d:", cval = isn++); - if ((c = mapch('"')) >= 0) - printf("\t.byte %04o", c); - for (i = 2; (c = mapch('"')) >= 0; i++) - printf(",%04o", c); - printf(",04"); + partid = C_getid(); + C_beginpart(partid); + if (string_part) + C_insertpart(string_part); + + cval = isn++; + C_df_dlb(cval); + for (i = 1; (c = mapch('"')) >= 0; i++) { + b = c; + C_con_scon(&b, 1); + } + + b = 04; + C_con_scon(&b, 1); + + b = 0; while ((i++%4) != 0) - printf(",00"); - printf("\n"); + C_con_scon(&b, 1); + + C_endpart(partid); + string_part = partid; + return STRING; } @@ -447,26 +486,30 @@ declist(void) void function(void) { - printf("\tpush\t%%ebp\n"); - printf("\tmov\t%%esp,%%ebp\n"); - declare(ARG); statement(1); - retseq(); + C_ret(0); + C_end(paramsize); } void global(char *s) { - printf("\t.globl\t_%s\n", s); - printf("\t.data\n"); - printf("\t.align %d\n", ALIGN); + C_exa_dnam(manglename(s, 'b')); } void -bsymb(char *s, int und) +bsymb(char *s) { - printf("\t.section .bsymb; .long %s%s; .data\n", und?"_":"", s); + int newpart = C_getid(); + C_beginpart(newpart); + if (bsymb_part != 0) + C_insertpart(bsymb_part); + C_rom_dlb(isn, 0); + C_endpart(newpart); + + bsymb_part = newpart; + C_df_dlb(isn++); } void @@ -474,6 +517,7 @@ extdef(void) { int o, dim, i; char *bs; + char *ms; if ((o = symbol()) == EOFC || o == SEMI) return; @@ -484,7 +528,9 @@ extdef(void) switch(o = symbol()) { case SEMI: - printf("\t.comm\t_%s,%d,%d\n", bs, NCPW, ALIGN); + global(bs); + C_df_dnam(manglename(bs, 'b')); + C_bss_cst(wordsize, 0, 1); goto done; /* init */ @@ -492,8 +538,8 @@ extdef(void) case STRING: global(bs); if (o == STRING) - bsymb(bs,1); - printf("_%s:", bs); + bsymb(bs); + C_df_dnam(manglename(bs, 'b')); pushsym(o); goto init; @@ -507,13 +553,17 @@ extdef(void) goto syntax; global(bs); if ((o=symbol()) == SEMI) { - printf("\t.comm\tL%d,%d,%d\n", isn, dim*NCPW, ALIGN); - bsymb(bs,1); - printf("_%s:\t.long L%d\n", bs, isn++); + bsymb(bs); + C_df_dnam(manglename(bs, 'b')); + C_con_dlb(isn, 0); + C_df_dlb(isn++); + C_bss_cst(wordsize*dim, 0, 1); goto done; } - bsymb(bs,1); - printf("_%s:\t.long 1f\n1:", bs); + bsymb(bs); + C_df_dnam(manglename(bs, 'b')); + C_con_dlb(isn, 0); + C_df_dlb(isn++); pushsym(o); init: @@ -521,15 +571,26 @@ extdef(void) if ((o=symbol()) != CON && o != STRING && o != NAME) goto syntax; if (o == NAME) { - bsymb("1f",0); - printf("1:\t.long _%s\n", bsym->name); - } else - printf("\t.long %s%d\n", o==STRING?"L":"",cval); + bsymb(NULL); + C_con_dnam(manglename(bsym->name, 'b'), 0); + } else { + if (o == STRING) { + bsymb(NULL); + C_con_dlb(cval, 0); + } else + C_con_cst(cval); + } i++; } while ((o=symbol()) == COMMA); dim = (i > dim) ? i : dim; - if (dim - i) - printf("\t.zero %d\n", (dim-i)*NCPW); + if (i == 0) + C_bss_cst((dim-i)*wordsize, 0, 1); + else { + while (dim -i) { + C_con_cst(0); + i++; + } + } if (o == SEMI) goto done; goto syntax; @@ -537,12 +598,15 @@ extdef(void) /* function */ case LPARN: global(bs); - bsymb(bs,1); - printf("_%s:\t.long 1f\n", bs); - printf("\t.text\n\t.align %s\n1:", wordsize); + ms = manglename(bs, 'b'); + bsymb(ms); + C_df_dnam(ms); + ms = manglename(bs, 'i'); + C_con_pnam(ms); + C_inp(ms); + C_pro_narg(ms); function(); done: - printf("\n"); return; case EOFC: @@ -555,26 +619,6 @@ syntax: statement(0); } -void -setstk(int a) -{ - int dif; - - dif = stack-a; - stack = a; - if (dif) - printf("\tsub\t$%d, %%esp\n", dif); -} - -void -defvec(void) -{ - stack -= NCPW; - printf("\tmov\t%%esp,%%eax\n"); - printf("\tshr\t$2,%%eax\n"); - printf("\tpush\t%%eax\n"); -} - void blkhed(void) { @@ -583,27 +627,29 @@ blkhed(void) declist(); stack = al = -wordsize; - pl = wordsize*2; + pl = 0; /* EM parameters start at offset 0. */ while (paraml) { paraml = (bs = paraml)->next; bs->offset = pl; - pl += NCPW; + pl += wordsize; } for (bs = hshtab; bs < &hshtab[HSHSIZ]; bs++) if (bs->name[0]) { if (bs->class == AUTO) { bs->offset = al; if (bs->dim) { - al -= bs->dim*NCPW; - setstk(al); - defvec(); + al -= bs->dim*wordsize; + C_lal(al); + al -= wordsize; + fromnativeaddr(); + C_stl(al); bs->offset = al; } - al -= NCPW; + al -= wordsize; } else if (bs->class == ARG) bs->class = AUTO; } - setstk(al); + paramsize = -al - wordsize; } void @@ -641,33 +687,23 @@ syntax: } void -label(int l) +fnlabel(int l) { - printf("L%d:\n", l); + C_ilb(l); } +/* Jump to "lab", if the expression "t" evaluated to 0. */ void -retseq(void) -{ - printf("\tjmp\tretrn\n"); -} - -/* Jump to "lab", if the expression "t" evaluated to "val". */ -void -cbranch(struct tnode *t, int lab, int val) +cbranch(struct tnode *t, int lab) { rcexpr(t); - if (val == 0) - printf("\ttest\t%%eax,%%eax\n"); - else - printf("\tcmp\t%%eax,$%d\n", val); - printf("\tje\tL%d\n", lab); + C_zeq(lab); } void jump(int lab) { - printf("\tjmp\tL%d\n", lab); + C_bra(lab); } void @@ -676,26 +712,31 @@ pswitch(void) struct swtab *sswp; int dl, swlab; - sswp = swp; if (swp == NULL) swp = swtab; + sswp = swp; swlab = isn++; - printf("\tmov\t$L%d,%%ebx\n", swlab); - printf("\tjmp\tbswitch\n"); + C_lae_dlb(swlab, 0); + C_csb(wordsize); + dl = deflab; deflab = 0; statement(0); - if (!deflab) { - deflab = isn++; - label(deflab); - } - printf("L%d:\n\t.data\nL%d:", brklab, swlab); + if (!deflab) + deflab = brklab; + + C_df_dlb(swlab); + C_con_ilb(deflab); + C_con_cst(swp - sswp); + while (swp > sswp && swp > swtab) { --swp; - printf("\t.long %d,L%d\n", swp->swval, swp->swlab); + C_con_cst(swp->swval); + C_con_ilb(swp->swlab); } - printf("\t.long L%d,0\n", deflab); - printf("\t.text\n"); + + C_df_dlb(brklab); + deflab = dl; swp = sswp; } @@ -742,33 +783,36 @@ stmt: goto semi; case RETURN: - if (pushsym(symbol()) == LPARN) + if (pushsym(symbol()) == LPARN) { rcexpr(pexpr()); - retseq(); + C_ret(wordsize); + } else { + C_ret(0); + } goto semi; case IF: - cbranch(pexpr(), o1=isn++, 0); + cbranch(pexpr(), o1=isn++); statement(0); if ((o = symbol()) == KEYW && cval == ELSE) { jump(o2 = isn++); - label(o1); + fnlabel(o1); statement(0); - label(o2); + fnlabel(o2); return; } pushsym(o); - label(o1); + fnlabel(o1); return; case WHILE: o1 = contlab; o2 = brklab; - label(contlab = isn++); - cbranch(pexpr(), brklab=isn++, 0); + fnlabel(contlab = isn++); + cbranch(pexpr(), brklab=isn++); statement(0); jump(contlab); - label(brklab); + fnlabel(brklab); contlab = o1; brklab = o2; return; @@ -811,7 +855,7 @@ stmt: else { swp->swlab = isn; (swp++)->swval = cval; - label(isn++); + fnlabel(isn++); } goto stmt; @@ -821,7 +865,7 @@ stmt: if ((o = symbol()) != COLON) goto syntax; deflab = isn++; - label(deflab); + fnlabel(deflab); goto stmt; } @@ -837,12 +881,13 @@ stmt: } bsym->class = INTERN; bsym->offset = isn++; - label(bsym->offset); + fnlabel(bsym->offset); goto stmt; } } pushsym(o); rcexpr(tree()); + C_asp(wordsize); goto semi; semi: @@ -948,7 +993,8 @@ advanc: switch (o=symbol()) { case NAME: if (pushsym(symbol()) == LPARN) { /* function */ - bsym->class = EXTERN; + if (bsym->class == 0) + bsym->class = EXTERN; } else if (bsym->class == 0) { error("%s undefined", bsym->name); bsym->class = EXTERN; diff --git a/lang/b/compiler/b1.c b/lang/b/compiler/b1.c index 6295810ab..30ce5c7f7 100644 --- a/lang/b/compiler/b1.c +++ b/lang/b/compiler/b1.c @@ -1,26 +1,51 @@ #include "b.h" /* - * Code generation (x86 assembly) + * Code generation (EM) */ -void -push(void) +static int +shiftsize(void) { - printf("\tpush\t%%eax\n"); + switch (wordsize) { + case 1: return 0; + case 2: return 1; + case 4: return 2; + case 8: return 3; + default: + error("unsupported word size"); + exit(1); + } } void -pop(char *s) +tonativeaddr(void) { - printf("\tpop\t%%%s\n", s); + C_loc(shiftsize()); + C_slu(wordsize); +} + +void +fromnativeaddr(void) +{ + C_loc(shiftsize()); + C_sru(wordsize); +} + +char* +manglename(char* name, char prefix) +{ + static char buffer[NCPS+3]; + buffer[0] = prefix; + buffer[1] = '_'; + strcpy(buffer+2, name); + return buffer; } void binary(struct tnode *tr) { rcexpr(tr->tr1); - push(); rcexpr(tr->tr2); } @@ -33,13 +58,11 @@ pushargs(struct tnode *tr) return 0; if (tr->op == COMMA) { rcexpr(tr->tr2); - push(); stk = pushargs(tr->tr1); - return stk+NCPW; + return stk+wordsize; } rcexpr(tr); - push(); - return NCPW; + return wordsize; } void @@ -56,42 +79,50 @@ lvalexp(struct tnode *tr) case INCAFT: if (tr->tr1->op == STAR) { rcexpr(tr->tr1->tr1); - printf("\tmov\t%%eax,%%ebx\n"); - sprintf(memloc,"(,%%ebx,4)"); + tonativeaddr(); } else { /* NAME, checked in "build" */ bs = (struct hshtab *) tr->tr1->tr1; if (bs->class == EXTERN) - sprintf(memloc,"_%s", bs->name); + C_lae_dnam(manglename(bs->name, 'b'), 0); else if (bs->class == AUTO) - sprintf(memloc,"%d(%%ebp)", bs->offset); + C_lal(bs->offset); else goto classerror; } if (tr->op == DECBEF || tr->op == INCBEF) { - printf("\t%s\t%s\n", tr->op == DECBEF ? "decl" : "incl", - memloc); - printf("\tmov\t%s,%%eax\n", memloc); + C_dup(wordsize); /* ( addr addr -- ) */ + C_loi(wordsize); /* ( addr val -- ) */ + C_adp((tr->op == DECBEF) ? -1 : 1); /* ( addr newval -- ) */ + C_exg(wordsize); /* ( newval addr -- ) */ + C_dup(wordsize*2); /* ( newval addr newval addr -- ) */ + C_sti(wordsize); /* ( newval addr -- ) */ + C_asp(wordsize); /* ( newval -- ) */ } else { - printf("\tmov\t%s,%%eax\n", memloc); - printf("\t%s\t%s\n", tr->op == DECAFT ? "decl" : "incl", - memloc); + C_dup(wordsize); /* ( addr addr -- ) */ + C_loi(wordsize); /* ( addr val -- ) */ + C_exg(wordsize); /* ( val addr -- ) */ + C_dup(wordsize*2); /* ( val addr val addr -- ) */ + C_asp(wordsize); /* ( val addr val -- ) */ + C_adp((tr->op == DECAFT) ? -1 : 1); /* ( val addr newval -- ) */ + C_exg(wordsize); /* ( val newval addr -- ) */ + C_sti(wordsize); /* ( val -- ) */ } return; case ASSIGN: rcexpr(tr->tr2); + C_dup(wordsize); if (tr->tr1->op == STAR) { - push(); rcexpr(tr->tr1->tr1); - pop("ebx"); - printf("\tmov\t%%ebx,(,%%eax,4)\n"); + tonativeaddr(); + C_sti(wordsize); } else { /* NAME */ bs = (struct hshtab *) tr->tr1->tr1; - if (bs->class == EXTERN) - printf("\tmov\t%%eax,_%s\n", bs->name); - else if (bs->class == AUTO) - printf("\tmov\t%%eax,%d(%%ebp)\n", bs->offset); - else + if (bs->class == EXTERN) { + C_ste_dnam(bs->name, 0); + } else if (bs->class == AUTO) { + C_stl(bs->offset); + } else goto classerror; } return; @@ -138,20 +169,20 @@ rcexpr(struct tnode *tr) switch (tr->op) { case CON: - printf("\tmov\t$%d,%%eax\n", tr->value); + C_loc(tr->value); return; case STRING: - printf("\tmov\t$L%d,%%eax\n", tr->value); - printf("\tshr\t$2,%%eax\n"); + C_lae_dlb(tr->value, 0); + fromnativeaddr(); return; case NAME: /* only rvalue */ bs = (struct hshtab *) tr->tr1; if (bs->class == EXTERN) - printf("\tmov\t_%s,%%eax\n", bs->name); + C_loe_dnam(manglename(bs->name, 'b'), 0); else if (bs->class == AUTO) - printf("\tmov\t%d(%%ebp),%%eax\n", bs->offset); + C_lol(bs->offset); else goto classerror; return; @@ -159,89 +190,73 @@ rcexpr(struct tnode *tr) case CALL: stk = pushargs(tr->tr2); rcexpr(tr->tr1); - printf("\tshl\t$2,%%eax\n"); - printf("\tcall\t*%%eax\n"); + tonativeaddr(); + C_cai(); if (stk) - printf("\tadd\t$%d,%%esp\n",stk); + C_asp(stk); + C_lfr(wordsize); return; case AMPER: bs = (struct hshtab *) tr->tr1->tr1; if (bs->class == EXTERN) { - printf("\tmov\t$_%s,%%eax\n", bs->name); - printf("\tshr\t$2,%%eax\n"); + C_lae_dnam(manglename(bs->name, 'b'), 0); } else if (bs->class == AUTO) { - printf("\tlea\t%d(%%ebp),%%eax\n", bs->offset); - printf("\tshr\t$2,%%eax\n"); + C_lal(bs->offset); } else goto classerror; + fromnativeaddr(); return; case STAR: /* only rvalue */ rcexpr(tr->tr1); - printf("\tmov\t(,%%eax,4),%%eax\n"); + tonativeaddr(); + C_loi(wordsize); return; case PLUS: binary(tr); - pop("ebx"); - printf("\tadd\t%%ebx,%%eax\n"); + C_adi(wordsize); return; case MINUS: binary(tr); - printf("\tmov\t%%eax,%%ebx\n"); - pop("eax"); - printf("\tsub\t%%ebx,%%eax\n"); + C_sbi(wordsize); return; case TIMES: binary(tr); - pop("ebx"); - printf("\tmul\t%%ebx\n"); + C_mli(wordsize); return; case DIVIDE: binary(tr); - printf("\tmov\t%%eax,%%ebx\n"); - pop("eax"); - printf("\txor\t%%edx,%%edx\n"); - printf("\tdiv\t%%ebx\n"); + C_dvi(wordsize); return; case MOD: binary(tr); - printf("\tmov\t%%eax,%%ebx\n"); - pop("eax"); - printf("\txor\t%%edx,%%edx\n"); - printf("\tdiv\t%%ebx\n"); - printf("\tmov\t%%edx,%%eax\n"); + C_rmi(wordsize); return; case AND: binary(tr); - pop("ebx"); - printf("\tand\t%%ebx,%%eax\n"); + C_and(wordsize); return; case OR: binary(tr); - pop("ebx"); - printf("\tor\t%%ebx,%%eax\n"); + C_ior(wordsize); return; case LSHIFT: binary(tr); - printf("\tmov\t%%eax,%%ecx\n"); - pop("eax"); - printf("\tshl\t%%cl,%%eax\n"); + C_sli(wordsize); return; case RSHIFT: binary(tr); - printf("\tmov\t%%eax,%%ecx\n"); - pop("eax"); - printf("\tshr\t%%cl,%%eax\n"); + C_sri(wordsize); return; case EQUAL: @@ -251,50 +266,46 @@ rcexpr(struct tnode *tr) case GREAT: case GREATEQ: binary(tr); - pop("ebx"); - printf("\tcmp\t%%eax,%%ebx\n"); + C_cmi(wordsize); switch (tr->op) { case EQUAL: - printf("\tsete\t%%al\n"); + C_teq(); break; case NEQUAL: - printf("\tsetne\t%%al\n"); + C_tne(); break; case LESS: - printf("\tsetl\t%%al\n"); + C_tlt(); break; case LESSEQ: - printf("\tsetle\t%%al\n"); + C_tle(); break; case GREAT: - printf("\tsetg\t%%al\n"); + C_tgt(); break; case GREATEQ: - printf("\tsetge\t%%al\n"); + C_tge(); break; } - printf("\tmovzb\t%%al,%%eax\n"); return; case EXCLA: rcexpr(tr->tr1); - printf("\ttest\t%%eax,%%eax\n"); - printf("\tsete\t%%al\n"); - printf("\tmovzb\t%%al,%%eax\n"); + C_tne(); return; case NEG: rcexpr(tr->tr1); - printf("\tneg\t%%eax\n"); + C_ngi(wordsize); return; case QUEST: - cbranch(tr->tr1, o1=isn++, 0); + cbranch(tr->tr1, o1=isn++); rcexpr(tr->tr2->tr1); jump(o2 = isn++); - label(o1); + fnlabel(o1); rcexpr(tr->tr2->tr2); - label(o2); + fnlabel(o2); return; default: diff --git a/lang/b/compiler/build.lua b/lang/b/compiler/build.lua index 76fac395f..00afc81ef 100644 --- a/lang/b/compiler/build.lua +++ b/lang/b/compiler/build.lua @@ -5,10 +5,15 @@ cprogram { "./*.c", }, deps = { + "./*.h", "modules+headers", - "modules/src/em_code+lib_k", + "modules/src/alloc+lib", + "modules/src/em_code+lib_e", "modules/src/em_data+lib", "modules/src/em_mes+lib", + "modules/src/print+lib", + "modules/src/string+lib", + "modules/src/system+lib", } } From 5bce5fc4dae67fa58ea4ba4e0d8667696f151fda Mon Sep 17 00:00:00 2001 From: David Given Date: Sun, 27 Nov 2016 20:38:33 +0100 Subject: [PATCH 033/173] Change the extension used by Basic files for .b to .bas, to avoid conflicts with B. --- examples/build.lua | 2 +- examples/{hilo.b => hilo.bas} | 0 lang/basic/test/{bull.b => bull.bas} | 0 lang/basic/test/{buzzword.b => buzzword.bas} | 0 lang/basic/test/{checker.b => checker.bas} | 0 lang/basic/test/{creator.b => creator.bas} | 0 lang/basic/test/{grafiek.b => grafiek.bas} | 0 lang/basic/test/{gunner.b => gunner.bas} | 0 lang/basic/test/{learn.b => learn.bas} | 0 lang/basic/test/{opg1.b => opg1.bas} | 0 lang/basic/test/{opg2.b => opg2.bas} | 0 lang/basic/test/{opg3.b => opg3.bas} | 0 lang/basic/test/{opg4.b => opg4.bas} | 0 lang/basic/test/{opg5.b => opg5.bas} | 0 lang/basic/test/{opg6.b => opg6.bas} | 0 lang/basic/test/{som4.b => som4.bas} | 0 lang/basic/test/{test01.b => test01.bas} | 0 lang/basic/test/{test02.b => test02.bas} | 0 lang/basic/test/{test03.b => test03.bas} | 0 lang/basic/test/{test04.b => test04.bas} | 0 lang/basic/test/{test05.b => test05.bas} | 0 lang/basic/test/{test06.b => test06.bas} | 0 lang/basic/test/{test07.b => test07.bas} | 0 lang/basic/test/{test08.b => test08.bas} | 0 lang/basic/test/{test09.b => test09.bas} | 0 lang/basic/test/{test10.b => test10.bas} | 0 lang/basic/test/{test11.b => test11.bas} | 0 lang/basic/test/{test12.b => test12.bas} | 0 lang/basic/test/{test13.b => test13.bas} | 0 lang/basic/test/{test14.b => test14.bas} | 0 lang/basic/test/{test15.b => test15.bas} | 0 lang/basic/test/{test16.b => test16.bas} | 0 lang/basic/test/{test17.b => test17.bas} | 0 lang/basic/test/{test18.b => test18.bas} | 0 lang/basic/test/{test19.b => test19.bas} | 0 lang/basic/test/{test20.b => test20.bas} | 0 lang/basic/test/{test21.b => test21.bas} | 0 lang/basic/test/{test22.b => test22.bas} | 0 lang/basic/test/{test23.b => test23.bas} | 0 lang/basic/test/{test24.b => test24.bas} | 0 lang/basic/test/{test25.b => test25.bas} | 0 lang/basic/test/{test26.b => test26.bas} | 0 lang/basic/test/{test27.b => test27.bas} | 0 lang/basic/test/{test28.b => test28.bas} | 0 lang/basic/test/{test29.b => test29.bas} | 0 lang/basic/test/{test30.b => test30.bas} | 0 lang/basic/test/{test31.b => test31.bas} | 0 lang/basic/test/{test32.b => test32.bas} | 0 lang/basic/test/{test33.b => test33.bas} | 0 lang/basic/test/{test34.b => test34.bas} | 0 lang/basic/test/{test35.b => test35.bas} | 0 lib/6500/descr | 8 ++++---- lib/6800/descr | 8 ++++---- lib/6805/descr | 8 ++++---- lib/6809/descr | 8 ++++---- lib/arm/descr | 10 +++++----- lib/descr/cpm | 2 +- lib/descr/fe | 10 +++++----- lib/em22/descr | 6 +++--- lib/em24/descr | 6 +++--- lib/em44/descr | 6 +++--- lib/i286/descr | 2 +- lib/i386/descr | 6 +++--- lib/i80/descr | 8 ++++---- lib/i86/descr | 6 +++--- lib/m68020/descr | 6 +++--- lib/m68k2/descr | 6 +++--- lib/m68k4/descr | 6 +++--- lib/mantra/descr | 6 +++--- lib/minix/descr | 6 +++--- lib/minixST/descr | 6 +++--- lib/ns/descr | 6 +++--- lib/pdp/descr | 6 +++--- lib/pmds/descr | 6 +++--- lib/pmds4/descr | 6 +++--- lib/s2650/descr | 8 ++++---- lib/sparc/descr | 6 +++--- lib/sparc_solaris/descr | 6 +++--- lib/sun2/descr | 6 +++--- lib/sun3/descr | 6 +++--- lib/vax4/descr | 6 +++--- lib/xenix3/descr | 6 +++--- lib/z80/descr | 8 ++++---- lib/z8000/descr | 8 ++++---- mach/z80/int/em22 | 6 +++--- plat/cpm/descr | 6 +++--- plat/linux386/descr | 6 +++--- plat/linux68k/descr | 6 +++--- plat/linuxppc/descr | 6 +++--- plat/pc86/descr | 6 +++--- plat/qemuppc/descr | 6 +++--- plat/rpi/descr | 6 +++--- util/ack/ack.1.X | 4 ++-- 93 files changed, 134 insertions(+), 134 deletions(-) rename examples/{hilo.b => hilo.bas} (100%) rename lang/basic/test/{bull.b => bull.bas} (100%) rename lang/basic/test/{buzzword.b => buzzword.bas} (100%) rename lang/basic/test/{checker.b => checker.bas} (100%) rename lang/basic/test/{creator.b => creator.bas} (100%) rename lang/basic/test/{grafiek.b => grafiek.bas} (100%) rename lang/basic/test/{gunner.b => gunner.bas} (100%) rename lang/basic/test/{learn.b => learn.bas} (100%) rename lang/basic/test/{opg1.b => opg1.bas} (100%) rename lang/basic/test/{opg2.b => opg2.bas} (100%) rename lang/basic/test/{opg3.b => opg3.bas} (100%) rename lang/basic/test/{opg4.b => opg4.bas} (100%) rename lang/basic/test/{opg5.b => opg5.bas} (100%) rename lang/basic/test/{opg6.b => opg6.bas} (100%) rename lang/basic/test/{som4.b => som4.bas} (100%) rename lang/basic/test/{test01.b => test01.bas} (100%) rename lang/basic/test/{test02.b => test02.bas} (100%) rename lang/basic/test/{test03.b => test03.bas} (100%) rename lang/basic/test/{test04.b => test04.bas} (100%) rename lang/basic/test/{test05.b => test05.bas} (100%) rename lang/basic/test/{test06.b => test06.bas} (100%) rename lang/basic/test/{test07.b => test07.bas} (100%) rename lang/basic/test/{test08.b => test08.bas} (100%) rename lang/basic/test/{test09.b => test09.bas} (100%) rename lang/basic/test/{test10.b => test10.bas} (100%) rename lang/basic/test/{test11.b => test11.bas} (100%) rename lang/basic/test/{test12.b => test12.bas} (100%) rename lang/basic/test/{test13.b => test13.bas} (100%) rename lang/basic/test/{test14.b => test14.bas} (100%) rename lang/basic/test/{test15.b => test15.bas} (100%) rename lang/basic/test/{test16.b => test16.bas} (100%) rename lang/basic/test/{test17.b => test17.bas} (100%) rename lang/basic/test/{test18.b => test18.bas} (100%) rename lang/basic/test/{test19.b => test19.bas} (100%) rename lang/basic/test/{test20.b => test20.bas} (100%) rename lang/basic/test/{test21.b => test21.bas} (100%) rename lang/basic/test/{test22.b => test22.bas} (100%) rename lang/basic/test/{test23.b => test23.bas} (100%) rename lang/basic/test/{test24.b => test24.bas} (100%) rename lang/basic/test/{test25.b => test25.bas} (100%) rename lang/basic/test/{test26.b => test26.bas} (100%) rename lang/basic/test/{test27.b => test27.bas} (100%) rename lang/basic/test/{test28.b => test28.bas} (100%) rename lang/basic/test/{test29.b => test29.bas} (100%) rename lang/basic/test/{test30.b => test30.bas} (100%) rename lang/basic/test/{test31.b => test31.bas} (100%) rename lang/basic/test/{test32.b => test32.bas} (100%) rename lang/basic/test/{test33.b => test33.bas} (100%) rename lang/basic/test/{test34.b => test34.bas} (100%) rename lang/basic/test/{test35.b => test35.bas} (100%) diff --git a/examples/build.lua b/examples/build.lua index 631752976..bf73cc044 100644 --- a/examples/build.lua +++ b/examples/build.lua @@ -5,7 +5,7 @@ local conly = { } local sourcefiles = filenamesof( - "./hilo.b", + "./hilo.bas", "./hilo.c", "./hilo.mod", "./hilo.p", diff --git a/examples/hilo.b b/examples/hilo.bas similarity index 100% rename from examples/hilo.b rename to examples/hilo.bas diff --git a/lang/basic/test/bull.b b/lang/basic/test/bull.bas similarity index 100% rename from lang/basic/test/bull.b rename to lang/basic/test/bull.bas diff --git a/lang/basic/test/buzzword.b b/lang/basic/test/buzzword.bas similarity index 100% rename from lang/basic/test/buzzword.b rename to lang/basic/test/buzzword.bas diff --git a/lang/basic/test/checker.b b/lang/basic/test/checker.bas similarity index 100% rename from lang/basic/test/checker.b rename to lang/basic/test/checker.bas diff --git a/lang/basic/test/creator.b b/lang/basic/test/creator.bas similarity index 100% rename from lang/basic/test/creator.b rename to lang/basic/test/creator.bas diff --git a/lang/basic/test/grafiek.b b/lang/basic/test/grafiek.bas similarity index 100% rename from lang/basic/test/grafiek.b rename to lang/basic/test/grafiek.bas diff --git a/lang/basic/test/gunner.b b/lang/basic/test/gunner.bas similarity index 100% rename from lang/basic/test/gunner.b rename to lang/basic/test/gunner.bas diff --git a/lang/basic/test/learn.b b/lang/basic/test/learn.bas similarity index 100% rename from lang/basic/test/learn.b rename to lang/basic/test/learn.bas diff --git a/lang/basic/test/opg1.b b/lang/basic/test/opg1.bas similarity index 100% rename from lang/basic/test/opg1.b rename to lang/basic/test/opg1.bas diff --git a/lang/basic/test/opg2.b b/lang/basic/test/opg2.bas similarity index 100% rename from lang/basic/test/opg2.b rename to lang/basic/test/opg2.bas diff --git a/lang/basic/test/opg3.b b/lang/basic/test/opg3.bas similarity index 100% rename from lang/basic/test/opg3.b rename to lang/basic/test/opg3.bas diff --git a/lang/basic/test/opg4.b b/lang/basic/test/opg4.bas similarity index 100% rename from lang/basic/test/opg4.b rename to lang/basic/test/opg4.bas diff --git a/lang/basic/test/opg5.b b/lang/basic/test/opg5.bas similarity index 100% rename from lang/basic/test/opg5.b rename to lang/basic/test/opg5.bas diff --git a/lang/basic/test/opg6.b b/lang/basic/test/opg6.bas similarity index 100% rename from lang/basic/test/opg6.b rename to lang/basic/test/opg6.bas diff --git a/lang/basic/test/som4.b b/lang/basic/test/som4.bas similarity index 100% rename from lang/basic/test/som4.b rename to lang/basic/test/som4.bas diff --git a/lang/basic/test/test01.b b/lang/basic/test/test01.bas similarity index 100% rename from lang/basic/test/test01.b rename to lang/basic/test/test01.bas diff --git a/lang/basic/test/test02.b b/lang/basic/test/test02.bas similarity index 100% rename from lang/basic/test/test02.b rename to lang/basic/test/test02.bas diff --git a/lang/basic/test/test03.b b/lang/basic/test/test03.bas similarity index 100% rename from lang/basic/test/test03.b rename to lang/basic/test/test03.bas diff --git a/lang/basic/test/test04.b b/lang/basic/test/test04.bas similarity index 100% rename from lang/basic/test/test04.b rename to lang/basic/test/test04.bas diff --git a/lang/basic/test/test05.b b/lang/basic/test/test05.bas similarity index 100% rename from lang/basic/test/test05.b rename to lang/basic/test/test05.bas diff --git a/lang/basic/test/test06.b b/lang/basic/test/test06.bas similarity index 100% rename from lang/basic/test/test06.b rename to lang/basic/test/test06.bas diff --git a/lang/basic/test/test07.b b/lang/basic/test/test07.bas similarity index 100% rename from lang/basic/test/test07.b rename to lang/basic/test/test07.bas diff --git a/lang/basic/test/test08.b b/lang/basic/test/test08.bas similarity index 100% rename from lang/basic/test/test08.b rename to lang/basic/test/test08.bas diff --git a/lang/basic/test/test09.b b/lang/basic/test/test09.bas similarity index 100% rename from lang/basic/test/test09.b rename to lang/basic/test/test09.bas diff --git a/lang/basic/test/test10.b b/lang/basic/test/test10.bas similarity index 100% rename from lang/basic/test/test10.b rename to lang/basic/test/test10.bas diff --git a/lang/basic/test/test11.b b/lang/basic/test/test11.bas similarity index 100% rename from lang/basic/test/test11.b rename to lang/basic/test/test11.bas diff --git a/lang/basic/test/test12.b b/lang/basic/test/test12.bas similarity index 100% rename from lang/basic/test/test12.b rename to lang/basic/test/test12.bas diff --git a/lang/basic/test/test13.b b/lang/basic/test/test13.bas similarity index 100% rename from lang/basic/test/test13.b rename to lang/basic/test/test13.bas diff --git a/lang/basic/test/test14.b b/lang/basic/test/test14.bas similarity index 100% rename from lang/basic/test/test14.b rename to lang/basic/test/test14.bas diff --git a/lang/basic/test/test15.b b/lang/basic/test/test15.bas similarity index 100% rename from lang/basic/test/test15.b rename to lang/basic/test/test15.bas diff --git a/lang/basic/test/test16.b b/lang/basic/test/test16.bas similarity index 100% rename from lang/basic/test/test16.b rename to lang/basic/test/test16.bas diff --git a/lang/basic/test/test17.b b/lang/basic/test/test17.bas similarity index 100% rename from lang/basic/test/test17.b rename to lang/basic/test/test17.bas diff --git a/lang/basic/test/test18.b b/lang/basic/test/test18.bas similarity index 100% rename from lang/basic/test/test18.b rename to lang/basic/test/test18.bas diff --git a/lang/basic/test/test19.b b/lang/basic/test/test19.bas similarity index 100% rename from lang/basic/test/test19.b rename to lang/basic/test/test19.bas diff --git a/lang/basic/test/test20.b b/lang/basic/test/test20.bas similarity index 100% rename from lang/basic/test/test20.b rename to lang/basic/test/test20.bas diff --git a/lang/basic/test/test21.b b/lang/basic/test/test21.bas similarity index 100% rename from lang/basic/test/test21.b rename to lang/basic/test/test21.bas diff --git a/lang/basic/test/test22.b b/lang/basic/test/test22.bas similarity index 100% rename from lang/basic/test/test22.b rename to lang/basic/test/test22.bas diff --git a/lang/basic/test/test23.b b/lang/basic/test/test23.bas similarity index 100% rename from lang/basic/test/test23.b rename to lang/basic/test/test23.bas diff --git a/lang/basic/test/test24.b b/lang/basic/test/test24.bas similarity index 100% rename from lang/basic/test/test24.b rename to lang/basic/test/test24.bas diff --git a/lang/basic/test/test25.b b/lang/basic/test/test25.bas similarity index 100% rename from lang/basic/test/test25.b rename to lang/basic/test/test25.bas diff --git a/lang/basic/test/test26.b b/lang/basic/test/test26.bas similarity index 100% rename from lang/basic/test/test26.b rename to lang/basic/test/test26.bas diff --git a/lang/basic/test/test27.b b/lang/basic/test/test27.bas similarity index 100% rename from lang/basic/test/test27.b rename to lang/basic/test/test27.bas diff --git a/lang/basic/test/test28.b b/lang/basic/test/test28.bas similarity index 100% rename from lang/basic/test/test28.b rename to lang/basic/test/test28.bas diff --git a/lang/basic/test/test29.b b/lang/basic/test/test29.bas similarity index 100% rename from lang/basic/test/test29.b rename to lang/basic/test/test29.bas diff --git a/lang/basic/test/test30.b b/lang/basic/test/test30.bas similarity index 100% rename from lang/basic/test/test30.b rename to lang/basic/test/test30.bas diff --git a/lang/basic/test/test31.b b/lang/basic/test/test31.bas similarity index 100% rename from lang/basic/test/test31.b rename to lang/basic/test/test31.bas diff --git a/lang/basic/test/test32.b b/lang/basic/test/test32.bas similarity index 100% rename from lang/basic/test/test32.b rename to lang/basic/test/test32.bas diff --git a/lang/basic/test/test33.b b/lang/basic/test/test33.bas similarity index 100% rename from lang/basic/test/test33.b rename to lang/basic/test/test33.bas diff --git a/lang/basic/test/test34.b b/lang/basic/test/test34.bas similarity index 100% rename from lang/basic/test/test34.b rename to lang/basic/test/test34.bas diff --git a/lang/basic/test/test35.b b/lang/basic/test/test35.bas similarity index 100% rename from lang/basic/test/test35.b rename to lang/basic/test/test35.bas diff --git a/lib/6500/descr b/lib/6500/descr index 70c5445b4..32885519b 100644 --- a/lib/6500/descr +++ b/lib/6500/descr @@ -29,19 +29,19 @@ name asld mapflag -i IFILE={EM}/{RT}i mapflag -ansi C_LIB={EM}/{LIB}ac args {IFILE?} (.e:{HEAD}={EM}/{RT}em) \ - ({RTS}:.ocm.b={EM}/{RT}cc) \ + ({RTS}:.ocm.bas={EM}/{RT}cc) \ ({RTS}{ANSI?}:.c={EM}/{RT}cc) \ ({RTS}{ANSI?}:.cansi={EM}/{RT}ac) \ ({RTS}:.p={EM}/{RT}pc) \ ({RTS}:.mod={EM}/{RT}m2) \ -o > < \ (.p:{TAIL}={EM}/{LIB}pc) \ - (.b:{TAIL}={EM}/{LIB}bc) \ + (.bas:{TAIL}={EM}/{LIB}bc) \ (.ocm:{TAIL}={EM}/{LIB}ocm) \ (.mod:{TAIL}={EM}/{LIB}m2) \ - (.ocm.b:{TAIL}={OLD_C_LIB}) \ + (.ocm.bas:{TAIL}={OLD_C_LIB}) \ (.c:{TAIL}={C_LIB}) \ - (.mod.ocm.b.c.p.e:{TAIL}={EM}/{LIB}mon) \ + (.mod.ocm.bas.c.p.e:{TAIL}={EM}/{LIB}mon) \ (.e:{TAIL}={EM}/{LIB}em {EM}/{LIB}mon2 {EM}/lib/{M}/end_em) linker end diff --git a/lib/6800/descr b/lib/6800/descr index 59bcabf56..7bf0b53c4 100644 --- a/lib/6800/descr +++ b/lib/6800/descr @@ -25,19 +25,19 @@ name led program {EM}/lib.bin/em_led mapflag -l* LNAME={EM}/{LIB}* args (.e:{HEAD}={EM}/{RT}em) \ - ({RTS}:.ocm.b={EM}/{RT}cc) \ + ({RTS}:.ocm.bas={EM}/{RT}cc) \ ({RTS}{ANSI?}:.c={EM}/{RT}cc) \ ({RTS}{ANSI?}:.cansi={EM}/{RT}ac) \ ({RTS}:.p={EM}/{RT}pc) \ ({RTS}:.mod={EM}/{RT}m2) \ -o > < \ (.p:{TAIL}={EM}/{LIB}pc) \ - (.b:{TAIL}={EM}/{LIB}bc) \ + (.bas:{TAIL}={EM}/{LIB}bc) \ (.ocm:{TAIL}={EM}/{LIB}ocm) \ (.mod:{TAIL}={EM}/{LIB}m2) \ - (.ocm.b:{TAIL}={OLD_C_LIB}) \ + (.ocm.bas:{TAIL}={OLD_C_LIB}) \ (.c:{TAIL}={C_LIB}) \ - (.mod.ocm.b.c.p.e:{TAIL}={EM}/{LIB}mon) \ + (.mod.ocm.bas.c.p.e:{TAIL}={EM}/{LIB}mon) \ (.e:{TAIL}={EM}/{LIB}em {EM}/lib/{M}/end_em) linker end diff --git a/lib/6805/descr b/lib/6805/descr index c4b0077a3..3081cd2d7 100644 --- a/lib/6805/descr +++ b/lib/6805/descr @@ -25,19 +25,19 @@ name led program {EM}/lib.bin/em_led mapflag -l* LNAME={EM}/{LIB}* args (.e:{HEAD}={EM}/{RT}em) \ - ({RTS}:.ocm.b={EM}/{RT}cc) \ + ({RTS}:.ocm.bas={EM}/{RT}cc) \ ({RTS}{ANSI?}:.c={EM}/{RT}cc) \ ({RTS}{ANSI?}:.cansi={EM}/{RT}ac) \ ({RTS}:.p={EM}/{RT}pc) \ ({RTS}:.mod={EM}/{RT}m2) \ -o > < \ (.p:{TAIL}={EM}/{LIB}pc) \ - (.b:{TAIL}={EM}/{LIB}bc) \ + (.bas:{TAIL}={EM}/{LIB}bc) \ (.ocm:{TAIL}={EM}/{LIB}ocm) \ (.mod:{TAIL}={EM}/{LIB}m2) \ - (.ocm.b:{TAIL}={OLD_C_LIB}) \ + (.ocm.bas:{TAIL}={OLD_C_LIB}) \ (.c:{TAIL}={C_LIB}) \ - (.mod.ocm.b.c.p.e:{TAIL}={EM}/{LIB}mon) \ + (.mod.ocm.bas.c.p.e:{TAIL}={EM}/{LIB}mon) \ (.e:{TAIL}={EM}/{LIB}em {EM}/lib/{M}/end_em) linker end diff --git a/lib/6809/descr b/lib/6809/descr index b42be9d4a..1d9848569 100644 --- a/lib/6809/descr +++ b/lib/6809/descr @@ -26,19 +26,19 @@ name led program {EM}/lib.bin/em_led mapflag -l* LNAME={EM}/{LIB}* args -b0:0x800 (.e:{HEAD}={ALIGN} {EM}/{RT}em) \ - ({RTS}:.ocm.b={EM}/{RT}cc) \ + ({RTS}:.ocm.bas={EM}/{RT}cc) \ ({RTS}{ANSI?}:.c={EM}/{RT}cc) \ ({RTS}{ANSI?}:.cansi={EM}/{RT}ac) \ ({RTS}:.p={EM}/{RT}pc) \ ({RTS}:.mod={EM}/{RT}m2) \ -o > < \ (.p:{TAIL}={EM}/{LIB}pc) \ - (.b:{TAIL}={EM}/{LIB}bc) \ + (.bas:{TAIL}={EM}/{LIB}bc) \ (.ocm:{TAIL}={EM}/{LIB}ocm) \ (.mod:{TAIL}={EM}/{LIB}m2) \ - (.ocm.b:{TAIL}={OLD_C_LIB}) \ + (.ocm.bas:{TAIL}={OLD_C_LIB}) \ (.c:{TAIL}={C_LIB}) \ - (.mod.ocm.b.c.p.e:{TAIL}={EM}/{LIB}mon) \ + (.mod.ocm.bas.c.p.e:{TAIL}={EM}/{LIB}mon) \ (.e:{TAIL}={EM}/{LIB}em {EM}/lib/{M}/end_em) linker end diff --git a/lib/arm/descr b/lib/arm/descr index 4f12cc1da..cd49778a0 100644 --- a/lib/arm/descr +++ b/lib/arm/descr @@ -37,7 +37,7 @@ name asld mapflag -l* LNAME={EM}/{LIB}* mapflag -ansi C_LIB={EM}/{LIB}ac args (.e:{HEAD}={EM}/{RT}em) \ - ({RTS}:.ocm.b={EM}/{RT}cc) \ + ({RTS}:.ocm.bas={EM}/{RT}cc) \ ({RTS}{ANSI?}:.c={EM}/{RT}cc) \ ({RTS}{ANSI?}:.cansi={EM}/{RT}ac) \ ({RTS}:.f={EM}/{RT}ac) \ @@ -45,14 +45,14 @@ name asld ({RTS}:.mod={EM}/{RT}m2) \ -o > < \ (.p:{TAIL}={EM}/{LIB}pc) \ - (.b:{TAIL}={EM}/{LIB}bc) \ + (.bas:{TAIL}={EM}/{LIB}bc) \ (.ocm:{TAIL}={EM}/{LIB}ocm) \ (.mod:{TAIL}={EM}/{LIB}m2) \ (.f:{TAIL}={EM}/{LIB}f77 {EM}/{LIB}ac) \ - (.ocm.b:{TAIL}={OLD_C_LIB}) \ + (.ocm.bas:{TAIL}={OLD_C_LIB}) \ (.c:{TAIL}={C_LIB}) \ - (.mod.ocm.b.c.p.f.e:{TAIL}={EM}/{LIB}mon) \ - (.mod.ocm.b.c.p.f.e:{TAIL}={EM}/{LIB}fp) \ + (.mod.ocm.bas.c.p.f.e:{TAIL}={EM}/{LIB}mon) \ + (.mod.ocm.bas.c.p.f.e:{TAIL}={EM}/{LIB}fp) \ (.e:{TAIL}={EM}/{LIB}em {EM}/{LIB}mon2 {EM}/lib/{M}/end_em) linker end diff --git a/lib/descr/cpm b/lib/descr/cpm index 9575b3222..e414ed68f 100644 --- a/lib/descr/cpm +++ b/lib/descr/cpm @@ -22,7 +22,7 @@ name asld mapflag -s* SIZE_F=-s* args {ASS_F?} ({RTS}:.b.c={EM}/{RT}cc) ({RTS}:.p={EM}/{RT}pc) -o > < \ (.p:{TAIL}={EM}/{LIB}pc) \ - (.b:{TAIL}={EM}/{LIB}bc) \ + (.bas:{TAIL}={EM}/{LIB}bc) \ (.b.c:{TAIL}={EM}/{LIB}cc.1s {EM}/{LIB}cc.2g) \ (.b.c.p:{TAIL}={EM}/{LIB}mon) linker diff --git a/lib/descr/fe b/lib/descr/fe index e88663a6d..b40f3ec9d 100644 --- a/lib/descr/fe +++ b/lib/descr/fe @@ -153,8 +153,8 @@ name ocm prep cond callname ocm end -name abc - from .b +name basic + from .bas to .k program {EM}/lib/ack/em_bem mapflag -h ABC_F={ABC_F?} -h @@ -164,9 +164,9 @@ name abc # mapflag -d ABC_F={ABC_F?} -d args -Vw{w}p{p}f{d} {ABC_F?} < > {SOURCE} prep cond - rts .b - need .b - callname abc + rts .bas + need .bas + callname basic end var A68INIT={EM}/lib/ack/em_a68s_init name a68s diff --git a/lib/em22/descr b/lib/em22/descr index ca39d5a94..551222b05 100644 --- a/lib/em22/descr +++ b/lib/em22/descr @@ -25,17 +25,17 @@ name asld mapflag -s* SIZE_FLAG=-s* mapflag -ansi C_LIB={EM}/{LIB}ac args {SIZE_FLAG} \ - ({RTS}:.ocm.b={EM}/{RT}cc) \ + ({RTS}:.ocm.bas={EM}/{RT}cc) \ ({RTS}{ANSI?}:.c={EM}/{RT}cc) \ ({RTS}{ANSI?}:.cansi={EM}/{RT}ac) \ ({RTS}:.mod={EM}/{RT}m2) \ ({RTS}:.p={EM}/{RT}pc) \ -o > < \ (.p:{TAIL}={EM}/{LIB}pc) \ - (.b:{TAIL}={EM}/{LIB}bc) \ + (.bas:{TAIL}={EM}/{LIB}bc) \ (.ocm:{TAIL}={EM}/{LIB}ocm) \ (.mod:{TAIL}={EM}/{LIB}m2) \ - (.ocm.b:{TAIL}={OLD_C_LIB}) \ + (.ocm.bas:{TAIL}={OLD_C_LIB}) \ (.c:{TAIL}={C_LIB}) \ (.b.c.ocm.mod.p.e:{TAIL}={EM}/{LIB}mon) \ ({RTS}{ANSI?}:.cansi={EM}/lib/em22/end_em) diff --git a/lib/em24/descr b/lib/em24/descr index aa04837d7..b3eeb0fb9 100644 --- a/lib/em24/descr +++ b/lib/em24/descr @@ -25,17 +25,17 @@ name asld mapflag -s* SIZE_FLAG=-s* mapflag -ansi C_LIB={EM}/{LIB}ac args {SIZE_FLAG} \ - ({RTS}:.ocm.b={EM}/{RT}cc) \ + ({RTS}:.ocm.bas={EM}/{RT}cc) \ ({RTS}{ANSI?}:.c={EM}/{RT}cc) \ ({RTS}{ANSI?}:.cansi={EM}/{RT}ac) \ ({RTS}:.mod={EM}/{RT}m2) \ ({RTS}:.p={EM}/{RT}pc) \ -o > < \ (.p:{TAIL}={EM}/{LIB}pc) \ - (.b:{TAIL}={EM}/{LIB}bc) \ + (.bas:{TAIL}={EM}/{LIB}bc) \ (.ocm:{TAIL}={EM}/{LIB}ocm) \ (.mod:{TAIL}={EM}/{LIB}m2) \ - (.ocm.b:{TAIL}={OLD_C_LIB}) \ + (.ocm.bas:{TAIL}={OLD_C_LIB}) \ (.c:{TAIL}={C_LIB}) \ (.p.b.mod.ocm.c.e:{TAIL}={EM}/{LIB}mon) \ ({RTS}{ANSI?}:.cansi={EM}/lib/em24/end_em) diff --git a/lib/em44/descr b/lib/em44/descr index 0b4439ced..79531e21b 100644 --- a/lib/em44/descr +++ b/lib/em44/descr @@ -25,7 +25,7 @@ name asld mapflag -s* SIZE_FLAG=-s* mapflag -ansi C_LIB={EM}/{LIB}ac args {SIZE_FLAG} \ - ({RTS}:.ocm.b={EM}/{RT}cc) \ + ({RTS}:.ocm.bas={EM}/{RT}cc) \ ({RTS}{ANSI?}:.c={EM}/{RT}cc) \ ({RTS}{ANSI?}:.cansi={EM}/{RT}ac) \ ({RTS}:.f={EM}/{RT}ac) \ @@ -33,11 +33,11 @@ name asld ({RTS}:.p={EM}/{RT}pc) \ -o > < \ (.p:{TAIL}={EM}/{LIB}pc) \ - (.b:{TAIL}={EM}/{LIB}bc) \ + (.bas:{TAIL}={EM}/{LIB}bc) \ (.ocm:{TAIL}={EM}/{LIB}ocm) \ (.mod:{TAIL}={EM}/{LIB}m2) \ (.f:{TAIL}={EM}/{LIB}f77 {EM}/{LIB}ac) \ - (.ocm.b:{TAIL}={OLD_C_LIB}) \ + (.ocm.bas:{TAIL}={OLD_C_LIB}) \ (.c:{TAIL}={C_LIB}) \ (.p.b.ocm.mod.c.f.e:{TAIL}={EM}/{LIB}mon) \ ({RTS}{ANSI?}:.cansi={EM}/lib/em44/end_em) diff --git a/lib/i286/descr b/lib/i286/descr index 31b74f2b8..9d505d3ca 100644 --- a/lib/i286/descr +++ b/lib/i286/descr @@ -28,7 +28,7 @@ name asld args {IFILE?} (.e:{HEAD}={EM}/{RT}em) \ ({RTS}:.b.c={EM}/{RT}cc) ({RTS}:.p={EM}/{RT}pc) -o > < \ (.p:{TAIL}={EM}/{LIB}pc) \ - (.b:{TAIL}={EM}/{LIB}bc) \ + (.bas:{TAIL}={EM}/{LIB}bc) \ (.b.c:{TAIL}={EM}/{LIB}cc.1s {EM}/{LIB}cc.2g) \ (.b.c.p.e:{TAIL}={EM}/{LIB}alo) (.b.c.p:{TAIL}={EM}/{LIB}mon) \ (.e:{TAIL}={EM}/{LIB}em) diff --git a/lib/i386/descr b/lib/i386/descr index a6ef6b3d8..c8a26cbf5 100644 --- a/lib/i386/descr +++ b/lib/i386/descr @@ -41,7 +41,7 @@ name led mapflag -ansi C_LIB={EM}/{LIB}ac mapflag -g LIBDB={EM}/{LIB}db args {ALIGN} {SEPID?} (.e:{HEAD}={EM}/{RT}em) \ - ({RTS}:.ocm.b={EM}/{RT}cc) \ + ({RTS}:.ocm.bas={EM}/{RT}cc) \ ({RTS}{ANSI?}:.c={EM}/{RT}cc) \ ({RTS}{ANSI?}:.cansi={EM}/{RT}ac) \ ({RTS}:.mod={EM}/{RT}m2) \ @@ -49,11 +49,11 @@ name led ({RTS}:.p={EM}/{RT}pc) \ -o > < \ (.p:{TAIL}={EM}/{LIB}pc) \ - (.b:{TAIL}={EM}/{LIB}bc) \ + (.bas:{TAIL}={EM}/{LIB}bc) \ (.mod:{TAIL}={EM}/{LIB}m2) \ (.f:{TAIL}={EM}/{LIB}f {EM}/{LIB}ac) \ (.ocm:{TAIL}={EM}/{LIB}ocm) \ - (.ocm.b:{TAIL}={OLD_C_LIB}) \ + (.ocm.bas:{TAIL}={OLD_C_LIB}) \ (.c:{TAIL}={C_LIB}) \ {FLOATS?} \ {LIBDB?} \ diff --git a/lib/i80/descr b/lib/i80/descr index 9964d031a..293352338 100644 --- a/lib/i80/descr +++ b/lib/i80/descr @@ -36,19 +36,19 @@ name led mapflag -l* LNAME={EM}/{LIB}* mapflag -ansi C_LIB={EM}/{LIB}ac args -b0:0x1000 {ALIGN} {SEPID?} (.e:{HEAD}={EM}/{RT}em) \ - ({RTS}:.ocm.b={EM}/{RT}cc) \ + ({RTS}:.ocm.bas={EM}/{RT}cc) \ ({RTS}{ANSI?}:.c={EM}/{RT}cc) \ ({RTS}{ANSI?}:.cansi={EM}/{RT}ac) \ ({RTS}:.p={EM}/{RT}pc) \ ({RTS}:.mod={EM}/{RT}m2) \ -o > < \ (.p:{TAIL}={EM}/{LIB}pc) \ - (.b:{TAIL}={EM}/{LIB}bc) \ + (.bas:{TAIL}={EM}/{LIB}bc) \ (.ocm:{TAIL}={EM}/{LIB}ocm) \ (.mod:{TAIL}={EM}/{LIB}m2) \ - (.ocm.b:{TAIL}={OLD_C_LIB}) \ + (.ocm.bas:{TAIL}={OLD_C_LIB}) \ (.c:{TAIL}={C_LIB}) \ - (.mod.ocm.b.c.p.e:{TAIL}={EM}/{LIB}mon) \ + (.mod.ocm.bas.c.p.e:{TAIL}={EM}/{LIB}mon) \ (.e:{TAIL}={EM}/{LIB}em {EM}/{LIB}mon2 {EM}/lib/{M}/end_em) linker end diff --git a/lib/i86/descr b/lib/i86/descr index 7fcb90e0d..1d402fba5 100644 --- a/lib/i86/descr +++ b/lib/i86/descr @@ -38,17 +38,17 @@ name led mapflag -fp FLOATS={EM}/{ILIB}fp mapflag -ansi C_LIB={EM}/{LIB}ac args {ALIGN} {SEPID?} (.e:{HEAD}={EM}/{RT}em) \ - ({RTS}:.ocm.b={EM}/{RT}cc) \ + ({RTS}:.ocm.bas={EM}/{RT}cc) \ ({RTS}{ANSI?}:.c={EM}/{RT}cc) \ ({RTS}{ANSI?}:.cansi={EM}/{RT}ac) \ ({RTS}:.mod={EM}/{RT}m2) \ ({RTS}:.p={EM}/{RT}pc) \ -o > < \ (.p:{TAIL}={EM}/{LIB}pc) \ - (.b:{TAIL}={EM}/{LIB}bc) \ + (.bas:{TAIL}={EM}/{LIB}bc) \ (.mod:{TAIL}={EM}/{LIB}m2) \ (.ocm:{TAIL}={EM}/{LIB}ocm) \ - (.ocm.b:{TAIL}={OLD_C_LIB}) \ + (.ocm.bas:{TAIL}={OLD_C_LIB}) \ (.c:{TAIL}={C_LIB}) \ {FLOATS?} \ (.e:{TAIL}={EM}/{LIB}em {EM}/{LIB}mon {EM}/lib/{M}/end_em) diff --git a/lib/m68020/descr b/lib/m68020/descr index 2e3e7fbc5..73b147869 100644 --- a/lib/m68020/descr +++ b/lib/m68020/descr @@ -49,7 +49,7 @@ name led mapflag -ansi C_LIB={EM}/{LIB}ac mapflag -g LIBDB={EM}/{LIB}db args {ALIGN} (.e:{HEAD}= {EM}/{RT}em) \ - ({RTS}:.ocm.b={EM}/{RT}cc) \ + ({RTS}:.ocm.bas={EM}/{RT}cc) \ ({RTS}{ANSI?}:.c={EM}/{RT}cc) \ ({RTS}{ANSI?}:.cansi={EM}/{RT}ac) \ ({RTS}:.f={EM}/{RT}ac) \ @@ -57,11 +57,11 @@ name led ({RTS}:.mod={EM}/{RT}m2) \ -o > < \ (.p:{TAIL}={EM}/{LIB}pc) \ - (.b:{TAIL}={EM}/{LIB}bc) \ + (.bas:{TAIL}={EM}/{LIB}bc) \ (.ocm:{TAIL}={EM}/{LIB}ocm) \ (.mod:{TAIL}={EM}/{LIB}m2) \ (.f:{TAIL}={EM}/{LIB}f77 {EM}/{LIB}ac) \ - (.ocm.b:{TAIL}={OLD_C_LIB}) \ + (.ocm.bas:{TAIL}={OLD_C_LIB}) \ (.c:{TAIL}={C_LIB}) \ {LIBFP?} \ {LIBDB?} \ diff --git a/lib/m68k2/descr b/lib/m68k2/descr index 61dcbdb08..581debf09 100644 --- a/lib/m68k2/descr +++ b/lib/m68k2/descr @@ -51,17 +51,17 @@ name led mapflag -fp LIBFP={EM}/{LIB}fp mapflag -ansi C_LIB={EM}/{LIB}ac args -b0:0x20000 {ALIGN} (.e:{HEAD}={EM}/{RT}em) \ - ({RTS}:.ocm.b={EM}/{RT}cc) \ + ({RTS}:.ocm.bas={EM}/{RT}cc) \ ({RTS}{ANSI?}:.c={EM}/{RT}cc) \ ({RTS}{ANSI?}:.cansi={EM}/{RT}ac) \ ({RTS}:.p={EM}/{RT}pc) \ ({RTS}:.mod={EM}/{RT}m2) \ -o > < \ (.p:{TAIL}={EM}/{LIB}pc) \ - (.b:{TAIL}={EM}/{LIB}bc) \ + (.bas:{TAIL}={EM}/{LIB}bc) \ (.ocm:{TAIL}={EM}/{LIB}ocm) \ (.mod:{TAIL}={EM}/{LIB}m2) \ - (.ocm.b:{TAIL}={OLD_C_LIB}) \ + (.ocm.bas:{TAIL}={OLD_C_LIB}) \ (.c:{TAIL}={C_LIB}) \ {LIBFP?} \ (.e:{TAIL}={EM}/{LIB}em {EM}/{LIB}mon {EM}/lib/{M}/end_em) diff --git a/lib/m68k4/descr b/lib/m68k4/descr index bc2fa4992..ca628d5c6 100644 --- a/lib/m68k4/descr +++ b/lib/m68k4/descr @@ -51,7 +51,7 @@ name led mapflag -fp LIBFP={EM}/{LIB}fp mapflag -ansi C_LIB={EM}/{LIB}ac args -b0:0x20000 {ALIGN} (.e:{HEAD}={EM}/{RT}em) \ - ({RTS}:.ocm.b={EM}/{RT}cc) \ + ({RTS}:.ocm.bas={EM}/{RT}cc) \ ({RTS}{ANSI?}:.c={EM}/{RT}cc) \ ({RTS}{ANSI?}:.cansi={EM}/{RT}ac) \ ({RTS}:.f={EM}/{RT}ac) \ @@ -59,11 +59,11 @@ name led ({RTS}:.mod={EM}/{RT}m2) \ -o > < \ (.p:{TAIL}={EM}/{LIB}pc) \ - (.b:{TAIL}={EM}/{LIB}bc) \ + (.bas:{TAIL}={EM}/{LIB}bc) \ (.ocm:{TAIL}={EM}/{LIB}ocm) \ (.mod:{TAIL}={EM}/{LIB}m2) \ (.f:{TAIL}={EM}/{LIB}f77 {EM}/{LIB}ac) \ - (.ocm.b:{TAIL}={OLD_C_LIB}) \ + (.ocm.bas:{TAIL}={OLD_C_LIB}) \ (.c:{TAIL}={C_LIB}) \ {LIBFP?} \ (.e:{TAIL}={EM}/{LIB}em {EM}/{LIB}mon {EM}/lib/{M}/end_em) diff --git a/lib/mantra/descr b/lib/mantra/descr index 2183e9555..8ca806316 100644 --- a/lib/mantra/descr +++ b/lib/mantra/descr @@ -52,7 +52,7 @@ name led mapflag -fp LIBFP={EM}/{MLIB}fp mapflag -ansi C_LIB={EM}/{LIB}ac args -b0:0x80000 {ALIGN} (.e:{HEAD}={EM}/{RT}em) \ - ({RTS}:.ocm.b={EM}/{RT}cc) \ + ({RTS}:.ocm.bas={EM}/{RT}cc) \ ({RTS}{ANSI?}:.c={EM}/{RT}cc) \ ({RTS}{ANSI?}:.cansi={EM}/{RT}ac) \ ({RTS}:.mod={EM}/{RT}m2) \ @@ -60,11 +60,11 @@ name led ({RTS}:.p={EM}/{RT}pc) \ -o > < \ (.p:{TAIL}={EM}/{LIB}pc) \ - (.b:{TAIL}={EM}/{LIB}bc) \ + (.bas:{TAIL}={EM}/{LIB}bc) \ (.mod:{TAIL}={EM}/{LIB}m2) \ (.f:{TAIL}={EM}/{LIB}f77 {EM}/{LIB}ac) \ (.ocm:{TAIL}={EM}/{LIB}ocm) \ - (.ocm.b:{TAIL}={OLD_C_LIB}) \ + (.ocm.bas:{TAIL}={OLD_C_LIB}) \ (.c:{TAIL}={C_LIB}) \ {LIBFP?} \ (.e:{TAIL}={EM}/{MLIB}em {EM}/{LIB}mon {EM}/lib/{M}/end_em) diff --git a/lib/minix/descr b/lib/minix/descr index 45b22a525..66e48c8a9 100644 --- a/lib/minix/descr +++ b/lib/minix/descr @@ -42,14 +42,14 @@ name led mapflag -ansi C_LIB={EM}/{LIB}ac args {ALIGN} {SEPID?} \ (.e:{HEAD}={EM}/{RT}em) \ - ({RTS}:.ocm.b={EM}/{RT}cc) \ + ({RTS}:.ocm.bas={EM}/{RT}cc) \ ({RTS}{ANSI?}:.c={EM}/{RT}cc) \ ({RTS}{ANSI?}:.cansi={EM}/{RT}ac) \ ({RTS}:.p={EM}/{RT}pc) -o > < \ (.p:{TAIL}={EM}/{LIB}pc) \ - (.b:{TAIL}={EM}/{LIB}bc) \ + (.bas:{TAIL}={EM}/{LIB}bc) \ (.ocm:{TAIL}={EM}/{LIB}ocm) \ - (.ocm.b:{TAIL}={OLD_C_LIB}) \ + (.ocm.bas:{TAIL}={OLD_C_LIB}) \ (.c:{TAIL}={C_LIB}) \ {LIBFP?} \ (.e:{TAIL}={EM}/{MLIB}em {EM}/{LIB}mon {EM}/lib/i86/end_em) diff --git a/lib/minixST/descr b/lib/minixST/descr index cd3f7b838..e9326714d 100644 --- a/lib/minixST/descr +++ b/lib/minixST/descr @@ -41,17 +41,17 @@ name led mapflag -fp LIBFP={EM}/{NLIB}fp mapflag -ansi C_LIB={EM}/{LIB}ac args {ALIGN} {SEPID?} -c (.e:{HEAD}={EM}/{RT}em) \ - ({RTS}:.ocm.b={EM}/{RT}cc) \ + ({RTS}:.ocm.bas={EM}/{RT}cc) \ ({RTS}{ANSI?}:.c={EM}/{RT}cc) \ ({RTS}{ANSI?}:.cansi={EM}/{RT}ac) \ ({RTS}:.p={EM}/{RT}pc) \ ({RTS}:.mod={EM}/{RT}m2) \ -o > < \ (.p:{TAIL}={EM}/{LIB}pc) \ - (.b:{TAIL}={EM}/{LIB}bc) \ + (.bas:{TAIL}={EM}/{LIB}bc) \ (.ocm:{TAIL}={EM}/{LIB}ocm) \ (.mod:{TAIL}={EM}/{LIB}m2) \ - (.ocm.b:{TAIL}={OLD_C_LIB}) \ + (.ocm.bas:{TAIL}={OLD_C_LIB}) \ (.c:{TAIL}={C_LIB}) \ {LIBFP?} \ (.e:{TAIL}={EM}/{LIB}mon {EM}/{MLIB}em {EM}/lib/m68k2/end_em) diff --git a/lib/ns/descr b/lib/ns/descr index 1fe1b8f82..7b21ddc19 100644 --- a/lib/ns/descr +++ b/lib/ns/descr @@ -36,7 +36,7 @@ name led mapflag -l* LNAME={EM}/{LIB}* mapflag -ansi C_LIB={EM}/{LIB}ac args {ALIGN} (.e:{HEAD}={EM}/{RT}em) \ - ({RTS}:.ocm.b={EM}/{RT}cc) \ + ({RTS}:.ocm.bas={EM}/{RT}cc) \ ({RTS}{ANSI?}:.c={EM}/{RT}cc) \ ({RTS}{ANSI?}:.cansi={EM}/{RT}ac) \ ({RTS}:.f={EM}/{RT}ac) \ @@ -44,11 +44,11 @@ name led ({RTS}:.mod={EM}/{RT}m2) \ -o > < \ (.p:{TAIL}={EM}/{LIB}pc) \ - (.b:{TAIL}={EM}/{LIB}bc) \ + (.bas:{TAIL}={EM}/{LIB}bc) \ (.ocm:{TAIL}={EM}/{LIB}ocm) \ (.mod:{TAIL}={EM}/{LIB}m2) \ (.f:{TAIL}={EM}/{LIB}f77 {EM}/{LIB}ac) \ - (.ocm.b:{TAIL}={OLD_C_LIB}) \ + (.ocm.bas:{TAIL}={OLD_C_LIB}) \ (.c:{TAIL}={C_LIB}) \ (.e:{TAIL}={EM}/{LIB}mon {EM}/{LIB}mon2 {EM}/{LIB}em {EM}/lib/{M}/end_em) linker diff --git a/lib/pdp/descr b/lib/pdp/descr index 46d403b54..7b4bf0f0d 100644 --- a/lib/pdp/descr +++ b/lib/pdp/descr @@ -47,17 +47,17 @@ name led mapflag -nr ALIGN=-a0:1 -a1:1 -a2:0x2000 -a3:1 mapflag -ansi C_LIB={EM}/{LIB}ac args {ALIGN} {SEPID?} (.e:{HEAD}={EM}/{RT}em) \ - ({RTS}:.ocm.b={EM}/{RT}cc) \ + ({RTS}:.ocm.bas={EM}/{RT}cc) \ ({RTS}{ANSI?}:.c={EM}/{RT}cc) \ ({RTS}{ANSI?}:.cansi={EM}/{RT}ac) \ ({RTS}:.mod={EM}/{RT}m2) \ ({RTS}:.p={EM}/{RT}pc) \ -o > < \ (.p:{TAIL}={EM}/{LIB}pc) \ - (.b:{TAIL}={EM}/{LIB}bc) \ + (.bas:{TAIL}={EM}/{LIB}bc) \ (.ocm:{TAIL}={EM}/{LIB}ocm) \ (.mod:{TAIL}={EM}/{LIB}m2) \ - (.ocm.b:{TAIL}={OLD_C_LIB}) \ + (.ocm.bas:{TAIL}={OLD_C_LIB}) \ (.c:{TAIL}={C_LIB}) \ (.e:{TAIL}={EM}/{LIB}em {EM}/{LIB}mon {EM}/lib/{M}/end_em) linker diff --git a/lib/pmds/descr b/lib/pmds/descr index c5f76c60d..96342504c 100644 --- a/lib/pmds/descr +++ b/lib/pmds/descr @@ -53,17 +53,17 @@ name led mapflag -fp LIBFP={EM}/{MLIB}fp mapflag -ansi C_LIB={EM}/{LIB}ac args {ALIGN} (.e:{HEAD}={EM}/{RT}em) \ - ({RTS}:.ocm.b={EM}/{RT}cc) \ + ({RTS}:.ocm.bas={EM}/{RT}cc) \ ({RTS}{ANSI?}:.c={EM}/{RT}cc) \ ({RTS}{ANSI?}:.cansi={EM}/{RT}ac) \ ({RTS}:.p={EM}/{RT}pc) \ ({RTS}:.mod={EM}/{RT}m2) \ -o > < \ (.p:{TAIL}={EM}/{LIB}pc) \ - (.b:{TAIL}={EM}/{LIB}bc) \ + (.bas:{TAIL}={EM}/{LIB}bc) \ (.ocm:{TAIL}={EM}/{LIB}ocm) \ (.mod:{TAIL}={EM}/{LIB}m2) \ - (.ocm.b:{TAIL}={OLD_C_LIB}) \ + (.ocm.bas:{TAIL}={OLD_C_LIB}) \ (.c:{TAIL}={C_LIB}) \ {LIBFP?} \ (.e:{TAIL}={EM}/{MLIB}em {EM}/{LIB}mon {EM}/lib/{M}/end_em) diff --git a/lib/pmds4/descr b/lib/pmds4/descr index 0802f1cc1..8ae806f24 100644 --- a/lib/pmds4/descr +++ b/lib/pmds4/descr @@ -53,7 +53,7 @@ name led mapflag -fp LIBFP={EM}/{MLIB}fp mapflag -ansi C_LIB={EM}/{LIB}ac args {ALIGN} (.e:{HEAD}={EM}/{RT}em) \ - ({RTS}:.ocm.b={EM}/{RT}cc) \ + ({RTS}:.ocm.bas={EM}/{RT}cc) \ ({RTS}{ANSI?}:.c={EM}/{RT}cc) \ ({RTS}{ANSI?}:.cansi={EM}/{RT}ac) \ ({RTS}:.f={EM}/{RT}ac) \ @@ -61,11 +61,11 @@ name led ({RTS}:.mod={EM}/{RT}m2) \ -o > < \ (.p:{TAIL}={EM}/{LIB}pc) \ - (.b:{TAIL}={EM}/{LIB}bc) \ + (.bas:{TAIL}={EM}/{LIB}bc) \ (.ocm:{TAIL}={EM}/{LIB}ocm) \ (.mod:{TAIL}={EM}/{LIB}m2) \ (.f:{TAIL}={EM}/{LIB}f77 {EM}/{LIB}ac) \ - (.ocm.b:{TAIL}={OLD_C_LIB}) \ + (.ocm.bas:{TAIL}={OLD_C_LIB}) \ (.c:{TAIL}={C_LIB}) \ {LIBFP?} \ (.e:{TAIL}={EM}/{MLIB}em {EM}/{LIB}mon {EM}/lib/{M}/end_em) diff --git a/lib/s2650/descr b/lib/s2650/descr index 11028bd59..a9fdc0076 100644 --- a/lib/s2650/descr +++ b/lib/s2650/descr @@ -25,19 +25,19 @@ name led program {EM}/lib.bin/em_led mapflag -l* LNAME={EM}/{LIB}* args (.e:{HEAD}={EM}/{RT}em) \ - ({RTS}:.ocm.b={EM}/{RT}cc) \ + ({RTS}:.ocm.bas={EM}/{RT}cc) \ ({RTS}{ANSI?}:.c={EM}/{RT}cc) \ ({RTS}{ANSI?}:.cansi={EM}/{RT}ac) \ ({RTS}:.p={EM}/{RT}pc) \ ({RTS}:.mod={EM}/{RT}m2) \ -o > < \ (.p:{TAIL}={EM}/{LIB}pc) \ - (.b:{TAIL}={EM}/{LIB}bc) \ + (.bas:{TAIL}={EM}/{LIB}bc) \ (.ocm:{TAIL}={EM}/{LIB}ocm) \ (.mod:{TAIL}={EM}/{LIB}m2) \ - (.ocm.b:{TAIL}={OLD_C_LIB}) \ + (.ocm.bas:{TAIL}={OLD_C_LIB}) \ (.c:{TAIL}={C_LIB}) \ - (.mod.ocm.b.c.p.e:{TAIL}={EM}/{LIB}mon) \ + (.mod.ocm.bas.c.p.e:{TAIL}={EM}/{LIB}mon) \ (.e:{TAIL}={EM}/{LIB}em {EM}/lib/{M}/end_em) linker end diff --git a/lib/sparc/descr b/lib/sparc/descr index 10d129b47..1730f009e 100644 --- a/lib/sparc/descr +++ b/lib/sparc/descr @@ -48,7 +48,7 @@ name led mapflag -ansi C_LIB={EM}/{LIB}ac args -Bstatic -dc -e begtext \ (.e:{HEAD}= {EM}/{RT}em) \ - ({RTS}:.ocm.b={EM}/{RT}cc) \ + ({RTS}:.ocm.bas={EM}/{RT}cc) \ ({RTS}{ANSI?}:.c={EM}/{RT}cc) \ ({RTS}{ANSI?}:.cansi={EM}/{RT}ac) \ ({RTS}:.f={EM}/{RT}ac) \ @@ -59,11 +59,11 @@ name led (.8:{TAIL}={EM}/{LIB}a68s) \ (.p:{TAIL}={EM}/{LIB}pc) \ (.cp.8:{TAIL}={EM}/{LIB}cpc) \ - (.b:{TAIL}={EM}/{LIB}bc) \ + (.bas:{TAIL}={EM}/{LIB}bc) \ (.ocm:{TAIL}={EM}/{LIB}ocm) \ (.mod:{TAIL}={EM}/{LIB}m2) \ (.f:{TAIL}={EM}/{LIB}f77 {EM}/{LIB}ac) \ - (.ocm.b:{TAIL}={OLD_C_LIB}) \ + (.ocm.bas:{TAIL}={OLD_C_LIB}) \ (.c:{TAIL}={C_LIB}) \ {LIBDB?} \ (.e:{TAIL}={EM}/{LIB}em {EM}/{LIB}mon {EM}/lib/{M}/end_em) diff --git a/lib/sparc_solaris/descr b/lib/sparc_solaris/descr index 43faa72ab..137768b9d 100644 --- a/lib/sparc_solaris/descr +++ b/lib/sparc_solaris/descr @@ -48,7 +48,7 @@ name led mapflag -ansi C_LIB={EM}/{LIB}ac args \ (.e:{HEAD}= {EM}/{RT}em) \ - ({RTS}:.ocm.b={EM}/{RT}cc) \ + ({RTS}:.ocm.bas={EM}/{RT}cc) \ ({RTS}{ANSI?}:.c={EM}/{RT}cc) \ ({RTS}{ANSI?}:.cansi={EM}/{RT}ac) \ ({RTS}:.f={EM}/{RT}ac) \ @@ -59,11 +59,11 @@ name led (.8:{TAIL}={EM}/{LIB}a68s) \ (.p:{TAIL}={EM}/{LIB}pc) \ (.cp.8:{TAIL}={EM}/{LIB}cpc) \ - (.b:{TAIL}={EM}/{LIB}bc) \ + (.bas:{TAIL}={EM}/{LIB}bc) \ (.ocm:{TAIL}={EM}/{LIB}ocm) \ (.mod:{TAIL}={EM}/{LIB}m2) \ (.f:{TAIL}={EM}/{LIB}f77 {EM}/{LIB}ac) \ - (.ocm.b:{TAIL}={OLD_C_LIB}) \ + (.ocm.bas:{TAIL}={OLD_C_LIB}) \ (.c:{TAIL}={C_LIB}) \ {LIBDB?} \ (.e:{TAIL}={EM}/{LIB}em {EM}/{LIB}mon -lc {EM}/lib/{M}/end_em) diff --git a/lib/sun2/descr b/lib/sun2/descr index 84507ffdb..b4a20bdf0 100644 --- a/lib/sun2/descr +++ b/lib/sun2/descr @@ -55,7 +55,7 @@ name led mapflag -fp LIBFP={EM}/{MLIB}fp mapflag -ansi C_LIB={EM}/{LIB}ac args {ALIGN} (.e:{HEAD}={EM}/{RT}em) \ - ({RTS}:.ocm.b={EM}/{RT}cc) \ + ({RTS}:.ocm.bas={EM}/{RT}cc) \ ({RTS}{ANSI?}:.c={EM}/{RT}cc) \ ({RTS}{ANSI?}:.cansi={EM}/{RT}ac) \ ({RTS}:.f={EM}/{RT}ac) \ @@ -63,11 +63,11 @@ name led ({RTS}:.mod={EM}/{RT}m2) \ -o > < \ (.p:{TAIL}={EM}/{LIB}pc) \ - (.b:{TAIL}={EM}/{LIB}bc) \ + (.bas:{TAIL}={EM}/{LIB}bc) \ (.ocm:{TAIL}={EM}/{LIB}ocm) \ (.mod:{TAIL}={EM}/{LIB}m2) \ (.f:{TAIL}={EM}/{LIB}f77 {EM}/{LIB}ac) \ - (.ocm.b:{TAIL}={OLD_C_LIB}) \ + (.ocm.bas:{TAIL}={OLD_C_LIB}) \ (.c:{TAIL}={C_LIB}) \ {LIBFP?} \ (.e:{TAIL}={EM}/{MLIB}em {EM}/{LIB}mon {EM}/lib/{M}/end_em) diff --git a/lib/sun3/descr b/lib/sun3/descr index a1d3a33d0..4cf88dd52 100644 --- a/lib/sun3/descr +++ b/lib/sun3/descr @@ -56,7 +56,7 @@ name led mapflag -g LIBDB={EM}/{MLIB}db mapflag -ansi C_LIB={EM}/{LIB}ac args {ALIGN} (.e:{HEAD}= {EM}/{RT}em) \ - ({RTS}:.ocm.b={EM}/{RT}cc) \ + ({RTS}:.ocm.bas={EM}/{RT}cc) \ ({RTS}{ANSI?}:.c={EM}/{RT}cc) \ ({RTS}{ANSI?}:.cansi={EM}/{RT}ac) \ ({RTS}:.mod={EM}/{RT}m2) \ @@ -67,11 +67,11 @@ name led (.8:{TAIL}={EM}/{LIB}a68s) \ (.p:{TAIL}={EM}/{LIB}pc) \ (.cp.8:{TAIL}={EM}/{LIB}cpc) \ - (.b:{TAIL}={EM}/{LIB}bc) \ + (.bas:{TAIL}={EM}/{LIB}bc) \ (.ocm:{TAIL}={EM}/{LIB}ocm) \ (.mod:{TAIL}={EM}/{LIB}m2) \ (.f:{TAIL}={EM}/{LIB}f77 {EM}/{LIB}ac) \ - (.ocm.b:{TAIL}={OLD_C_LIB}) \ + (.ocm.bas:{TAIL}={OLD_C_LIB}) \ (.c:{TAIL}={C_LIB}) \ {LIBFP?} \ {LIBDB?} \ diff --git a/lib/vax4/descr b/lib/vax4/descr index d17a937e4..ef2c96e58 100644 --- a/lib/vax4/descr +++ b/lib/vax4/descr @@ -51,7 +51,7 @@ name led mapflag -ansi C_LIB={EM}/{LIB}ac mapflag -g LIBDB={EM}/{LIB}db args {ALIGN} (.e:{HEAD}= {EM}/{RT}em) \ - ({RTS}:.ocm.b={EM}/{RT}cc) \ + ({RTS}:.ocm.bas={EM}/{RT}cc) \ ({RTS}{ANSI?}:.c={EM}/{RT}cc) \ ({RTS}{ANSI?}:.cansi={EM}/{RT}ac) \ ({RTS}:.mod={EM}/{RT}m2) \ @@ -60,11 +60,11 @@ name led -o > < \ (.8:{TAIL}={EM}/{LIB}a68s) \ (.p.8:{TAIL}={EM}/{LIB}pc) \ - (.b:{TAIL}={EM}/{LIB}bc) \ + (.bas:{TAIL}={EM}/{LIB}bc) \ (.ocm:{TAIL}={EM}/{LIB}ocm) \ (.mod:{TAIL}={EM}/{LIB}m2) \ (.f:{TAIL}={EM}/{LIB}f77 {EM}/{LIB}ac) \ - (.ocm.b:{TAIL}={OLD_C_LIB}) \ + (.ocm.bas:{TAIL}={OLD_C_LIB}) \ (.c:{TAIL}={C_LIB}) \ {LIBDB?} \ (.e:{TAIL}={EM}/{LIB}em {EM}/{LIB}mon {EM}/lib/{M}/end_em) diff --git a/lib/xenix3/descr b/lib/xenix3/descr index 2d3f85d0d..9fefc2a9e 100644 --- a/lib/xenix3/descr +++ b/lib/xenix3/descr @@ -40,17 +40,17 @@ name led mapflag -fp FLOATS={EM}/{ILIB}fp mapflag -ansi C_LIB={EM}/{LIB}ac args {ALIGN} {SEPID?} (.e:{HEAD}={EM}/{RT}em) \ - ({RTS}:.ocm.b={EM}/{RT}cc) \ + ({RTS}:.ocm.bas={EM}/{RT}cc) \ ({RTS}{ANSI?}:.c={EM}/{RT}cc) \ ({RTS}{ANSI?}:.cansi={EM}/{RT}ac) \ ({RTS}:.p={EM}/{RT}pc) \ ({RTS}:.mod={EM}/{RT}m2) \ -o > < \ (.p:{TAIL}={EM}/{LIB}pc) \ - (.b:{TAIL}={EM}/{LIB}bc) \ + (.bas:{TAIL}={EM}/{LIB}bc) \ (.mod:{TAIL}={EM}/{LIB}m2) \ (.ocm:{TAIL}={EM}/{LIB}ocm) \ - (.ocm.b:{TAIL}={OLD_C_LIB}) \ + (.ocm.bas:{TAIL}={OLD_C_LIB}) \ (.c:{TAIL}={C_LIB}) \ {FLOATS?} \ (.e:{TAIL}={EM}/{ILIB}em {EM}/{LIB}mon {EM}/lib/i86/end_em) diff --git a/lib/z80/descr b/lib/z80/descr index cd1fd4850..152b5d7df 100644 --- a/lib/z80/descr +++ b/lib/z80/descr @@ -35,19 +35,19 @@ name led mapflag -l* LNAME={EM}/{LIB}* mapflag -ansi C_LIB={EM}/{LIB}ac args -b0:0x1000 (.e:{HEAD}={EM}/{RT}em) \ - ({RTS}:.ocm.b={EM}/{RT}cc) \ + ({RTS}:.ocm.bas={EM}/{RT}cc) \ ({RTS}{ANSI?}:.c={EM}/{RT}cc) \ ({RTS}{ANSI?}:.cansi={EM}/{RT}ac) \ ({RTS}:.p={EM}/{RT}pc) \ ({RTS}:.mod={EM}/{RT}m2) \ -o > < \ (.p:{TAIL}={EM}/{LIB}pc) \ - (.b:{TAIL}={EM}/{LIB}bc) \ + (.bas:{TAIL}={EM}/{LIB}bc) \ (.ocm:{TAIL}={EM}/{LIB}ocm) \ (.mod:{TAIL}={EM}/{LIB}m2) \ - (.ocm.b:{TAIL}={OLD_C_LIB}) \ + (.ocm.bas:{TAIL}={OLD_C_LIB}) \ (.c:{TAIL}={C_LIB}) \ - (.mod.ocm.b.c.p.e:{TAIL}={EM}/{LIB}mon) \ + (.mod.ocm.bas.c.p.e:{TAIL}={EM}/{LIB}mon) \ (.e:{TAIL}={EM}/{LIB}em {EM}/{LIB}mon2 {EM}/lib/{M}/end_em) linker end diff --git a/lib/z8000/descr b/lib/z8000/descr index 61085f014..1ac1780e5 100644 --- a/lib/z8000/descr +++ b/lib/z8000/descr @@ -29,19 +29,19 @@ name asld mapflag -i IFILE={EM}/{RT}i mapflag -ansi C_LIB={EM}/{LIB}ac args {IFILE?} (.e:{HEAD}={EM}/{RT}em) \ - ({RTS}:.ocm.b={EM}/{RT}cc) \ + ({RTS}:.ocm.bas={EM}/{RT}cc) \ ({RTS}{ANSI?}:.c={EM}/{RT}cc) \ ({RTS}{ANSI?}:.cansi={EM}/{RT}ac) \ ({RTS}:.p={EM}/{RT}pc) \ ({RTS}:.mod={EM}/{RT}m2) \ -o > < \ (.p:{TAIL}={EM}/{LIB}pc) \ - (.b:{TAIL}={EM}/{LIB}bc) \ + (.bas:{TAIL}={EM}/{LIB}bc) \ (.ocm:{TAIL}={EM}/{LIB}ocm) \ (.mod:{TAIL}={EM}/{LIB}m2) \ - (.ocm.b:{TAIL}={OLD_C_LIB}) \ + (.ocm.bas:{TAIL}={OLD_C_LIB}) \ (.c:{TAIL}={C_LIB}) \ - (.mod.ocm.b.c.p.e:{TAIL}={EM}/{LIB}mon) \ + (.mod.ocm.bas.c.p.e:{TAIL}={EM}/{LIB}mon) \ (.e:{TAIL}={EM}/{LIB}em {EM}/{LIB}mon2 {EM}/lib/z8000/end_em) linker end diff --git a/mach/z80/int/em22 b/mach/z80/int/em22 index 8591c7bfc..d30597a0e 100644 --- a/mach/z80/int/em22 +++ b/mach/z80/int/em22 @@ -25,17 +25,17 @@ name asld mapflag -s* SIZE_FLAG=-s* mapflag -ansi C_LIB={EM}/{LIB}ac args {SIZE_FLAG} \ - ({RTS}:.ocm.b={EM}/{RT}cc) \ + ({RTS}:.ocm.bas={EM}/{RT}cc) \ ({RTS}{ANSI?}:.c={EM}/{RT}cc) \ ({RTS}{ANSI?}:.cansi={EM}/{RT}ac) \ ({RTS}:.mod={EM}/{RT}m2) \ ({RTS}:.p={EM}/{RT}pc) \ -o > < \ (.p:{TAIL}={EM}/{LIB}pc) \ - (.b:{TAIL}={EM}/{LIB}bc) \ + (.bas:{TAIL}={EM}/{LIB}bc) \ (.ocm:{TAIL}={EM}/{LIB}ocm) \ (.mod:{TAIL}={EM}/{LIB}m2) \ - (.ocm.b:{TAIL}={OLD_C_LIB}) \ + (.ocm.bas:{TAIL}={OLD_C_LIB}) \ (.c:{TAIL}={C_LIB}) \ (.b.c.ocm.mod.p.e:{TAIL}={EM}/{LIB}mon) \ ({RTS}{ANSI?}:.cansi={EM}/lib/em22/end_em) diff --git a/plat/cpm/descr b/plat/cpm/descr index 2d626295a..80dec921c 100644 --- a/plat/cpm/descr +++ b/plat/cpm/descr @@ -61,16 +61,16 @@ name led mapflag -fp FLOATS={EM}/{ILIB}fp args {ALIGN} {SEPID?} \ (.e:{HEAD}={PLATFORMDIR}/boot.o) \ - ({RTS}:.ocm.b={PLATFORMDIR}/c-ansi.o) \ + ({RTS}:.ocm.bas={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) \ + (.bas:{TAIL}={PLATFORMDIR}/libbasic.a) \ (.mod:{TAIL}={PLATFORMDIR}/libmodula2.a) \ (.ocm:{TAIL}={PLATFORMDIR}/liboccam.a) \ - (.ocm.b.mod.c.p:{TAIL}={PLATFORMDIR}/libc.a) \ + (.ocm.bas.mod.c.p:{TAIL}={PLATFORMDIR}/libc.a) \ {FLOATS?} \ (.e:{TAIL}={PLATFORMDIR}/libem.a \ {PLATFORMDIR}/libsys.a \ diff --git a/plat/linux386/descr b/plat/linux386/descr index 611e96e44..92d3b9f9c 100644 --- a/plat/linux386/descr +++ b/plat/linux386/descr @@ -57,16 +57,16 @@ name led mapflag -fp FLOATS={EM}/{LIB}fp args {ALIGN} {SEPID?} \ (.e:{HEAD}={PLATFORMDIR}/boot.o) \ - ({RTS}:.ocm.b={PLATFORMDIR}/c-ansi.o) \ + ({RTS}:.ocm.bas={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) \ + (.bas:{TAIL}={PLATFORMDIR}/libbasic.a) \ (.mod:{TAIL}={PLATFORMDIR}/libmodula2.a) \ (.ocm:{TAIL}={PLATFORMDIR}/liboccam.a) \ - (.ocm.b.mod.c.p:{TAIL}={PLATFORMDIR}/libc.a) \ + (.ocm.bas.mod.c.p:{TAIL}={PLATFORMDIR}/libc.a) \ {FLOATS?} \ (.e:{TAIL}={PLATFORMDIR}/libem.a \ {PLATFORMDIR}/libsys.a \ diff --git a/plat/linux68k/descr b/plat/linux68k/descr index 9347ad2b2..5963d1a44 100644 --- a/plat/linux68k/descr +++ b/plat/linux68k/descr @@ -57,16 +57,16 @@ name led mapflag -fp FLOATS={EM}/{LIB}fp args {ALIGN} {SEPID?} \ (.e:{HEAD}={PLATFORMDIR}/boot.o) \ - ({RTS}:.ocm.b={PLATFORMDIR}/c-ansi.o) \ + ({RTS}:.ocm.bas={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) \ + (.bas:{TAIL}={PLATFORMDIR}/libbasic.a) \ (.mod:{TAIL}={PLATFORMDIR}/libmodula2.a) \ (.ocm:{TAIL}={PLATFORMDIR}/liboccam.a) \ - (.ocm.b.mod.c.p:{TAIL}={PLATFORMDIR}/libc.a) \ + (.ocm.bas.mod.c.p:{TAIL}={PLATFORMDIR}/libc.a) \ {FLOATS?} \ (.e:{TAIL}={PLATFORMDIR}/libem.a \ {PLATFORMDIR}/libsys.a \ diff --git a/plat/linuxppc/descr b/plat/linuxppc/descr index 12bece6e9..f54f4ad3e 100644 --- a/plat/linuxppc/descr +++ b/plat/linuxppc/descr @@ -63,16 +63,16 @@ name led mapflag -fp FLOATS={EM}/{LIB}fp args {ALIGN} {SEPID?} \ (.e:{HEAD}={PLATFORMDIR}/boot.o) \ - ({RTS}:.ocm.b={PLATFORMDIR}/c-ansi.o) \ + ({RTS}:.ocm.bas={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) \ + (.bas:{TAIL}={PLATFORMDIR}/libbasic.a) \ (.mod:{TAIL}={PLATFORMDIR}/libmodula2.a) \ (.ocm:{TAIL}={PLATFORMDIR}/liboccam.a) \ - (.ocm.b.mod.c.p:{TAIL}={PLATFORMDIR}/libc.a) \ + (.ocm.bas.mod.c.p:{TAIL}={PLATFORMDIR}/libc.a) \ {FLOATS?} \ (.e:{TAIL}={PLATFORMDIR}/libem.a \ {PLATFORMDIR}/libsys.a \ diff --git a/plat/pc86/descr b/plat/pc86/descr index d8cb006e6..3037df99f 100644 --- a/plat/pc86/descr +++ b/plat/pc86/descr @@ -53,16 +53,16 @@ name led mapflag -fp FLOATS={EM}/{ILIB}fp args {ALIGN} {SEPID?} \ (.e:{HEAD}={PLATFORMDIR}/boot.o) \ - ({RTS}:.ocm.b={PLATFORMDIR}/c-ansi.o) \ + ({RTS}:.ocm.bas={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) \ + (.bas:{TAIL}={PLATFORMDIR}/libbasic.a) \ (.mod:{TAIL}={PLATFORMDIR}/libmodula2.a) \ (.ocm:{TAIL}={PLATFORMDIR}/liboccam.a) \ - (.ocm.b.mod.c.p:{TAIL}={PLATFORMDIR}/libc.a) \ + (.ocm.bas.mod.c.p:{TAIL}={PLATFORMDIR}/libc.a) \ {FLOATS?} \ (.e:{TAIL}={PLATFORMDIR}/libem.a \ {PLATFORMDIR}/libsys.a \ diff --git a/plat/qemuppc/descr b/plat/qemuppc/descr index c0bc1eab0..43b5743b8 100644 --- a/plat/qemuppc/descr +++ b/plat/qemuppc/descr @@ -63,16 +63,16 @@ name led mapflag -fp FLOATS={EM}/{LIB}fp args {ALIGN} {SEPID?} \ (.e:{HEAD}={PLATFORMDIR}/boot.o) \ - ({RTS}:.ocm.b={PLATFORMDIR}/c-ansi.o) \ + ({RTS}:.ocm.bas={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) \ + (.bas:{TAIL}={PLATFORMDIR}/libbasic.a) \ (.mod:{TAIL}={PLATFORMDIR}/libmodula2.a) \ (.ocm:{TAIL}={PLATFORMDIR}/liboccam.a) \ - (.ocm.b.mod.c.p:{TAIL}={PLATFORMDIR}/libc.a) \ + (.ocm.bas.mod.c.p:{TAIL}={PLATFORMDIR}/libc.a) \ {FLOATS?} \ (.e:{TAIL}={PLATFORMDIR}/libem.a \ {PLATFORMDIR}/libsys.a \ diff --git a/plat/rpi/descr b/plat/rpi/descr index 6daff9606..22682bac1 100644 --- a/plat/rpi/descr +++ b/plat/rpi/descr @@ -52,16 +52,16 @@ name led mapflag -fp FLOATS={EM}/{ILIB}fp args {ALIGN} {SEPID?} \ (.e:{HEAD}={PLATFORMDIR}/boot.o) \ - ({RTS}:.ocm.b={PLATFORMDIR}/c-ansi.o) \ + ({RTS}:.ocm.bas={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) \ + (.bas:{TAIL}={PLATFORMDIR}/libbasic.a) \ (.mod:{TAIL}={PLATFORMDIR}/libmodula2.a) \ (.ocm:{TAIL}={PLATFORMDIR}/liboccam.a) \ - (.ocm.b.mod.c.p:{TAIL}={PLATFORMDIR}/libc.a) \ + (.ocm.bas.mod.c.p:{TAIL}={PLATFORMDIR}/libc.a) \ {FLOATS?} \ (.e:{TAIL}={PLATFORMDIR}/libem.a \ {PLATFORMDIR}/libsys.a \ diff --git a/util/ack/ack.1.X b/util/ack/ack.1.X index 689992ac7..48c41480b 100644 --- a/util/ack/ack.1.X +++ b/util/ack/ack.1.X @@ -50,7 +50,7 @@ but the following are recognized by most machines: Pascal program. .IP .c C module. -.IP .b +.IP .bas Basic program. .IP .ocm Occam program. @@ -354,7 +354,7 @@ input:name:output:description \&.f:f77:.c:Fortran-to-C front end \&.c:cem:.k:C front end [4,5,6] \&.p:pc:.k:Pascal front end [2,3,6] -\&.b:abc:.k:Basic front end [6,8] +\&.b:basic:.k:Basic front end [6,8] \&.ocm:ocm:.k:Occam front end [9] \&.mod:m2:.k:Modula-2 front end [11] \&.e:encode:.k:Compactify EM assembly language [1] From 4485d89b23f0eb93967db22cd1d48af2d6378f12 Mon Sep 17 00:00:00 2001 From: David Given Date: Sun, 27 Nov 2016 20:48:07 +0100 Subject: [PATCH 034/173] Hook the B compiler up to the compiler driver. --- lang/b/compiler/build.lua | 2 +- lib/descr/fe | 10 ++++++++++ plat/cpm/descr | 5 +++-- plat/linux386/descr | 5 +++-- plat/linux68k/descr | 5 +++-- plat/linuxppc/descr | 5 +++-- plat/pc86/descr | 5 +++-- plat/qemuppc/descr | 5 +++-- plat/rpi/descr | 5 +++-- 9 files changed, 32 insertions(+), 15 deletions(-) diff --git a/lang/b/compiler/build.lua b/lang/b/compiler/build.lua index 00afc81ef..82095a683 100644 --- a/lang/b/compiler/build.lua +++ b/lang/b/compiler/build.lua @@ -8,7 +8,7 @@ cprogram { "./*.h", "modules+headers", "modules/src/alloc+lib", - "modules/src/em_code+lib_e", + "modules/src/em_code+lib_k", "modules/src/em_data+lib", "modules/src/em_mes+lib", "modules/src/print+lib", diff --git a/lib/descr/fe b/lib/descr/fe index b40f3ec9d..874e2901c 100644 --- a/lib/descr/fe +++ b/lib/descr/fe @@ -180,6 +180,16 @@ name a68s need .8 callname a68s end +name b + from .b + to .k + program {EM}/lib/ack/em_b + args -i < -o > -w {p} + prep cond + rts .b + need .b + callname abc +end name encode from .e to .k diff --git a/plat/cpm/descr b/plat/cpm/descr index 80dec921c..d178b46c5 100644 --- a/plat/cpm/descr +++ b/plat/cpm/descr @@ -61,16 +61,17 @@ name led mapflag -fp FLOATS={EM}/{ILIB}fp args {ALIGN} {SEPID?} \ (.e:{HEAD}={PLATFORMDIR}/boot.o) \ - ({RTS}:.ocm.bas={PLATFORMDIR}/c-ansi.o) \ + ({RTS}:.ocm.bas.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}/libb.a) \ (.bas:{TAIL}={PLATFORMDIR}/libbasic.a) \ (.mod:{TAIL}={PLATFORMDIR}/libmodula2.a) \ (.ocm:{TAIL}={PLATFORMDIR}/liboccam.a) \ - (.ocm.bas.mod.c.p:{TAIL}={PLATFORMDIR}/libc.a) \ + (.ocm.bas.mod.b.c.p:{TAIL}={PLATFORMDIR}/libc.a) \ {FLOATS?} \ (.e:{TAIL}={PLATFORMDIR}/libem.a \ {PLATFORMDIR}/libsys.a \ diff --git a/plat/linux386/descr b/plat/linux386/descr index 92d3b9f9c..7dbeec738 100644 --- a/plat/linux386/descr +++ b/plat/linux386/descr @@ -57,16 +57,17 @@ name led mapflag -fp FLOATS={EM}/{LIB}fp args {ALIGN} {SEPID?} \ (.e:{HEAD}={PLATFORMDIR}/boot.o) \ - ({RTS}:.ocm.bas={PLATFORMDIR}/c-ansi.o) \ + ({RTS}:.ocm.bas.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}/libb.a) \ (.bas:{TAIL}={PLATFORMDIR}/libbasic.a) \ (.mod:{TAIL}={PLATFORMDIR}/libmodula2.a) \ (.ocm:{TAIL}={PLATFORMDIR}/liboccam.a) \ - (.ocm.bas.mod.c.p:{TAIL}={PLATFORMDIR}/libc.a) \ + (.ocm.bas.mod.b.c.p:{TAIL}={PLATFORMDIR}/libc.a) \ {FLOATS?} \ (.e:{TAIL}={PLATFORMDIR}/libem.a \ {PLATFORMDIR}/libsys.a \ diff --git a/plat/linux68k/descr b/plat/linux68k/descr index 5963d1a44..5fbe16a38 100644 --- a/plat/linux68k/descr +++ b/plat/linux68k/descr @@ -57,16 +57,17 @@ name led mapflag -fp FLOATS={EM}/{LIB}fp args {ALIGN} {SEPID?} \ (.e:{HEAD}={PLATFORMDIR}/boot.o) \ - ({RTS}:.ocm.bas={PLATFORMDIR}/c-ansi.o) \ + ({RTS}:.ocm.bas.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}/libb.a) \ (.bas:{TAIL}={PLATFORMDIR}/libbasic.a) \ (.mod:{TAIL}={PLATFORMDIR}/libmodula2.a) \ (.ocm:{TAIL}={PLATFORMDIR}/liboccam.a) \ - (.ocm.bas.mod.c.p:{TAIL}={PLATFORMDIR}/libc.a) \ + (.ocm.bas.mod.b.c.p:{TAIL}={PLATFORMDIR}/libc.a) \ {FLOATS?} \ (.e:{TAIL}={PLATFORMDIR}/libem.a \ {PLATFORMDIR}/libsys.a \ diff --git a/plat/linuxppc/descr b/plat/linuxppc/descr index f54f4ad3e..51121278d 100644 --- a/plat/linuxppc/descr +++ b/plat/linuxppc/descr @@ -63,16 +63,17 @@ name led mapflag -fp FLOATS={EM}/{LIB}fp args {ALIGN} {SEPID?} \ (.e:{HEAD}={PLATFORMDIR}/boot.o) \ - ({RTS}:.ocm.bas={PLATFORMDIR}/c-ansi.o) \ + ({RTS}:.ocm.bas.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}/libb.a) \ (.bas:{TAIL}={PLATFORMDIR}/libbasic.a) \ (.mod:{TAIL}={PLATFORMDIR}/libmodula2.a) \ (.ocm:{TAIL}={PLATFORMDIR}/liboccam.a) \ - (.ocm.bas.mod.c.p:{TAIL}={PLATFORMDIR}/libc.a) \ + (.ocm.bas.mod.b.c.p:{TAIL}={PLATFORMDIR}/libc.a) \ {FLOATS?} \ (.e:{TAIL}={PLATFORMDIR}/libem.a \ {PLATFORMDIR}/libsys.a \ diff --git a/plat/pc86/descr b/plat/pc86/descr index 3037df99f..578ac292c 100644 --- a/plat/pc86/descr +++ b/plat/pc86/descr @@ -53,16 +53,17 @@ name led mapflag -fp FLOATS={EM}/{ILIB}fp args {ALIGN} {SEPID?} \ (.e:{HEAD}={PLATFORMDIR}/boot.o) \ - ({RTS}:.ocm.bas={PLATFORMDIR}/c-ansi.o) \ + ({RTS}:.ocm.bas.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}/libb.a) \ (.bas:{TAIL}={PLATFORMDIR}/libbasic.a) \ (.mod:{TAIL}={PLATFORMDIR}/libmodula2.a) \ (.ocm:{TAIL}={PLATFORMDIR}/liboccam.a) \ - (.ocm.bas.mod.c.p:{TAIL}={PLATFORMDIR}/libc.a) \ + (.ocm.bas.mod.b.c.p:{TAIL}={PLATFORMDIR}/libc.a) \ {FLOATS?} \ (.e:{TAIL}={PLATFORMDIR}/libem.a \ {PLATFORMDIR}/libsys.a \ diff --git a/plat/qemuppc/descr b/plat/qemuppc/descr index 43b5743b8..2027b613c 100644 --- a/plat/qemuppc/descr +++ b/plat/qemuppc/descr @@ -63,16 +63,17 @@ name led mapflag -fp FLOATS={EM}/{LIB}fp args {ALIGN} {SEPID?} \ (.e:{HEAD}={PLATFORMDIR}/boot.o) \ - ({RTS}:.ocm.bas={PLATFORMDIR}/c-ansi.o) \ + ({RTS}:.ocm.bas.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}/libb.a) \ (.bas:{TAIL}={PLATFORMDIR}/libbasic.a) \ (.mod:{TAIL}={PLATFORMDIR}/libmodula2.a) \ (.ocm:{TAIL}={PLATFORMDIR}/liboccam.a) \ - (.ocm.bas.mod.c.p:{TAIL}={PLATFORMDIR}/libc.a) \ + (.ocm.bas.mod.b.c.p:{TAIL}={PLATFORMDIR}/libc.a) \ {FLOATS?} \ (.e:{TAIL}={PLATFORMDIR}/libem.a \ {PLATFORMDIR}/libsys.a \ diff --git a/plat/rpi/descr b/plat/rpi/descr index 22682bac1..76c3f4707 100644 --- a/plat/rpi/descr +++ b/plat/rpi/descr @@ -52,16 +52,17 @@ name led mapflag -fp FLOATS={EM}/{ILIB}fp args {ALIGN} {SEPID?} \ (.e:{HEAD}={PLATFORMDIR}/boot.o) \ - ({RTS}:.ocm.bas={PLATFORMDIR}/c-ansi.o) \ + ({RTS}:.ocm.bas.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}/libb.a) \ (.bas:{TAIL}={PLATFORMDIR}/libbasic.a) \ (.mod:{TAIL}={PLATFORMDIR}/libmodula2.a) \ (.ocm:{TAIL}={PLATFORMDIR}/liboccam.a) \ - (.ocm.bas.mod.c.p:{TAIL}={PLATFORMDIR}/libc.a) \ + (.ocm.bas.mod.b.c.p:{TAIL}={PLATFORMDIR}/libc.a) \ {FLOATS?} \ (.e:{TAIL}={PLATFORMDIR}/libem.a \ {PLATFORMDIR}/libsys.a \ From b9665c7c99b146bd2b56d05926098c403d7920f3 Mon Sep 17 00:00:00 2001 From: David Given Date: Sun, 27 Nov 2016 21:08:14 +0100 Subject: [PATCH 035/173] Fix some basic showstopping bugs; compilation now works up to failing to find the libb standard library. --- lang/b/compiler/b0.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lang/b/compiler/b0.c b/lang/b/compiler/b0.c index abbeeba32..d0ea69826 100644 --- a/lang/b/compiler/b0.c +++ b/lang/b/compiler/b0.c @@ -97,11 +97,11 @@ main(int argc, char *argv[]) if (string_part) C_insertpart(string_part); - C_exp("bsymb_start"); - C_exp("bsymb_end"); + C_exa_dnam("bsymb_patch_table"); + C_df_dnam("bsymb_patch_table"); if (bsymb_part) C_insertpart(bsymb_part); - C_df_dnam("bsymb_end"); + C_rom_cst(0); C_close(); @@ -735,7 +735,7 @@ pswitch(void) C_con_ilb(swp->swlab); } - C_df_dlb(brklab); + C_df_ilb(brklab); deflab = dl; swp = sswp; From fbd6e8f63db91116fc8b1023a8c24bd584c8612b Mon Sep 17 00:00:00 2001 From: David Given Date: Sun, 27 Nov 2016 21:18:00 +0100 Subject: [PATCH 036/173] Add support for consecutive labels; needed by the B compiler. --- mach/proto/mcg/data.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/mach/proto/mcg/data.c b/mach/proto/mcg/data.c index 13352ed37..ff4ddb5bd 100644 --- a/mach/proto/mcg/data.c +++ b/mach/proto/mcg/data.c @@ -12,14 +12,19 @@ static struct symbol* pending; void data_label(const char* label) { - if (pending) - fatal("two consecutive data labels ('%s' and '%s')", - pending->name, label); + struct symbol* sym = symbol_get(label); + if (sym->is_defined) + fatal("label '%s' defined twice", sym->name); - pending = symbol_get(label); - if (pending->is_defined) - fatal("label '%s' defined twice", pending->name); - pending->is_defined = true; + if (pending) + fprintf(outputfile, "%s = %s\n", + platform_label(label), platform_label(pending->name)); + else + { + pending = sym; + pending = symbol_get(label); + pending->is_defined = true; + } } static const char* section_to_str(int section) From 9f34262f95c3f579d388fd79a00f87dd66c3d674 Mon Sep 17 00:00:00 2001 From: David Given Date: Sun, 27 Nov 2016 22:05:15 +0100 Subject: [PATCH 037/173] Implement enough libb to make 'Hello, world!' work. --- lang/b/lib/b.h | 19 ++++++++++++++ lang/b/lib/build.lua | 27 ++++++++++++++++++++ lang/b/lib/main.c | 59 ++++++++++++++++++++++++++++++++++++++++++++ plat/build.lua | 1 + 4 files changed, 106 insertions(+) create mode 100644 lang/b/lib/b.h create mode 100644 lang/b/lib/build.lua create mode 100644 lang/b/lib/main.c diff --git a/lang/b/lib/b.h b/lang/b/lib/b.h new file mode 100644 index 000000000..123eabc58 --- /dev/null +++ b/lang/b/lib/b.h @@ -0,0 +1,19 @@ +#ifndef B_H +#define B_H + +#include +#include + +#if EM_PSIZE == 2 +#define SHIFT 1 +#elif EM_PSIZE == 4 +#define SHIFT 2 +#elif EM_PSIZE == 8 +#define SHIFT 3 +#else +#error Unsupported EM_PSIZE +#endif + +extern FILE* output_unit; + +#endif diff --git a/lang/b/lib/build.lua b/lang/b/lib/build.lua new file mode 100644 index 000000000..a45ab78a0 --- /dev/null +++ b/lang/b/lib/build.lua @@ -0,0 +1,27 @@ +include("plat/build.lua") + +for _, plat in ipairs(vars.plats) do + acklibrary { + name = "lib_"..plat, + srcs = { + "./*.c", + "./*.e", + }, + hdrs = {}, -- must be empty + deps = { + "./*.h", + "h+emheaders", + "lang/cem/libcc.ansi/headers+headers", + "plat/"..plat.."/include+headers", + }, + vars = { plat = plat } + } + + installable { + name = "pkg_"..plat, + map = { + ["$(PLATIND)/"..plat.."/libb.a"] = "+lib_"..plat, + } + } +end + diff --git a/lang/b/lib/main.c b/lang/b/lib/main.c new file mode 100644 index 000000000..1d18a800e --- /dev/null +++ b/lang/b/lib/main.c @@ -0,0 +1,59 @@ +#include "b.h" + +extern uintptr_t* bsymb_patch_table[]; +extern intptr_t i_main(intptr_t argc, const char* argv[]); + +FILE* output_unit; + +static intptr_t i_char(intptr_t s, intptr_t n) +{ + const char* p = (const char*)(s<>= SHIFT; + } +} + +int main(int argc, const char* argv[]) +{ + patch_addresses(bsymb_patch_table); + patch_addresses(lib_patch_table); + output_unit = stdout; + return i_main(argc, NULL); +} \ No newline at end of file diff --git a/plat/build.lua b/plat/build.lua index 85ba61bc9..a8d1684bb 100644 --- a/plat/build.lua +++ b/plat/build.lua @@ -104,6 +104,7 @@ definerule("build_plat_libs", "lang/cem/libcc.ansi+pkg_"..e.plat, "lang/m2/libm2+pkg_"..e.plat, "lang/pc/libpc+pkg_"..e.plat, + "lang/b/lib+pkg_"..e.plat, ["$(PLATIND)/"..e.plat.."/libem.a"] = "mach/"..e.arch.."/libem+lib_"..e.plat, ["$(PLATIND)/"..e.plat.."/libend.a"] = "mach/"..e.arch.."/libend+lib_"..e.plat, } From 466bc555fe1f9ce2686091367faabba97033c766 Mon Sep 17 00:00:00 2001 From: George Koehler Date: Mon, 28 Nov 2016 14:32:49 -0500 Subject: [PATCH 038/173] Add getdirentries() and stat() for Mac OS X. Also add fstat() and lstat(). I don't #define the constants for st_mode or d_type, but I provide enough to get the block size of a file and to list the names in a directory. Some fields of struct stat get truncated, see XXX in plat/osx/include/sys/stat.h. In struct dirent, the inode field might be d_ino or d_fileno. I picked d_ino because Apple's sys/dirent.h uses d_ino (but Apple's manual pages use d_fileno). --- plat/osx/include/build.lua | 2 ++ plat/osx/include/sys/dirent.h | 17 +++++++++++ plat/osx/include/sys/stat.h | 49 ++++++++++++++++++++++++++++++ plat/osx/include/sys/types.h | 12 ++++++-- plat/osx/include/unistd.h | 7 +++-- plat/osx386/libsys/build.lua | 4 +++ plat/osx386/libsys/fstat.s | 7 +++++ plat/osx386/libsys/getdirentries.s | 7 +++++ plat/osx386/libsys/lstat.s | 7 +++++ plat/osx386/libsys/stat.s | 7 +++++ plat/osxppc/libsys/build.lua | 4 +++ plat/osxppc/libsys/fstat.s | 9 ++++++ plat/osxppc/libsys/getdirentries.s | 11 +++++++ plat/osxppc/libsys/lstat.s | 9 ++++++ plat/osxppc/libsys/stat.s | 9 ++++++ 15 files changed, 157 insertions(+), 4 deletions(-) create mode 100644 plat/osx/include/sys/dirent.h create mode 100644 plat/osx/include/sys/stat.h create mode 100644 plat/osx386/libsys/fstat.s create mode 100644 plat/osx386/libsys/getdirentries.s create mode 100644 plat/osx386/libsys/lstat.s create mode 100644 plat/osx386/libsys/stat.s create mode 100644 plat/osxppc/libsys/fstat.s create mode 100644 plat/osxppc/libsys/getdirentries.s create mode 100644 plat/osxppc/libsys/lstat.s create mode 100644 plat/osxppc/libsys/stat.s diff --git a/plat/osx/include/build.lua b/plat/osx/include/build.lua index 7eb73f3aa..ff7c87a4d 100644 --- a/plat/osx/include/build.lua +++ b/plat/osx/include/build.lua @@ -9,7 +9,9 @@ local function addheader(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") diff --git a/plat/osx/include/sys/dirent.h b/plat/osx/include/sys/dirent.h new file mode 100644 index 000000000..073c84588 --- /dev/null +++ b/plat/osx/include/sys/dirent.h @@ -0,0 +1,17 @@ +#ifndef _SYS_DIRENT_H +#define _SYS_DIRENT_H + +#include + +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 diff --git a/plat/osx/include/sys/stat.h b/plat/osx/include/sys/stat.h new file mode 100644 index 000000000..6cb24902f --- /dev/null +++ b/plat/osx/include/sys/stat.h @@ -0,0 +1,49 @@ +#ifndef _SYS_STAT_H +#define _SYS_STAT_H + +#include +#include /* 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 diff --git a/plat/osx/include/sys/types.h b/plat/osx/include/sys/types.h index a9fb63277..b4561b7b3 100644 --- a/plat/osx/include/sys/types.h +++ b/plat/osx/include/sys/types.h @@ -3,7 +3,15 @@ #include /* for off_t, ptrdiff_t, size_t */ -typedef int pid_t; -typedef ptrdiff_t ssize_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 diff --git a/plat/osx/include/unistd.h b/plat/osx/include/unistd.h index 24eaf4e54..320db4a86 100644 --- a/plat/osx/include/unistd.h +++ b/plat/osx/include/unistd.h @@ -22,6 +22,11 @@ int ioctl(int, unsigned long, ...); 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; @@ -48,8 +53,6 @@ int gettimeofday(struct timeval *, struct timezone *); #define O_TRUNC 0x0400 #define O_EXCL 0x0800 -typedef int mode_t; - int creat(const char *, mode_t); int open(const char *, int, ...); diff --git a/plat/osx386/libsys/build.lua b/plat/osx386/libsys/build.lua index a5356ee6c..b3a04c8e7 100644 --- a/plat/osx386/libsys/build.lua +++ b/plat/osx386/libsys/build.lua @@ -3,17 +3,21 @@ acklibrary { 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", diff --git a/plat/osx386/libsys/fstat.s b/plat/osx386/libsys/fstat.s new file mode 100644 index 000000000..1b49ae0b7 --- /dev/null +++ b/plat/osx386/libsys/fstat.s @@ -0,0 +1,7 @@ +.sect .text +.define _fstat +_fstat: + mov eax, 189 + int 0x80 + jb .set_errno + ret diff --git a/plat/osx386/libsys/getdirentries.s b/plat/osx386/libsys/getdirentries.s new file mode 100644 index 000000000..9c59c627c --- /dev/null +++ b/plat/osx386/libsys/getdirentries.s @@ -0,0 +1,7 @@ +.sect .text +.define _getdirentries +_getdirentries: + mov eax, 196 + int 0x80 + jb .set_errno + ret diff --git a/plat/osx386/libsys/lstat.s b/plat/osx386/libsys/lstat.s new file mode 100644 index 000000000..a492cc3cb --- /dev/null +++ b/plat/osx386/libsys/lstat.s @@ -0,0 +1,7 @@ +.sect .text +.define _lstat +_lstat: + mov eax, 190 + int 0x80 + jb .set_errno + ret diff --git a/plat/osx386/libsys/stat.s b/plat/osx386/libsys/stat.s new file mode 100644 index 000000000..858d84db0 --- /dev/null +++ b/plat/osx386/libsys/stat.s @@ -0,0 +1,7 @@ +.sect .text +.define _stat +_stat: + mov eax, 188 + int 0x80 + jb .set_errno + ret diff --git a/plat/osxppc/libsys/build.lua b/plat/osxppc/libsys/build.lua index a595ed0fa..2accf6eb7 100644 --- a/plat/osxppc/libsys/build.lua +++ b/plat/osxppc/libsys/build.lua @@ -3,17 +3,21 @@ acklibrary { 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", diff --git a/plat/osxppc/libsys/fstat.s b/plat/osxppc/libsys/fstat.s new file mode 100644 index 000000000..d641cbd91 --- /dev/null +++ b/plat/osxppc/libsys/fstat.s @@ -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 diff --git a/plat/osxppc/libsys/getdirentries.s b/plat/osxppc/libsys/getdirentries.s new file mode 100644 index 000000000..d038c5977 --- /dev/null +++ b/plat/osxppc/libsys/getdirentries.s @@ -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 diff --git a/plat/osxppc/libsys/lstat.s b/plat/osxppc/libsys/lstat.s new file mode 100644 index 000000000..24d7c44ab --- /dev/null +++ b/plat/osxppc/libsys/lstat.s @@ -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 diff --git a/plat/osxppc/libsys/stat.s b/plat/osxppc/libsys/stat.s new file mode 100644 index 000000000..ab8422cda --- /dev/null +++ b/plat/osxppc/libsys/stat.s @@ -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 From bbcc08a6b6188eb80bda12bbb1d2a8ad9d03d0a2 Mon Sep 17 00:00:00 2001 From: David Given Date: Mon, 28 Nov 2016 21:38:46 +0100 Subject: [PATCH 039/173] Fix putchar() return value. --- lang/b/lib/main.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lang/b/lib/main.c b/lang/b/lib/main.c index 1d18a800e..9b868bada 100644 --- a/lang/b/lib/main.c +++ b/lang/b/lib/main.c @@ -22,9 +22,10 @@ static intptr_t i_getchar(void) return fgetc(output_unit); } -static void i_putchar(intptr_t c) +static intptr_t i_putchar(intptr_t c) { fputc(c, output_unit); + return c; } uintptr_t b_char = (uintptr_t)i_char; From 0c2b6f523cf39338570f4e7752c48d7b46ddcb0b Mon Sep 17 00:00:00 2001 From: George Koehler Date: Mon, 28 Nov 2016 20:58:51 -0500 Subject: [PATCH 040/173] Enable top and make other tweaks in plat/osxppc/descr David Given made top for PowerPC. Copy the asopt phase (running top) from linuxppc to osxppc. Remove CC_ALIGN=-Vr to become compatible with Apple's gcc. Apple uses left adjustment for bitfields; the first bitfield is on the left side (the big end), not the right side. Remove unused variables C_LIB and OLD_C_LIB; the file libc-ansi.a doesn't exist. Change MACHOPT_F from -m10 to -m3. This means to use no more than 3 adds and shifts to optimize a multiply by a constant. I pick -m3 because -m4 can use too many instructions. At -m4, the compiler rewrites n * 14 as s = n << 1 (s << 3) + (0 - s) This means (n * 16 - n * 2), but even at ack -O6, the compiler doesn't rewrite (a + (0 - b)) as (a - b). The compiler emits 5 instructions: 2 of rlinmw for 2 left shifts, then addi to load 0 in a register, subf to subtract from that 0, then add. These 5 instructions cost 5 cycles on the MPC7450, using the cycle counts from mach/powerpc/ncg/table. At -m3, (n * 14) becomes 2 instructions: addi to load 14 in a register and mullw to multiply. This also costs 5 cycles (because mullw costs 4 cycles), but uses less space. --- plat/osxppc/descr | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/plat/osxppc/descr b/plat/osxppc/descr index 130d2bd25..2a6d47871 100644 --- a/plat/osxppc/descr +++ b/plat/osxppc/descr @@ -19,12 +19,7 @@ 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 C_LIB={PLATFORMDIR}/libc-ansi.a -# bitfields reversed for compatibility with (g)cc. -# XXX this is from linux386, might be wrong for osxppc -var CC_ALIGN=-Vr -var OLD_C_LIB={C_LIB} -var MACHOPT_F=-m10 +var 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 @@ -41,6 +36,15 @@ name be stdout need .e end +name asopt + from .s + to .so + program {EM}/lib/ack/linuxppc/top + args + optimizer + stdin + stdout +end name as from .s.so to .o From 960584c0f3e8d0e9909b5b98a057dc0faa3f22ff Mon Sep 17 00:00:00 2001 From: David Given Date: Tue, 29 Nov 2016 20:59:43 +0100 Subject: [PATCH 041/173] Replace the hacky and broken pipeline in testdriver.sh with a custom-written tool in C; much more robust and easier to understand, as well as avoiding the dependency on timeout (which isn't Posix). --- tests/plat/build.lua | 5 +- tests/plat/testdriver.sh | 65 ++++++++++++------------ util/build/build.lua | 7 +++ util/build/testrunner.c | 104 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 146 insertions(+), 35 deletions(-) create mode 100644 util/build/build.lua create mode 100644 util/build/testrunner.c diff --git a/tests/plat/build.lua b/tests/plat/build.lua index 3873ed9a5..be65668fd 100644 --- a/tests/plat/build.lua +++ b/tests/plat/build.lua @@ -45,10 +45,11 @@ definerule("plat_testsuite", outleaves = { "stamp" }, ins = { bin, - "tests/plat/testdriver.sh" + "tests/plat/testdriver.sh", + "util/build+testrunner" }, commands = { - "%{ins[2]} "..e.method.." %{ins[1]} 5", + "%{ins[2]} "..e.method.." %{ins[1]} 5 %{ins[3]}", "touch %{outs}" } } diff --git a/tests/plat/testdriver.sh b/tests/plat/testdriver.sh index 272c6b2b7..6af14da0f 100755 --- a/tests/plat/testdriver.sh +++ b/tests/plat/testdriver.sh @@ -2,50 +2,49 @@ method=$1 img=$2 timeout=$3 +timeoutprog=$4 -pipe=/tmp/$$.testdriver.pipe -mknod $pipe p -trap "rm -f $pipe" EXIT +set -e result=/tmp/$$.testdriver.result trap "rm -f $result" EXIT -pidfile=/tmp/$$.testdriver.pid -trap "rm -f $pidfile" EXIT +errcho() { + >&2 echo "$*" +} -case $method in - qemu-system-*) - if ! command -v $method >/dev/null 2>&1 ; then - echo "Warning: $method not installed, skipping test" - exit 0 - fi +get_test_output() { + case $method in + qemu-system-*) + if ! command -v $method >/dev/null 2>&1 ; then + errcho "Warning: $method not installed, skipping test" + exit 0 + fi - case $method in - qemu-system-i386) img="-drive file=$img,if=floppy,format=raw" ;; - qemu-system-ppc) img="-kernel $img" ;; - esac + case $method in + qemu-system-i386) img="-drive file=$img,if=floppy,format=raw" ;; + qemu-system-ppc) img="-kernel $img" ;; + esac - ( $method -nographic $img 2>&1 & echo $! > $pidfile ) \ - | tee $result \ - | ( timeout $timeout grep -l -q @@FINISHED ; echo ) \ - | ( read dummy && kill $(cat $pidfile) ) - - ;; + $timeoutprog -t $timeout -- $method -nographic $img > $result + ;; - qemu-*) - if ! command -v $method >/dev/null 2>&1 ; then - echo "Warning: $method not installed, skipping test" - exit 0 - fi + qemu-*) + if ! command -v $method >/dev/null 2>&1 ; then + errcho "Warning: $method not installed, skipping test" + exit 0 + fi - $method $img > $result - ;; + $method $img > $result + ;; - *) - echo "Error: $method not known by testdriver" - exit 1 - ;; -esac + *) + errcho "Error: $method not known by testdriver" + exit 1 + ;; + esac +} +get_test_output > $result ( grep -q @@FAIL $result || ! grep -q @@FINISHED $result ) && cat $result && exit 1 exit 0 diff --git a/util/build/build.lua b/util/build/build.lua new file mode 100644 index 000000000..76623fe91 --- /dev/null +++ b/util/build/build.lua @@ -0,0 +1,7 @@ +cprogram { + name = "testrunner", + srcs = { "./testrunner.c" }, + deps = { + "modules/src/data+lib" + } +} diff --git a/util/build/testrunner.c b/util/build/testrunner.c new file mode 100644 index 000000000..16d526d9a --- /dev/null +++ b/util/build/testrunner.c @@ -0,0 +1,104 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include "diagnostics.h" + +static bool timed_out = false; +static bool child_exited = false; +static char** command = NULL; +static int timeout = 0; +static jmp_buf exit_jmp; + +static void parse_arguments(int argc, char* const argv[]) +{ + program_name = argv[0]; + for (;;) + { + int c = getopt(argc, argv, "t:"); + if (c == -1) + break; + + switch (c) + { + case 't': + timeout = atoi(optarg); + break; + + default: + fatal("syntax: testrunner -- \n"); + } + } + + command = &argv[optind]; + if (!command[0]) + fatal("you must supply a command"); + if (timeout <= 0) + fatal("timeout missing or invalid"); +} + +static void sigalrm_cb(int sigraised) +{ + timed_out = true; + longjmp(exit_jmp, 1); +} + +int main(int argc, char* const argv[]) +{ + const int READ = 0; + const int WRITE = 1; + + int fds[2]; + int pid; + FILE* childin; + int wstatus; + char buffer[4096]; + + parse_arguments(argc, argv); + + if (setjmp(exit_jmp) == 0) + { + /* First time through. */ + + signal(SIGALRM, sigalrm_cb); + alarm(timeout); + + pipe(fds); + pid = fork(); + if (pid == 0) + { + /* Child */ + close(fds[READ]); + close(0); + dup2(fds[WRITE], 1); + dup2(fds[WRITE], 2); + execvp(command[0], command); + _exit(1); + } + + childin = fdopen(fds[READ], "r"); + while (!timed_out) + { + if (!fgets(buffer, sizeof(buffer), childin)) + break; + fputs(buffer, stdout); + + if (strcmp(buffer, "@@FINISHED\n") == 0) + break; + if (strcmp(buffer, "@@FINISHED\r\n") == 0) + break; + } + } + + /* Reached via longjmp, EOF, or seeing a @@FINISHED. */ + + kill(pid, SIGKILL); + waitpid(pid, &wstatus, 0); + if (timed_out) + exit(1); + exit(WEXITSTATUS(wstatus)); +} From 543bbcb9ab02a9195271c524733f24621ee37bf3 Mon Sep 17 00:00:00 2001 From: George Koehler Date: Wed, 30 Nov 2016 14:33:40 -0500 Subject: [PATCH 042/173] Declare raise() for Mac OS X. This prevents the warning, "implicit declaration of function raise", in programs that call raise(). I forgot to declare it because the function raise() is in libc but the declaration goes in libsys. --- plat/osx/include/unistd.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/plat/osx/include/unistd.h b/plat/osx/include/unistd.h index 320db4a86..bafa2a6c4 100644 --- a/plat/osx/include/unistd.h +++ b/plat/osx/include/unistd.h @@ -120,6 +120,8 @@ 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); From 8ef7c31089631537b5d74c74bbefe5560211029f Mon Sep 17 00:00:00 2001 From: George Koehler Date: Wed, 30 Nov 2016 15:29:19 -0500 Subject: [PATCH 043/173] Write a powerpc.descr for ego and use it with osxppc. No change to linuxppc and qemuppc. They continue to run ego without any descr file. I copied m68020.descr to powerpc.descr and changed some numbers. My numbers are guesses; I know little about PowerPC cycle counts, and almost nothing about ego. This powerpc.descr causes most of the example programs to shrink in size (without descr -> with descr): 65429 -> 57237 hilo_b.osxppc -8192 36516 -> 32420 hilo_c.osxppc -4096 55782 -> 51686 hilo_mod.osxppc -4096 20096 -> 20096 hilo_p.osxppc 0 8813 -> 8813 mandelbrot_c.osxppc 0 93355 -> 89259 paranoia_c.osxppc -4096 92751 -> 84559 startrek_c.osxppc -8192 (Each file has 2 Mach segments, then a symbol table. Each segment takes a multiple of 4096 bytes. When the code shrinks, we lose a multiple of 4096 bytes.) I used "ack -mosxppc -O6 -c.so" to examine the assembly code for hilo.mod and mandelbrot.c, both without and with descr. This reveals optimizations made only with descr, from 2 ego phases: SP (stack pollution) and RA (register allocation). In hilo.mod, SP deletes some instructions that remove items from the stack. These items get removed when the function returns. In both hilo.mod and mandelbrot.c, RA moves some values into local variables, so ncg can make them into register variables. This shrinks code size, probably because register variables get preserved across function calls. More values stay in registers, and ncg emits shorter code. I believe that the ego descr file uses (time,space) tuples but the ncg table uses (space,time) tuples. This is confusing. Perhaps I am wrong, and some or all tuples are backwards. My time values are the cycle counts in latency from the MPC7450 Reference Manual (but not including complications like "store serialization"). In powerpc.descr, I give the cost for saving and restoring registers as if I was using chains of stw and lwz instructions. Actually ncg uses single stmw and lmw instructions with at least 2 instructions. The (time,space) for stmw and lmw would be much less than the (time,space) for chains of stw and lwz. But this ignores the pipeline of the MPC7450. The chains of stw and lwz may run faster than stmw and lmw in the pipeline, because the throughput may be better than the latency. By using the wrong values for (time,space), I'm trying to tell ego that stmw and lmw are not better than chains of stw and lwz. --- plat/osxppc/descr | 2 +- util/ego/descr/build.lua | 1 + util/ego/descr/powerpc.descr | 118 +++++++++++++++++++++++++++++++++++ 3 files changed, 120 insertions(+), 1 deletion(-) create mode 100644 util/ego/descr/powerpc.descr diff --git a/plat/osxppc/descr b/plat/osxppc/descr index 2a6d47871..1aa615965 100644 --- a/plat/osxppc/descr +++ b/plat/osxppc/descr @@ -20,7 +20,7 @@ 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 +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. diff --git a/util/ego/descr/build.lua b/util/ego/descr/build.lua index 034ffa3ce..e9a008cc5 100644 --- a/util/ego/descr/build.lua +++ b/util/ego/descr/build.lua @@ -22,6 +22,7 @@ end build_descr("i386") build_descr("i86") build_descr("m68020") +build_descr("powerpc") installable { name = "pkg", diff --git a/util/ego/descr/powerpc.descr b/util/ego/descr/powerpc.descr new file mode 100644 index 000000000..5138cc44b --- /dev/null +++ b/util/ego/descr/powerpc.descr @@ -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 From b7de58e34ebb6150974fca24c6e07e4b46d21b0d Mon Sep 17 00:00:00 2001 From: David Given Date: Thu, 1 Dec 2016 22:05:22 +0100 Subject: [PATCH 044/173] Fix signal unsafety in testdriver.c. --- util/build/testrunner.c | 72 ++++++++++++++++++++++------------------- 1 file changed, 38 insertions(+), 34 deletions(-) diff --git a/util/build/testrunner.c b/util/build/testrunner.c index 16d526d9a..e666ec4ac 100644 --- a/util/build/testrunner.c +++ b/util/build/testrunner.c @@ -10,9 +10,9 @@ static bool timed_out = false; static bool child_exited = false; -static char** command = NULL; +static char* const* command = NULL; static int timeout = 0; -static jmp_buf exit_jmp; +static int pid = 0; static void parse_arguments(int argc, char* const argv[]) { @@ -44,7 +44,8 @@ static void parse_arguments(int argc, char* const argv[]) static void sigalrm_cb(int sigraised) { timed_out = true; - longjmp(exit_jmp, 1); + if (pid) + kill(pid, SIGKILL); } int main(int argc, char* const argv[]) @@ -53,48 +54,51 @@ int main(int argc, char* const argv[]) const int WRITE = 1; int fds[2]; - int pid; FILE* childin; int wstatus; char buffer[4096]; parse_arguments(argc, argv); - if (setjmp(exit_jmp) == 0) + pipe(fds); + pid = fork(); + if (pid == 0) { - /* First time through. */ - + /* Child */ + close(fds[READ]); + close(0); + dup2(fds[WRITE], 1); + dup2(fds[WRITE], 2); + execvp(command[0], command); + _exit(1); + } + else + { + /* Parent */ + close(fds[WRITE]); signal(SIGALRM, sigalrm_cb); alarm(timeout); - - pipe(fds); - pid = fork(); - if (pid == 0) - { - /* Child */ - close(fds[READ]); - close(0); - dup2(fds[WRITE], 1); - dup2(fds[WRITE], 2); - execvp(command[0], command); - _exit(1); - } - - childin = fdopen(fds[READ], "r"); - while (!timed_out) - { - if (!fgets(buffer, sizeof(buffer), childin)) - break; - fputs(buffer, stdout); - - if (strcmp(buffer, "@@FINISHED\n") == 0) - break; - if (strcmp(buffer, "@@FINISHED\r\n") == 0) - break; - } } - /* Reached via longjmp, EOF, or seeing a @@FINISHED. */ + childin = fdopen(fds[READ], "r"); + if (!childin) + fatal("cannot open pipe"); + + while (!timed_out) + { + if (!fgets(buffer, sizeof(buffer), childin)) + break; + fputs(buffer, stdout); + + if (strcmp(buffer, "@@FINISHED\n") == 0) + break; + if (strcmp(buffer, "@@FINISHED\r\n") == 0) + break; + } + + /* Reached via EOF or seeing a @@FINISHED. */ + + alarm(0); kill(pid, SIGKILL); waitpid(pid, &wstatus, 0); From 8c99e2b7ad7647197f9f0f96e82f8d777dc0edcc Mon Sep 17 00:00:00 2001 From: David Given Date: Thu, 1 Dec 2016 23:03:30 +0100 Subject: [PATCH 045/173] Run all tests, even the ones which fail, and emit a test summary right at the end of the build (and fail then). --- Makefile | 2 +- build.lua | 16 +++++++++++++--- first/testsummary.sh | 11 +++++++++++ tests/plat/_dummy.c | 1 - tests/plat/build.lua | 11 ++++------- tests/plat/lib/test.c | 7 +++++-- tests/plat/testdriver.sh | 6 +++--- util/build/build.lua | 1 + util/build/testrunner.c | 13 +++++++++++-- 9 files changed, 49 insertions(+), 19 deletions(-) create mode 100755 first/testsummary.sh diff --git a/Makefile b/Makefile index febd87aff..4399f0c28 100644 --- a/Makefile +++ b/Makefile @@ -63,7 +63,7 @@ PLATDEP = $(INSDIR)/lib/ack .NOTPARALLEL: -MAKECMDGOALS ?= +ack +MAKECMDGOALS ?= +ack +tests BUILD_FILES = $(shell find * -name '*.lua') ifneq ($(shell which ninja),) diff --git a/build.lua b/build.lua index 607a83a3b..98ee9ff9b 100644 --- a/build.lua +++ b/build.lua @@ -46,8 +46,18 @@ installable { "examples+pkg", plat_packages }, - deps = { - test_packages - } } +normalrule { + name = "tests", + ins = { + "first/testsummary.sh", + test_packages + }, + outleaves = { + "stamp" + }, + commands = { + "%{ins}" + } +} diff --git a/first/testsummary.sh b/first/testsummary.sh new file mode 100755 index 000000000..4ad46d52d --- /dev/null +++ b/first/testsummary.sh @@ -0,0 +1,11 @@ +#!/bin/sh +failed=$(find "$@" ! -size 0) +echo "" +echo "$(echo $failed | wc -w) failed tests" +echo "" +for a in $failed; do + echo "**** $a" + cat $a + echo "" +done +exec test "$failed" == "" diff --git a/tests/plat/_dummy.c b/tests/plat/_dummy.c index a4693300f..48104b5aa 100644 --- a/tests/plat/_dummy.c +++ b/tests/plat/_dummy.c @@ -6,4 +6,3 @@ void _m_a_i_n(void) ASSERT(0 == 0); finished(); } - diff --git a/tests/plat/build.lua b/tests/plat/build.lua index be65668fd..f5885a190 100644 --- a/tests/plat/build.lua +++ b/tests/plat/build.lua @@ -42,24 +42,21 @@ definerule("plat_testsuite", tests[#tests+1] = normalrule { name = fs, - outleaves = { "stamp" }, + outleaves = { e.plat.."-"..fs.."-testlog.txt" }, ins = { bin, "tests/plat/testdriver.sh", "util/build+testrunner" }, commands = { - "%{ins[2]} "..e.method.." %{ins[1]} 5 %{ins[3]}", - "touch %{outs}" + "(%{ins[2]} "..e.method.." %{ins[1]} 5 %{ins[3]} || echo FAILED) 2>&1 > %{outs}", } } end - return normalrule { + return bundle { name = e.name, - outleaves = { "stamp" }, - ins = tests, - commands = { "touch %{outs}" } + srcs = tests, } end ) \ No newline at end of file diff --git a/tests/plat/lib/test.c b/tests/plat/lib/test.c index df00e1089..426f9944a 100644 --- a/tests/plat/lib/test.c +++ b/tests/plat/lib/test.c @@ -26,7 +26,10 @@ void writehex(uint32_t code) void fail(uint32_t code) { - write(1, "@@FAIL 0x", 10); + static const char fail_msg[] = "@@FAIL 0x"; + static const char nl_msg[] = "\n"; + + write(1, fail_msg, sizeof(fail_msg)-1); writehex(code); - write(1, "\n", 1); + write(1, nl_msg, sizeof(nl_msg)-1); } diff --git a/tests/plat/testdriver.sh b/tests/plat/testdriver.sh index 6af14da0f..6c421f798 100755 --- a/tests/plat/testdriver.sh +++ b/tests/plat/testdriver.sh @@ -26,7 +26,7 @@ get_test_output() { qemu-system-ppc) img="-kernel $img" ;; esac - $timeoutprog -t $timeout -- $method -nographic $img > $result + $timeoutprog -t $timeout -- $method -nographic $img 2>&1 > $result ;; qemu-*) @@ -35,7 +35,7 @@ get_test_output() { exit 0 fi - $method $img > $result + $method $img 2>&1 > $result ;; *) @@ -45,6 +45,6 @@ get_test_output() { esac } -get_test_output > $result +get_test_output ( grep -q @@FAIL $result || ! grep -q @@FINISHED $result ) && cat $result && exit 1 exit 0 diff --git a/util/build/build.lua b/util/build/build.lua index 76623fe91..41bd0b6ad 100644 --- a/util/build/build.lua +++ b/util/build/build.lua @@ -5,3 +5,4 @@ cprogram { "modules/src/data+lib" } } + diff --git a/util/build/testrunner.c b/util/build/testrunner.c index e666ec4ac..fb2add562 100644 --- a/util/build/testrunner.c +++ b/util/build/testrunner.c @@ -6,6 +6,7 @@ #include #include #include +#include #include "diagnostics.h" static bool timed_out = false; @@ -57,6 +58,7 @@ int main(int argc, char* const argv[]) FILE* childin; int wstatus; char buffer[4096]; + char* p; parse_arguments(argc, argv); @@ -90,9 +92,13 @@ int main(int argc, char* const argv[]) break; fputs(buffer, stdout); - if (strcmp(buffer, "@@FINISHED\n") == 0) + p = buffer; + while (isspace(*p)) + p++; + + if (strcmp(p, "@@FINISHED\n") == 0) break; - if (strcmp(buffer, "@@FINISHED\r\n") == 0) + if (strcmp(p, "@@FINISHED\r\n") == 0) break; } @@ -103,6 +109,9 @@ int main(int argc, char* const argv[]) kill(pid, SIGKILL); waitpid(pid, &wstatus, 0); if (timed_out) + { + fprintf(stderr, "@@TIMEDOUT\n"); exit(1); + } exit(WEXITSTATUS(wstatus)); } From 9e6581b0ff4505ff62cf4aafa536ddf3d63f490c Mon Sep 17 00:00:00 2001 From: David Given Date: Thu, 1 Dec 2016 23:14:29 +0100 Subject: [PATCH 046/173] Mark skipped tests in the logs (so we can get stats on them later). --- tests/plat/testdriver.sh | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/plat/testdriver.sh b/tests/plat/testdriver.sh index 6c421f798..a0fed5686 100755 --- a/tests/plat/testdriver.sh +++ b/tests/plat/testdriver.sh @@ -18,6 +18,7 @@ get_test_output() { qemu-system-*) if ! command -v $method >/dev/null 2>&1 ; then errcho "Warning: $method not installed, skipping test" + echo "@@SKIPPED" > $result exit 0 fi @@ -32,6 +33,7 @@ get_test_output() { qemu-*) if ! command -v $method >/dev/null 2>&1 ; then errcho "Warning: $method not installed, skipping test" + echo "@@SKIPPED" > $result exit 0 fi @@ -46,5 +48,5 @@ get_test_output() { } get_test_output -( grep -q @@FAIL $result || ! grep -q @@FINISHED $result ) && cat $result && exit 1 +( grep -q '@@FAIL\|@@SKIPPED' $result || ! grep -q @@FINISHED $result ) && cat $result && exit 1 exit 0 From 467709ff38ac08be7b5bf127fabd32da26a95855 Mon Sep 17 00:00:00 2001 From: David Given Date: Fri, 2 Dec 2016 00:00:31 +0100 Subject: [PATCH 047/173] Report skipped, failed and timed out tests. --- first/testsummary.sh | 18 ++++++++++++++---- tests/plat/testdriver.sh | 4 ++-- 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/first/testsummary.sh b/first/testsummary.sh index 4ad46d52d..be0842afa 100755 --- a/first/testsummary.sh +++ b/first/testsummary.sh @@ -1,11 +1,21 @@ #!/bin/sh -failed=$(find "$@" ! -size 0) +notsucceeding=$(find "$@" ! -size 0) echo "" -echo "$(echo $failed | wc -w) failed tests" +echo "$(echo $notsucceeding | wc -w) tests failed to pass" + +skipped=$(grep -l @@SKIPPED $notsucceeding) +echo "$(echo $skipped | wc -w) were skipped (see build log for details)" + +timedout=$(grep -l @@TIMEDOUT $notsucceeding) +echo "$(echo $timedout | wc -w) timed out" + +failed=$(grep -l @@FAIL $notsucceeding) +echo "$(echo $failed | wc -w) failed" + echo "" -for a in $failed; do +for a in $failed $timedout; do echo "**** $a" cat $a echo "" done -exec test "$failed" == "" +exec test "$failed" == "" -o "$timedout" == "" diff --git a/tests/plat/testdriver.sh b/tests/plat/testdriver.sh index a0fed5686..5e8e5b899 100755 --- a/tests/plat/testdriver.sh +++ b/tests/plat/testdriver.sh @@ -18,7 +18,7 @@ get_test_output() { qemu-system-*) if ! command -v $method >/dev/null 2>&1 ; then errcho "Warning: $method not installed, skipping test" - echo "@@SKIPPED" > $result + echo "@@SKIPPED" exit 0 fi @@ -33,7 +33,7 @@ get_test_output() { qemu-*) if ! command -v $method >/dev/null 2>&1 ; then errcho "Warning: $method not installed, skipping test" - echo "@@SKIPPED" > $result + echo "@@SKIPPED" exit 0 fi From 3aa048728983a33c4cc46871c093d6276af87d8d Mon Sep 17 00:00:00 2001 From: David Given Date: Fri, 2 Dec 2016 00:10:33 +0100 Subject: [PATCH 048/173] UI tweaks to the test summary. --- first/testsummary.sh | 36 ++++++++++++++++++++++++------------ 1 file changed, 24 insertions(+), 12 deletions(-) diff --git a/first/testsummary.sh b/first/testsummary.sh index be0842afa..9f1002b39 100755 --- a/first/testsummary.sh +++ b/first/testsummary.sh @@ -1,21 +1,33 @@ #!/bin/sh -notsucceeding=$(find "$@" ! -size 0) echo "" -echo "$(echo $notsucceeding | wc -w) tests failed to pass" -skipped=$(grep -l @@SKIPPED $notsucceeding) -echo "$(echo $skipped | wc -w) were skipped (see build log for details)" +succeeding="$(find "$@" -size 0)" +notsucceeding="$(find "$@" ! -size 0)" +skipped="$(grep -l @@SKIPPED $notsucceeding)" +timedout="$(grep -l @@TIMEDOUT $notsucceeding)" +failed="$(grep -l @@FAIL $notsucceeding)" -timedout=$(grep -l @@TIMEDOUT $notsucceeding) -echo "$(echo $timedout | wc -w) timed out" - -failed=$(grep -l @@FAIL $notsucceeding) -echo "$(echo $failed | wc -w) failed" - -echo "" for a in $failed $timedout; do echo "**** $a" cat $a echo "" done -exec test "$failed" == "" -o "$timedout" == "" + +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 + echo "Test status: SAD FACE (tests are failing)" + exit 1 +fi +if [ "$succeeding" = "" ]; then + echo "Test status: PUZZLED FACE (all tests were skipped)" + exit 1 +fi +echo "Test status: HAPPY FACE (all tests are passing)" +exit 0 + From 213def96664ba7bb1e0a3e72b8a9439f9038daed Mon Sep 17 00:00:00 2001 From: David Given Date: Fri, 2 Dec 2016 00:14:40 +0100 Subject: [PATCH 049/173] Don't fail to build if all tests are skipped. --- first/testsummary.sh | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/first/testsummary.sh b/first/testsummary.sh index 9f1002b39..4923b0787 100755 --- a/first/testsummary.sh +++ b/first/testsummary.sh @@ -26,7 +26,11 @@ if [ "$failed" != "" -o "$timedout" != "" ]; then fi if [ "$succeeding" = "" ]; then echo "Test status: PUZZLED FACE (all tests were skipped)" - exit 1 + exit 0 +fi +if [ "$skipped" != "" ]; then + echo "Test status: MILDLY PLEASED FACE (some tests were skipped, but the rest pass)" + echo 0 fi echo "Test status: HAPPY FACE (all tests are passing)" exit 0 From 353e2d284270a54ae01d44819cb461e77e023e0d Mon Sep 17 00:00:00 2001 From: David Given Date: Fri, 2 Dec 2016 00:18:44 +0100 Subject: [PATCH 050/173] Typo fix. --- first/testsummary.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/first/testsummary.sh b/first/testsummary.sh index 4923b0787..6301cb977 100755 --- a/first/testsummary.sh +++ b/first/testsummary.sh @@ -30,7 +30,7 @@ if [ "$succeeding" = "" ]; then fi if [ "$skipped" != "" ]; then echo "Test status: MILDLY PLEASED FACE (some tests were skipped, but the rest pass)" - echo 0 + exit 0 fi echo "Test status: HAPPY FACE (all tests are passing)" exit 0 From e06b1fa05e0d587a1ab20256f8b8b753266135c9 Mon Sep 17 00:00:00 2001 From: George Koehler Date: Fri, 2 Dec 2016 18:04:06 -0500 Subject: [PATCH 051/173] Write a manual page for cvmach(6). This manual is in the new mdoc(7) format. All existing ack manuals use the old man(7) format. This might be a problem if someone can't display mdoc(7) files. The build system doesn't install the cvmach(6) manual; that might happen later. The current build system installs manuals in two different places, and doesn't install some manuals, so I don't know what to do. --- plat/osx/cvmach/cvmach.6 | 96 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 96 insertions(+) create mode 100644 plat/osx/cvmach/cvmach.6 diff --git a/plat/osx/cvmach/cvmach.6 b/plat/osx/cvmach/cvmach.6 new file mode 100644 index 000000000..30d4aa2d7 --- /dev/null +++ b/plat/osx/cvmach/cvmach.6 @@ -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. From 25e159c930d2b95371be23dfe7365545338ec51a Mon Sep 17 00:00:00 2001 From: George Koehler Date: Sat, 3 Dec 2016 17:07:51 -0500 Subject: [PATCH 052/173] Remove bad overflow check from plat/osx/libsys/brk.c If I want to check for overflow, then I should check it before I do base + incr, not after. Now that I have no check, I am passing the overflowed base + incr to brk1(), where it will probably fail the nbreak < segment check. --- plat/osx/libsys/brk.c | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/plat/osx/libsys/brk.c b/plat/osx/libsys/brk.c index a732cac1c..9b58ca1d8 100644 --- a/plat/osx/libsys/brk.c +++ b/plat/osx/libsys/brk.c @@ -76,20 +76,11 @@ int brk(void *addr) void *sbrk(int incr) { - char *base, *nbreak; + char *base; brk_init(); base = cbreak; - nbreak = base + incr; - - /* Did base + incr overflow? */ - if ((incr < 0 && nbreak > base) || - (incr > 0 && nbreak < base)) { - errno = ENOMEM; - return (void*)-1; - } - - if (brk1(nbreak) < 0) + if (brk1(base + incr) < 0) return (void*)-1; return base; } From 355cc06fff7bbf2590c39b5f1802f49cb490c02f Mon Sep 17 00:00:00 2001 From: George Koehler Date: Sat, 3 Dec 2016 17:17:44 -0500 Subject: [PATCH 053/173] Write README files for osx386 and osxppc. --- plat/osx386/README | 25 +++++++++++ plat/osxppc/README | 110 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 135 insertions(+) create mode 100644 plat/osx386/README create mode 100644 plat/osxppc/README diff --git a/plat/osx386/README b/plat/osx386/README new file mode 100644 index 000000000..8c34134ff --- /dev/null +++ b/plat/osx386/README @@ -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 +2016-12-03 diff --git a/plat/osxppc/README b/plat/osxppc/README new file mode 100644 index 000000000..dd9a4d49c --- /dev/null +++ b/plat/osxppc/README @@ -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 +2016-12-03 From 969e98b82de338ea54c7490dee5171415f54148c Mon Sep 17 00:00:00 2001 From: George Koehler Date: Sat, 3 Dec 2016 17:52:24 -0500 Subject: [PATCH 054/173] Create Mach-o files with mode 0777 to allow executing them. Until now, I was always doing chmod +x before running my files on the Mac. Now files get created +x. There's no change when overwriting an existing file. I needed to gmake clean my build to remove the example programs without +x, so cvmach can create them with +x. --- plat/osx/cvmach/cvmach.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/plat/osx/cvmach/cvmach.c b/plat/osx/cvmach/cvmach.c index 0b5b6bf80..5f8315ddd 100644 --- a/plat/osx/cvmach/cvmach.c +++ b/plat/osx/cvmach/cvmach.c @@ -12,6 +12,7 @@ * libobject is pinched from the Xenix i386 cv (mach/i386/cv/cv.c). */ +#include #include #include #include @@ -470,7 +471,7 @@ int main(int argc, char *argv[]) { uint32_t end, pad[3], sz, sz_load_cmds; - int cpu_subtype, mflag = 0; + int cpu_subtype, fd, mflag = 0; /* General housecleaning and setup. */ output = stdout; @@ -520,7 +521,11 @@ main(int argc, char *argv[]) break; case 3: /* Both input and output files specified. */ - output = fopen(argv[2], "w"); + /* 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]; From c5aff6fc2e6f452d5b313b95c77836cebeeff83c Mon Sep 17 00:00:00 2001 From: David Given Date: Mon, 5 Dec 2016 20:33:26 +0100 Subject: [PATCH 055/173] Change dependency from simplerule{} with a dependency but no outputs to an installable; otherwise, the dependency would be built, but the result wouldn't get added to the header path and so wouldn't be seen. --- plat/osx386/include/build.lua | 7 ++----- plat/osxppc/include/build.lua | 9 +++------ 2 files changed, 5 insertions(+), 11 deletions(-) diff --git a/plat/osx386/include/build.lua b/plat/osx386/include/build.lua index 164e2b44a..2f80c1257 100644 --- a/plat/osx386/include/build.lua +++ b/plat/osx386/include/build.lua @@ -1,7 +1,4 @@ -simplerule { +installable { name = "headers", - deps = { "plat/osx/include+headers" }, - ins = {}, - outs = {}, - commands = {}, + map = { "plat/osx/include+pkg" } } diff --git a/plat/osxppc/include/build.lua b/plat/osxppc/include/build.lua index 164e2b44a..2058eb2cc 100644 --- a/plat/osxppc/include/build.lua +++ b/plat/osxppc/include/build.lua @@ -1,7 +1,4 @@ -simplerule { +installable { name = "headers", - deps = { "plat/osx/include+headers" }, - ins = {}, - outs = {}, - commands = {}, -} + map = { "plat/osx/include+pkg" } +} \ No newline at end of file From c569ca15d8d6db8eebe275d7fb376a203557e0ce Mon Sep 17 00:00:00 2001 From: David Given Date: Mon, 5 Dec 2016 21:05:24 +0100 Subject: [PATCH 056/173] Clean up how the language libraries refer to plat headers; they should be using the +pkg forms of the rules and getting the headers via the paths in descr, rather than depending on the +headers version. --- lang/basic/lib/build.lua | 4 ++-- lang/cem/libcc.ansi/build.lua | 4 ++-- lang/m2/libm2/build.lua | 4 ++-- lang/pc/libpc/build.lua | 4 ++-- plat/osx386/include/build.lua | 2 +- plat/osx386/libsys/build.lua | 2 +- plat/osxppc/include/build.lua | 2 +- plat/osxppc/libsys/build.lua | 2 +- 8 files changed, 12 insertions(+), 12 deletions(-) diff --git a/lang/basic/lib/build.lua b/lang/basic/lib/build.lua index 71710a542..cff3b57ca 100644 --- a/lang/basic/lib/build.lua +++ b/lang/basic/lib/build.lua @@ -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 } } diff --git a/lang/cem/libcc.ansi/build.lua b/lang/cem/libcc.ansi/build.lua index 601a50de4..20591f803 100644 --- a/lang/cem/libcc.ansi/build.lua +++ b/lang/cem/libcc.ansi/build.lua @@ -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", diff --git a/lang/m2/libm2/build.lua b/lang/m2/libm2/build.lua index d0861b966..a1a9e5c0a 100644 --- a/lang/m2/libm2/build.lua +++ b/lang/m2/libm2/build.lua @@ -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 } diff --git a/lang/pc/libpc/build.lua b/lang/pc/libpc/build.lua index 7845991e5..215f0c745 100644 --- a/lang/pc/libpc/build.lua +++ b/lang/pc/libpc/build.lua @@ -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 } diff --git a/plat/osx386/include/build.lua b/plat/osx386/include/build.lua index 2f80c1257..c2a1050c2 100644 --- a/plat/osx386/include/build.lua +++ b/plat/osx386/include/build.lua @@ -1,4 +1,4 @@ installable { - name = "headers", + name = "pkg", map = { "plat/osx/include+pkg" } } diff --git a/plat/osx386/libsys/build.lua b/plat/osx386/libsys/build.lua index b3a04c8e7..23e491f7a 100644 --- a/plat/osx386/libsys/build.lua +++ b/plat/osx386/libsys/build.lua @@ -27,7 +27,7 @@ acklibrary { }, deps = { "lang/cem/libcc.ansi/headers+headers", - "plat/osx386/include+headers", + "plat/osx386/include+pkg", }, vars = { plat = "osx386" diff --git a/plat/osxppc/include/build.lua b/plat/osxppc/include/build.lua index 2058eb2cc..0fe204ece 100644 --- a/plat/osxppc/include/build.lua +++ b/plat/osxppc/include/build.lua @@ -1,4 +1,4 @@ installable { - name = "headers", + name = "pkg", map = { "plat/osx/include+pkg" } } \ No newline at end of file diff --git a/plat/osxppc/libsys/build.lua b/plat/osxppc/libsys/build.lua index 2accf6eb7..072730b7a 100644 --- a/plat/osxppc/libsys/build.lua +++ b/plat/osxppc/libsys/build.lua @@ -27,7 +27,7 @@ acklibrary { }, deps = { "lang/cem/libcc.ansi/headers+headers", - "plat/osxppc/include+headers", + "plat/osxppc/include+pkg", }, vars = { plat = "osxppc" From 3fe285f8f8fcff0fd32de4c971400503d72158e0 Mon Sep 17 00:00:00 2001 From: David Given Date: Mon, 5 Dec 2016 21:06:38 +0100 Subject: [PATCH 057/173] Fix some shell issues that would occasionally cause hangs if no tests failed. --- first/testsummary.sh | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/first/testsummary.sh b/first/testsummary.sh index 6301cb977..6c2d3e39a 100755 --- a/first/testsummary.sh +++ b/first/testsummary.sh @@ -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 From 6cbea83f7f969910b97e283297a83979634da190 Mon Sep 17 00:00:00 2001 From: George Koehler Date: Mon, 5 Dec 2016 20:13:29 -0500 Subject: [PATCH 058/173] Don't share as, ncg, top between Linux and Mac OS X. Telling osx386 and osxppc to build and run their own tools, not to reuse the tools from linux386 and linuxppc. This wastes time to build identical tools, but it removes some bogus dependencies. OS X tools had wrongly depended on Linux descr files and aelflod; now they don't. Discussion in https://github.com/davidgiven/ack/pull/23 --- plat/osx386/build-tools.lua | 15 ++++++++++++++- plat/osx386/descr | 4 ++-- plat/osxppc/build-tools.lua | 21 ++++++++++++++++++++- plat/osxppc/descr | 6 +++--- 4 files changed, 39 insertions(+), 7 deletions(-) diff --git a/plat/osx386/build-tools.lua b/plat/osx386/build-tools.lua index 097cb94d3..a1a9a8e2b 100644 --- a/plat/osx386/build-tools.lua +++ b/plat/osx386/build-tools.lua @@ -1,8 +1,21 @@ +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/linux386+tools", "plat/osx/cvmach+pkg", "util/opt+pkg", } diff --git a/plat/osx386/descr b/plat/osx386/descr index 9e4cf2577..a6f021878 100644 --- a/plat/osx386/descr +++ b/plat/osx386/descr @@ -34,7 +34,7 @@ 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/linux386/ncg + program {EM}/lib/ack/{PLATFORM}/ncg mapflag -gdb GF=-gdb args {GF?} < stdout @@ -43,7 +43,7 @@ end name as from .s.so to .o - program {EM}/lib/ack/linux386/as + program {EM}/lib/ack/{PLATFORM}/as args - -o > < prep cond end diff --git a/plat/osxppc/build-tools.lua b/plat/osxppc/build-tools.lua index d19d25e19..eddeea85a 100644 --- a/plat/osxppc/build-tools.lua +++ b/plat/osxppc/build-tools.lua @@ -1,8 +1,27 @@ +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/linuxppc+tools", "plat/osx/cvmach+pkg", "util/opt+pkg", } diff --git a/plat/osxppc/descr b/plat/osxppc/descr index 1aa615965..f659ff0ef 100644 --- a/plat/osxppc/descr +++ b/plat/osxppc/descr @@ -30,7 +30,7 @@ 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/linuxppc/ncg + program {EM}/lib/ack/{PLATFORM}/ncg mapflag -gdb GF=-gdb args {GF?} < stdout @@ -39,7 +39,7 @@ end name asopt from .s to .so - program {EM}/lib/ack/linuxppc/top + program {EM}/lib/ack/{PLATFORM}/top args optimizer stdin @@ -48,7 +48,7 @@ end name as from .s.so to .o - program {EM}/lib/ack/linuxppc/as + program {EM}/lib/ack/{PLATFORM}/as args - -o > < prep cond end From 55e24e1f24b932592ba3b24c8e97c3410c1a9d8b Mon Sep 17 00:00:00 2001 From: David Given Date: Tue, 6 Dec 2016 21:45:20 +0100 Subject: [PATCH 059/173] inn was assuming that bitfields were arrays of bytes, when actually they're arrays of words (which makes the LSB move on big-endian systems). --- mach/powerpc/libem/inn.s | 6 +++--- tests/plat/inn_e.e | 27 ++++++++++----------------- 2 files changed, 13 insertions(+), 20 deletions(-) diff --git a/mach/powerpc/libem/inn.s b/mach/powerpc/libem/inn.s index f5ae4c63e..9770ac094 100644 --- a/mach/powerpc/libem/inn.s +++ b/mach/powerpc/libem/inn.s @@ -13,10 +13,10 @@ lwz r4, 4(sp) /* r4 = bit number */ addi r5, sp, 8 /* r5 = base address of bit set */ - srawi r6, r4, 3 /* r6 = byte address into set */ - andi. r7, r4, 7 /* r7 = bit within byte */ + rlwinm r6, r4, 29, 3, 29 /* r6 = byte index of word in set */ + andi. r7, r4, 31 /* r7 = bit within word */ - lbzx r8, r5, r6 /* r8 = individual byte from set */ + lwzx r8, r5, r6 /* r8 = individual byte from set */ sraw r8, r8, r7 rlwinm r8, r8, 0, 31, 31 diff --git a/tests/plat/inn_e.e b/tests/plat/inn_e.e index 7d27abf42..a5aee02f5 100644 --- a/tests/plat/inn_e.e +++ b/tests/plat/inn_e.e @@ -7,10 +7,10 @@ /* Test non-existent bit */ .1 - rom 0I1, 0I1, 0I1, 0I1 + rom 0I4 loe .1 loc 1 /* bit number */ - inn EM_WSIZE + inn 4 zeq *1 loc __LINE__ @@ -21,9 +21,12 @@ /* Test existent bit */ .2 - rom 2I1, 0I1, 0I1, 0I1 + rom 16384 +.21 + rom 14 /* to defeat constant folding */ + loe .2 - loc 1 /* bit number */ + loe .21 /* bit number */ inn EM_WSIZE zne *2 @@ -35,10 +38,9 @@ /* Test non-existent high bit */ .3 - rom 0I1, 0I1, 0I1, 0I1 - rom 0I1, 0I1, 0I1, 0I1 + rom 0, 0 .31 - rom (EM_WSIZE*8)+1 /* to defeat constant folding */ + rom 8 /* to defeat constant folding */ lae .3 loi EM_WSIZE*2 @@ -54,16 +56,7 @@ /* Test existent high bit */ .4 -#if EM_WSIZE == 2 - rom 0I1, 0I1 - rom 2I1, 0I1 -#elif EM_WSIZE == 4 - rom 0I1, 0I1, 0I1, 0I1 - rom 2I1, 0I1, 0I1, 0I1 -#else - #error Unknown word size -#endif - + rom 0, 2 .41 rom (EM_WSIZE*8)+1 /* to defeat constant folding */ From cc3d72e884848fce02ad44277924d9eecce14ff0 Mon Sep 17 00:00:00 2001 From: David Given Date: Tue, 6 Dec 2016 22:05:14 +0100 Subject: [PATCH 060/173] Fix redirection so stray stderr output from qemu doesn't cause mysterious test failures. --- tests/plat/testdriver.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/plat/testdriver.sh b/tests/plat/testdriver.sh index 5e8e5b899..384c83b47 100755 --- a/tests/plat/testdriver.sh +++ b/tests/plat/testdriver.sh @@ -27,7 +27,7 @@ get_test_output() { qemu-system-ppc) img="-kernel $img" ;; esac - $timeoutprog -t $timeout -- $method -nographic $img 2>&1 > $result + $timeoutprog -t $timeout -- $method -nographic $img > $result 2>&1 ;; qemu-*) @@ -37,7 +37,7 @@ get_test_output() { exit 0 fi - $method $img 2>&1 > $result + $method $img > $result 2>&1 ;; *) From 67e7d226ad15464ed9133810defa474cc021627e Mon Sep 17 00:00:00 2001 From: David Given Date: Tue, 6 Dec 2016 22:06:17 +0100 Subject: [PATCH 061/173] Disable qemuppc tests; turns out qemu-system-ppc won't load more than the first 4kB of a kernel... --- build.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.lua b/build.lua index 6364e5f75..91415d689 100644 --- a/build.lua +++ b/build.lua @@ -18,7 +18,7 @@ vars.plats = { vars.plats_with_tests = { "linux386", "linuxppc", - "qemuppc", + -- "qemuppc", FIXME: disable until we figure out why qemu won't run binaries bigger than 4kB "pc86", } From 1039c0a7473ff5f6bf03ace435ca6ecc46edb060 Mon Sep 17 00:00:00 2001 From: David Given Date: Tue, 6 Dec 2016 22:07:22 +0100 Subject: [PATCH 062/173] Add a test for #22. --- tests/plat/{_dummy.c => _dummy_e.c} | 0 tests/plat/bugs/bug-22-inn_mod.mod | 26 ++++++++++++++++++++++++++ tests/plat/build.lua | 9 +++++---- 3 files changed, 31 insertions(+), 4 deletions(-) rename tests/plat/{_dummy.c => _dummy_e.c} (100%) create mode 100644 tests/plat/bugs/bug-22-inn_mod.mod diff --git a/tests/plat/_dummy.c b/tests/plat/_dummy_e.c similarity index 100% rename from tests/plat/_dummy.c rename to tests/plat/_dummy_e.c diff --git a/tests/plat/bugs/bug-22-inn_mod.mod b/tests/plat/bugs/bug-22-inn_mod.mod new file mode 100644 index 000000000..8f3a2d00a --- /dev/null +++ b/tests/plat/bugs/bug-22-inn_mod.mod @@ -0,0 +1,26 @@ +MODULE test; +FROM InOut IMPORT WriteLn, WriteString; + +TYPE charset = SET OF CHAR; + +PROCEDURE Space(c: CHAR): BOOLEAN; +BEGIN + RETURN c IN charset{' ', 11C, 12C, 15C} +END Space; + +BEGIN + IF Space('a') THEN + WriteString("@@FAIL 1"); + WriteLn; + END; + IF NOT Space(' ') THEN + WriteString("@@FAIL 2"); + WriteLn; + END; + IF NOT Space(12C) THEN + WriteString("@@FAIL 3"); + WriteLn; + END; + WriteString("@@FINISHED"); + WriteLn; +END test. \ No newline at end of file diff --git a/tests/plat/build.lua b/tests/plat/build.lua index f5885a190..d8362b3a0 100644 --- a/tests/plat/build.lua +++ b/tests/plat/build.lua @@ -11,7 +11,8 @@ definerule("plat_testsuite", local testfiles = filenamesof( "tests/plat/*.c", "tests/plat/*.e", - "tests/plat/*.p" + "tests/plat/*.p", + "tests/plat/bugs/*.mod" ) acklibrary { @@ -23,8 +24,8 @@ definerule("plat_testsuite", local tests = {} for _, f in ipairs(testfiles) do - local fs = replace(basename(f), "%..$", "") - local _, _, lang = fs:find("_(.)$") + local fs = replace(basename(f), "%.[^.]+$", "") + local _, _, lang = fs:find("_([^_]+)$") if not lang then lang = "e" end @@ -49,7 +50,7 @@ definerule("plat_testsuite", "util/build+testrunner" }, commands = { - "(%{ins[2]} "..e.method.." %{ins[1]} 5 %{ins[3]} || echo FAILED) 2>&1 > %{outs}", + "(%{ins[2]} "..e.method.." %{ins[1]} 5 %{ins[3]} || echo FAILED) > %{outs}", } } end From b8c921ca70c17a51b74e39d11974e130c32ed409 Mon Sep 17 00:00:00 2001 From: George Koehler Date: Wed, 7 Dec 2016 17:28:00 -0500 Subject: [PATCH 063/173] Allow mfspr, mtspr with a register number. PowerPC has a few hundred special-purpose registers. The assembler had only accepted the names "xer", "lr", "ctr". Most programs use only those three SPRs. If I add more names, they would almost never get used, and they might conflict with labels. I want to use "mfspr r3, 0x3f0" and "mtspr 0x3f0, r3" in plat/qemu/boot.s to access register hid0 from supervisor mode. --- mach/powerpc/as/mach2.c | 2 +- mach/powerpc/as/mach4.c | 16 +++++++++++++--- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/mach/powerpc/as/mach2.c b/mach/powerpc/as/mach2.c index 96d6690df..480c5faa3 100644 --- a/mach/powerpc/as/mach2.c +++ b/mach/powerpc/as/mach2.c @@ -88,4 +88,4 @@ %type c %type e16 u8 u7 u6 u5 u4 u2 u1 -%type nb ds bda bdl lia lil +%type nb ds bda bdl lia lil spr_num diff --git a/mach/powerpc/as/mach4.c b/mach/powerpc/as/mach4.c index 3f79ca86c..e1fb3fdf0 100644 --- a/mach/powerpc/as/mach4.c +++ b/mach/powerpc/as/mach4.c @@ -34,7 +34,7 @@ operation | OP_RT_RA_RB_C c GPR ',' GPR ',' GPR { emit4($1 | $2 | ($3<<21) | ($5<<16) | ($7<<11)); } | OP_RT_RA_SI GPR ',' GPR ',' e16 { emit4($1 | ($2<<21) | ($4<<16) | $6); } | OP_RT_RA_SI_addic c GPR ',' GPR ',' e16 { emit4($1 | ($2<<26) | ($3<<21) | ($5<<16) | $7); } - | OP_RT_SPR GPR ',' SPR { emit4($1 | ($2<<21) | ($4<<11)); } + | OP_RT_SPR GPR ',' spr_num { emit4($1 | ($2<<21) | ($4<<11)); } | OP_RS_FXM u7 ',' GPR { emit4($1 | ($4<<21) | ($2<<12)); } | OP_RS_RA_C c GPR ',' GPR { emit4($1 | $2 | ($5<<21) | ($3<<16)); } | OP_RS_RA_D GPR ',' e16 '(' GPR ')' { emit4($1 | ($2<<21) | ($6<<16) | $4); } @@ -53,7 +53,7 @@ operation | OP_RS_RA_SH_ME6_SH_C c GPR ',' GPR ',' u6 ',' u6 { emit4($1 | $2 | ($5<<21) | ($3<<16) | (($7&0x1F)<<11) | ($9<<6) | (($7&0x20)>>4)); } | OP_RS_RA_SH5_C c GPR ',' GPR ',' u5 { emit4($1 | $2 | ($5<<21) | ($3<<16) | ($7<<11)); } | OP_RS_RA_SH6_C c GPR ',' GPR ',' u6 { emit4($1 | $2 | ($5<<21) | ($3<<16) | (($7&0x1F)<<11) | (($7&0x20)>>4)); } - | OP_RS_SPR SPR ',' GPR { emit4($1 | ($4<<21) | ($2<<11)); } + | OP_RS_SPR spr_num ',' GPR { emit4($1 | ($4<<21) | ($2<<11)); } | OP_TO_RA_RB u5 ',' GPR ',' GPR { emit4($1 | ($2<<21) | ($4<<16) | ($6<<11)); } | OP_TO_RA_SI u5 ',' GPR ',' e16 { emit4($1 | ($2<<21) | ($4<<16) | $6); } | OP_LEV u7 { emit4($1 | ($2<<5)); } @@ -237,4 +237,14 @@ lia $$ = target & 0x03FFFFFD; } ; - + +spr_num + : SPR { $$ = $1; } + | absexp + { + if (($1 < 0) || ($1 > 0x3ff)) + serror("spr number out of range"); + /* mfspr, mtspr swap the low and high 5 bits */ + $$ = ($1 >> 5) | (($1 & 0x1f) << 5); + } + ; From d94ea4c508269b6c9ba4f3f4abb25c615acddd60 Mon Sep 17 00:00:00 2001 From: George Koehler Date: Wed, 7 Dec 2016 18:11:12 -0500 Subject: [PATCH 064/173] Teach qemuppc to halt the cpu on _exit(). Without this, qemu-system-ppc spins the host cpu until I close its window. I assume the default G3 emulation. The emulator yields the host cpu if I set certain flags in hid0 then msr. The hid0 flag can be any of DOZE, NAP, SLEEP, so I just set all 3. I encode mfmsr and mtmsr with .data4, because our assembler doesn't know instructions for supervisor mode. Also move some common symbols from .rom to .bss. Our assembler puts common symbols in any section. Also clean up the file. Delete a comment about linuxppc that is wrong here. Delete redundant .extern because .define is the same. --- plat/qemuppc/boot.s | 47 +++++++++++++++++++++++---------------------- 1 file changed, 24 insertions(+), 23 deletions(-) diff --git a/plat/qemuppc/boot.s b/plat/qemuppc/boot.s index 2dd9a4c5c..1100f3883 100644 --- a/plat/qemuppc/boot.s +++ b/plat/qemuppc/boot.s @@ -13,22 +13,14 @@ .sect .text begtext: - ! This code is placed at the beginning of the ELF executable and is the - ! first thing that runs. + ! This code is the first thing that runs. The booloader + ! passes the Open Firmware pointer in r5. ! - ! On entry, the stack looks like this: + ! We keep the bootloader's stack. The ACK expects: ! - ! sp+... NULL - ! sp+8+(4*argc) env (X quads) - ! sp+4+(4*argc) NULL - ! sp+4 argv (argc quads) + ! sp+8 environment pointer + ! sp+4 argv as a pointer ! sp argc - ! - ! The ACK actually expects: - ! - ! sp+8 argc - ! sp+4 ptr to argv - ! sp ptr to env li32 r3, __openfirmware_ptr stw r5, 0(r3) @@ -47,15 +39,23 @@ begtext: ! falls through .define __exit -.extern __exit .define EXIT -.extern EXIT __exit: EXIT: - b EXIT + ! Halt the CPU. This code halts the default G3 emulation of + ! qemu-system-ppc. It's wrong for some other CPU models. +#define hid0 0x3f0 +#define mfmsr(r) [[31<<26]|[[r]<<21]|0x0a6] +#define mtmsr(r) [[31<<26]|[[r]<<21]|0x124] + mfspr r3, hid0 + oris r3, r3, 0x00e0 ! set DOZE, NAP, SLEEP + mtspr hid0, r3 ! in hid0 + .data4 mfmsr(3) + oris r3, r3, 0x0004 ! set POW + .data4 mtmsr(3) ! in msr0 + b EXIT ! If we failed to halt, then spin. .define _openfirmware_call -.extern _openfirmware_call _openfirmware_call: lwz r3, 0(sp) li32 r4, __openfirmware_ptr @@ -66,15 +66,10 @@ _openfirmware_call: ! Define symbols at the beginning of our various segments, so that we can find ! them. (Except .text, which has already been done.) -.sect .data; begdata: .sect .rom; begrom: +.sect .data; begdata: .sect .bss; begbss: -! Some magic data. All EM systems need these. - -.define _errno -.comm _errno, 4 ! Posix errno storage - ! The argv and env arrays. .sect .rom @@ -82,6 +77,12 @@ argv: .data4 exename, 0 envp: .data4 0 exename: .asciz 'qemuppc.img' +! Some magic data. All EM systems need these. + +.sect .bss +.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 From df86e3b84f38ad8b6882ee6139a3e0926c4f7f71 Mon Sep 17 00:00:00 2001 From: George Koehler Date: Fri, 9 Dec 2016 16:04:21 -0500 Subject: [PATCH 065/173] Fix typo: msr0 should be msr. --- plat/qemuppc/boot.s | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plat/qemuppc/boot.s b/plat/qemuppc/boot.s index 1100f3883..ac3227dc9 100644 --- a/plat/qemuppc/boot.s +++ b/plat/qemuppc/boot.s @@ -52,7 +52,7 @@ EXIT: mtspr hid0, r3 ! in hid0 .data4 mfmsr(3) oris r3, r3, 0x0004 ! set POW - .data4 mtmsr(3) ! in msr0 + .data4 mtmsr(3) ! in msr b EXIT ! If we failed to halt, then spin. .define _openfirmware_call From 244e554f2f592094bed0a5eea11229e33465c79b Mon Sep 17 00:00:00 2001 From: George Koehler Date: Fri, 9 Dec 2016 16:36:42 -0500 Subject: [PATCH 066/173] Remove trailing whitespace in mach/powerpc/ncg/table --- mach/powerpc/ncg/table | 366 ++++++++++++++++++++--------------------- 1 file changed, 183 insertions(+), 183 deletions(-) diff --git a/mach/powerpc/ncg/table b/mach/powerpc/ncg/table index 77fdaedf1..1d2c5516e 100644 --- a/mach/powerpc/ncg/table +++ b/mach/powerpc/ncg/table @@ -48,12 +48,12 @@ PROPERTIES FSREG /* any allocatable single-precision FPR */ SPR /* any SPR */ CR /* any CR */ - + GPR0 GPRSP GPRFP GPR3 GPR4 GPR5 GPR6 GPR7 GPR8 GPR9 GPR10 GPR11 GPR12 GPR13 GPR14 GPR15 GPR16 GPR17 GPR18 GPR19 GPR20 GPR21 GPR22 GPR23 GPR24 GPR25 GPR26 GPR27 GPR28 GPR29 GPR30 GPR31 - + CR0 CR1 FPR0 FPR1 FPR2 FPR3 FPR4 FPR5 FPR6 FPR7 @@ -64,7 +64,7 @@ PROPERTIES REGISTERS /* Reverse order to encourage ncg to allocate them from r31 down */ - + R31("r31") : GPR, REG, GPR31 regvar. R30("r30") : GPR, REG, GPR30 regvar. R29("r29") : GPR, REG, GPR29 regvar. @@ -195,17 +195,17 @@ TOKENS SUM_RIS = { GPR reg; INT offhi; } 4. SUM_RC = { GPR reg; INT off; } 4. SUM_RR = { GPR reg1; GPR reg2; } 4. - + TRISTATE_RC_S = { GPR reg; INT val; } 4. TRISTATE_RC_U = { GPR reg; INT val; } 4. TRISTATE_RR_S = { GPR reg1; GPR reg2; } 4. TRISTATE_RR_U = { GPR reg1; GPR reg2; } 4. - + TRISTATE_FF = { FPR reg1; FPR reg2; } 4. - + SEX_B = { GPR reg; } 4. SEX_H = { GPR reg; } 4. - + IND_RC_B = { GPR reg; INT off; } 4. IND_RR_B = { GPR reg1; GPR reg2; } 4. IND_RC_H = { GPR reg; INT off; } 4. @@ -216,9 +216,9 @@ TOKENS IND_RR_W = { GPR reg1; GPR reg2; } 4. IND_RC_D = { GPR reg; INT off; } 8. IND_RR_D = { GPR reg1; GPR reg2; } 8. - + NOT_R = { GPR reg; } 4. - + AND_RR = { GPR reg1; GPR reg2; } 4. OR_RR = { GPR reg1; GPR reg2; } 4. OR_RIS = { GPR reg; INT valhi; } 4. @@ -241,12 +241,12 @@ SETS CONST_8000 + CONST_8001_FFFF + CONST_HZ + CONST_HL. SUM_ALL = SUM_RC + SUM_RR. - + TRISTATE_ALL = TRISTATE_RC_S + TRISTATE_RC_U + TRISTATE_RR_S + TRISTATE_RR_U + TRISTATE_FF. - + SEX_ALL = SEX_B + SEX_H. - + LOGICAL_ALL = NOT_R + AND_RR + OR_RR + OR_RC + XOR_RR + XOR_RC. @@ -371,7 +371,7 @@ INSTRUCTIONS comment "!" LABEL:ro cost(0, 0). - + MOVES from GPR to GPR @@ -381,12 +381,12 @@ MOVES /* GPRE exists solely to allow us to use regvar() (which can only be used in an expression) as a register constant. */ - + from GPR to GPRE gen COMMENT("move GPR->GPRE") or %2.reg, %1, %1 - + /* Constants */ from CONST_ALL smalls(%val) to GPR @@ -406,19 +406,19 @@ MOVES gen COMMENT("move LABEL->GPR") li32 %2, {LABEL, %1.adr} - + /* Sign extension */ from SEX_B to GPR gen COMMENT("move SEX_B->GPR") extsb %2, %1.reg - + from SEX_H to GPR gen COMMENT("move SEX_H->GPR") extsh %2, %1.reg - + /* Register + something */ from SUM_RIS to GPR @@ -575,38 +575,38 @@ MOVES from TRISTATE_RR_S to CR0 gen cmp %2, {CONST, 0}, %1.reg1, %1.reg2 - + from TRISTATE_RR_U to CR0 gen cmpl %2, {CONST, 0}, %1.reg1, %1.reg2 - + from TRISTATE_RC_S to CR0 gen COMMENT("move TRISTATE_RC_S->CR0 large") move {CONST, %1.val}, RSCRATCH cmp %2, {CONST, 0}, %1.reg, RSCRATCH - + from TRISTATE_RC_U smallu(%val) to CR0 gen COMMENT("move TRISTATE_RC_U->CR0 small") cmpli %2, {CONST, 0}, %1.reg, {CONST, %1.val} - + from TRISTATE_RC_U to CR0 gen COMMENT("move TRISTATE_RC_U->CR0") move {CONST, %1.val}, RSCRATCH cmpl %2, {CONST, 0}, %1.reg, RSCRATCH - + from TRISTATE_FF to CR0 gen COMMENT("move TRISTATE_FF->CR0") fcmpo %2, %1.reg1, %1.reg2 - + from GPR to CR0 gen COMMENT("move GPR->CR0") orX RSCRATCH, %1, %1 /* alas, can't call test */ - + from TRISTATE_RR_S + TRISTATE_RC_S + TRISTATE_FF to GPR gen COMMENT("move TRISTATE_R*_S->GPR") @@ -671,9 +671,9 @@ MOVES gen move %1, %2.reg - + TESTS - + to test GPR gen orX RSCRATCH, %1, %1 @@ -709,36 +709,36 @@ STACKINGRULES COMMENT("stack SEX_B") extsb RSCRATCH, %1.reg stwu RSCRATCH, {GPRINDIRECT, SP, 0-4} - + from SEX_H to STACK gen COMMENT("stack SEX_H") extsh RSCRATCH, %1.reg stwu RSCRATCH, {GPRINDIRECT, SP, 0-4} - + from SUM_ALL + TRISTATE_ALL + LOGICAL_ALL to STACK gen COMMENT("stack SUM_ALL + TRISTATE_ALL + LOGICAL_ALL") move %1, RSCRATCH stwu RSCRATCH, {GPRINDIRECT, SP, 0-4} - + from IND_ALL_BHW to STACK gen COMMENT("stack IND_ALL_BHW") move %1, RSCRATCH stwu RSCRATCH, {GPRINDIRECT, SP, 0-4} - + from IND_ALL_D to STACK gen COMMENT("stack IND_ALL_D") move %1, FSCRATCH stfdu FSCRATCH, {GPRINDIRECT, SP, 0-8} - + from FREG to STACK gen COMMENT("stack FPR") stfdu %1, {GPRINDIRECT, SP, 0-8} - + from FSREG to STACK gen COMMENT("stack FSREG") @@ -761,14 +761,14 @@ COERCIONS COMMENT("coerce CONST_ALL->REG") move %1, %a yields %a - + from LABEL uses REG gen COMMENT("coerce LABEL->REG") move %1, %a yields %a - + from STACK uses REG gen @@ -792,32 +792,32 @@ COERCIONS COMMENT("coerce SEX_B->REG") extsb %a, %1.reg yields %a - + from SEX_H uses REG gen COMMENT("coerce SEX_H->REG") extsh %a, %1.reg yields %a - + from SUM_ALL + TRISTATE_ALL + LOGICAL_ALL uses REG gen move %1, %a yields %a - + from FSREG uses FSREG gen fmr %a, %1 yields %a - + from FREG uses FREG gen fmr %a, %1 yields %a - + from STACK uses FREG gen @@ -884,17 +884,17 @@ PATTERNS yields %1 %1 with FSREG yields %1 %1 - + pat dup $1==INT64 /* Duplicate double-word on top of stack */ with REG REG yields %2 %1 %2 %1 with FREG yields %1 %1 - + pat exg $1==INT32 /* Exchange top two words on stack */ with REG REG yields %1 %2 - + pat stl lol $1==$2 /* Store then load local */ leaving dup 4 @@ -910,13 +910,13 @@ PATTERNS dup INT32 lal $1 sti $2 - + pat ste loe $1==$2 /* Store then load external */ leaving dup 4 ste $1 - - + + /* Type conversions */ pat loc loc cii loc loc cii $1==$4 && $2==$5 /* madness, generated by the C compiler */ @@ -924,19 +924,19 @@ PATTERNS loc $1 loc $2 cii - + pat loc loc cii loc loc cii $2==INT32 && $5==INT32 && $4<$2 /* madness, generated by the C compiler */ leaving loc $4 loc $5 cii - + pat loc loc ciu /* signed X -> unsigned X */ leaving loc $1 loc $2 cuu - + pat loc loc cuu $1==$2 /* unsigned X -> unsigned X */ /* nop */ @@ -945,25 +945,25 @@ PATTERNS pat loc loc cui $1==$2 /* unsigned X -> signed X */ /* nop */ - + pat loc loc cui $1==INT8 && $2==INT32 /* unsigned char -> signed int */ /* nop */ - + pat loc loc cui $1==INT16 && $2==INT32 /* unsigned short -> signed int */ /* nop */ - + pat loc loc cii $1==INT8 && $2==INT32 /* signed char -> signed int */ with GPR yields {SEX_B, %1} - + pat loc loc cii $1==2 && $2==4 /* signed char -> signed short */ with GPR yields {SEX_H, %1} - - - - + + + + /* Local variables */ pat lal smalls($1) /* Load address of local */ @@ -975,7 +975,7 @@ PATTERNS pat lol inreg($1)>0 /* Load from local */ yields {LOCAL, $1} - + pat lol /* Load from local */ leaving lal $1 @@ -985,34 +985,34 @@ PATTERNS leaving lal $1 loi INT32*2 - + pat stl inreg($1)>0 /* Store to local */ with CONST_ALL + LABEL + GPR + OP_ALL_W kills regvar($1), LOCAL %off==$1 gen move %1, {GPRE, regvar($1)} - + pat stl /* Store to local */ leaving lal $1 sti INT32 - + pat sdl /* Store double-word to local */ leaving lal $1 sti INT32*2 - + pat lil inreg($1)>0 /* Load from indirected local */ uses REG gen lwz %a, {GPRINDIRECT, regvar($1), 0} yields %a - + pat lil /* Load from indirected local */ leaving lol $1 loi INT32 - + pat sil /* Save to indirected local */ leaving lol $1 @@ -1022,14 +1022,14 @@ PATTERNS leaving loc 0 stl $1 - + pat inl /* Increment local */ leaving lol $1 loc 1 adi 4 stl $1 - + pat del /* Decrement local */ leaving lol $1 @@ -1039,14 +1039,14 @@ PATTERNS /* Global variables */ - + pat lpi /* Load address of external function */ leaving lae $1 - + pat lae /* Load address of external */ yields {LABEL, $1} - + pat loe /* Load word external */ leaving lae $1 @@ -1056,36 +1056,36 @@ PATTERNS leaving lae $1 sti INT32 - + pat lde /* Load double-word external */ leaving lae $1 loi INT64 - + pat sde /* Store double-word external */ leaving lae $1 sti INT64 - + pat zre /* Zero external */ leaving loc 0 ste $1 - + pat ine /* Increment external */ uses REG={LABEL, $1}, REG gen lwz %b, {GPRINDIRECT, %a, 0} addi %b, %b, {CONST, 1} stw %b, {GPRINDIRECT, %a, 0} - + pat dee /* Decrement external */ uses REG={LABEL, $1}, REG gen lwz %b, {GPRINDIRECT, %a, 0} addi %b, %b, {CONST, 0-1} stw %b, {GPRINDIRECT, %a, 0} - + /* Structures */ @@ -1094,22 +1094,22 @@ PATTERNS leaving adp $1 loi INT32 - + pat ldf /* Load double-word offsetted */ leaving adp $1 loi INT64 - + pat stf /* Store word offsetted */ leaving adp $1 sti INT32 - + pat sdf /* Store double-word offsetted */ leaving adp $1 sti INT64 - + /* Loads and stores */ @@ -1159,7 +1159,7 @@ PATTERNS leaving loc $1 los INT32 - + pat los /* Load arbitrary size */ with GPR3 GPR4 STACK kills ALL @@ -1288,17 +1288,17 @@ PATTERNS kills ALL gen bl {LABEL, ".sts"} - + /* Arithmetic wrappers */ pat ads $1==4 /* Add var to pointer */ leaving adi $1 - + pat sbs $1==4 /* Subtract var from pointer */ leaving sbi $1 - + pat adp /* Add constant to pointer */ leaving loc $1 @@ -1307,41 +1307,41 @@ PATTERNS pat adu /* Add unsigned */ leaving adi $1 - + pat sbu /* Subtract unsigned */ leaving sbi $1 - + pat inc /* Add 1 */ leaving loc 1 adi 4 - + pat dec /* Subtract 1 */ leaving loc 1 sbi 4 - + pat loc mlu $2==2 /* Unsigned multiply by constant */ leaving loc $1 mli 4 - + pat mlu /* Unsigned multiply by var */ leaving mli $1 - + pat loc slu /* Shift left unsigned by constant amount */ leaving loc $1 sli $2 - + pat slu /* Shift left unsigned by variable amount */ leaving sli $1 - - + + /* Word arithmetic */ pat adi $1==4 /* Add word (second + top) */ @@ -1389,21 +1389,21 @@ PATTERNS gen neg %a, %1 yields %a - + pat mli $1==4 /* Multiply word (second * top) */ with REG REG uses reusing %2, REG gen mullw %a, %2, %1 yields %a - + pat dvi $1==4 /* Divide word (second / top) */ with REG REG uses reusing %2, REG gen divw %a, %2, %1 yields %a - + pat dvu $1==4 /* Divide unsigned word (second / top) */ with REG REG uses reusing %2, REG @@ -1419,7 +1419,7 @@ PATTERNS mullw %a, %a, %1 subf %a, %a, %2 yields %a - + pat rmu $1==4 /* Remainder unsigned word (second % top) */ with REG REG uses REG @@ -1527,7 +1527,7 @@ PATTERNS with STACK gen bl {LABEL, ".xor"} - + pat com $1==INT32 /* NOT word */ with AND_RR uses REG @@ -1546,12 +1546,12 @@ PATTERNS yields %a with GPR yields {NOT_R, %1} - + pat com !defined($1) /* NOT set */ with STACK gen bl {LABEL, ".com"} - + pat sli $1==4 /* Shift left (second << top) */ with CONST_ALL GPR uses reusing %2, REG @@ -1563,7 +1563,7 @@ PATTERNS gen slw %a, %2, %1 yields %a - + pat sri $1==4 /* Shift right signed (second >> top) */ with CONST_ALL GPR uses reusing %2, REG @@ -1587,7 +1587,7 @@ PATTERNS gen srw %a, %2, %1 yields %a - + /* Arrays */ @@ -1597,19 +1597,19 @@ PATTERNS gen bl {LABEL, ".aar4"} yields R3 - + pat lae lar $2==INT32 && nicesize(rom($1, 3)) /* Load array */ leaving lae $1 aar INT32 loi rom($1, 3) - + pat lar $1==INT32 /* Load array */ with GPR3 GPR4 GPR5 STACK kills ALL gen bl {LABEL, ".lar4"} - + pat lae sar $2==INT32 && nicesize(rom($1, 3)) /* Store array */ leaving lae $1 @@ -1621,10 +1621,10 @@ PATTERNS kills ALL gen bl {LABEL, ".sar4"} - - + + /* Sets */ pat set defined($1) /* Create word with set bit */ @@ -1632,12 +1632,12 @@ PATTERNS loc 1 exg INT32 sli INT32 - + pat set !defined($1) /* Create structure with set bit (variable) */ with GPR3 GPR4 STACK gen bl {LABEL, ".set"} - + pat inn /* Test for set bit */ with STACK kills ALL @@ -1646,9 +1646,9 @@ PATTERNS li32 %a, {CONST, $1} stwu %a, {GPRINDIRECT, SP, 0-4} bl {LABEL, ".inn"} - - - + + + /* Boolean resolutions */ pat teq /* top = (top == 0) */ @@ -1660,7 +1660,7 @@ PATTERNS move {LABEL, ".teq_table"}, %a lwzx %a, %a, RSCRATCH yields %a - + pat tne /* top = (top != 0) */ with TRISTATE_ALL + GPR uses reusing %1, REG @@ -1670,7 +1670,7 @@ PATTERNS move {LABEL, ".tne_table"}, %a lwzx %a, %a, RSCRATCH yields %a - + pat tlt /* top = (top < 0) */ with TRISTATE_ALL + GPR uses reusing %1, REG @@ -1680,7 +1680,7 @@ PATTERNS move {LABEL, ".tlt_table"}, %a lwzx %a, %a, RSCRATCH yields %a - + pat tle /* top = (top <= 0) */ with TRISTATE_ALL + GPR uses reusing %1, REG @@ -1690,7 +1690,7 @@ PATTERNS move {LABEL, ".tle_table"}, %a lwzx %a, %a, RSCRATCH yields %a - + pat tgt /* top = (top > 0) */ with TRISTATE_ALL + GPR uses reusing %1, REG @@ -1710,7 +1710,7 @@ PATTERNS move {LABEL, ".tge_table"}, %a lwzx %a, %a, RSCRATCH yields %a - + @@ -1726,7 +1726,7 @@ PATTERNS leaving cmi INT32 zeq $1 - + pat zne /* Branch if signed top != 0 */ with TRISTATE_ALL+GPR STACK gen @@ -1737,7 +1737,7 @@ PATTERNS leaving cmi INT32 zne $1 - + pat zgt /* Branch if signed top > 0 */ with TRISTATE_ALL+GPR STACK gen @@ -1748,7 +1748,7 @@ PATTERNS leaving cmi INT32 zgt $1 - + pat zge /* Branch if signed top >= 0 */ with TRISTATE_ALL+GPR STACK gen @@ -1759,7 +1759,7 @@ PATTERNS leaving cmi INT32 zge $1 - + pat zlt /* Branch if signed top < 0 */ with TRISTATE_ALL+GPR STACK gen @@ -1770,7 +1770,7 @@ PATTERNS leaving cmi INT32 zlt $1 - + pat zle /* Branch if signed top >= 0 */ with TRISTATE_ALL+GPR STACK gen @@ -1781,7 +1781,7 @@ PATTERNS leaving cmi INT32 zle $1 - + /* Compare and jump */ @@ -1790,23 +1790,23 @@ PATTERNS yields {TRISTATE_RC_S, %2, %1.val} with GPR GPR yields {TRISTATE_RR_S, %2, %1} - + pat cmu /* Unsigned tristate compare */ with CONST_ALL GPR yields {TRISTATE_RC_U, %2, %1.val} with GPR GPR yields {TRISTATE_RR_U, %2, %1} - + pat cmp /* Compare pointers */ leaving cmu INT32 - + pat cms $1==INT32 /* Compare blocks (word sized) */ leaving cmi INT32 - - - + + + /* Other branching and labelling */ @@ -1814,31 +1814,31 @@ PATTERNS gen labeldef $1 yields R3 - + pat lab topeltsize($1)==4 && fallthrough($1) with GPR3 gen labeldef $1 yields %1 - + pat lab topeltsize($1)!=4 with STACK kills ALL gen labeldef $1 - + pat bra topeltsize($1)==4 /* Unconditional jump with TOS GPRister */ with GPR3 STACK gen b {LABEL, $1} - + pat bra topeltsize($1)!=4 /* Unconditional jump without TOS GPRister */ with STACK gen b {LABEL, $1} - - - + + + /* Miscellaneous */ pat cal /* Call procedure */ @@ -1853,18 +1853,18 @@ PATTERNS gen mtspr CTR, %1 bcctrl ALWAYS, {CONST, 0}, {CONST, 0} - + pat lfr $1==INT32 /* Load function result, word */ yields R3 - + pat lfr $1==INT64 /* Load function result, double-word */ yields R4 R3 - + pat ret $1==0 /* Return from procedure */ gen return b {LABEL, ".ret"} - + pat ret $1==INT32 /* Return from procedure, word */ with GPR3 gen @@ -1887,7 +1887,7 @@ PATTERNS stwu %1, {GPRINDIRECT, SP, 0-4} bl {LABEL, "_memmove"} addi SP, SP, {CONST, 12} - + pat bls /* Block move variable length */ with GPR GPR GPR STACK gen @@ -1896,18 +1896,18 @@ PATTERNS stwu %2, {GPRINDIRECT, SP, 0-4} bl {LABEL, "_memmove"} addi SP, SP, {CONST, 12} - + pat csa /* Array-lookup switch */ with STACK gen b {LABEL, ".csa"} - + pat csb /* Table-lookup switch */ with STACK gen b {LABEL, ".csb"} - + /* EM specials */ @@ -1915,7 +1915,7 @@ PATTERNS leaving lae $1 ste "hol0+4" - + pat lin /* Set current line number */ leaving loc $1 @@ -1924,37 +1924,37 @@ PATTERNS pat lni /* Increment line number */ leaving ine "hol0" - + pat lim /* Load EM trap ignore mask */ leaving lde ".ignmask" - + pat sim /* Store EM trap ignore mask */ leaving ste ".ignmask" - + pat trp /* Raise EM trap */ with GPR3 gen bl {LABEL, ".trap"} - + pat sig /* Set trap handler */ leaving ste ".trppc" - + pat rtt /* Return from trap */ leaving ret 0 - + pat lxl $1==0 /* Load FP */ leaving lor 0 - + pat lxl $1==1 /* Load caller's FP */ leaving lxl 0 dch - + pat dch /* FP -> caller FP */ with GPR uses reusing %1, REG @@ -1965,12 +1965,12 @@ PATTERNS pat lpb /* Convert FP to argument address */ leaving adp EM_BSIZE - + pat lxa /* Load caller's SP */ leaving lxl $1 lpb - + pat gto /* longjmp */ uses REG gen @@ -1986,27 +1986,27 @@ PATTERNS gen move FP, %a yields %a - + pat lor $1==1 /* Load SP */ uses REG gen move SP, %a yields %a - + pat lor $1==2 /* Load HP */ leaving loe ".reghp" - + pat str $1==0 /* Store FP */ with GPR gen move %1, FP - + pat str $1==1 /* Store SP */ with GPR gen move %1, SP - + pat str $1==2 /* Store HP */ leaving ste ".reghp" @@ -2032,39 +2032,39 @@ PATTERNS with GPR STACK gen move {SUM_RR, SP, %1}, SP - + pat asp /* Adjust stack by constant amount */ leaving loc $1 ass - - - + + + /* Floating point support */ /* All very cheap and nasty --- this needs to be properly integrated into * the code generator. ncg doesn't like having separate FPU registers. */ /* Single-precision */ - + pat zrf $1==INT32 /* Push zero */ leaving loe ".fs_00000000" - + pat adf $1==INT32 /* Add single */ with FSREG FSREG uses reusing %1, FSREG gen fadds %a, %2, %1 yields %a - + pat sbf $1==INT32 /* Subtract single */ with FSREG FSREG uses reusing %1, FSREG gen fsubs %a, %2, %1 yields %a - + pat mlf $1==INT32 /* Multiply single */ with FSREG FSREG uses reusing %1, FSREG @@ -2089,56 +2089,56 @@ PATTERNS pat cmf $1==INT32 /* Compare single */ with FSREG FSREG yields {TRISTATE_FF, %2.1, %1.1} - + pat loc loc cff $1==INT32 && $2==INT64 /* Convert single to double */ with FSREG yields %1.1 - + pat loc loc cfu $1==INT32 && $2==INT32 /* Convert single to unsigned int */ with STACK gen bl {LABEL, ".cfu4"} - + pat loc loc cfi $1==INT32 && $2==INT32 /* Convert single to signed int */ with STACK gen bl {LABEL, ".cfi4"} - + pat loc loc cif $1==INT32 && $2==INT32 /* Convert integer to single */ with STACK gen bl {LABEL, ".cif4"} - + pat loc loc cuf $1==INT32 && $2==INT32 /* Convert unsigned int to single */ with STACK gen bl {LABEL, ".cuf4"} - + pat fef $1==INT32 /* Split single */ with STACK gen bl {LABEL, ".fef4"} - + /* Double-precision */ - + pat zrf $1==INT64 /* Push zero */ leaving lde ".fd_00000000" - + pat adf $1==INT64 /* Add double */ with FREG FREG uses FREG gen fadd %a, %2, %1 yields %a - + pat sbf $1==INT64 /* Subtract double */ with FREG FREG uses FREG gen fsub %a, %2, %1 yields %a - + pat mlf $1==INT64 /* Multiply double */ with FREG FREG uses reusing %1, FREG @@ -2163,30 +2163,30 @@ PATTERNS pat cmf $1==INT64 /* Compare double */ with FREG FREG yields {TRISTATE_FF, %2, %1} - + pat loc loc cff $1==INT64 && $2==INT32 /* Convert double to single */ with FREG uses reusing %1, FSREG gen frsp %a, %1 yields %a - + pat loc loc cfu $1==INT64 && $2==INT32 /* Convert double to unsigned int */ with STACK gen bl {LABEL, ".cfu8"} - + pat loc loc cfi $1==INT64 && $2==INT32 /* Convert double to signed int */ with STACK gen bl {LABEL, ".cfi8"} - + pat loc loc cif $1==INT32 && $2==INT64 /* Convert integer to double */ with STACK kills ALL gen bl {LABEL, ".cif8"} - + pat loc loc cuf $1==INT32 && $2==INT64 /* Convert unsigned int to double */ with STACK gen From 805883e3772410f1b57cb9d73bfffd42b5adfedf Mon Sep 17 00:00:00 2001 From: George Koehler Date: Fri, 9 Dec 2016 16:58:47 -0500 Subject: [PATCH 067/173] Fill in a hint for enabling the COMMENT macro. If you want to enable comments in the .s file, change #define COMMENT(n) /* comment {LABEL, n} */ to #define COMMENT(n) comment {LABEL, n} --- mach/powerpc/ncg/table | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mach/powerpc/ncg/table b/mach/powerpc/ncg/table index 1d2c5516e..1f2232c3b 100644 --- a/mach/powerpc/ncg/table +++ b/mach/powerpc/ncg/table @@ -10,7 +10,7 @@ INT64 = 8 FP_OFFSET = 0 /* Offset of saved FP relative to our FP */ PC_OFFSET = 4 /* Offset of saved PC relative to our FP */ -#define COMMENT(n) /* noop */ +#define COMMENT(n) /* comment {LABEL, n} */ #define nicesize(x) ((x)==INT8 || (x)==INT16 || (x)==INT32 || (x)==INT64) From 5bd0ad42692cab2932e0496849a95bf080512651 Mon Sep 17 00:00:00 2001 From: George Koehler Date: Fri, 9 Dec 2016 17:00:56 -0500 Subject: [PATCH 068/173] Remove the bogus rules for 'lor 2' and 'str 2'. These instructions would load or store the EM heap pointer. They don't work. Programs must use brk() or sbrk() in libsys. The last file to use 'lor 2' and 'str 2' was lang/pc/libpc/sav.e in the Pascal library. Commit c084f9f deleted the file, so we no longer need rules 'lor 2' or 'str 2' to build the ACK. --- mach/powerpc/ncg/table | 8 -------- 1 file changed, 8 deletions(-) diff --git a/mach/powerpc/ncg/table b/mach/powerpc/ncg/table index 1f2232c3b..9d12698e5 100644 --- a/mach/powerpc/ncg/table +++ b/mach/powerpc/ncg/table @@ -1993,10 +1993,6 @@ PATTERNS move SP, %a yields %a - pat lor $1==2 /* Load HP */ - leaving - loe ".reghp" - pat str $1==0 /* Store FP */ with GPR gen @@ -2007,10 +2003,6 @@ PATTERNS gen move %1, SP - pat str $1==2 /* Store HP */ - leaving - ste ".reghp" - pat loc ass $1==4 /* Drop 4 bytes from stack */ with exact GPR /* nop */ From 17211eef475fcf91cda493c968c0565798f413a4 Mon Sep 17 00:00:00 2001 From: George Koehler Date: Fri, 9 Dec 2016 17:32:42 -0500 Subject: [PATCH 069/173] Fix ass to match the EM spec. The spec says, "ASS w: Adjust the stack pointer by w-byte integer". The w argument "can either be given as argument or on top of the stack." Therefore, 'ass 4' would pop the 4-byte integer from the stack, but 'ass' would pop the size w from the stack, then pop the w-byte integer. PowerPC ncg wrongly implemented 'ass' as if it was 'ass 4'. Fix it to accept only 'ass 4'. --- mach/powerpc/ncg/table | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/mach/powerpc/ncg/table b/mach/powerpc/ncg/table index 9d12698e5..cf3de92fd 100644 --- a/mach/powerpc/ncg/table +++ b/mach/powerpc/ncg/table @@ -2003,14 +2003,14 @@ PATTERNS gen move %1, SP - pat loc ass $1==4 /* Drop 4 bytes from stack */ + pat loc ass $1==4 && $2==4 /* Drop 4 bytes from stack */ with exact GPR /* nop */ with STACK gen addi SP, SP, {CONST, 4} - pat ass /* Adjust stack by variable amount */ + pat ass $1==4 /* Adjust stack by variable amount */ with CONST2 STACK gen move {SUM_RC, SP, %1.val}, SP @@ -2028,7 +2028,7 @@ PATTERNS pat asp /* Adjust stack by constant amount */ leaving loc $1 - ass + ass 4 From 436114fce4fd0ba6b27adae2c583ae2f259fcfe2 Mon Sep 17 00:00:00 2001 From: George Koehler Date: Fri, 9 Dec 2016 18:40:14 -0500 Subject: [PATCH 070/173] Add a move from CONST smalls(%val) to GPR. This allows 'move {CONST, $1}, R3' with a small enough $1 to emit one instruction (addi) instead of two instructions (addis, ori). The CONST token confusingly isn't in the CONST_ALL set. --- mach/powerpc/ncg/table | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mach/powerpc/ncg/table b/mach/powerpc/ncg/table index cf3de92fd..d8b8082c7 100644 --- a/mach/powerpc/ncg/table +++ b/mach/powerpc/ncg/table @@ -389,7 +389,7 @@ MOVES /* Constants */ - from CONST_ALL smalls(%val) to GPR + from CONST_ALL + CONST smalls(%val) to GPR gen COMMENT("move CONST_ALL->GPR smalls") addi %2, R0, {CONST, %1.val} From fcda786fe98b7d944622043de36ff8f702626543 Mon Sep 17 00:00:00 2001 From: George Koehler Date: Fri, 9 Dec 2016 19:49:50 -0500 Subject: [PATCH 071/173] Add some missing clauses to los, sts, aar, inn, cmi, cmu. We only implement 'los 4', 'sts 4', 'cmi 4', 'cmu 4', not for sizes other than 4. Add clause $1==4. We only implement inn when defined($1). The rule for aar needs 'kills ALL' because it kills many registers, like other rules that call libem. --- mach/powerpc/ncg/table | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/mach/powerpc/ncg/table b/mach/powerpc/ncg/table index d8b8082c7..a6859ca14 100644 --- a/mach/powerpc/ncg/table +++ b/mach/powerpc/ncg/table @@ -1160,7 +1160,7 @@ PATTERNS loc $1 los INT32 - pat los /* Load arbitrary size */ + pat los $1==INT32 /* Load arbitrary size */ with GPR3 GPR4 STACK kills ALL gen @@ -1283,7 +1283,7 @@ PATTERNS loc $1 sts INT32 - pat sts /* Store arbitrary size */ + pat sts $1==INT32 /* Store arbitrary size */ with GPR3 GPR4 STACK kills ALL gen @@ -1594,6 +1594,7 @@ PATTERNS pat aar $1==INT32 /* Index array */ with GPR3 GPR4 GPR5 + kills ALL gen bl {LABEL, ".aar4"} yields R3 @@ -1638,7 +1639,7 @@ PATTERNS gen bl {LABEL, ".set"} - pat inn /* Test for set bit */ + pat inn defined($1) /* Test for set bit */ with STACK kills ALL uses REG @@ -1785,13 +1786,13 @@ PATTERNS /* Compare and jump */ - pat cmi /* Signed tristate compare */ + pat cmi $1==INT32 /* Signed tristate compare */ with CONST_ALL GPR yields {TRISTATE_RC_S, %2, %1.val} with GPR GPR yields {TRISTATE_RR_S, %2, %1} - pat cmu /* Unsigned tristate compare */ + pat cmu $1==INT32 /* Unsigned tristate compare */ with CONST_ALL GPR yields {TRISTATE_RC_U, %2, %1.val} with GPR GPR From 8605a2fcfc0439aeb92f75a66664a9fa885e5000 Mon Sep 17 00:00:00 2001 From: George Koehler Date: Sat, 10 Dec 2016 12:23:07 -0500 Subject: [PATCH 072/173] Add Modula-2 set operations to PowerPC ncg. This provides and, ior, xor, com, zer, set, cms when defined($1) and ior, set when !defined($1). I don't provide the other operations !defined($1) because our Modula-2 compiler hasn't used them. I wrote a Modula-2 example in https://gist.github.com/kernigh/add79662bb3c63ffb7c46d01dc8ae788 Put a dummy comment in mach/powerpc/libem/build.lua so git checkout will touch that file. Without the touch, the build system doesn't see the new *.s files. --- mach/powerpc/libem/and.s | 24 +++++++++++++++ mach/powerpc/libem/build.lua | 2 +- mach/powerpc/libem/cms.s | 32 ++++++++++++++++++++ mach/powerpc/libem/com.s | 20 +++++++++++++ mach/powerpc/libem/ior.s | 24 +++++++++++++++ mach/powerpc/libem/set.s | 29 ++++++++++++++++++ mach/powerpc/libem/xor.s | 24 +++++++++++++++ mach/powerpc/libem/zer.s | 21 +++++++++++++ mach/powerpc/ncg/table | 57 ++++++++++++++++++++++++++++-------- 9 files changed, 220 insertions(+), 13 deletions(-) create mode 100644 mach/powerpc/libem/and.s create mode 100644 mach/powerpc/libem/cms.s create mode 100644 mach/powerpc/libem/com.s create mode 100644 mach/powerpc/libem/ior.s create mode 100644 mach/powerpc/libem/set.s create mode 100644 mach/powerpc/libem/xor.s create mode 100644 mach/powerpc/libem/zer.s diff --git a/mach/powerpc/libem/and.s b/mach/powerpc/libem/and.s new file mode 100644 index 000000000..4a1a81c04 --- /dev/null +++ b/mach/powerpc/libem/and.s @@ -0,0 +1,24 @@ +#include "powerpc.h" + +.sect .text + +! Set intersection. +! Stack: ( b a -- a*b ) +! With r3 = size of set + +.define .and +.and: + mr r4, sp ! r4 = ptr to set a + add r5, sp, r3 ! r5 = ptr to set b + rlwinm r6, r3, 30, 2, 31 + mtspr ctr, r6 ! ctr = r3 / 4 +1: + lwz r7, 0(r4) + lwz r8, 0(r5) + and r8, r7, r8 ! intersection of words + stw r8, 0(r5) + addi r4, r4, 4 + addi r5, r5, 4 + bc DNZ, 0, 1b ! loop ctr times + add sp, sp, r3 + bclr ALWAYS, 0, 0 diff --git a/mach/powerpc/libem/build.lua b/mach/powerpc/libem/build.lua index 318be381d..786be4e11 100644 --- a/mach/powerpc/libem/build.lua +++ b/mach/powerpc/libem/build.lua @@ -7,7 +7,7 @@ for _, plat in ipairs(vars.plats) do acklibrary { name = "lib_"..plat, srcs = { - "./*.s", + "./*.s", -- zer.s "./*.e", }, vars = { plat = plat }, diff --git a/mach/powerpc/libem/cms.s b/mach/powerpc/libem/cms.s new file mode 100644 index 000000000..53cb65691 --- /dev/null +++ b/mach/powerpc/libem/cms.s @@ -0,0 +1,32 @@ +#include "powerpc.h" + +.sect .text + +! Compare sets a, b. +! Stack: ( b a -- ) +! With r3 = size of each set +! Yields r3 = 0 if equal, nonzero if not equal + +.define .cms +.cms: + mr r4, sp ! r4 = ptr to set a + add r5, sp, r3 ! r5 = ptr to set b + mr r6, r3 ! r6 = size + rlwinm r3, r3, 30, 2, 31 + mtspr ctr, r3 ! ctr = size / 4 +1: + lwz r7, 0(r4) + lwz r8, 0(r5) + cmp cr0, 0, r7, r8 ! compare words in sets + addi r4, r4, 4 + addi r5, r5, 4 + bc IFFALSE, EQ, 2f ! branch if not equal + bc DNZ, 0, 1b ! loop ctr times + addi r3, r0, 0 ! equal: return 0 + b 3f +2: + addi r3, r0, 1 ! not equal: return 1 +3: + rlwinm r6, r6, 1, 0, 30 ! r6 = size * 2 + add sp, sp, r6 ! remove sets from stack + bclr ALWAYS, 0, 0 diff --git a/mach/powerpc/libem/com.s b/mach/powerpc/libem/com.s new file mode 100644 index 000000000..8b7082332 --- /dev/null +++ b/mach/powerpc/libem/com.s @@ -0,0 +1,20 @@ +#include "powerpc.h" + +.sect .text + +! Set complement. +! Stack: ( a -- ~a ) +! With r3 = size of set + +.define .com +.com: + mr r4, sp ! r4 = pointer to set a + rlwinm r5, r3, 30, 2, 31 + mtspr ctr, r5 ! ctr = r3 / 4 +1: + lwz r6, 0(r4) + nor r6, r6, r6 ! complement of word + stw r6, 0(r4) + addi r4, r4, 4 + bc DNZ, 0, 1b ! loop ctr times + bclr ALWAYS, 0, 0 diff --git a/mach/powerpc/libem/ior.s b/mach/powerpc/libem/ior.s new file mode 100644 index 000000000..61e099934 --- /dev/null +++ b/mach/powerpc/libem/ior.s @@ -0,0 +1,24 @@ +#include "powerpc.h" + +.sect .text + +! Set union. +! Stack: ( b a -- a+b ) +! With r3 = size of set + +.define .ior +.ior: + mr r4, sp ! r4 = ptr to set a + add r5, sp, r3 ! r5 = ptr to set b + rlwinm r6, r3, 30, 2, 31 + mtspr ctr, r6 ! ctr = r3 / 4 +1: + lwz r7, 0(r4) + lwz r8, 0(r5) + or r8, r7, r8 ! union of words + stw r8, 0(r5) + addi r4, r4, 4 + addi r5, r5, 4 + bc DNZ, 0, 1b ! loop ctr times + add sp, sp, r3 + bclr ALWAYS, 0, 0 diff --git a/mach/powerpc/libem/set.s b/mach/powerpc/libem/set.s new file mode 100644 index 000000000..18ad877e8 --- /dev/null +++ b/mach/powerpc/libem/set.s @@ -0,0 +1,29 @@ +#include "powerpc.h" + +.sect .text + +! Create singleton set. +! Stack: ( -- set ) +! With r3 = size of set, r4 = bit number + +.define .set +.set: + rlwinm r7, r3, 30, 2, 31 + neg r5, r3 + add sp, sp, r5 ! allocate set + mr r6, sp ! r6 = ptr to set + mtspr ctr, r7 ! ctr = r3 / 4 +1: + rlwinm. r7, r4, 0, 0, 26 ! r7 = r4 & ~31 + bc IFTRUE, EQ, 2f ! branch if r4 in 0..31 + addi r5, r0, 0 ! no bit, word is zero + b 3f +2: + addi r5, r0, 1 + slw r5, r5, r4 ! yes bit, set bit in word +3: + stw r5, 0(r6) ! store word in set + addi r4, r4, -32 + addi r6, r6, 4 + bc DNZ, 0, 1b ! loop ctr times + bclr ALWAYS, 0, 0 diff --git a/mach/powerpc/libem/xor.s b/mach/powerpc/libem/xor.s new file mode 100644 index 000000000..9d4bc76b9 --- /dev/null +++ b/mach/powerpc/libem/xor.s @@ -0,0 +1,24 @@ +#include "powerpc.h" + +.sect .text + +! Set symmetric difference. +! Stack: ( b a -- a/b ) +! With r3 = size of set + +.define .xor +.xor: + mr r4, sp ! r4 = ptr to set a + add r5, sp, r3 ! r5 = ptr to set b + rlwinm r6, r3, 30, 2, 31 + mtspr ctr, r6 ! ctr = r3 / 4 +1: + lwz r7, 0(r4) + lwz r8, 0(r5) + xor r8, r7, r8 ! symmetric difference of words + stw r8, 0(r5) + addi r4, r4, 4 + addi r5, r5, 4 + bc DNZ, 0, 1b ! loop ctr times + add sp, sp, r3 + bclr ALWAYS, 0, 0 diff --git a/mach/powerpc/libem/zer.s b/mach/powerpc/libem/zer.s new file mode 100644 index 000000000..ba978ba3e --- /dev/null +++ b/mach/powerpc/libem/zer.s @@ -0,0 +1,21 @@ +#include "powerpc.h" + +.sect .text + +! Create empty set. +! Stack: ( -- set ) +! With r3 = size of set + +.define .zer +.zer: + rlwinm r7, r3, 30, 2, 31 + addi r4, r0, 0 ! r4 = zero + neg r5, r3 + add sp, sp, r5 ! allocate set + mr r6, sp ! r6 = ptr to set + mtspr ctr, r7 ! ctr = r3 / 4 +1: + stw r4, 0(r6) ! store zero in set + addi r6, r6, 4 + bc DNZ, 0, 1b ! loop ctr times + bclr ALWAYS, 0, 0 diff --git a/mach/powerpc/ncg/table b/mach/powerpc/ncg/table index a6859ca14..adb0db2c8 100644 --- a/mach/powerpc/ncg/table +++ b/mach/powerpc/ncg/table @@ -1463,9 +1463,11 @@ PATTERNS andisX %a, %2, {CONST, hi(%1.val)} yields %a - pat and !defined($1) /* AND set */ + pat and defined($1) /* AND set */ with STACK + kills ALL gen + move {CONST, $1}, R3 bl {LABEL, ".and"} pat ior $1==4 /* OR word */ @@ -1498,8 +1500,17 @@ PATTERNS uses reusing %2, REG={OR_RIS, %2, hi(%1.val)} yields {OR_RC, %2, lo(%1.val)} - pat ior !defined($1) /* OR set */ + pat ior defined($1) /* OR set */ with STACK + kills ALL + gen + move {CONST, $1}, R3 + bl {LABEL, ".ior"} + + /* OR set (variable), used in lang/m2/libm2/LtoUset.e */ + pat ior !defined($1) + with GPR3 STACK + kills ALL gen bl {LABEL, ".ior"} @@ -1523,9 +1534,11 @@ PATTERNS uses reusing %2, REG={XOR_RIS, %2, hi(%1.val)} yields {XOR_RC, %2, lo(%1.val)} - pat xor !defined($1) /* XOR set */ + pat xor defined($1) /* XOR set */ with STACK + kills ALL gen + move {CONST, $1}, R3 bl {LABEL, ".xor"} pat com $1==INT32 /* NOT word */ @@ -1547,11 +1560,23 @@ PATTERNS with GPR yields {NOT_R, %1} - pat com !defined($1) /* NOT set */ + pat com defined($1) /* NOT set */ with STACK gen + move {CONST, $1}, R3 bl {LABEL, ".com"} + pat zer $1==4 /* Push zero */ + leaving + loc 0 + + pat zer defined($1) /* Create empty set */ + with STACK + kills ALL + gen + move {CONST, $1}, R3 + bl {LABEL, ".zer"} + pat sli $1==4 /* Shift left (second << top) */ with CONST_ALL GPR uses reusing %2, REG @@ -1625,17 +1650,19 @@ PATTERNS - /* Sets */ - pat set defined($1) /* Create word with set bit */ - leaving - loc 1 - exg INT32 - sli INT32 + pat set defined($1) /* Create singleton set */ + with GPR4 STACK + kills ALL + gen + move {CONST, $1}, R3 + bl {LABEL, ".set"} - pat set !defined($1) /* Create structure with set bit (variable) */ + /* Create set (variable), used in lang/m2/libm2/LtoUset.e */ + pat set !defined($1) with GPR3 GPR4 STACK + kills ALL gen bl {LABEL, ".set"} @@ -1649,7 +1676,6 @@ PATTERNS bl {LABEL, ".inn"} - /* Boolean resolutions */ pat teq /* top = (top == 0) */ @@ -1806,6 +1832,13 @@ PATTERNS leaving cmi INT32 + pat cms defined($1) + with STACK + kills ALL + gen + move {CONST, $1}, R3 + bl {LABEL, ".cms"} + yields R3 From 62edb906418a3121604d988a68c4b954d4a2f01b Mon Sep 17 00:00:00 2001 From: David Given Date: Sun, 11 Dec 2016 23:06:37 +0100 Subject: [PATCH 073/173] Convert the inn test to work with the test library and not import InOut; it now runs on qemuppc again. Reenable qemuppc tests. --- build.lua | 2 +- tests/plat/bugs/bug-22-inn_mod.mod | 14 +++++--------- tests/plat/build.lua | 5 ++++- tests/plat/lib/Test.def | 6 ++++++ tests/plat/lib/build.lua | 7 ------- 5 files changed, 16 insertions(+), 18 deletions(-) create mode 100644 tests/plat/lib/Test.def delete mode 100644 tests/plat/lib/build.lua diff --git a/build.lua b/build.lua index 91415d689..6364e5f75 100644 --- a/build.lua +++ b/build.lua @@ -18,7 +18,7 @@ vars.plats = { vars.plats_with_tests = { "linux386", "linuxppc", - -- "qemuppc", FIXME: disable until we figure out why qemu won't run binaries bigger than 4kB + "qemuppc", "pc86", } diff --git a/tests/plat/bugs/bug-22-inn_mod.mod b/tests/plat/bugs/bug-22-inn_mod.mod index 8f3a2d00a..53fe93568 100644 --- a/tests/plat/bugs/bug-22-inn_mod.mod +++ b/tests/plat/bugs/bug-22-inn_mod.mod @@ -1,5 +1,5 @@ MODULE test; -FROM InOut IMPORT WriteLn, WriteString; +FROM Test IMPORT fail, finished; TYPE charset = SET OF CHAR; @@ -10,17 +10,13 @@ END Space; BEGIN IF Space('a') THEN - WriteString("@@FAIL 1"); - WriteLn; + fail(1); END; IF NOT Space(' ') THEN - WriteString("@@FAIL 2"); - WriteLn; + fail(2); END; IF NOT Space(12C) THEN - WriteString("@@FAIL 3"); - WriteLn; + fail(3); END; - WriteString("@@FINISHED"); - WriteLn; + finished; END test. \ No newline at end of file diff --git a/tests/plat/build.lua b/tests/plat/build.lua index d8362b3a0..3f43fb95b 100644 --- a/tests/plat/build.lua +++ b/tests/plat/build.lua @@ -18,7 +18,10 @@ definerule("plat_testsuite", acklibrary { name = "lib", srcs = { "tests/plat/lib/test.c" }, - hdrs = { "tests/plat/lib/test.h" }, + hdrs = { + "tests/plat/lib/test.h", + "tests/plat/lib/Test.def" + }, vars = { plat = e.plat }, } diff --git a/tests/plat/lib/Test.def b/tests/plat/lib/Test.def new file mode 100644 index 000000000..cab31f2e8 --- /dev/null +++ b/tests/plat/lib/Test.def @@ -0,0 +1,6 @@ +(*$Foreign*) +DEFINITION MODULE Test; + PROCEDURE finished(); + PROCEDURE writehex(code: LONGINT); + PROCEDURE fail(code: LONGINT); +END Test. diff --git a/tests/plat/lib/build.lua b/tests/plat/lib/build.lua deleted file mode 100644 index be9928c84..000000000 --- a/tests/plat/lib/build.lua +++ /dev/null @@ -1,7 +0,0 @@ -include("plat/build.lua") - -acklibrary { - name = "lib", - srcs = { "./test.c" }, - hdrs = { "./test.h" }, -} From 2874806048fb0d2efb9a0e7383b4de30c3988c1c Mon Sep 17 00:00:00 2001 From: George Koehler Date: Tue, 13 Dec 2016 15:54:38 -0500 Subject: [PATCH 074/173] Tweak man syntax in aelflod.1 and aslod.1 Put end of sentence at end of line. This is roff(7) syntax so the formatter can make spacing between sentences. Use the macro .PP to break paragraphs. Use bold for the command name in SYNOPSIS, to match other ack manuals. --- util/amisc/aelflod.1 | 26 ++++++++++++++------------ util/amisc/aslod.1 | 10 +++++----- 2 files changed, 19 insertions(+), 17 deletions(-) diff --git a/util/amisc/aelflod.1 b/util/amisc/aelflod.1 index 24001ba2d..00cd62220 100644 --- a/util/amisc/aelflod.1 +++ b/util/amisc/aelflod.1 @@ -1,25 +1,27 @@ -.TH ASLOD 1 "$Revision$" +.TH AELFLOD 1 "$Revision$" .SH NAME aelflod \- ACK ELF loader .SH SYNOPSIS -aelflod [-h] [-v] inputfile outputfile +.B aelflod +[-h] [-v] inputfile outputfile .SH DESCRIPTION .I aelflod converts an absolute ack.out file into a simple binary memory -dump wrapped up in an ELF executable. It is suitable for producing -executables for operating systems such as Linux. - +dump wrapped up in an ELF executable. +It is suitable for producing executables for operating systems +such as Linux. +.PP The input file must contain exactly four segments: TEXT, ROM, DATA and BSS, in that order, all occupying contiguous memory. The file must have all references resolved and be linked to a -fixed address. The fixed address must be at least 0x54 bytes -greater than a page boundary, in order to make room for the ELF -header itself. - +fixed address. +The fixed address must be at least 0x54 bytes greater than a +page boundary, in order to make room for the ELF header itself. +.PP aelflod will write out an ELF header followed by each segment, in order, ensuring that enough padding is inserted between each segment -to keep the offsets correct. The created executable will contain just -one rwx segment, and no sections. - +to keep the offsets correct. +The created executable will contain just one rwx segment, and no +sections. .SH "SEE ALSO" ack.out(5) diff --git a/util/amisc/aslod.1 b/util/amisc/aslod.1 index a786b13e6..f81590739 100644 --- a/util/amisc/aslod.1 +++ b/util/amisc/aslod.1 @@ -2,19 +2,19 @@ .SH NAME aslod \- ACK simple loader .SH SYNOPSIS -aslod [-h] [-v] inputfile outputfile +.B aslod +[-h] [-v] inputfile outputfile .SH DESCRIPTION .I aslod -converts an absolute ack.out file into a simple binary memory -dump. It is suitable for producing RAM images, executables for +converts an absolute ack.out file into a simple binary memory dump. +It is suitable for producing RAM images, executables for simple operating systems such as CP/M, DOS, etc. - +.PP The input file must contain exactly four segments: TEXT, ROM, DATA and BSS, in that order, all occupying contiguous memory. The file must have all references resolved and be linked to a fixed address. aslod will dump the segments, in order, such that the first byte of TEXT is at offset 0 in the file (regardless of where it is in memory). - .SH "SEE ALSO" ack.out(5) From 8280ca8745af514236f3dd24b52f404bfe2bcf09 Mon Sep 17 00:00:00 2001 From: George Koehler Date: Tue, 13 Dec 2016 16:02:38 -0500 Subject: [PATCH 075/173] In aslod, remove some unused m68k2 stuff. --- util/amisc/aslod.c | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/util/amisc/aslod.c b/util/amisc/aslod.c index afc8f8c3e..72fbc8ce4 100644 --- a/util/amisc/aslod.c +++ b/util/amisc/aslod.c @@ -45,12 +45,6 @@ FILE* output; /* Output stream */ #define readf(a, b, c) fread((a), (b), (int)(c), input) #define writef(a, b, c) fwrite((a), (b), (int)(c), output) -/* Output file definitions and such */ - -#define HDR_LENGTH 32 - -char hdr[HDR_LENGTH] ; - bool verbose = false; /* Segment numbers understood by aslod. */ @@ -63,14 +57,6 @@ enum { NUM_SEGMENTS }; -#define N_EXT 040 -#define N_UNDEF 00 -#define N_ABS 01 -#define N_TEXT 02 -#define N_DATA 03 -#define N_BSS 04 -#define N_FN 037 - /* Produce an error message and exit. */ void fatal(const char* s, ...) From 5cf2a684384c17880e63c478eff78d756b9041ca Mon Sep 17 00:00:00 2001 From: George Koehler Date: Tue, 13 Dec 2016 16:41:22 -0500 Subject: [PATCH 076/173] Teach aelflod to write the ELF symbol table. Convert each ack.out symbol to ELF, preserving its name and value, and some but not all other symbol info. The ELF symbol table comes with ELF section headers. If the input file has no symbols (ack -Rled-s), then the output file has no ELF section headers. Append the symbol table and section headers to the ELF file. Linux ignores this appended info when it execs the file. The info might pollute the last page of the ELF segment, but Linux clears this pollution. Tools like nm and gdb can read the ELF symbol table. I include code to translate debugger symbols to an ELF .stab section. I did not test this code, because I did not find a platform that can put S_STB symbols in the ack.out file. --- util/amisc/aelflod.c | 448 +++++++++++++++++++++++++++++++++++++++---- 1 file changed, 412 insertions(+), 36 deletions(-) diff --git a/util/amisc/aelflod.c b/util/amisc/aelflod.c index e3692ac01..d5a9c0df3 100644 --- a/util/amisc/aelflod.c +++ b/util/amisc/aelflod.c @@ -35,10 +35,14 @@ int elfabi = 3; /* abi = Linux */ int elfmachine = 3; /* machine = EM_386 */ /* Header and section table of an ack object file. */ - + struct outhead outhead; struct outsect outsect[S_MAX]; +struct outname* outname = NULL; char* stringarea; +uint32_t ack_off_char; +int nstab = 0; /* S_STB symbol count */ +int nsym = 0; /* other symbol count */ char* outputfile = NULL; /* Name of output file, or NULL */ char* program; /* Name of current program: argv[0] */ @@ -49,23 +53,30 @@ FILE* output; /* Output stream */ #define readf(a, b, c) fread((a), (b), (int)(c), input) #define writef(a, b, c) fwrite((a), (b), (int)(c), output) -/* Header and program header table of an ELF object file. */ +/* Contents of an ELF object file. */ #define ELF_HEADER_SIZE 0x34 #define PROGRAM_HEADER_SIZE 0x20 #define PROGRAM_HEADER_COUNT 1 -unsigned long codeoffset; +#define SECTION_HEADER_SIZE 0x28 +#define STAB_SYMBOL_SIZE 12 +#define ELF_SYMBOL_SIZE 16 + +uint32_t code_offset; /* ELF segment */ +uint32_t stab_offset; /* Debugger symbol table */ +uint32_t symtab_offset; /* ELF symbol table */ +uint32_t strtab_offset; /* String table */ +uint32_t shstrtab_offset; /* Section header string table */ +uint32_t sh_offset; /* ELF section headers */ + +int sh_count = 0; /* Number of ELF sections */ +int shstrtab_nr = 0; /* Section number of .shstrtab */ +int shstrtab_size; const char elf_le_ident_string[] = { 0x7F, 'E', 'L', 'F' }; -/* Output file definitions and such */ - -#define HDR_LENGTH 32 - -char hdr[HDR_LENGTH] ; - bool verbose = false; /* Segment numbers understood by aelflod. */ @@ -78,13 +89,33 @@ enum { NUM_SEGMENTS }; -#define N_EXT 040 -#define N_UNDEF 00 -#define N_ABS 01 -#define N_TEXT 02 -#define N_DATA 03 -#define N_BSS 04 -#define N_FN 037 +/* + * ELF section numbers count up in the order that we write the ELF + * section headers. If we have no debugger symbols, we will skip + * .stab and .stabstr, then subtract 2 from all later numbers. + */ +enum { + N_UNDEF = 0, + N_TEXT, + N_RODATA, + N_DATA, + N_BSS, + N_STAB, + N_STABSTR, + N_SYMTAB, + N_STRTAB, + N_SHSTRTAB, + NUM_ELF_SECTIONS, +}; +const char shstrtab[] = + "\0.text\0.rodata\0.data\0.bss\0.stab\0.stabstr\0" + ".symtab\0.strtab\0.shstrtab"; + /* Compiler appends one more "\0". */ +const int sh_name[] = { + /* Index of each name in shstrtab: */ + 0, 1, 7, 15, 21, 26, 32, + 41, 49, 57, +}; /* Produce an error message and exit. */ @@ -121,6 +152,80 @@ int follows(struct outsect* pa, struct outsect* pb) return (pa->os_base >= align(pb->os_base+pb->os_size, pa->os_lign)); } +/* Convert a symbol's name index from ack.out to ELF. */ + +uint32_t cvname(struct outname* n) +{ + if (n->on_foff) { + /* ack.out: offset from beginning of file + * ELF: index in string table + * the + 1 because we prepend a '\0' */ + return n->on_foff - ack_off_char + 1; + } else + return 0; /* no name */ +} + +/* Convert a symbol's type and binding from ack.out to ELF. */ + +int cvinfo(struct outname* n) +{ + int bind, type; + + switch (n->on_type & S_ETC) { + case S_SCT: + type = 3; /* STT_SECTION */ + break; + case S_FIL: + case S_MOD: + type = 4; /* STT_FILE */ + break; + default: + switch (n->on_type & S_TYP) { + case S_MIN + TEXT: + type = 2; /* STT_FUNC */ + break; + case S_MIN + ROM: + case S_MIN + DATA: + case S_MIN + BSS: + case S_MIN + NUM_SEGMENTS: + type = 1; /* STT_OBJECT */ + break; + default: + type = 0; /* STT_NOTYPE */ + break; + } + break; + } + + if (n->on_type & S_EXT) + bind = 1; /* STB_GLOBAL */ + else + bind = 0; /* STB_LOCAL */ + + return (bind << 4) | type; +} + +/* Convert a symbol's section index from ack.out to ELF. */ + +int cvsect(struct outname* n) +{ + switch (n->on_type & S_TYP) { + case S_ABS: + return 0xfff1; /* SHN_ABS */ + case S_MIN + TEXT: + return N_TEXT; + case S_MIN + ROM: + return N_RODATA; + case S_MIN + DATA: + return N_DATA; + case S_MIN + BSS: + case S_MIN + NUM_SEGMENTS: + return N_BSS; + default: + return N_UNDEF; + } +} + /* Writes a byte. */ void emit8(unsigned char value) @@ -220,6 +325,188 @@ void emitphdr(unsigned long address, unsigned long filesize, fileoffset += filesize; } +/* The next few functions write parts of the symbol table. */ + +void emit_stab(void) +{ + struct outname* n; + int i; + + for (i = 0; i < outhead.oh_nname; i++) { + n = &outname[i]; + if (n->on_type & S_STB) { + emit32(cvname(n)); /* name index */ + emit8(n->on_type >> 8); /* type */ + emit8(cvsect(n)); /* section */ + emit16(n->on_desc); /* desc */ + emit32(n->on_valu); /* value */ + } + } +} + +void emit_symtab(void) +{ + struct outname* n; + int i; + + for (i = 0; i < outhead.oh_nname; i++) { + n = &outname[i]; + if (!(n->on_type & S_STB)) { + emit32(cvname(n)); /* name index */ + emit32(n->on_valu); /* value */ + emit32(0); /* size = unknown */ + emit8(cvinfo(n)); /* info */ + emit8(0); /* other */ + emit16(cvsect(n)); /* section */ + } + } +} + +void emit_strtab(void) +{ + /* We prepend a '\0' because ELF uses offset 0 for symbols + * without a name. */ + emit8('\0'); + writef(stringarea, outhead.oh_nchar, 1); +} + +void emit_shstrtab(void) +{ + if (nstab) { + writef(shstrtab, sizeof(shstrtab), 1); + } else { + /* Skip .stab and .stabstr */ + int i = sh_name[N_SYMTAB]; + writef(shstrtab, sh_name[N_STAB], 1); + writef(shstrtab + i, sizeof(shstrtab) - i, 1); + } +} + +/* Writes out an ELF section header. */ + +void emit_sh(int i) +{ + uint32_t name, type, flags, addr, offset, size, addralign, + link, entsize; + + /* If no debugger symbols, skip .stab and .stabstr */ + if (nstab == 0 && (i == N_STAB || i == N_STABSTR)) + return; + + name = sh_name[i]; + if (nstab == 0 && i >= N_STAB) + name -= (sh_name[N_SYMTAB] - sh_name[N_STAB]); + + switch (i) { + case N_TEXT: + case N_RODATA: + case N_DATA: + case N_STAB: + type = 1; /* SHT_PROGBITS */ + break; + case N_BSS: + type = 8; /* SHT_NOBITS */ + break; + case N_SYMTAB: + type = 2; /* SHT_SYMTAB */ + break; + case N_STABSTR: + case N_STRTAB: + type = 3; /* SHT_STRTAB */ + break; + default: + type = 0; /* SHT_NULL */ + break; + } + + switch (i) { + case N_TEXT: + flags = 4|2; /* SHF_EXECINSTR|SHF_ALLOC */ + addr = outsect[TEXT].os_base; + offset = code_offset; + size = outsect[TEXT].os_size; + addralign = outsect[TEXT].os_lign; + break; + case N_RODATA: + flags = 2; /* SHF_ALLOC */ + addr = outsect[ROM].os_base; + offset = code_offset + outsect[TEXT].os_size; + size = outsect[ROM].os_size; + addralign = outsect[ROM].os_lign; + break; + case N_DATA: + flags = 2|1; /* SHF_ALLOC|SHF_WRITE */ + addr = outsect[DATA].os_base; + offset = code_offset + outsect[TEXT].os_size + + outsect[ROM].os_size; + size = outsect[DATA].os_size; + addralign = outsect[DATA].os_lign; + break; + case N_BSS: + flags = 2|1; /* SHF_ALLOC|SHF_WRITE */ + addr = outsect[BSS].os_base; + offset = code_offset + outsect[TEXT].os_size + + outsect[ROM].os_size + outsect[DATA].os_size; + size = outsect[BSS].os_size; + addralign = outsect[BSS].os_lign; + break; + default: + flags = addr = offset = size = addralign = 0; + break; + } + + entsize = 0; + switch (i) { + case N_STAB: + offset = stab_offset; + size = STAB_SYMBOL_SIZE * nstab; + entsize = STAB_SYMBOL_SIZE; + break; + case N_SYMTAB: + offset = symtab_offset; + size = ELF_SYMBOL_SIZE * nsym; + entsize = ELF_SYMBOL_SIZE; + break; + case N_STABSTR: + case N_STRTAB: + /* .stabstr, .strtab share the string area */ + offset = strtab_offset; + /* the + 1 because we prepend a '\0' */ + size = 1 + outhead.oh_nchar; + break; + case N_SHSTRTAB: + offset = shstrtab_offset; + size = shstrtab_size; + break; + } + + /* Link .stab to .stabstr and .symtab to .strtab */ + switch (i) { + case N_STAB: + link = N_STABSTR; + break; + case N_SYMTAB: + link = N_STRTAB; + if (nstab == 0) + link -= 2; + break; + default: + link = 0; + break; + } + + emit32(name); + emit32(type); + emit32(flags); + emit32(addr); + emit32(offset); + emit32(size); + emit32(link); + emit32(0); /* info */ + emit32(addralign); + emit32(entsize); +} + /* Macros from modules/src/object/obj.h */ #define Xchar(ch) ((ch) & 0377) #define uget2(c) (Xchar((c)[0]) | ((unsigned) Xchar((c)[1]) << 8)) @@ -264,6 +551,57 @@ int rsect(FILE* f, struct outsect* sect) return 1 ; } +/* + * Read the ack.out symbol table and string area. Count symbols. + * Seek back to the current file position. + */ +int rnames(FILE* f) +{ + long told; + int i; + + /* If no symbols, then do nothing successfully. */ + if (outhead.oh_nname == 0) + return 1; + + /* Seek to the symbol table. */ + told = ftell(f); + if (told == -1) + return 0; + ack_off_char = OFF_CHAR(outhead); /* for cvname() */ + if (fseek(f, OFF_NAME(outhead), SEEK_SET)) + return 0; + + /* Using calloc(a, b) to check if a * b would overflow. */ + outname = calloc(outhead.oh_nname, sizeof(outname[0])); + if (outname == NULL) + fatal("out of memory."); + for (i = 0; i < outhead.oh_nname; i++) { + char buf[SZ_NAME], *c; + if (fread(buf, SZ_NAME, 1, f) != 1) + return 0; + c = buf; + outname[i].on_foff = get4(c); c += 4; + outname[i].on_type = uget2(c); c += 2; + outname[i].on_desc = uget2(c); c += 2; + outname[i].on_valu = get4(c); + if (outname[i].on_type & S_STB) + nstab++; + else + nsym++; + } + + stringarea = malloc(outhead.oh_nchar); + if (stringarea == NULL) + fatal("out of memory."); + if (fread(stringarea, outhead.oh_nchar, 1, f) != 1) + return 0; + + if (fseek(f, told, SEEK_SET)) + return 0; + return 1; +} + int main(int argc, char* argv[]) { /* General housecleaning and setup. */ @@ -287,7 +625,7 @@ int main(int argc, char* argv[]) break; case 'h': - fprintf(stderr, "%s: Syntax: aelflod [-a] [-b] [-h] [-l]\n\t[-m] \n", + fprintf(stderr, "%s: Syntax: aelflod [-a] [-b] [-h] [-l]\n\t[-m] [-v] \n", program); exit(0); @@ -360,6 +698,11 @@ int main(int argc, char* argv[]) } } + /* Read the symbol table, then seek back to the section data. */ + + if (!rnames(input)) + fatal("failed to read symbol table."); + /* A few checks */ if (outsect[BSS].os_flen != 0) @@ -387,8 +730,8 @@ int main(int argc, char* argv[]) /* Ensure the base address doesn't overlap the file header. */ - codeoffset = outsect[TEXT].os_base & 0x1FFF; - if (codeoffset < (ELF_HEADER_SIZE + PROGRAM_HEADER_SIZE*PROGRAM_HEADER_COUNT)) + code_offset = outsect[TEXT].os_base & 0x1FFF; + if (code_offset < (ELF_HEADER_SIZE + PROGRAM_HEADER_SIZE*PROGRAM_HEADER_COUNT)) fatal("base address too small --- overlaps ELF header"); /* Rationalise the memory sizes. */ @@ -398,6 +741,30 @@ int main(int argc, char* argv[]) outsect[DATA].os_size = outsect[BSS ].os_base - outsect[DATA].os_base; outsect[BSS ].os_size = align(outsect[BSS].os_size, outsect[BSS].os_lign); + stab_offset = code_offset + outsect[TEXT].os_size + + outsect[ROM].os_size + outsect[DATA].os_size; + + /* If we have symbols, then calculate some offsets. */ + + if (outhead.oh_nname) { + sh_count = NUM_ELF_SECTIONS; + shstrtab_nr = N_SHSTRTAB; + shstrtab_size = sizeof(shstrtab); + if (nstab == 0) { + /* Skip .stab and .stabstr */ + sh_count -= 2; + shstrtab_nr -= 2; + shstrtab_size -= + (sh_name[N_SYMTAB] - sh_name[N_STAB]); + } + + symtab_offset = stab_offset + STAB_SYMBOL_SIZE * nstab; + strtab_offset = symtab_offset + ELF_SYMBOL_SIZE * nsym; + /* the + 1 because we prepend a '\0' */ + shstrtab_offset = strtab_offset + 1 + outhead.oh_nchar; + sh_offset = shstrtab_offset + shstrtab_size; + } + /* Write out the ELF file header. */ writef(elf_le_ident_string, 4, 1); @@ -414,33 +781,29 @@ int main(int argc, char* argv[]) emit32(1); /* ELF version again */ emit32(outsect[TEXT].os_base); /* entry point */ emit32(ELF_HEADER_SIZE); /* program header offset */ - emit32(0); /* section header offset */ + emit32(sh_offset); /* section header offset */ emit32(0); /* flags */ emit16(ELF_HEADER_SIZE); /* elf header size */ emit16(PROGRAM_HEADER_SIZE); /* program header entry size */ emit16(1); /* number of program header entries */ - emit16(0x28); /* section header entry size */ - emit16(0); /* number of section header entries */ - emit16(0); /* section header string table index = SHN_UNDEF */ + emit16(SECTION_HEADER_SIZE); /* section header entry size */ + emit16(sh_count); /* number of section header entries */ + emit16(shstrtab_nr); /* section header string table index */ /* Write out a single rwx section for the entire program. */ { - unsigned long filelength = codeoffset + - outsect[TEXT].os_size + - outsect[ROM].os_size + - outsect[DATA].os_size; - - unsigned long memlength = filelength + - outsect[BSS].os_size; - - emitphdr(outsect[TEXT].os_base & ~0x1FFF, filelength, memlength, - 0, 4|2|1); + uint32_t filelength = stab_offset; + uint32_t memlength = filelength + outsect[BSS].os_size; + + emitphdr(outsect[TEXT].os_base & ~0x1FFF, + filelength, memlength, 0, 4|2|1); } /* Write padding until the code start. */ - - fseek(output, codeoffset, SEEK_SET); + + if (fseek(output, code_offset, SEEK_SET)) + fatal("output seek error"); /* Write out the actual data. */ @@ -448,6 +811,19 @@ int main(int argc, char* argv[]) emits(&outsect[ROM]); emits(&outsect[DATA]); + /* Write out the symbol table and section headers. */ + + if (outhead.oh_nname) { + int i; + if (nstab) + emit_stab(); + emit_symtab(); + emit_strtab(); + emit_shstrtab(); + for (i = 0; i < NUM_ELF_SECTIONS; i++) + emit_sh(i); + } + if (ferror(output)) fatal("output write error"); if (outputfile) @@ -459,7 +835,7 @@ int main(int argc, char* argv[]) { uint32_t ss = 0; printf(" address length\n"); - printf(" ehdr : %08"PRIx32" %08"PRIx32"\n", outsect[TEXT].os_base & ~0x1FFF, codeoffset); + printf(" ehdr : %08"PRIx32" %08"PRIx32"\n", outsect[TEXT].os_base & ~0x1FFF, code_offset); printf(" text : %08"PRIx32" %08"PRIx32"\n", outsect[TEXT].os_base, outsect[TEXT].os_size); printf(" rom : %08"PRIx32" %08"PRIx32"\n", outsect[ROM].os_base, outsect[ROM].os_size); printf(" data : %08"PRIx32" %08"PRIx32"\n", outsect[DATA].os_base, outsect[DATA].os_size); From 7e39a821f4338d8f6114f87fbe447aadc370968a Mon Sep 17 00:00:00 2001 From: George Koehler Date: Tue, 13 Dec 2016 17:22:45 -0500 Subject: [PATCH 077/173] Update aelflod.1 to describe options, mention symbol table. --- util/amisc/aelflod.1 | 41 ++++++++++++++++++++++++++++++++++++----- 1 file changed, 36 insertions(+), 5 deletions(-) diff --git a/util/amisc/aelflod.1 b/util/amisc/aelflod.1 index 00cd62220..808b95429 100644 --- a/util/amisc/aelflod.1 +++ b/util/amisc/aelflod.1 @@ -3,7 +3,7 @@ aelflod \- ACK ELF loader .SH SYNOPSIS .B aelflod -[-h] [-v] inputfile outputfile +[-a\fInumber\fP] [-b] [-h] [-l] [-m\fInumber\fP] [-v] inputfile outputfile .SH DESCRIPTION .I aelflod converts an absolute ack.out file into a simple binary memory @@ -11,6 +11,32 @@ dump wrapped up in an ELF executable. It is suitable for producing executables for operating systems such as Linux. .PP +.I aelflod +accepts the following flags: +.TP +.BI \-a number +Set the ABI in the ELF header to \fInumber\fP. +The default value is \fI3\fP for Linux. +.TP +.B \-b +Write a big-endian ELF file. +.TP +.B \-h +Print a help message and exit. +.TP +.B \-l +Write a little-endian ELF file. +This is the default. +.TP +.BI \-m number +Set the machine type in the ELF header to \fInumber\fP. +The default value is \fI3\fP for Intel 386 (i386). +Other values are \fI4\fP for Motorola 68000 (m68k) +and \fI20\fP for PowerPC. +.TP +.B \-v +Be verbose. +.PP The input file must contain exactly four segments: TEXT, ROM, DATA and BSS, in that order, all occupying contiguous memory. The file must have all references resolved and be linked to a @@ -18,10 +44,15 @@ fixed address. The fixed address must be at least 0x54 bytes greater than a page boundary, in order to make room for the ELF header itself. .PP -aelflod will write out an ELF header followed by each segment, in -order, ensuring that enough padding is inserted between each segment +.I aelflod +will write out an ELF header followed by each segment, in order, +ensuring that enough padding is inserted between each segment to keep the offsets correct. -The created executable will contain just one rwx segment, and no -sections. +The created executable will contain just one ELF segment mapped rwx. +.PP +If the input file has symbols, then +.I aelflod +will convert the symbol table to ELF. +The output file has ELF section headers if and only if it has symbols. .SH "SEE ALSO" ack.out(5) From 3cdceaa7003ce3b72c5b751490d50c536c630567 Mon Sep 17 00:00:00 2001 From: David Given Date: Wed, 28 Dec 2016 17:30:14 +0000 Subject: [PATCH 078/173] Merge in B changes. --- plat/osx386/descr | 10 +++++----- plat/osxppc/descr | 10 +++++----- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/plat/osx386/descr b/plat/osx386/descr index a6f021878..45595e252 100644 --- a/plat/osx386/descr +++ b/plat/osx386/descr @@ -55,16 +55,16 @@ name led 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}:.ocm.bas.b.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) \ + (.b:{TAIL}={PLATFORMDIR}/libb.a) \ + (.bas:{TAIL}={PLATFORMDIR}/libbasic.a) \ (.mod:{TAIL}={PLATFORMDIR}/libmodula2.a) \ (.ocm:{TAIL}={PLATFORMDIR}/liboccam.a) \ - (.ocm.b.mod.c.p:{TAIL}={PLATFORMDIR}/libc.a) \ + (.p:{TAIL}={PLATFORMDIR}/libpascal.a) \ + (.ocm.bas.mod.b.c.p:{TAIL}={PLATFORMDIR}/libc.a) \ {FLOATS?} \ (.e:{TAIL}={PLATFORMDIR}/libem.a \ {PLATFORMDIR}/libsys.a \ diff --git a/plat/osxppc/descr b/plat/osxppc/descr index f659ff0ef..7fde17035 100644 --- a/plat/osxppc/descr +++ b/plat/osxppc/descr @@ -60,16 +60,16 @@ name led 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}:.ocm.bas.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) \ + (.b:{TAIL}={PLATFORMDIR}/libb.a) \ + (.bas:{TAIL}={PLATFORMDIR}/libbasic.a) \ (.mod:{TAIL}={PLATFORMDIR}/libmodula2.a) \ (.ocm:{TAIL}={PLATFORMDIR}/liboccam.a) \ - (.ocm.b.mod.c.p:{TAIL}={PLATFORMDIR}/libc.a) \ + (.p:{TAIL}={PLATFORMDIR}/libpascal.a) \ + (.ocm.bas.mod.b.c.p:{TAIL}={PLATFORMDIR}/libc.a) \ {FLOATS?} \ (.e:{TAIL}={PLATFORMDIR}/libem.a \ {PLATFORMDIR}/libsys.a \ From 49dd5724ca3c0116ce213d08ce894620a570be72 Mon Sep 17 00:00:00 2001 From: David Given Date: Wed, 28 Dec 2016 19:16:15 +0000 Subject: [PATCH 079/173] Correctly export PREFIX to the Lua build system. --- Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/Makefile b/Makefile index 4399f0c28..59b4e1a57 100644 --- a/Makefile +++ b/Makefile @@ -96,6 +96,7 @@ $(BUILDDIR)/build.$(BUILDSYSTEM): first/ackbuilder.lua Makefile $(BUILD_FILES) $ INSDIR=$(INSDIR) \ PLATIND=$(PLATIND) \ PLATDEP=$(PLATDEP) \ + PREFIX=$(PREFIX) \ AR=$(AR) \ CC=$(CC) \ > $(BUILDDIR)/build.$(BUILDSYSTEM) From 52f82a76b6a9997964ae4021da35f80f7acefefd Mon Sep 17 00:00:00 2001 From: David Given Date: Wed, 28 Dec 2016 23:49:55 +0000 Subject: [PATCH 080/173] Don't crash when using the -u option to enter undefined symbols. --- util/led/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/util/led/main.c b/util/led/main.c index 4ea0b0d05..028bc3b3f 100644 --- a/util/led/main.c +++ b/util/led/main.c @@ -328,7 +328,7 @@ makename(string) { static struct outname namebuf; - namebuf.on_mptr = string; + namebuf.on_foff = string - core_position - mems[ALLOMODL].mem_base; namebuf.on_type = S_UND + S_EXT; namebuf.on_valu = (long)0; From e3f8fb84dc34b270b61179f7cd54166824b58bf9 Mon Sep 17 00:00:00 2001 From: David Given Date: Thu, 29 Dec 2016 17:08:53 +0000 Subject: [PATCH 081/173] Change the i80 assembler to be three-pass, which allows forward references; required for assembling B. --- mach/i80/as/mach0.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/mach/i80/as/mach0.c b/mach/i80/as/mach0.c index 2249df643..e5a7e88ec 100644 --- a/mach/i80/as/mach0.c +++ b/mach/i80/as/mach0.c @@ -9,3 +9,5 @@ */ #define LISTING #define RELOCATION +#define THREE_PASS + From ebd424e7f10113d6d7214bf8825fc03ee7246cf6 Mon Sep 17 00:00:00 2001 From: David Given Date: Thu, 29 Dec 2016 17:10:21 +0000 Subject: [PATCH 082/173] First draft of the B module code; a module name can now be specified as a compiler flag, which is used to set the name of the patch table. The compiler now understands C preprocessor line directives. Extend the standard library somewhat. --- lang/b/compiler/b.h | 3 + lang/b/compiler/b0.c | 36 ++++++++-- lang/b/compiler/build.lua | 1 + lang/b/lib/b.h | 3 + lang/b/lib/main.c | 139 ++++++++++++++++++++++++++++++++++++-- 5 files changed, 170 insertions(+), 12 deletions(-) diff --git a/lang/b/compiler/b.h b/lang/b/compiler/b.h index 61548b6e8..acfb4a966 100644 --- a/lang/b/compiler/b.h +++ b/lang/b/compiler/b.h @@ -4,6 +4,7 @@ #include #include #include +#include "astring.h" #define NCPS 8 /* chars per symbol */ #define HSHSIZ 400 /* hash table size */ @@ -40,6 +41,7 @@ struct swtab { }; extern int wordsize; +extern const char* modulename; int paramsize; struct hshtab hshtab[HSHSIZ]; int hshused; @@ -89,6 +91,7 @@ char* manglename(char* name, char prefix); #define RPARN 7 #define COLON 8 #define COMMA 9 +#define HASH 10 #define MCALL 15 #define CALL 16 diff --git a/lang/b/compiler/b0.c b/lang/b/compiler/b0.c index d0ea69826..3d87774a2 100644 --- a/lang/b/compiler/b0.c +++ b/lang/b/compiler/b0.c @@ -14,6 +14,7 @@ int contlab = -1; int brklab = -1; int wordsize = 4; +const char* modulename = "b_module_main"; int bsymb_part; int code_part; int string_part; @@ -38,7 +39,7 @@ main(int argc, char *argv[]) { for (;;) { - int opt = getopt(argc, argv, "-w:i:o:"); + int opt = getopt(argc, argv, "-w:B:i:o:"); if (opt == -1) break; @@ -47,6 +48,10 @@ main(int argc, char *argv[]) wordsize = atoi(optarg); break; + case 'B': + modulename = aprintf("b_module_%s", optarg); + break; + case 'i': if (freopen(optarg, "r", stdin) == NULL) { error("Can't find %s", optarg); @@ -62,7 +67,7 @@ main(int argc, char *argv[]) break; derfault: - error("Usage: em_b [-w wordsize] [-i inputfile] [-o outputfile]"); + error("Usage: em_b [-w wordsize] [-B modulename] [-i inputfile] [-o outputfile]"); exit(1); } } @@ -97,8 +102,8 @@ main(int argc, char *argv[]) if (string_part) C_insertpart(string_part); - C_exa_dnam("bsymb_patch_table"); - C_df_dnam("bsymb_patch_table"); + C_exa_dnam((char*) modulename); + C_df_dnam((char*) modulename); if (bsymb_part) C_insertpart(bsymb_part); C_rom_cst(0); @@ -340,11 +345,30 @@ loop: case NEWLN: line++; - + /* fall through */ case SPACE: c = getchar(); goto loop; + case HASH: + /* # is invalid in B; but we handle it out of convenience so that we can read + * in input files that have been run through the C preprocessor. Ideally we + * should only recognise it when it's the first character in a line, but as + * it's not used anywhere else we can get away with recognising it anywhere. + */ + + while ((c = getchar()) == ' ') + ; + + peekc = c; + getnum(); + line = cval; + + while ((c = getchar()) != '\n') + ; + + goto loop; + case PLUS: return subseq(c,PLUS,INCBEF); @@ -1242,7 +1266,7 @@ char ctab[128] = { LETTER, SPACE, NEWLN, SPACE, SPACE, UNKN, UNKN, UNKN, UNKN, UNKN, UNKN, UNKN, UNKN, UNKN, UNKN, UNKN, UNKN, UNKN, UNKN, UNKN, UNKN, UNKN, UNKN, UNKN, - SPACE, EXCLA, DQUOTE, UNKN, UNKN, MOD, AND, SQUOTE, + SPACE, EXCLA, DQUOTE, HASH, UNKN, MOD, AND, SQUOTE, LPARN, RPARN, TIMES, PLUS, COMMA, MINUS, UNKN, DIVIDE, DIGIT, DIGIT, DIGIT, DIGIT, DIGIT, DIGIT, DIGIT, DIGIT, DIGIT, DIGIT, COLON, SEMI, LESS, ASSIGN, GREAT, QUEST, diff --git a/lang/b/compiler/build.lua b/lang/b/compiler/build.lua index 82095a683..27564280d 100644 --- a/lang/b/compiler/build.lua +++ b/lang/b/compiler/build.lua @@ -8,6 +8,7 @@ cprogram { "./*.h", "modules+headers", "modules/src/alloc+lib", + "modules/src/data+lib", "modules/src/em_code+lib_k", "modules/src/em_data+lib", "modules/src/em_mes+lib", diff --git a/lang/b/lib/b.h b/lang/b/lib/b.h index 123eabc58..571c1794b 100644 --- a/lang/b/lib/b.h +++ b/lang/b/lib/b.h @@ -14,6 +14,9 @@ #error Unsupported EM_PSIZE #endif +extern FILE* input_unit; extern FILE* output_unit; +#define END 4 + #endif diff --git a/lang/b/lib/main.c b/lang/b/lib/main.c index 9b868bada..404e1fd9d 100644 --- a/lang/b/lib/main.c +++ b/lang/b/lib/main.c @@ -1,8 +1,12 @@ #include "b.h" +#include +#include +#include -extern uintptr_t* bsymb_patch_table[]; +extern uintptr_t* b_module_main[]; extern intptr_t i_main(intptr_t argc, const char* argv[]); +FILE* input_unit; FILE* output_unit; static intptr_t i_char(intptr_t s, intptr_t n) @@ -19,7 +23,7 @@ static void i_lchar(intptr_t s, intptr_t n, intptr_t c) static intptr_t i_getchar(void) { - return fgetc(output_unit); + return fgetc(input_unit); } static intptr_t i_putchar(intptr_t c) @@ -28,17 +32,139 @@ static intptr_t i_putchar(intptr_t c) return c; } +static intptr_t i_putstr(intptr_t s) +{ + char* p = (char*)(s< 0); + + do + fputc(s[--i], output_unit); + while (i > 0); +} + +static void i_printf(intptr_t s, ...) +{ + char* p = (char*)(s< Date: Thu, 29 Dec 2016 17:11:07 +0000 Subject: [PATCH 083/173] Build the B compiler and standard library (also the Basic one, which was missing). --- plat/build.lua | 3 +++ 1 file changed, 3 insertions(+) diff --git a/plat/build.lua b/plat/build.lua index a8d1684bb..dc0821f26 100644 --- a/plat/build.lua +++ b/plat/build.lua @@ -15,6 +15,8 @@ definerule("ackfile", name = e.name, srcs = e.srcs, deps = { + "lang/b/compiler+pkg", + "lang/basic/src+pkg", "lang/cem/cemcom.ansi+pkg", "lang/cem/cpp.ansi+pkg", "lang/m2/comp+pkg", @@ -100,6 +102,7 @@ definerule("build_plat_libs", return installable { name = e.name, map = { + "lang/b/lib+pkg_"..e.plat, "lang/basic/lib+pkg_"..e.plat, "lang/cem/libcc.ansi+pkg_"..e.plat, "lang/m2/libm2+pkg_"..e.plat, From 0e10329876bd28e8b1e3e9b5645084c97d10b3ae Mon Sep 17 00:00:00 2001 From: David Given Date: Thu, 29 Dec 2016 17:11:53 +0000 Subject: [PATCH 084/173] Fix an issue throughout where B couldn't be built by ackprogram due to symbol laziness. --- plat/cpm/descr | 1 + plat/linux386/descr | 1 + plat/linux68k/descr | 1 + plat/linuxppc/descr | 1 + plat/osx386/descr | 1 + plat/osxppc/descr | 3 ++- plat/pc86/descr | 1 + plat/qemuppc/descr | 1 + plat/rpi/descr | 1 + 9 files changed, 10 insertions(+), 1 deletion(-) diff --git a/plat/cpm/descr b/plat/cpm/descr index d178b46c5..d084f89ea 100644 --- a/plat/cpm/descr +++ b/plat/cpm/descr @@ -60,6 +60,7 @@ name led mapflag -i SEPID=-b1:0 mapflag -fp FLOATS={EM}/{ILIB}fp args {ALIGN} {SEPID?} \ + ({RTS}:.b=-u _i_main) \ (.e:{HEAD}={PLATFORMDIR}/boot.o) \ ({RTS}:.ocm.bas.b={PLATFORMDIR}/c-ansi.o) \ ({RTS}:.c={PLATFORMDIR}/c-ansi.o) \ diff --git a/plat/linux386/descr b/plat/linux386/descr index 7dbeec738..1888e4182 100644 --- a/plat/linux386/descr +++ b/plat/linux386/descr @@ -56,6 +56,7 @@ name led mapflag -l* LNAME={PLATFORMDIR}/lib* mapflag -fp FLOATS={EM}/{LIB}fp args {ALIGN} {SEPID?} \ + ({RTS}:.b=-u _i_main) \ (.e:{HEAD}={PLATFORMDIR}/boot.o) \ ({RTS}:.ocm.bas.b={PLATFORMDIR}/c-ansi.o) \ ({RTS}:.c={PLATFORMDIR}/c-ansi.o) \ diff --git a/plat/linux68k/descr b/plat/linux68k/descr index 5fbe16a38..1e3b6a5bd 100644 --- a/plat/linux68k/descr +++ b/plat/linux68k/descr @@ -56,6 +56,7 @@ name led mapflag -l* LNAME={PLATFORMDIR}/lib* mapflag -fp FLOATS={EM}/{LIB}fp args {ALIGN} {SEPID?} \ + ({RTS}:.b=-u _i_main) \ (.e:{HEAD}={PLATFORMDIR}/boot.o) \ ({RTS}:.ocm.bas.b={PLATFORMDIR}/c-ansi.o) \ ({RTS}:.c={PLATFORMDIR}/c-ansi.o) \ diff --git a/plat/linuxppc/descr b/plat/linuxppc/descr index 51121278d..ced1de4b1 100644 --- a/plat/linuxppc/descr +++ b/plat/linuxppc/descr @@ -62,6 +62,7 @@ name led mapflag -l* LNAME={PLATFORMDIR}/lib* mapflag -fp FLOATS={EM}/{LIB}fp args {ALIGN} {SEPID?} \ + ({RTS}:.b=-u _i_main) \ (.e:{HEAD}={PLATFORMDIR}/boot.o) \ ({RTS}:.ocm.bas.b={PLATFORMDIR}/c-ansi.o) \ ({RTS}:.c={PLATFORMDIR}/c-ansi.o) \ diff --git a/plat/osx386/descr b/plat/osx386/descr index 45595e252..afe46c588 100644 --- a/plat/osx386/descr +++ b/plat/osx386/descr @@ -54,6 +54,7 @@ name led mapflag -l* LNAME={PLATFORMDIR}/lib* mapflag -fp FLOATS={EM}/{LIB}fp args {ALIGN} {SEPID?} \ + ({RTS}:.b=-u _i_main) \ (.e:{HEAD}={PLATFORMDIR}/boot.o) \ ({RTS}:.ocm.bas.b.c={PLATFORMDIR}/c-ansi.o) \ ({RTS}:.mod={PLATFORMDIR}/modula2.o) \ diff --git a/plat/osxppc/descr b/plat/osxppc/descr index 7fde17035..5f416c44c 100644 --- a/plat/osxppc/descr +++ b/plat/osxppc/descr @@ -59,8 +59,9 @@ name led mapflag -l* LNAME={PLATFORMDIR}/lib* mapflag -fp FLOATS={EM}/{LIB}fp args {ALIGN} {SEPID?} \ + ({RTS}:.b=-u _i_main) \ (.e:{HEAD}={PLATFORMDIR}/boot.o) \ - ({RTS}:.ocm.bas.c={PLATFORMDIR}/c-ansi.o) \ + ({RTS}:.ocm.bas.b.c={PLATFORMDIR}/c-ansi.o) \ ({RTS}:.mod={PLATFORMDIR}/modula2.o) \ ({RTS}:.p={PLATFORMDIR}/pascal.o) \ -o > < \ diff --git a/plat/pc86/descr b/plat/pc86/descr index 578ac292c..6a0db9e19 100644 --- a/plat/pc86/descr +++ b/plat/pc86/descr @@ -52,6 +52,7 @@ name led mapflag -i SEPID=-b1:0 mapflag -fp FLOATS={EM}/{ILIB}fp args {ALIGN} {SEPID?} \ + ({RTS}:.b=-u _i_main) \ (.e:{HEAD}={PLATFORMDIR}/boot.o) \ ({RTS}:.ocm.bas.b={PLATFORMDIR}/c-ansi.o) \ ({RTS}:.c={PLATFORMDIR}/c-ansi.o) \ diff --git a/plat/qemuppc/descr b/plat/qemuppc/descr index 2027b613c..f5191b249 100644 --- a/plat/qemuppc/descr +++ b/plat/qemuppc/descr @@ -62,6 +62,7 @@ name led mapflag -l* LNAME={PLATFORMDIR}/lib* mapflag -fp FLOATS={EM}/{LIB}fp args {ALIGN} {SEPID?} \ + ({RTS}:.b=-u _i_main) \ (.e:{HEAD}={PLATFORMDIR}/boot.o) \ ({RTS}:.ocm.bas.b={PLATFORMDIR}/c-ansi.o) \ ({RTS}:.c={PLATFORMDIR}/c-ansi.o) \ diff --git a/plat/rpi/descr b/plat/rpi/descr index 76c3f4707..43d3256a3 100644 --- a/plat/rpi/descr +++ b/plat/rpi/descr @@ -51,6 +51,7 @@ name led mapflag -i SEPID=-b1:0 mapflag -fp FLOATS={EM}/{ILIB}fp args {ALIGN} {SEPID?} \ + ({RTS}:.b=-u _i_main) \ (.e:{HEAD}={PLATFORMDIR}/boot.o) \ ({RTS}:.ocm.bas.b={PLATFORMDIR}/c-ansi.o) \ ({RTS}:.c={PLATFORMDIR}/c-ansi.o) \ From 4e68af9781013f05c57c05dbcb98fffb2d90151c Mon Sep 17 00:00:00 2001 From: David Given Date: Thu, 29 Dec 2016 17:12:40 +0000 Subject: [PATCH 085/173] Add a declaration for the -Bxyz module name flag, used by the B compiler. Rename some of the Basic flags to avoid confusion. --- lib/descr/fe | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/lib/descr/fe b/lib/descr/fe index 874e2901c..5149fd0eb 100644 --- a/lib/descr/fe +++ b/lib/descr/fe @@ -157,12 +157,12 @@ name basic from .bas to .k program {EM}/lib/ack/em_bem - mapflag -h ABC_F={ABC_F?} -h - mapflag -w ABC_F={ABC_F?} -w - mapflag -L ABC_F={ABC_F?} -L - mapflag -E ABC_F={ABC_F?} -E -# mapflag -d ABC_F={ABC_F?} -d - args -Vw{w}p{p}f{d} {ABC_F?} < > {SOURCE} + mapflag -h BASIC_F={BASIC_F?} -h + mapflag -w BASIC_F={BASIC_F?} -w + mapflag -L BASIC_F={BASIC_F?} -L + mapflag -E BASIC_F={BASIC_F?} -E +# mapflag -d BASIC_F={BASIC_F?} -d + args -Vw{w}p{p}f{d} {BASIC_F?} < > {SOURCE} prep cond rts .bas need .bas @@ -184,6 +184,7 @@ name b from .b to .k program {EM}/lib/ack/em_b + mapflag -B* ABC_F={ABC_F?} -B* args -i < -o > -w {p} prep cond rts .b From e460adc9238ed9cac20e1fd5c5288717857a1300 Mon Sep 17 00:00:00 2001 From: David Given Date: Thu, 29 Dec 2016 17:20:51 +0000 Subject: [PATCH 086/173] Add a B version of the hilo program. --- examples/build.lua | 1 + examples/hilo.b | 108 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 109 insertions(+) create mode 100644 examples/hilo.b diff --git a/examples/build.lua b/examples/build.lua index bf73cc044..fced8e299 100644 --- a/examples/build.lua +++ b/examples/build.lua @@ -5,6 +5,7 @@ local conly = { } local sourcefiles = filenamesof( + "./hilo.b", "./hilo.bas", "./hilo.c", "./hilo.mod", diff --git a/examples/hilo.b b/examples/hilo.b new file mode 100644 index 000000000..818d1fb12 --- /dev/null +++ b/examples/hilo.b @@ -0,0 +1,108 @@ +# + +buffer[6]; +PlayerName[6]; + +/* Taken intact from the B reference manual. */ +strcopy(sl ,s2) +{ + auto i; + + i = 0; + while (lchar(sl, i, char(s2, i)) != '*e') + i++; +} + +reads() +{ + extrn buffer; + + putstr("> "); + flush(); + getstr(buffer); +} + +atoi(s) +{ + auto value, sign, i, c; + + i = 0; + if (char(s, i) == '-') + { + sign = -1; + i++; + } + else + sign = 1; + + value = 0; + while ((c = char(s, i++)) != '*e') + value = value*10 + (c - '0'); + + return(value * sign); +} + +rand() +{ + /* Genuinely random; retrieved from random.org */ + return(57); +} + +game() +{ + extrn buffer; + auto Number, Attempts; + auto guess; + + printf("See if you can guess my number.*n"); + + Number = rand() % 100; + Attempts = 1; + + while (1) + { + reads(); + guess = atoi(buffer); + + if (guess == Number) + { + printf("*nYou got it right in only %d %s!*n", Attempts, + (Attempts == 1) ? "go" : "goes"); + return; + } + + if (guess < Number) + printf("*nTry a bit higher.*n"); + if (guess > Number) + printf("*nTry a bit lower.*n"); + Attempts++; + } +} + +main() +{ + extrn buffer, PlayerName; + + printf("*nHi there! I'm written in B. Before we start, what is your name?*n"); + reads(); + strcopy(PlayerName, buffer); + printf("*nHello, %s! ", PlayerName); + + while (1) + { + game(); + printf("*nWould you like another go?*n"); + reads(); + + if ((char(buffer, 0) == 'n') | (char(buffer, 0) == 'N')) + { + printf("*nThanks for playing --- goodbye!*n"); + break; + } + + printf("*nExcellent! "); + } + + return(0); +} + From 462529a7d238b635361e478c7851fca084ac1176 Mon Sep 17 00:00:00 2001 From: David Given Date: Thu, 29 Dec 2016 17:30:47 +0000 Subject: [PATCH 087/173] Trying to install openbios-ppc causes Travis to error out now (not sure why). --- .travis.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 765b5cea1..f06e5aca3 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,7 +6,6 @@ addons: apt: packages: - ed - - openbios-ppc - qemu-user git: From fa02a855e84968ae60dbb7993178cc222bf040f8 Mon Sep 17 00:00:00 2001 From: David Given Date: Sat, 31 Dec 2016 00:14:04 +0000 Subject: [PATCH 088/173] Fix issue where !x was actually calculating !!x. --- lang/b/compiler/b1.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lang/b/compiler/b1.c b/lang/b/compiler/b1.c index 30ce5c7f7..e959e797b 100644 --- a/lang/b/compiler/b1.c +++ b/lang/b/compiler/b1.c @@ -291,7 +291,7 @@ rcexpr(struct tnode *tr) case EXCLA: rcexpr(tr->tr1); - C_tne(); + C_teq(); return; case NEG: From c3e1ef1064f1ff682e1cf80bb382a8211a06af61 Mon Sep 17 00:00:00 2001 From: David Given Date: Sat, 31 Dec 2016 00:14:28 +0000 Subject: [PATCH 089/173] B patch table names shouldn't be in the B symbol namespace. --- lang/b/compiler/b0.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lang/b/compiler/b0.c b/lang/b/compiler/b0.c index 3d87774a2..f42298d33 100644 --- a/lang/b/compiler/b0.c +++ b/lang/b/compiler/b0.c @@ -14,7 +14,7 @@ int contlab = -1; int brklab = -1; int wordsize = 4; -const char* modulename = "b_module_main"; +const char* modulename = "bmodule_main"; int bsymb_part; int code_part; int string_part; @@ -49,7 +49,7 @@ main(int argc, char *argv[]) break; case 'B': - modulename = aprintf("b_module_%s", optarg); + modulename = aprintf("bmodule_%s", optarg); break; case 'i': From 803b81e3f4aca291ef937174d9033bc30f32e78c Mon Sep 17 00:00:00 2001 From: David Given Date: Sat, 31 Dec 2016 17:36:12 +0000 Subject: [PATCH 090/173] Add support for the xor operator. --- lang/b/compiler/b.h | 10 ++++++---- lang/b/compiler/b0.c | 22 +++++++++++++++------- lang/b/compiler/b1.c | 6 ++++++ 3 files changed, 27 insertions(+), 11 deletions(-) diff --git a/lang/b/compiler/b.h b/lang/b/compiler/b.h index acfb4a966..3da667be6 100644 --- a/lang/b/compiler/b.h +++ b/lang/b/compiler/b.h @@ -120,6 +120,7 @@ char* manglename(char* name, char prefix); #define LESS 42 #define GREATEQ 43 #define GREAT 44 +#define EOR 45 #define ASSIGN 49 #define ASPLUS 50 @@ -137,11 +138,12 @@ char* manglename(char* name, char prefix); #define ASLESS 62 #define ASGTQ 63 #define ASGREAT 64 +#define ASEOR 65 -#define CON 65 -#define STRING 66 -#define NAME 67 -#define KEYW 68 +#define CON 70 +#define STRING 71 +#define NAME 72 +#define KEYW 73 #define SQUOTE 121 #define DQUOTE 122 diff --git a/lang/b/compiler/b0.c b/lang/b/compiler/b0.c index f42298d33..03123ecdd 100644 --- a/lang/b/compiler/b0.c +++ b/lang/b/compiler/b0.c @@ -393,7 +393,7 @@ loop: if (ctab[peekc = spnextchar()] == LETTER) return ASSIGN; c = symbol(); - if (PLUS <= c && c <= GREAT) + if (PLUS <= c && c <= EOR) return c + ASPLUS-PLUS; if (c == ASSIGN) return EQUAL; @@ -1236,7 +1236,7 @@ int opdope[] = { 024005, /* < */ 024005, /* >= */ 024005, /* > */ - 000000, /* 45 */ + 017005, /* ^ */ 000000, /* 46 */ 000000, /* 47 */ 000000, /* 48 */ @@ -1256,6 +1256,11 @@ int opdope[] = { 012213, /* =< */ 012213, /* =>= */ 012213, /* => */ + 012213, /* =^ */ + 000000, /* 66 */ + 000000, /* 67 */ + 000000, /* 68 */ + 000000, /* 69 */ 000000, /* CON */ 000000, /* STRING */ 000000 /* NAME */ @@ -1273,7 +1278,7 @@ char ctab[128] = { UNKN, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, - LETTER, LETTER, LETTER, LBRACK, UNKN, RBRACK, UNKN, LETTER, + LETTER, LETTER, LETTER, LBRACK, UNKN, RBRACK, EOR, LETTER, UNKN, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, @@ -1294,6 +1299,7 @@ void printtoken(int tok, FILE *out) strtab[7] = "RPARN"; strtab[8] = "COLON"; strtab[9] = "COMMA"; + strtab[10] = "HASH"; strtab[15] = "MCALL"; strtab[16] = "CALL"; @@ -1322,6 +1328,7 @@ void printtoken(int tok, FILE *out) strtab[42] = "LESS"; strtab[43] = "GREATEQ"; strtab[44] = "GREAT"; + strtab[45] = "EOR"; strtab[49] = "ASSIGN"; strtab[50] = "ASPLUS"; @@ -1339,11 +1346,12 @@ void printtoken(int tok, FILE *out) strtab[62] = "ASLESS"; strtab[63] = "ASGTQ"; strtab[64] = "ASGREAT"; + strtab[65] = "ASEOR"; - strtab[65] = "CON"; - strtab[66] = "STRING"; - strtab[67] = "NAME"; - strtab[68] = "KEYW"; + strtab[70] = "CON"; + strtab[71] = "STRING"; + strtab[72] = "NAME"; + strtab[73] = "KEYW"; strtab[127] = "UNKN"; diff --git a/lang/b/compiler/b1.c b/lang/b/compiler/b1.c index e959e797b..19dc17a68 100644 --- a/lang/b/compiler/b1.c +++ b/lang/b/compiler/b1.c @@ -142,6 +142,7 @@ lvalexp(struct tnode *tr) case ASLESS: case ASGTQ: case ASGREAT: + case ASEOR: tr->op -= ASPLUS-PLUS; rcexpr(block(ASSIGN,0,tr->tr1,tr)); return; @@ -249,6 +250,11 @@ rcexpr(struct tnode *tr) C_ior(wordsize); return; + case EOR: + binary(tr); + C_xor(wordsize); + return; + case LSHIFT: binary(tr); C_sli(wordsize); From 1beedca590e3ba7cdb494d87860be7007f7ff8be Mon Sep 17 00:00:00 2001 From: David Given Date: Sat, 31 Dec 2016 17:38:52 +0000 Subject: [PATCH 091/173] Add support for B tests; add a test for the B operators (finding several compiler bugs in the process). --- tests/plat/b/operators_b.b | 57 ++++++++++++++++++++++++++++++++++++++ tests/plat/build.lua | 12 +++++--- tests/plat/lib/test_b.c | 34 +++++++++++++++++++++++ 3 files changed, 99 insertions(+), 4 deletions(-) create mode 100644 tests/plat/b/operators_b.b create mode 100644 tests/plat/lib/test_b.c diff --git a/tests/plat/b/operators_b.b b/tests/plat/b/operators_b.b new file mode 100644 index 000000000..5a4c1d91f --- /dev/null +++ b/tests/plat/b/operators_b.b @@ -0,0 +1,57 @@ +# +zero 0; +one 1; +two 2; + +main() +{ + extrn zero, one, two; + auto i; + + if (!((two + two) == 4)) fail(__LINE__); + if (!((two - two) == 0)) fail(__LINE__); + if (!((two * two) == 4)) fail(__LINE__); + if (!((two / two) == 1)) fail(__LINE__); + if (!((two % two) == 0)) fail(__LINE__); + + if (!(zero == zero)) fail(__LINE__); + if (!(zero != one)) fail(__LINE__); + if (!(zero < one)) fail(__LINE__); + if (!(zero <= one)) fail(__LINE__); + if (!(zero <= zero)) fail(__LINE__); + if (!(one > zero)) fail(__LINE__); + if (!(one >= zero)) fail(__LINE__); + if (!(one >= one)) fail(__LINE__); + + if (!((one << 1) == 2)) fail(__LINE__); + if (!((two >> 1) == 1)) fail(__LINE__); + + if (!((two & 1) == 0)) fail(__LINE__); + if (!((two | 1) == 3)) fail(__LINE__); + if (!((two ^ 2) == 0)) fail(__LINE__); + + i = 2; i =+ two; if (!(i == 4)) fail(__LINE__); + i = 2; i =- two; if (!(i == 0)) fail(__LINE__); + i = 2; i =* two; if (!(i == 4)) fail(__LINE__); + i = 2; i =/ two; if (!(i == 1)) fail(__LINE__); + i = 2; i =% two; if (!(i == 0)) fail(__LINE__); + + i = zero; i === zero; if (!i) fail(__LINE__); + i = zero; i =!= one; if (!i) fail(__LINE__); + i = zero; i =< one; if (!i) fail(__LINE__); + i = zero; i =<= one; if (!i) fail(__LINE__); + i = zero; i =<= zero; if (!i) fail(__LINE__); + i = one; i => zero; if (!i) fail(__LINE__); + i = one; i =>= zero; if (!i) fail(__LINE__); + i = one; i =>= one; if (!i) fail(__LINE__); + + i = one; i =<< one; if (!(i == 2)) fail(__LINE__); + i = two; i =>> one; if (!(i == 1)) fail(__LINE__); + + i = two; i =& 1; if (!(i == 0)) fail(__LINE__); + i = two; i =| 1; if (!(i == 3)) fail(__LINE__); + i = two; i =^ 2; if (!(i == 0)) fail(__LINE__); + + finished(); +} + diff --git a/tests/plat/build.lua b/tests/plat/build.lua index 3f43fb95b..b689ea5f6 100644 --- a/tests/plat/build.lua +++ b/tests/plat/build.lua @@ -12,12 +12,16 @@ definerule("plat_testsuite", "tests/plat/*.c", "tests/plat/*.e", "tests/plat/*.p", + "tests/plat/b/*.b", "tests/plat/bugs/*.mod" ) acklibrary { name = "lib", - srcs = { "tests/plat/lib/test.c" }, + srcs = { + "tests/plat/lib/test.c", + "tests/plat/lib/test_b.c", + }, hdrs = { "tests/plat/lib/test.h", "tests/plat/lib/Test.def" @@ -40,7 +44,7 @@ definerule("plat_testsuite", vars = { plat = e.plat, lang = lang, - ackcflags = "-O0" + ackcflags = "-O0 -Bmain" } } @@ -53,7 +57,7 @@ definerule("plat_testsuite", "util/build+testrunner" }, commands = { - "(%{ins[2]} "..e.method.." %{ins[1]} 5 %{ins[3]} || echo FAILED) > %{outs}", + "(%{ins[2]} "..e.method.." %{ins[1]} 5 %{ins[3]} || echo @@FAIL) > %{outs}", } } end @@ -63,4 +67,4 @@ definerule("plat_testsuite", srcs = tests, } end -) \ No newline at end of file +) diff --git a/tests/plat/lib/test_b.c b/tests/plat/lib/test_b.c new file mode 100644 index 000000000..b2173b4f3 --- /dev/null +++ b/tests/plat/lib/test_b.c @@ -0,0 +1,34 @@ +#include +#include "test.h" + +extern void patch_addresses(uintptr_t* module); +extern uintptr_t* bmodule_main; + +static void i_writehex(intptr_t code) +{ + writehex(code); +} + +static void i_fail(intptr_t code) +{ + fail(code); +} + +uintptr_t b_finished = (uintptr_t)&finished; +uintptr_t b_writehex = (uintptr_t)&i_writehex; +uintptr_t b_fail = (uintptr_t)&i_fail; + +static uintptr_t* bmodule_test[] = +{ + &b_finished, + &b_writehex, + &b_fail, + 0 +}; + +void binit(void) +{ + patch_addresses(&bmodule_test); + patch_addresses(&bmodule_main); +} + From a01523a89378036da8390dc99699056f4f954436 Mon Sep 17 00:00:00 2001 From: David Given Date: Sat, 31 Dec 2016 17:39:51 +0000 Subject: [PATCH 092/173] Allow programs to override binit() (so they can register their own modules). --- lang/b/lib/b.h | 6 ++++++ lang/b/lib/init.c | 10 ++++++++++ lang/b/lib/main.c | 9 ++++----- 3 files changed, 20 insertions(+), 5 deletions(-) create mode 100644 lang/b/lib/init.c diff --git a/lang/b/lib/b.h b/lang/b/lib/b.h index 571c1794b..1125452cd 100644 --- a/lang/b/lib/b.h +++ b/lang/b/lib/b.h @@ -19,4 +19,10 @@ extern FILE* output_unit; #define END 4 +extern uintptr_t* bmodule_main[]; + +extern void patch_addresses(uintptr_t** p); + +extern void binit(void); + #endif diff --git a/lang/b/lib/init.c b/lang/b/lib/init.c new file mode 100644 index 000000000..b7ad01f08 --- /dev/null +++ b/lang/b/lib/init.c @@ -0,0 +1,10 @@ +#include "b.h" +#include +#include +#include + +void binit(void) +{ + patch_addresses(bmodule_main); +} + diff --git a/lang/b/lib/main.c b/lang/b/lib/main.c index 404e1fd9d..b583a4309 100644 --- a/lang/b/lib/main.c +++ b/lang/b/lib/main.c @@ -3,7 +3,6 @@ #include #include -extern uintptr_t* b_module_main[]; extern intptr_t i_main(intptr_t argc, const char* argv[]); FILE* input_unit; @@ -155,7 +154,7 @@ uintptr_t b_getstr = (uintptr_t)i_getstr; uintptr_t b_flush = (uintptr_t)i_flush; uintptr_t b_printf = (uintptr_t)i_printf; -static uintptr_t* b_module_stdlib[] = +static uintptr_t* bmodule_stdlib[] = { &b_char, &b_lchar, @@ -168,7 +167,7 @@ static uintptr_t* b_module_stdlib[] = 0 }; -static void patch_addresses(uintptr_t** p) +void patch_addresses(uintptr_t** p) { while (*p) { @@ -179,8 +178,8 @@ static void patch_addresses(uintptr_t** p) int main(int argc, const char* argv[]) { - patch_addresses(b_module_main); - patch_addresses(b_module_stdlib); + patch_addresses(bmodule_stdlib); + binit(); input_unit = stdin; output_unit = stdout; return i_main(argc, NULL); From b1576e2c7737d55340fb64bac3df04dce35bbd12 Mon Sep 17 00:00:00 2001 From: David Given Date: Sat, 31 Dec 2016 19:43:03 +0000 Subject: [PATCH 093/173] Add support for negative constants in external initialisers. --- lang/b/compiler/b0.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/lang/b/compiler/b0.c b/lang/b/compiler/b0.c index 03123ecdd..e6845bea0 100644 --- a/lang/b/compiler/b0.c +++ b/lang/b/compiler/b0.c @@ -373,7 +373,15 @@ loop: return subseq(c,PLUS,INCBEF); case MINUS: - return subseq(c,MINUS,DECBEF); + /* avoid peeking a name, which could overwrite + * an already set bsym. */ + if (ctab[peekc = spnextchar()] == DIGIT) { + getnum(); + cval = -cval; + return CON; + } else { + return subseq(c,MINUS,DECBEF); + } case LESS: if (subseq(c,0,1)) From 374e7a1c57ec44a98ad1e9df2291b6638c54efa0 Mon Sep 17 00:00:00 2001 From: David Given Date: Sun, 1 Jan 2017 17:40:06 +0000 Subject: [PATCH 094/173] Add support for the ~ operator. --- lang/b/compiler/b.h | 1 + lang/b/compiler/b0.c | 6 ++++-- lang/b/compiler/b1.c | 5 +++++ 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/lang/b/compiler/b.h b/lang/b/compiler/b.h index 3da667be6..f5a11fd2a 100644 --- a/lang/b/compiler/b.h +++ b/lang/b/compiler/b.h @@ -104,6 +104,7 @@ char* manglename(char* name, char prefix); #define AMPER 23 #define STAR 24 #define QUEST 25 +#define NOT 26 #define PLUS 30 #define MINUS 31 diff --git a/lang/b/compiler/b0.c b/lang/b/compiler/b0.c index e6845bea0..cb28a6a3c 100644 --- a/lang/b/compiler/b0.c +++ b/lang/b/compiler/b0.c @@ -1060,6 +1060,7 @@ tand: goto oponst; case EXCLA: + case NOT: if (andflg) goto syntax; goto oponst; @@ -1225,7 +1226,7 @@ int opdope[] = { 034200, /* &un */ 034200, /* *un */ 014201, /* ? */ - 000000, /* 26 */ + 034200, /* ~un */ 000000, /* 27 */ 000000, /* 28 */ 000000, /* 29 */ @@ -1290,7 +1291,7 @@ char ctab[128] = { UNKN, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, - LETTER, LETTER, LETTER, LBRACE, OR, RBRACE, UNKN, UNKN + LETTER, LETTER, LETTER, LBRACE, OR, RBRACE, NOT, UNKN }; /* debug function */ @@ -1320,6 +1321,7 @@ void printtoken(int tok, FILE *out) strtab[23] = "AMPER"; strtab[24] = "STAR"; strtab[25] = "QUEST"; + strtab[26] = "NOT"; strtab[30] = "PLUS"; strtab[31] = "MINUS"; diff --git a/lang/b/compiler/b1.c b/lang/b/compiler/b1.c index 19dc17a68..cc08d21ca 100644 --- a/lang/b/compiler/b1.c +++ b/lang/b/compiler/b1.c @@ -305,6 +305,11 @@ rcexpr(struct tnode *tr) C_ngi(wordsize); return; + case NOT: + rcexpr(tr->tr1); + C_com(wordsize); + return; + case QUEST: cbranch(tr->tr1, o1=isn++); rcexpr(tr->tr2->tr1); From be909fe0450a3165d3458feed7dd5679546ded35 Mon Sep 17 00:00:00 2001 From: David Given Date: Sun, 1 Jan 2017 17:44:03 +0000 Subject: [PATCH 095/173] Add tests for more operators. --- tests/plat/b/operators_b.b | 30 ++++++++++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/tests/plat/b/operators_b.b b/tests/plat/b/operators_b.b index 5a4c1d91f..796b82906 100644 --- a/tests/plat/b/operators_b.b +++ b/tests/plat/b/operators_b.b @@ -1,12 +1,19 @@ # +minusone -1; zero 0; one 1; two 2; main() { - extrn zero, one, two; - auto i; + extrn minusone, zero, one, two; + auto i, j; + + if (!(-one == -1)) fail(__LINE__); + if (!(!one == 0)) fail(__LINE__); + if (!(!zero == 1)) fail(__LINE__); + if (!(~zero == -1)) fail(__LINE__); + if (!(~minusone == 0)) fail(__LINE__); if (!((two + two) == 4)) fail(__LINE__); if (!((two - two) == 0)) fail(__LINE__); @@ -52,6 +59,25 @@ main() i = two; i =| 1; if (!(i == 3)) fail(__LINE__); i = two; i =^ 2; if (!(i == 0)) fail(__LINE__); + if (!(one ? 1 : 0)) fail(__LINE__); + if (!(zero ? 0 : 1)) fail(__LINE__); + + i = 0; + if (!(i++ == 0)) fail(__LINE__); + if (!(i == 1)) fail(__LINE__); + + i == 1; + if (!(i-- == 1)) fail(__LINE__); + if (!(i == 0)) fail(__LINE__); + + i = 0; + if (!(++i == 1)) fail(__LINE__); + if (!(i == 1)) fail(__LINE__); + + i == 1; + if (!(--i == 0)) fail(__LINE__); + if (!(i == 0)) fail(__LINE__); + finished(); } From 049aff9f33c4be93aa32085c924e118ff84c4d94 Mon Sep 17 00:00:00 2001 From: David Given Date: Sun, 1 Jan 2017 17:44:55 +0000 Subject: [PATCH 096/173] Remove the negative-constant code from the compiler; I think it's going to break a=-1 (with no spaces). Backed out changeset dead3363ac7d. --- lang/b/compiler/b0.c | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/lang/b/compiler/b0.c b/lang/b/compiler/b0.c index cb28a6a3c..16fbee167 100644 --- a/lang/b/compiler/b0.c +++ b/lang/b/compiler/b0.c @@ -373,15 +373,7 @@ loop: return subseq(c,PLUS,INCBEF); case MINUS: - /* avoid peeking a name, which could overwrite - * an already set bsym. */ - if (ctab[peekc = spnextchar()] == DIGIT) { - getnum(); - cval = -cval; - return CON; - } else { - return subseq(c,MINUS,DECBEF); - } + return subseq(c,MINUS,DECBEF); case LESS: if (subseq(c,0,1)) From 8b8910595a4f1652265737a0d8efd931c3e7d201 Mon Sep 17 00:00:00 2001 From: David Given Date: Sun, 1 Jan 2017 17:56:53 +0000 Subject: [PATCH 097/173] Add proper support for negative constants in external initialisers. --- lang/b/compiler/b0.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/lang/b/compiler/b0.c b/lang/b/compiler/b0.c index 16fbee167..a668724ce 100644 --- a/lang/b/compiler/b0.c +++ b/lang/b/compiler/b0.c @@ -542,6 +542,7 @@ extdef(void) int o, dim, i; char *bs; char *ms; + int neg; if ((o = symbol()) == EOFC || o == SEMI) return; @@ -549,6 +550,7 @@ extdef(void) goto syntax; bs = bsym->name; i = dim = 0; + neg = 0; switch(o = symbol()) { case SEMI: @@ -560,9 +562,16 @@ extdef(void) /* init */ case CON: case STRING: + case MINUS: global(bs); if (o == STRING) bsymb(bs); + else if (o == MINUS) { + o = symbol(); + if (o != CON) + goto syntax; + cval = -cval; + } C_df_dnam(manglename(bs, 'b')); pushsym(o); goto init; From 62bc2ab97a2628bca6c6c812c94e7b4e0bbbfd20 Mon Sep 17 00:00:00 2001 From: David Given Date: Sun, 1 Jan 2017 23:28:41 +0000 Subject: [PATCH 098/173] Jump tables for switch now go in ROM (required by the EM spec). Forward gotos now work. --- lang/b/compiler/b0.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/lang/b/compiler/b0.c b/lang/b/compiler/b0.c index a668724ce..7ae35239b 100644 --- a/lang/b/compiler/b0.c +++ b/lang/b/compiler/b0.c @@ -759,13 +759,13 @@ pswitch(void) deflab = brklab; C_df_dlb(swlab); - C_con_ilb(deflab); - C_con_cst(swp - sswp); + C_rom_ilb(deflab); + C_rom_cst(swp - sswp); while (swp > sswp && swp > swtab) { --swp; - C_con_cst(swp->swval); - C_con_ilb(swp->swlab); + C_rom_cst(swp->swval); + C_rom_ilb(swp->swlab); } C_df_ilb(brklab); @@ -812,6 +812,8 @@ stmt: case GOTO: if ((o = symbol()) != NAME) goto syntax; + if (bsym->offset == 0) + bsym->offset = isn++; jump(bsym->offset); goto semi; @@ -913,7 +915,8 @@ stmt: goto stmt; } bsym->class = INTERN; - bsym->offset = isn++; + if (bsym->offset == 0) + bsym->offset = isn++; fnlabel(bsym->offset); goto stmt; } From e2751f76b5d655110a242f7b8c799c21bda670bb Mon Sep 17 00:00:00 2001 From: David Given Date: Sun, 1 Jan 2017 23:51:48 +0000 Subject: [PATCH 099/173] Add a control flow test. --- tests/plat/b/control_b.b | 107 +++++++++++++++++++++++++++++++++++++ tests/plat/b/operators_b.b | 1 + 2 files changed, 108 insertions(+) create mode 100644 tests/plat/b/control_b.b diff --git a/tests/plat/b/control_b.b b/tests/plat/b/control_b.b new file mode 100644 index 000000000..a31b9d380 --- /dev/null +++ b/tests/plat/b/control_b.b @@ -0,0 +1,107 @@ +# +zero 0; +one 1; + +if_t() +{ + extrn zero, one; + auto fails, successes; + + successes = 0; + + if (zero) + fail(__LINE__); + + if (zero) + fail(__LINE__); + else + successes++; + + if (one) + successes++; + + if (one) + successes++; + else + fail(__LINE__); + + if (successes != 3) + fail(__LINE__); +} + +while_t() +{ + extrn zero, one; + auto successes, count; + + successes = 3; + count = 0; + while (count) + { + successes++; + count--; + } + if (successes != 3) + fail(__LINE__); + + while (zero) + fail(__LINE__); + + while (one) + { + break; + fail(__LINE__); + } +} + +sdata(n) +{ + switch (n) + { + case 0: return(0); + case 1: return(1); + case 100: return(100); + default: return(-1); + } +} + +switch_t() +{ + extrn zero; + auto successes; + + if (!(sdata(-1) == -1)) fail(__LINE__); + if (!(sdata(0) == 0)) fail(__LINE__); + if (!(sdata(1) == 1)) fail(__LINE__); + if (!(sdata(2) == -1)) fail(__LINE__); + if (!(sdata(100) == 100)) fail(__LINE__); + if (!(sdata(200) == -1)) fail(__LINE__); + + successes = 0; + switch (zero) + { + case 0: /* fall through */ + case 1: successes++; break; + } + if (successes != 1) + fail(__LINE__); +} + +goto_t() +{ + goto n; + fail(__LINE__); + n:; +} + +main() +{ + if_t(); + switch_t(); + goto_t(); + while_t(); + + finished(); + return(0); +} + diff --git a/tests/plat/b/operators_b.b b/tests/plat/b/operators_b.b index 796b82906..36b4b742a 100644 --- a/tests/plat/b/operators_b.b +++ b/tests/plat/b/operators_b.b @@ -79,5 +79,6 @@ main() if (!(i == 0)) fail(__LINE__); finished(); + return(0); } From aeb9d4952d4f72f6341c487d66d8d4e8ebf3a889 Mon Sep 17 00:00:00 2001 From: David Given Date: Tue, 3 Jan 2017 18:54:13 +0000 Subject: [PATCH 100/173] Added an abmodules tool which detects B modules and generates an initialiser function for them (in C, unfortunately). --- util/amisc/abmodules.1 | 27 ++++++ util/amisc/abmodules.c | 216 +++++++++++++++++++++++++++++++++++++++++ util/amisc/build.lua | 5 + 3 files changed, 248 insertions(+) create mode 100644 util/amisc/abmodules.1 create mode 100644 util/amisc/abmodules.c diff --git a/util/amisc/abmodules.1 b/util/amisc/abmodules.1 new file mode 100644 index 000000000..8d34871f0 --- /dev/null +++ b/util/amisc/abmodules.1 @@ -0,0 +1,27 @@ +.TH ABMODULES 1 +.SH NAME +abmodules \- find B modules + +.SH SYNOPSIS +abmodules [ \-o outputfile.c ] [ file ... ] + +.SH DESCRIPTION +.I abmodules +finds B modules in a set of ack.out(5) format object files, and either lists +them or generates a C file which initialises the modules. +.PP +This tool is used for multiple compilation of B programs; B modules must be +initiaised before use, and this tool generates the initialisation code for +programs containing an abitrary number of modules. See em_b(6) for details. +.PP +Options are: +.TP +.B \-o filename +Write C source to +.I filename +containing a definition of a binit() function which will initalise all modules +found. If not present, a simple list of module names is written to stdout +instead. + +.SH SEE ALSO +ack.out(5), em_b(6) diff --git a/util/amisc/abmodules.c b/util/amisc/abmodules.c new file mode 100644 index 000000000..e1190c207 --- /dev/null +++ b/util/amisc/abmodules.c @@ -0,0 +1,216 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "out.h" +#include "arch.h" +#include "ranlib.h" +#include "object.h" +#include "diagnostics.h" +#include "stringlist.h" + +int numsort_flg; +int sectsort_flg; +int undef_flg; +int revsort_flg = 1; +int globl_flg; +int nosort_flg; +int arch_flg; +int prep_flg; +int read_error; +struct outsect sbuf; +long off; +long s_base[S_MAX]; /* for specially encoded bases */ +char *filename; +int narg; + +extern int rd_unsigned2(); + +static const char prefix[] = "_bmodule_"; + +static struct stringlist modules; + +static void do_file(int fd) +{ + struct outhead hbuf; + struct outname *nbufp = NULL; + char *cbufp; + long fi_to_co; + long n; + unsigned readcount; + int i,j; + int compare(); + + read_error = 0; + rd_fdopen(fd); + + rd_ohead(&hbuf); + if (BADMAGIC(hbuf)) + return; + + n = hbuf.oh_nname; + if (n == 0) + fatal("%s --- no name list", filename); + + if (hbuf.oh_nchar == 0) + fatal("%s --- no names", filename); + + if ((readcount = hbuf.oh_nchar) != hbuf.oh_nchar) + fatal("%s --- string area too big", filename); + + cbufp = calloc(readcount, 1); + rd_string(cbufp, hbuf.oh_nchar); + if (read_error) + goto corrupt; + + fi_to_co = (long) (cbufp - OFF_CHAR(hbuf)); + while (--n >= 0) + { + struct outname nbuf; + struct stringfragment* f; + + rd_name(&nbuf, 1); + if (read_error) + goto corrupt; + + if (!(nbuf.on_type & S_EXT)) + continue; + if ((nbuf.on_type & S_TYP) == S_UND) + continue; + + if (nbuf.on_foff == 0) + nbuf.on_mptr = 0; + else + nbuf.on_mptr = (char *) (nbuf.on_foff + fi_to_co); + + if (strlen(nbuf.on_mptr) <= sizeof(prefix)) + continue; + if (memcmp(nbuf.on_mptr, prefix, sizeof(prefix)-1) != 0) + continue; + + stringlist_add(&modules, strdup(nbuf.on_mptr + sizeof(prefix) - 1)); + } + + if (cbufp) + free(cbufp); + + return; +corrupt: + fatal("%s --- corrupt", filename); +} + +static void process(int fd) +{ + uint16_t magic = rd_unsigned2(fd); + switch(magic) { + case O_MAGIC: + lseek(fd, 0L, 0); + do_file(fd); + break; + + case ARMAG: + case AALMAG: + { + struct ar_hdr archive_header; + static char buf[sizeof(archive_header.ar_name)+1]; + + while (rd_arhdr(fd, &archive_header)) + { + long nextpos = lseek(fd, 0L, SEEK_CUR) + archive_header.ar_size; + if (nextpos & 1) + nextpos++; + + strncpy(buf, archive_header.ar_name, sizeof(archive_header.ar_name)); + filename = buf; + if (strcmp(filename, SYMDEF) != 0) + do_file(fd); + lseek(fd, nextpos, 0); + } + break; + } + + default: + fatal("file %s is of unknown format", filename); + } +} + +int main(int argc, char* const argv[]) +{ + int opt; + FILE* outputfp = NULL; + + program_name = argv[0]; + for (;;) + { + int opt = getopt(argc, argv, "o:"); + if (opt == -1) + break; + + switch (opt) + { + case 'o': + outputfp = fopen(optarg, "w"); + if (!outputfp) + fatal("cannot open output file: %s", strerror(errno)); + break; + + default: + fatal("usage: abmodules [-o outputfile] [file...]"); + } + } + + for (;;) + { + int fd; + + filename = argv[optind++]; + if (!filename) + break; + if ((fd = open(filename, 0)) < 0) + fatal("cannot open %s: %s", filename, strerror(errno)); + process(fd); + close(fd); + } + + if (outputfp) + { + struct stringfragment* f; + + fprintf(outputfp, "#include \n"); + fprintf(outputfp, "\n"); + + for (f = modules.first; f; f = f->next) + fprintf(outputfp, "extern uintptr_t bmodule_%s[];\n", f->data); + + fprintf(outputfp, "\n"); + fprintf(outputfp, "extern void patch_addresses(uintptr_t* module);\n"); + fprintf(outputfp, "\n"); + fprintf(outputfp, "void binit(void) {\n"); + for (f = modules.first; f; f = f->next) + fprintf(outputfp, "\tpatch_addresses(bmodule_%s);\n", f->data); + fprintf(outputfp, "}\n"); + fclose(outputfp); + } + else + { + struct stringfragment* f; + + for (f = modules.first; f; f = f->next) + printf("%s\n", f->data); + } + + exit(0); +} + +void rd_fatal(void) +{ + fatal("read error on %s", filename); +} diff --git a/util/amisc/build.lua b/util/amisc/build.lua index d1b8a3356..1d856f197 100644 --- a/util/amisc/build.lua +++ b/util/amisc/build.lua @@ -4,7 +4,10 @@ local function simpleprogram(name) srcs = { "./"..name..".c" }, deps = { "h+emheaders", + "modules/src/alloc+lib", + "modules/src/data+lib", "modules/src/object+lib", + "modules/src/system+lib", } } @@ -17,6 +20,7 @@ local function simpleprogram(name) } end +simpleprogram("abmodules") simpleprogram("aelflod") simpleprogram("anm") simpleprogram("ashow") @@ -27,6 +31,7 @@ simpleprogram("astrip") installable { name = "pkg", map = { + "+abmodules-pkg", "+aelflod-pkg", "+anm-pkg", "+ashow-pkg", From 72766a02de34519bcb34d6028746ab224acd63a2 Mon Sep 17 00:00:00 2001 From: David Given Date: Wed, 4 Jan 2017 13:28:40 +0000 Subject: [PATCH 101/173] Fix typo in the descr file which was stopping -B from working. Add B documentation to the ack man page. --- lib/descr/fe | 2 +- util/ack/ack.1.X | 50 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 51 insertions(+), 1 deletion(-) diff --git a/lib/descr/fe b/lib/descr/fe index 5149fd0eb..04d33e4fa 100644 --- a/lib/descr/fe +++ b/lib/descr/fe @@ -185,7 +185,7 @@ name b to .k program {EM}/lib/ack/em_b mapflag -B* ABC_F={ABC_F?} -B* - args -i < -o > -w {p} + args -i < -o > -w {p} {ABC_F} prep cond rts .b need .b diff --git a/util/ack/ack.1.X b/util/ack/ack.1.X index cfa2d8072..671aa4e47 100644 --- a/util/ack/ack.1.X +++ b/util/ack/ack.1.X @@ -11,10 +11,13 @@ .. .TH ACK 1 "$Revision$" .ad + .SH NAME ack \- Amsterdam Compiler Kit + .SH SYNOPSIS \fBack\fP arguments + .SH DESCRIPTION This program transforms sources in several languages to load files for a variety of machines, @@ -50,6 +53,8 @@ but the following are recognized by most machines: Pascal program. .IP .c C module. +.IP .b +B module. .IP .bas Basic program. .IP .ocm @@ -140,6 +145,12 @@ is called and just before each return \fBprocexit\fP is called. These routines are supplied with one parameter, a pointer to a string containing the name of the routine. +.IP \-B\fIname\fP +Tells the B front end what the name of the module being compiled is, for use +with separate compilation. Defaults to +.I main +if not specified. See the section below on compiling B. + .IP \-O .IP \-O\fInum\fP .IP \-O\fIopt1,opt2,...\fP @@ -309,6 +320,7 @@ Sparc, Vax, Intel 80386. .PP All arguments without a suffix or with an unrecognized suffix are passed to the loaders, as for flags. + .SH PREPROCESSOR All C source programs are run through the preprocessor before they are fed to the compiler proper. @@ -336,6 +348,43 @@ As the ANSI C rules forbid this, in ANSI C, underscores are prepended to these names. .PP The default directories searched for include files differ for each machine. + +.SH COMPILING B + +B programs have special needs when compiled with the ACK. B modules have to be +initialised before use, to convert pointer addresses to word addresses; this is +done automatically when compiling a single B source file to an executable, but +must be done manually when using separate compilation. + +.PP +To do this, compile your B modules with the \fI-B\fP option as usual, and then +use the +.B abmodules +program to scan the object files and emit a C file which performs the +initialisation. Then compile this as well into an object file, and link the +whole lot together. The result will be a runnable executable. + +.PP +Beware --- referring to an uninitialised module will cause your program to +crash! + +.PP +The default initialiser in the B standard library looks for a module called +\fBmain\fP. + +.PP +For example: + +.nf +.sp +ack -c -mpc86 thismodule.b -Bthismodule +ack -c -mpc86 thatmodule.b -Bthatmodule +ack -c -mpc86 theothermodule.b -Btheothermodule +abmodules -o binit.c thismodule.o thatmodule.o theothermodule.o +ack -c -mpc86 binit.c +ack -mpc86 -o pc86.exe thismodule.o thatmodule.o theothermodule.o binit.o +.fi + .SH PROGRAMS \fIAck\fP uses one or more programs in each phase of the transformation. @@ -372,6 +421,7 @@ input:name:output:description \&.o:cv:a.out:Conversion from Ack object to machine object .TE .in -2 + .SH "ENVIRONMENT VARIABLES" .IP ACKDIR If set, this environment variable overrides ack's idea of its home From 24d26b2826e962450462a5fb871e45077ece8b42 Mon Sep 17 00:00:00 2001 From: Xin Wang Date: Fri, 6 Jan 2017 18:33:52 +0800 Subject: [PATCH 102/173] Add execve() system call for Linux --- plat/linux/libsys/execve.c | 7 +++++++ plat/linux386/include/unistd.h | 1 + plat/linuxppc/include/unistd.h | 1 + 3 files changed, 9 insertions(+) create mode 100644 plat/linux/libsys/execve.c diff --git a/plat/linux/libsys/execve.c b/plat/linux/libsys/execve.c new file mode 100644 index 000000000..d8f37b1cf --- /dev/null +++ b/plat/linux/libsys/execve.c @@ -0,0 +1,7 @@ +#include +#include "libsys.h" + +int execve(const char *path, char *const argv[], char *const envp[]) +{ + return _syscall(__NR_execve, (quad) path, (quad) argv, (quad) envp); +} diff --git a/plat/linux386/include/unistd.h b/plat/linux386/include/unistd.h index 35dc8dde7..5c6f31ef4 100644 --- a/plat/linux386/include/unistd.h +++ b/plat/linux386/include/unistd.h @@ -69,6 +69,7 @@ extern pid_t getpid(void); extern int brk(void* ptr); extern void* sbrk(int increment); extern int isatty(int d); +extern int execve(const char *path, char *const argv[], char *const envp[]); /* Signal handling */ diff --git a/plat/linuxppc/include/unistd.h b/plat/linuxppc/include/unistd.h index 307192f77..a31bd9f0d 100644 --- a/plat/linuxppc/include/unistd.h +++ b/plat/linuxppc/include/unistd.h @@ -67,6 +67,7 @@ extern pid_t getpid(void); extern int brk(void* ptr); extern void* sbrk(int increment); extern int isatty(int d); +extern int execve(const char *path, char *const argv[], char *const envp[]); /* Signal handling */ From 73922f1d165abbebbb5c6151c1c249b13da1a655 Mon Sep 17 00:00:00 2001 From: David Given Date: Fri, 6 Jan 2017 22:29:52 +0100 Subject: [PATCH 103/173] Ensure that procedure labels are word-aligned. --- mach/i386/ncg/mach.h | 1 + mach/i86/ncg/mach.h | 1 + 2 files changed, 2 insertions(+) diff --git a/mach/i386/ncg/mach.h b/mach/i386/ncg/mach.h index e58f4f423..f3075a37f 100644 --- a/mach/i386/ncg/mach.h +++ b/mach/i386/ncg/mach.h @@ -11,6 +11,7 @@ #define newilb(x) fprintf(codefile,"%s:\n",x) #define newdlb(x) fprintf(codefile,"%s:\n",x) +#define newplb(x) fprintf(codefile,".align 4\n%s:\n", x) #define dlbdlb(x,y) fprintf(codefile,"%s = %s\n",x,y) #define newlbss(l,x) fprintf(codefile,".comm %s,%ld\n",l,x); diff --git a/mach/i86/ncg/mach.h b/mach/i86/ncg/mach.h index 8f9f65938..ab5a0d156 100644 --- a/mach/i86/ncg/mach.h +++ b/mach/i86/ncg/mach.h @@ -11,6 +11,7 @@ #define newilb(x) fprintf(codefile,"%s:\n",x) #define newdlb(x) fprintf(codefile,"%s:\n",x) +#define newplb(x) fprintf(codefile,".align 2\n%s:\n", x) #define dlbdlb(x,y) fprintf(codefile,"%s = %s\n",x,y) #define newlbss(l,x) fprintf(codefile,".comm %s,%u\n",l,x); From 77fc62285d7dea942209b1e9c77e2b3872345bae Mon Sep 17 00:00:00 2001 From: David Given Date: Fri, 6 Jan 2017 23:24:05 +0100 Subject: [PATCH 104/173] Extern variables can now be written to. --- lang/b/compiler/b1.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lang/b/compiler/b1.c b/lang/b/compiler/b1.c index cc08d21ca..dd5570e0b 100644 --- a/lang/b/compiler/b1.c +++ b/lang/b/compiler/b1.c @@ -119,7 +119,7 @@ lvalexp(struct tnode *tr) } else { /* NAME */ bs = (struct hshtab *) tr->tr1->tr1; if (bs->class == EXTERN) { - C_ste_dnam(bs->name, 0); + C_ste_dnam(manglename(bs->name, 'b'), 0); } else if (bs->class == AUTO) { C_stl(bs->offset); } else From 0da248dced7b3fdf3062ba02b610bd0815b2f8c2 Mon Sep 17 00:00:00 2001 From: David Given Date: Sat, 7 Jan 2017 01:03:15 +0100 Subject: [PATCH 105/173] Use a better NOT; and after remembering that PowerPC bit numbers are all backwards in the documentation, rewrote IFEQ/IFLT/IFLE to actually work. Probably. Thanks to the B test suite for spotting this. --- mach/powerpc/mcg/table | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/mach/powerpc/mcg/table b/mach/powerpc/mcg/table index 8511dbb5b..b72990c36 100644 --- a/mach/powerpc/mcg/table +++ b/mach/powerpc/mcg/table @@ -572,26 +572,26 @@ PATTERNS out:(int)reg = IFEQ.I(in:(cr)cr) emit "mfcr %out" /* get cr0 */ - emit "rlwinm %out, %out, [32-2], 2, 31" /* extract just EQ */ + emit "rlwinm %out, %out, 3, 31, 31" /* extract just EQ */ cost 8; +#if 0 out:(int)reg = IFEQ.I(in:(int)reg) emit "cntlzw %out, %in" /* returns 0..32 */ - emit "rlwinm %out, %out, [32-5], 5, 31" /* if 32, return 1, otherwise 0 */ + emit "rlwinm %out, %out, [32-5], 31, 31" /* if 32, return 1, otherwise 0 */ cost 8; +#endif out:(int)reg = IFLT.I(in:(cr)cr) emit "mfcr %out" /* get cr0 */ - emit "andi. %out, %out, 1" /* leave just LT */ + emit "rlwinm %out, %out, 1, 31, 31" /* leave just LT */ cost 8; out:(int)reg = IFLE.I(in:(cr)cr) emit "mfcr %out" /* get cr0 */ - emit "andi. %out, %out, 5" /* leave just LT and EQ */ - emit "cntlzw %out, %out" /* returns 0..32 */ - emit "rlwinm %out, %out, [32-5], 5, 31" /* if 32, return 1, otherwise 0 */ + emit "rlwinm %out, %out, 2, 31, 31" /* leave just GT */ emit "xori %out, %out, 1" /* negate */ - cost 8; + cost 12; @@ -673,10 +673,9 @@ PATTERNS emit "neg %out, %left" cost 4; - out:(int)reg = NOT.I(left:(int)reg) - emit "cntlzw %out, %left" - emit "rlwinm %out, %out, 32-5, 5, 31" - cost 8; + out:(int)reg = NOT.I(in:(int)reg) + emit "nor %out, %in, %in" + cost 4; ALUR(AND.I, "and") ALUCC(AND.I, "andi.") From 7710c76d56d0614ae7d029ac19be9a2cef0c76d6 Mon Sep 17 00:00:00 2001 From: David Given Date: Sat, 7 Jan 2017 13:17:39 +0100 Subject: [PATCH 106/173] Introduce sequence points before store instructions to prevent loads from the same address being delayed until after the store (at which point they'll return the wrong value). --- mach/proto/mcg/treebuilder.c | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/mach/proto/mcg/treebuilder.c b/mach/proto/mcg/treebuilder.c index 2ead527fc..5b2a1b93d 100644 --- a/mach/proto/mcg/treebuilder.c +++ b/mach/proto/mcg/treebuilder.c @@ -119,6 +119,25 @@ static struct ir* appendir(struct ir* ir) return ir; } +static void sequence_point(void) +{ + int i; + + /* Ensures that any partially-evaluated expressions on the stack are executed right + * now. This typically needs to happen before store operations, to prevents loads of + * the same address being delayed until after the store (at which point they'll + * return incorrect values). + */ + + assert(current_bb != NULL); + + for (i=0; iirs, ir); + } +} + static void materialise_stack(void) { int i; @@ -229,6 +248,8 @@ static struct ir* store(int size, struct ir* address, int offset, struct ir* val { int opcode; + sequence_point(); + if (size == 1) { opcode = IR_STOREB; @@ -475,6 +496,7 @@ static void insn_simple(int opcode) case op_sim: { + sequence_point(); appendir( new_ir2( (EM_wordsize == 2) ? IR_STORE : IR_STOREH, EM_wordsize, @@ -1497,6 +1519,7 @@ static void insn_lvalue(int opcode, const char* label, arith offset) break; case op_ste: + sequence_point(); appendir( new_ir2( IR_STORE, EM_wordsize, @@ -1507,6 +1530,7 @@ static void insn_lvalue(int opcode, const char* label, arith offset) break; case op_sde: + sequence_point(); appendir( new_ir2( IR_STORE, EM_wordsize*2, @@ -1517,6 +1541,7 @@ static void insn_lvalue(int opcode, const char* label, arith offset) break; case op_zre: + sequence_point(); appendir( new_ir2( IR_STORE, EM_wordsize, @@ -1527,6 +1552,7 @@ static void insn_lvalue(int opcode, const char* label, arith offset) break; case op_ine: + sequence_point(); appendir( new_ir2( IR_STORE, EM_wordsize, @@ -1544,6 +1570,7 @@ static void insn_lvalue(int opcode, const char* label, arith offset) break; case op_dee: + sequence_point(); appendir( new_ir2( IR_STORE, EM_wordsize, From 6b4f8d72b826b5ec3c39b8878f6fd512a3f2b300 Mon Sep 17 00:00:00 2001 From: David Given Date: Sat, 7 Jan 2017 13:25:09 +0100 Subject: [PATCH 107/173] ine and ste are now declared to modify memory (preventing cached values being propagated across the modification). --- mach/powerpc/ncg/table | 2 ++ 1 file changed, 2 insertions(+) diff --git a/mach/powerpc/ncg/table b/mach/powerpc/ncg/table index adb0db2c8..52f335c3d 100644 --- a/mach/powerpc/ncg/table +++ b/mach/powerpc/ncg/table @@ -1073,6 +1073,7 @@ PATTERNS ste $1 pat ine /* Increment external */ + kills MEMORY uses REG={LABEL, $1}, REG gen lwz %b, {GPRINDIRECT, %a, 0} @@ -1080,6 +1081,7 @@ PATTERNS stw %b, {GPRINDIRECT, %a, 0} pat dee /* Decrement external */ + kills MEMORY uses REG={LABEL, $1}, REG gen lwz %b, {GPRINDIRECT, %a, 0} From 39215c131e39290009d4d76bcb8453372bd1f31d Mon Sep 17 00:00:00 2001 From: David Given Date: Sat, 7 Jan 2017 18:38:43 +0100 Subject: [PATCH 108/173] Moved the inc/dec operator tests into their own source file; more exhaustive testing. --- tests/plat/b/incdec_b.b | 77 ++++++++++++++++++++++++++++++++++++++ tests/plat/b/operators_b.b | 31 ++++----------- 2 files changed, 85 insertions(+), 23 deletions(-) create mode 100644 tests/plat/b/incdec_b.b diff --git a/tests/plat/b/incdec_b.b b/tests/plat/b/incdec_b.b new file mode 100644 index 000000000..b3cb16da5 --- /dev/null +++ b/tests/plat/b/incdec_b.b @@ -0,0 +1,77 @@ +# +i 0; + +ext_t() +{ + extrn i; + + i = 0; + if (!(i++ == 0)) fail(__LINE__); + + i == 1; + if (!(i-- == 1)) fail(__LINE__); + if (!(i == 0)) fail(__LINE__); + + i = 0; + if (!(++i == 1)) fail(__LINE__); + if (!(i == 1)) fail(__LINE__); + + i == 1; + if (!(--i == 0)) fail(__LINE__); + if (!(i == 0)) fail(__LINE__); +} + +int_t() +{ + auto i; + + i = 0; + if (!(i++ == 0)) fail(__LINE__); + + i == 1; + if (!(i-- == 1)) fail(__LINE__); + if (!(i == 0)) fail(__LINE__); + + i = 0; + if (!(++i == 1)) fail(__LINE__); + if (!(i == 1)) fail(__LINE__); + + i == 1; + if (!(--i == 0)) fail(__LINE__); + if (!(i == 0)) fail(__LINE__); +} + +star_t() +{ + extrn i; + auto p; + + p = &i; + + i = 0; + if (!((*p)++ == 0)) fail(__LINE__); + + i == 1; + if (!((*p)-- == 1)) fail(__LINE__); + if (!(i == 0)) fail(__LINE__); + + i = 0; + if (!(++(*p) == 1)) fail(__LINE__); + if (!(i == 1)) fail(__LINE__); + + i == 1; + if (!(--(*p) == 0)) fail(__LINE__); + if (!(i == 0)) fail(__LINE__); +} + +main() +{ + ext_t(); + int_t(); + star_t(); + + finished(); + return(0); +} + + diff --git a/tests/plat/b/operators_b.b b/tests/plat/b/operators_b.b index 36b4b742a..5baa674b1 100644 --- a/tests/plat/b/operators_b.b +++ b/tests/plat/b/operators_b.b @@ -9,18 +9,14 @@ main() extrn minusone, zero, one, two; auto i, j; + if (!(zero == 0)) fail(__LINE__); + if (!(one == 1)) fail(__LINE__); if (!(-one == -1)) fail(__LINE__); if (!(!one == 0)) fail(__LINE__); if (!(!zero == 1)) fail(__LINE__); if (!(~zero == -1)) fail(__LINE__); if (!(~minusone == 0)) fail(__LINE__); - if (!((two + two) == 4)) fail(__LINE__); - if (!((two - two) == 0)) fail(__LINE__); - if (!((two * two) == 4)) fail(__LINE__); - if (!((two / two) == 1)) fail(__LINE__); - if (!((two % two) == 0)) fail(__LINE__); - if (!(zero == zero)) fail(__LINE__); if (!(zero != one)) fail(__LINE__); if (!(zero < one)) fail(__LINE__); @@ -30,6 +26,12 @@ main() if (!(one >= zero)) fail(__LINE__); if (!(one >= one)) fail(__LINE__); + if (!((two + two) == 4)) fail(__LINE__); + if (!((two - two) == 0)) fail(__LINE__); + if (!((two * two) == 4)) fail(__LINE__); + if (!((two / two) == 1)) fail(__LINE__); + if (!((two % two) == 0)) fail(__LINE__); + if (!((one << 1) == 2)) fail(__LINE__); if (!((two >> 1) == 1)) fail(__LINE__); @@ -62,23 +64,6 @@ main() if (!(one ? 1 : 0)) fail(__LINE__); if (!(zero ? 0 : 1)) fail(__LINE__); - i = 0; - if (!(i++ == 0)) fail(__LINE__); - if (!(i == 1)) fail(__LINE__); - - i == 1; - if (!(i-- == 1)) fail(__LINE__); - if (!(i == 0)) fail(__LINE__); - - i = 0; - if (!(++i == 1)) fail(__LINE__); - if (!(i == 1)) fail(__LINE__); - - i == 1; - if (!(--i == 0)) fail(__LINE__); - if (!(i == 0)) fail(__LINE__); - finished(); return(0); } - From 5a38ce2a6920311015ee68303b3a6fb2ba724b2f Mon Sep 17 00:00:00 2001 From: David Given Date: Sat, 7 Jan 2017 18:46:03 +0100 Subject: [PATCH 109/173] Pre-and-post-modification operators now work substantially better (i.e., working). --- lang/b/compiler/b1.c | 93 +++++++++++++++++++++++++++++++++----------- 1 file changed, 70 insertions(+), 23 deletions(-) diff --git a/lang/b/compiler/b1.c b/lang/b/compiler/b1.c index dd5570e0b..ca5ae5593 100644 --- a/lang/b/compiler/b1.c +++ b/lang/b/compiler/b1.c @@ -80,33 +80,80 @@ lvalexp(struct tnode *tr) if (tr->tr1->op == STAR) { rcexpr(tr->tr1->tr1); tonativeaddr(); + + if ((tr->op == DECBEF) || (tr->op == INCBEF)) { + C_dup(wordsize); /* ( addr addr -- ) */ + C_loi(wordsize); /* ( addr val -- ) */ + if (tr->op == DECBEF) + C_dec(); /* ( addr newval -- ) */ + else + C_inc(); /* ( addr newval -- ) */ + C_exg(wordsize); /* ( newval addr -- ) */ + C_dup(wordsize*2); /* ( newval addr newval addr -- ) */ + C_sti(wordsize); /* ( newval addr -- ) */ + C_asp(wordsize); /* ( newval -- ) */ + } else { + C_dup(wordsize); /* ( addr addr -- ) */ + C_loi(wordsize); /* ( addr val -- ) */ + C_dup(wordsize*2); /* ( addr val addr val -- ) */ + if (tr->op == DECAFT) + C_dec(); /* ( addr val addr newval -- ) */ + else + C_inc(); /* ( addr val addr newval -- ) */ + C_exg(wordsize); /* ( addr val newval addr -- ) */ + C_sti(wordsize); /* ( addr val -- ) */ + C_exg(wordsize); /* ( val addr -- ) */ + C_asp(wordsize); /* ( val -- ) */ + } } else { /* NAME, checked in "build" */ bs = (struct hshtab *) tr->tr1->tr1; - if (bs->class == EXTERN) - C_lae_dnam(manglename(bs->name, 'b'), 0); - else if (bs->class == AUTO) - C_lal(bs->offset); - else + if (bs->class == EXTERN) { + switch (tr->op) { + case INCBEF: + C_ine_dnam(manglename(bs->name, 'b'), 0); + C_loe_dnam(manglename(bs->name, 'b'), 0); + break; + + case DECBEF: + C_dee_dnam(manglename(bs->name, 'b'), 0); + C_loe_dnam(manglename(bs->name, 'b'), 0); + break; + + case INCAFT: + C_loe_dnam(manglename(bs->name, 'b'), 0); + C_ine_dnam(manglename(bs->name, 'b'), 0); + break; + + case DECAFT: + C_loe_dnam(manglename(bs->name, 'b'), 0); + C_dee_dnam(manglename(bs->name, 'b'), 0); + break; + } + } else if (bs->class == AUTO) { + switch (tr->op) { + case INCBEF: + C_inl(bs->offset); + C_lol(bs->offset); + break; + + case DECBEF: + C_del(bs->offset); + C_lol(bs->offset); + break; + + case INCAFT: + C_lol(bs->offset); + C_inl(bs->offset); + break; + + case DECAFT: + C_lol(bs->offset); + C_del(bs->offset); + break; + } + } else goto classerror; } - if (tr->op == DECBEF || tr->op == INCBEF) { - C_dup(wordsize); /* ( addr addr -- ) */ - C_loi(wordsize); /* ( addr val -- ) */ - C_adp((tr->op == DECBEF) ? -1 : 1); /* ( addr newval -- ) */ - C_exg(wordsize); /* ( newval addr -- ) */ - C_dup(wordsize*2); /* ( newval addr newval addr -- ) */ - C_sti(wordsize); /* ( newval addr -- ) */ - C_asp(wordsize); /* ( newval -- ) */ - } else { - C_dup(wordsize); /* ( addr addr -- ) */ - C_loi(wordsize); /* ( addr val -- ) */ - C_exg(wordsize); /* ( val addr -- ) */ - C_dup(wordsize*2); /* ( val addr val addr -- ) */ - C_asp(wordsize); /* ( val addr val -- ) */ - C_adp((tr->op == DECAFT) ? -1 : 1); /* ( val addr newval -- ) */ - C_exg(wordsize); /* ( val newval addr -- ) */ - C_sti(wordsize); /* ( val -- ) */ - } return; case ASSIGN: From efab08178b6c224547694f5484602bc198555716 Mon Sep 17 00:00:00 2001 From: David Given Date: Sat, 7 Jan 2017 18:47:00 +0100 Subject: [PATCH 110/173] Fix a bunch of issues with pushing and popping mismatched sizes, which the B compiler does a lot; dup 8 for pairs of words is now optimised. --- mach/proto/mcg/treebuilder.c | 69 +++++++++++++++++++++++++----------- 1 file changed, 48 insertions(+), 21 deletions(-) diff --git a/mach/proto/mcg/treebuilder.c b/mach/proto/mcg/treebuilder.c index 5b2a1b93d..667562e8d 100644 --- a/mach/proto/mcg/treebuilder.c +++ b/mach/proto/mcg/treebuilder.c @@ -30,6 +30,18 @@ static void push(struct ir* ir) stack[stackptr++] = ir; } +/* Returns the size of the top item on the stack. */ +static int peek(int delta) +{ + if (stackptr <= delta) + return EM_wordsize; + else + { + struct ir* ir = stack[stackptr-1-delta]; + return ir->size; + } +} + static struct ir* pop(int size) { if (size < EM_wordsize) @@ -58,7 +70,6 @@ static struct ir* pop(int size) if (size < EM_wordsize) ir = convertu(ir, size); #endif - if (ir->size != size) { if ((size == (EM_wordsize*2)) && (ir->size == EM_wordsize)) @@ -875,17 +886,17 @@ static void insn_ivalue(int opcode, arith value) struct ir* ptr = pop(EM_pointersize); int offset = 0; - /* FIXME: this is awful; need a better way of dealing with - * non-standard EM sizes. */ if (value > (EM_wordsize*2)) + { + /* We're going to need to do multiple stores; fix the address + * so it'll go into a register and we can do maths on it. */ appendir(ptr); + } while (value > 0) { - int s; - if (value > (EM_wordsize*2)) - s = EM_wordsize*2; - else + int s = EM_wordsize*2; + if (value < s) s = value; push( @@ -934,24 +945,25 @@ static void insn_ivalue(int opcode, arith value) struct ir* ptr = pop(EM_pointersize); int offset = 0; - /* FIXME: this is awful; need a better way of dealing with - * non-standard EM sizes. */ - if (value > (EM_wordsize*2)) + if (value > peek(0)) + { + /* We're going to need to do multiple stores; fix the address + * so it'll go into a register and we can do maths on it. */ appendir(ptr); + } while (value > 0) { - int s; - if (value > (EM_wordsize*2)) - s = EM_wordsize*2; - else + struct ir* v = pop(peek(0)); + int s = v->size; + if (value < s) s = value; appendir( store( s, ptr, offset, - pop(s) + v ) ); @@ -1044,10 +1056,22 @@ static void insn_ivalue(int opcode, arith value) case op_dup: { - struct ir* v = pop(value); - appendir(v); - push(v); - push(v); + sequence_point(); + if ((value == (EM_wordsize*2)) && (peek(0) == EM_wordsize) && (peek(1) == EM_wordsize)) + { + struct ir* v1 = pop(EM_wordsize); + struct ir* v2 = pop(EM_wordsize); + push(v2); + push(v1); + push(v2); + push(v1); + } + else + { + struct ir* v = pop(value); + push(v); + push(v); + } break; } @@ -1077,8 +1101,11 @@ static void insn_ivalue(int opcode, arith value) default: while ((value > 0) && (stackptr > 0)) { - struct ir* ir = pop(stack[stackptr-1]->size); - value -= ir->size; + int s = peek(0); + if (s > value) + s = value; + pop(s); + value -= s; } if (value != 0) From abbead482a9f2ce84877b80c5a6a2859d52b0b76 Mon Sep 17 00:00:00 2001 From: David Given Date: Sat, 7 Jan 2017 18:47:46 +0100 Subject: [PATCH 111/173] Sections are now aligned (required by the EM spec). --- plat/pc86/descr | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plat/pc86/descr b/plat/pc86/descr index 6a0db9e19..9b54410ff 100644 --- a/plat/pc86/descr +++ b/plat/pc86/descr @@ -20,7 +20,7 @@ var ARCH=i86 var PLATFORM=pc86 var PLATFORMDIR={EM}/share/ack/{PLATFORM} var CPP_F=-D__unix -var ALIGN=-a0:1 -a1:1 -a2:1 -a3:1 +var ALIGN=-a0:2 -a1:2 -a2:2 -a3:2 var MACHOPT_F=-m8 var EGO_PLAT_FLAGS=-M{EM}/share/ack/ego/{ARCH}.descr From 837b9622fbf0f957fefbfa33cea8b1700952ba95 Mon Sep 17 00:00:00 2001 From: David Given Date: Sat, 7 Jan 2017 19:53:57 +0100 Subject: [PATCH 112/173] Make sure that constant folding doesn't render our tests trivial. --- tests/plat/b/incdec_b.b | 35 ++++++++++++++++++++--------------- 1 file changed, 20 insertions(+), 15 deletions(-) diff --git a/tests/plat/b/incdec_b.b b/tests/plat/b/incdec_b.b index b3cb16da5..4edf5f6bf 100644 --- a/tests/plat/b/incdec_b.b +++ b/tests/plat/b/incdec_b.b @@ -1,65 +1,70 @@ # +/* External variables to defeat constant folding. */ +zero 0; +one 1; + i 0; ext_t() { - extrn i; + extrn zero, one, i; - i = 0; + i = zero; if (!(i++ == 0)) fail(__LINE__); - i == 1; + i = one; if (!(i-- == 1)) fail(__LINE__); if (!(i == 0)) fail(__LINE__); - i = 0; + i = zero; if (!(++i == 1)) fail(__LINE__); if (!(i == 1)) fail(__LINE__); - i == 1; + i = one; if (!(--i == 0)) fail(__LINE__); if (!(i == 0)) fail(__LINE__); } int_t() { - auto i; + extrn zero, one; + auto i; - i = 0; + i = zero; if (!(i++ == 0)) fail(__LINE__); - i == 1; + i = one; if (!(i-- == 1)) fail(__LINE__); if (!(i == 0)) fail(__LINE__); - i = 0; + i = zero; if (!(++i == 1)) fail(__LINE__); if (!(i == 1)) fail(__LINE__); - i == 1; + i = one; if (!(--i == 0)) fail(__LINE__); if (!(i == 0)) fail(__LINE__); } star_t() { - extrn i; + extrn zero, one, i; auto p; p = &i; - i = 0; + i = zero; if (!((*p)++ == 0)) fail(__LINE__); - i == 1; + i = one; if (!((*p)-- == 1)) fail(__LINE__); if (!(i == 0)) fail(__LINE__); - i = 0; + i = zero; if (!(++(*p) == 1)) fail(__LINE__); if (!(i == 1)) fail(__LINE__); - i == 1; + i = one; if (!(--(*p) == 0)) fail(__LINE__); if (!(i == 0)) fail(__LINE__); } From a7fa54e4e0031a502ee7c8792b5e9ae470d784a6 Mon Sep 17 00:00:00 2001 From: David Given Date: Sat, 7 Jan 2017 20:11:01 +0100 Subject: [PATCH 113/173] Update the README. --- README | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/README b/README index 830c86cfc..d3273fc0b 100644 --- a/README +++ b/README @@ -2,7 +2,7 @@ =================================== © 1987-2005 Vrije Universiteit, Amsterdam - 2016-11-26 + 2017-01-07 INTRODUCTION @@ -25,7 +25,7 @@ SUPPORT Languages: -ANSI C, Pascal, Modula 2, Basic. K&R is supported via the ANSI C compiler. +ANSI C, B, Pascal, Modula 2, Basic. K&R is supported via the ANSI C compiler. Platforms: @@ -120,7 +120,8 @@ Some useful options include: ack figures out which language to use from the file extension: .c C (ANSI or K&R) - .b Basic + .b the PDP-11 dialect of B + .bas Basic .mod Modula-2 .ocm Occam 1 .p Pascal @@ -159,6 +160,10 @@ There are some things you should be aware of. - The ACK uses its own .o format. You won't be able to mix the ACK's object files and another compiler's. +- When compiling together multiple B source files, you need to do some extra + work to initialise them properly otherwise your program will crash on + startup; see the ack(1) and abmodules(1) man pages. + - The distribution contains *everything*, including the weird, ancient, archaic stuff that doesn't work any more and never will, such as the int EM interpreter and the assembler-linkers. Only some of it builds. Look for From 9945b019d2770e3a45da7402da3e4b91670b31e0 Mon Sep 17 00:00:00 2001 From: David Given Date: Sat, 7 Jan 2017 22:35:02 +0100 Subject: [PATCH 114/173] Add a B man page. --- lang/b/compiler/build.lua | 3 +- lang/b/compiler/em_b.6 | 68 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 70 insertions(+), 1 deletion(-) create mode 100644 lang/b/compiler/em_b.6 diff --git a/lang/b/compiler/build.lua b/lang/b/compiler/build.lua index 27564280d..6e2cc1820 100644 --- a/lang/b/compiler/build.lua +++ b/lang/b/compiler/build.lua @@ -21,7 +21,8 @@ cprogram { installable { name = "pkg", map = { - ["$(PLATDEP)/em_b"] = "+em_b" + ["$(PLATDEP)/em_b"] = "+em_b", + ["$(INSDIR)/share/man/man6/em_m2.6"] = "./em_b.6" } } diff --git a/lang/b/compiler/em_b.6 b/lang/b/compiler/em_b.6 new file mode 100644 index 000000000..e0d1b40fe --- /dev/null +++ b/lang/b/compiler/em_b.6 @@ -0,0 +1,68 @@ +.TH EM_B 6 +.ad + + +.SH NAME +em_b \- ACK B compiler + + +.SH SYNOPSIS +.B ~em/lib/ack/em_b +.RI [ options ] + + +.SH DESCRIPTION +.I em_b +is a port of the ABC B compiler to the ACK. Interested parties will be +interested in the upstream distribution here: + +.nf +.sp +https://github.com/aap/abc +.fi + +However, the version here has been heavily modified --- bug reports should be +filed with the ACK, not with the upstream compiler. + +.PP +Since B was designed for machines with word addressing, some hacking is +required to make it work on modern, byte addressed machines. The generated +code expects B variables to contain word addresses, and then generates +code to transform these into native addresses before use (which, +unfortunately, impacts performance). However, the ACK's linker doesn't know +how to emit word addresses into the program's data sections, and so a +separate fixup stage has to happen at runtime, just before \fBmain()\fP, +to convert the byte addresses into word addresses. + +.PP +The end result is that using multiple source files with B is somewhat +unwieldy, requiring each module to be explicitly named and then an extra +stage to generate the fixup code. See the \fBack\fP(1) and \fBabmodules\fP(1) +for details. + + +.SH OPTIONS + +.I em_b +accepts the following flags: + +.IP \-w\ \fIsize\fP +Sets the word size, used for scaling addresses. Usually either 2 or 4. + +.IP \-B\ \fIname\fP +Sets the name of the module currently being compiled (used to generate the +fixup table symbol name). Defaults to \fImain\fP if not specified. + +.IP \-i\ \fIfilename\fP +The source B file. + +.IP \-o\ \fIfilename\fP +The output compact EM bytecode file. + + + +.SH SEE ALSO +\fIack\fR(1), \fIabmodules\fR(1) + +.SH REMARKS +It is very unlikely the \fIem_b\fP will ever be useful for anything. From cca6171e5536195417bc3d0e887c1ec88424172d Mon Sep 17 00:00:00 2001 From: David Given Date: Sat, 7 Jan 2017 22:38:30 +0100 Subject: [PATCH 115/173] Properly install man pages. --- util/amisc/build.lua | 2 +- util/arch/build.lua | 2 +- util/misc/build.lua | 56 ++------------------------------------------ 3 files changed, 4 insertions(+), 56 deletions(-) diff --git a/util/amisc/build.lua b/util/amisc/build.lua index 1d856f197..22fa396cf 100644 --- a/util/amisc/build.lua +++ b/util/amisc/build.lua @@ -15,7 +15,7 @@ local function simpleprogram(name) name = name.."-pkg", map = { ["$(INSDIR)/bin/"..name] = "+"..name, - ["$(PLATIND)/man/man1/"..name..".1"] = "./"..name..".1", + ["$(INSDIR)/share/man/man1/"..name..".1"] = "./"..name..".1", } } end diff --git a/util/arch/build.lua b/util/arch/build.lua index 54b05f981..160b9c21f 100644 --- a/util/arch/build.lua +++ b/util/arch/build.lua @@ -17,6 +17,6 @@ installable { name = "pkg", map = { ["$(INSDIR)/bin/aal"] = "+aal", - ["$(PLATIND)/man/man1/aal.1"] = "./aal.1" + ["$(INSDIR)/share/man/man1/aal.1"] = "./aal.1" } } diff --git a/util/misc/build.lua b/util/misc/build.lua index dd207bbbc..e8dfbca33 100644 --- a/util/misc/build.lua +++ b/util/misc/build.lua @@ -41,59 +41,7 @@ installable { ["$(PLATDEP)/em_encode"] = "+encode", ["$(PLATDEP)/em_decode"] = "+decode", ["$(INSDIR)/bin/esize"] = "+esize", - ["$(PLATIND)/man/man1/esize.1"] = "./esize.1", - ["$(PLATIND)/man/man6/em_decode.6"] = "./em_decode.6" + ["$(INSDIR)/share/man/man1/esize.1"] = "./esize.1", + ["$(INSDIR)/share/man/man6/em_decode.6"] = "./em_decode.6" } } - ---[[ -D := util/misc - -define build-misc-impl - $(call reset) - $(call cfile, $D/esize.c) - $(call cprogram, $(BINDIR)/esize) - $(call installto, $(INSDIR)/bin/esize) - - $(call reset) - $(eval q := $D/esize.1) - $(call installto, $(INSDIR)/share/man/man1/esize.1) - - $(call reset) - $(eval objdir := encode) - $(call cfile, $D/convert.c) - $(eval $q: $(INCDIR)/em_comp.h $(INCDIR)/em_codeEK.h) - $(call rawfile, $(LIBREAD_EMEV)) - $(call rawfile, $(LIBEMK)) - $(call rawfile, $(LIBEM_DATA)) - $(call rawfile, $(LIBALLOC)) - $(call rawfile, $(LIBPRINT)) - $(call rawfile, $(LIBSTRING)) - $(call rawfile, $(LIBSYSTEM)) - $(call cprogram, $(BINDIR)/em_encode) - $(call installto, $(PLATDEP)/em_encode) - $(eval EM_ENCODE := $o) - $(eval ACK_CORE_TOOLS += $o) - - $(call reset) - $(eval objdir := decode) - $(call cfile, $D/convert.c) - $(eval $q: $(INCDIR)/em_comp.h $(INCDIR)/em_codeEK.h) - $(call rawfile, $(LIBREAD_EMKV)) - $(call rawfile, $(LIBEME)) - $(call rawfile, $(LIBEM_DATA)) - $(call rawfile, $(LIBALLOC)) - $(call rawfile, $(LIBPRINT)) - $(call rawfile, $(LIBSTRING)) - $(call rawfile, $(LIBSYSTEM)) - $(call cprogram, $(BINDIR)/em_decode) - $(call installto, $(PLATDEP)/em_decode) - $(eval EM_DECODE := $o) - - $(call reset) - $(eval q := $D/em_decode.6) - $(call installto, $(INSDIR)/share/man/man6/em_decode.6) -endef - -$(eval $(build-misc-impl)) ---]] From d50a6f99def1f1dcfe14da71e4ec7be56bbf2f3d Mon Sep 17 00:00:00 2001 From: David Given Date: Sat, 7 Jan 2017 22:56:00 +0100 Subject: [PATCH 116/173] Run through clang-format. --- lang/m2/comp/defmodule.c | 118 +++++++++++++++++++++------------------ 1 file changed, 64 insertions(+), 54 deletions(-) diff --git a/lang/m2/comp/defmodule.c b/lang/m2/comp/defmodule.c index f26168a28..a164c1939 100644 --- a/lang/m2/comp/defmodule.c +++ b/lang/m2/comp/defmodule.c @@ -9,48 +9,49 @@ /* $Id$ */ +#include "debug.h" #include "parameters.h" -#include "debug.h" +#include +#include +#include +#include #include -#include -#include -#include -#include -#include "idf.h" -#include "input.h" -#include "scope.h" -#include "LLlex.h" -#include "def.h" -#include "Lpars.h" -#include "f_info.h" -#include "main.h" -#include "node.h" -#include "type.h" -#include "misc.h" +#include "LLlex.h" +#include "Lpars.h" +#include "def.h" +#include "f_info.h" +#include "idf.h" +#include "input.h" +#include "main.h" +#include "misc.h" +#include "node.h" +#include "scope.h" +#include "type.h" #ifdef DEBUG -long sys_filesize(); +long sys_filesize(); #endif -t_idf *DefId; +t_idf* DefId; -char * -getwdir(fn) - register char *fn; +char* + getwdir(fn) register char* fn; { - register char *p; - char *strrchr(); + register char* p; + char* strrchr(); - while ((p = strrchr(fn,'/')) && *(p + 1) == '\0') { + while ((p = strrchr(fn, '/')) && *(p + 1) == '\0') + { /* remove trailing /'s */ *p = '\0'; } - if (p) { + if (p) + { *p = '\0'; - fn = Salloc(fn, (unsigned) (p - &fn[0] + 1)); + fn = Salloc(fn, (unsigned)(p - &fn[0] + 1)); *p = '/'; return fn; } @@ -58,8 +59,7 @@ getwdir(fn) } STATIC -GetFile(name) - char *name; +GetFile(name) char* name; { /* Try to find a file with basename "name" and extension ".def", in the directories mentioned in "DEFPATH". @@ -68,10 +68,11 @@ GetFile(name) char *strncpy(), *strcat(); strncpy(buf, name, 10); - buf[10] = '\0'; /* maximum length */ + buf[10] = '\0'; /* maximum length */ strcat(buf, ".def"); DEFPATH[0] = WorkingDir; - if (! InsertFile(buf, DEFPATH, &(FileName))) { + if (!InsertFile(buf, DEFPATH, &(FileName))) + { error("could not find a DEFINITION MODULE for \"%s\"", name); return 0; } @@ -81,25 +82,25 @@ GetFile(name) return 1; } -t_def * -GetDefinitionModule(id, incr) - register t_idf *id; +t_def* + GetDefinitionModule(id, incr) register t_idf* id; { /* Return a pointer to the "def" structure of the definition module indicated by "id". We may have to read the definition module itself. Also increment level by "incr". */ - register t_def *df; + register t_def* df; static int level; - t_scopelist *vis; - char *fn = FileName; + t_scopelist* vis; + char* fn = FileName; int ln = LineNumber; - t_scope *newsc; + t_scope* newsc; level += incr; df = lookup(id, GlobalScope, D_IMPORTED, 0); - if (!df) { + if (!df) + { /* Read definition module. Make an exception for SYSTEM. */ extern int ForeignFlag; @@ -110,53 +111,62 @@ GetDefinitionModule(id, incr) newsc = CurrentScope; vis = CurrVis; newsc->sc_defmodule = incr; - if (!strcmp(id->id_text, "SYSTEM")) { + if (!strcmp(id->id_text, "SYSTEM")) + { do_SYSTEM(); df = lookup(id, GlobalScope, D_IMPORTED, 0); } - else { - if (!is_anon_idf(id) && GetFile(id->id_text)) { + else + { + if (!is_anon_idf(id) && GetFile(id->id_text)) + { - char *f = FileName; + char* f = FileName; DefModule(); df = lookup(id, GlobalScope, D_IMPORTED, 0); - if (level == 1 && - (df && !(df->df_flags & D_FOREIGN))) { + if (level == 1 && (df && !(df->df_flags & D_FOREIGN))) + { /* The module is directly imported by the currently defined module, and is not foreign, so we have to remember its name because we have to call its initialization routine */ - static t_node *nd_end; - register t_node *n; - extern t_node *Modules; + static t_node* nd_end; + register t_node* n; + extern t_node* Modules; n = dot2leaf(Def); n->nd_def = newsc->sc_definedby; - if (nd_end) nd_end->nd_NEXT = n; - else Modules = n; + if (nd_end) + nd_end->nd_NEXT = n; + else + Modules = n; nd_end = n; } free(f); } - else { + else + { df = lookup(id, GlobalScope, D_IMPORTED, 0); newsc->sc_name = id->id_text; } } close_scope(SC_CHKFORW); - if (! df) { + if (!df) + { df = MkDef(id, GlobalScope, D_ERROR); df->mod_vis = vis; newsc->sc_definedby = df; } } - else if (df->df_flags & D_BUSY) { + else if (df->df_flags & D_BUSY) + { error("definition module \"%s\" depends on itself", - id->id_text); + id->id_text); } - else if (df == Defined && level == 1) { + else if (df == Defined && level == 1) + { error("cannot import from current module \"%s\"", id->id_text); df->df_kind = D_ERROR; } From 893471a42eb4d189cc0ba1dac1864d6f151bccd7 Mon Sep 17 00:00:00 2001 From: David Given Date: Sat, 7 Jan 2017 23:00:52 +0100 Subject: [PATCH 117/173] No longer truncate module names at 10 characters when constructing paths; rename some library modules to their full names. --- lang/m2/comp/build.lua | 1 + lang/m2/comp/defmodule.c | 8 ++------ lang/m2/libm2/{Conversion.def => Conversions.def} | 0 lang/m2/libm2/{Conversion.mod => Conversions.mod} | 0 lang/m2/libm2/{RealConver.def => RealConversions.def} | 0 lang/m2/libm2/{RealConver.mod => RealConversions.mod} | 0 6 files changed, 3 insertions(+), 6 deletions(-) rename lang/m2/libm2/{Conversion.def => Conversions.def} (100%) rename lang/m2/libm2/{Conversion.mod => Conversions.mod} (100%) rename lang/m2/libm2/{RealConver.def => RealConversions.def} (100%) rename lang/m2/libm2/{RealConver.mod => RealConversions.mod} (100%) diff --git a/lang/m2/comp/build.lua b/lang/m2/comp/build.lua index 95c4a30d7..4e12d24f7 100644 --- a/lang/m2/comp/build.lua +++ b/lang/m2/comp/build.lua @@ -113,6 +113,7 @@ cprogram { "h+emheaders", "modules+headers", "modules/src/alloc+lib", + "modules/src/data+lib", "modules/src/em_code+lib_k", "modules/src/em_data+lib", "modules/src/em_mes+lib", diff --git a/lang/m2/comp/defmodule.c b/lang/m2/comp/defmodule.c index a164c1939..0ecb1dd2a 100644 --- a/lang/m2/comp/defmodule.c +++ b/lang/m2/comp/defmodule.c @@ -17,6 +17,7 @@ #include #include #include +#include #include "LLlex.h" #include "Lpars.h" @@ -64,12 +65,7 @@ GetFile(name) char* name; /* Try to find a file with basename "name" and extension ".def", in the directories mentioned in "DEFPATH". */ - char buf[15]; - char *strncpy(), *strcat(); - - strncpy(buf, name, 10); - buf[10] = '\0'; /* maximum length */ - strcat(buf, ".def"); + char* buf = aprintf("%s.def", name); DEFPATH[0] = WorkingDir; if (!InsertFile(buf, DEFPATH, &(FileName))) { diff --git a/lang/m2/libm2/Conversion.def b/lang/m2/libm2/Conversions.def similarity index 100% rename from lang/m2/libm2/Conversion.def rename to lang/m2/libm2/Conversions.def diff --git a/lang/m2/libm2/Conversion.mod b/lang/m2/libm2/Conversions.mod similarity index 100% rename from lang/m2/libm2/Conversion.mod rename to lang/m2/libm2/Conversions.mod diff --git a/lang/m2/libm2/RealConver.def b/lang/m2/libm2/RealConversions.def similarity index 100% rename from lang/m2/libm2/RealConver.def rename to lang/m2/libm2/RealConversions.def diff --git a/lang/m2/libm2/RealConver.mod b/lang/m2/libm2/RealConversions.mod similarity index 100% rename from lang/m2/libm2/RealConver.mod rename to lang/m2/libm2/RealConversions.mod From 11ea3a2fe18925379893557aa5ec643c6f312bee Mon Sep 17 00:00:00 2001 From: David Given Date: Sun, 8 Jan 2017 00:15:10 +0100 Subject: [PATCH 118/173] Don't sort inludes any more (breaks too many ACK files). --- .clang-format | 1 + 1 file changed, 1 insertion(+) diff --git a/.clang-format b/.clang-format index d5e0c3a16..7dced3479 100644 --- a/.clang-format +++ b/.clang-format @@ -7,5 +7,6 @@ IndentCaseLabels: 'true' PointerAlignment: Left TabWidth: '4' UseTab: ForIndentation +SortIncludes: false ... From 4b7fc5e23382399cc24ad78a4b245e86ba9827d9 Mon Sep 17 00:00:00 2001 From: David Given Date: Sun, 8 Jan 2017 00:15:23 +0100 Subject: [PATCH 119/173] Run through clang-format. --- util/ack/main.c | 720 ++++++++++++++++++++++++++++-------------------- 1 file changed, 421 insertions(+), 299 deletions(-) diff --git a/util/ack/main.c b/util/ack/main.c index 539f42180..0c7c432ac 100644 --- a/util/ack/main.c +++ b/util/ack/main.c @@ -15,451 +15,573 @@ #include #ifndef NORCSID -static char rcs_id[] = "$Id$" ; -static char rcs_ack[] = RCS_ACK ; +static char rcs_id[] = "$Id$"; +static char rcs_ack[] = RCS_ACK; #endif -static int sigs[] = { SIGINT, SIGHUP, SIGTERM, 0 } ; +static int sigs[] = { SIGINT, SIGHUP, SIGTERM, 0 }; static int arg_count; -static char *srcvar(void); -static char *getsuffix(void); +static char* srcvar(void); +static char* getsuffix(void); static void varinit(void); -static void vieuwargs(int, char **); -static void firstarg(char *); -static int process(char *); -static int startrf(trf *); -static void block(trf *); +static void vieuwargs(int, char**); +static void firstarg(char*); +static int process(char*); +static int startrf(trf*); +static void block(trf*); static int mayprep(void); static void scanneeds(void); -static void setneeds(const char *, int); +static void setneeds(const char*, int); static void noodstop(int); -int main(int argc, char **argv) { - register list_elem *elem ; - register char *frontend ; - register int *n_sig ; - register trf *phase ; +int main(int argc, char** argv) +{ + register list_elem* elem; + register char* frontend; + register int* n_sig; + register trf* phase; - progname=argv[0]; + progname = argv[0]; varinit(); - vieuwargs(argc,argv); - if ( (frontend=getenv("ACKFE")) ) { - setlist(frontend) ; - } else { + vieuwargs(argc, argv); + if ((frontend = getenv("ACKFE"))) + { + setlist(frontend); + } + else + { setlist(FRONTENDS); } - if ( callname ) { - if ( machine ) { + if (callname) + { + if (machine) + { fuerror("can not produce code for both %s and %s", - callname,machine) ; + callname, machine); } - machine= callname ; + machine = callname; } - if ( !machine && ! (machine=getenv("ACKM")) ) { + if (!machine && !(machine = getenv("ACKM"))) + { #ifdef ACKM - machine= ACKM; /* The default machine */ + machine = ACKM; /* The default machine */ #else - fuerror("No machine specified") ; + fuerror("No machine specified"); #endif } setlist(machine); /* Find the linker, needed for argument building */ - scanlist(l_first(tr_list),elem) { - if ( t_cont(*elem)->t_linker ) { - linker= t_cont(*elem) ; + scanlist(l_first(tr_list), elem) + { + if (t_cont(*elem)->t_linker) + { + linker = t_cont(*elem); } } transini(); scanneeds(); - sprintf(template,TMPNAME,getpid()) ; - if ( n_error && !k_flag ) exit(n_error) ; + sprintf(template, TMPNAME, getpid()); + if (n_error && !k_flag) + exit(n_error); - for ( n_sig=sigs ; *n_sig ; n_sig++ ) { - if ( signal(*n_sig,noodstop)==SIG_IGN ) { - signal(*n_sig,SIG_IGN) ; + for (n_sig = sigs; *n_sig; n_sig++) + { + if (signal(*n_sig, noodstop) == SIG_IGN) + { + signal(*n_sig, SIG_IGN); } } - scanlist ( l_first(arguments), elem ) { + scanlist(l_first(arguments), elem) + { arg_count++; } - scanlist ( l_first(arguments), elem ) { - if ( !process(l_content(*elem)) && !k_flag ) exit(1) ; + scanlist(l_first(arguments), elem) + { + if (!process(l_content(*elem)) && !k_flag) + exit(1); } - orig.p_path= (char *)0 ; - if ( !rts ) rts="." ; - setsvar(keeps(RTS),rts) ; - if ( linker ) getmapflags(linker) ; + orig.p_path = (char*)0; + if (!rts) + rts = "."; + setsvar(keeps(RTS), rts); + if (linker) + getmapflags(linker); - scanlist(l_first(tr_list),elem) { - phase=t_cont(*elem) ; - if ( phase->t_combine && phase->t_do ) { - if ( phase->t_blocked ) { + scanlist(l_first(tr_list), elem) + { + phase = t_cont(*elem); + if (phase->t_combine && phase->t_do) + { + if (phase->t_blocked) + { #ifdef DEBUG - if ( debug ) { + if (debug) + { vprint("phase %s is blocked\n", - phase->t_name) ; + phase->t_name); } #endif - disc_inputs(phase) ; - continue ; + disc_inputs(phase); + continue; } - orig.p_keep=YES ; - orig.p_keeps=NO ; - orig.p_path=phase->t_origname ; - if ( p_basename ) throws(p_basename) ; - if ( orig.p_path ) { - p_basename= keeps(ack_basename(orig.p_path)) ; - } else { - p_basename=0 ; + orig.p_keep = YES; + orig.p_keeps = NO; + orig.p_path = phase->t_origname; + if (p_basename) + throws(p_basename); + if (orig.p_path) + { + p_basename = keeps(ack_basename(orig.p_path)); } - if ( !startrf(phase) && !k_flag ) exit(1) ; + else + { + p_basename = 0; + } + if (!startrf(phase) && !k_flag) + exit(1); } } - if ( n_error ) exit(n_error) ; + if (n_error) + exit(n_error); - exit(0) ; + exit(0); } -static char *srcvar(void) { - return orig.p_path ; +static char* srcvar(void) +{ + return orig.p_path; } -static char *getsuffix(void) { - return strrchr(orig.p_path, SUFCHAR) ; +static char* getsuffix(void) +{ + return strrchr(orig.p_path, SUFCHAR); } -static void varinit(void) { +static void varinit(void) +{ /* initialize the string variables */ - register char *envstr ; - extern char *em_dir; + register char* envstr; + extern char* em_dir; - if ( envstr=getenv("ACKDIR") ) { + if (envstr = getenv("ACKDIR")) + { em_dir = keeps(envstr); } - setsvar(keeps(HOME),em_dir) ; - setpvar(keeps(SRC),srcvar) ; - setpvar(keeps(SUFFIX),getsuffix) ; + setsvar(keeps(HOME), em_dir); + setpvar(keeps(SRC), srcvar); + setpvar(keeps(SUFFIX), getsuffix); } /************************* flag processing ***********************/ -void vieuwargs(int argc, char **argv) { - register char *argp; - register int nextarg ; - register int eaten ; - int hide ; +void vieuwargs(int argc, char** argv) +{ + register char* argp; + register int nextarg; + register int eaten; + int hide; - firstarg(argv[0]) ; + firstarg(argv[0]); - nextarg= 1 ; + nextarg = 1; - while ( nextarg=argc ) { - fuerror("-o can't be the last flag") ; - } - if ( outfile ) fuerror("Two results?") ; - outfile= argv[nextarg++] ; - hide=YES ; - break ; - case 'O': Optlevel = atoi(&argp[2]); - if (! Optlevel) Optlevel = 1; - Optlist= &argp[2] ; - eaten=1 ; - break ; - case 'v': if ( argp[2] ) { - v_flag += atoi(&argp[2]) ; - eaten=1 ; - } else { - v_flag++ ; - } + hide = NO; /* Do not hide this flags to the phases */ + eaten = 0; /* Did not 'eat' tail of flag yet */ + switch (argp[1]) + { + case 'm': + if (machine) + fuerror("Two machines?"); + machine = &argp[2]; + if (*machine == '\0') + { + fuerror("-m needs machine name"); + } + eaten = 1; + break; + case 'o': + if (nextarg >= argc) + { + fuerror("-o can't be the last flag"); + } + if (outfile) + fuerror("Two results?"); + outfile = argv[nextarg++]; + hide = YES; + break; + case 'O': + Optlevel = atoi(&argp[2]); + if (!Optlevel) + Optlevel = 1; + Optlist = &argp[2]; + eaten = 1; + break; + case 'v': + if (argp[2]) + { + v_flag += atoi(&argp[2]); + eaten = 1; + } + else + { + v_flag++; + } #ifdef DEBUG - if ( v_flag>=3 ) debug=v_flag-2 ; + if (v_flag >= 3) + debug = v_flag - 2; #endif - break ; - case 'c': if ( stopsuffix ) fuerror("Two -c flags") ; - stopsuffix= &argp[2]; eaten=1; - if ( *stopsuffix && *stopsuffix!=SUFCHAR ) { - fuerror("-c flag has invalid tail") ; - } - break ; - case 'k': k_flag++ ; - break ; - case 't': t_flag++ ; - break ; - case 'R': eaten=1; - break ; - case 'r': if ( argp[2]!=SUFCHAR ) { - error("-r must be followed by %c",SUFCHAR) ; - } - l_add(&tail_list, &argp[2]) ; - eaten=1 ; - break ; - case '.': if ( rts ) { - if ( strcmp(rts,&argp[1])!=0 ) - fuerror("Two run-time systems?") ; - } else { - rts= &argp[1] ; - l_add(&head_list, rts) ; - l_add(&tail_list, rts) ; - } - eaten=1 ; - break ; - case 0 : nill_flag++ ; eaten++ ; - hide=YES ; - break; - case 'w': w_flag++; - break ; - default: /* The flag is not recognized, + break; + case 'c': + if (stopsuffix) + fuerror("Two -c flags"); + stopsuffix = &argp[2]; + eaten = 1; + if (*stopsuffix && *stopsuffix != SUFCHAR) + { + fuerror("-c flag has invalid tail"); + } + break; + case 'k': + k_flag++; + break; + case 't': + t_flag++; + break; + case 'R': + eaten = 1; + break; + case 'r': + if (argp[2] != SUFCHAR) + { + error("-r must be followed by %c", SUFCHAR); + } + l_add(&tail_list, &argp[2]); + eaten = 1; + break; + case '.': + if (rts) + { + if (strcmp(rts, &argp[1]) != 0) + fuerror("Two run-time systems?"); + } + else + { + rts = &argp[1]; + l_add(&head_list, rts); + l_add(&tail_list, rts); + } + eaten = 1; + break; + case 0: + nill_flag++; + eaten++; + hide = YES; + break; + case 'w': + w_flag++; + break; + default: /* The flag is not recognized, put it on the list for the sub-processes */ #ifdef DEBUG - if ( debug ) { - vprint("Flag %s: phase dependent\n",argp) ; - } + if (debug) + { + vprint("Flag %s: phase dependent\n", argp); + } #endif - l_add(&flags,keeps(argp)) ; - eaten=1 ; - hide=YES ; + l_add(&flags, keeps(argp)); + eaten = 1; + hide = YES; } - if ( !hide ) { - register char *tokeep ; - tokeep=keeps(argp) ; - if ( argp[1]=='R' ) { - l_add(&R_list, tokeep) ; - } else { - *tokeep |= NO_SCAN ; + if (!hide) + { + register char* tokeep; + tokeep = keeps(argp); + if (argp[1] == 'R') + { + l_add(&R_list, tokeep); } - l_add(&flags,tokeep) ; + else + { + *tokeep |= NO_SCAN; + } + l_add(&flags, tokeep); } - if ( argp[2] && !eaten ) { - werror("Unexpected characters at end of %s",argp) ; + if (argp[2] && !eaten) + { + werror("Unexpected characters at end of %s", argp); } } - return ; + return; } -static void firstarg(char *argp) { - register char *name ; +static void firstarg(char* argp) +{ + register char* name; - name=strrchr(argp,'/') ; - if ( name && *(name+1) ) { - name++ ; - } else { - name= argp ; + name = strrchr(argp, '/'); + if (name && *(name + 1)) + { + name++; } - callname= name; + else + { + name = argp; + } + callname = name; } /************************* argument processing ***********************/ -static int process(char *arg) { +static int process(char* arg) +{ /* Process files & library arguments */ - trf *phase ; - register trf *tmp ; + trf* phase; + register trf* tmp; #ifdef DEBUG - if ( debug ) vprint("Processing %s\n",arg) ; + if (debug) + vprint("Processing %s\n", arg); #endif - p_suffix= strrchr(arg,SUFCHAR) ; - orig.p_keep= YES ; /* Don't throw away the original ! */ - orig.p_keeps= NO; - orig.p_path= arg ; - if ( arg[0]=='-' || !p_suffix ) { - if ( linker ) add_input(&orig,linker) ; - return 1 ; + p_suffix = strrchr(arg, SUFCHAR); + orig.p_keep = YES; /* Don't throw away the original ! */ + orig.p_keeps = NO; + orig.p_path = arg; + if (arg[0] == '-' || !p_suffix) + { + if (linker) + add_input(&orig, linker); + return 1; } - if ( p_basename ) throws(p_basename) ; - p_basename= keeps(ack_basename(arg)) ; + if (p_basename) + throws(p_basename); + p_basename = keeps(ack_basename(arg)); /* Try to find a path through the transformations */ - switch( getpath(&phase) ) { - case F_NOPATH : - error("Cannot produce the desired file from %s",arg) ; - if ( linker ) add_input(&orig,linker) ; - return 1 ; - case F_NOMATCH : - if ( stopsuffix ) werror("Unknown suffix in %s",arg) ; - if ( linker ) add_input(&orig,linker) ; - return 1 ; - case F_OK : - break ; + switch (getpath(&phase)) + { + case F_NOPATH: + error("Cannot produce the desired file from %s", arg); + if (linker) + add_input(&orig, linker); + return 1; + case F_NOMATCH: + if (stopsuffix) + werror("Unknown suffix in %s", arg); + if (linker) + add_input(&orig, linker); + return 1; + case F_OK: + break; } - if ( !phase ) return 1 ; - for ( tmp=phase ; tmp ; tmp=tmp->t_next ) - if ( !tmp->t_visited ) { - /* The flags are set up once. + if (!phase) + return 1; + for (tmp = phase; tmp; tmp = tmp->t_next) + if (!tmp->t_visited) + { + /* The flags are set up once. At the first time each phase is in a list. The program name and flags may already be touched by vieuwargs. */ - tmp->t_visited=YES ; - if ( tmp->t_priority<0 ) - werror("Using phase %s (negative priority)", - tmp->t_name) ; - if ( !rts && tmp->t_rts ) rts= tmp->t_rts ; - if ( tmp->t_needed ) { - add_head(tmp->t_needed) ; - add_tail(tmp->t_needed) ; + tmp->t_visited = YES; + if (tmp->t_priority < 0) + werror("Using phase %s (negative priority)", + tmp->t_name); + if (!rts && tmp->t_rts) + rts = tmp->t_rts; + if (tmp->t_needed) + { + add_head(tmp->t_needed); + add_tail(tmp->t_needed); + } } + if (phase->t_combine) + { + add_input(&orig, phase); + return 1; } - if ( phase->t_combine ) { - add_input(&orig,phase) ; - return 1 ; + in = orig; + if (!nill_flag && arg_count > 1) + { + printf("%s\n", arg); } - in= orig ; - if ( !nill_flag && arg_count > 1 ) { - printf("%s\n",arg) ; - } - return startrf(phase) ; + return startrf(phase); } -static int startrf(trf *first) { +static int startrf(trf* first) +{ /* Start the transformations at the indicated phase */ - register trf *phase ; + register trf* phase; - phase=first ; - for(;;) { + phase = first; + for (;;) + { int do_preprocess = 0; int only_prep = 0; - switch ( phase->t_prep ) { + switch (phase->t_prep) + { /* BEWARE, sign extension */ - case NO : break ; - default : if ( !mayprep() ) break ; - case YES: do_preprocess = 1; - break; + case NO: + break; + default: + if (!mayprep()) + break; + case YES: + do_preprocess = 1; + break; } - if ( cpp_trafo && stopsuffix && - strcmp(cpp_trafo->t_out,stopsuffix)==0 ) { + if (cpp_trafo && stopsuffix && strcmp(cpp_trafo->t_out, stopsuffix) == 0) + { /* user explicitly asked for preprocessing */ do_preprocess = 1; only_prep = 1; } - if (do_preprocess && !transform(cpp_trafo) ) { - n_error++ ; + if (do_preprocess && !transform(cpp_trafo)) + { + n_error++; #ifdef DEBUG - vprint("Pre-processor failed\n") ; + vprint("Pre-processor failed\n"); #endif - return 0 ; + return 0; } - if ( only_prep ) { - break ; + if (only_prep) + { + break; } - if ( !transform(phase) ) { - n_error++ ; - block(phase->t_next) ; + if (!transform(phase)) + { + n_error++; + block(phase->t_next); #ifdef DEBUG - if ( debug ) { - if ( !orig.p_path ) { + if (debug) + { + if (!orig.p_path) + { vprint("phase %s failed\n", - phase->t_name ) ; - } else { + phase->t_name); + } + else + { vprint("phase %s for %s failed\n", - phase->t_name,orig.p_path) ; + phase->t_name, orig.p_path); } } #endif - return 0 ; + return 0; } - first=NO ; - phase=phase->t_next ; - if ( !phase ) { + first = NO; + phase = phase->t_next; + if (!phase) + { #ifdef DEBUG -if ( debug ) vprint("Transformation sequence complete for %s\n", - orig.p_path) ; + if (debug) + vprint("Transformation sequence complete for %s\n", + orig.p_path); #endif /* No more work on this file */ - if ( !in.p_keep ) { - fatal("attempt to discard the result file") ; + if (!in.p_keep) + { + fatal("attempt to discard the result file"); } - if ( in.p_keeps ) throws(in.p_path) ; - in.p_keep=NO ; in.p_keeps=NO ; in.p_path= (char *) 0 ; - return 1 ; + if (in.p_keeps) + throws(in.p_path); + in.p_keep = NO; + in.p_keeps = NO; + in.p_path = (char*)0; + return 1; } - if ( phase->t_combine ) { - add_input(&in,phase) ; - break ; + if (phase->t_combine) + { + add_input(&in, phase); + break; } } - return 1 ; + return 1; } -static void block(trf *first) { +static void block(trf* first) +{ /* One of the input files of this phase could not be produced, block all combiners taking their input from this one. */ - register trf *phase ; - for ( phase=first ; phase ; phase=phase->t_next ) { - if ( phase->t_combine ) phase->t_blocked=YES ; + register trf* phase; + for (phase = first; phase; phase = phase->t_next) + { + if (phase->t_combine) + phase->t_blocked = YES; } } -static int mayprep(void) { - int file ; - char fc ; - file=open(in.p_path,0); - if ( file<0 ) return 0 ; - if ( read(file,&fc,1)!=1 ) fc=0 ; - close(file) ; - return fc=='#' ; +static int mayprep(void) +{ + int file; + char fc; + file = open(in.p_path, 0); + if (file < 0) + return 0; + if (read(file, &fc, 1) != 1) + fc = 0; + close(file); + return fc == '#'; } -static void scanneeds(void) { - register list_elem *elem ; - scanlist(l_first(head_list), elem) { setneeds(l_content(*elem),0) ; } - l_clear(&head_list) ; - scanlist(l_first(tail_list), elem) { setneeds(l_content(*elem),1) ; } - l_clear(&tail_list) ; +static void scanneeds(void) +{ + register list_elem* elem; + scanlist(l_first(head_list), elem) { setneeds(l_content(*elem), 0); } + l_clear(&head_list); + scanlist(l_first(tail_list), elem) { setneeds(l_content(*elem), 1); } + l_clear(&tail_list); } -static void setneeds(const char *suffix, int tail) { - trf *phase ; +static void setneeds(const char* suffix, int tail) +{ + trf* phase; - p_suffix= suffix ; - switch ( getpath(&phase) ) { - case F_OK : - for ( ; phase ; phase= phase->t_next ) { - if ( phase->t_needed ) { - if ( tail ) - add_tail(phase->t_needed) ; - else - add_head(phase->t_needed) ; + p_suffix = suffix; + switch (getpath(&phase)) + { + case F_OK: + for (; phase; phase = phase->t_next) + { + if (phase->t_needed) + { + if (tail) + add_tail(phase->t_needed); + else + add_head(phase->t_needed); + } } - } - break ; - case F_NOMATCH : - werror("\"%s\": unrecognized suffix",suffix) ; - break ; - case F_NOPATH : - werror("sorry, cannot produce the desired file(s) from %s files", - suffix) ; - break ; + break; + case F_NOMATCH: + werror("\"%s\": unrecognized suffix", suffix); + break; + case F_NOPATH: + werror("sorry, cannot produce the desired file(s) from %s files", + suffix); + break; } } -static void noodstop(int sig) { - quit(-3) ; +static void noodstop(int sig) +{ + quit(-3); } From 62022c6f6b5d0bc06b2f45c9e3a43ddce669c023 Mon Sep 17 00:00:00 2001 From: David Given Date: Sun, 8 Jan 2017 00:16:35 +0100 Subject: [PATCH 120/173] Don't print source file names during compilation (gcc stopped doing it years ago). --- util/ack/main.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/util/ack/main.c b/util/ack/main.c index 0c7c432ac..a57454d60 100644 --- a/util/ack/main.c +++ b/util/ack/main.c @@ -417,10 +417,6 @@ static int process(char* arg) return 1; } in = orig; - if (!nill_flag && arg_count > 1) - { - printf("%s\n", arg); - } return startrf(phase); } From ee5ef73dfb8808257b365b0d6ab26d9febcd826f Mon Sep 17 00:00:00 2001 From: David Given Date: Sun, 8 Jan 2017 11:23:56 +0100 Subject: [PATCH 121/173] Run through clang-format. --- lang/m2/comp/walk.c | 862 ++++++++++++++++++++++++-------------------- 1 file changed, 470 insertions(+), 392 deletions(-) diff --git a/lang/m2/comp/walk.c b/lang/m2/comp/walk.c index 93cc3308b..b51316802 100644 --- a/lang/m2/comp/walk.c +++ b/lang/m2/comp/walk.c @@ -13,71 +13,72 @@ code for these parts. */ -#include -#include +#include +#include #include "parameters.h" -#include "debug.h" +#include "debug.h" -#include -#include -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include +#include +#include -#include "LLlex.h" -#include "def.h" -#include "type.h" -#include "scope.h" -#include "main.h" -#include "node.h" -#include "Lpars.h" -#include "desig.h" -#include "f_info.h" -#include "idf.h" -#include "chk_expr.h" -#include "walk.h" -#include "misc.h" -#include "warning.h" +#include "LLlex.h" +#include "def.h" +#include "type.h" +#include "scope.h" +#include "main.h" +#include "node.h" +#include "Lpars.h" +#include "desig.h" +#include "f_info.h" +#include "idf.h" +#include "chk_expr.h" +#include "walk.h" +#include "misc.h" +#include "warning.h" -extern arith NewPtr(); -extern arith NewInt(); -extern arith TmpSpace(); +extern arith NewPtr(); +extern arith NewInt(); +extern arith TmpSpace(); -extern int proclevel; -extern int gdb_flag; +extern int proclevel; +extern int gdb_flag; -label text_label; -label data_label = 1; -struct withdesig *WithDesigs; -t_node *Modules; +label text_label; +label data_label = 1; +struct withdesig* WithDesigs; +t_node* Modules; -static t_type *func_type; -static t_node *priority; -static int oldlineno; +static t_type* func_type; +static t_node* priority; +static int oldlineno; -static int RegisterMessage(); -static int WalkDef(); +static int RegisterMessage(); +static int WalkDef(); #ifdef DBSYMTAB -static int stabdef(); +static int stabdef(); #endif -static int MkCalls(); -static void UseWarnings(); +static int MkCalls(); +static void UseWarnings(); -#define NO_EXIT_LABEL ((label) 0) -#define RETURN_LABEL ((label) 1) +#define NO_EXIT_LABEL ((label)0) +#define RETURN_LABEL ((label)1) -#define REACH_FLAG 1 -#define EXIT_FLAG 2 +#define REACH_FLAG 1 +#define EXIT_FLAG 2 void DoAssign(); int -LblWalkNode(lbl, nd, exit, reach) - label lbl, exit; - t_node *nd; + LblWalkNode(lbl, nd, exit, reach) + label lbl, + exit; +t_node* nd; { /* Generate code for node "nd", after generating instruction label "lbl". "exit" is the exit label for the closest @@ -96,10 +97,11 @@ DoPriority() /* For the time being (???), handle priorities by calls to the runtime system */ - if (priority) { + if (priority) + { tmpprio = NewInt(); C_loc(priority->nd_INT); - CAL("stackprio", (int) word_size); + CAL("stackprio", (int)word_size); C_lfr(word_size); C_stl(tmpprio); } @@ -108,15 +110,16 @@ DoPriority() STATIC EndPriority() { - if (priority) { + if (priority) + { C_lol(tmpprio); - CAL("unstackprio", (int) word_size); + CAL("unstackprio", (int)word_size); FreeInt(tmpprio); } } def_ilb(l) - label l; + label l; { /* Instruction label definition. Forget about line number. */ @@ -124,27 +127,29 @@ def_ilb(l) oldlineno = 0; } -DoLineno(nd) - register t_node *nd; +DoLineno(nd) register t_node* nd; { /* Generate line number information, if necessary. */ - if ((! options['L'] + if ((!options['L'] #ifdef DBSYMTAB - || options['g'] + || options['g'] #endif /* DBSYMTAB */ - ) && - nd->nd_lineno && - nd->nd_lineno != oldlineno) { + ) + && nd->nd_lineno && nd->nd_lineno != oldlineno) + { oldlineno = nd->nd_lineno; - if (! options['L']) C_lin((arith) nd->nd_lineno); + if (!options['L']) + C_lin((arith)nd->nd_lineno); #ifdef DBSYMTAB - if ( options['g']) { - static int ms_lineno; + if (options['g']) + { + static int ms_lineno; - if (ms_lineno != nd->nd_lineno) { + if (ms_lineno != nd->nd_lineno) + { ms_lineno = nd->nd_lineno; - C_ms_std((char *) 0, N_SLINE, ms_lineno); + C_ms_std((char*)0, N_SLINE, ms_lineno); } } #endif /* DBSYMTAB */ @@ -158,30 +163,31 @@ DoFilename(needed) procedure entry, and after generating a call to another procedure. */ - static label filename_label = 0; + static label filename_label = 0; - oldlineno = 0; /* always invalidate remembered line number */ - if (needed && ! options['L']) { + oldlineno = 0; /* always invalidate remembered line number */ + if (needed && !options['L']) + { - if (! filename_label) { + if (!filename_label) + { filename_label = 1; - C_df_dlb((label) 1); - C_rom_scon(FileName, (arith) (strlen(FileName) + 1)); + C_df_dlb((label)1); + C_rom_scon(FileName, (arith)(strlen(FileName) + 1)); } - C_fil_dlb((label) 1, (arith) 0); + C_fil_dlb((label)1, (arith)0); } } -WalkModule(module) - register t_def *module; +WalkModule(module) register t_def* module; { /* Walk through a module, and all its local definitions. Also generate code for its body. This code is collected in an initialization routine. */ - register t_scope *sc; - t_scopelist *savevis = CurrVis; + register t_scope* sc; + t_scopelist* savevis = CurrVis; CurrVis = module->mod_vis; priority = module->mod_priority; @@ -195,52 +201,58 @@ WalkModule(module) First call initialization routines for modules defined within this module. */ - sc->sc_off = 0; /* no locals (yet) */ - text_label = 1; /* label at end of initialization routine */ - TmpOpen(sc); /* Initialize for temporaries */ + sc->sc_off = 0; /* no locals (yet) */ + text_label = 1; /* label at end of initialization routine */ + TmpOpen(sc); /* Initialize for temporaries */ C_pro_narg(sc->sc_name); #ifdef DBSYMTAB - if (options['g']) { + if (options['g']) + { stb_string(module, D_MODULE); WalkDefList(sc->sc_def, stabdef); - if (state == PROGRAM && module == Defined) { + if (state == PROGRAM && module == Defined) + { C_ms_stb_cst(module->df_idf->id_text, - N_MAIN, - 0, - (arith) 0); + N_MAIN, + 0, + (arith)0); } stb_string(module, D_END); } #endif DoPriority(); - if (module == Defined) { + if (module == Defined) + { /* Body of implementation or program module. Call initialization routines of imported modules. Also prevent recursive calls of this one. */ - register t_node *nd = Modules; + register t_node* nd = Modules; - if (state == IMPLEMENTATION) { + if (state == IMPLEMENTATION) + { /* We don't actually prevent recursive calls, but do nothing if called recursively */ C_df_dlb(++data_label); - C_con_cst((arith) 0); + C_con_cst((arith)0); /* if this one is set to non-zero, the initialization was already done. */ - C_loe_dlb(data_label, (arith) 0); + C_loe_dlb(data_label, (arith)0); C_zne(RETURN_LABEL); - C_ine_dlb(data_label, (arith) 0); + C_ine_dlb(data_label, (arith)0); } - else if (! options['R']) { + else if (!options['R']) + { /* put funny value in BSS, in an attempt to detect uninitialized variables */ C_cal("killbss"); } - for (; nd; nd = nd->nd_NEXT) { + for (; nd; nd = nd->nd_NEXT) + { C_cal(nd->nd_def->mod_vis->sc_scope->sc_name); } DoFilename(1); @@ -248,18 +260,20 @@ WalkModule(module) WalkDefList(sc->sc_def, MkCalls); proclevel++; #ifdef DBSYMTAB - if (options['g']) { - C_ms_std((char *) 0, N_LBRAC, gdb_flag ? 0 : proclevel); + if (options['g']) + { + C_ms_std((char*)0, N_LBRAC, gdb_flag ? 0 : proclevel); } #endif /* DBSYMTAB */ WalkNode(module->mod_body, NO_EXIT_LABEL, REACH_FLAG); DO_DEBUG(options['X'], PrNode(module->mod_body, 0)); def_ilb(RETURN_LABEL); EndPriority(); - C_ret((arith) 0); + C_ret((arith)0); #ifdef DBSYMTAB - if (options['g']) { - C_ms_std((char *) 0, N_RBRAC, gdb_flag ? 0 : proclevel); + if (options['g']) + { + C_ms_std((char*)0, N_RBRAC, gdb_flag ? 0 : proclevel); } #endif /* DBSYMTAB */ C_end(-sc->sc_off); @@ -270,19 +284,18 @@ WalkModule(module) WalkDefList(sc->sc_def, UseWarnings); } -WalkProcedure(procedure) - register t_def *procedure; +WalkProcedure(procedure) register t_def* procedure; { /* Walk through the definition of a procedure and all its local definitions, checking and generating code. */ - t_scopelist *savevis = CurrVis; - register t_type *tp; - register t_param *param; - register t_scope *procscope = procedure->prc_vis->sc_scope; - label too_big = 0; /* returnsize larger than returnarea */ - arith StackAdjustment = 0; /* space for conformant arrays */ - arith retsav = 0; /* temporary space for return value */ + t_scopelist* savevis = CurrVis; + register t_type* tp; + register t_param* param; + register t_scope* procscope = procedure->prc_vis->sc_scope; + label too_big = 0; /* returnsize larger than returnarea */ + arith StackAdjustment = 0; /* space for conformant arrays */ + arith retsav = 0; /* temporary space for return value */ arith func_res_size = 0; #ifdef USE_INSERT int partno = C_getid(); @@ -301,9 +314,11 @@ WalkProcedure(procedure) func_type = tp = RemoveEqual(ResultType(procedure->df_type)); - if (tp) { + if (tp) + { func_res_size = WA(tp->tp_size); - if (TooBigForReturnArea(tp)) { + if (TooBigForReturnArea(tp)) + { #ifdef BIG_RESULT_ON_STACK /* The result type of this procedure is too big. The caller will have reserved space on its stack, @@ -330,22 +345,23 @@ WalkProcedure(procedure) */ TmpOpen(procscope); #ifdef USE_INSERT - C_insertpart(partno2); /* procedure header */ + C_insertpart(partno2); /* procedure header */ #else C_pro_narg(procedure->prc_name); #ifdef DBSYMTAB - if (options['g']) { + if (options['g']) + { stb_string(procedure, D_PROCEDURE); WalkDefList(procscope->sc_def, stabdef); stb_string(procedure, D_PEND); - C_ms_std((char *) 0, N_LBRAC, gdb_flag ? 0 : proclevel); + C_ms_std((char*)0, N_LBRAC, gdb_flag ? 0 : proclevel); } #endif /* DBSYMTAB */ C_ms_par(procedure->df_type->prc_nbpar #ifdef BIG_RESULT_ON_STACK - + (too_big ? func_res_size : 0) + + (too_big ? func_res_size : 0) #endif - ); + ); #endif /* generate code for filename only when the procedure can be exported, either directly or by taking the address. @@ -355,27 +371,31 @@ WalkProcedure(procedure) DoFilename(procscope->sc_level == 1); DoPriority(); - text_label = 1; /* label at end of procedure */ + text_label = 1; /* label at end of procedure */ /* Check if we must save the stack pointer */ for (param = ParamList(procedure->df_type); param; - param = param->par_next) { - if (! IsVarParam(param)) { + param = param->par_next) + { + if (!IsVarParam(param)) + { tp = TypeOfParam(param); - if ( IsConformantArray(tp)) { + if (IsConformantArray(tp)) + { /* First time we get here */ - if (func_type && !too_big) { + if (func_type && !too_big) + { /* Some local space, only needed if the value itself is returned */ - retsav= TmpSpace(func_res_size, 1); + retsav = TmpSpace(func_res_size, 1); } StackAdjustment = NewPtr(); - C_lor((arith) 1); + C_lor((arith)1); STL(StackAdjustment, pointer_size); } } @@ -390,12 +410,14 @@ WalkProcedure(procedure) def_ilb(cd_body); #endif - if ((WalkNode(procedure->prc_body, NO_EXIT_LABEL, REACH_FLAG) & REACH_FLAG)) { - if (func_res_size) { + if ((WalkNode(procedure->prc_body, NO_EXIT_LABEL, REACH_FLAG) & REACH_FLAG)) + { + if (func_res_size) + { node_warning(procscope->sc_end, - W_ORDINARY, - "function procedure \"%s\" does not always return a value", - procedure->df_idf->id_text); + W_ORDINARY, + "function procedure \"%s\" does not always return a value", + procedure->df_idf->id_text); c_loc(M2_NORESULT); C_trp(); C_asp(-func_res_size); @@ -422,13 +444,16 @@ WalkProcedure(procedure) */ for (param = ParamList(procedure->df_type); param; - param = param->par_next) { - if (! IsVarParam(param)) { + param = param->par_next) + { + if (!IsVarParam(param)) + { tp = TypeOfParam(param); - if (! IsConformantArray(tp)) { - if (tp->tp_size < word_size && - (int) word_size % (int) tp->tp_size == 0) { + if (!IsConformantArray(tp)) + { + if (tp->tp_size < word_size && (int)word_size % (int)tp->tp_size == 0) + { C_lol(param->par_def->var_off); STL(param->par_def->var_off, tp->tp_size); @@ -450,11 +475,11 @@ WalkProcedure(procedure) CAL("new_stackptr", (int)pointer_size); C_lfr(pointer_size); C_ass(pointer_size); - /* adjusted stack pointer */ + /* adjusted stack pointer */ LOL(param->par_def->var_off, pointer_size); - /* push source address */ + /* push source address */ CAL("copy_array", (int)pointer_size); - /* copy */ + /* copy */ } } #ifdef USE_INSERT @@ -463,9 +488,10 @@ WalkProcedure(procedure) c_bra(cd_body); #endif DO_DEBUG(options['X'], PrNode(procedure->prc_body, 0)); - def_ilb(RETURN_LABEL); /* label at end */ - if (too_big) { - /* Fill the data area reserved for the function result + def_ilb(RETURN_LABEL); /* label at end */ + if (too_big) + { +/* Fill the data area reserved for the function result with the result */ #ifdef BIG_RESULT_ON_STACK @@ -474,11 +500,12 @@ WalkProcedure(procedure) c_lae_dlb(too_big); #endif /* BIG_RESULT_ON_STACK */ C_sti(func_res_size); - if (StackAdjustment) { + if (StackAdjustment) + { /* Remove copies of conformant arrays */ LOL(StackAdjustment, pointer_size); - C_str((arith) 1); + C_str((arith)1); } #ifdef BIG_RESULT_ON_STACK func_res_size = 0; @@ -487,17 +514,20 @@ WalkProcedure(procedure) func_res_size = pointer_size; #endif /* BIG_RESULT_ON_STACK */ } - else if (StackAdjustment) { + else if (StackAdjustment) + { /* First save the function result in a safe place. Then remove copies of conformant arrays, and put function result back on the stack */ - if (func_type) { + if (func_type) + { STL(retsav, func_res_size); } LOL(StackAdjustment, pointer_size); - C_str((arith) 1); - if (func_type) { + C_str((arith)1); + if (func_type) + { LOL(retsav, func_res_size); } } @@ -507,32 +537,36 @@ WalkProcedure(procedure) C_beginpart(partno2); C_pro(procedure->prc_name, -procscope->sc_off); #ifdef DBSYMTAB - if (options['g']) { + if (options['g']) + { stb_string(procedure, D_PROCEDURE); WalkDefList(procscope->sc_def, stabdef); stb_string(procedure, D_PEND); - C_ms_std((char *) 0, N_LBRAC, gdb_flag ? 0 : proclevel); + C_ms_std((char*)0, N_LBRAC, gdb_flag ? 0 : proclevel); } #endif /* DBSYMTAB */ C_ms_par(procedure->df_type->prc_nbpar #ifdef BIG_RESULT_ON_STACK - + (too_big ? func_res_size : 0) + + (too_big ? func_res_size : 0) #endif - ); + ); #endif - if (! options['n']) WalkDefList(procscope->sc_def, RegisterMessage); + if (!options['n']) + WalkDefList(procscope->sc_def, RegisterMessage); #ifdef USE_INSERT C_endpart(partno2); #endif #ifdef DBSYMTAB - if (options['g']) { - C_ms_std((char *) 0, N_RBRAC, gdb_flag ? 0 : proclevel); + if (options['g']) + { + C_ms_std((char*)0, N_RBRAC, gdb_flag ? 0 : proclevel); } #endif /* DBSYMTAB */ C_end(-procscope->sc_off); - if (! fit(procscope->sc_off, (int) word_size)) { + if (!fit(procscope->sc_off, (int)word_size)) + { node_error(procedure->prc_body, - "maximum local byte count exceeded"); + "maximum local byte count exceeded"); } TmpClose(); CurrVis = savevis; @@ -540,50 +574,48 @@ WalkProcedure(procedure) WalkDefList(procscope->sc_def, UseWarnings); } -static -WalkDef(df) - register t_def *df; +static WalkDef(df) register t_def* df; { /* Walk through a list of definitions */ - switch(df->df_kind) { - case D_MODULE: - WalkModule(df); - break; - case D_PROCEDURE: - WalkProcedure(df); - break; - case D_VARIABLE: - if (!proclevel && !(df->df_flags & D_ADDRGIVEN)) { - C_df_dnam(df->var_name); - C_bss_cst( - WA(df->df_type->tp_size), - (arith) 0, 0); - } - break; - default: - /* nothing */ - ; + switch (df->df_kind) + { + case D_MODULE: + WalkModule(df); + break; + case D_PROCEDURE: + WalkProcedure(df); + break; + case D_VARIABLE: + if (!proclevel && !(df->df_flags & D_ADDRGIVEN)) + { + C_df_dnam(df->var_name); + C_bss_cst( + WA(df->df_type->tp_size), + (arith)0, 0); + } + break; + default: + /* nothing */ + ; } } -static -MkCalls(df) - register t_def *df; +static MkCalls(df) register t_def* df; { /* Generate calls to initialization routines of modules */ - if (df->df_kind == D_MODULE) { - C_lxl((arith) 0); + if (df->df_kind == D_MODULE) + { + C_lxl((arith)0); CAL(df->mod_vis->sc_scope->sc_name, (int)pointer_size); } } -WalkLink(nd, exit_label, end_reached) - register t_node *nd; - label exit_label; +WalkLink(nd, exit_label, end_reached) register t_node* nd; +label exit_label; { /* Walk node "nd", which is a link. "exit_label" is set to a label number when inside a LOOP. @@ -591,7 +623,8 @@ WalkLink(nd, exit_label, end_reached) and whether an EXIT statement was seen (EXIT_FLAG). */ - while (nd && nd->nd_class == Link) { /* statement list */ + while (nd && nd->nd_class == Link) + { /* statement list */ end_reached = WalkNode(nd->nd_LEFT, exit_label, end_reached); nd = nd->nd_RIGHT; } @@ -600,85 +633,93 @@ WalkLink(nd, exit_label, end_reached) } STATIC -ForLoopVarExpr(nd) - register t_node *nd; +ForLoopVarExpr(nd) register t_node* nd; { - register t_type *tp = nd->nd_type; + register t_type* tp = nd->nd_type; CodePExpr(nd); CodeCoercion(tp, BaseType(tp)); } int -WalkStat(nd, exit_label, end_reached) - register t_node *nd; - label exit_label; + WalkStat(nd, exit_label, end_reached) register t_node* nd; +label exit_label; { /* Walk through a statement, generating code for it. */ - register t_node *left = nd->nd_LEFT; - register t_node *right = nd->nd_RIGHT; + register t_node* left = nd->nd_LEFT; + register t_node* right = nd->nd_RIGHT; assert(nd->nd_class == Stat); - if (nd->nd_symb == ';') return 1; + if (nd->nd_symb == ';') + return 1; - if (! end_reached & REACH_FLAG) { + if (!end_reached & REACH_FLAG) + { node_warning(nd, W_ORDINARY, "statement not reached"); } - if (nd->nd_symb != WHILE || - nd->nd_lineno != left->nd_lineno) { + if (nd->nd_symb != WHILE || nd->nd_lineno != left->nd_lineno) + { /* Avoid double linenumber generation in while statements */ DoLineno(nd); } options['R'] = (nd->nd_flags & ROPTION); options['A'] = (nd->nd_flags & AOPTION); - switch(nd->nd_symb) { - case '(': { - t_node *nd1 = nd; - if (ChkCall(&nd1)) { - assert(nd == nd1); - if (nd->nd_type != 0) { - node_error(nd, "procedure call expected instead of function call"); - break; + switch (nd->nd_symb) + { + case '(': + { + t_node* nd1 = nd; + if (ChkCall(&nd1)) + { + assert(nd == nd1); + if (nd->nd_type != 0) + { + node_error(nd, "procedure call expected instead of function call"); + break; + } + CodeCall(nd); } - CodeCall(nd); - } } break; - case BECOMES: - DoAssign(nd); - break; + case BECOMES: + DoAssign(nd); + break; - case IF: - { label l1 = ++text_label, l3 = ++text_label; + case IF: + { + label l1 = ++text_label, l3 = ++text_label; int end_r; ExpectBool(&(nd->nd_LEFT), l3, l1); assert(right->nd_symb == THEN); end_r = LblWalkNode(l3, right->nd_LEFT, exit_label, end_reached); - if (right->nd_RIGHT) { /* ELSE part */ + if (right->nd_RIGHT) + { /* ELSE part */ label l2 = ++text_label; c_bra(l2); end_reached = end_r | LblWalkNode(l1, right->nd_RIGHT, exit_label, end_reached); l1 = l2; } - else end_reached |= end_r; + else + end_reached |= end_r; def_ilb(l1); break; } - case CASE: - end_reached = CaseCode(nd, exit_label, end_reached); - break; + case CASE: + end_reached = CaseCode(nd, exit_label, end_reached); + break; - case WHILE: - { label loop = ++text_label, - exit = ++text_label, - dummy = ++text_label; + case WHILE: + { + label loop = ++text_label, + exit = ++text_label, + dummy = ++text_label; c_bra(dummy); end_reached |= LblWalkNode(loop, right, exit_label, end_reached); @@ -688,8 +729,9 @@ WalkStat(nd, exit_label, end_reached) break; } - case REPEAT: - { label loop = ++text_label, exit = ++text_label; + case REPEAT: + { + label loop = ++text_label, exit = ++text_label; end_reached = LblWalkNode(loop, left, exit_label, end_reached); ExpectBool(&(nd->nd_RIGHT), exit, loop); @@ -697,19 +739,22 @@ WalkStat(nd, exit_label, end_reached) break; } - case LOOP: - { label loop = ++text_label, exit = ++text_label; + case LOOP: + { + label loop = ++text_label, exit = ++text_label; - if (LblWalkNode(loop, right, exit, end_reached) & EXIT_FLAG) { + if (LblWalkNode(loop, right, exit, end_reached) & EXIT_FLAG) + { end_reached &= REACH_FLAG; } - else end_reached = 0; + else + end_reached = 0; c_bra(loop); def_ilb(exit); break; } - case FOR: + case FOR: { arith tmp = NewInt(); arith tmp2 = NewInt(); @@ -718,17 +763,19 @@ WalkStat(nd, exit_label, end_reached) label l2 = ++text_label; int uns = 0; arith stepsize; - t_type *bstp; - t_node *loopid; + t_type* bstp; + t_node* loopid; good_forvar = DoForInit(left); loopid = left->nd_LEFT; - if ((stepsize = right->nd_LEFT->nd_INT) == 0) { + if ((stepsize = right->nd_LEFT->nd_INT) == 0) + { node_warning(right->nd_LEFT, - W_ORDINARY, - "zero stepsize in FOR loop"); + W_ORDINARY, + "zero stepsize in FOR loop"); } - if (good_forvar) { + if (good_forvar) + { bstp = BaseType(loopid->nd_type); uns = bstp->tp_fund != T_INTEGER; CodePExpr(left->nd_RIGHT->nd_RIGHT); @@ -737,37 +784,46 @@ WalkStat(nd, exit_label, end_reached) C_dup(int_size); C_stl(tmp2); C_lol(tmp); - if (uns) C_cmu(int_size); - else C_cmi(int_size); - if (stepsize >= 0) C_zgt(l2); - else C_zlt(l2); + if (uns) + C_cmu(int_size); + else + C_cmi(int_size); + if (stepsize >= 0) + C_zgt(l2); + else + C_zlt(l2); C_lol(tmp2); RangeCheck(loopid->nd_type, - left->nd_RIGHT->nd_LEFT->nd_type); + left->nd_RIGHT->nd_LEFT->nd_type); CodeDStore(loopid); - if (stepsize >= 0) { + if (stepsize >= 0) + { C_lol(tmp); ForLoopVarExpr(loopid); } - else { + else + { stepsize = -stepsize; ForLoopVarExpr(loopid); C_lol(tmp); } C_sbu(int_size); - if (stepsize) { + if (stepsize) + { C_loc(stepsize); C_dvu(int_size); } C_stl(tmp); loopid->nd_def->df_flags |= D_FORLOOP; def_ilb(l1); - if (! options['R']) { + if (!options['R']) + { ForLoopVarExpr(loopid); C_stl(tmp2); } end_reached |= WalkNode(right->nd_RIGHT, exit_label, end_reached); - if (! options['R']) { + if (!options['R']) + { label x = ++text_label; C_lol(tmp2); ForLoopVarExpr(loopid); @@ -778,7 +834,8 @@ WalkStat(nd, exit_label, end_reached) } loopid->nd_def->df_flags &= ~D_FORLOOP; FreeInt(tmp2); - if (stepsize) { + if (stepsize) + { C_lol(tmp); C_zeq(l2); C_lol(tmp); @@ -792,7 +849,8 @@ WalkStat(nd, exit_label, end_reached) CodeDStore(loopid); } } - else { + else + { end_reached |= WalkNode(right->nd_RIGHT, exit_label, end_reached); loopid->nd_def->df_flags &= ~D_FORLOOP; } @@ -802,15 +860,17 @@ WalkStat(nd, exit_label, end_reached) } break; - case WITH: + case WITH: { t_scopelist link; struct withdesig wds; t_desig ds; - if (! WalkDesignator(&(nd->nd_LEFT), &ds, D_USED)) break; + if (!WalkDesignator(&(nd->nd_LEFT), &ds, D_USED)) + break; left = nd->nd_LEFT; - if (left->nd_type->tp_fund != T_RECORD) { + if (left->nd_type->tp_fund != T_RECORD) + { node_error(left, "record variable expected"); break; } @@ -836,44 +896,50 @@ WalkStat(nd, exit_label, end_reached) CurrVis = link.sc_next; WithDesigs = wds.w_next; FreePtr(ds.dsg_offset); - ChkDesig(&(nd->nd_LEFT), wds.w_flags & (D_USED|D_DEFINED)); + ChkDesig(&(nd->nd_LEFT), wds.w_flags & (D_USED | D_DEFINED)); break; } - case EXIT: - assert(exit_label != 0); + case EXIT: + assert(exit_label != 0); - if (end_reached & REACH_FLAG) end_reached = EXIT_FLAG; - c_bra(exit_label); - break; + if (end_reached & REACH_FLAG) + end_reached = EXIT_FLAG; + c_bra(exit_label); + break; - case RETURN: - end_reached &= ~REACH_FLAG; - if (right) { - if (! ChkExpression(&(nd->nd_RIGHT))) break; - /* The type of the return-expression must be + case RETURN: + end_reached &= ~REACH_FLAG; + if (right) + { + if (!ChkExpression(&(nd->nd_RIGHT))) + break; + /* The type of the return-expression must be assignment compatible with the result type of the function procedure (See Rep. 9.11). */ - if (!ChkAssCompat(&(nd->nd_RIGHT), func_type, "RETURN")) { - break; + if (!ChkAssCompat(&(nd->nd_RIGHT), func_type, "RETURN")) + { + break; + } + right = nd->nd_RIGHT; + if (right->nd_type->tp_fund == T_STRING) + { + CodePString(right, func_type); + } + else + CodePExpr(right); } - right = nd->nd_RIGHT; - if (right->nd_type->tp_fund == T_STRING) { - CodePString(right, func_type); - } - else CodePExpr(right); - } - c_bra(RETURN_LABEL); - break; + c_bra(RETURN_LABEL); + break; - default: - crash("(WalkStat)"); + default: + crash("(WalkStat)"); } return end_reached; } -extern int NodeCrash(); +extern int NodeCrash(); int (*WalkTable[])() = { NodeCrash, @@ -893,9 +959,8 @@ int (*WalkTable[])() = { extern t_desig null_desig; -ExpectBool(pnd, true_label, false_label) - register t_node **pnd; - label true_label, false_label; +ExpectBool(pnd, true_label, false_label) register t_node** pnd; +label true_label, false_label; { /* "pnd" must indicate a boolean expression. Check this and generate code to evaluate the expression. @@ -903,25 +968,27 @@ ExpectBool(pnd, true_label, false_label) t_desig ds; ds = null_desig; - if (ChkExpression(pnd)) { - if ((*pnd)->nd_type != bool_type && - (*pnd)->nd_type != error_type) { + if (ChkExpression(pnd)) + { + if ((*pnd)->nd_type != bool_type && (*pnd)->nd_type != error_type) + { node_error(*pnd, "boolean expression expected"); } - CodeExpr(*pnd, &ds, true_label, false_label); + CodeExpr(*pnd, &ds, true_label, false_label); } } int -WalkDesignator(pnd, ds, flags) - t_node **pnd; - t_desig *ds; + WalkDesignator(pnd, ds, flags) + t_node** pnd; +t_desig* ds; { /* Check designator and generate code for it */ - if (! ChkVariable(pnd, flags)) return 0; + if (!ChkVariable(pnd, flags)) + return 0; *ds = null_desig; CodeDesig(*pnd, ds); @@ -929,47 +996,54 @@ WalkDesignator(pnd, ds, flags) } DoForInit(nd) - t_node *nd; + t_node* nd; { - register t_node *right = nd->nd_RIGHT; - register t_def *df; - t_type *base_tp; + register t_node* right = nd->nd_RIGHT; + register t_def* df; + t_type* base_tp; t_type *tpl, *tpr; int r; - r = ChkVariable(&(nd->nd_LEFT), D_USED|D_DEFINED); + r = ChkVariable(&(nd->nd_LEFT), D_USED | D_DEFINED); r &= ChkExpression(&(right->nd_LEFT)); r &= ChkExpression(&(right->nd_RIGHT)); - if (!r) return 0; + if (!r) + return 0; df = nd->nd_LEFT->nd_def; - if (df->df_kind == D_FIELD) { + if (df->df_kind == D_FIELD) + { node_error(nd, - "FOR-loop variable may not be a field of a record"); + "FOR-loop variable may not be a field of a record"); return 1; } - if (!df->var_name && df->var_off >= 0) { + if (!df->var_name && df->var_off >= 0) + { node_error(nd, "FOR-loop variable may not be a parameter"); return 1; } - if (df->df_scope != CurrentScope) { - register t_scopelist *sc = CurrVis; + if (df->df_scope != CurrentScope) + { + register t_scopelist* sc = CurrVis; - for (;;) { - if (!sc) { + for (;;) + { + if (!sc) + { node_error(nd, - "FOR-loop variable may not be imported"); + "FOR-loop variable may not be imported"); return 1; } - if (sc->sc_scope == df->df_scope) break; + if (sc->sc_scope == df->df_scope) + break; sc = nextvisible(sc); } } - if (df->df_type->tp_size > word_size || - !(df->df_type->tp_fund & T_DISCRETE)) { + if (df->df_type->tp_size > word_size || !(df->df_type->tp_fund & T_DISCRETE)) + { node_error(nd, "illegal type of FOR loop variable"); return 1; } @@ -978,19 +1052,21 @@ DoForInit(nd) tpl = right->nd_LEFT->nd_type; tpr = right->nd_RIGHT->nd_type; #ifndef STRICT_3RD_ED - if (! options['3']) { - if (!ChkAssCompat(&(right->nd_LEFT), base_tp, "FOR statement") || - !ChkAssCompat(&(right->nd_RIGHT), base_tp, "FOR statement")) { - return 1; - } - if (!TstCompat(df->df_type, tpl) || - !TstCompat(df->df_type, tpr)) { -node_warning(nd, W_OLDFASHIONED, "compatibility required in FOR statement"); - } - } else + if (!options['3']) + { + if (!ChkAssCompat(&(right->nd_LEFT), base_tp, "FOR statement") || !ChkAssCompat(&(right->nd_RIGHT), base_tp, "FOR statement")) + { + return 1; + } + if (!TstCompat(df->df_type, tpl) || !TstCompat(df->df_type, tpr)) + { + node_warning(nd, W_OLDFASHIONED, "compatibility required in FOR statement"); + } + } + else #endif - if (!ChkCompat(&(right->nd_LEFT), base_tp, "FOR statement") || - !ChkCompat(&(right->nd_RIGHT), base_tp, "FOR statement")) { + if (!ChkCompat(&(right->nd_LEFT), base_tp, "FOR statement") || !ChkCompat(&(right->nd_RIGHT), base_tp, "FOR statement")) + { return 1; } @@ -998,8 +1074,7 @@ node_warning(nd, W_OLDFASHIONED, "compatibility required in FOR statement"); } void -DoAssign(nd) - register t_node *nd; + DoAssign(nd) register t_node* nd; { /* May we do it in this order (expression first) ??? The reference manual sais nothing about it, but the book does: @@ -1007,148 +1082,151 @@ DoAssign(nd) DAMN THE BOOK! */ t_desig dsr; - register t_type *tp; + register t_type* tp; - if (! (ChkExpression(&(nd->nd_RIGHT)) & - ChkVariable(&(nd->nd_LEFT), D_DEFINED))) return; + if (!(ChkExpression(&(nd->nd_RIGHT)) & ChkVariable(&(nd->nd_LEFT), D_DEFINED))) + return; tp = nd->nd_LEFT->nd_type; - if (! ChkAssCompat(&(nd->nd_RIGHT), tp, "assignment")) { + if (!ChkAssCompat(&(nd->nd_RIGHT), tp, "assignment")) + { return; } dsr = null_desig; -#define StackNeededFor(ds) ((ds).dsg_kind == DSG_PLOADED \ - || (ds).dsg_kind == DSG_INDEXED) +#define StackNeededFor(ds) ((ds).dsg_kind == DSG_PLOADED \ + || (ds).dsg_kind == DSG_INDEXED) CodeExpr(nd->nd_RIGHT, &dsr, NO_LABEL, NO_LABEL); tp = nd->nd_RIGHT->nd_type; - if (complex(tp)) { - if (StackNeededFor(dsr)) CodeAddress(&dsr); + if (complex(tp)) + { + if (StackNeededFor(dsr)) + CodeAddress(&dsr); } - else { + else + { CodeValue(&dsr, tp); } CodeMove(&dsr, nd->nd_LEFT, tp); } -static -RegisterMessage(df) - register t_def *df; +static RegisterMessage(df) register t_def* df; { - register t_type *tp; + register t_type* tp; - if (df->df_kind == D_VARIABLE) { - if ( !(df->df_flags & D_NOREG)) { + if (df->df_kind == D_VARIABLE) + { + if (!(df->df_flags & D_NOREG)) + { /* Examine type and size */ tp = BaseType(df->df_type); - if ((df->df_flags & D_VARPAR) || - (tp->tp_fund&(T_POINTER|T_HIDDEN|T_EQUAL))) { + if ((df->df_flags & D_VARPAR) || (tp->tp_fund & (T_POINTER | T_HIDDEN | T_EQUAL))) + { C_ms_reg(df->var_off, - pointer_size, - reg_pointer, - 0); + pointer_size, + reg_pointer, + 0); } - else if (tp->tp_fund & T_NUMERIC) { + else if (tp->tp_fund & T_NUMERIC) + { C_ms_reg(df->var_off, - tp->tp_size, - tp->tp_fund == T_REAL ? - reg_float : reg_any, - 0); + tp->tp_size, + tp->tp_fund == T_REAL ? reg_float : reg_any, + 0); } } } } static void -df_warning(nd, df, warning) - t_node *nd; - t_def *df; - char *warning; + df_warning(nd, df, warning) + t_node* nd; +t_def* df; +char* warning; { - if (! (df->df_kind & (D_VARIABLE|D_PROCEDURE|D_TYPE|D_CONST|D_PROCHEAD))) { + if (!(df->df_kind & (D_VARIABLE | D_PROCEDURE | D_TYPE | D_CONST | D_PROCHEAD))) + { return; } - if (warning) { + if (warning) + { node_warning(nd, - W_ORDINARY, - "%s \"%s\" %s", - (df->df_flags & D_VALPAR) ? "value parameter" : - (df->df_flags & D_VARPAR) ? "variable parameter" : - (df->df_kind == D_VARIABLE) ? "variable" : - (df->df_kind == D_TYPE) ? "type" : - (df->df_kind == D_CONST) ? "constant" : - "procedure", - df->df_idf->id_text, warning); + W_ORDINARY, + "%s \"%s\" %s", + (df->df_flags & D_VALPAR) ? "value parameter" : (df->df_flags & D_VARPAR) ? "variable parameter" : (df->df_kind == D_VARIABLE) ? "variable" : (df->df_kind == D_TYPE) ? "type" : (df->df_kind == D_CONST) ? "constant" : "procedure", + df->df_idf->id_text, warning); } } static void -UseWarnings(df) - register t_def *df; + UseWarnings(df) register t_def* df; { - t_node *nd = df->df_scope->sc_end; + t_node* nd = df->df_scope->sc_end; - if (is_anon_idf(df->df_idf) || - !(df->df_kind&(D_IMPORTED|D_VARIABLE|D_PROCEDURE|D_CONST|D_TYPE)) || - (df->df_flags&(D_EXPORTED|D_QEXPORTED))) { + if (is_anon_idf(df->df_idf) || !(df->df_kind & (D_IMPORTED | D_VARIABLE | D_PROCEDURE | D_CONST | D_TYPE)) || (df->df_flags & (D_EXPORTED | D_QEXPORTED))) + { return; } - if (df->df_kind & D_IMPORTED) { - register t_def *df1 = df->imp_def; + if (df->df_kind & D_IMPORTED) + { + register t_def* df1 = df->imp_def; - df1->df_flags |= df->df_flags & (D_USED|D_DEFINED); - if (df->df_kind == D_INUSE) return; - if ( !(df->df_flags & D_IMP_BY_EXP)) { - if (df->df_flags & (D_USED | D_DEFINED)) { + df1->df_flags |= df->df_flags & (D_USED | D_DEFINED); + if (df->df_kind == D_INUSE) + return; + if (!(df->df_flags & D_IMP_BY_EXP)) + { + if (df->df_flags & (D_USED | D_DEFINED)) + { return; } df_warning(nd, - df1, - df1->df_kind == D_VARIABLE ? - "imported but not used/assigned" : - "imported but not used"); + df1, + df1->df_kind == D_VARIABLE ? "imported but not used/assigned" : "imported but not used"); return; } df = df1; nd = df->df_scope->sc_end; } - switch(df->df_flags & (D_USED|D_DEFINED|D_VALPAR|D_VARPAR)) { - case 0: - case D_VARPAR: - df_warning(nd, df,"never used/assigned"); - break; - case D_USED: - df_warning(nd, df,"never assigned"); - break; - case D_VALPAR: - case D_DEFINED: - case D_DEFINED|D_VALPAR: - df_warning(nd, df,"never used"); - break; + switch (df->df_flags & (D_USED | D_DEFINED | D_VALPAR | D_VARPAR)) + { + case 0: + case D_VARPAR: + df_warning(nd, df, "never used/assigned"); + break; + case D_USED: + df_warning(nd, df, "never assigned"); + break; + case D_VALPAR: + case D_DEFINED: + case D_DEFINED | D_VALPAR: + df_warning(nd, df, "never used"); + break; } } -WalkDefList(df, proc) - register t_def *df; - int (*proc)(); +WalkDefList(df, proc) register t_def* df; +int (*proc)(); { - for (; df; df = df->df_nextinscope) { + for (; df; df = df->df_nextinscope) + { (*proc)(df); } } #ifdef DBSYMTAB static int -stabdef(df) - t_def *df; + stabdef(df) + t_def* df; { - switch(df->df_kind) { - case D_CONST: - case D_VARIABLE: - stb_string(df, df->df_kind); - break; + switch (df->df_kind) + { + case D_CONST: + case D_VARIABLE: + stb_string(df, df->df_kind); + break; } } #endif From 612e14b4b40098cdbb16a0567cb357944337c772 Mon Sep 17 00:00:00 2001 From: David Given Date: Sun, 8 Jan 2017 11:25:57 +0100 Subject: [PATCH 122/173] Improve confusing error message when calling function procedures from a top-level statement. Fixes: #30 --- lang/m2/comp/walk.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lang/m2/comp/walk.c b/lang/m2/comp/walk.c index b51316802..b36dbc8f0 100644 --- a/lang/m2/comp/walk.c +++ b/lang/m2/comp/walk.c @@ -676,7 +676,8 @@ label exit_label; assert(nd == nd1); if (nd->nd_type != 0) { - node_error(nd, "procedure call expected instead of function call"); + node_error(nd, "only proper procedures can be called from top-level " + "statement; this is a function procedure"); break; } CodeCall(nd); From fd83b09c587b4a2d92102cc4f734b12087d6cb25 Mon Sep 17 00:00:00 2001 From: David Given Date: Sun, 8 Jan 2017 18:53:59 +0100 Subject: [PATCH 123/173] Fix typo. --- lang/b/compiler/build.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lang/b/compiler/build.lua b/lang/b/compiler/build.lua index 6e2cc1820..c647f6036 100644 --- a/lang/b/compiler/build.lua +++ b/lang/b/compiler/build.lua @@ -22,7 +22,7 @@ installable { name = "pkg", map = { ["$(PLATDEP)/em_b"] = "+em_b", - ["$(INSDIR)/share/man/man6/em_m2.6"] = "./em_b.6" + ["$(INSDIR)/share/man/man6/em_b.6"] = "./em_b.6" } } From 8edbff9795ef559eaefefefdf1760f57b3a926c8 Mon Sep 17 00:00:00 2001 From: David Given Date: Sun, 15 Jan 2017 00:15:01 +0100 Subject: [PATCH 124/173] Add assembler support for fixing up arbitrary oris/addi pairs of instructions; this should allow oris/lwz constant value loads, which will save an opcode. --- mach/powerpc/as/mach2.c | 3 ++ mach/powerpc/as/mach3.c | 5 ++- mach/powerpc/as/mach4.c | 88 +++++++++++++++++++++++++++++------------ mach/powerpc/as/mach5.c | 1 - mach/powerpc/ncg/table | 24 ++++++++--- util/led/relocate.c | 19 +++++---- 6 files changed, 97 insertions(+), 43 deletions(-) diff --git a/mach/powerpc/as/mach2.c b/mach/powerpc/as/mach2.c index 480c5faa3..a07f21b99 100644 --- a/mach/powerpc/as/mach2.c +++ b/mach/powerpc/as/mach2.c @@ -84,6 +84,9 @@ %token OP_LA %token OP_LI32 +%token OP_POWERPC_FIXUP +%token OP_HI OP_LO + /* Other token types */ %type c diff --git a/mach/powerpc/as/mach3.c b/mach/powerpc/as/mach3.c index 0f0bfdae7..62ed20471 100644 --- a/mach/powerpc/as/mach3.c +++ b/mach/powerpc/as/mach3.c @@ -102,6 +102,9 @@ 0, OP_LA, 0, "la", 0, OP_LA, 0, "li", 0, OP_RS_RA_RA_C, 31<<26 | 444<<1, "mr", +0, OP_POWERPC_FIXUP, 0, ".powerpcfixup", +0, OP_HI, 0, "hi", +0, OP_LO, 0, "lo", /* Branch processor instructions (page 20) */ @@ -270,7 +273,7 @@ 0, OP_RS_RA_SH_ME6_SH_C, 30<<26 | 1<<2, "rldicr", 0, OP_RS_RA_SH_MB6_SH_C, 30<<26 | 2<<2, "rldic", 0, OP_RS_RA_SH_MB5_ME5_C, 21<<26, "rlwinm", -0, OP_RS_RA_RB_MB6_C, 30<<26 | 8<<1, "rldcl", +0, OP_RS_RA_RB_MB6_C, 30<<26 | 8<<1, "rldcl", 0, OP_RS_RA_RB_ME6_C, 30<<26 | 9<<1, "rldcr", 0, OP_RS_RA_RB_MB5_ME5_C, 23<<26, "rlwnm", 0, OP_RS_RA_SH_MB6_SH_C, 30<<26 | 3<<2, "rldimi", diff --git a/mach/powerpc/as/mach4.c b/mach/powerpc/as/mach4.c index e1fb3fdf0..d9e4b0371 100644 --- a/mach/powerpc/as/mach4.c +++ b/mach/powerpc/as/mach4.c @@ -19,9 +19,9 @@ operation | OP_FRS_RA_D FPR ',' e16 '(' GPR ')' { emit4($1 | ($2<<21) | ($6<<16) | $4); } | OP_FRS_RA_RB FPR ',' GPR ',' GPR { emit4($1 | ($2<<21) | ($4<<16) | ($6<<11)); } | OP_FRT_FRA_FRB_C c FPR ',' FPR ',' FPR { emit4($1 | $2 | ($3<<21) | ($5<<16) | ($7<<11)); } - | OP_FRT_FRA_FRC_FRB_C c FPR ',' FPR ',' FPR ',' FPR { emit4($1 | $2 | ($3<<21) | ($5<<16) | ($9<<11) | ($7<<6)); } + | OP_FRT_FRA_FRC_FRB_C c FPR ',' FPR ',' FPR ',' FPR { emit4($1 | $2 | ($3<<21) | ($5<<16) | ($9<<11) | ($7<<6)); } | OP_FRT_FRA_FRC_C c FPR ',' FPR ',' FPR { emit4($1 | $2 | ($3<<21) | ($5<<16) | ($7<<6)); } - | OP_FRT_FRB_C c FPR ',' FPR { emit4($1 | $2 | ($3<<21) | ($5<<11)); } + | OP_FRT_FRB_C c FPR ',' FPR { emit4($1 | $2 | ($3<<21) | ($5<<11)); } | OP_FRT_RA_D FPR ',' e16 '(' GPR ')' { emit4($1 | ($2<<21) | ($6<<16) | $4); } | OP_FRT_RA_RB FPR ',' GPR ',' GPR { emit4($1 | ($2<<21) | ($4<<16) | ($6<<11)); } | OP_FRT_C c FPR { emit4($1 | $2 | ($3<<21)); } @@ -40,15 +40,15 @@ operation | OP_RS_RA_D GPR ',' e16 '(' GPR ')' { emit4($1 | ($2<<21) | ($6<<16) | $4); } | OP_RS_RA_DS GPR ',' ds '(' GPR ')' { emit4($1 | ($2<<21) | ($6<<16) | $4); } | OP_RS_RA_NB GPR ',' GPR ',' nb { emit4($1 | ($2<<21) | ($4<<16) | ($6<<11)); } - | OP_RS_RA_UI GPR ',' GPR ',' e16 { emit4($1 | ($4<<21) | ($2<<16) | $6); } - | OP_RS_RA_UI_CC C GPR ',' GPR ',' e16 { emit4($1 | ($5<<21) | ($3<<16) | $7); } + | OP_RS_RA_UI GPR ',' GPR ',' e16 { emit4($1 | ($4<<21) | ($2<<16) | $6); } + | OP_RS_RA_UI_CC C GPR ',' GPR ',' e16 { emit4($1 | ($5<<21) | ($3<<16) | $7); } | OP_RS_RA_RB GPR ',' GPR ',' GPR { emit4($1 | ($2<<21) | ($4<<16) | ($6<<11)); } | OP_RS_RA_RB_C c GPR ',' GPR ',' GPR { emit4($1 | $2 | ($5<<21) | ($3<<16) | ($7<<11)); } | OP_RS_RA_RA_C c GPR ',' GPR { emit4($1 | $2 | ($5<<21) | ($3<<16) | ($5<<11)); } - | OP_RS_RA_RB_MB5_ME5_C c GPR ',' GPR ',' GPR ',' u5 ',' u5 { emit4($1 | $2 | ($5<<21) | ($3<<16) | ($7<<11) | ($9<<6) | ($11<<1)); } + | OP_RS_RA_RB_MB5_ME5_C c GPR ',' GPR ',' GPR ',' u5 ',' u5 { emit4($1 | $2 | ($5<<21) | ($3<<16) | ($7<<11) | ($9<<6) | ($11<<1)); } | OP_RS_RA_RB_MB6_C c GPR ',' GPR ',' GPR ',' u6 { emit4($1 | $2 | ($5<<21) | ($3<<16) | ($7<<11) | (($9&0x1F)<<6) | (($9&0x20)>>0)); } | OP_RS_RA_RB_ME6_C c GPR ',' GPR ',' GPR ',' u6 { emit4($1 | $2 | ($5<<21) | ($3<<16) | ($7<<11) | (($9&0x1F)<<6) | (($9&0x20)>>0)); } - | OP_RS_RA_SH_MB5_ME5_C c GPR ',' GPR ',' u5 ',' u5 ',' u5 { emit4($1 | $2 | ($5<<21) | ($3<<16) | ($7<<11) | ($9<<6) | ($11<<1)); } + | OP_RS_RA_SH_MB5_ME5_C c GPR ',' GPR ',' u5 ',' u5 ',' u5 { emit4($1 | $2 | ($5<<21) | ($3<<16) | ($7<<11) | ($9<<6) | ($11<<1)); } | OP_RS_RA_SH_MB6_SH_C c GPR ',' GPR ',' u6 ',' u6 { emit4($1 | $2 | ($5<<21) | ($3<<16) | (($7&0x1F)<<11) | ($9<<6) | (($7&0x20)>>4)); } | OP_RS_RA_SH_ME6_SH_C c GPR ',' GPR ',' u6 ',' u6 { emit4($1 | $2 | ($5<<21) | ($3<<16) | (($7&0x1F)<<11) | ($9<<6) | (($7&0x20)>>4)); } | OP_RS_RA_SH5_C c GPR ',' GPR ',' u5 { emit4($1 | $2 | ($5<<21) | ($3<<16) | ($7<<11)); } @@ -60,13 +60,14 @@ operation | OP_LIA lia { emit4($1 | $2); } | OP_LIL lil { emit4($1 | $2); } | OP_LI32 li32 /* emitted in subrule */ + | OP_POWERPC_FIXUP powerpcfixup /* emitted in subrule */ ; c : /* nothing */ { $$ = 0; } | C { $$ = 1; } ; - + e16 : absexp { @@ -75,8 +76,34 @@ e16 serror("16-bit value out of range"); $$ = (uint16_t) $1; } + | OP_HI expr + { + /* If this is a symbol reference, discard the symbol and keep only the + * offset part. */ + quad type = $2.typ & S_TYP; + quad val = $2.val; + + /* If the assembler stored a symbol for relocation later, we need to + * abandon it (because we're not going to generate a relocation). */ + if (type != S_ABS) + relonami = 0; + + $$ = ((quad)val) >> 16; + } + | OP_LO expr + { + quad type = $2.typ & S_TYP; + quad val = $2.val; + + /* If the assembler stored a symbol for relocation later, we need to + * abandon it (because we're not going to generate a relocation). */ + if (type != S_ABS) + relonami = 0; + + $$ = val & 0xffff; + } ; - + u8 : absexp { @@ -85,7 +112,7 @@ u8 $$ = $1; } ; - + u7 : absexp { @@ -94,7 +121,7 @@ u7 $$ = $1; } ; - + u6 : absexp { @@ -103,7 +130,7 @@ u6 $$ = $1; } ; - + u5 : absexp { @@ -112,7 +139,7 @@ u5 $$ = $1; } ; - + u4 : absexp { @@ -121,7 +148,7 @@ u4 $$ = $1; } ; - + u1 : absexp { @@ -130,7 +157,7 @@ u1 $$ = $1; } ; - + u2 : absexp { @@ -139,7 +166,7 @@ u2 $$ = $1; } ; - + ds : e16 { @@ -148,26 +175,26 @@ ds $$ = $1; } ; - + nb : absexp { if (($1 < 1) || ($1 > 32)) serror("register count must be in the range 1..32"); - + if ($1 == 32) $$ = 0; else - $$ = $1; + $$ = $1; } ; - + bdl : expr { int dist = $1.val - DOTVAL; fit(fitx(dist, 25)); - + if (dist & 0x3) serror("jump targets must be 4-aligned"); @@ -183,7 +210,7 @@ bda { int target = $1.val; fit(fitx(target, 16)); - + if (target & 0x3) serror("jump targets must be 4-aligned"); @@ -193,7 +220,7 @@ bda $$ = target & 0xFFFD; } ; - + li32 : GPR ',' expr { @@ -215,7 +242,7 @@ lil { int dist = $1.val - DOTVAL; fit(fitx(dist, 26)); - + if (dist & 0x3) serror("jump targets must be 4-aligned"); @@ -223,13 +250,13 @@ lil $$ = dist & 0x03FFFFFD; } ; - + lia : expr { int target = $1.val; fit(fitx(target, 26)); - + if (target & 0x3) serror("jump targets must be 4-aligned"); @@ -248,3 +275,14 @@ spr_num $$ = ($1 >> 5) | (($1 & 0x1f) << 5); } ; + +powerpcfixup + : expr + { + quad type = $1.typ & S_TYP; + quad val = $1.val; + if (type == S_ABS) + serror(".powerpcfixup is useless on absolute values"); + newrelo($1.typ, RELOPPC | FIXUPFLAGS); + } + ; diff --git a/mach/powerpc/as/mach5.c b/mach/powerpc/as/mach5.c index 998cd8d9c..5b8eb9167 100644 --- a/mach/powerpc/as/mach5.c +++ b/mach/powerpc/as/mach5.c @@ -2,4 +2,3 @@ * $Source$ * $State$ */ - diff --git a/mach/powerpc/ncg/table b/mach/powerpc/ncg/table index 52f335c3d..29353a259 100644 --- a/mach/powerpc/ncg/table +++ b/mach/powerpc/ncg/table @@ -169,11 +169,14 @@ TOKENS /* Used only in instruction descriptions (to generate the correct syntax). */ GPRINDIRECT = { GPR reg; INT off; } 4 off "(" reg ")". + GPRINDIRECT_OFFSET_LO = { GPR reg; ADDR adr; } 4 "lo [" adr "](" reg ")". CONST = { INT val; } 4 val. /* Primitives */ LABEL = { ADDR adr; } 4 adr. + LABEL_OFFSET_HI = { ADDR adr; } 4 "hi " adr. + LABEL_OFFSET_LO = { ADDR adr; } 4 "lo " adr. LOCAL = { INT off; } 4. /* Allows us to use regvar() to refer to registers */ @@ -282,7 +285,7 @@ INSTRUCTIONS add GPR:wo, GPR:ro, GPR:ro. addX "add." GPR:wo, GPR:ro, GPR:ro. addi GPR:wo, GPR:ro, CONST:ro. - addis GPR:wo, GPR:ro, CONST:ro. + addis GPR:wo, GPR:ro, CONST+LABEL_OFFSET_HI:ro. and GPR:wo, GPR:ro, GPR:ro. andc GPR:wo, GPR:ro, GPR:ro. andiX "andi." GPR:wo:cc, GPR:ro, CONST:ro. @@ -329,10 +332,9 @@ INSTRUCTIONS lhz GPR:wo, GPRINDIRECT:ro cost(4, 3). lhzx GPR:wo, GPR:ro, GPR:ro cost(4, 3). li32 GPR:wo, CONST:ro cost(8, 2). - li32 GPR:wo, LABEL:ro cost(8, 2). lwzu GPR:wo, GPRINDIRECT:ro cost(4, 3). lwzx GPR:wo, GPR:ro, GPR:ro cost(4, 3). - lwz GPR:wo, GPRINDIRECT:ro cost(4, 3). + lwz GPR:wo, GPRINDIRECT+GPRINDIRECT_OFFSET_LO:ro cost(4, 3). nand GPR:wo, GPR:ro, GPR:ro. neg GPR:wo, GPR:ro. nor GPR:wo, GPR:ro, GPR:ro. @@ -342,7 +344,7 @@ INSTRUCTIONS mtspr SPR:wo, GPR:ro cost(4, 2). or GPR:wo, GPR:ro, GPR:ro. orc GPR:wo, GPR:ro, GPR:ro. - ori GPR:wo, GPR:ro, CONST:ro. + ori GPR:wo, GPR:ro, CONST+LABEL_OFFSET_LO:ro. oris GPR:wo, GPR:ro, CONST:ro. orX "or." GPR:wo:cc, GPR:ro, GPR:ro. rlwinm GPR:wo, GPR:ro, CONST:ro, CONST:ro, CONST:ro. @@ -368,7 +370,8 @@ INSTRUCTIONS xori GPR:wo, GPR:ro, CONST:ro. xoris GPR:wo, GPR:ro, CONST:ro. - comment "!" LABEL:ro cost(0, 0). + fixup ".powerpcfixup" LABEL:ro. + comment "!" LABEL:ro cost(0, 0). @@ -405,7 +408,9 @@ MOVES from LABEL to GPR gen COMMENT("move LABEL->GPR") - li32 %2, {LABEL, %1.adr} + fixup {LABEL, %1.adr} + addis %2, R0, {LABEL_OFFSET_HI, %1.adr} + ori %2, %2, {LABEL_OFFSET_LO, %1.adr} /* Sign extension */ @@ -1142,6 +1147,13 @@ PATTERNS yields {IND_RC_H, %1.reg, %1.off} pat loi $1==INT32 /* Load word indirect */ + with LABEL + uses REG + gen + fixup {LABEL, %1.adr} + addis %a, R0, {LABEL_OFFSET_HI, %1.adr} + lwz %a, {GPRINDIRECT_OFFSET_LO, %a, %1.adr} + yields %a with GPR yields {IND_RC_W, %1, 0} with SUM_RC diff --git a/util/led/relocate.c b/util/led/relocate.c index c72965e75..02b0be381 100644 --- a/util/led/relocate.c +++ b/util/led/relocate.c @@ -119,14 +119,13 @@ static uint32_t get_powerpc_valu(char* addr, uint16_t type) /* branch instruction */ return opcode1 & 0x03fffffd; } - else if (((opcode1 & 0xfc1f0000) == 0x3c000000) && - ((opcode2 & 0xfc000000) == 0x60000000)) + else { - /* addis / ori instruction pair */ + /* If it's not a branch, we're just going to assume that the user + * knows what they're doing and this is a addis/ori pair (or + * compatible). */ return ((opcode1 & 0xffff) << 16) | (opcode2 & 0xffff); } - - assert(0 && "unrecognised PowerPC instruction"); } /* @@ -260,17 +259,17 @@ static void put_powerpc_valu(char* addr, uint32_t value, uint16_t type) i |= value & 0x03fffffd; write4(i, addr, type); } - else if (((opcode1 & 0xfc1f0000) == 0x3c000000) && - ((opcode2 & 0xfc000000) == 0x60000000)) + else { + /* If it's not a branch, we're just going to assume that the user + * knows what they're doing and this is a addis/ori pair (or + * compatible). */ uint16_t hi = value >> 16; uint16_t lo = value & 0xffff; write4((opcode1 & 0xffff0000) | hi, addr+0, type); write4((opcode2 & 0xffff0000) | lo, addr+4, type); } - else - assert(0 && "unrecognised PowerPC instruction"); } /* @@ -339,7 +338,7 @@ addrelo(relo, names, valu_out) extern int hash(); extern struct outname *searchname(); extern unsigned indexof(); - extern struct outhead outhead; + extern struct outhead outhead; name = searchname(local->on_mptr, hash(local->on_mptr)); if (name == (struct outname *)0) From 3c0bc205fcf8e38cf4fc6658412ee254ac2cf248 Mon Sep 17 00:00:00 2001 From: David Given Date: Sun, 15 Jan 2017 10:21:02 +0100 Subject: [PATCH 125/173] Update the hi/lo syntax to be a bit more standard. --- mach/powerpc/as/mach3.c | 4 ++-- mach/powerpc/as/mach4.c | 12 ++++++------ mach/powerpc/ncg/table | 6 +++--- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/mach/powerpc/as/mach3.c b/mach/powerpc/as/mach3.c index 62ed20471..a40e2495d 100644 --- a/mach/powerpc/as/mach3.c +++ b/mach/powerpc/as/mach3.c @@ -103,8 +103,8 @@ 0, OP_LA, 0, "li", 0, OP_RS_RA_RA_C, 31<<26 | 444<<1, "mr", 0, OP_POWERPC_FIXUP, 0, ".powerpcfixup", -0, OP_HI, 0, "hi", -0, OP_LO, 0, "lo", +0, OP_HI, 0, "ha16", +0, OP_LO, 0, "lo16", /* Branch processor instructions (page 20) */ diff --git a/mach/powerpc/as/mach4.c b/mach/powerpc/as/mach4.c index d9e4b0371..016877576 100644 --- a/mach/powerpc/as/mach4.c +++ b/mach/powerpc/as/mach4.c @@ -76,12 +76,12 @@ e16 serror("16-bit value out of range"); $$ = (uint16_t) $1; } - | OP_HI expr + | OP_HI ASC_LPAR expr ASC_RPAR { /* If this is a symbol reference, discard the symbol and keep only the * offset part. */ - quad type = $2.typ & S_TYP; - quad val = $2.val; + quad type = $3.typ & S_TYP; + quad val = $3.val; /* If the assembler stored a symbol for relocation later, we need to * abandon it (because we're not going to generate a relocation). */ @@ -90,10 +90,10 @@ e16 $$ = ((quad)val) >> 16; } - | OP_LO expr + | OP_LO ASC_LPAR expr ASC_RPAR { - quad type = $2.typ & S_TYP; - quad val = $2.val; + quad type = $3.typ & S_TYP; + quad val = $3.val; /* If the assembler stored a symbol for relocation later, we need to * abandon it (because we're not going to generate a relocation). */ diff --git a/mach/powerpc/ncg/table b/mach/powerpc/ncg/table index 29353a259..a907e4294 100644 --- a/mach/powerpc/ncg/table +++ b/mach/powerpc/ncg/table @@ -169,14 +169,14 @@ TOKENS /* Used only in instruction descriptions (to generate the correct syntax). */ GPRINDIRECT = { GPR reg; INT off; } 4 off "(" reg ")". - GPRINDIRECT_OFFSET_LO = { GPR reg; ADDR adr; } 4 "lo [" adr "](" reg ")". + GPRINDIRECT_OFFSET_LO = { GPR reg; ADDR adr; } 4 "lo16[" adr "](" reg ")". CONST = { INT val; } 4 val. /* Primitives */ LABEL = { ADDR adr; } 4 adr. - LABEL_OFFSET_HI = { ADDR adr; } 4 "hi " adr. - LABEL_OFFSET_LO = { ADDR adr; } 4 "lo " adr. + LABEL_OFFSET_HI = { ADDR adr; } 4 "ha16[" adr "]". + LABEL_OFFSET_LO = { ADDR adr; } 4 "lo16[" adr "]". LOCAL = { INT off; } 4. /* Allows us to use regvar() to refer to registers */ From 14aab2120463064cbd196cf9fc39e77ed419a163 Mon Sep 17 00:00:00 2001 From: David Given Date: Sun, 15 Jan 2017 10:31:20 +0100 Subject: [PATCH 126/173] Revert change; addis/ori requires different handling to addis/lwz due to ori's payload being unsigned while lwz's payload is signed. --- util/led/relocate.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/util/led/relocate.c b/util/led/relocate.c index 02b0be381..9e5c92b7c 100644 --- a/util/led/relocate.c +++ b/util/led/relocate.c @@ -119,13 +119,14 @@ static uint32_t get_powerpc_valu(char* addr, uint16_t type) /* branch instruction */ return opcode1 & 0x03fffffd; } - else + else if (((opcode1 & 0xfc1f0000) == 0x3c000000) && + ((opcode2 & 0xfc000000) == 0x60000000)) { - /* If it's not a branch, we're just going to assume that the user - * knows what they're doing and this is a addis/ori pair (or - * compatible). */ + /* addis / ori instruction pair */ return ((opcode1 & 0xffff) << 16) | (opcode2 & 0xffff); } + + assert(0 && "unrecognised PowerPC instruction"); } /* @@ -259,17 +260,17 @@ static void put_powerpc_valu(char* addr, uint32_t value, uint16_t type) i |= value & 0x03fffffd; write4(i, addr, type); } - else + else if (((opcode1 & 0xfc1f0000) == 0x3c000000) && + ((opcode2 & 0xfc000000) == 0x60000000)) { - /* If it's not a branch, we're just going to assume that the user - * knows what they're doing and this is a addis/ori pair (or - * compatible). */ uint16_t hi = value >> 16; uint16_t lo = value & 0xffff; write4((opcode1 & 0xffff0000) | hi, addr+0, type); write4((opcode2 & 0xffff0000) | lo, addr+4, type); } + else + assert(0 && "unrecognised PowerPC instruction"); } /* From f80acfe9f5cdbdea954df4d553fd347129b34038 Mon Sep 17 00:00:00 2001 From: David Given Date: Sun, 15 Jan 2017 11:51:37 +0100 Subject: [PATCH 127/173] Signed vs unsigned lower halves of powerpc fixups are now handled by having two assembler directives, ha16() and has16(), for the upper half; has16() applies the sign adjustment. .powerpcfixup is now gone, as we generate the relocation in ha*() instead. Add special logic to the linker for undoing and redoing the sign adjustment when reading/writing fixups. Tests still pass. --- mach/powerpc/as/mach1.c | 4 +++ mach/powerpc/as/mach2.c | 2 +- mach/powerpc/as/mach3.c | 4 +-- mach/powerpc/as/mach4.c | 30 +++------------------- mach/powerpc/as/mach5.c | 42 ++++++++++++++++++++++++++++--- mach/powerpc/ncg/table | 12 ++++----- util/led/const.h | 2 -- util/led/debug.h | 2 ++ util/led/relocate.c | 55 +++++++++++++++++++++++++++++++++++++++-- 9 files changed, 108 insertions(+), 45 deletions(-) diff --git a/mach/powerpc/as/mach1.c b/mach/powerpc/as/mach1.c index 998cd8d9c..8cf9ca282 100644 --- a/mach/powerpc/as/mach1.c +++ b/mach/powerpc/as/mach1.c @@ -3,3 +3,7 @@ * $State$ */ +#include + +extern quad emit_ha(struct expr_t* expr, bool is_signed); +extern quad emit_lo(struct expr_t* expr); diff --git a/mach/powerpc/as/mach2.c b/mach/powerpc/as/mach2.c index a07f21b99..f64d148cd 100644 --- a/mach/powerpc/as/mach2.c +++ b/mach/powerpc/as/mach2.c @@ -85,7 +85,7 @@ %token OP_LI32 %token OP_POWERPC_FIXUP -%token OP_HI OP_LO +%token OP_HA OP_HAS OP_LO /* Other token types */ diff --git a/mach/powerpc/as/mach3.c b/mach/powerpc/as/mach3.c index a40e2495d..74415aa9f 100644 --- a/mach/powerpc/as/mach3.c +++ b/mach/powerpc/as/mach3.c @@ -102,8 +102,8 @@ 0, OP_LA, 0, "la", 0, OP_LA, 0, "li", 0, OP_RS_RA_RA_C, 31<<26 | 444<<1, "mr", -0, OP_POWERPC_FIXUP, 0, ".powerpcfixup", -0, OP_HI, 0, "ha16", +0, OP_HA, 0, "ha16", +0, OP_HAS, 0, "has16", 0, OP_LO, 0, "lo16", /* Branch processor instructions (page 20) */ diff --git a/mach/powerpc/as/mach4.c b/mach/powerpc/as/mach4.c index 016877576..bb6f5163b 100644 --- a/mach/powerpc/as/mach4.c +++ b/mach/powerpc/as/mach4.c @@ -60,7 +60,6 @@ operation | OP_LIA lia { emit4($1 | $2); } | OP_LIL lil { emit4($1 | $2); } | OP_LI32 li32 /* emitted in subrule */ - | OP_POWERPC_FIXUP powerpcfixup /* emitted in subrule */ ; c @@ -76,32 +75,9 @@ e16 serror("16-bit value out of range"); $$ = (uint16_t) $1; } - | OP_HI ASC_LPAR expr ASC_RPAR - { - /* If this is a symbol reference, discard the symbol and keep only the - * offset part. */ - quad type = $3.typ & S_TYP; - quad val = $3.val; - - /* If the assembler stored a symbol for relocation later, we need to - * abandon it (because we're not going to generate a relocation). */ - if (type != S_ABS) - relonami = 0; - - $$ = ((quad)val) >> 16; - } - | OP_LO ASC_LPAR expr ASC_RPAR - { - quad type = $3.typ & S_TYP; - quad val = $3.val; - - /* If the assembler stored a symbol for relocation later, we need to - * abandon it (because we're not going to generate a relocation). */ - if (type != S_ABS) - relonami = 0; - - $$ = val & 0xffff; - } + | OP_HA ASC_LPAR expr ASC_RPAR { $$ = emit_ha(&$3, false); } + | OP_HAS ASC_LPAR expr ASC_RPAR { $$ = emit_ha(&$3, true); } + | OP_LO ASC_LPAR expr ASC_RPAR { $$ = emit_lo(&$3); } ; u8 diff --git a/mach/powerpc/as/mach5.c b/mach/powerpc/as/mach5.c index 5b8eb9167..a8e4cd043 100644 --- a/mach/powerpc/as/mach5.c +++ b/mach/powerpc/as/mach5.c @@ -1,4 +1,38 @@ -/* - * $Source$ - * $State$ - */ + +quad emit_ha(struct expr_t* expr, bool is_signed) +{ + /* If this is a symbol reference, discard the symbol and keep only the + * offset part. */ + quad type = expr->typ & S_TYP; + quad val = expr->val; + uint16_t hi = val >> 16; + uint16_t lo = val & 0xffff; + + if (type != S_ABS) + newrelo(expr->typ, RELOPPC | FIXUPFLAGS); + + /* If the low half of this relocation is going to be a memory operation, + * then it'll be treated as a signed value. That means that values greater + * than 0x7fff will cause the high word to have 1 subtracted from it; so + * we apply an adjustment here. + */ + + if (is_signed && (lo > 0x7fff)) + hi++; + + return hi; +} + +quad emit_lo(struct expr_t* expr) +{ + quad type = expr->typ & S_TYP; + quad val = expr->val; + + /* If the assembler stored a symbol for relocation later, we need to + * abandon it (because the relocation was generated by emit_ha). */ + + if (type != S_ABS) + relonami = 0; + + return val & 0xffff; +} diff --git a/mach/powerpc/ncg/table b/mach/powerpc/ncg/table index a907e4294..d37bed8f0 100644 --- a/mach/powerpc/ncg/table +++ b/mach/powerpc/ncg/table @@ -175,7 +175,8 @@ TOKENS /* Primitives */ LABEL = { ADDR adr; } 4 adr. - LABEL_OFFSET_HI = { ADDR adr; } 4 "ha16[" adr "]". + LABEL_OFFSET_HA = { ADDR adr; } 4 "ha16[" adr "]". + LABEL_OFFSET_HAS = { ADDR adr; } 4 "has16[" adr "]". LABEL_OFFSET_LO = { ADDR adr; } 4 "lo16[" adr "]". LOCAL = { INT off; } 4. @@ -285,7 +286,7 @@ INSTRUCTIONS add GPR:wo, GPR:ro, GPR:ro. addX "add." GPR:wo, GPR:ro, GPR:ro. addi GPR:wo, GPR:ro, CONST:ro. - addis GPR:wo, GPR:ro, CONST+LABEL_OFFSET_HI:ro. + addis GPR:wo, GPR:ro, CONST+LABEL_OFFSET_HA+LABEL_OFFSET_HAS:ro. and GPR:wo, GPR:ro, GPR:ro. andc GPR:wo, GPR:ro, GPR:ro. andiX "andi." GPR:wo:cc, GPR:ro, CONST:ro. @@ -370,7 +371,6 @@ INSTRUCTIONS xori GPR:wo, GPR:ro, CONST:ro. xoris GPR:wo, GPR:ro, CONST:ro. - fixup ".powerpcfixup" LABEL:ro. comment "!" LABEL:ro cost(0, 0). @@ -408,8 +408,7 @@ MOVES from LABEL to GPR gen COMMENT("move LABEL->GPR") - fixup {LABEL, %1.adr} - addis %2, R0, {LABEL_OFFSET_HI, %1.adr} + addis %2, R0, {LABEL_OFFSET_HA, %1.adr} ori %2, %2, {LABEL_OFFSET_LO, %1.adr} /* Sign extension */ @@ -1150,8 +1149,7 @@ PATTERNS with LABEL uses REG gen - fixup {LABEL, %1.adr} - addis %a, R0, {LABEL_OFFSET_HI, %1.adr} + addis %a, R0, {LABEL_OFFSET_HAS, %1.adr} lwz %a, {GPRINDIRECT_OFFSET_LO, %a, %1.adr} yields %a with GPR diff --git a/util/led/const.h b/util/led/const.h index 40ad395b5..d2d27f51a 100644 --- a/util/led/const.h +++ b/util/led/const.h @@ -4,8 +4,6 @@ */ /* $Id$ */ -typedef int bool; - #define FALSE 0 #define TRUE 1 diff --git a/util/led/debug.h b/util/led/debug.h index 0e493185d..715409d25 100644 --- a/util/led/debug.h +++ b/util/led/debug.h @@ -17,3 +17,5 @@ extern int DEB; extern int Verbose; #define verbose(s, a1, a2, a3, a4) (Verbose && do_verbose(s, a1, a2, a3, a4)) + +extern void fatal(char* format, ...); diff --git a/util/led/relocate.c b/util/led/relocate.c index 9e5c92b7c..613a0afa7 100644 --- a/util/led/relocate.c +++ b/util/led/relocate.c @@ -9,6 +9,7 @@ static char rcsid[] = "$Id$"; #include #include #include +#include #include #include "out.h" #include "const.h" @@ -104,6 +105,24 @@ static uint32_t get_vc4_valu(char* addr) assert(0 && "unrecognised VC4 instruction"); } +static bool is_powerpc_memory_op(uint32_t opcode) +{ + /* Tests for any PowerPC memory indirection instruction where the payload + * is a *signed* 16-bit value. */ + switch ((opcode & 0xfc000000) >> 26) + { + case 34: /* lbz */ + case 40: /* lhz */ + case 32: /* lwz */ + case 38: /* stb */ + case 44: /* sth */ + case 36: /* stw */ + return true; + } + + return false; +} + /* PowerPC fixups are complex as we need to patch up to the next two * instructions in one of several different ways, depending on what the * instructions area. @@ -125,8 +144,23 @@ static uint32_t get_powerpc_valu(char* addr, uint16_t type) /* addis / ori instruction pair */ return ((opcode1 & 0xffff) << 16) | (opcode2 & 0xffff); } + else if (((opcode1 & 0xfc1f0000) == 0x3c000000) && + is_powerpc_memory_op(opcode2)) + { + /* addis / memoryop instruction pair */ + uint16_t hi = opcode1 & 0xffff; + uint16_t lo = opcode2 & 0xffff; - assert(0 && "unrecognised PowerPC instruction"); + /* Undo the sign adjustment (see mach/powerpc/as/mach5.c). */ + + if (lo > 0x7fff) + hi--; + + return ((hi << 16) | lo); + } + + fatal("Don't know how to read from PowerPC fixup on instructions 0x%08x+0x%08x", + opcode1, opcode2); } /* @@ -269,8 +303,25 @@ static void put_powerpc_valu(char* addr, uint32_t value, uint16_t type) write4((opcode1 & 0xffff0000) | hi, addr+0, type); write4((opcode2 & 0xffff0000) | lo, addr+4, type); } + else if (((opcode1 & 0xfc1f0000) == 0x3c000000) && + is_powerpc_memory_op(opcode2)) + { + /* addis / memoryop instruction pair */ + uint16_t hi = value >> 16; + uint16_t lo = value & 0xffff; + + /* Apply the sign adjustment (see mach/powerpc/as/mach5.c). */ + + if (lo > 0x7fff) + hi++; + + write4((opcode1 & 0xffff0000) | hi, addr+0, type); + write4((opcode2 & 0xffff0000) | lo, addr+4, type); + } + else - assert(0 && "unrecognised PowerPC instruction"); + fatal("Don't know how to write a PowerPC fixup to instructions 0x%08x+0x%08x", + opcode1, opcode2); } /* From 9a346c382d74e07471b7025d6aa8364dc00bbe6d Mon Sep 17 00:00:00 2001 From: David Given Date: Sun, 15 Jan 2017 11:59:33 +0100 Subject: [PATCH 128/173] Turns out Apple's hi16/ha16 exactly match my ha16/has16, so renamed accordingly. (Memo to self: read the docs *before* doing the work.) --- mach/powerpc/as/mach1.c | 2 +- mach/powerpc/as/mach2.c | 2 +- mach/powerpc/as/mach3.c | 4 ++-- mach/powerpc/as/mach4.c | 4 ++-- mach/powerpc/as/mach5.c | 2 +- mach/powerpc/ncg/table | 8 ++++---- util/led/relocate.c | 1 + 7 files changed, 12 insertions(+), 11 deletions(-) diff --git a/mach/powerpc/as/mach1.c b/mach/powerpc/as/mach1.c index 8cf9ca282..c1651fcfe 100644 --- a/mach/powerpc/as/mach1.c +++ b/mach/powerpc/as/mach1.c @@ -5,5 +5,5 @@ #include -extern quad emit_ha(struct expr_t* expr, bool is_signed); +extern quad emit_hi(struct expr_t* expr, bool is_signed); extern quad emit_lo(struct expr_t* expr); diff --git a/mach/powerpc/as/mach2.c b/mach/powerpc/as/mach2.c index f64d148cd..3ecaf10cf 100644 --- a/mach/powerpc/as/mach2.c +++ b/mach/powerpc/as/mach2.c @@ -85,7 +85,7 @@ %token OP_LI32 %token OP_POWERPC_FIXUP -%token OP_HA OP_HAS OP_LO +%token OP_HI OP_HA OP_LO /* Other token types */ diff --git a/mach/powerpc/as/mach3.c b/mach/powerpc/as/mach3.c index 74415aa9f..724ba7312 100644 --- a/mach/powerpc/as/mach3.c +++ b/mach/powerpc/as/mach3.c @@ -102,8 +102,8 @@ 0, OP_LA, 0, "la", 0, OP_LA, 0, "li", 0, OP_RS_RA_RA_C, 31<<26 | 444<<1, "mr", -0, OP_HA, 0, "ha16", -0, OP_HAS, 0, "has16", +0, OP_HI, 0, "hi16", +0, OP_HA, 0, "ha16", 0, OP_LO, 0, "lo16", /* Branch processor instructions (page 20) */ diff --git a/mach/powerpc/as/mach4.c b/mach/powerpc/as/mach4.c index bb6f5163b..1ad180de4 100644 --- a/mach/powerpc/as/mach4.c +++ b/mach/powerpc/as/mach4.c @@ -75,8 +75,8 @@ e16 serror("16-bit value out of range"); $$ = (uint16_t) $1; } - | OP_HA ASC_LPAR expr ASC_RPAR { $$ = emit_ha(&$3, false); } - | OP_HAS ASC_LPAR expr ASC_RPAR { $$ = emit_ha(&$3, true); } + | OP_HI ASC_LPAR expr ASC_RPAR { $$ = emit_hi(&$3, false); } + | OP_HA ASC_LPAR expr ASC_RPAR { $$ = emit_hi(&$3, true); } | OP_LO ASC_LPAR expr ASC_RPAR { $$ = emit_lo(&$3); } ; diff --git a/mach/powerpc/as/mach5.c b/mach/powerpc/as/mach5.c index a8e4cd043..e3e23f272 100644 --- a/mach/powerpc/as/mach5.c +++ b/mach/powerpc/as/mach5.c @@ -1,5 +1,5 @@ -quad emit_ha(struct expr_t* expr, bool is_signed) +quad emit_hi(struct expr_t* expr, bool is_signed) { /* If this is a symbol reference, discard the symbol and keep only the * offset part. */ diff --git a/mach/powerpc/ncg/table b/mach/powerpc/ncg/table index d37bed8f0..d3d2fcbf4 100644 --- a/mach/powerpc/ncg/table +++ b/mach/powerpc/ncg/table @@ -175,8 +175,8 @@ TOKENS /* Primitives */ LABEL = { ADDR adr; } 4 adr. + LABEL_OFFSET_HI = { ADDR adr; } 4 "hi16[" adr "]". LABEL_OFFSET_HA = { ADDR adr; } 4 "ha16[" adr "]". - LABEL_OFFSET_HAS = { ADDR adr; } 4 "has16[" adr "]". LABEL_OFFSET_LO = { ADDR adr; } 4 "lo16[" adr "]". LOCAL = { INT off; } 4. @@ -286,7 +286,7 @@ INSTRUCTIONS add GPR:wo, GPR:ro, GPR:ro. addX "add." GPR:wo, GPR:ro, GPR:ro. addi GPR:wo, GPR:ro, CONST:ro. - addis GPR:wo, GPR:ro, CONST+LABEL_OFFSET_HA+LABEL_OFFSET_HAS:ro. + addis GPR:wo, GPR:ro, CONST+LABEL_OFFSET_HI+LABEL_OFFSET_HA:ro. and GPR:wo, GPR:ro, GPR:ro. andc GPR:wo, GPR:ro, GPR:ro. andiX "andi." GPR:wo:cc, GPR:ro, CONST:ro. @@ -408,7 +408,7 @@ MOVES from LABEL to GPR gen COMMENT("move LABEL->GPR") - addis %2, R0, {LABEL_OFFSET_HA, %1.adr} + addis %2, R0, {LABEL_OFFSET_HI, %1.adr} ori %2, %2, {LABEL_OFFSET_LO, %1.adr} /* Sign extension */ @@ -1149,7 +1149,7 @@ PATTERNS with LABEL uses REG gen - addis %a, R0, {LABEL_OFFSET_HAS, %1.adr} + addis %a, R0, {LABEL_OFFSET_HA, %1.adr} lwz %a, {GPRINDIRECT_OFFSET_LO, %a, %1.adr} yields %a with GPR diff --git a/util/led/relocate.c b/util/led/relocate.c index 613a0afa7..7e2f9db10 100644 --- a/util/led/relocate.c +++ b/util/led/relocate.c @@ -297,6 +297,7 @@ static void put_powerpc_valu(char* addr, uint32_t value, uint16_t type) else if (((opcode1 & 0xfc1f0000) == 0x3c000000) && ((opcode2 & 0xfc000000) == 0x60000000)) { + /* addis / ori instruction pair */ uint16_t hi = value >> 16; uint16_t lo = value & 0xffff; From b63a4513d5ecb19a2781fe01ea15d8ead37f5230 Mon Sep 17 00:00:00 2001 From: David Given Date: Sun, 15 Jan 2017 12:04:47 +0100 Subject: [PATCH 129/173] Add missing header. --- util/led/archive.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/util/led/archive.c b/util/led/archive.c index e36958d17..7cb3397b8 100644 --- a/util/led/archive.c +++ b/util/led/archive.c @@ -8,6 +8,8 @@ static char rcsid[] = "$Id$"; #include #include +#include +#include #include "arch.h" #include "out.h" #include "ranlib.h" From 1ea46f6afef4c7db32a07b9c539dfa42dce99857 Mon Sep 17 00:00:00 2001 From: David Given Date: Sun, 15 Jan 2017 22:26:09 +0100 Subject: [PATCH 130/173] Actually tell the user which tests failed. --- first/testsummary.sh | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/first/testsummary.sh b/first/testsummary.sh index 6c2d3e39a..9ab5daa2f 100755 --- a/first/testsummary.sh +++ b/first/testsummary.sh @@ -26,6 +26,13 @@ echo "$(echo "$timedout" | wc -w) timed out" echo "$(echo "$failed" | wc -w) failed" echo "" +if [ "$failed" != "" ]; then + echo "Failing test logs:" + for t in $failed; do + echo $t + done + exit 1 +fi if [ "$failed" != "" -o "$timedout" != "" ]; then echo "Test status: SAD FACE (tests are failing)" exit 1 From e7e29d34ff53680248f4b733b80bff7a83d2a213 Mon Sep 17 00:00:00 2001 From: David Given Date: Sun, 15 Jan 2017 22:28:14 +0100 Subject: [PATCH 131/173] Add a test (currently failing) to check that Pascal char sets can store all 256 possible values. Add the PowerPC ncg and mcg backend support to let the test actually run, including modifying a bunch of PowrePC libem functions so that they can be called from both ncg and mcg. --- mach/powerpc/libem/ior.s | 6 +- mach/powerpc/libem/rck.s | 22 ++++ mach/powerpc/libem/set.s | 7 +- mach/powerpc/libem/zer.s | 6 +- mach/powerpc/ncg/table | 58 +++++------ mach/proto/mcg/treebuilder.c | 185 +++++++++++++++++++--------------- plat/linuxppc/libsys/trap.s | 25 +++-- plat/qemuppc/libsys/trap.s | 7 +- tests/plat/charsignedness_p.p | 28 +++++ tests/plat/newdispose_p.p | 4 +- 10 files changed, 218 insertions(+), 130 deletions(-) create mode 100644 mach/powerpc/libem/rck.s create mode 100644 tests/plat/charsignedness_p.p diff --git a/mach/powerpc/libem/ior.s b/mach/powerpc/libem/ior.s index 61e099934..b3ebf81e9 100644 --- a/mach/powerpc/libem/ior.s +++ b/mach/powerpc/libem/ior.s @@ -3,11 +3,13 @@ .sect .text ! Set union. -! Stack: ( b a -- a+b ) -! With r3 = size of set +! Stack: ( size b a -- a+b ) .define .ior .ior: + lwz r3, 0 (sp) + addi sp, sp, 4 + mr r4, sp ! r4 = ptr to set a add r5, sp, r3 ! r5 = ptr to set b rlwinm r6, r3, 30, 2, 31 diff --git a/mach/powerpc/libem/rck.s b/mach/powerpc/libem/rck.s new file mode 100644 index 000000000..b716e5091 --- /dev/null +++ b/mach/powerpc/libem/rck.s @@ -0,0 +1,22 @@ +#include "powerpc.h" + +.sect .text + +! Bounds check. Traps if the value is out of range. +! Stack: ( descriptor value -- ) + +.define .rck +.rck: + lwz r3, 0 (sp) + lwz r4, 4 (sp) + addi sp, sp, 8 + + lwz r5, 0 (r3) + cmp cr0, 0, r4, r5 + bc IFTRUE, LT, .trap_erange + + lwz r5, 4 (r3) + cmp cr0, 0, r4, r5 + bc IFTRUE, GT, .trap_erange + + bclr ALWAYS, 0, 0 diff --git a/mach/powerpc/libem/set.s b/mach/powerpc/libem/set.s index 18ad877e8..daffb9c3d 100644 --- a/mach/powerpc/libem/set.s +++ b/mach/powerpc/libem/set.s @@ -3,11 +3,14 @@ .sect .text ! Create singleton set. -! Stack: ( -- set ) -! With r3 = size of set, r4 = bit number +! Stack: ( size bitnumber -- set ) .define .set .set: + lwz r3, 0 (sp) + lwz r4, 4 (sp) + addi sp, sp, 8 + rlwinm r7, r3, 30, 2, 31 neg r5, r3 add sp, sp, r5 ! allocate set diff --git a/mach/powerpc/libem/zer.s b/mach/powerpc/libem/zer.s index ba978ba3e..697a5715f 100644 --- a/mach/powerpc/libem/zer.s +++ b/mach/powerpc/libem/zer.s @@ -3,11 +3,13 @@ .sect .text ! Create empty set. -! Stack: ( -- set ) -! With r3 = size of set +! Stack: ( size -- set ) .define .zer .zer: + lwz r3, 0(sp) + addi sp, sp, 4 + rlwinm r7, r3, 30, 2, 31 addi r4, r0, 0 ! r4 = zero neg r5, r3 diff --git a/mach/powerpc/ncg/table b/mach/powerpc/ncg/table index 52f335c3d..6498c591c 100644 --- a/mach/powerpc/ncg/table +++ b/mach/powerpc/ncg/table @@ -1503,18 +1503,14 @@ PATTERNS yields {OR_RC, %2, lo(%1.val)} pat ior defined($1) /* OR set */ - with STACK - kills ALL - gen - move {CONST, $1}, R3 - bl {LABEL, ".ior"} + leaving + loc $1 + cal ".ior" /* OR set (variable), used in lang/m2/libm2/LtoUset.e */ pat ior !defined($1) - with GPR3 STACK - kills ALL - gen - bl {LABEL, ".ior"} + leaving + cal ".ior" pat xor $1==4 /* XOR word */ with REG REG @@ -1572,12 +1568,10 @@ PATTERNS leaving loc 0 - pat zer defined($1) /* Create empty set */ - with STACK - kills ALL - gen - move {CONST, $1}, R3 - bl {LABEL, ".zer"} + pat zer defined($1) /* Create empty set */ + leaving + loc $1 + cal ".zer" pat sli $1==4 /* Shift left (second << top) */ with CONST_ALL GPR @@ -1655,27 +1649,19 @@ PATTERNS /* Sets */ pat set defined($1) /* Create singleton set */ - with GPR4 STACK - kills ALL - gen - move {CONST, $1}, R3 - bl {LABEL, ".set"} + leaving + loc $1 + cal ".set" /* Create set (variable), used in lang/m2/libm2/LtoUset.e */ pat set !defined($1) - with GPR3 GPR4 STACK - kills ALL - gen - bl {LABEL, ".set"} + leaving + cal ".set" pat inn defined($1) /* Test for set bit */ - with STACK - kills ALL - uses REG - gen - li32 %a, {CONST, $1} - stwu %a, {GPRINDIRECT, SP, 0-4} - bl {LABEL, ".inn"} + leaving + loc $1 + cal ".inn" /* Boolean resolutions */ @@ -2066,6 +2052,16 @@ PATTERNS loc $1 ass 4 + pat lae rck $2==4 /* Range check */ + with GPR + uses CR0 + gen + cmpli %a, {CONST, 0}, %1, {CONST, rom($1, 1)} + bc IFTRUE, LT, {LABEL, ".trap_erange"} + cmpli %a, {CONST, 0}, %1, {CONST, rom($1, 2)} + bc IFTRUE, GT, {LABEL, ".trap_erange"} + + /* Floating point support */ diff --git a/mach/proto/mcg/treebuilder.c b/mach/proto/mcg/treebuilder.c index 667562e8d..ba4f7198f 100644 --- a/mach/proto/mcg/treebuilder.c +++ b/mach/proto/mcg/treebuilder.c @@ -66,7 +66,7 @@ static struct ir* pop(int size) #if 0 /* If we try to pop something which is smaller than a word, convert it first. */ - + if (size < EM_wordsize) ir = convertu(ir, size); #endif @@ -200,7 +200,7 @@ static struct ir* address_of_external(const char* label, arith offset) static struct ir* convert(struct ir* src, int srcsize, int destsize, int opcode) { - if (srcsize == 1) + if (srcsize == 1) { if ((opcode == IR_FROMSI) || (opcode == IR_FROMSL)) { @@ -433,7 +433,7 @@ static void insn_simple(int opcode) ); break; } - + case op_cii: simple_convert(IR_FROMSI); break; case op_ciu: simple_convert(IR_FROMSI); break; case op_cui: simple_convert(IR_FROMUI); break; @@ -528,10 +528,12 @@ static void insn_simple(int opcode) } /* FIXME: These instructions are really complex and barely used - * (Modula-2 bitset support, I believe). Leave them until later. */ + * (Modula-2 and Pascal set support, I believe). Leave them until + * later. */ case op_set: helper_function(".unimplemented_set"); break; case op_ior: helper_function(".unimplemented_ior"); break; + case op_dch: push( new_ir1( @@ -540,7 +542,7 @@ static void insn_simple(int opcode) ) ); break; - + case op_lpb: push( new_ir1( @@ -607,29 +609,53 @@ static void insn_bvalue(int opcode, struct basicblock* leftbb, struct basicblock } } -static void simple_alu1(int opcode, int size, int irop) +static void simple_alu1(int opcode, int size, int irop, const char* fallback) { - struct ir* val = pop(size); + if (size > (2*EM_wordsize)) + { + if (!fallback) + fatal("treebuilder: can't do opcode %d with size %d", opcode, size); + push( + new_wordir(size) + ); + helper_function(fallback); + } + else + { + struct ir* val = pop(size); - push( - new_ir1( - irop, size, - val - ) - ); + push( + new_ir1( + irop, size, + val + ) + ); + } } -static void simple_alu2(int opcode, int size, int irop) +static void simple_alu2(int opcode, int size, int irop, const char* fallback) { - struct ir* right = pop(size); - struct ir* left = pop(size); + if (size > (2*EM_wordsize)) + { + if (!fallback) + fatal("treebuilder: can't do opcode %d with size %d", opcode, size); + push( + new_wordir(size) + ); + helper_function(fallback); + } + else + { + struct ir* right = pop(size); + struct ir* left = pop(size); - push( - new_ir2( - irop, size, - left, right - ) - ); + push( + new_ir2( + irop, size, + left, right + ) + ); + } } static struct ir* extract_block_refs(struct basicblock* bb) @@ -708,39 +734,43 @@ static void insn_ivalue(int opcode, arith value) { switch (opcode) { - case op_adi: simple_alu2(opcode, value, IR_ADD); break; - case op_sbi: simple_alu2(opcode, value, IR_SUB); break; - case op_mli: simple_alu2(opcode, value, IR_MUL); break; - case op_dvi: simple_alu2(opcode, value, IR_DIV); break; - case op_rmi: simple_alu2(opcode, value, IR_MOD); break; - case op_sli: simple_alu2(opcode, value, IR_ASL); break; - case op_sri: simple_alu2(opcode, value, IR_ASR); break; - case op_ngi: simple_alu1(opcode, value, IR_NEG); break; + case op_adi: simple_alu2(opcode, value, IR_ADD, NULL); break; + case op_sbi: simple_alu2(opcode, value, IR_SUB, NULL); break; + case op_mli: simple_alu2(opcode, value, IR_MUL, NULL); break; + case op_dvi: simple_alu2(opcode, value, IR_DIV, NULL); break; + case op_rmi: simple_alu2(opcode, value, IR_MOD, NULL); break; + case op_sli: simple_alu2(opcode, value, IR_ASL, NULL); break; + case op_sri: simple_alu2(opcode, value, IR_ASR, NULL); break; + case op_ngi: simple_alu1(opcode, value, IR_NEG, NULL); break; - case op_adu: simple_alu2(opcode, value, IR_ADD); break; - case op_sbu: simple_alu2(opcode, value, IR_SUB); break; - case op_mlu: simple_alu2(opcode, value, IR_MUL); break; - case op_slu: simple_alu2(opcode, value, IR_LSL); break; - case op_sru: simple_alu2(opcode, value, IR_LSR); break; - case op_rmu: simple_alu2(opcode, value, IR_MODU); break; - case op_dvu: simple_alu2(opcode, value, IR_DIVU); break; + case op_adu: simple_alu2(opcode, value, IR_ADD, NULL); break; + case op_sbu: simple_alu2(opcode, value, IR_SUB, NULL); break; + case op_mlu: simple_alu2(opcode, value, IR_MUL, NULL); break; + case op_slu: simple_alu2(opcode, value, IR_LSL, NULL); break; + case op_sru: simple_alu2(opcode, value, IR_LSR, NULL); break; + case op_rmu: simple_alu2(opcode, value, IR_MODU, NULL); break; + case op_dvu: simple_alu2(opcode, value, IR_DIVU, NULL); break; - case op_and: simple_alu2(opcode, value, IR_AND); break; - case op_ior: simple_alu2(opcode, value, IR_OR); break; - case op_xor: simple_alu2(opcode, value, IR_EOR); break; - case op_com: simple_alu1(opcode, value, IR_NOT); break; + case op_and: simple_alu2(opcode, value, IR_AND, NULL); break; + case op_ior: simple_alu2(opcode, value, IR_OR, ".ior"); break; + case op_xor: simple_alu2(opcode, value, IR_EOR, NULL); break; + case op_com: simple_alu1(opcode, value, IR_NOT, NULL); break; - case op_adf: simple_alu2(opcode, value, IR_ADDF); break; - case op_sbf: simple_alu2(opcode, value, IR_SUBF); break; - case op_mlf: simple_alu2(opcode, value, IR_MULF); break; - case op_dvf: simple_alu2(opcode, value, IR_DIVF); break; - case op_ngf: simple_alu1(opcode, value, IR_NEGF); break; + case op_adf: simple_alu2(opcode, value, IR_ADDF, NULL); break; + case op_sbf: simple_alu2(opcode, value, IR_SUBF, NULL); break; + case op_mlf: simple_alu2(opcode, value, IR_MULF, NULL); break; + case op_dvf: simple_alu2(opcode, value, IR_DIVF, NULL); break; + case op_ngf: simple_alu1(opcode, value, IR_NEGF, NULL); break; case op_cmu: /* fall through */ case op_cms: push(tristate_compare(value, IR_COMPAREUI)); break; case op_cmi: push(tristate_compare(value, IR_COMPARESI)); break; case op_cmf: push(tristate_compare(value, IR_COMPAREF)); break; + case op_rck: helper_function(".rck"); break; + case op_set: push(new_wordir(value)); helper_function(".set"); break; + case op_inn: push(new_wordir(value)); helper_function(".inn"); break; + case op_lol: push( load( @@ -874,7 +904,7 @@ static void insn_ivalue(int opcode, arith value) ) ); break; - + case op_loc: push( new_wordir(value) @@ -1041,7 +1071,7 @@ static void insn_ivalue(int opcode, arith value) struct ir* right = pop(EM_pointersize); struct ir* left = pop(EM_pointersize); - struct ir* delta = + struct ir* delta = new_ir2( IR_SUB, EM_pointersize, left, right @@ -1053,7 +1083,7 @@ static void insn_ivalue(int opcode, arith value) push(delta); break; } - + case op_dup: { sequence_point(); @@ -1084,6 +1114,18 @@ static void insn_ivalue(int opcode, arith value) break; } + case op_zer: + { + if (value <= EM_wordsize) + push(new_constir(value, 0)); + else + { + push(new_wordir(value)); + helper_function(".zer"); + } + break; + } + case op_asp: { switch (value) @@ -1108,15 +1150,12 @@ static void insn_ivalue(int opcode, arith value) value -= s; } - if (value != 0) - { - appendir( - new_ir1( - IR_STACKADJUST, EM_pointersize, - new_wordir(value) - ) - ); - } + appendir( + new_ir1( + IR_STACKADJUST, EM_pointersize, + new_wordir(value) + ) + ); break; } break; @@ -1169,7 +1208,7 @@ static void insn_ivalue(int opcode, arith value) ); break; } - + case op_lfr: { push( @@ -1300,11 +1339,11 @@ static void insn_ivalue(int opcode, arith value) new_labelir((value == 4) ? ".fef4" : ".fef8") ) ); - + /* exit, leaving an int and then a float (or double) on the stack. */ break; } - + case op_fif: { /* fif is implemented by calling a helper function which then mutates @@ -1320,11 +1359,11 @@ static void insn_ivalue(int opcode, arith value) new_labelir((value == 4) ? ".fif4" : ".fif8") ) ); - + /* exit, leaving two floats (or doubles) on the stack. */ break; } - + case op_lor: { switch (value) @@ -1341,7 +1380,7 @@ static void insn_ivalue(int opcode, arith value) ) ); break; - + case 1: push( appendir( @@ -1492,18 +1531,6 @@ static void insn_ivalue(int opcode, arith value) break; } - /* FIXME: These instructions are really complex and barely used - * (Modula-2 bitset support, I believe). Leave them until leter. */ - case op_inn: - { - push( - new_wordir(value) - ); - - helper_function(".inn"); - break; - } - case op_lin: { /* Set line number --- ignore. */ @@ -1577,7 +1604,7 @@ static void insn_lvalue(int opcode, const char* label, arith offset) ) ); break; - + case op_ine: sequence_point(); appendir( @@ -1666,7 +1693,7 @@ static void insn_lvalue(int opcode, const char* label, arith offset) /* Set filename --- ignore. */ break; } - + default: fatal("treebuilder: unknown lvalue instruction '%s'", em_mnem[opcode - sp_fmnem]); @@ -1699,7 +1726,7 @@ static void generate_tree(struct basicblock* bb) break; case PARAM_LVALUE: - tracef('E', "label=%s offset=%d\n", + tracef('E', "label=%s offset=%d\n", em->u.lvalue.label, em->u.lvalue.offset); insn_lvalue(em->opcode, em->u.lvalue.label, em->u.lvalue.offset); break; diff --git a/plat/linuxppc/libsys/trap.s b/plat/linuxppc/libsys/trap.s index 09d3b0b21..296f17391 100644 --- a/plat/linuxppc/libsys/trap.s +++ b/plat/linuxppc/libsys/trap.s @@ -52,43 +52,48 @@ EUNIMPL = 63 ! unimplemented em-instruction called .trap_ecase: addi r3, r0, ECASE b .trap - + .define .trap_earray .trap_earray: addi r3, r0, EARRAY b .trap - + +.define .trap_erange +.trap_erange: + addi r3, r0, ERANGE + b .trap + .define .trap .trap: cmpi cr0, 0, r3, 15 ! traps >15 can't be ignored bc IFTRUE, LT, 1f - + addi r4, r0, 1 rlwnm r4, r4, r3, 0, 31 ! calculate trap bit li32 r5, .ignmask lwz r5, 0(r5) ! load ignore mask and. r4, r4, r5 ! compare bclr IFFALSE, EQ, 0 ! return if non-zero - + 1: li32 r4, .trppc lwz r5, 0(r4) ! load user trap routine or. r5, r5, r5 ! test bc IFTRUE, EQ, fatal ! if no user trap routine, bail out - + addi r0, r0, 0 stw r0, 0(r4) ! reset trap routine - + mfspr r0, lr stwu r0, -4(sp) ! save old lr - + stwu r3, -4(sp) mtspr ctr, r5 bcctrl ALWAYS, 0, 0 ! call trap routine - + lwz r0, 4(sp) ! load old lr again addi sp, sp, 8 ! retract over stack usage - bclr ALWAYS, 0, 0 ! return + bclr ALWAYS, 0, 0 ! return fatal: addi r3, r0, 1 @@ -96,7 +101,7 @@ fatal: addi r5, r0, 6 addi r0, r0, 4 ! write() sc 0 - + addi r0, r0, 1 ! exit() sc 0 diff --git a/plat/qemuppc/libsys/trap.s b/plat/qemuppc/libsys/trap.s index f05b907d0..280adc33b 100644 --- a/plat/qemuppc/libsys/trap.s +++ b/plat/qemuppc/libsys/trap.s @@ -49,11 +49,15 @@ EUNIMPL = 63 ! unimplemented em-instruction called .define .trap_ecase .trap_ecase: b .trp - + .define .trap_earray .trap_earray: b .trp +.define .trap_erange +.trap_erange: + b .trap + .define .trp .define .trap .trp: @@ -66,4 +70,3 @@ EUNIMPL = 63 ! unimplemented em-instruction called li32 r4, .trppc stw r3, 0(r4) bclr ALWAYS, 0, 0 ! return - \ No newline at end of file diff --git a/tests/plat/charsignedness_p.p b/tests/plat/charsignedness_p.p new file mode 100644 index 000000000..6263111ce --- /dev/null +++ b/tests/plat/charsignedness_p.p @@ -0,0 +1,28 @@ +# +(*$U+ -- enables underscores in identifiers *) + +program markrelease; + +type + charset = set of char; + +var + s : charset; + i : integer; + +procedure finished; + extern; + +procedure fail(line: integer); + extern; + +#define ASSERT(cond) \ + if (not (cond)) then fail(__LINE__) + +begin + s := []; + for i := 0 to 255 do + s := s + [chr(i)]; + + finished +end. diff --git a/tests/plat/newdispose_p.p b/tests/plat/newdispose_p.p index 36f09e99b..aa3be5a46 100644 --- a/tests/plat/newdispose_p.p +++ b/tests/plat/newdispose_p.p @@ -9,13 +9,13 @@ type var ptr1 : iptr; ptr2 : iptr; - + procedure finished; extern; procedure fail(line: integer); extern; - + #define ASSERT(cond) \ if (not (cond)) then fail(__LINE__) From 5ff983ad9b4b6f01417e7d7df6492595d7b3174c Mon Sep 17 00:00:00 2001 From: David Given Date: Sun, 15 Jan 2017 22:30:25 +0100 Subject: [PATCH 132/173] Increase the number of items in a char set from 128 to 256, to cover all possible bytes (7-bit bytes are so 70s). --- lang/pc/comp/type.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lang/pc/comp/type.c b/lang/pc/comp/type.c index faca8fee5..d13419cf4 100644 --- a/lang/pc/comp/type.c +++ b/lang/pc/comp/type.c @@ -94,8 +94,8 @@ InitTypes() /* character type */ char_type = standard_type(T_CHAR, 1, (arith) 1); - char_type->enm_ncst = 128; /* only 7 bits ASCII characters */ - + char_type->enm_ncst = 256; /* all bytes */ + /* boolean type */ bool_type = standard_type(T_ENUMERATION, 1, (arith) 1); From 5fd1634830b4c43abbc2ca34267d2851b216894c Mon Sep 17 00:00:00 2001 From: David Given Date: Sun, 15 Jan 2017 22:33:41 +0100 Subject: [PATCH 133/173] Rename the test to something more sensible. --- tests/plat/{charsignedness_p.p => pascalsets_p.p} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename tests/plat/{charsignedness_p.p => pascalsets_p.p} (94%) diff --git a/tests/plat/charsignedness_p.p b/tests/plat/pascalsets_p.p similarity index 94% rename from tests/plat/charsignedness_p.p rename to tests/plat/pascalsets_p.p index 6263111ce..3253414f9 100644 --- a/tests/plat/charsignedness_p.p +++ b/tests/plat/pascalsets_p.p @@ -1,7 +1,7 @@ # (*$U+ -- enables underscores in identifiers *) -program markrelease; +program pascalsets; type charset = set of char; From b32be06881eee7a075c79fe641c4ac47da536d98 Mon Sep 17 00:00:00 2001 From: David Given Date: Sun, 15 Jan 2017 22:41:11 +0100 Subject: [PATCH 134/173] Allow the full 8-bit byte range when reading program source. --- lang/pc/comp/LLlex.c | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/lang/pc/comp/LLlex.c b/lang/pc/comp/LLlex.c index 7bd857a2b..4de2c0d8b 100644 --- a/lang/pc/comp/LLlex.c +++ b/lang/pc/comp/LLlex.c @@ -164,14 +164,10 @@ register int delim; Malloc((unsigned) sizeof(struct string)); register char *p; register int len = ISTRSIZE; - + str->s_str = p = Malloc((unsigned int) ISTRSIZE); for( ; ; ) { LoadChar(ch); - if( ch & 0200 ) { - fatal("non-ascii '\\%03o' read", ch & 0377); - /*NOTREACHED*/ - } if( class(ch) == STNL ) { lexerror("newline in string"); LineNumber++; @@ -310,11 +306,6 @@ again: LoadChar(ch); if( !options['C'] ) /* -C : cases are different */ TO_LOWER(ch); - - if( (ch & 0200) && ch != EOI ) { - fatal("non-ascii '\\%03o' read", ch & 0377); - /*NOTREACHED*/ - } } switch( class(ch) ) { @@ -420,7 +411,7 @@ again: /* dtrg: removed to allow Pascal programs to access system routines * (necessary to make them do anything useful). What's this for, * anyway? */ - + #if 0 if( buf[0] == '_' ) lexerror("underscore starts identifier"); #endif @@ -492,7 +483,7 @@ again: PushBack(); goto end; } - + } if( ch == 'e' || ch == 'E' ) { char *tp = np; /* save position in string */ From 09c79b7dba9660628f16db12b3c6c6831b0f771f Mon Sep 17 00:00:00 2001 From: David Given Date: Sun, 15 Jan 2017 23:00:17 +0100 Subject: [PATCH 135/173] Fix cosmetic warning when compiling B. --- lib/descr/fe | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/descr/fe b/lib/descr/fe index 04d33e4fa..b7a07cdc4 100644 --- a/lib/descr/fe +++ b/lib/descr/fe @@ -185,7 +185,7 @@ name b to .k program {EM}/lib/ack/em_b mapflag -B* ABC_F={ABC_F?} -B* - args -i < -o > -w {p} {ABC_F} + args -i < -o > -w {p} {ABC_F?} prep cond rts .b need .b From fa5675d43959b5a4b1f29e28d9796cfc434f3eb6 Mon Sep 17 00:00:00 2001 From: David Given Date: Mon, 16 Jan 2017 21:16:33 +0100 Subject: [PATCH 136/173] Run through clang-format. --- mach/proto/ncg/codegen.c | 1750 +++++++++++++++++++++----------------- 1 file changed, 960 insertions(+), 790 deletions(-) diff --git a/mach/proto/ncg/codegen.c b/mach/proto/ncg/codegen.c index 15d99d393..8c7958cf2 100644 --- a/mach/proto/ncg/codegen.c +++ b/mach/proto/ncg/codegen.c @@ -22,12 +22,12 @@ static char rcsid[] = "$Id$"; * Author: Hans van Staveren */ -#define ALLOW_NEXTEM /* code generator is allowed new try of NEXTEM - in exceptional cases */ +#define ALLOW_NEXTEM /* code generator is allowed new try of NEXTEM \ + in exceptional cases */ byte startupcode[] = { DO_NEXTEM }; -byte *nextem(); +byte* nextem(); unsigned costcalc(); unsigned docoerc(); unsigned stackupto(); @@ -38,885 +38,1048 @@ string ad2str(); #define DEBUG(string) #else #include -#define DEBUG(string) {if(Debug) fprintf(stderr,"%-*d%s\n",4*level,level,string);} +#define DEBUG(string) \ + { \ + if (Debug) \ + fprintf(stderr, "%-*d%s\n", 4 * level, level, string); \ + } #endif -#define BROKE() {assert(origcp!=startupcode || !paniced);DEBUG("BROKE");totalcost=INFINITY;goto doreturn;} -#define CHKCOST() {if (totalcost>=costlimit) BROKE();} +#define BROKE() \ + { \ + assert(origcp != startupcode || !paniced); \ + DEBUG("BROKE"); \ + totalcost = INFINITY; \ + goto doreturn; \ + } +#define CHKCOST() \ + { \ + if (totalcost >= costlimit) \ + BROKE(); \ + } #ifdef TABLEDEBUG int tablelines[MAXTDBUG]; int ntableline; -int set_fd,set_size; -short *set_val; -char *set_flag; +int set_fd, set_size; +short* set_val; +char* set_flag; #endif -unsigned codegen(codep,ply,toplevel,costlimit,forced) byte *codep; unsigned costlimit; { +unsigned codegen(codep, ply, toplevel, costlimit, forced) byte* codep; +unsigned costlimit; +{ #ifndef NDEBUG - byte *origcp=codep; - static int level=0; + byte* origcp = codep; + static int level = 0; #endif unsigned totalcost = 0; - int inscoerc=0; - int procarg[MAXPROCARG+1]; + int inscoerc = 0; + int procarg[MAXPROCARG + 1]; #ifdef ALLOW_NEXTEM static int paniced; - char *savebp = 0; + char* savebp = 0; #endif state_t state; -#define SAVEST savestatus(&state) -#define RESTST restorestatus(&state) -#define FREEST /* nothing */ +#define SAVEST savestatus(&state) +#define RESTST restorestatus(&state) +#define FREEST /* nothing */ #ifdef TABLEDEBUG - extern char *tablename; + extern char* tablename; #endif #ifndef NDEBUG assert(costlimit <= INFINITY); level++; DEBUG("Entering codegen"); - if (Debug > 1) fprintf(stderr, "toplevel = %d\n", toplevel); + if (Debug > 1) + fprintf(stderr, "toplevel = %d\n", toplevel); #endif - for (;;) { - switch( (*codep++)&037 ) { - default: - assert(FALSE); - /* NOTREACHED */ + for (;;) + { + switch ((*codep++) & 037) + { + default: + assert(FALSE); +/* NOTREACHED */ #ifdef TABLEDEBUG - case DO_DLINE: { - int n; + case DO_DLINE: + { + int n; - getint(n,codep); - tablelines[ntableline++] = n; - if (ntableline>=MAXTDBUG) - ntableline -= MAXTDBUG; - if (set_fd) - set_val[n>>4] &= ~(1<<(n&017)); + getint(n, codep); + tablelines[ntableline++] = n; + if (ntableline >= MAXTDBUG) + ntableline -= MAXTDBUG; + if (set_fd) + set_val[n >> 4] &= ~(1 << (n & 017)); #ifndef NDEBUG - if (Debug) - fprintf(stderr,"code from \"%s\", line %d\n",tablename,n); + if (Debug) + fprintf(stderr, "code from \"%s\", line %d\n", tablename, n); #endif - break; - } + break; + } #endif - case DO_NEXTEM: { - byte *bp; - int n; - unsigned mindistance,dist; - register i; - int cindex; - int npos,pos[MAXRULE]; - unsigned mincost,t; + case DO_NEXTEM: + { + byte* bp; + int n; + unsigned mindistance, dist; + register i; + int cindex; + int npos, pos[MAXRULE]; + unsigned mincost, t; - DEBUG("NEXTEM"); - tokpatlen = 0; - nallreg=0; - if (toplevel) { - garbage_collect(); - totalcost=0; - } else { - if (--ply <= 0) - goto doreturn; - } - if (stackheight>MAXFSTACK-7) { + DEBUG("NEXTEM"); + tokpatlen = 0; + nallreg = 0; + if (toplevel) + { + garbage_collect(); + totalcost = 0; + } + else + { + if (--ply <= 0) + goto doreturn; + } + if (stackheight > MAXFSTACK - 7) + { #ifndef NDEBUG - if (Debug) - fprintf(stderr,"Fakestack overflow threatens(%d), action ...\n",stackheight); + if (Debug) + fprintf(stderr, "Fakestack overflow threatens(%d), action ...\n", stackheight); #endif - totalcost += stackupto(&fakestack[6],ply,toplevel); - } + totalcost += stackupto(&fakestack[6], ply, toplevel); + } #ifndef ALLOW_NEXTEM - bp = nextem(toplevel); + bp = nextem(toplevel); #else - if (toplevel) paniced=0; - savebp = nextem(toplevel); - panic: - if (toplevel) totalcost = 0; - bp = savebp; + if (toplevel) + paniced = 0; + savebp = nextem(toplevel); + panic: + if (toplevel) + totalcost = 0; + bp = savebp; #endif - if (bp == 0) { - /* + if (bp == 0) + { + /* * No pattern found, can be pseudo or error * in table. */ - if (toplevel) { - codep--; - DEBUG("pseudo"); - dopseudo(); - } else - goto doreturn; - } else { -#ifndef NDEBUG - chkregs(); -#endif - if (! toplevel) { - ply -= emp-saveemp+1; - if (ply <= 0) ply = 1; - } - n = *bp++; - if (n==0) { /* "procedure" */ - int j, nargs; - getint(i,bp); - getint(nargs,bp); - assert(nargs <= MAXPROCARG); - for (j = 0; j < nargs; j++) { - getint(procarg[j],bp); - } - bp= &pattern[i]; - n = *bp++; - DEBUG("PROC_CALL"); - } - assert(n>0 && n<=MAXRULE); - if (n>1) { - mindistance = MAXINT; npos=0; - for(i=0;i1) { - /* + else + { +#ifndef NDEBUG + chkregs(); +#endif + if (!toplevel) + { + ply -= emp - saveemp + 1; + if (ply <= 0) + ply = 1; + } + n = *bp++; + if (n == 0) + { /* "procedure" */ + int j, nargs; + getint(i, bp); + getint(nargs, bp); + assert(nargs <= MAXPROCARG); + for (j = 0; j < nargs; j++) + { + getint(procarg[j], bp); + } + bp = &pattern[i]; + n = *bp++; + DEBUG("PROC_CALL"); + } + assert(n > 0 && n <= MAXRULE); + if (n > 1) + { + mindistance = MAXINT; + npos = 0; + for (i = 0; i < n; i++) + { + getint(cindex, bp); + dist = distance(cindex); +#ifndef NDEBUG + if (Debug) + fprintf(stderr, "distance of pos %d is %u\n", i, dist); +#endif + if (dist <= mindistance +#ifdef ALLOW_NEXTEM + || paniced +#endif + ) + { + if (dist < mindistance) + { + if (dist == 0) + goto gotit; + npos = 0; + mindistance = dist; + } +#ifdef ALLOW_NEXTEM + if (dist < MAXINT) +#endif + pos[npos++] = cindex; + } + } + assert(mindistance < MAXINT); + if (npos > 1) + { + /* * More than 1 tokenpattern is a candidate. * Decision has to be made by lookahead. */ - SAVEST; - mincost = costlimit-totalcost+1; - assert(mincost <= INFINITY); - for(i=0;i costlimit) + { + BROKE(); + } + } + else + { + cindex = pos[0]; + } + } + else + { + getint(cindex, bp); } - RESTST; - } - FREEST; - if (totalcost+mincost>costlimit) { - BROKE(); - } - } else { - cindex = pos[0]; - } - } else { - getint(cindex,bp); - } - gotit: - /* + gotit: + /* * Now cindex contains the code-index of the best candidate * so proceed to use it. */ - codep = &coderules[cindex]; - } - break; - } - case DO_COERC: { - DEBUG("COERC"); - tokpatlen=1; - inscoerc=1; - break; - } - case DO_XXMATCH: - DEBUG("XXMATCH"); - case DO_XMATCH: { - register i; - int temp; - - DEBUG("XMATCH"); - tokpatlen=(codep[-1]>>5)&07; - for (i=0;i>5)&07; - for(i=0;i=fakestack) { - size=tsize(tp); - while (i= fakestack) { - size = tsize(tp); - lsize= ssize(tokexp[i]); - if (size != lsize) { /* find coercion */ -#ifdef MAXSPLIT - sret = split(tp,&tokexp[i],ply,toplevel); - if (sret==0) { -#endif /* MAXSPLIT */ - totalcost += stackupto(tp,ply,toplevel); - CHKCOST(); - break; -#ifdef MAXSPLIT - } - i += sret; -#endif /* MAXSPLIT */ - } else - i += 1; - tp--; - } - nextmatch: - tp = &fakestack[stackheight-1]; - i=0; nregneeded = 0; - while (i=fakestack) { - if (!match(tp,&machsets[tokexp[i]],0)) { - cp = findcoerc(tp, &machsets[tokexp[i]]); -#ifndef NDEBUG -if (Debug>1) fprintf(stderr,"findcoerc returns 0x%x at position %d\n",(unsigned)cp,i); -#endif - if (cp==0) { - for (j=0;jc3_prop<0) { - totalcost+=docoerc(tp,cp,ply,toplevel,0); - CHKCOST(); - } else { -#ifndef NDEBUG -if(Debug>1) fprintf(stderr,"Register of type %d needed, remembering...\n",cp->c3_prop); -#endif - assert(nregneededstackheight) { -#ifndef NDEBUG -if(Debug>1) fprintf(stderr,"Pattern too long, %d with only %d items on stack\n", - tokpatlen,stackheight); + case DO_COERC: + { + DEBUG("COERC"); + tokpatlen = 1; + inscoerc = 1; + break; + } + case DO_XXMATCH: + DEBUG("XXMATCH"); + case DO_XMATCH: + { + register i; + int temp; + + DEBUG("XMATCH"); + tokpatlen = (codep[-1] >> 5) & 07; + for (i = 0; i < tokpatlen; i++) + getint(temp, codep); + break; /* match already checked by distance() */ + } + case DO_MATCH: + { + register i; + int j; + unsigned mincost, t; + token_p tp; + int size, lsize; + int tokexp[MAXPATLEN]; + int nregneeded; + token_p regtp[MAXCREG]; + c3_p regcp[MAXCREG]; + rl_p regls[MAXCREG]; + c3_p cp, findcoerc(); +#ifdef MAXSPLIT + int sret; #endif - stackpad = tokpatlen-stackheight; - for (j=stackheight-1;j>=0;j--) - fakestack[j+stackpad] = fakestack[j]; - for (j=0;j=fakestack;i++,tp--) { - cp = findcoerc((token_p) 0, &machsets[tokexp[i]]); - if (cp==0) { - for (j=0;j> 5) & 07; + for (i = 0; i < tokpatlen; i++) + getint(tokexp[i], codep); + tokexp[i] = 0; + tp = &fakestack[stackheight - 1]; + i = 0; + while (i < tokpatlen && tp >= fakestack) + { + size = tsize(tp); + while (i < tokpatlen && (lsize = ssize(tokexp[i])) <= size) + { + size -= lsize; + i++; + } + if (i < tokpatlen && size != 0) + { + totalcost += stackupto(tp, ply, toplevel); + CHKCOST(); + break; + } + tp--; + } + tp = &fakestack[stackheight - 1]; + i = 0; + while (i < tokpatlen && tp >= fakestack) + { + size = tsize(tp); + lsize = ssize(tokexp[i]); + if (size != lsize) + { /* find coercion */ +#ifdef MAXSPLIT + sret = split(tp, &tokexp[i], ply, toplevel); + if (sret == 0) + { +#endif /* MAXSPLIT */ + totalcost += stackupto(tp, ply, toplevel); + CHKCOST(); + break; +#ifdef MAXSPLIT + } + i += sret; +#endif /* MAXSPLIT */ + } + else + i += 1; + tp--; + } + nextmatch: + tp = &fakestack[stackheight - 1]; + i = 0; + nregneeded = 0; + while (i < tokpatlen && tp >= fakestack) + { + if (!match(tp, &machsets[tokexp[i]], 0)) + { + cp = findcoerc(tp, &machsets[tokexp[i]]); +#ifndef NDEBUG + if (Debug > 1) + fprintf(stderr, "findcoerc returns 0x%x at position %d\n", (unsigned)cp, i); +#endif + if (cp == 0) + { + for (j = 0; j < nregneeded; j++) + regtp[j] -= (tp - fakestack + 1); + totalcost += stackupto(tp, ply, toplevel); + CHKCOST(); + break; + } + else + { + if (cp->c3_prop < 0) + { + totalcost += docoerc(tp, cp, ply, toplevel, 0); + CHKCOST(); + } + else + { +#ifndef NDEBUG + if (Debug > 1) + fprintf(stderr, "Register of type %d needed, remembering...\n", cp->c3_prop); +#endif + assert(nregneeded < MAXCREG); + regtp[nregneeded] = tp; + regcp[nregneeded] = cp; + regls[nregneeded] = curreglist; + nregneeded++; + } + } + } + i++; + tp--; + } + if (tokpatlen > stackheight) + { +#ifndef NDEBUG + if (Debug > 1) + fprintf(stderr, "Pattern too long, %d with only %d items on stack\n", + tokpatlen, stackheight); +#endif + stackpad = tokpatlen - stackheight; + for (j = stackheight - 1; j >= 0; j--) + fakestack[j + stackpad] = fakestack[j]; + for (j = 0; j < stackpad; j++) + fakestack[j].t_token = 0; + stackheight += stackpad; + for (j = 0; j < nregneeded; j++) + regtp[j] += stackpad; + for (tp = &fakestack[stackpad - 1]; i < tokpatlen && tp >= fakestack; i++, tp--) + { + cp = findcoerc((token_p)0, &machsets[tokexp[i]]); + if (cp == 0) + { + for (j = 0; j < nregneeded; j++) + myfree((string)(regls[j])); #ifndef ALLOW_NEXTEM - assert(!toplevel); - BROKE(); + assert(!toplevel); + BROKE(); #else - assert(!(toplevel&&paniced)); - if (paniced) goto normalfailed; - totalcost = INFINITY; - for (i=0;ic3_prop<0) { - totalcost+=docoerc(tp,cp,ply,toplevel,0); - CHKCOST(); - } else { - assert(nregneededc3_prop < 0) + { + totalcost += docoerc(tp, cp, ply, toplevel, 0); + CHKCOST(); + } + else + { + assert(nregneeded < MAXCREG); + regtp[nregneeded] = tp; + regcp[nregneeded] = cp; + regls[nregneeded] = curreglist; + nregneeded++; + } + } + } + else + stackpad = 0; + assert(i == tokpatlen); + if (nregneeded == 0) + break; + SAVEST; + mincost = costlimit - totalcost + 1; + tup = tuples(regls, nregneeded); + besttup = 0; + for (; tup != 0; tup = ntup) + { #ifndef NDEBUG -if(Debug>1) { fprintf(stderr,"Next tuple %d,%d,%d,%d\n", - tup->p_rar[0], - tup->p_rar[1], - tup->p_rar[2], - tup->p_rar[3]); - fprintf(stderr, "totalcost = %u, costlimit = %u, mincost = %u\n", - totalcost, costlimit, mincost); - } + if (Debug > 1) + { + fprintf(stderr, "Next tuple %d,%d,%d,%d\n", + tup->p_rar[0], + tup->p_rar[1], + tup->p_rar[2], + tup->p_rar[3]); + fprintf(stderr, "totalcost = %u, costlimit = %u, mincost = %u\n", + totalcost, costlimit, mincost); + } #endif - ntup = tup->p_next; - for (i=0,t=0;ip_rar[i]); + ntup = tup->p_next; + for (i = 0, t = 0; i < nregneeded && t < mincost; i++) + t += docoerc(regtp[i], regcp[i], ply, FALSE, tup->p_rar[i]); #ifndef NDEBUG -if (Debug > 1) fprintf(stderr, "cost after coercions: %u\n", t); + if (Debug > 1) + fprintf(stderr, "cost after coercions: %u\n", t); #endif - if ( t2) - fprintf(stderr,"Continuing match after coercions\n"); + if (Debug > 2) + fprintf(stderr, "Continuing match after coercions\n"); #endif - t += codegen(codep,ply,FALSE,mincostcostlimit) { - if (besttup) - myfree((string)besttup); -normalfailed: if (stackpad!=tokpatlen) { - if (stackpad) { - for (i=0;i costlimit) + { + if (besttup) + myfree((string)besttup); + normalfailed: + if (stackpad != tokpatlen) + { + if (stackpad) + { + for (i = 0; i < stackheight - stackpad; i++) + fakestack[i] = fakestack[i + stackpad]; + stackheight -= stackpad; + if (costlimit < MAXINT) + BROKE(); + totalcost += stackupto(&fakestack[stackheight - 1], ply, toplevel); + } + else + totalcost += stackupto(fakestack, ply, toplevel); + CHKCOST(); + goto nextmatch; + } + totalcost += mincost; + for (i = 0; i < stackheight - stackpad; i++) + fakestack[i] = fakestack[i + stackpad]; + stackheight -= stackpad; BROKE(); - totalcost += stackupto(&fakestack[stackheight-1],ply,toplevel); - } else - totalcost += stackupto(fakestack,ply,toplevel); - CHKCOST(); - goto nextmatch; - } - totalcost += mincost; - for (i=0;ip_rar[i]); - assert(totalcost <= costlimit); - myfree((string)besttup); - break; - } - case DO_TOSTACK: - case DO_REMOVE: { - int texpno,nodeno; - token_p tp; - struct reginfo *rp; - int doremove = (codep[-1] & 037) == DO_REMOVE; - extern int allsetno; + } + for (i = 0; i < nregneeded; i++) + totalcost += docoerc(regtp[i], regcp[i], ply, toplevel, besttup->p_rar[i]); + assert(totalcost <= costlimit); + myfree((string)besttup); + break; + } + case DO_TOSTACK: + case DO_REMOVE: + { + int texpno, nodeno; + token_p tp; + struct reginfo* rp; + int doremove = (codep[-1] & 037) == DO_REMOVE; + extern int allsetno; - DEBUG(doremove ? "REMOVE" : "TOSTACK"); - if (codep[-1]&32) { - getint(texpno,codep); - getint(nodeno,codep); - } else { - getint(texpno,codep); - nodeno=0; - } - if (texpno == allsetno) { - totalcost += stackupto(&fakestack[stackheight-tokpatlen-1],ply,toplevel); - CHKCOST(); - if (doremove) for (rp=machregs;rpr_contents.t_token=0; - break; - } - for (tp= &fakestack[stackheight-tokpatlen-1];tp>=&fakestack[0];tp--) - if (match(tp,&machsets[texpno],nodeno)) { - /* investigate possible coercion to register */ - totalcost += stackupto(tp,ply,toplevel); - CHKCOST(); - break; - } - if (doremove) for (rp=machregs;rpr_contents.t_token != 0 && - match(&rp->r_contents,&machsets[texpno],nodeno)) { + DEBUG(doremove ? "REMOVE" : "TOSTACK"); + if (codep[-1] & 32) + { + getint(texpno, codep); + getint(nodeno, codep); + } + else + { + getint(texpno, codep); + nodeno = 0; + } + if (texpno == allsetno) + { + totalcost += stackupto(&fakestack[stackheight - tokpatlen - 1], ply, toplevel); + CHKCOST(); + if (doremove) + for (rp = machregs; rp < machregs + NREGS; rp++) + rp->r_contents.t_token = 0; + break; + } + for (tp = &fakestack[stackheight - tokpatlen - 1]; tp >= &fakestack[0]; tp--) + if (match(tp, &machsets[texpno], nodeno)) + { + /* investigate possible coercion to register */ + totalcost += stackupto(tp, ply, toplevel); + CHKCOST(); + break; + } + if (doremove) + for (rp = machregs; rp < machregs + NREGS; rp++) + { + if (rp->r_contents.t_token != 0 && match(&rp->r_contents, &machsets[texpno], nodeno)) + { #ifndef NDEBUG - if (Debug > 1) fprintf(stderr, "killing reg %ld (%s)\n", (long)(rp-machregs), rp->r_repr ? codestrings[rp->r_repr] : "cc"); + if (Debug > 1) + fprintf(stderr, "killing reg %ld (%s)\n", (long)(rp - machregs), rp->r_repr ? codestrings[rp->r_repr] : "cc"); #endif - rp->r_contents.t_token=0; - } - } - break; - } - case DO_KILLREG: - case DO_RREMOVE: { /* register remove */ - register i; - int nodeno; - token_p tp; - tkdef_p tdp; - result_t result; - int dokill = (codep[-1] & 037) == DO_KILLREG; + rp->r_contents.t_token = 0; + } + } + break; + } + case DO_KILLREG: + case DO_RREMOVE: + { /* register remove */ + register i; + int nodeno; + token_p tp; + tkdef_p tdp; + result_t result; + int dokill = (codep[-1] & 037) == DO_KILLREG; - DEBUG(dokill ? "KILLREG" : "RREMOVE"); - getint(nodeno,codep); - compute(&enodes[nodeno], &result); - if (result.e_typ!=EV_REG) - break; - if ( in_stack(result.e_v.e_reg) ) BROKE() ; /* Check aside-stack */ - if (dokill) { - /* kill register, and kill condition codes if they are set to + DEBUG(dokill ? "KILLREG" : "RREMOVE"); + getint(nodeno, codep); + compute(&enodes[nodeno], &result); + if (result.e_typ != EV_REG) + break; + if (in_stack(result.e_v.e_reg)) + BROKE(); /* Check aside-stack */ + if (dokill) + { + /* kill register, and kill condition codes if they are set to this register */ - machregs[result.e_v.e_reg].r_contents.t_token = 0; - if (machregs[0].r_contents.t_token == -1 && - machregs[0].r_contents.t_att[0].ar == result.e_v.e_reg) { - machregs[0].r_contents.t_token = 0; - } - } - for (tp= &fakestack[stackheight-tokpatlen-1];tp>=&fakestack[0];tp--) - if (tp->t_token==-1) { - if(tp->t_att[0].ar==result.e_v.e_reg) - goto gotone; - } else { - tdp = &tokens[tp->t_token]; - for(i=0;it_type[i]==EV_REG && - tp->t_att[i].ar==result.e_v.e_reg) - goto gotone; - } - break; - gotone: - /* investigate possible coercion to register */ - totalcost += stackupto(tp,ply,toplevel); - CHKCOST(); - break; - } - case DO_DEALLOCATE: { - register i; - tkdef_p tdp; - int tinstno; - token_t token; - - DEBUG("DEALLOCATE"); - getint(tinstno,codep); - instance(tinstno,&token); - if (token.t_token==-1) - chrefcount(token.t_att[0].ar,-1,TRUE); - else { - tdp= &tokens[token.t_token]; - for (i=0;it_type[i]==EV_REG) - chrefcount(token.t_att[i].ar,-1,TRUE); - } - break; - } - case DO_REALLOCATE: { - struct reginfo *rp; - - DEBUG("REALLOCATE"); - for(rp=machregs+1;rpr_tcount) { - rp->r_refcount -= rp->r_tcount; - rp->r_tcount = 0; - } - break; - } - case DO_ALLOCATE: { - register i; - int j; - int tinstno; - int npos,npos2,pos[NREGS],pos2[NREGS]; - unsigned mincost,t; - struct reginfo *rp,**rpp; - token_t token,token2; - int propno; - int exactmatch; - int decision; - - if (codep[-1]&32) { - getint(propno,codep); - getint(tinstno,codep); - DEBUG("ALLOCATE,INIT"); - } else { - getint(propno,codep); - tinstno=0; - DEBUG("ALLOCATE,EMPTY"); - } - instance(tinstno,&token); - if (!forced) { - do { - npos=exactmatch=0; - for(rpp=reglist[propno];rp= *rpp; rpp++) - if (getrefcount((int)(rp-machregs), FALSE)==0) { - pos[npos++] = rp-machregs; - if (eqtoken(&rp->r_contents,&token)) - pos2[exactmatch++] = rp-machregs; + machregs[result.e_v.e_reg].r_contents.t_token = 0; + if (machregs[0].r_contents.t_token == -1 && machregs[0].r_contents.t_att[0].ar == result.e_v.e_reg) + { + machregs[0].r_contents.t_token = 0; + } } - /* + for (tp = &fakestack[stackheight - tokpatlen - 1]; tp >= &fakestack[0]; tp--) + if (tp->t_token == -1) + { + if (tp->t_att[0].ar == result.e_v.e_reg) + goto gotone; + } + else + { + tdp = &tokens[tp->t_token]; + for (i = 0; i < TOKENSIZE; i++) + if (tdp->t_type[i] == EV_REG && tp->t_att[i].ar == result.e_v.e_reg) + goto gotone; + } + break; + gotone: + /* investigate possible coercion to register */ + totalcost += stackupto(tp, ply, toplevel); + CHKCOST(); + break; + } + case DO_DEALLOCATE: + { + register i; + tkdef_p tdp; + int tinstno; + token_t token; + + DEBUG("DEALLOCATE"); + getint(tinstno, codep); + instance(tinstno, &token); + if (token.t_token == -1) + chrefcount(token.t_att[0].ar, -1, TRUE); + else + { + tdp = &tokens[token.t_token]; + for (i = 0; i < TOKENSIZE; i++) + if (tdp->t_type[i] == EV_REG) + chrefcount(token.t_att[i].ar, -1, TRUE); + } + break; + } + case DO_REALLOCATE: + { + struct reginfo* rp; + + DEBUG("REALLOCATE"); + for (rp = machregs + 1; rp < machregs + NREGS; rp++) + if (rp->r_tcount) + { + rp->r_refcount -= rp->r_tcount; + rp->r_tcount = 0; + } + break; + } + case DO_ALLOCATE: + { + register i; + int j; + int tinstno; + int npos, npos2, pos[NREGS], pos2[NREGS]; + unsigned mincost, t; + struct reginfo *rp, **rpp; + token_t token, token2; + int propno; + int exactmatch; + int decision; + + if (codep[-1] & 32) + { + getint(propno, codep); + getint(tinstno, codep); + DEBUG("ALLOCATE,INIT"); + } + else + { + getint(propno, codep); + tinstno = 0; + DEBUG("ALLOCATE,EMPTY"); + } + instance(tinstno, &token); + if (!forced) + { + do + { + npos = exactmatch = 0; + for (rpp = reglist[propno]; rp = *rpp; rpp++) + if (getrefcount((int)(rp - machregs), FALSE) == 0) + { + pos[npos++] = rp - machregs; + if (eqtoken(&rp->r_contents, &token)) + pos2[exactmatch++] = rp - machregs; + } + /* * Now pos[] contains all free registers with desired * property. If none then some stacking has to take place. */ - if (npos==0) { - if (stackheight<=tokpatlen) { - if (!toplevel) { - BROKE(); - } else { - if (paniced) - fatal("No regs available"); - totalcost += stackupto( &fakestack[0],ply,toplevel); - goto panic; - } - } - totalcost += stackupto( &fakestack[0],ply,toplevel); - CHKCOST(); - } - } while (npos==0); + if (npos == 0) + { + if (stackheight <= tokpatlen) + { + if (!toplevel) + { + BROKE(); + } + else + { + if (paniced) + fatal("No regs available"); + totalcost += stackupto(&fakestack[0], ply, toplevel); + goto panic; + } + } + totalcost += stackupto(&fakestack[0], ply, toplevel); + CHKCOST(); + } + } while (npos == 0); - if (!exactmatch && tinstno!=0) { - /* + if (!exactmatch && tinstno != 0) + { + /* * No exact match, but we were looking for a particular * token. Now try to find registers of which no * known contents is available (the others might still * be useful). */ - for (i=0;i costlimit) + BROKE(); + } + } + else + { + decision = forced; + if (getrefcount(decision, FALSE) != 0) + BROKE(); + token2.t_token = -1; + } + chrefcount(decision, 1, FALSE); + token2.t_att[0].ar = decision; if (token.t_token != 0) - t=move(&token,&token2,ply,FALSE,mincost); - else { - t = 0; - erasereg(pos2[j]); + { + totalcost += move(&token, &token2, ply, toplevel, MAXINT); + CHKCOST(); } - if (tcostlimit) - BROKE(); - } - } else { - decision = forced; - if (getrefcount(decision, FALSE)!=0) - BROKE(); - token2.t_token = -1; - } - chrefcount(decision,1,FALSE); - token2.t_att[0].ar=decision; - if (token.t_token != 0) { - totalcost+=move(&token,&token2,ply,toplevel,MAXINT); - CHKCOST(); - } else - erasereg(decision); - allreg[nallreg++]=decision; - break; - } - case DO_INSTR: { - register i; - int n; - int tinstno; - token_t token; - int stringno; + case DO_INSTR: + { + register i; + int n; + int tinstno; + token_t token; + int stringno; - DEBUG("INSTR"); - n=((codep[-1]>>5)&07); - getint(stringno,codep); - if (toplevel) { - swtxt(); - if (stringno>10000) { - assert(stringno < 100001 + MAXPROCARG); - genstr(procarg[stringno-10001]); - } else - genstr(stringno); - } - for(i=0;i0) - totalcost += tokens[token.t_token].t_cost.ct_space; - } - if (toplevel) - gennl(); - CHKCOST(); - break; - } - case DO_MOVE: { - int tinstno; - token_t token,token2; + DEBUG("INSTR"); + n = ((codep[-1] >> 5) & 07); + getint(stringno, codep); + if (toplevel) + { + swtxt(); + if (stringno > 10000) + { + assert(stringno < 100001 + MAXPROCARG); + genstr(procarg[stringno - 10001]); + } + else + genstr(stringno); + } + for (i = 0; i < n; i++) + { + getint(tinstno, codep); + instance(tinstno, &token); + if (toplevel) + prtoken(&token, i == 0 ? ' ' : ','); + if (token.t_token > 0) + totalcost += tokens[token.t_token].t_cost.ct_space; + } + if (toplevel) + gennl(); + CHKCOST(); + break; + } + case DO_MOVE: + { + int tinstno; + token_t token, token2; - DEBUG("MOVE"); - getint(tinstno,codep); - instance(tinstno,&token); - getint(tinstno,codep); - instance(tinstno,&token2); - totalcost += move(&token,&token2,ply,toplevel,costlimit-totalcost+1); - CHKCOST(); - break; - } - case DO_TEST: { - int tinstno; - token_t token; + DEBUG("MOVE"); + getint(tinstno, codep); + instance(tinstno, &token); + getint(tinstno, codep); + instance(tinstno, &token2); + totalcost += move(&token, &token2, ply, toplevel, costlimit - totalcost + 1); + CHKCOST(); + break; + } + case DO_TEST: + { + int tinstno; + token_t token; - DEBUG("TEST"); - getint(tinstno,codep); - instance(tinstno,&token); - totalcost += test(&token,ply,toplevel,costlimit-totalcost+1); - CHKCOST(); - break; - } - case DO_SETCC: { - int tinstno; - token_t token; + DEBUG("TEST"); + getint(tinstno, codep); + instance(tinstno, &token); + totalcost += test(&token, ply, toplevel, costlimit - totalcost + 1); + CHKCOST(); + break; + } + case DO_SETCC: + { + int tinstno; + token_t token; - DEBUG("SETCC"); - getint(tinstno,codep); - instance(tinstno,&token); - setcc(&token); - break; - } - case DO_ERASE: { - int nodeno; - result_t result; + DEBUG("SETCC"); + getint(tinstno, codep); + instance(tinstno, &token); + setcc(&token); + break; + } + case DO_ERASE: + { + int nodeno; + result_t result; - DEBUG("ERASE"); - getint(nodeno,codep); - compute(&enodes[nodeno], &result); - assert(result.e_typ!=EV_INT && result.e_typ!=EV_ADDR); - if (result.e_typ==EV_REG) - { - int regno = result.e_v.e_reg; - erasereg(regno); - } - break; - } - case DO_TOKREPLACE: { - register i; - int tinstno; - int repllen; - token_t reptoken[MAXREPLLEN]; + DEBUG("ERASE"); + getint(nodeno, codep); + compute(&enodes[nodeno], &result); + assert(result.e_typ != EV_INT && result.e_typ != EV_ADDR); + if (result.e_typ == EV_REG) + { + int regno = result.e_v.e_reg; + erasereg(regno); + } + break; + } + case DO_TOKREPLACE: + { + register i; + int tinstno; + int repllen; + token_t reptoken[MAXREPLLEN]; - DEBUG("TOKREPLACE"); - assert(stackheight>=tokpatlen); - repllen=(codep[-1]>>5)&07; + DEBUG("TOKREPLACE"); + assert(stackheight >= tokpatlen); + repllen = (codep[-1] >> 5) & 07; #ifndef NDEBUG - if (Debug>2) - fprintf(stderr,"Stackheight=%d, tokpatlen=%d, repllen=%d %s\n", - stackheight,tokpatlen,repllen,inscoerc ? "(inscoerc)":""); + if (Debug > 2) + fprintf(stderr, "Stackheight=%d, tokpatlen=%d, repllen=%d %s\n", + stackheight, tokpatlen, repllen, inscoerc ? "(inscoerc)" : ""); #endif - for(i=0;i>5)&07; - j=emp-emlines; - if (emrepllen>j) { - assert(nemlines+emrepllen-j=0;i--) - emlines[i+emrepllen-j] = emlines[i]; - nemlines += emrepllen-j; - emp += emrepllen-j; - } - emp -= emrepllen; - for (i=0;i> 5) & 07; + j = emp - emlines; + if (emrepllen > j) + { + assert(nemlines + emrepllen - j < MAXEMLINES); + for (i = nemlines; i >= 0; i--) + emlines[i + emrepllen - j] = emlines[i]; + nemlines += emrepllen - j; + emp += emrepllen - j; + } + emp -= emrepllen; + for (i = 0; i < emrepllen; i++) + { + getint(eminstr, codep); + getint(nodeno, codep); + emp[i].em_instr = eminstr; + compute(&enodes[nodeno], &result[i]); + } + for (i = 0; i < emrepllen; i++) + { + switch (result[i].e_typ) + { + default: + assert(FALSE); + case 0: + emp[i].em_optyp = OPNO; + emp[i].em_soper = 0; + break; + case EV_INT: + emp[i].em_optyp = OPINT; + emp[i].em_soper = tostring(result[i].e_v.e_con); + emp[i].em_u.em_ioper = result[i].e_v.e_con; + break; + case EV_ADDR: + emp[i].em_optyp = OPSYMBOL; + emp[i].em_soper = ad2str(result[i].e_v.e_addr); + break; + } + } + if (!toplevel) + { + ply += emrepllen; #ifndef NDEBUG - if (Debug > 4) - fprintf(stderr, "ply becomes %d\n", ply); + if (Debug > 4) + fprintf(stderr, "ply becomes %d\n", ply); #endif - } - break; - } - case DO_COST: { - cost_t cost; + } + break; + } + case DO_COST: + { + cost_t cost; - DEBUG("COST"); - getint(cost.ct_space,codep); - getint(cost.ct_time,codep); - totalcost += costcalc(cost); - CHKCOST(); - break; - } + DEBUG("COST"); + getint(cost.ct_space, codep); + getint(cost.ct_time, codep); + totalcost += costcalc(cost); + CHKCOST(); + break; + } #ifdef REGVARS - case DO_PRETURN: { - if (toplevel) { - swtxt(); - regreturn(); /* in mach.c */ - } - break; - } + case DO_PRETURN: + { + if (toplevel) + { + swtxt(); + regreturn(); /* in mach.c */ + } + break; + } #endif - case DO_RETURN: - DEBUG("RETURN"); - assert(origcp!=startupcode); + case DO_RETURN: + DEBUG("RETURN"); + assert(origcp != startupcode); #ifndef NDEBUG - level--; + level--; #endif - return(totalcost); + return (totalcost); #ifdef USE_TES - case DO_LABDEF: { - int index; + case DO_LABDEF: + { + int index; - DEBUG("LABDEF"); - getint(index,codep); - if (toplevel) { - swtxt(); - printlabel(index); - } + DEBUG("LABDEF"); + getint(index, codep); + if (toplevel) + { + swtxt(); + printlabel(index); + } - break; - } + break; + } #endif + } } - } - doreturn: +doreturn: #ifdef ALLOW_NEXTEM - if (toplevel && totalcost == INFINITY && ! paniced) { + if (toplevel && totalcost == INFINITY && !paniced) + { DEBUG("PANIC!"); - totalcost += stackupto(&fakestack[stackheight-1], ply, toplevel); + totalcost += stackupto(&fakestack[stackheight - 1], ply, toplevel); #ifndef NDEBUG if (Debug > 2) fprintf(stderr, "Stackheight = %d\n", stackheight); @@ -929,18 +1092,21 @@ normalfailed: if (stackpad!=tokpatlen) { #ifndef NDEBUG level--; #endif - return(totalcost); + return (totalcost); } -readcodebytes() { +readcodebytes() +{ #ifndef CODEINC register fd; extern int ncodebytes; - if ((fd=open("code",0))<0) { + if ((fd = open("code", 0)) < 0) + { error("Can't open code"); } - if (read(fd,coderules,ncodebytes)!=ncodebytes) { + if (read(fd, coderules, ncodebytes) != ncodebytes) + { error("Short read from code"); } close(fd); @@ -948,30 +1114,34 @@ readcodebytes() { } #ifdef TABLEDEBUG -initlset(f) char *f; { - extern char *myalloc(); +initlset(f) char* f; +{ + extern char* myalloc(); set_flag = f; - if ((set_fd=open(f+1,2))<0) - error("Can't open %s rw",f+1); - read(set_fd,&set_size,sizeof(int)); - set_val=( short *) myalloc(set_size); - read(set_fd,set_val,set_size); + if ((set_fd = open(f + 1, 2)) < 0) + error("Can't open %s rw", f + 1); + read(set_fd, &set_size, sizeof(int)); + set_val = (short*)myalloc(set_size); + read(set_fd, set_val, set_size); } -termlset() { +termlset() +{ - if (set_fd) { - lseek(set_fd,(long) sizeof(int),0); - write(set_fd,set_val,set_size); + if (set_fd) + { + lseek(set_fd, (long)sizeof(int), 0); + write(set_fd, set_val, set_size); close(set_fd); - if (set_flag[0]=='u') { + if (set_flag[0] == 'u') + { register i; - - fprintf(stderr,"Unused code rules:\n\n"); - for(i=0;i<8*set_size;i++) - if(set_val[i>>4]&(1<<(i&017))) - fprintf(stderr,"\"%s\", line %d\n",tablename,i); + + fprintf(stderr, "Unused code rules:\n\n"); + for (i = 0; i < 8 * set_size; i++) + if (set_val[i >> 4] & (1 << (i & 017))) + fprintf(stderr, "\"%s\", line %d\n", tablename, i); } } } From 2cdcc16bc236e7277342077c1f6aab2fc3e93cda Mon Sep 17 00:00:00 2001 From: David Given Date: Mon, 16 Jan 2017 22:44:37 +0100 Subject: [PATCH 137/173] Fix a buffer overrun that was manifesting on OpenBSD; also fix a bounds check and some uninitialised variable problems. --- mach/proto/ncg/codegen.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/mach/proto/ncg/codegen.c b/mach/proto/ncg/codegen.c index 8c7958cf2..95a3c012d 100644 --- a/mach/proto/ncg/codegen.c +++ b/mach/proto/ncg/codegen.c @@ -66,8 +66,7 @@ short* set_val; char* set_flag; #endif -unsigned codegen(codep, ply, toplevel, costlimit, forced) byte* codep; -unsigned costlimit; +unsigned codegen(byte* codep, int ply, int toplevel, unsigned costlimit, int forced) { #ifndef NDEBUG byte* origcp = codep; @@ -75,7 +74,7 @@ unsigned costlimit; #endif unsigned totalcost = 0; int inscoerc = 0; - int procarg[MAXPROCARG + 1]; + int procarg[MAXPROCARG + 1] = {}; #ifdef ALLOW_NEXTEM static int paniced; char* savebp = 0; @@ -328,7 +327,6 @@ unsigned costlimit; tokpatlen = (codep[-1] >> 5) & 07; for (i = 0; i < tokpatlen; i++) getint(tokexp[i], codep); - tokexp[i] = 0; tp = &fakestack[stackheight - 1]; i = 0; while (i < tokpatlen && tp >= fakestack) @@ -860,7 +858,7 @@ unsigned costlimit; swtxt(); if (stringno > 10000) { - assert(stringno < 100001 + MAXPROCARG); + assert(stringno < 10001 + MAXPROCARG); genstr(procarg[stringno - 10001]); } else From c471f617b7d8ddc48bc6faad1425678ec6353ee1 Mon Sep 17 00:00:00 2001 From: David Given Date: Mon, 16 Jan 2017 22:45:03 +0100 Subject: [PATCH 138/173] Ensure that memory is zero-initialised. --- mach/proto/ncg/salloc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mach/proto/ncg/salloc.c b/mach/proto/ncg/salloc.c index e110d75ad..7ce1287bb 100644 --- a/mach/proto/ncg/salloc.c +++ b/mach/proto/ncg/salloc.c @@ -37,7 +37,7 @@ void chkstr(); string myalloc(size) { register string p; - p = (string) malloc((unsigned)size); + p = (string) calloc((unsigned)size, 1); if (p==0) fatal("Out of memory"); return(p); From e97116c0370426dc3568230df1e31d76a69ed39f Mon Sep 17 00:00:00 2001 From: George Koehler Date: Mon, 16 Jan 2017 18:09:55 -0500 Subject: [PATCH 139/173] Remove some obsolete code that causes a gcc warning. In my OpenBSD/amd64 system, the code becomes if (0) outname.on_valu &= ~(((0xFFFFFFFF)<<32)<<32); The 0xFFFFFFFF is a 32-bit int, so the left shift by 32 is out of range and causes the gcc warning. The intent might be to clear any sign-extended bits, if the assignment outname.on_valu = valu did sign extension. Old C had no unsigned long, so .on_valu would have been long. The code is obsolete because h/out.h now declares .on_valu as uint32_t. --- mach/proto/as/comm6.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/mach/proto/as/comm6.c b/mach/proto/as/comm6.c index 9cb943cba..fdbeb77ff 100644 --- a/mach/proto/as/comm6.c +++ b/mach/proto/as/comm6.c @@ -354,8 +354,6 @@ valu_t valu; outname.on_type = type; outname.on_desc = desc; outname.on_valu = valu; - if (sizeof(valu) != sizeof(long)) - outname.on_valu &= ~(((0xFFFFFFFF)<<(4*sizeof(valu_t)))<<(4*sizeof(valu_t))); wr_name(&outname, 1); } From 916d270534fb154d15f0633911bb223a190bf48a Mon Sep 17 00:00:00 2001 From: George Koehler Date: Mon, 16 Jan 2017 22:39:44 -0500 Subject: [PATCH 140/173] Delay inclusion of when compiling comm2.y See issue #1 (https://github.com/davidgiven/ack/issues/1). The file mach/proto/as/comm2.y goes through cpp twice. The _include macro, defined in comm2.y and used in comm0.h, delays the inclusion of system header files. The inclusion of wasn't delayed. This caused multiple inclusions of in FreeBSD and in OpenBSD. Use _include to delay . Also use _include for "arch.h" and "out.h", because h/out.h includes and h/arch.h might include it in the future. Sort the system includes in comm0.h by moving them up to be with . Must include before "mach0.c", because mach/powerpc/as/mach0.c needs it. Must include "mach0.c" before checking ASLD. --- mach/proto/as/comm0.h | 36 ++++++++++++++++++++---------------- 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/mach/proto/as/comm0.h b/mach/proto/as/comm0.h index dedafa4c7..2d00c8e45 100644 --- a/mach/proto/as/comm0.h +++ b/mach/proto/as/comm0.h @@ -8,7 +8,21 @@ * All preprocessor based options/constants/functions */ -#include +#ifdef _include +_include +_include +_include +_include +_include +_include +#else +#include +#include +#include +#include +#include +#include +#endif /* ========== ON/OFF options (use #define in mach0.c) ========== */ @@ -80,23 +94,16 @@ separate linker only possible if relocation info produced /* ========== Machine independent type declarations ========== */ #ifdef _include -_include -_include -_include -_include -_include -#else -#include -#include -#include -#include -#include +#ifdef ASLD +_include "arch.h" #endif - +_include "out.h" +#else #ifdef ASLD #include "arch.h" #endif #include "out.h" +#endif #if DEBUG == 0 #define assert(ex) /* nothing */ @@ -265,6 +272,3 @@ typedef struct sect_t sect_t; #define MACHREL_BWR (0) #endif #endif - -extern FILE *fopen(); /* some systems don't have this in stdio.h */ - From 81c677d218a3f14c8b94e9dbfca055ba27f6610a Mon Sep 17 00:00:00 2001 From: David Given Date: Tue, 17 Jan 2017 22:31:38 +0100 Subject: [PATCH 141/173] Add a bunch more set operations to the PowerPC backends, and the Pascal test for the same. --- mach/powerpc/libem/and.s | 6 ++++-- mach/powerpc/libem/com.s | 6 ++++-- mach/powerpc/libem/ior.s | 2 +- mach/powerpc/libem/rck.s | 4 ++-- mach/powerpc/libem/set.s | 2 +- mach/powerpc/ncg/table | 30 ++++++++++++++++++++---------- mach/proto/mcg/treebuilder.c | 22 +++++++++++++++++----- plat/linuxppc/libsys/trap.s | 2 ++ plat/qemuppc/libsys/trap.s | 7 ------- tests/plat/pascalsets_p.p | 9 +++++++++ 10 files changed, 60 insertions(+), 30 deletions(-) diff --git a/mach/powerpc/libem/and.s b/mach/powerpc/libem/and.s index 4a1a81c04..727d79ec0 100644 --- a/mach/powerpc/libem/and.s +++ b/mach/powerpc/libem/and.s @@ -3,11 +3,13 @@ .sect .text ! Set intersection. -! Stack: ( b a -- a*b ) -! With r3 = size of set +! Stack: ( b a size -- a*b ) .define .and .and: + lwz r3, 0 (sp) ! r3 = size + addi sp, sp, 4 + mr r4, sp ! r4 = ptr to set a add r5, sp, r3 ! r5 = ptr to set b rlwinm r6, r3, 30, 2, 31 diff --git a/mach/powerpc/libem/com.s b/mach/powerpc/libem/com.s index 8b7082332..084eeeb62 100644 --- a/mach/powerpc/libem/com.s +++ b/mach/powerpc/libem/com.s @@ -3,11 +3,13 @@ .sect .text ! Set complement. -! Stack: ( a -- ~a ) -! With r3 = size of set +! Stack: ( a size -- ~a ) .define .com .com: + lwz r3, 0 (sp) ! size + addi sp, sp, 4 + mr r4, sp ! r4 = pointer to set a rlwinm r5, r3, 30, 2, 31 mtspr ctr, r5 ! ctr = r3 / 4 diff --git a/mach/powerpc/libem/ior.s b/mach/powerpc/libem/ior.s index b3ebf81e9..363799e1d 100644 --- a/mach/powerpc/libem/ior.s +++ b/mach/powerpc/libem/ior.s @@ -3,7 +3,7 @@ .sect .text ! Set union. -! Stack: ( size b a -- a+b ) +! Stack: ( b a size -- a+b ) .define .ior .ior: diff --git a/mach/powerpc/libem/rck.s b/mach/powerpc/libem/rck.s index b716e5091..0d5717f16 100644 --- a/mach/powerpc/libem/rck.s +++ b/mach/powerpc/libem/rck.s @@ -3,13 +3,13 @@ .sect .text ! Bounds check. Traps if the value is out of range. -! Stack: ( descriptor value -- ) +! Stack: ( value descriptor -- value ) .define .rck .rck: lwz r3, 0 (sp) lwz r4, 4 (sp) - addi sp, sp, 8 + addi sp, sp, 4 ! leave value on stack lwz r5, 0 (r3) cmp cr0, 0, r4, r5 diff --git a/mach/powerpc/libem/set.s b/mach/powerpc/libem/set.s index daffb9c3d..b42881cd7 100644 --- a/mach/powerpc/libem/set.s +++ b/mach/powerpc/libem/set.s @@ -3,7 +3,7 @@ .sect .text ! Create singleton set. -! Stack: ( size bitnumber -- set ) +! Stack: ( bitnumber size -- set ) .define .set .set: diff --git a/mach/powerpc/ncg/table b/mach/powerpc/ncg/table index 6498c591c..6297f8889 100644 --- a/mach/powerpc/ncg/table +++ b/mach/powerpc/ncg/table @@ -1466,11 +1466,13 @@ PATTERNS yields %a pat and defined($1) /* AND set */ - with STACK - kills ALL - gen - move {CONST, $1}, R3 - bl {LABEL, ".and"} + leaving + loc $1 + cal ".and" + + pat and !defined($1) + leaving + cal ".and" pat ior $1==4 /* OR word */ with REG NOT_R @@ -1559,10 +1561,13 @@ PATTERNS yields {NOT_R, %1} pat com defined($1) /* NOT set */ - with STACK - gen - move {CONST, $1}, R3 - bl {LABEL, ".com"} + leaving + loc $1 + cal ".com" + + pat com !defined($1) + leaving + cal ".com" pat zer $1==4 /* Push zero */ leaving @@ -1663,6 +1668,10 @@ PATTERNS loc $1 cal ".inn" + pat inn !defined($1) + leaving + cal ".inn" + /* Boolean resolutions */ @@ -2053,13 +2062,14 @@ PATTERNS ass 4 pat lae rck $2==4 /* Range check */ - with GPR + with REG uses CR0 gen cmpli %a, {CONST, 0}, %1, {CONST, rom($1, 1)} bc IFTRUE, LT, {LABEL, ".trap_erange"} cmpli %a, {CONST, 0}, %1, {CONST, rom($1, 2)} bc IFTRUE, GT, {LABEL, ".trap_erange"} + yields %1 diff --git a/mach/proto/mcg/treebuilder.c b/mach/proto/mcg/treebuilder.c index ba4f7198f..eed770170 100644 --- a/mach/proto/mcg/treebuilder.c +++ b/mach/proto/mcg/treebuilder.c @@ -519,7 +519,19 @@ static void insn_simple(int opcode) } case op_trp: helper_function(".trp"); break; - case op_sig: helper_function(".sig"); break; + + case op_sig: + { + struct ir* value = pop(EM_pointersize); + appendir( + store( + EM_pointersize, + new_labelir(".trppc"), 0, + value + ) + ); + break; + } case op_rtt: { @@ -614,7 +626,7 @@ static void simple_alu1(int opcode, int size, int irop, const char* fallback) if (size > (2*EM_wordsize)) { if (!fallback) - fatal("treebuilder: can't do opcode %d with size %d", opcode, size); + fatal("treebuilder: can't do opcode %s with size %d", em_mnem[opcode - sp_fmnem], size); push( new_wordir(size) ); @@ -638,7 +650,7 @@ static void simple_alu2(int opcode, int size, int irop, const char* fallback) if (size > (2*EM_wordsize)) { if (!fallback) - fatal("treebuilder: can't do opcode %d with size %d", opcode, size); + fatal("treebuilder: can't do opcode %s with size %d", em_mnem[opcode - sp_fmnem], size); push( new_wordir(size) ); @@ -751,10 +763,10 @@ static void insn_ivalue(int opcode, arith value) case op_rmu: simple_alu2(opcode, value, IR_MODU, NULL); break; case op_dvu: simple_alu2(opcode, value, IR_DIVU, NULL); break; - case op_and: simple_alu2(opcode, value, IR_AND, NULL); break; + case op_and: simple_alu2(opcode, value, IR_AND, ".and"); break; case op_ior: simple_alu2(opcode, value, IR_OR, ".ior"); break; case op_xor: simple_alu2(opcode, value, IR_EOR, NULL); break; - case op_com: simple_alu1(opcode, value, IR_NOT, NULL); break; + case op_com: simple_alu1(opcode, value, IR_NOT, ".com"); break; case op_adf: simple_alu2(opcode, value, IR_ADDF, NULL); break; case op_sbf: simple_alu2(opcode, value, IR_SUBF, NULL); break; diff --git a/plat/linuxppc/libsys/trap.s b/plat/linuxppc/libsys/trap.s index 296f17391..93c5189a4 100644 --- a/plat/linuxppc/libsys/trap.s +++ b/plat/linuxppc/libsys/trap.s @@ -63,7 +63,9 @@ EUNIMPL = 63 ! unimplemented em-instruction called addi r3, r0, ERANGE b .trap +.define .trp .define .trap +.trp: .trap: cmpi cr0, 0, r3, 15 ! traps >15 can't be ignored bc IFTRUE, LT, 1f diff --git a/plat/qemuppc/libsys/trap.s b/plat/qemuppc/libsys/trap.s index 280adc33b..e00c4d561 100644 --- a/plat/qemuppc/libsys/trap.s +++ b/plat/qemuppc/libsys/trap.s @@ -63,10 +63,3 @@ EUNIMPL = 63 ! unimplemented em-instruction called .trp: .trap: b .trp ! spin forever - -.define .sig -.sig: - lwz r3, 0(sp) - li32 r4, .trppc - stw r3, 0(r4) - bclr ALWAYS, 0, 0 ! return diff --git a/tests/plat/pascalsets_p.p b/tests/plat/pascalsets_p.p index 3253414f9..b443b492d 100644 --- a/tests/plat/pascalsets_p.p +++ b/tests/plat/pascalsets_p.p @@ -24,5 +24,14 @@ begin for i := 0 to 255 do s := s + [chr(i)]; + i := 99; (* to defeat optimisation *) + ASSERT(chr(42) in s); + ASSERT(chr(142) in s); + ASSERT(chr(i) in s); + s := s - [chr(42)]; + ASSERT(not(chr(42) in s)); + ASSERT(chr(142) in s); + ASSERT(chr(i) in s); + finished end. From ba2a03705e497239fb73c8d030789bd773eca8e5 Mon Sep 17 00:00:00 2001 From: George Koehler Date: Tue, 17 Jan 2017 16:41:29 -0500 Subject: [PATCH 142/173] Use prototypes in mach/proto/as/comm5.c Order the function prototypes in comm1.h to match the order of the function definitions in *.c files. --- mach/proto/as/comm1.h | 33 +++++++++++++--------- mach/proto/as/comm5.c | 66 ++++++++++++++++++++++++------------------- 2 files changed, 57 insertions(+), 42 deletions(-) diff --git a/mach/proto/as/comm1.h b/mach/proto/as/comm1.h index 6a40a2e90..b3011ac97 100644 --- a/mach/proto/as/comm1.h +++ b/mach/proto/as/comm1.h @@ -104,21 +104,28 @@ extern struct outhead outhead; extern int curr_token; /* forward function declarations */ +/* comm5.c */ +int yylex(void); +void putval(int); +int getval(int); +int nextchar(void); #ifdef ASLD -extern char *readident(); +char *readident(int); #endif -extern char *remember(); -extern item_t *fb_shift(); -extern item_t *fb_alloc(); -extern item_t *item_alloc(); -extern item_t *item_search(); -extern valu_t load(); -extern FILE *ffcreat(); -extern FILE *fftemp(); - -extern void fatal(const char* s, ...); -extern void serror(const char* s, ...); -extern void warning(const char* s, ...); +int hash(char *); +item_t *item_search(char *); +void item_insert(item_t *, int); +item_t *item_alloc(int); +item_t *fb_alloc(int); +item_t *fb_shift(int); +/* comm7.c */ +valu_t load(); +char *remember(); +FILE *ffcreat(); +FILE *fftemp(); +void fatal(const char *, ...); +void serror(const char *, ...); +void warning(const char *, ...); /* ========== Machine dependent C declarations ========== */ diff --git a/mach/proto/as/comm5.c b/mach/proto/as/comm5.c index 7dee7c1a9..9120cea65 100644 --- a/mach/proto/as/comm5.c +++ b/mach/proto/as/comm5.c @@ -11,9 +11,16 @@ extern YYSTYPE yylval; -void putval(); +static void readcode(int); +static int induo(int); +static int inident(int); +static int innumber(int); +static int instring(int); +static int inescape(void); +static int infbsym(char *); -yylex() +int +yylex(void) { register c; @@ -71,7 +78,7 @@ yylex() } void -putval(c) +putval(int c) { register valu_t v; register n = 0; @@ -144,7 +151,8 @@ putval(c) putc(*p++, tempfile); } -getval(c) +int +getval(int c) { register n = 0; register valu_t v; @@ -209,7 +217,8 @@ getval(c) /* ---------- lexical scan in pass 1 ---------- */ -nextchar() +int +nextchar(void) { register c; @@ -233,7 +242,8 @@ nextchar() return(c); } -readcode(n) +static void +readcode(int n) { register c; @@ -252,8 +262,8 @@ readcode(n) } while (--n); } -induo(c) -register c; +static int +induo(int c) { static short duo[] = { ('='<<8) | '=', OP_EQ, @@ -277,8 +287,8 @@ register c; static char name[NAMEMAX+1]; -inident(c) -register c; +static int +inident(int c) { register char *p = name; register item_t *ip; @@ -309,8 +319,7 @@ register c; #ifdef ASLD char * -readident(c) -register c; +readident(int c) { register n = NAMEMAX; register char *p = name; @@ -326,8 +335,8 @@ register c; } #endif -innumber(c) -register c; +static int +innumber(int c) { register char *p; register radix; @@ -373,7 +382,8 @@ register c; return(NUMBER); } -instring(termc) +static int +instring(int termc) { register char *p; register c; @@ -412,7 +422,8 @@ instring(termc) return(STRING); } -inescape() +static int +inescape(void) { register c, j, r; @@ -442,8 +453,8 @@ inescape() return(c); } -infbsym(p) -register char *p; +static int +infbsym(char *p) { register lab; register item_t *ip; @@ -469,8 +480,8 @@ ok: return(FBSYM); } -hash(p) -register char *p; +int +hash(char *p) { register unsigned short h; register c; @@ -484,8 +495,7 @@ register char *p; } item_t * -item_search(p) -char *p; +item_search(char *p) { register h; register item_t *ip; @@ -503,15 +513,15 @@ done: return(ip); } -item_insert(ip, h) -item_t *ip; +void +item_insert(item_t *ip, int h) { ip->i_next = hashtab[h]; hashtab[h] = ip; } item_t * -item_alloc(typ) +item_alloc(int typ) { register item_t *ip; static nleft = 0; @@ -532,8 +542,7 @@ item_alloc(typ) } item_t * -fb_alloc(lab) -register lab; +fb_alloc(int lab) { register item_t *ip, *p; @@ -548,8 +557,7 @@ register lab; } item_t * -fb_shift(lab) -register lab; +fb_shift(int lab) { register item_t *ip; From 01a61e07084cd2484984e04a893e23bee124fe37 Mon Sep 17 00:00:00 2001 From: David Given Date: Wed, 18 Jan 2017 00:06:14 +0100 Subject: [PATCH 143/173] Apply kernigh@'s fix to broken symbol tables in aelflod (via mailing list patch): ---snip--- The ELF spec at http://www.sco.com/developers/gabi/ says, "In each symbol table, all symbols with STB_LOCAL binding precede the weak and global symbols," and that sh_info is the index of the first non-local symbol. I was mixing local and global symbols and setting sh_info to zero. I also forgot to set the type of the .shstrtab section. ---snip--- --- util/amisc/aelflod.c | 56 ++++++++++++++++++++++++++++++++------------ 1 file changed, 41 insertions(+), 15 deletions(-) diff --git a/util/amisc/aelflod.c b/util/amisc/aelflod.c index d5a9c0df3..dbaafc9b5 100644 --- a/util/amisc/aelflod.c +++ b/util/amisc/aelflod.c @@ -43,6 +43,7 @@ char* stringarea; uint32_t ack_off_char; int nstab = 0; /* S_STB symbol count */ int nsym = 0; /* other symbol count */ +int nlocal = 0; /* local symbols */ char* outputfile = NULL; /* Name of output file, or NULL */ char* program; /* Name of current program: argv[0] */ @@ -347,17 +348,29 @@ void emit_stab(void) void emit_symtab(void) { struct outname* n; - int i; + int i, pass; + bool global; - for (i = 0; i < outhead.oh_nname; i++) { - n = &outname[i]; - if (!(n->on_type & S_STB)) { - emit32(cvname(n)); /* name index */ - emit32(n->on_valu); /* value */ - emit32(0); /* size = unknown */ - emit8(cvinfo(n)); /* info */ - emit8(0); /* other */ - emit16(cvsect(n)); /* section */ + /* ELF .symtab must have local symbols before other symbols. + * We emit locals in pass 0, globals in pass 1. */ + for (pass = 0; pass < 2; pass++) { + for (i = 0; i < outhead.oh_nname; i++) { + n = &outname[i]; + + /* Don't emit .stab symbol in .symtab. */ + if (n->on_type & S_STB) + continue; + + global = (n->on_type & S_EXT); + if ((pass == 0 && !global) || + (pass == 1 && global)) { + emit32(cvname(n)); /* name index */ + emit32(n->on_valu); /* value */ + emit32(0); /* size = unknown */ + emit8(cvinfo(n)); /* info */ + emit8(0); /* other */ + emit16(cvsect(n)); /* section */ + } } } } @@ -386,8 +399,8 @@ void emit_shstrtab(void) void emit_sh(int i) { - uint32_t name, type, flags, addr, offset, size, addralign, - link, entsize; + uint32_t name, type, flags, addr, offset, size, link, info, + addralign, entsize; /* If no debugger symbols, skip .stab and .stabstr */ if (nstab == 0 && (i == N_STAB || i == N_STABSTR)) @@ -412,6 +425,7 @@ void emit_sh(int i) break; case N_STABSTR: case N_STRTAB: + case N_SHSTRTAB: type = 3; /* SHT_STRTAB */ break; default: @@ -495,6 +509,15 @@ void emit_sh(int i) break; } + switch (i) { + case N_SYMTAB: + info = nlocal; + break; + default: + info = 0; + break; + } + emit32(name); emit32(type); emit32(flags); @@ -502,7 +525,7 @@ void emit_sh(int i) emit32(offset); emit32(size); emit32(link); - emit32(0); /* info */ + emit32(info); emit32(addralign); emit32(entsize); } @@ -585,10 +608,13 @@ int rnames(FILE* f) outname[i].on_type = uget2(c); c += 2; outname[i].on_desc = uget2(c); c += 2; outname[i].on_valu = get4(c); - if (outname[i].on_type & S_STB) + if (outname[i].on_type & S_STB) { nstab++; - else + } else { nsym++; + if (!(outname[i].on_type & S_EXT)) + nlocal++; + } } stringarea = malloc(outhead.oh_nchar); From f705339f865948502c2d444e66392edff545986d Mon Sep 17 00:00:00 2001 From: George Koehler Date: Tue, 17 Jan 2017 22:41:11 -0500 Subject: [PATCH 144/173] Allow more tokens in the assembler. I need this so I can add more %token lines to mach/powerpc/as/mach2.c The assembler's tempfile encoded each token in a byte. This only worked with tokens 0 to 127 and 256 and 383. If a token 384 or higher existed, the assembler stopped working. I need tokens 384 and higher. I change the token encoding to a 2-byte little-endian integer. I also change a byte in the string encoding. --- mach/proto/as/comm5.c | 39 ++++++++++++++++++++++++--------------- 1 file changed, 24 insertions(+), 15 deletions(-) diff --git a/mach/proto/as/comm5.c b/mach/proto/as/comm5.c index 9120cea65..1fa84537d 100644 --- a/mach/proto/as/comm5.c +++ b/mach/proto/as/comm5.c @@ -22,7 +22,7 @@ static int infbsym(char *); int yylex(void) { - register c; + int c, c0, c1; if (pass == PASS_1) { /* scan the input file */ @@ -59,19 +59,24 @@ yylex(void) /* produce the intermediate token file */ if (c <= 0) return(0); - if (c <= 127) + if (c < 256) { putc(c, tempfile); - else + putc(0, tempfile); + } else { putval(c); + } } else { /* read from intermediate token file */ - c = getc(tempfile); - if (c == EOF) + c0 = getc(tempfile); + if (c0 == EOF) return(0); - if (c > 127) { - c += 128; + c1 = getc(tempfile); + if (c1 == EOF) + return(0); + + c = c0 + (c1 << 8); + if (c >= 256) c = getval(c); - } } curr_token = c; return(c); @@ -84,7 +89,7 @@ putval(int c) register n = 0; register char *p = 0; - assert(c >= 256 && c < 256+128); + assert(c == (c & 0xffff)); switch (c) { case CODE1: n = 1; goto putnum; @@ -99,9 +104,11 @@ putval(int c) break; v >>= 8; } + assert(n <= 4); c = NUMBER0 + n; putnum: - putc(c-128, tempfile); + putc(c, tempfile); + putc(c >> 8, tempfile); v = yylval.y_valu; while (--n >= 0) putc((int) (v >> (n*8)), tempfile); @@ -117,14 +124,15 @@ putval(int c) #endif case STRING: v = stringlen; - putc(c-128, tempfile); + putc(c, tempfile); + putc(c >> 8, tempfile); for (n = 0; n < sizeof(v); n++) { if (v == 0) break; v >>= 8; } - c = NUMBER0 + n; - putc(c-128, tempfile); + assert(n <= 4); + putc(n, tempfile); v = stringlen; while (--n >= 0) putc((int) (v >> (n*8)), tempfile); @@ -146,7 +154,8 @@ putval(int c) n = sizeof(word_t); p = (char *) &yylval.y_word; break; } - putc(c-128, tempfile); + putc(c, tempfile); + putc(c >> 8, tempfile); while (--n >= 0) putc(*p++, tempfile); } @@ -193,7 +202,7 @@ getval(int c) p = (char *) &yylval.y_strp; break; #endif case STRING: - getval(getc(tempfile)+128); + getval(getc(tempfile)+NUMBER0); stringlen = n = yylval.y_valu; p = stringbuf; p[n] = '\0'; break; From d5a83fd73e2eb14dd9e20cda3719710369fb2022 Mon Sep 17 00:00:00 2001 From: David Given Date: Wed, 18 Jan 2017 19:55:56 +0100 Subject: [PATCH 145/173] Clean up the led includes. --- util/led/archive.c | 2 +- util/led/error.c | 8 +++++--- util/led/extract.c | 4 +++- util/led/finish.c | 4 ++++ util/led/main.c | 4 +++- util/led/memory.c | 15 +++++++++------ util/led/output.c | 6 +++++- util/led/read.c | 5 +++++ util/led/save.c | 4 +++- util/led/scan.c | 4 +++- util/led/sym.c | 8 +++++--- util/led/write.c | 6 ++++-- 12 files changed, 50 insertions(+), 20 deletions(-) diff --git a/util/led/archive.c b/util/led/archive.c index 7cb3397b8..7e39e9fb7 100644 --- a/util/led/archive.c +++ b/util/led/archive.c @@ -6,8 +6,8 @@ static char rcsid[] = "$Id$"; #endif -#include #include +#include #include #include #include "arch.h" diff --git a/util/led/error.c b/util/led/error.c index e7f4fc6ec..61dc7983e 100644 --- a/util/led/error.c +++ b/util/led/error.c @@ -6,9 +6,11 @@ static char rcsid[] = "$Id$"; #endif -#include -#include #include +#include +#include +#include +#include #include #include "const.h" @@ -73,7 +75,7 @@ do_verbose(char *format, ...) static void diag(char *tail, char *format, va_list ap) { - extern char *progname, *archname, *modulname; + extern char *progname, *archname, *modulname; fprintf(stderr, "%s: ", progname); if (archname && modulname) diff --git a/util/led/extract.c b/util/led/extract.c index 5878d527d..48a2f16c6 100644 --- a/util/led/extract.c +++ b/util/led/extract.c @@ -6,8 +6,10 @@ static char rcsid[] = "$Id$"; #endif -#include #include +#include +#include +#include #include "out.h" #include "const.h" #include "debug.h" diff --git a/util/led/finish.c b/util/led/finish.c index 2eace760b..439d4b364 100644 --- a/util/led/finish.c +++ b/util/led/finish.c @@ -6,6 +6,10 @@ static char rcsid[] = "$Id$"; #endif +#include +#include +#include +#include #include #include "const.h" #include "defs.h" diff --git a/util/led/main.c b/util/led/main.c index 028bc3b3f..125f0c9a5 100644 --- a/util/led/main.c +++ b/util/led/main.c @@ -11,7 +11,9 @@ static char rcsid[] = "$Id$"; */ #include +#include #include +#include #include #include "const.h" #include "debug.h" @@ -168,7 +170,7 @@ first_pass(argv) case 'c': /* * Leave relocation information in the output, so that - * a next pass can see where relocation was done. The + * a next pass can see where relocation was done. The * resulting output however is no longer relocatable. */ flagword &= ~RFLAG; diff --git a/util/led/memory.c b/util/led/memory.c index 6349c826a..df4ee99d9 100644 --- a/util/led/memory.c +++ b/util/led/memory.c @@ -22,6 +22,9 @@ static char rcsid[] = "$Id$"; */ #include +#include +#include +#include #include #include "const.h" #include "assert.h" @@ -112,7 +115,7 @@ init_core() incore = FALSE; /* In core strategy failed. */ if (sbreak(AT_LEAST) == -1) fatal("no core at all"); - + base = BASE; for (mem = mems; mem < &mems[NMEMS]; mem++) { mem->mem_base = base; @@ -198,15 +201,15 @@ compact(piece, incr, flag) gain = (mem->mem_full + incr) >> SHIFT_COUNT; if (incr < gain) incr = gain; } - + /* * First, check that moving will result in enough space */ if (flag != FREEZE) { gain = mem->mem_left; for (mem = &mems[piece-1]; mem >= &mems[0]; mem--) { - /* - * Don't give it all away! + /* + * Don't give it all away! * If this does not give us enough, bad luck */ if (flag == FORCED) @@ -224,8 +227,8 @@ compact(piece, incr, flag) } if (min == piece) for (mem = &mems[piece+1]; mem <= &mems[NMEMS - 1]; mem++) { - /* - * Don't give it all away! + /* + * Don't give it all away! * If this does not give us enough, bad luck */ if (flag == FORCED) diff --git a/util/led/output.c b/util/led/output.c index 0ee622e3a..835627631 100644 --- a/util/led/output.c +++ b/util/led/output.c @@ -6,6 +6,10 @@ static char rcsid[] = "$Id$"; #endif +#include +#include +#include +#include #include #include "const.h" #include "memory.h" @@ -60,7 +64,7 @@ generate_section_names() extern struct outsect outsect[]; extern char *core_alloc(); - size = (long)outhead.oh_nsect * sizeof(struct outname); + size = (long)outhead.oh_nsect * sizeof(struct outname); name = (struct outname *)core_alloc(ALLOGLOB, size); if (name == (struct outname *)0) return; diff --git a/util/led/read.c b/util/led/read.c index 95ec7dd6b..3ea15925c 100644 --- a/util/led/read.c +++ b/util/led/read.c @@ -6,6 +6,11 @@ static char rcsid[] = "$Id$"; #endif +#include +#include +#include +#include + int infile; /* The current input file. */ rd_fatal() diff --git a/util/led/save.c b/util/led/save.c index 3804413d9..952649633 100644 --- a/util/led/save.c +++ b/util/led/save.c @@ -10,8 +10,10 @@ static char rcsid[] = "$Id$"; * If everything is kept in core, we must save some things for the second pass. */ -#include #include +#include +#include +#include #include #include "arch.h" #include "out.h" diff --git a/util/led/scan.c b/util/led/scan.c index a870f8e05..1740a14de 100644 --- a/util/led/scan.c +++ b/util/led/scan.c @@ -6,8 +6,10 @@ static char rcsid[] = "$Id$"; #endif -#include #include +#include +#include +#include #ifdef SYMDBUG #include #include diff --git a/util/led/sym.c b/util/led/sym.c index 2ec47b6b7..53f0f3440 100644 --- a/util/led/sym.c +++ b/util/led/sym.c @@ -10,8 +10,10 @@ static char rcsid[] = "$Id$"; * Symbol table management. */ -#include #include +#include +#include +#include #include "out.h" #include "const.h" #include "memory.h" @@ -49,7 +51,7 @@ init_symboltable() * in the hash table is followed. If the names match, a pointer to the outname * in this element of the list is returned. When a match cannot be found, * NIL is returned. - */ + */ struct outname * searchname(string, hashval) char *string; @@ -74,7 +76,7 @@ searchname(string, hashval) debug("found %x, %x, %lx\n", name->on_type, name->on_desc, name->on_valu, 0); return name; - } + } symindex = sym->sy_next; } /* Not found. */ diff --git a/util/led/write.c b/util/led/write.c index d77ea98ef..b916949ae 100644 --- a/util/led/write.c +++ b/util/led/write.c @@ -6,8 +6,10 @@ static char rcsid[] = "$Id$"; #endif -#include #include +#include +#include +#include #include #include "out.h" #include "const.h" @@ -75,7 +77,7 @@ end_write() for (sectindex = 0; sectindex < outhead.oh_nsect; sectindex++) wrt_name(sectname(sectindex), 1); } - + wrt_emit(emit, sectindex, cnt) char *emit; int sectindex; From 9cc264cfee18f8a1491794fafb0959122a83fbf4 Mon Sep 17 00:00:00 2001 From: David Given Date: Wed, 18 Jan 2017 20:10:16 +0100 Subject: [PATCH 146/173] Add a man page for the PowerPC assembler (not used anywhere yet). --- man/powerpc_as.6 | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 man/powerpc_as.6 diff --git a/man/powerpc_as.6 b/man/powerpc_as.6 new file mode 100644 index 000000000..8198d6bce --- /dev/null +++ b/man/powerpc_as.6 @@ -0,0 +1,33 @@ +.TH POWERPC_AS 1 +.ad +.SH NAME +powerpc_as \- assembler for PowerPC + +.SH SYNOPSIS +as [options] argument ... + +.SH DESCRIPTION +This assembler is made with the general framework +described in \fIuni_ass\fP(6). + +.SH SYNTAX +Most 32-bit integer and floating point instructions are supported, but not many +short form instructions. Instructions which take 16-bit operands can additionally +use the following special functions: + +.IP hi16[value], ha16[value] +Returns the high half of the value of the expression; if the value is not absolute, +also generates the appropriate fixup. Use of either of these \fImust\fR be followed, +in the next instruction, by the corresponding use of \fBlo16[]\fR. Use \fBhi16[]\fR +if the low half is going to interpret its payload as an unsigned value, and +\fBha16[]\fR if it will be interpreted as a signed value (so that the high half can +be adjusted to match). + +.IP lo16[] +Returns the low half of the value of the expression. No fixup is generated. Use of +\fBlo16[]\fR must come in the instruction immediately after a use of \fBhi16[]\fR or +\fBha16[]\fR. + +.SH "SEE ALSO" +uni_ass(6), +ack(1) From f91bc2804d46b43b6d6aea876c95d6e05664fbe7 Mon Sep 17 00:00:00 2001 From: George Koehler Date: Wed, 18 Jan 2017 23:02:30 -0500 Subject: [PATCH 147/173] Tune the installed manual pages. This commit slightly improves the formatting of the manuals. My OpenBSD machine uses mandoc(1) to format manuals. I check the manuals with `mandoc -T lint` and fix most of the warnings. I also make other changes where mandoc didn't warn me. roff(7) says, "Each sentence should terminate at the end of an input line," but we often forgot this rule. I insert some newlines after sentences that had ended mid-line. roff(7) also says that blank lines "are only permitted within literal contexts." I delete blank lines. This removes some extra blank lines from mandoc's output. If I do want a blank line in the output, I call ".sp 1" to make it in man(7). If I want a blank line in the source, but not the output, I put a plain dot "." so roff ignores it. Hyphens used for command-line options, like \-a, should be escaped by a backslash. I insert a few missing backslashes. mandoc warns if the date in .TH doesn't look like a date. Our manuals had a missing date or the RCS keyword "$Revision$". Git doesn't expand RCS keywords. I put in today's date, 2017-01-18. Some manuals used tab characters in filled mode. That doesn't work. I use .nf to turn off filled mode, or I use .IP in man(7) to make the indentation without a tab character. ack(1) defined a macro .SB but never used it, so I delete the definition. I also remove a call to the missing macro .RF. mandoc warns about empty paragraphs. I deleted them. mandoc also warned about these macro pairs in anm(1): .SM .B text The .SM did nothing because the .B text is on a different line. I changed each pair to .SB for small bold text. I make a few other small changes. --- lang/b/compiler/em_b.6 | 47 ++++++++--------------- lang/m2/comp/em_m2.6 | 15 ++++---- lang/pc/comp/em_pc.6 | 22 ++++++----- util/ack/ack.1.X | 87 ++++++++++++++++++++---------------------- util/amisc/abmodules.1 | 14 +++---- util/amisc/aelflod.1 | 5 ++- util/amisc/anm.1 | 30 ++++++--------- util/amisc/ashow.1 | 6 +-- util/amisc/asize.1 | 2 +- util/amisc/aslod.1 | 4 +- util/amisc/astrip.1 | 5 ++- util/arch/aal.1 | 12 +++--- util/led/ack.out.5 | 43 ++++++++++++--------- util/led/led.6 | 22 ++++++----- util/misc/em_decode.6 | 5 +-- util/misc/esize.1 | 5 ++- util/opt/em_opt.6 | 21 +++++----- 17 files changed, 166 insertions(+), 179 deletions(-) diff --git a/lang/b/compiler/em_b.6 b/lang/b/compiler/em_b.6 index e0d1b40fe..f7030f214 100644 --- a/lang/b/compiler/em_b.6 +++ b/lang/b/compiler/em_b.6 @@ -1,68 +1,53 @@ -.TH EM_B 6 +.TH EM_B 6 2017-01-18 .ad - - .SH NAME em_b \- ACK B compiler - - .SH SYNOPSIS .B ~em/lib/ack/em_b -.RI [ options ] - - +.RI [ options ] .SH DESCRIPTION .I em_b -is a port of the ABC B compiler to the ACK. Interested parties will be +is a port of the ABC B compiler to the ACK. +Interested parties will be interested in the upstream distribution here: - .nf .sp https://github.com/aap/abc .fi - -However, the version here has been heavily modified --- bug reports should be +.PP +However, the version here has been heavily modified \(em bug reports should be filed with the ACK, not with the upstream compiler. - .PP Since B was designed for machines with word addressing, some hacking is -required to make it work on modern, byte addressed machines. The generated +required to make it work on modern, byte addressed machines. +The generated code expects B variables to contain word addresses, and then generates code to transform these into native addresses before use (which, -unfortunately, impacts performance). However, the ACK's linker doesn't know +unfortunately, impacts performance). +However, the ACK's linker doesn't know how to emit word addresses into the program's data sections, and so a separate fixup stage has to happen at runtime, just before \fBmain()\fP, to convert the byte addresses into word addresses. - .PP The end result is that using multiple source files with B is somewhat unwieldy, requiring each module to be explicitly named and then an extra -stage to generate the fixup code. See the \fBack\fP(1) and \fBabmodules\fP(1) -for details. - - +stage to generate the fixup code. +See the \fBack\fP(1) and \fBabmodules\fP(1) for details. .SH OPTIONS - .I em_b accepts the following flags: - .IP \-w\ \fIsize\fP -Sets the word size, used for scaling addresses. Usually either 2 or 4. - +Sets the word size, used for scaling addresses. +Usually either 2 or 4. .IP \-B\ \fIname\fP Sets the name of the module currently being compiled (used to generate the -fixup table symbol name). Defaults to \fImain\fP if not specified. - +fixup table symbol name). +Defaults to \fImain\fP if not specified. .IP \-i\ \fIfilename\fP The source B file. - .IP \-o\ \fIfilename\fP The output compact EM bytecode file. - - - .SH SEE ALSO \fIack\fR(1), \fIabmodules\fR(1) - .SH REMARKS It is very unlikely the \fIem_b\fP will ever be useful for anything. diff --git a/lang/m2/comp/em_m2.6 b/lang/m2/comp/em_m2.6 index a122a4a30..dfe41a3df 100644 --- a/lang/m2/comp/em_m2.6 +++ b/lang/m2/comp/em_m2.6 @@ -1,10 +1,10 @@ -.TH EM_M2 6 "$Revision$" +.TH EM_M2 6 2017-01-18 .ad .SH NAME em_m2 \- ACK Modula\-2 compiler .SH SYNOPSIS .B ~em/lib.bin/em_m2 -.RI [ option ] +.RI [ option ] .I source .I destination .SH DESCRIPTION @@ -15,9 +15,9 @@ into EM code. The input is taken from .IR source , while the -EM code is written on +EM code is written on .IR destination . -.br +.PP .I Option is a, possibly empty, sequence of the following combinations: .IP \fB\-I\fIdirname\fR @@ -65,7 +65,8 @@ make all procedure names global, so that \fIadb\fR(1) understands them. .IP \fB\-g\fR produce a DBX-style symbol table. .IP \fB\-l\fR -enable local extensions. Currently, there are two local extensions: +enable local extensions. +Currently, there are two local extensions: procedure constants, and the type LONGCARD. .IP \fB\-s\fR make INTEGER ranges symmetric, t.i., MIN(INTEGER) = - MAX(INTEGER). @@ -77,11 +78,11 @@ disable all range checks. enable extra array bound checks, for machines that do not implement the EM ones. .IP \fB-U\fR -allow for underscores within identifiers. Identifiers may not start with +allow for underscores within identifiers. +Identifiers may not start with an underscore, even if this flag is given. .IP \fB-3\fR only accept Modula-2 programs that strictly conform to [1]. -.LP .SH SEE ALSO \fIack\fR(1), \fImodula-2\fR(1) .IP [1] diff --git a/lang/pc/comp/em_pc.6 b/lang/pc/comp/em_pc.6 index f544e0536..7ba0de3eb 100644 --- a/lang/pc/comp/em_pc.6 +++ b/lang/pc/comp/em_pc.6 @@ -1,4 +1,4 @@ -.TH EM_PC 6 "$Revision$" +.TH EM_PC 6 2017-01-18 .ad .SH NAME em_pc \- Pascal compiler @@ -45,9 +45,9 @@ and the \fIn\fR parameter for the alignment of that type. Absence of \fIm\fR or \fIn\fR causes a default value to be retained. .IP \fB\-w\fR suppress warning messages. -.IP .IP \fB\-R\fR -disable range checks. Additionally, the run-time tests to see if +disable range checks. +Additionally, the run-time tests to see if a function is assigned, are skipped. .IP \fB\-A\fR enable extra array bound checks, for machines that do not implement the @@ -55,26 +55,28 @@ EM ones. .IP \fB\-C\fR the lower case and upper case letters are treated differently. .IP "\fB\-u\fR, \fB\-U\fR" -allow underscores in identifiers. It is not allowed to start an identifier +allow underscores in identifiers. +It is not allowed to start an identifier with an underscore. .IP \fB\-a\fR don't generate code for assertions. .IP \fB\-c\fR -allow C-like strings. This option is mainly intended for usage with -C-functions. This option will cause the type 'string' to be known. +allow C-like strings. +This option is mainly intended for usage with C-functions. +This option will cause the type 'string' to be known. .IP \fB\-d\fR allow the type 'long'. .IP \fB\-i\fR\fIn\fR set the size of integer sets to \fIn\fR. When not used, a default value is retained. .IP \fB\-s\fR -allow only standard Pascal. This disables the \fB\-c\fR, \fB\-d\fR, \fB\-u\fR, -\fB\-U\fR and \fB\-C\fR -options. Furthermore, assertions are not recognized at all (instead of just +allow only standard Pascal. +This disables the \fB\-c\fR, \fB\-d\fR, \fB\-u\fR, +\fB\-U\fR and \fB\-C\fR options. +Furthermore, assertions are not recognized at all (instead of just being skipped). .IP \fB\-t\fR trace calls and exits of procedures and functions. -.PP .SH FILES .IR ~em/lib/em_pc : binary of the Pascal compiler. diff --git a/util/ack/ack.1.X b/util/ack/ack.1.X index 671aa4e47..8ea920586 100644 --- a/util/ack/ack.1.X +++ b/util/ack/ack.1.X @@ -1,23 +1,12 @@ -.\" $Id$ -.de SB -.\" SuBheader -.sp 1 -.PP -.nr Sf \\n(.f -.ft B -\\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9 -.ft \\n(Sf -.sp 1 -.. -.TH ACK 1 "$Revision$" +.TH ACK 1 2017-01-18 .ad - +. .SH NAME ack \- Amsterdam Compiler Kit - +. .SH SYNOPSIS \fBack\fP arguments - +. .SH DESCRIPTION This program transforms sources in several languages to load files for a variety of machines, @@ -73,10 +62,8 @@ Optimized compact EM assembly code. Machine assembly language code. .IP .o Object file. -.PP - +. .SH OPTIONS - \fIAck\fP accepts the following flags: .IP \-m\fImachine\fP This flag tells \fIack\fP to generate a load file for \fImachine\fP. @@ -106,7 +93,8 @@ Note: \fIack\fP refuses to overwrite argument \fI.e\fP files. Preserve all intermediate files. If two \fB\-t\fP are used, \fIack\fP also preserves output of failed transformations. - +. +.sp 1 .IP \-w Suppress all warning messages. .IP \-v @@ -118,7 +106,8 @@ Tell the C-compiler to conform to "Kernighan & Ritchie" C. Tell \fIack\fP to use the ANSI C compiler instead of the old one. .IP \-fp Use the software floating point package, if present. - +. +.sp 1 .IP \-I\fIdir\fP \&\`#include\' files whose names do not begin with \`/\' are always sought first in the directory of the \fIfile\fP argument, @@ -136,7 +125,8 @@ preprocessing. Don't generate line directives. .IP \-C Leave C-comments in. - +. +.sp 1 .IP \-p This flag tells both the Pascal and C front ends to include code enabling the user to do some monitoring/debugging. @@ -144,13 +134,16 @@ Each time a routine is entered the routine \fBprocentry\fP is called and just before each return \fBprocexit\fP is called. These routines are supplied with one parameter, a pointer to a string containing the name of the routine. - +. +.sp 1 .IP \-B\fIname\fP Tells the B front end what the name of the module being compiled is, for use -with separate compilation. Defaults to +with separate compilation. +Defaults to .I main if not specified. See the section below on compiling B. - +. +.sp 1 .IP \-O .IP \-O\fInum\fP .IP \-O\fIopt1,opt2,...\fP @@ -239,7 +232,8 @@ for higher levels: as for \-O4. Disable the generation of code by the front ends to record line number and source file name at run-time. (This is the default for C and Fortran). - +. +.sp 1 .IP \-l\fIname\fP Tells \fIack\fP to insert a library module at this point. For example: the library \fImon\fP contains the @@ -259,13 +253,14 @@ These flags tell \fIack\fP to include the libraries needed when a file with \fIsuffix\fP would be included in the arguments. .IP \-LIB This flag tells the peephole optimizer -.RF em_opt 6 +em_opt(6) to add information about the visibility of the names used to each output module. This is needed by assembler/linkers when these modules are to be inserted in libraries. - +. +.sp 1 .IP \-{xxx} The string starting after \`{\' and terminated by a \`}\' is passed as an option string to the Pascal compiler and supersedes corresponding @@ -293,7 +288,8 @@ the defaults per program. The changed options are recorded in the "e.out" header. These flags \-\- and \-+ are passed to the assembler for this purpose. So, \-\-t and \-+pfce invert the defaults. - +. +.sp 1 .IP \-R\fIprogram=xxx\fP Replace the \fIprogram\fP by the pathname \fIxxx\fP. The program names referred to later in this manual are allowed here. @@ -320,7 +316,7 @@ Sparc, Vax, Intel 80386. .PP All arguments without a suffix or with an unrecognized suffix are passed to the loaders, as for flags. - +. .SH PREPROCESSOR All C source programs are run through the preprocessor before they are fed to the compiler proper. @@ -341,40 +337,37 @@ EM_WSIZE:wordsize:EM_PSIZE:pointer size EM_SSIZE:size of shorts (C):EM_LSIZE:size of longs (C+Pascal) EM_FSIZE:size of floats (C):EM_DSIZE:size of doubles (C+Pascal) .TE -.sp 1 +.PP The name of the \fImachine\fP or something like it when the machine name is numeric is also defined (as 1). As the ANSI C rules forbid this, in ANSI C, underscores are prepended to these names. .PP The default directories searched for include files differ for each machine. - +. .SH COMPILING B - -B programs have special needs when compiled with the ACK. B modules have to be +B programs have special needs when compiled with the ACK. +B modules have to be initialised before use, to convert pointer addresses to word addresses; this is done automatically when compiling a single B source file to an executable, but must be done manually when using separate compilation. - .PP To do this, compile your B modules with the \fI-B\fP option as usual, and then use the .B abmodules program to scan the object files and emit a C file which performs the -initialisation. Then compile this as well into an object file, and link the -whole lot together. The result will be a runnable executable. - +initialisation. +Then compile this as well into an object file, and link the +whole lot together. +The result will be a runnable executable. .PP -Beware --- referring to an uninitialised module will cause your program to +Beware \(em referring to an uninitialised module will cause your program to crash! - .PP The default initialiser in the B standard library looks for a module called \fBmain\fP. - .PP For example: - .nf .sp ack -c -mpc86 thismodule.b -Bthismodule @@ -384,7 +377,7 @@ abmodules -o binit.c thismodule.o thatmodule.o theothermodule.o ack -c -mpc86 binit.c ack -mpc86 -o pc86.exe thismodule.o thatmodule.o theothermodule.o binit.o .fi - +. .SH PROGRAMS \fIAck\fP uses one or more programs in each phase of the transformation. @@ -421,7 +414,7 @@ input:name:output:description \&.o:cv:a.out:Conversion from Ack object to machine object .TE .in -2 - +. .SH "ENVIRONMENT VARIABLES" .IP ACKDIR If set, this environment variable overrides ack's idea of its home @@ -432,13 +425,14 @@ machine it compiles for. .IP ACKFE If set, this environment variable tells ack where to get the front-end description file. +. .SH "SEE ALSO" -.PD 0 em_opt(6), em_ass(6), em_cg(6), ack.out(5) .IP [1] A.S. Tanenbaum, Hans van Staveren, Ed Keizer and Johan Stevenson, \fIDescription of a machine architecture for use with block structured languages\fP, Informatica rapport IR-81. +.PD 0 .IP [2] K. Jensen and N. Wirth, \fIPASCAL, User manual and report\fP Springer Verlag. @@ -463,12 +457,13 @@ Informatica rapport IR-99. .IP [11] C.J.H. Jacobs, \fIThe ACK Modula-2 Compiler\fP. .PD +. .SH DIAGNOSTICS -.PD The diagnostics are intended to be self\-explanatory. +. .SH BUGS Not all warning messages are superseded by \fB\-w\fP. -.br +.PP Argument assembly files are not preprocessed when fed into the universal assembler/loader. .SH AUTHOR diff --git a/util/amisc/abmodules.1 b/util/amisc/abmodules.1 index 8d34871f0..1eb67d843 100644 --- a/util/amisc/abmodules.1 +++ b/util/amisc/abmodules.1 @@ -1,18 +1,17 @@ -.TH ABMODULES 1 +.TH ABMODULES 1 2017-01-18 .SH NAME abmodules \- find B modules - .SH SYNOPSIS abmodules [ \-o outputfile.c ] [ file ... ] - .SH DESCRIPTION .I abmodules finds B modules in a set of ack.out(5) format object files, and either lists them or generates a C file which initialises the modules. .PP This tool is used for multiple compilation of B programs; B modules must be -initiaised before use, and this tool generates the initialisation code for -programs containing an abitrary number of modules. See em_b(6) for details. +initialised before use, and this tool generates the initialisation code for +programs containing an abitrary number of modules. +See em_b(6) for details. .PP Options are: .TP @@ -20,8 +19,7 @@ Options are: Write C source to .I filename containing a definition of a binit() function which will initalise all modules -found. If not present, a simple list of module names is written to stdout -instead. - +found. +If not present, a simple list of module names is written to stdout instead. .SH SEE ALSO ack.out(5), em_b(6) diff --git a/util/amisc/aelflod.1 b/util/amisc/aelflod.1 index 808b95429..e6af7ef2e 100644 --- a/util/amisc/aelflod.1 +++ b/util/amisc/aelflod.1 @@ -1,9 +1,10 @@ -.TH AELFLOD 1 "$Revision$" +.TH AELFLOD 1 2017-01-18 .SH NAME aelflod \- ACK ELF loader .SH SYNOPSIS .B aelflod -[-a\fInumber\fP] [-b] [-h] [-l] [-m\fInumber\fP] [-v] inputfile outputfile +[\-a\fInumber\fP] [\-b] [\-h] [\-l] [\-m\fInumber\fP] [\-v] +inputfile outputfile .SH DESCRIPTION .I aelflod converts an absolute ack.out file into a simple binary memory diff --git a/util/amisc/anm.1 b/util/amisc/anm.1 index 48cdff814..a76be02cd 100644 --- a/util/amisc/anm.1 +++ b/util/amisc/anm.1 @@ -1,4 +1,4 @@ -.TH ANM 1 "$Revision$" +.TH ANM 1 2017-01-18 .SH NAME anm \- print name list .SH SYNOPSIS @@ -7,7 +7,8 @@ anm [ \-gnoprus ] [ file ... ] .I Anm prints the name list (symbol table) of each ack.out(5) format object .I file -in the argument list. If an argument is an aal(1) or arch(1) archive, +in the argument list. +If an argument is an aal(1) or arch(1) archive, a listing of each object file in the archive will be produced. If no .I file @@ -18,32 +19,24 @@ are listed. Each symbol name is preceded by its value, a section indicator and a type indicator. A section indicator can be -.SM -.B U +.SB U (undefined symbol), -.SM -.B A +.SB A (absolute symbol), -.SM -.B C +.SB C (common symbol), a section number (section related symbol), or -.SM -.B - +.SB \- (other symbol). A type indicator can be -.SM -.B F +.SB F (filename), -.SM -.B M +.SB M (module name), -.SM -.B E +.SB E (external (global) symbol), or -.SM -.B - +.SB \- (local symbol). The output is sorted alphabetically. .PP @@ -69,6 +62,5 @@ Print only undefined symbols. .TP .B \-s Sort in section order. -.sh FILES .SH SEE ALSO ack.out(5) diff --git a/util/amisc/ashow.1 b/util/amisc/ashow.1 index 842c8ea35..1aaac2623 100644 --- a/util/amisc/ashow.1 +++ b/util/amisc/ashow.1 @@ -1,12 +1,12 @@ -.TH ASLOD 1 "$Revision$" +.TH ASHOW 1 2017-01-18 .SH NAME ashow \- make the contents of an ACK object file human readable .SH SYNOPSIS ashow inputfile inputfile... .SH DESCRIPTION .I ashow -dumps the contents of an ack.out file in human-readable form. It shows +dumps the contents of an ack.out file in human-readable form. +It shows details of all symbols, relocation entries, sections, and other information. - .SH "SEE ALSO" ack.out(5) diff --git a/util/amisc/asize.1 b/util/amisc/asize.1 index 89454dcaf..36a4d6ada 100644 --- a/util/amisc/asize.1 +++ b/util/amisc/asize.1 @@ -1,4 +1,4 @@ -.TH ASIZE 1 "$Revision$" +.TH ASIZE 1 2017-01-18 .SH NAME asize \- size of an object file .SH SYNOPSIS diff --git a/util/amisc/aslod.1 b/util/amisc/aslod.1 index f81590739..5a1f857a0 100644 --- a/util/amisc/aslod.1 +++ b/util/amisc/aslod.1 @@ -1,9 +1,9 @@ -.TH ASLOD 1 "$Revision$" +.TH ASLOD 1 2017-01-18 .SH NAME aslod \- ACK simple loader .SH SYNOPSIS .B aslod -[-h] [-v] inputfile outputfile +[\-h] [\-v] inputfile outputfile .SH DESCRIPTION .I aslod converts an absolute ack.out file into a simple binary memory dump. diff --git a/util/amisc/astrip.1 b/util/amisc/astrip.1 index 2f83bf1ab..1a3fa5433 100644 --- a/util/amisc/astrip.1 +++ b/util/amisc/astrip.1 @@ -1,4 +1,4 @@ -.TH ASTRIP 1 "$Revision$" +.TH ASTRIP 1 2017-01-18 .SH NAME astrip \- remove symbols and relocation information .SH SYNOPSIS @@ -11,6 +11,7 @@ ack.out(5) format object files. This is useful to save space after a program has been debugged. .SH FILES -/tmp/s? temporary file +.IP /tmp/s? 16n +temporary file .SH "SEE ALSO" ack.out(5) diff --git a/util/arch/aal.1 b/util/arch/aal.1 index 93b41191e..7f9af68ed 100644 --- a/util/arch/aal.1 +++ b/util/arch/aal.1 @@ -1,5 +1,4 @@ -.\" $Id$ -.TH AAL 1 "$Revision$" +.TH AAL 1 2017-01-18 .ad .SH NAME aal \- archive and library maintainer @@ -18,10 +17,10 @@ only understands archives made with .PP .I Key is one character from the set -.B qdrtx, +.BR qdrtx , optionally concatenated with one or more of -.B vlc. +.BR vlc . .I Afile is the archive file. The @@ -82,9 +81,10 @@ The create option supresses the normal message that is produced when .I afile is created. .SH FILES -/tmp/ar.* temporaries +.IP /tmp/ar.* 16 +temporaries .SH "SEE ALSO" -led(6), arch(5), +led(6), arch(5) .SH BUGS If the same file is mentioned twice in an argument list, it may be put in the archive twice. diff --git a/util/led/ack.out.5 b/util/led/ack.out.5 index b49b0976b..fa997e8ca 100644 --- a/util/led/ack.out.5 +++ b/util/led/ack.out.5 @@ -1,4 +1,4 @@ -.TH "ACK.OUT" 5 "$Revision$" +.TH "ACK.OUT" 5 2017-01-18 .ad .SH NAME ack.out\ \-\ ACK-assembler and link editor output @@ -14,7 +14,7 @@ further processed on another. .ta \w'#define x'u +\w'XXXXXXXX'u +\w'XXXXXXXXXXX'u .PP In the following discussion, some structures are defined using -\fBlong\fR and \fBshort\fR as type indicators. +\fBlong\fR and \fBshort\fR as type indicators. It is assumed that the size of a short is 2 bytes (chars) and that the size of a long is 4 bytes. However, these types @@ -55,7 +55,9 @@ struct outhead { }; .fi .PP +.nf #define HF_LINK 0x0004 /* unresolved references left */ +.fi .PP The fields of this structure have the following purpose: .nr x \w'oh_magic\ \ \ 'u @@ -131,9 +133,10 @@ in tact. .br The next part of an object file contains the sections themselves. Usually, the LED program places the sections right behind one another in the -target machine, taking the -alignment requirements into account. However, the user is allowed to give -the start addresses of each section. But if the user gave a start address for +target machine, taking the alignment requirements into account. +However, the user is allowed to give +the start addresses of each section. +But if the user gave a start address for say section 2, but not for section 3, section 3 will be put right behind section 2. .PP @@ -194,13 +197,16 @@ The fields of this structure have the following purpose: Contains several flags: One of RELO1, RELO2 and RELO4 is set, indicating the size of the relocatable datum, RELPC is set when the datum is relocated pc relative, RELBR and RELWR indicate byte and word order of -the relocatable datum. RELBR and RELWR are needed here. It is not sufficient +the relocatable datum. +RELBR and RELWR are needed here. +It is not sufficient to have flags for them in the header of the object file, because some machines (NS 32016) use several of the possible combinations in their instruction encoding. .IP or_sect \nxu -Contains the section number of the referenc\fIing\fR section. This is a number -that lies between S_MIN and S_MAX. The section indicated with number S_MIN +Contains the section number of the referenc\fIing\fR section. +This is a number that lies between S_MIN and S_MAX. +The section indicated with number S_MIN is the first section in the sections-section, etc. .IP or_addr \nxu Contains the address of the relocatable datum, in the form of an @@ -209,10 +215,12 @@ offset from the base of the section indicated in the \fIor_sect\fR field. Usually contains the index of the referenced symbol in the symbol table, starting at 0. In this case, the reference is to an undefined external symbol, a common -symbol, or a section name. The relocatable datum then contains +symbol, or a section name. +The relocatable datum then contains an offset from the indicated symbol or the start of the indicated section. It may, however, also have the same value as -the \fIoh_nname\fR field of the header. In this case the relocatable datum +the \fIoh_nname\fR field of the header. +In this case the relocatable datum is an absolute number, and the datum is relocated pc relative. The relocatable datum must then be relocated with respect to the base address of its section. @@ -250,12 +258,13 @@ struct outname { .PP The members of this structure have the following purpose: .IP on_foff \nxu -Contains the offset of the name from the beginning of the file. The name -extends from the offset to the next null byte. +Contains the offset of the name from the beginning of the file. +The name extends from the offset to the next null byte. .IP on_type \nxu The S_TYP field of this member contains the section number of the symbol. Here, this number may be S_ABS for an absolute item, or S_UND, for an -undefined item. The S_EXT flag is set in this member if the symbol is external. +undefined item. +The S_EXT flag is set in this member if the symbol is external. The S_ETC field has the following flags: S_SCT is set if the symbol represents a section name, S_COM is set if the symbol represents a common name, @@ -265,15 +274,16 @@ and S_MOD is set if the symbol refers to an assembler source file item. .IP on_desc \nxu Currently not used. .IP on_valu \nxu -Is not used if the symbol refers to an undefined item. For absolute items +Is not used if the symbol refers to an undefined item. +For absolute items it contains the value, for common names it contains the size, and for anything else it contains the offset from the beginning of the section. In a fully linked binary, the beginning of the section is added. .PP .B The string area. .br -The last part of an object file contains the name list. This is just a -sequence of null-terminated strings. +The last part of an object file contains the name list. +This is just a sequence of null-terminated strings. .PP The relocation information, the symbol table, and the name list do not have to be present, but then of course we do not have a relocatable @@ -283,7 +293,6 @@ object file. .br The following miscellaneous defines might come in handy when reading object files: -.fi .PP .nf /* diff --git a/util/led/led.6 b/util/led/led.6 index c89866efe..8e4b98e69 100644 --- a/util/led/led.6 +++ b/util/led/led.6 @@ -1,4 +1,4 @@ -.TH LED 6 "$Revision$" +.TH LED 6 2017-01-18 .ad .SH NAME led \- link editor @@ -78,7 +78,7 @@ The previous remarks about and .I nnnn apply. -.TP +.TP .B \-o The .I name @@ -88,7 +88,7 @@ is used as the name of the .I led output file, instead of .BR a.out . -.TP +.TP .B \-r Generate relocation information in the output file so that it can be the subject of another @@ -104,7 +104,8 @@ at load time. This flag disables the \fB\-r\fP flag. .TP .B \-n Usually, after linking, a value in the namelist represents an absolute -address. Sometimes, particularly when using the \fB\-c\fR flag, it may be +address. +Sometimes, particularly when using the \fB\-c\fR flag, it may be useful to have as value the offset with respect to the beginning of the corresponding section. The \fB\-n\fR flag enables this. .TP @@ -112,7 +113,7 @@ corresponding section. The \fB\-n\fR flag enables this. `Strip' the output, that is, remove the name table and relocation information to save space (but impair the usefulness of the debuggers). -.TP +.TP .B \-u Take the following argument as a symbol and enter it as undefined in the name table. @@ -129,9 +130,12 @@ chose to link it (which unresolved reference it resolves). This option is useful in resolving 'multiply defined' problems. .SH FILES ~em/lib.bin/em_led -a.out output file +.PD 0 +.IP a.out 24n +output file +.PD .SH "SEE ALSO" -ack(1) -arch(1) -ack.out.h(5) +ack(1), +arch(1), +ack.out.h(5), uni_ass(6) diff --git a/util/misc/em_decode.6 b/util/misc/em_decode.6 index 92f7a084d..a21c939eb 100644 --- a/util/misc/em_decode.6 +++ b/util/misc/em_decode.6 @@ -1,8 +1,7 @@ -.\" $Id$ -.TH EM_DECODE 6 "$Revision$" +.TH EM_DECODE 6 2017-01-18 .ad .SH NAME -em_decode,em_encode \- compact to readable EM and v.v. +em_decode, em_encode \- compact to readable EM and v.v. .SH SYNOPSIS .B ~em/lib.bin/em_decode [ inputfile [ outputfile ] ] diff --git a/util/misc/esize.1 b/util/misc/esize.1 index e62a17028..c05eb42f3 100644 --- a/util/misc/esize.1 +++ b/util/misc/esize.1 @@ -1,4 +1,4 @@ -.TH ESIZE I +.TH ESIZE 1 2017-01-18 .SH NAME esize \- print info from e.out header .SH SYNOPSIS @@ -9,7 +9,8 @@ esize \- print info from e.out header prints information from the .I e.out headers of the indicated files, including flags, word and pointer sizes, -text and data sizes, etc. All values are in decimal. +text and data sizes, etc. +All values are in decimal. .PP If no parameters are given, the header of .I e.out diff --git a/util/opt/em_opt.6 b/util/opt/em_opt.6 index bdb6587d9..267bd9c69 100644 --- a/util/opt/em_opt.6 +++ b/util/opt/em_opt.6 @@ -1,11 +1,10 @@ -.\" $Id$ -.TH EM_OPT 6 "$Revision$" +.TH EM_OPT 6 2017-01-18 .ad .SH NAME em_opt \- EM peephole optimizer .SH SYNOPSIS .B ~em/lib.bin/em_opt -[-Ln] [-m[l]] [ argument ] +[\-Ln] [\-m[l]] [ argument ] .SH DESCRIPTION Em_opt reads a compact EM-program, argument or standard input, and produces another compact EM program on standard output @@ -15,22 +14,22 @@ Some other functions are here that make this program mandatory before running a codegenerator, it may be left out when interpretation is wanted. Flags recognized are: -.IP -L +.IP \-L Make a library module. This means that the output will start with a message giving the names of all exported entities in this module. -.IP -n +.IP \-n Do not optimize. No peephole optimizations will be performed, other functions will be carried out. -.IP -m +.IP \-m Try to replace multiplies with constants by combinations of shifts and adds, -but no more than of them. Integer overflow detection is lost with this -option. -.IP -ml -Like -m, but also for long multiplies. +but no more than of them. +Integer overflow detection is lost with this option. +.IP \-ml +Like \-m, but also for long multiplies. .SH "FILES" -/tmp/emopt??????, is used when the -L flag is given only. +/tmp/emopt??????, is used when the \-L flag is given only. .SH "SEE ALSO" ack(1) .PD 0 From 5aa2ac2246e23eac95f66447cfc6c532a4173717 Mon Sep 17 00:00:00 2001 From: George Koehler Date: Sat, 21 Jan 2017 23:49:29 -0500 Subject: [PATCH 148/173] Teach the assembler about PowerPC extended mnemonics. Also make a few changes to basic mnemonics. Fix typo in name of the basic "creqv". Add the basic "addc" and relatives, because it would be odd to have the extended "subc" without "addc". Fix the basic "rldicl", "rldicr", "rldic", "rldimi" to correctly encode the 6-bit MB field. Fix "slw" and relatives to correctly swap their RA and RS operands. Add many, but not all, of the extended mnemonics from IBM's Power ISA Version 2.06 Book I Appendix E. (I used 2.06, published 2009, just because I already had the PDF of it.) This commit includes mnemonics for branching, subtraction, traps, bit rotation, and a few others, like "mflr" and "nop". The assembler now understands branches like `beq cr7, label` and bit shifts like `slwi r7, r7, 2`. These encode the same machine instructions as the basic "bc" and "rlwinm". Some operands to basic names become optional. The assembler no longer requires the level in "sc" or the branch hint in "bcctr" and "bclr"; they default to zero. Some extended names take an optional branch hint or condition register. Some extended names are still missing. I don't provide names with static branch prediction, like "beq+" or "bge-", because the assembler parses '+' and '-' as operators, not as part of an instruction name. I also don't provide some names that 2.06 has for moving to or from the condition register or some special purpose registers, names like "mtcr" or "mfuamr". This commit also deletes some unused tokens and one unused yacc rule. --- mach/powerpc/as/mach0.c | 6 + mach/powerpc/as/mach2.c | 57 ++++--- mach/powerpc/as/mach3.c | 333 +++++++++++++++++++++++++++++++++++++--- mach/powerpc/as/mach4.c | 200 +++++++++++++++++++++--- 4 files changed, 531 insertions(+), 65 deletions(-) diff --git a/mach/powerpc/as/mach0.c b/mach/powerpc/as/mach0.c index 325c08910..3246828fc 100644 --- a/mach/powerpc/as/mach0.c +++ b/mach/powerpc/as/mach0.c @@ -31,3 +31,9 @@ typedef uint32_t quad; #define VALWIDTH 8 #define FIXUPFLAGS (RELBR | RELWR) + +/* 6-bit mb (mask begin) or me (mask end) field */ +#define MB6(v) (((v) & 0x1F)<<6 | ((v) & 0x20)>>0) + +/* 6-bit sh (shift) field */ +#define SH6(v) (((v) & 0x1F)<<11 | ((v) & 0x20)>>4) diff --git a/mach/powerpc/as/mach2.c b/mach/powerpc/as/mach2.c index 3ecaf10cf..555b92c38 100644 --- a/mach/powerpc/as/mach2.c +++ b/mach/powerpc/as/mach2.c @@ -8,20 +8,35 @@ %token FPR %token CR %token C +%token OP_HI OP_HA OP_LO %token OP +%token OP_BDA +%token OP_BDL %token OP_BF %token OP_BF_BFA %token OP_BF_FRA_FRB %token OP_BF_L_RA_RB %token OP_BF_L_RA_SI %token OP_BF_L_RA_UI +%token OP_BF_RA_RB +%token OP_BF_RA_SI +%token OP_BF_RA_UI %token OP_BF_U_C +%token OP_BH +%token OP_BI_BDA +%token OP_BI_BDL +%token OP_BI_BH +%token OP_BICR_BDA +%token OP_BICR_BDL +%token OP_BICR_BH %token OP_BO_BI_BDA %token OP_BO_BI_BDL %token OP_BO_BI_BH %token OP_BT_C +%token OP_BT_BA_BA %token OP_BT_BA_BB +%token OP_BT_BT_BT %token OP_FLM_FRB_C %token OP_FRS_RA_D %token OP_FRS_RA_RB @@ -32,16 +47,18 @@ %token OP_FRT_FRB_C %token OP_FRT_RA_D %token OP_FRT_RA_RB -%token OP_L %token OP_LEV %token OP_LIA %token OP_LIL -%token OP_L_RB -%token OP_RA_RB -%token OP_RB -%token OP_RS +%token OP_LI32 +%token OP_RA_RS_RB_C +%token OP_RA_RS_RB_MB5_ME5_C +%token OP_RA_RS_RB_MB6_C +%token OP_RA_RS_SH5_C +%token OP_RA_RS_SH5_MB5_ME5_C +%token OP_RA_RS_SH6_C +%token OP_RA_RS_SH6_MB6_C %token OP_RS_FXM -%token OP_RS_L %token OP_RS_RA %token OP_RS_RA_C %token OP_RS_RA_D @@ -50,14 +67,6 @@ %token OP_RS_RA_RB %token OP_RS_RA_RB_C %token OP_RS_RA_RA_C -%token OP_RS_RA_RB_MB5_ME5_C -%token OP_RS_RA_RB_MB6_C -%token OP_RS_RA_RB_ME6_C -%token OP_RS_RA_SH_MB5_ME5_C -%token OP_RS_RA_SH_MB6_SH_C -%token OP_RS_RA_SH_ME6_SH_C -%token OP_RS_RA_SH5_C -%token OP_RS_RA_SH6_C %token OP_RS_RA_UI %token OP_RS_RA_UI_CC %token OP_RS_RB @@ -73,22 +82,26 @@ %token OP_RT_RA_RB_C %token OP_RT_RA_SI %token OP_RT_RA_SI_addic +%token OP_RT_RA_SI_subi +%token OP_RT_RA_SI_subic %token OP_RT_RB +%token OP_RT_RB_RA_C +%token OP_RT_SI %token OP_RT_SPR %token OP_RT_SR %token OP_RT_TBR %token OP_TH_RA_RB %token OP_TO_RA_RB %token OP_TO_RA_SI - -%token OP_LA -%token OP_LI32 - -%token OP_POWERPC_FIXUP -%token OP_HI OP_HA OP_LO +%token OP_TOX_RA_RB +%token OP_TOX_RA_SI +%token OP_clrlsldi OP_clrldi OP_clrrdi OP_extldi OP_extrdi +%token OP_insrdi OP_rotrdi OP_sldi OP_srdi +%token OP_clrlslwi OP_clrlwi OP_clrrwi OP_extlwi OP_extrwi +%token OP_inslwi OP_insrwi OP_rotlwi OP_rotrwi OP_slwi OP_srwi /* Other token types */ %type c -%type e16 u8 u7 u6 u5 u4 u2 u1 -%type nb ds bda bdl lia lil spr_num +%type e16 negate16 u8 u7 u6 u5 u4 u2 u1 +%type opt_bh cr_opt nb ds bda bdl lia lil spr_num diff --git a/mach/powerpc/as/mach3.c b/mach/powerpc/as/mach3.c index 724ba7312..16c1e6ae0 100644 --- a/mach/powerpc/as/mach3.c +++ b/mach/powerpc/as/mach3.c @@ -99,9 +99,6 @@ /* Special instructions */ 0, OP_LI32, 0, "li32", -0, OP_LA, 0, "la", -0, OP_LA, 0, "li", -0, OP_RS_RA_RA_C, 31<<26 | 444<<1, "mr", 0, OP_HI, 0, "hi16", 0, OP_HA, 0, "ha16", 0, OP_LO, 0, "lo16", @@ -126,11 +123,173 @@ 0, OP_BT_BA_BB, 19<<26 | 193<<1, "crxor", 0, OP_BT_BA_BB, 19<<26 | 225<<1, "crnand", 0, OP_BT_BA_BB, 19<<26 | 33<<1, "crnor", -0, OP_BT_BA_BB, 19<<26 | 289<<1, "crneqv", +0, OP_BT_BA_BB, 19<<26 | 289<<1, "creqv", 0, OP_BT_BA_BB, 19<<26 | 129<<1, "crandc", 0, OP_BT_BA_BB, 19<<26 | 417<<1, "crorc", 0, OP_BF_BFA, 19<<26 | 0<<1, "mcrf", +/* extended mnemonics for bc, bcctr, bclr */ +0, OP_BH, 19<<26 | 20<<21 | 528<<1 | 0<<0, "bctr", +0, OP_BH, 19<<26 | 20<<21 | 528<<1 | 1<<0, "bctrl", +0, OP_BDL, 16<<26 | 16<<21 | 0<<1 | 0<<0, "bdnz", +0, OP_BDA, 16<<26 | 16<<21 | 1<<1 | 0<<0, "bdnza", +0, OP_BH, 19<<26 | 16<<21 | 16<<1 | 0<<0, "bdnzlr", +0, OP_BDL, 16<<26 | 16<<21 | 0<<1 | 1<<0, "bdnzl", +0, OP_BDA, 16<<26 | 16<<21 | 1<<1 | 1<<0, "bdnzla", +0, OP_BH, 19<<26 | 16<<21 | 16<<1 | 1<<0, "bdnzlrl", +0, OP_BI_BDL, 16<<26 | 0<<21 | 0<<1 | 0<<0, "bdnzf", +0, OP_BI_BDA, 16<<26 | 0<<21 | 1<<1 | 0<<0, "bdnzfa", +0, OP_BI_BH, 19<<26 | 0<<21 | 16<<1 | 0<<0, "bdnzflr", +0, OP_BI_BDL, 16<<26 | 0<<21 | 0<<1 | 1<<0, "bdnzfl", +0, OP_BI_BDA, 16<<26 | 0<<21 | 1<<1 | 1<<0, "bdnzfla", +0, OP_BI_BH, 19<<26 | 0<<21 | 16<<1 | 1<<0, "bdnzflrl", +0, OP_BI_BDL, 16<<26 | 8<<21 | 0<<1 | 0<<0, "bdnzt", +0, OP_BI_BDA, 16<<26 | 8<<21 | 1<<1 | 0<<0, "bdnzta", +0, OP_BI_BH, 19<<26 | 8<<21 | 16<<1 | 0<<0, "bdnztlr", +0, OP_BI_BDL, 16<<26 | 8<<21 | 0<<1 | 1<<0, "bdnztl", +0, OP_BI_BDA, 16<<26 | 8<<21 | 1<<1 | 1<<0, "bdnztla", +0, OP_BI_BH, 19<<26 | 8<<21 | 16<<1 | 1<<0, "bdnztlrl", +0, OP_BDL, 16<<26 | 18<<21 | 0<<1 | 0<<0, "bdz", +0, OP_BDA, 16<<26 | 18<<21 | 1<<1 | 0<<0, "bdza", +0, OP_BH, 19<<26 | 18<<21 | 16<<1 | 0<<0, "bdzlr", +0, OP_BDL, 16<<26 | 18<<21 | 0<<1 | 1<<0, "bdzl", +0, OP_BDA, 16<<26 | 18<<21 | 1<<1 | 1<<0, "bdzla", +0, OP_BH, 19<<26 | 18<<21 | 16<<1 | 1<<0, "bdzlrl", +0, OP_BI_BDL, 16<<26 | 2<<21 | 0<<1 | 0<<0, "bdzf", +0, OP_BI_BDA, 16<<26 | 2<<21 | 1<<1 | 0<<0, "bdzfa", +0, OP_BI_BH, 19<<26 | 2<<21 | 16<<1 | 0<<0, "bdzflr", +0, OP_BI_BDL, 16<<26 | 2<<21 | 0<<1 | 1<<0, "bdzfl", +0, OP_BI_BDA, 16<<26 | 2<<21 | 1<<1 | 1<<0, "bdzfla", +0, OP_BI_BH, 19<<26 | 2<<21 | 16<<1 | 1<<0, "bdzflrl", +0, OP_BI_BDL, 16<<26 | 10<<21 | 0<<1 | 0<<0, "bdzt", +0, OP_BI_BDA, 16<<26 | 10<<21 | 1<<1 | 0<<0, "bdzta", +0, OP_BI_BH, 19<<26 | 10<<21 | 16<<1 | 0<<0, "bdztlr", +0, OP_BI_BDL, 16<<26 | 10<<21 | 0<<1 | 1<<0, "bdztl", +0, OP_BI_BDA, 16<<26 | 10<<21 | 1<<1 | 1<<0, "bdztla", +0, OP_BI_BH, 19<<26 | 10<<21 | 16<<1 | 1<<0, "bdztlrl", +0, OP_BI_BDL, 16<<26 | 4<<21 | 0<<1 | 0<<0, "bf", +0, OP_BI_BDA, 16<<26 | 4<<21 | 1<<1 | 0<<0, "bfa", +0, OP_BI_BH, 19<<26 | 4<<21 | 528<<1 | 0<<0, "bfctr", +0, OP_BI_BH, 19<<26 | 4<<21 | 528<<1 | 1<<0, "bfctrl", +0, OP_BI_BDL, 16<<26 | 4<<21 | 0<<1 | 1<<0, "bfl", +0, OP_BI_BDA, 16<<26 | 4<<21 | 0<<1 | 1<<0, "bfla", +0, OP_BI_BH, 19<<26 | 4<<21 | 16<<1 | 0<<0, "bflr", +0, OP_BI_BH, 19<<26 | 4<<21 | 16<<1 | 1<<0, "bflrl", +0, OP_BH, 19<<26 | 20<<21 | 16<<1 | 0<<0, "blr", +0, OP_BH, 19<<26 | 20<<21 | 16<<1 | 1<<0, "blrl", +0, OP_BI_BDL, 16<<26 | 12<<21 | 0<<1 | 0<<0, "bt", +0, OP_BI_BDA, 16<<26 | 12<<21 | 1<<1 | 0<<0, "bta", +0, OP_BI_BH, 19<<26 | 12<<21 | 528<<1 | 0<<0, "btctr", +0, OP_BI_BH, 19<<26 | 12<<21 | 528<<1 | 1<<0, "btctrl", +0, OP_BI_BDL, 16<<26 | 12<<21 | 0<<1 | 1<<0, "btl", +0, OP_BI_BDA, 16<<26 | 12<<21 | 0<<1 | 1<<0, "btla", +0, OP_BI_BH, 19<<26 | 12<<21 | 16<<1 | 0<<0, "btlr", +0, OP_BI_BH, 19<<26 | 12<<21 | 16<<1 | 1<<0, "btlrl", + +/* extended m with condition in BI */ +0, OP_BICR_BDL, 16<<26 | 12<<21 | 2<<16 | 0<<1 | 0<<0, "beq", +0, OP_BICR_BDA, 16<<26 | 12<<21 | 2<<16 | 1<<1 | 0<<0, "beqa", +0, OP_BICR_BH, 19<<26 | 12<<21 | 2<<16 | 528<<1 | 0<<0, "beqctr", +0, OP_BICR_BH, 19<<26 | 12<<21 | 2<<16 | 528<<1 | 1<<0, "beqctrl", +0, OP_BICR_BDL, 16<<26 | 12<<21 | 2<<16 | 0<<1 | 1<<0, "beql", +0, OP_BICR_BDA, 16<<26 | 12<<21 | 2<<16 | 1<<1 | 1<<0, "beqla", +0, OP_BICR_BH, 19<<26 | 12<<21 | 2<<16 | 16<<1 | 0<<0, "beqlr", +0, OP_BICR_BH, 19<<26 | 12<<21 | 2<<16 | 16<<1 | 1<<0, "beqlrl", +0, OP_BICR_BDL, 16<<26 | 4<<21 | 0<<16 | 0<<1 | 0<<0, "bge", +0, OP_BICR_BDA, 16<<26 | 4<<21 | 0<<16 | 1<<1 | 0<<0, "bgea", +0, OP_BICR_BH, 19<<26 | 4<<21 | 0<<16 | 528<<1 | 0<<0, "bgectr", +0, OP_BICR_BH, 19<<26 | 4<<21 | 0<<16 | 528<<1 | 1<<0, "bgectrl", +0, OP_BICR_BDL, 16<<26 | 4<<21 | 0<<16 | 0<<1 | 1<<0, "bgel", +0, OP_BICR_BDA, 16<<26 | 4<<21 | 0<<16 | 1<<1 | 1<<0, "bgela", +0, OP_BICR_BH, 19<<26 | 4<<21 | 0<<16 | 16<<1 | 0<<0, "bgelr", +0, OP_BICR_BH, 19<<26 | 4<<21 | 0<<16 | 16<<1 | 1<<0, "bgelrl", +0, OP_BICR_BDL, 16<<26 | 12<<21 | 1<<16 | 0<<1 | 0<<0, "bgt", +0, OP_BICR_BDA, 16<<26 | 12<<21 | 1<<16 | 1<<1 | 0<<0, "bgta", +0, OP_BICR_BH, 19<<26 | 12<<21 | 1<<16 | 528<<1 | 0<<0, "bgtctr", +0, OP_BICR_BH, 19<<26 | 12<<21 | 1<<16 | 528<<1 | 1<<0, "bgtctrl", +0, OP_BICR_BDL, 16<<26 | 12<<21 | 1<<16 | 0<<1 | 1<<0, "bgtl", +0, OP_BICR_BDA, 16<<26 | 12<<21 | 1<<16 | 1<<1 | 1<<0, "bgtla", +0, OP_BICR_BH, 19<<26 | 12<<21 | 1<<16 | 16<<1 | 0<<0, "bgtlr", +0, OP_BICR_BH, 19<<26 | 12<<21 | 1<<16 | 16<<1 | 1<<0, "bgtlrl", +0, OP_BICR_BDL, 16<<26 | 4<<21 | 1<<16 | 0<<1 | 0<<0, "ble", +0, OP_BICR_BDA, 16<<26 | 4<<21 | 1<<16 | 1<<1 | 0<<0, "blea", +0, OP_BICR_BH, 19<<26 | 4<<21 | 1<<16 | 528<<1 | 0<<0, "blectr", +0, OP_BICR_BH, 19<<26 | 4<<21 | 1<<16 | 528<<1 | 1<<0, "blectrl", +0, OP_BICR_BDL, 16<<26 | 4<<21 | 1<<16 | 0<<1 | 1<<0, "blel", +0, OP_BICR_BDA, 16<<26 | 4<<21 | 1<<16 | 1<<1 | 1<<0, "blela", +0, OP_BICR_BH, 19<<26 | 4<<21 | 1<<16 | 16<<1 | 0<<0, "blelr", +0, OP_BICR_BH, 19<<26 | 4<<21 | 1<<16 | 16<<1 | 1<<0, "blelrl", +0, OP_BICR_BDL, 16<<26 | 12<<21 | 0<<16 | 0<<1 | 0<<0, "blt", +0, OP_BICR_BDA, 16<<26 | 12<<21 | 0<<16 | 1<<1 | 0<<0, "blta", +0, OP_BICR_BH, 19<<26 | 12<<21 | 0<<16 | 528<<1 | 0<<0, "bltctr", +0, OP_BICR_BH, 19<<26 | 12<<21 | 0<<16 | 528<<1 | 1<<0, "bltctrl", +0, OP_BICR_BDL, 16<<26 | 12<<21 | 0<<16 | 0<<1 | 1<<0, "bltl", +0, OP_BICR_BDA, 16<<26 | 12<<21 | 0<<16 | 1<<1 | 1<<0, "bltla", +0, OP_BICR_BH, 19<<26 | 12<<21 | 0<<16 | 16<<1 | 0<<0, "bltlr", +0, OP_BICR_BH, 19<<26 | 12<<21 | 0<<16 | 16<<1 | 1<<0, "bltlrl", +0, OP_BICR_BDL, 16<<26 | 4<<21 | 2<<16 | 0<<1 | 0<<0, "bne", +0, OP_BICR_BDA, 16<<26 | 4<<21 | 2<<16 | 1<<1 | 0<<0, "bnea", +0, OP_BICR_BH, 19<<26 | 4<<21 | 2<<16 | 528<<1 | 0<<0, "bnectr", +0, OP_BICR_BH, 19<<26 | 4<<21 | 2<<16 | 528<<1 | 1<<0, "bnectrl", +0, OP_BICR_BDL, 16<<26 | 4<<21 | 2<<16 | 0<<1 | 1<<0, "bnel", +0, OP_BICR_BDA, 16<<26 | 4<<21 | 2<<16 | 1<<1 | 1<<0, "bnela", +0, OP_BICR_BH, 19<<26 | 4<<21 | 2<<16 | 16<<1 | 0<<0, "bnelr", +0, OP_BICR_BH, 19<<26 | 4<<21 | 2<<16 | 16<<1 | 1<<0, "bnelrl", +0, OP_BICR_BDL, 16<<26 | 4<<21 | 1<<16 | 0<<1 | 0<<0, "bng", +0, OP_BICR_BDA, 16<<26 | 4<<21 | 1<<16 | 1<<1 | 0<<0, "bnga", +0, OP_BICR_BH, 19<<26 | 4<<21 | 1<<16 | 528<<1 | 0<<0, "bngctr", +0, OP_BICR_BH, 19<<26 | 4<<21 | 1<<16 | 528<<1 | 1<<0, "bngctrl", +0, OP_BICR_BDL, 16<<26 | 4<<21 | 1<<16 | 0<<1 | 1<<0, "bngl", +0, OP_BICR_BDA, 16<<26 | 4<<21 | 1<<16 | 1<<1 | 1<<0, "bngla", +0, OP_BICR_BH, 19<<26 | 4<<21 | 1<<16 | 16<<1 | 0<<0, "bnglr", +0, OP_BICR_BH, 19<<26 | 4<<21 | 1<<16 | 16<<1 | 1<<0, "bnglrl", +0, OP_BICR_BDL, 16<<26 | 4<<21 | 0<<16 | 0<<1 | 0<<0, "bnl", +0, OP_BICR_BDA, 16<<26 | 4<<21 | 0<<16 | 1<<1 | 0<<0, "bnla", +0, OP_BICR_BH, 19<<26 | 4<<21 | 0<<16 | 528<<1 | 0<<0, "bnlctr", +0, OP_BICR_BH, 19<<26 | 4<<21 | 0<<16 | 528<<1 | 1<<0, "bnlctrl", +0, OP_BICR_BDL, 16<<26 | 4<<21 | 0<<16 | 0<<1 | 1<<0, "bnll", +0, OP_BICR_BDA, 16<<26 | 4<<21 | 0<<16 | 1<<1 | 1<<0, "bnlla", +0, OP_BICR_BH, 19<<26 | 4<<21 | 0<<16 | 16<<1 | 0<<0, "bnllr", +0, OP_BICR_BH, 19<<26 | 4<<21 | 0<<16 | 16<<1 | 1<<0, "bnllrl", +0, OP_BICR_BDL, 16<<26 | 4<<21 | 3<<16 | 0<<1 | 0<<0, "bns", +0, OP_BICR_BDA, 16<<26 | 4<<21 | 3<<16 | 1<<1 | 0<<0, "bnsa", +0, OP_BICR_BH, 19<<26 | 4<<21 | 3<<16 | 528<<1 | 0<<0, "bnsctr", +0, OP_BICR_BH, 19<<26 | 4<<21 | 3<<16 | 528<<1 | 1<<0, "bnsctrl", +0, OP_BICR_BDL, 16<<26 | 4<<21 | 3<<16 | 0<<1 | 1<<0, "bnsl", +0, OP_BICR_BDA, 16<<26 | 4<<21 | 3<<16 | 1<<1 | 1<<0, "bnsla", +0, OP_BICR_BH, 19<<26 | 4<<21 | 3<<16 | 16<<1 | 0<<0, "bnslr", +0, OP_BICR_BH, 19<<26 | 4<<21 | 3<<16 | 16<<1 | 1<<0, "bnslrl", +0, OP_BICR_BDL, 16<<26 | 4<<21 | 3<<16 | 0<<1 | 0<<0, "bnu", +0, OP_BICR_BDA, 16<<26 | 4<<21 | 3<<16 | 1<<1 | 0<<0, "bnua", +0, OP_BICR_BH, 19<<26 | 4<<21 | 3<<16 | 528<<1 | 0<<0, "bnuctr", +0, OP_BICR_BH, 19<<26 | 4<<21 | 3<<16 | 528<<1 | 1<<0, "bnuctrl", +0, OP_BICR_BDL, 16<<26 | 4<<21 | 3<<16 | 0<<1 | 1<<0, "bnul", +0, OP_BICR_BDA, 16<<26 | 4<<21 | 3<<16 | 1<<1 | 1<<0, "bnula", +0, OP_BICR_BH, 19<<26 | 4<<21 | 3<<16 | 16<<1 | 0<<0, "bnulr", +0, OP_BICR_BH, 19<<26 | 4<<21 | 3<<16 | 16<<1 | 1<<0, "bnulrl", +0, OP_BICR_BDL, 16<<26 | 12<<21 | 3<<16 | 0<<1 | 0<<0, "bso", +0, OP_BICR_BDA, 16<<26 | 12<<21 | 3<<16 | 1<<1 | 0<<0, "bsoa", +0, OP_BICR_BH, 19<<26 | 12<<21 | 3<<16 | 528<<1 | 0<<0, "bsoctr", +0, OP_BICR_BH, 19<<26 | 12<<21 | 3<<16 | 528<<1 | 1<<0, "bsoctrl", +0, OP_BICR_BDL, 16<<26 | 12<<21 | 3<<16 | 0<<1 | 1<<0, "bsol", +0, OP_BICR_BDA, 16<<26 | 12<<21 | 3<<16 | 1<<1 | 1<<0, "bsola", +0, OP_BICR_BH, 19<<26 | 12<<21 | 3<<16 | 16<<1 | 0<<0, "bsolr", +0, OP_BICR_BH, 19<<26 | 12<<21 | 3<<16 | 16<<1 | 1<<0, "bsolrl", +0, OP_BICR_BDL, 16<<26 | 12<<21 | 3<<16 | 0<<1 | 0<<0, "bun", +0, OP_BICR_BDA, 16<<26 | 12<<21 | 3<<16 | 1<<1 | 0<<0, "buna", +0, OP_BICR_BH, 19<<26 | 12<<21 | 3<<16 | 528<<1 | 0<<0, "bunctr", +0, OP_BICR_BH, 19<<26 | 12<<21 | 3<<16 | 528<<1 | 1<<0, "bunctrl", +0, OP_BICR_BDL, 16<<26 | 12<<21 | 3<<16 | 0<<1 | 1<<0, "bunl", +0, OP_BICR_BDA, 16<<26 | 12<<21 | 3<<16 | 1<<1 | 1<<0, "bunla", +0, OP_BICR_BH, 19<<26 | 12<<21 | 3<<16 | 16<<1 | 0<<0, "bunlr", +0, OP_BICR_BH, 19<<26 | 12<<21 | 3<<16 | 16<<1 | 1<<0, "bunlrl", + +/* extended m for cr logic */ +0, OP_BT_BT_BT, 19<<26 | 289<<1, "crset", +0, OP_BT_BT_BT, 19<<26 | 193<<1, "crclr", +0, OP_BT_BA_BA, 19<<26 | 449<<1, "crmove", +0, OP_BT_BA_BA, 19<<26 | 33<<1, "crnot", + /* Fixed point instructions (page 29) */ 0, OP_RT_RA_D, 34<<26, "lbz", @@ -199,6 +358,10 @@ 0, OP_RT_RA_RB_C, 31<<26 | 1<<10 | 40<<1, "subfo", 0, OP_RT_RA_SI_addic, 12<<26, "addic", /* special case C */ 0, OP_RT_RA_SI, 8<<26, "subfic", +0, OP_RT_RA_RB_C, 31<<26 | 0<<10 | 10<<1, "addc", +0, OP_RT_RA_RB_C, 31<<26 | 1<<10 | 10<<1, "addco", +0, OP_RT_RA_RB_C, 31<<26 | 0<<10 | 8<<1, "subfc", +0, OP_RT_RA_RB_C, 31<<26 | 1<<10 | 8<<1, "subfco", 0, OP_RT_RA_RB_C, 31<<26 | 0<<10 | 138<<1, "adde", 0, OP_RT_RA_RB_C, 31<<26 | 1<<10 | 138<<1, "addeo", 0, OP_RT_RA_RB_C, 31<<26 | 0<<10 | 136<<1, "subfe", @@ -214,6 +377,20 @@ 0, OP_RT_RA_C, 31<<26 | 0<<10 | 104<<1, "neg", 0, OP_RT_RA_C, 31<<26 | 1<<10 | 104<<1, "nego", +/* extended m for addition */ +0, OP_RT_RA_D, 14<<26, "la", +0, OP_RT_SI, 14<<26 | 0<<16, "li", +0, OP_RT_SI, 15<<26 | 0<<16, "lis", + +/* extended m for subtraction */ +0, OP_RT_RB_RA_C, 31<<26 | 0<<10 | 40<<1, "sub", +0, OP_RT_RB_RA_C, 31<<26 | 1<<10 | 40<<1, "subo", +0, OP_RT_RB_RA_C, 31<<26 | 0<<10 | 8<<1, "subc", +0, OP_RT_RB_RA_C, 31<<26 | 0<<10 | 8<<1, "subco", +0, OP_RT_RA_SI_subi, 14<<26, "subi", +0, OP_RT_RA_SI_subi, 15<<26, "subis", +0, OP_RT_RA_SI_subic, 12<<26, "subic", + /* page 54 */ 0, OP_RT_RA_SI, 7<<26, "mulli", 0, OP_RT_RA_RB_C, 31<<26 | 0<<10 | 233<<1, "mulld", @@ -241,12 +418,85 @@ 0, OP_BF_L_RA_UI, 10<<26, "cmpli", 0, OP_BF_L_RA_RB, 31<<26 | 32<<1, "cmpl", +/* extended m for comparison */ +0, OP_BF_RA_SI, 11<<26 | 1<<21, "cmpdi", +0, OP_BF_RA_RB, 31<<26 | 1<<21 | 0<<1, "cmpd", +0, OP_BF_RA_UI, 10<<26 | 1<<21, "cmpldi", +0, OP_BF_RA_RB, 31<<26 | 1<<21 | 32<<1, "cmpld", +0, OP_BF_RA_SI, 11<<26 | 0<<21, "cmpwi", +0, OP_BF_RA_RB, 31<<26 | 0<<21 | 0<<1, "cmpw", +0, OP_BF_RA_UI, 10<<26 | 0<<21, "cmplwi", +0, OP_BF_RA_RB, 31<<26 | 0<<21 | 32<<1, "cmplw", + /* page 60 */ 0, OP_TO_RA_SI, 2<<26, "tdi", 0, OP_TO_RA_SI, 3<<26, "twi", 0, OP_TO_RA_RB, 31<<26 | 68<<1, "td", 0, OP_TO_RA_RB, 31<<26 | 4<<1, "tw", +/* extended m for traps */ +0, OP_TOX_RA_RB, 31<<26 | 4<<21 | 68<<1, "tdeq", +0, OP_TOX_RA_SI, 2<<26 | 4<<21, "tdeqi", +0, OP_TOX_RA_RB, 31<<26 | 12<<21 | 68<<1, "tdge", +0, OP_TOX_RA_SI, 2<<26 | 12<<21, "tdgei", +0, OP_TOX_RA_RB, 31<<26 | 8<<21 | 68<<1, "tdgt", +0, OP_TOX_RA_SI, 2<<26 | 8<<21, "tdgti", +0, OP_TOX_RA_RB, 31<<26 | 20<<21 | 68<<1, "tdle", +0, OP_TOX_RA_SI, 2<<26 | 20<<21, "tdlei", +0, OP_TOX_RA_RB, 31<<26 | 5<<21 | 68<<1, "tdlge", +0, OP_TOX_RA_SI, 2<<26 | 5<<21, "tdlgei", +0, OP_TOX_RA_RB, 31<<26 | 1<<21 | 68<<1, "tdlgt", +0, OP_TOX_RA_SI, 2<<26 | 1<<21, "tdlgti", +0, OP_TOX_RA_RB, 31<<26 | 6<<21 | 68<<1, "tdlle", +0, OP_TOX_RA_SI, 2<<26 | 6<<21, "tdllei", +0, OP_TOX_RA_RB, 31<<26 | 2<<21 | 68<<1, "tdllt", +0, OP_TOX_RA_SI, 2<<26 | 2<<21, "tdllti", +0, OP_TOX_RA_RB, 31<<26 | 6<<21 | 68<<1, "tdlng", +0, OP_TOX_RA_SI, 2<<26 | 6<<21, "tdlngi", +0, OP_TOX_RA_RB, 31<<26 | 5<<21 | 68<<1, "tdlnl", +0, OP_TOX_RA_SI, 2<<26 | 5<<21, "tdlnli", +0, OP_TOX_RA_RB, 31<<26 | 16<<21 | 68<<1, "tdlt", +0, OP_TOX_RA_SI, 2<<26 | 16<<21, "tdlti", +0, OP_TOX_RA_RB, 31<<26 | 24<<21 | 68<<1, "tdne", +0, OP_TOX_RA_SI, 2<<26 | 24<<21, "tdnei", +0, OP_TOX_RA_RB, 31<<26 | 20<<21 | 68<<1, "tdng", +0, OP_TOX_RA_SI, 2<<26 | 20<<21, "tdngi", +0, OP_TOX_RA_RB, 31<<26 | 12<<21 | 68<<1, "tdnl", +0, OP_TOX_RA_SI, 2<<26 | 12<<21, "tdnli", +0, OP_TOX_RA_RB, 31<<26 | 31<<21 | 68<<1, "tdu", +0, OP_TOX_RA_SI, 2<<26 | 31<<21, "tdui", +0, OP, 31<<26 | 31<<21 | 4<<1, "trap", +0, OP_TOX_RA_RB, 31<<26 | 4<<21 | 4<<1, "tweq", +0, OP_TOX_RA_SI, 3<<26 | 4<<21, "tweqi", +0, OP_TOX_RA_RB, 31<<26 | 12<<21 | 4<<1, "twge", +0, OP_TOX_RA_SI, 3<<26 | 12<<21, "twgei", +0, OP_TOX_RA_RB, 31<<26 | 8<<21 | 4<<1, "twgt", +0, OP_TOX_RA_SI, 3<<26 | 8<<21, "twgti", +0, OP_TOX_RA_RB, 31<<26 | 20<<21 | 4<<1, "twle", +0, OP_TOX_RA_SI, 3<<26 | 20<<21, "twlei", +0, OP_TOX_RA_RB, 31<<26 | 5<<21 | 4<<1, "twlge", +0, OP_TOX_RA_SI, 3<<26 | 5<<21, "twlgei", +0, OP_TOX_RA_RB, 31<<26 | 1<<21 | 4<<1, "twlgt", +0, OP_TOX_RA_SI, 3<<26 | 1<<21, "twlgti", +0, OP_TOX_RA_RB, 31<<26 | 6<<21 | 4<<1, "twlle", +0, OP_TOX_RA_SI, 3<<26 | 6<<21, "twllei", +0, OP_TOX_RA_RB, 31<<26 | 2<<21 | 4<<1, "twllt", +0, OP_TOX_RA_SI, 3<<26 | 2<<21, "twllti", +0, OP_TOX_RA_RB, 31<<26 | 6<<21 | 4<<1, "twlng", +0, OP_TOX_RA_SI, 3<<26 | 6<<21, "twlngi", +0, OP_TOX_RA_RB, 31<<26 | 5<<21 | 4<<1, "twlnl", +0, OP_TOX_RA_SI, 3<<26 | 5<<21, "twlnli", +0, OP_TOX_RA_RB, 31<<26 | 16<<21 | 4<<1, "twlt", +0, OP_TOX_RA_SI, 3<<26 | 16<<21, "twlti", +0, OP_TOX_RA_RB, 31<<26 | 24<<21 | 4<<1, "twne", +0, OP_TOX_RA_SI, 3<<26 | 24<<21, "twnei", +0, OP_TOX_RA_RB, 31<<26 | 20<<21 | 4<<1, "twng", +0, OP_TOX_RA_SI, 3<<26 | 20<<21, "twngi", +0, OP_TOX_RA_RB, 31<<26 | 12<<21 | 4<<1, "twnl", +0, OP_TOX_RA_SI, 3<<26 | 12<<21, "twnli", +0, OP_TOX_RA_RB, 31<<26 | 31<<21 | 4<<1, "twu", +0, OP_TOX_RA_SI, 3<<26 | 31<<21, "twui", + /* page 62 */ 0, OP_RS_RA_UI_CC, 28<<26, "andi", /* C compulsory */ 0, OP_RS_RA_UI_CC, 29<<26, "andis", /* C compulsory */ @@ -268,26 +518,59 @@ 0, OP_RS_RA_C, 31<<26 | 58<<1, "cntlzd", 0, OP_RS_RA_C, 31<<26 | 26<<1, "cntlzw", +/* extended m using logic */ +0, OP_RS_RA_RA_C, 31<<26 | 444<<1, "mr", +0, OP, 24<<26, "nop", +0, OP_RS_RA_RA_C, 31<<26 | 124<<1, "not", +0, OP, 26<<26, "xnop", + /* page 69 */ -0, OP_RS_RA_SH_MB6_SH_C, 30<<26 | 0<<2, "rldicl", -0, OP_RS_RA_SH_ME6_SH_C, 30<<26 | 1<<2, "rldicr", -0, OP_RS_RA_SH_MB6_SH_C, 30<<26 | 2<<2, "rldic", -0, OP_RS_RA_SH_MB5_ME5_C, 21<<26, "rlwinm", -0, OP_RS_RA_RB_MB6_C, 30<<26 | 8<<1, "rldcl", -0, OP_RS_RA_RB_ME6_C, 30<<26 | 9<<1, "rldcr", -0, OP_RS_RA_RB_MB5_ME5_C, 23<<26, "rlwnm", -0, OP_RS_RA_SH_MB6_SH_C, 30<<26 | 3<<2, "rldimi", -0, OP_RS_RA_SH_MB5_ME5_C, 20<<26, "rlwimi", +0, OP_RA_RS_SH6_MB6_C, 30<<26 | 0<<2, "rldicl", +0, OP_RA_RS_SH6_MB6_C, 30<<26 | 1<<2, "rldicr", +0, OP_RA_RS_SH6_MB6_C, 30<<26 | 2<<2, "rldic", +0, OP_RA_RS_SH5_MB5_ME5_C, 21<<26, "rlwinm", +0, OP_RA_RS_RB_MB6_C, 30<<26 | 8<<1, "rldcl", +0, OP_RA_RS_RB_MB6_C, 30<<26 | 9<<1, "rldcr", +0, OP_RA_RS_RB_MB5_ME5_C, 23<<26, "rlwnm", +0, OP_RA_RS_SH6_MB6_C, 30<<26 | 3<<2, "rldimi", +0, OP_RA_RS_SH5_MB5_ME5_C, 20<<26, "rlwimi", + +/* extended m for doubleword rotation */ +0, OP_clrlsldi, 30<<26 | 2<<2, "clrlsldi", +0, OP_clrldi, 30<<26 | 0<<2, "clrldi", +0, OP_clrrdi, 30<<26 | 1<<2, "clrrdi", +0, OP_extldi, 30<<26 | 0<<2, "extldi", +0, OP_extrdi, 30<<26 | 1<<2, "extrdi", +0, OP_insrdi, 30<<26 | 3<<2, "insrdi", +0, OP_RA_RS_RB_C, 30<<26 | MB6(0) | 8<<1, "rotld", +0, OP_RA_RS_SH6_C, 30<<26 | MB6(0) | 0<<2, "rotldi", +0, OP_rotrdi, 30<<26 | 0<<2, "rotrdi", +0, OP_sldi, 30<<26 | 1<<2, "sldi", +0, OP_srdi, 30<<26 | 0<<2, "srdi", + +/* extended m for word rotation */ +0, OP_clrlslwi, 21<<26, "clrlslwi", +0, OP_clrlwi, 21<<26, "clrlwi", +0, OP_clrrwi, 21<<26, "clrrwi", +0, OP_extlwi, 21<<26, "extlwi", +0, OP_extrwi, 21<<26, "extrwi", +0, OP_inslwi, 20<<26, "inslwi", +0, OP_insrwi, 20<<26, "insrwi", +0, OP_RA_RS_RB_C, 23<<26 | 0<<6 | 31<<1, "rotlw", +0, OP_RA_RS_SH5_C, 21<<26 | 0<<6 | 31<<1, "rotlwi", +0, OP_rotrwi, 21<<26, "rotrwi", +0, OP_slwi, 21<<26, "slwi", +0, OP_srwi, 21<<26, "srwi", /* page 74 */ -0, OP_RS_RA_RB_C, 31<<26 | 27<<1, "sld", -0, OP_RS_RA_RB_C, 31<<26 | 24<<1, "slw", -0, OP_RS_RA_RB_C, 31<<26 | 539<<1, "srd", -0, OP_RS_RA_RB_C, 31<<26 | 536<<1, "srw", -0, OP_RS_RA_SH6_C, 31<<26 | 413<<2, "sradi", -0, OP_RS_RA_SH5_C, 31<<26 | 824<<1, "srawi", -0, OP_RS_RA_RB_C, 31<<26 | 794<<1, "srad", -0, OP_RS_RA_RB_C, 31<<26 | 792<<1, "sraw", +0, OP_RA_RS_RB_C, 31<<26 | 27<<1, "sld", +0, OP_RA_RS_RB_C, 31<<26 | 24<<1, "slw", +0, OP_RA_RS_RB_C, 31<<26 | 539<<1, "srd", +0, OP_RA_RS_RB_C, 31<<26 | 536<<1, "srw", +0, OP_RA_RS_SH6_C, 31<<26 | 413<<2, "sradi", +0, OP_RA_RS_SH5_C, 31<<26 | 824<<1, "srawi", +0, OP_RA_RS_RB_C, 31<<26 | 794<<1, "srad", +0, OP_RA_RS_RB_C, 31<<26 | 792<<1, "sraw", /* page 78 */ 0, OP_RS_SPR, 31<<26 | 467<<1, "mtspr", @@ -295,6 +578,14 @@ 0, OP_RS_FXM, 31<<26 | 0<<21 | 144<<1, "mtcrf", 0, OP_RT, 31<<26 | 0<<21 | 19<<1, "mfcr", +/* extended m for special purpose registers */ +0, OP_RT, 31<<26 | 9<<16 | 0<<11 | 339<<1, "mfctr", +0, OP_RT, 31<<26 | 8<<16 | 0<<11 | 339<<1, "mflr", +0, OP_RT, 31<<26 | 1<<16 | 0<<11 | 339<<1, "mfxer", +0, OP_RT, 31<<26 | 9<<16 | 0<<11 | 467<<1, "mtctr", +0, OP_RT, 31<<26 | 8<<16 | 0<<11 | 467<<1, "mtlr", +0, OP_RT, 31<<26 | 1<<16 | 0<<11 | 467<<1, "mtxer", + /* Floating point instructions (page 83) */ 0, OP_FRT_RA_D, 48<<26, "lfs", diff --git a/mach/powerpc/as/mach4.c b/mach/powerpc/as/mach4.c index 1ad180de4..99f7f4537 100644 --- a/mach/powerpc/as/mach4.c +++ b/mach/powerpc/as/mach4.c @@ -4,16 +4,33 @@ */ operation - : OP_BF_BFA CR ',' CR { emit4($1 | ($2<<23) | ($4<<18)); } + : OP { emit4($1); } + | OP_BDA bda { emit4($1 | $2); } + | OP_BDL bdl { emit4($1 | $2); } + | OP_BF_BFA CR ',' CR { emit4($1 | ($2<<23) | ($4<<18)); } | OP_BF_FRA_FRB CR ',' FPR ',' FPR { emit4($1 | ($2<<23) | ($4<<16) | ($6<<11)); } | OP_BF_L_RA_RB CR ',' u1 ',' GPR ',' GPR { emit4($1 | ($2<<23) | ($4<<21) | ($6<<16) | ($8<<11)); } | OP_BF_L_RA_SI CR ',' u1 ',' GPR ',' e16 { emit4($1 | ($2<<23) | ($4<<21) | ($6<<16) | $8); } | OP_BF_L_RA_UI CR ',' u1 ',' GPR ',' e16 { emit4($1 | ($2<<23) | ($4<<21) | ($6<<16) | $8); } + | OP_BF_RA_RB cr_opt GPR ',' GPR { emit4($1 | ($2<<23) | ($3<<16) | ($5<<11)); } + | OP_BF_RA_SI cr_opt GPR ',' e16 { emit4($1 | ($2<<23) | ($3<<16) | $5); } + | OP_BF_RA_UI cr_opt GPR ',' e16 { emit4($1 | ($2<<23) | ($3<<16) | $5); } | OP_BF_U_C c CR ',' u4 { emit4($1 | $2 | ($3<<23) | ($5<<12)); } + | OP_BH { emit4($1); } + | OP_BH u2 { emit4($1 | ($2<<11)); } + | OP_BI_BDA u5 ',' bda { emit4($1 | ($2<<16) | $4); } + | OP_BI_BDL u5 ',' bdl { emit4($1 | ($2<<16) | $4); } + | OP_BI_BH u5 opt_bh { emit4($1 | ($2<<16) | $3); } + | OP_BICR_BDA cr_opt bda { emit4($1 | ($2<<18) | $3); } + | OP_BICR_BDL cr_opt bdl { emit4($1 | ($2<<18) | $3); } + | OP_BICR_BH { emit4($1); } + | OP_BICR_BH CR opt_bh { emit4($1 | ($2<<18) | $3); } | OP_BO_BI_BDA u5 ',' u5 ',' bda { emit4($1 | ($2<<21) | ($4<<16) | $6); } | OP_BO_BI_BDL u5 ',' u5 ',' bdl { emit4($1 | ($2<<21) | ($4<<16) | $6); } - | OP_BO_BI_BH u5 ',' u5 ',' u2 { emit4($1 | ($2<<21) | ($4<<16) | ($6<<11)); } + | OP_BO_BI_BH u5 ',' u5 opt_bh { emit4($1 | ($2<<21) | ($4<<16) | $5); } + | OP_BT_BA_BA u5 ',' u5 { emit4($1 | ($2<<21) | ($4<<16) | ($4<<11)); } | OP_BT_BA_BB u5 ',' u5 ',' u5 { emit4($1 | ($2<<21) | ($4<<16) | ($6<<11)); } + | OP_BT_BT_BT u5 { emit4($1 | ($2<<21) | ($2<<16) | ($2<<11)); } | OP_BT_C c u5 { emit4($1 | $2 | ($3<<21)); } | OP_FLM_FRB_C c u8 ',' FPR { emit4($1 | $2 | ($3<<17) | ($5<<11)); } | OP_FRS_RA_D FPR ',' e16 '(' GPR ')' { emit4($1 | ($2<<21) | ($6<<16) | $4); } @@ -25,15 +42,35 @@ operation | OP_FRT_RA_D FPR ',' e16 '(' GPR ')' { emit4($1 | ($2<<21) | ($6<<16) | $4); } | OP_FRT_RA_RB FPR ',' GPR ',' GPR { emit4($1 | ($2<<21) | ($4<<16) | ($6<<11)); } | OP_FRT_C c FPR { emit4($1 | $2 | ($3<<21)); } + | OP_RA_RS_RB_C c GPR ',' GPR ',' GPR + { emit4($1 | $2 | ($5<<21) | ($3<<16) | ($7<<11)); } + | OP_RA_RS_RB_MB5_ME5_C c GPR ',' GPR ',' GPR ',' u5 ',' u5 + { emit4($1 | $2 | ($5<<21) | ($3<<16) | ($7<<11) | + ($9<<6) | ($11<<1)); } + | OP_RA_RS_RB_MB6_C c GPR ',' GPR ',' GPR ',' u6 + { emit4($1 | $2 | ($5<<21) | ($3<<16) | ($7<<11) | MB6($9)); } + | OP_RA_RS_SH5_C c GPR ',' GPR ',' u5 + { emit4($1 | $2 | ($5<<21) | ($3<<16) | ($7<<11)); } + | OP_RA_RS_SH5_MB5_ME5_C c GPR ',' GPR ',' u5 ',' u5 ',' u5 + { emit4($1 | $2 | ($5<<21) | ($3<<16) | + ($7<<11) | ($9<<6) | ($11<<1)); } + | OP_RA_RS_SH6_C c GPR ',' GPR ',' u6 + { emit4($1 | $2 | ($5<<21) | ($3<<16) | SH6($7)); } + | OP_RA_RS_SH6_MB6_C c GPR ',' GPR ',' u6 ',' u6 + { emit4($1 | $2 | ($5<<21) | ($3<<16) | SH6($7) | MB6($9)); } | OP_RT GPR { emit4($1 | ($2<<21)); } | OP_RT_RA_C c GPR ',' GPR { emit4($1 | $2 | ($3<<21) | ($5<<16)); } | OP_RT_RA_D GPR ',' e16 '(' GPR ')' { emit4($1 | ($2<<21) | ($6<<16) | $4); } | OP_RT_RA_DS GPR ',' ds '(' GPR ')' { emit4($1 | ($2<<21) | ($6<<16) | $4); } | OP_RT_RA_NB GPR ',' GPR ',' nb { emit4($1 | ($2<<21) | ($4<<16) | ($6<<11)); } | OP_RT_RA_RB GPR ',' GPR ',' GPR { emit4($1 | ($2<<21) | ($4<<16) | ($6<<11)); } - | OP_RT_RA_RB_C c GPR ',' GPR ',' GPR { emit4($1 | $2 | ($3<<21) | ($5<<16) | ($7<<11)); } + | OP_RT_RA_RB_C c GPR ',' GPR ',' GPR { emit4($1 | $2 | ($3<<21) | ($5<<16) | ($7<<11)); } | OP_RT_RA_SI GPR ',' GPR ',' e16 { emit4($1 | ($2<<21) | ($4<<16) | $6); } | OP_RT_RA_SI_addic c GPR ',' GPR ',' e16 { emit4($1 | ($2<<26) | ($3<<21) | ($5<<16) | $7); } + | OP_RT_RA_SI_subi GPR ',' GPR ',' negate16 { emit4($1 | ($2<<21) | ($4<<16) | $6); } + | OP_RT_RA_SI_subic c GPR ',' GPR ',' negate16 { emit4($1 | ($2<<26) | ($3<<21) | ($5<<16) | $7); } + | OP_RT_RB_RA_C c GPR ',' GPR ',' GPR { emit4($1 | $2 | ($3<<21) | ($7<<16) | ($5<<11)); } + | OP_RT_SI GPR ',' e16 { emit4($1 | ($2<<21) | $4); } | OP_RT_SPR GPR ',' spr_num { emit4($1 | ($2<<21) | ($4<<11)); } | OP_RS_FXM u7 ',' GPR { emit4($1 | ($4<<21) | ($2<<12)); } | OP_RS_RA_C c GPR ',' GPR { emit4($1 | $2 | ($5<<21) | ($3<<16)); } @@ -45,21 +82,127 @@ operation | OP_RS_RA_RB GPR ',' GPR ',' GPR { emit4($1 | ($2<<21) | ($4<<16) | ($6<<11)); } | OP_RS_RA_RB_C c GPR ',' GPR ',' GPR { emit4($1 | $2 | ($5<<21) | ($3<<16) | ($7<<11)); } | OP_RS_RA_RA_C c GPR ',' GPR { emit4($1 | $2 | ($5<<21) | ($3<<16) | ($5<<11)); } - | OP_RS_RA_RB_MB5_ME5_C c GPR ',' GPR ',' GPR ',' u5 ',' u5 { emit4($1 | $2 | ($5<<21) | ($3<<16) | ($7<<11) | ($9<<6) | ($11<<1)); } - | OP_RS_RA_RB_MB6_C c GPR ',' GPR ',' GPR ',' u6 { emit4($1 | $2 | ($5<<21) | ($3<<16) | ($7<<11) | (($9&0x1F)<<6) | (($9&0x20)>>0)); } - | OP_RS_RA_RB_ME6_C c GPR ',' GPR ',' GPR ',' u6 { emit4($1 | $2 | ($5<<21) | ($3<<16) | ($7<<11) | (($9&0x1F)<<6) | (($9&0x20)>>0)); } - | OP_RS_RA_SH_MB5_ME5_C c GPR ',' GPR ',' u5 ',' u5 ',' u5 { emit4($1 | $2 | ($5<<21) | ($3<<16) | ($7<<11) | ($9<<6) | ($11<<1)); } - | OP_RS_RA_SH_MB6_SH_C c GPR ',' GPR ',' u6 ',' u6 { emit4($1 | $2 | ($5<<21) | ($3<<16) | (($7&0x1F)<<11) | ($9<<6) | (($7&0x20)>>4)); } - | OP_RS_RA_SH_ME6_SH_C c GPR ',' GPR ',' u6 ',' u6 { emit4($1 | $2 | ($5<<21) | ($3<<16) | (($7&0x1F)<<11) | ($9<<6) | (($7&0x20)>>4)); } - | OP_RS_RA_SH5_C c GPR ',' GPR ',' u5 { emit4($1 | $2 | ($5<<21) | ($3<<16) | ($7<<11)); } - | OP_RS_RA_SH6_C c GPR ',' GPR ',' u6 { emit4($1 | $2 | ($5<<21) | ($3<<16) | (($7&0x1F)<<11) | (($7&0x20)>>4)); } | OP_RS_SPR spr_num ',' GPR { emit4($1 | ($4<<21) | ($2<<11)); } | OP_TO_RA_RB u5 ',' GPR ',' GPR { emit4($1 | ($2<<21) | ($4<<16) | ($6<<11)); } | OP_TO_RA_SI u5 ',' GPR ',' e16 { emit4($1 | ($2<<21) | ($4<<16) | $6); } + | OP_TOX_RA_RB GPR ',' GPR { emit4($1 | ($2<<16) | ($4<<11)); } + | OP_TOX_RA_SI GPR ',' e16 { emit4($1 | ($2<<16) | $4); } + | OP_LEV { emit4($1); } | OP_LEV u7 { emit4($1 | ($2<<5)); } | OP_LIA lia { emit4($1 | $2); } | OP_LIL lil { emit4($1 | $2); } | OP_LI32 li32 /* emitted in subrule */ + | OP_clrlsldi c GPR ',' GPR ',' u6 ',' u6 + { + quad mb = ($7 - $9) & 0x3f; + fit($9 <= $7); + emit4($1 | $2 | ($5<<21) | ($3<<16) | SH6($9) | MB6(mb)); + } + | OP_clrldi c GPR ',' GPR ',' u6 + { + emit4($1 | $2 | ($5<<21) | ($3<<16) | SH6(0) | MB6($7)); + } + | OP_clrrdi c GPR ',' GPR ',' u6 + { + quad me = 63 - $7; + emit4($1 | $2 | ($5<<21) | ($3<<16) | SH6(0) | MB6(me)); + } + | OP_extldi c GPR ',' GPR ',' u6 ',' u6 + { + quad me = ($7 - 1) & 0x3f; + fit($7 > 0); + emit4($1 | $2 | ($5<<21) | ($3<<16) | SH6($9) | MB6(me)); + } + | OP_extrdi c GPR ',' GPR ',' u6 ',' u6 + { + quad sh = ($9 + $7) & 0x3f; + quad mb = (64 - $7) & 0x3f; + fit($7 > 0); + emit4($1 | $2 | ($5<<21) | ($3<<16) | SH6(sh) | MB6(mb)); + } + | OP_rotrdi c GPR ',' GPR ',' u6 + { + quad sh = (64 - $7) & 0x3f; + emit4($1 | $2 | ($5<<21) | ($3<<16) | SH6(sh) | MB6(0)); + } + | OP_sldi c GPR ',' GPR ',' u6 + { + quad me = 63 - $7; + emit4($1 | $2 | ($5<<21) | ($3<<16) | SH6($7) | MB6(me)); + } + | OP_srdi c GPR ',' GPR ',' u6 + { + quad sh = (64 - $7) & 0x3f; + emit4($1 | $2 | ($5<<21) | ($3<<16) | SH6(sh) | MB6($7)); + } + | OP_clrlslwi c GPR ',' GPR ',' u5 ',' u5 + { + quad mb = ($7 - $9) & 0x1f; + quad me = 31 - $9; + fit($9 <= $7); + emit4($1 | $2 | ($5<<21) | ($3<<16) | + ($9<<11) | (mb<<6) | (me<<1)); + } + | OP_clrlwi c GPR ',' GPR ',' u5 + { + emit4($1 | $2 | ($5<<21) | ($3<<16) | + (0<<11) | ($7<<6) | (31<<1)); + } + | OP_clrrwi c GPR ',' GPR ',' u5 + { + quad me = 31 - $7; + emit4($1 | $2 | ($5<<21) | ($3<<16) | + (0<<11) | (0<<6) | (me<<1)); + } + | OP_extlwi c GPR ',' GPR ',' u5 ',' u5 + { + quad me = ($7 - 1) & 0x1f; + fit($7 > 0); + emit4($1 | $2 | ($5<<21) | ($3<<16) | + ($9<<11) | (0<<6) | (me<<1)); + } + | OP_extrwi c GPR ',' GPR ',' u5 ',' u5 + { + quad sh = ($9 + $7) & 0x1f; + quad mb = (32 - $7) & 0x1f; + fit($7 > 0); + emit4($1 | $2 | ($5<<21) | ($3<<16) | + (sh<<11) | (mb<<6) | (31<<1)); + } + | OP_inslwi c GPR ',' GPR ',' u5 ',' u5 + { + quad sh = (32 - $9) & 0x1f; + quad me = ($9 + $7 - 1) & 0x1f; + fit($7 > 0); + emit4($1 | $2 | ($5<<21) | ($3<<16) | + (sh<<11) | ($9<<6) | (me<<1)); + } + | OP_insrwi c GPR ',' GPR ',' u5 ',' u5 + { + quad sh = (32 - $9 - $7) & 0x1f; + quad me = ($9 + $7 - 1) & 0x1f; + fit($7 > 0); + emit4($1 | $2 | ($5<<21) | ($3<<16) | + (sh<<11) | ($9<<6) | (me<<1)); + } + | OP_rotrwi c GPR ',' GPR ',' u5 + { + quad sh = (32 - $7) & 0x1f; + emit4($1 | $2 | ($5<<21) | ($3<<16) | + (sh<<11) | (0<<6) | (31<<1)); + } + | OP_slwi c GPR ',' GPR ',' u5 + { + quad me = 31 - $7; + emit4($1 | $2 | ($5<<21) | ($3<<16) | + ($7<<11) | (0<<6) | (me<<1)); + } + | OP_srwi c GPR ',' GPR ',' u5 + { + quad sh = (32 - $7) & 0x1f; + emit4($1 | $2 | ($5<<21) | ($3<<16) | + (sh<<11) | ($7<<6) | (31<<1)); + } ; c @@ -80,6 +223,17 @@ e16 | OP_LO ASC_LPAR expr ASC_RPAR { $$ = emit_lo(&$3); } ; +negate16 + : absexp + { + /* To encode subi, we negate the immediate value, then + * it must fit as signed 16-bit. */ + $$ = -$1; + fit(fitx($$, 16)); + $$ = (uint16_t) $$; + } + ; + u8 : absexp { @@ -143,6 +297,19 @@ u2 } ; +/* Optional comma, branch hint. */ +opt_bh + : /* nothing */ { $$ = 0; } + | ',' u2 { $$ = ($2<<11); } + +/* + * Optional condition register, comma. This checks if the token is a + * CR register name. This wouldn't work if we allowed CR as a number. + */ +cr_opt + : /* nothing */ { $$ = 0; } + | CR ',' { $$ = $1; } + ds : e16 { @@ -251,14 +418,3 @@ spr_num $$ = ($1 >> 5) | (($1 & 0x1f) << 5); } ; - -powerpcfixup - : expr - { - quad type = $1.typ & S_TYP; - quad val = $1.val; - if (type == S_ABS) - serror(".powerpcfixup is useless on absolute values"); - newrelo($1.typ, RELOPPC | FIXUPFLAGS); - } - ; From a585ddf578479853c73b4948fbf143306ff4b142 Mon Sep 17 00:00:00 2001 From: George Koehler Date: Sun, 22 Jan 2017 00:52:32 -0500 Subject: [PATCH 149/173] Fix parameters of signal handlers for linuxppc. Linux passes the arguments in registers, but our compiler expects arguments on the stack. Signal handlers got garbage instead of the signal number. Some handlers, like the one in lang/m2/libm2/sigtrp.c, need the correct signal number. I write a "bridge" in PowerPC assembly that moves the arguments to the stack. I put the bridge in sigaction(), so I provide a signal() that calls sigaction(). I remove the *.c glob or wildcard from build.lua, so linuxppc only compiles its own signal.c, not the other signal.c for linux386 and linux68k. My bridge uses sigprocmask(), so I also add sigprocmask(). Because linux386 and linux68k use globs, they also get sigprocmask(). I sync the header files so all three Linux platforms declare execve(), sigprocmask(), and unlink(), but not remove(), because we have remove() in . I am using sigaction.s to test some features that we recently added to our PowerPC assembler. These are the "hi16[...]" and "lo16[...]" syntax, and also the extended names like "beq", "cmpwi", "li", "subi". --- plat/linux/libsys/sigprocmask.c | 7 ++ plat/linux386/include/unistd.h | 9 +- plat/linux68k/include/unistd.h | 10 ++ plat/linuxppc/include/unistd.h | 27 ++++++ plat/linuxppc/libsys/build.lua | 38 ++++++-- plat/linuxppc/libsys/sigaction.s | 156 +++++++++++++++++++++++++++++++ plat/linuxppc/libsys/signal.c | 19 ++++ 7 files changed, 256 insertions(+), 10 deletions(-) create mode 100644 plat/linux/libsys/sigprocmask.c create mode 100644 plat/linuxppc/libsys/sigaction.s create mode 100644 plat/linuxppc/libsys/signal.c diff --git a/plat/linux/libsys/sigprocmask.c b/plat/linux/libsys/sigprocmask.c new file mode 100644 index 000000000..ad1b339c2 --- /dev/null +++ b/plat/linux/libsys/sigprocmask.c @@ -0,0 +1,7 @@ +#include +#include "libsys.h" + +int sigprocmask(int flags, const sigset_t *new, sigset_t *old) +{ + return _syscall(__NR_sigprocmask, flags, (quad) new, (quad) old); +} diff --git a/plat/linux386/include/unistd.h b/plat/linux386/include/unistd.h index 5c6f31ef4..8c8637c09 100644 --- a/plat/linux386/include/unistd.h +++ b/plat/linux386/include/unistd.h @@ -56,7 +56,6 @@ extern int write(int fd, void* buffer, size_t count); extern off_t lseek(int fildes, off_t offset, int whence); extern int fcntl(int fd, int op, ...); extern int unlink(const char* path); -extern int remove(const char* path); /* Special variables */ @@ -117,8 +116,16 @@ typedef int sig_atomic_t; #define _NSIG 32 /* Biggest signal number + 1 (not including real-time signals). */ + +/* sigprocmask */ +#define SIG_BLOCK 0 +#define SIG_UNBLOCK 1 +#define SIG_SETMASK 2 +typedef unsigned long sigset_t; + typedef void (*sighandler_t)(int); extern sighandler_t signal(int signum, sighandler_t handler); +extern int sigprocmask(int, const sigset_t *, sigset_t *); extern int raise(int signum); diff --git a/plat/linux68k/include/unistd.h b/plat/linux68k/include/unistd.h index 307192f77..927a20459 100644 --- a/plat/linux68k/include/unistd.h +++ b/plat/linux68k/include/unistd.h @@ -55,6 +55,7 @@ extern int read(int fd, void* buffer, size_t count); extern int write(int fd, void* buffer, size_t count); extern off_t lseek(int fildes, off_t offset, int whence); extern int fcntl(int fd, int op, ...); +extern int unlink(const char* path); /* Special variables */ @@ -67,6 +68,7 @@ extern pid_t getpid(void); extern int brk(void* ptr); extern void* sbrk(int increment); extern int isatty(int d); +extern int execve(const char *path, char *const argv[], char *const envp[]); /* Signal handling */ @@ -114,8 +116,16 @@ typedef int sig_atomic_t; #define _NSIG 32 /* Biggest signal number + 1 (not including real-time signals). */ + +/* sigprocmask */ +#define SIG_BLOCK 0 +#define SIG_UNBLOCK 1 +#define SIG_SETMASK 2 +typedef unsigned long sigset_t; + typedef void (*sighandler_t)(int); extern sighandler_t signal(int signum, sighandler_t handler); +extern int sigprocmask(int, const sigset_t *, sigset_t *); extern int raise(int signum); diff --git a/plat/linuxppc/include/unistd.h b/plat/linuxppc/include/unistd.h index a31bd9f0d..f57705365 100644 --- a/plat/linuxppc/include/unistd.h +++ b/plat/linuxppc/include/unistd.h @@ -55,6 +55,7 @@ extern int read(int fd, void* buffer, size_t count); extern int write(int fd, void* buffer, size_t count); extern off_t lseek(int fildes, off_t offset, int whence); extern int fcntl(int fd, int op, ...); +extern int unlink(const char* path); /* Special variables */ @@ -115,8 +116,34 @@ typedef int sig_atomic_t; #define _NSIG 32 /* Biggest signal number + 1 (not including real-time signals). */ + +/* sigprocmask */ +#define SIG_BLOCK 0 +#define SIG_UNBLOCK 1 +#define SIG_SETMASK 2 +typedef unsigned long sigset_t; + +/* sa_flags */ +#define SA_NODEFER 0x40000000UL +#define SA_RESETHAND 0x80000000UL + +struct __siginfo; +struct sigaction { + union { + void (*__sa_handler)(int); + void (*__sa_sigaction)(int, struct __siginfo *, void *); + } __sigaction_u; + sigset_t sa_mask; + unsigned long sa_flags; + void (*sa_restorer)(void); +}; +#define sa_handler __sigaction_u.__sa_handler +#define sa_sigaction __sigaction_u.__sa_sigaction + typedef void (*sighandler_t)(int); +extern int sigaction(int, const struct sigaction *, struct sigaction *); extern sighandler_t signal(int signum, sighandler_t handler); +extern int sigprocmask(int, const sigset_t *, sigset_t *); extern int raise(int signum); diff --git a/plat/linuxppc/libsys/build.lua b/plat/linuxppc/libsys/build.lua index e74f3f416..f7b16b378 100644 --- a/plat/linuxppc/libsys/build.lua +++ b/plat/linuxppc/libsys/build.lua @@ -1,16 +1,36 @@ acklibrary { - name = "lib", - srcs = { - "./*.s", - "plat/linux/libsys/*.c", - "plat/linux/libsys/*.s", - }, + name = "lib", + srcs = { + "./_syscall.s", + "./sigaction.s", + "./signal.c", + "./trap.s", + "plat/linux/libsys/_exit.c", + "plat/linux/libsys/_hol0.s", + "plat/linux/libsys/close.c", + "plat/linux/libsys/creat.c", + "plat/linux/libsys/errno.s", + "plat/linux/libsys/execve.c", + "plat/linux/libsys/getpid.c", + "plat/linux/libsys/gettimeofday.c", + "plat/linux/libsys/ioctl.c", + "plat/linux/libsys/isatty.c", + "plat/linux/libsys/kill.c", + "plat/linux/libsys/lseek.c", + "plat/linux/libsys/open.c", + "plat/linux/libsys/read.c", + "plat/linux/libsys/sbrk.c", + -- omit signal.c + "plat/linux/libsys/sigprocmask.c", + "plat/linux/libsys/unlink.c", + "plat/linux/libsys/write.c", + }, deps = { "lang/cem/libcc.ansi/headers+headers", "plat/linuxppc/include+headers", }, - vars = { - plat = "linuxppc" - } + vars = { + plat = "linuxppc" + } } diff --git a/plat/linuxppc/libsys/sigaction.s b/plat/linuxppc/libsys/sigaction.s new file mode 100644 index 000000000..0509c8e72 --- /dev/null +++ b/plat/linuxppc/libsys/sigaction.s @@ -0,0 +1,156 @@ +#define __NR_sigaction 67 +#define SIG_BLOCK 0 +#define SIG_SETMASK 2 +#define MAXSIG 32 + +/* offsets into our stack frame */ +#define mynew 16 /* new sigaction */ +#define mynset 32 /* new signal set */ +#define myoset 36 /* old signal set */ +#define mysave 40 +#define mysize 56 + +.sect .text; .sect .rodata; .sect .data; .sect .bss + +/* + * Linux calls signal handlers with arguments in registers, but the + * ACK expects arguments on the stack. This sigaction() uses a + * "bridge" to move the arguments. + */ +.sect .text +.define _sigaction +_sigaction: + mflr r0 + subi r1, r1, mysize + stw r31, mysave+8(r1) + stw r30, mysave+4(r1) + stw r29, mysave(r1) + stw r0, mysave+12(r1) + li r3, 0 + stw r3, mynset(r1) ! mynset = 0 + lwz r29, mysize(r1) ! r29 = signal number + lwz r30, mysize+4(r1) ! r30 = new action + lwz r31, mysize+8(r1) ! r31 = old action + /* + * If the new action is non-NULL, the signal number is in + * range 1 to MAXSIG, and the new handler is not SIG_DFL 0 + * or SIG_IGN 1, then we interpose our bridge. + */ + cmpwi cr0, r30, 0 + subi r7, r29, 1 ! r7 = index in handlers + cmplwi cr7, r7, MAXSIG ! unsigned comparison + beq cr0, kernel + bge cr7, kernel + lwz r3, 0(r30) ! r3 = new handler + clrrwi. r3, r3, 1 + beq cr0, kernel + /* + * Block the signal while we build the bridge. Prevents a + * race if a signal arrives after we change the bridge but + * before we change the action in the kernel. + */ + li r4, 1 + slw r4, r4, r7 + stw r4, mynset(r1) ! mynmask = 1 << (signal - 1) + li r3, SIG_BLOCK + la r4, mynset(r1) + la r5, myoset(r1) + stw r3, 0(r1) + stw r4, 4(r1) + stw r5, 8(r1) + bl _sigprocmask + /* + * Point our bridge to the new signal handler. Then copy the + * new sigaction but point it to our bridge. + */ + lis r6, hi16[handlers] + ori r6, r6, lo16[handlers] + subi r7, r29, 1 + slwi r7, r7, 2 + lwz r3, 0(r30) ! r3 = new handler + stwx r3, r6, r7 ! put it in array of handlers + lis r3, hi16[bridge] + ori r3, r3, lo16[bridge] + lwz r4, 4(r30) + lwz r5, 8(r30) + lwz r6, 12(r30) + stw r3, mynew(r1) ! sa_handler or sa_sigaction + stw r4, mynew+4(r1) ! sa_mask + stw r5, mynew+8(r1) ! sa_flags + stw r6, mynew+12(r1) ! sa_restorer + la r30, mynew(r1) +kernel: + li r3, __NR_sigaction + stw r3, 0(r1) + stw r29, 4(r1) + stw r30, 8(r1) + stw r31, 12(r1) + bl __syscall + /* + * If we blocked the signal, then restore the old signal mask. + */ + lwz r3, mynset(r1) + cmpwi cr0, r3, 0 + beq cr0, fixold + li r3, SIG_SETMASK + la r4, myoset(r1) + li r5, 0 + stw r3, 0(r1) + stw r4, 4(r1) + stw r5, 8(r1) + bl _sigprocmask + /* + * If the old sigaction is non-NULL and points to our bridge, + * then point it to the signal handler. + */ +fixold: + cmpwi cr0, r31, 0 + beq cr0, leave + lis r3, hi16[bridge] + ori r3, r3, lo16[bridge] + lwz r4, 0(r31) + cmpw cr0, r3, r4 + bne cr0, leave + lis r6, hi16[handlers] + ori r6, r6, lo16[handlers] + subi r7, r29, 1 + slwi r7, r7, 2 + lwzx r3, r6, r7 ! get it from array of handlers + stw r3, 0(r31) ! put it in old sigaction +leave: + lwz r0, mysave+12(r1) + lwz r29, mysave(r1) + lwz r30, mysave+4(r1) + lwz r31, mysave+8(r1) + addi r1, r1, mysize + mtlr r0 + blr ! return from sigaction + +/* + * Linux calls bridge(signum) or bridge(signum, info, context) with + * arguments in registers r3, r4, r5. + */ +bridge: + mflr r0 + subi r1, r1, 16 + stw r0, 12(r1) + stw r3, 0(r1) ! signal number + stw r4, 4(r1) ! info + stw r5, 8(r1) ! context + + lis r6, hi16[handlers] + ori r6, r6, lo16[handlers] + subi r7, r3, 1 + slwi r7, r7, 2 + lwzx r6, r6, r7 + mtctr r6 + bctrl ! call our signal handler + + lwz r0, 12(r1) + addi r1, r1, 16 + mtlr r0 + blr ! return from bridge + +.sect .bss +handlers: + .space 4 * MAXSIG ! array of signal handlers diff --git a/plat/linuxppc/libsys/signal.c b/plat/linuxppc/libsys/signal.c new file mode 100644 index 000000000..0ed1918e1 --- /dev/null +++ b/plat/linuxppc/libsys/signal.c @@ -0,0 +1,19 @@ +#include + +/* + * Uses our bridge in sigaction.s when calling the signal handler. + * Mimics Linux __NR_signal by using SA_NODEFER | SA_RESETHAND. + */ +sighandler_t signal(int signum, sighandler_t handler) { + struct sigaction new, old; + int i; + + new.sa_handler = handler; + new.sa_mask = 0; /* empty set */ + new.sa_flags = SA_NODEFER | SA_RESETHAND; + + i = sigaction(signum, &new, &old); + if (i < 0) + return SIG_ERR; + return old.sa_handler; +} From a41b6f0458604a32d34e94f68644055285a11ab5 Mon Sep 17 00:00:00 2001 From: George Koehler Date: Mon, 23 Jan 2017 16:19:38 -0500 Subject: [PATCH 150/173] Allow more PowerPC instructions in relocations. I need this for relocations in lis/lfd pairs. I add lfd along with addi, lfs, lha, stfs, stfd to the list. --- util/led/relocate.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/util/led/relocate.c b/util/led/relocate.c index 7e2f9db10..036b7dbb8 100644 --- a/util/led/relocate.c +++ b/util/led/relocate.c @@ -107,14 +107,20 @@ static uint32_t get_vc4_valu(char* addr) static bool is_powerpc_memory_op(uint32_t opcode) { - /* Tests for any PowerPC memory indirection instruction where the payload - * is a *signed* 16-bit value. */ + /* Tests for any PowerPC memory indirection instruction (or + * addi) where the payload is a *signed* 16-bit value. */ switch ((opcode & 0xfc000000) >> 26) { + case 14: /* addi */ case 34: /* lbz */ + case 48: /* lfs */ + case 50: /* lfd */ + case 42: /* lha */ case 40: /* lhz */ case 32: /* lwz */ case 38: /* stb */ + case 52: /* stfs */ + case 54: /* stfd */ case 44: /* sth */ case 36: /* stw */ return true; From 032bcffef610e94406c192e39d67b5231c2d7ab1 Mon Sep 17 00:00:00 2001 From: George Koehler Date: Mon, 23 Jan 2017 17:16:39 -0500 Subject: [PATCH 151/173] In PowerPC libem, use the new features of our assembler. The new features are the hi16/lo16 and ha16/lo16 syntax for relocations, and the extended mnemonics like "blr". Use ha16/lo16 to load some double floats with 2 instructions (lis/lfd) instead of 3 (lis/ori/lfd). Use the extended names for branches, comparisons, and bit rotations, so I can more easily read the code. The new names often encode the same machine instructions as the old names, except in a few places where I changed the instructions. Stop using andi. when we don't need to set cr0. In inn.s, I change andi. to extrwi to extract the same bits. In los.s and sts.s, I change "andi. r3, r3, ~3" to "clrrwi r3, r3, 2". This avoids setting cr0 and also stops clearing the high 16 bits of r3. In csa.s, los.s, sts.s, I change some comparisons and right shifts from signed to unsigned (cmplw, cmplwi, srwi), because the sizes are unsigned. In inn.s, the right shift can be signed (sraw) or unsigned (srw), but I use srw because we don't need the carry bit. In fef8.s, I save an instruction by using rlwinm instead of addis/andc to rlwinm to clear a field. The code no longer kills r7. In both fef8.s and fif8.s, I remove the list of killed registers. Also remove some whitespace from ends of lines. --- mach/powerpc/libem/aar4.s | 26 +++++++----------- mach/powerpc/libem/and.s | 8 +++--- mach/powerpc/libem/cfi8.s | 9 +------ mach/powerpc/libem/cfu8.s | 31 +++++++++------------- mach/powerpc/libem/cif8.s | 21 ++++++--------- mach/powerpc/libem/cms.s | 14 +++++----- mach/powerpc/libem/com.s | 8 +++--- mach/powerpc/libem/csa.s | 29 ++++++-------------- mach/powerpc/libem/csb.s | 25 +++++++----------- mach/powerpc/libem/cuf8.s | 23 ++++++---------- mach/powerpc/libem/fd_00000000.s | 7 +---- mach/powerpc/libem/fd_80000000.s | 7 +---- mach/powerpc/libem/fd_FFFFFFFF.s | 9 ++----- mach/powerpc/libem/fef8.s | 28 +++++++++----------- mach/powerpc/libem/fif8.s | 28 +++++++++----------- mach/powerpc/libem/inn.s | 12 ++++----- mach/powerpc/libem/ior.s | 8 +++--- mach/powerpc/libem/lar4.s | 19 ++++++-------- mach/powerpc/libem/los.s | 45 ++++++++++++++------------------ mach/powerpc/libem/rck.s | 12 ++++----- mach/powerpc/libem/ret.s | 17 ++++-------- mach/powerpc/libem/sar4.s | 19 ++++++-------- mach/powerpc/libem/set.s | 16 +++++------- mach/powerpc/libem/sts.s | 45 ++++++++++++++------------------ mach/powerpc/libem/xor.s | 8 +++--- mach/powerpc/libem/zer.s | 10 +++---- 26 files changed, 184 insertions(+), 300 deletions(-) diff --git a/mach/powerpc/libem/aar4.s b/mach/powerpc/libem/aar4.s index 2c65af643..5e4155091 100644 --- a/mach/powerpc/libem/aar4.s +++ b/mach/powerpc/libem/aar4.s @@ -1,12 +1,5 @@ -# -! $Source$ -! $State$ -! $Revision$ - -#include "powerpc.h" - .sect .text - + ! Index into a bounds-checked array. ! ! On entry: @@ -20,19 +13,20 @@ .define .aar4 .aar4: - li32 r0, .trap_earray + lis r0, hi16[.trap_earray] + ori r0, r0, lo16[.trap_earray] mtspr ctr, r0 ! load CTR with trap address lwz r0, 0(r3) subf. r4, r0, r4 ! adjust range - bcctr IFTRUE, LT, 0 ! check lower bound - + bltctr ! check lower bound + lwz r0, 4(r3) - cmpl cr0, 0, r4, r3 - bcctr IFFALSE, LT, 0 ! check upper bound - + cmplw r4, r3 + bgectr ! check upper bound + lwz r0, 8(r3) mullw r4, r4, r0 ! scale index add r3, r4, r5 ! calculate element address - - bclr ALWAYS, 0, 0 + + blr diff --git a/mach/powerpc/libem/and.s b/mach/powerpc/libem/and.s index 727d79ec0..cb4e1e54a 100644 --- a/mach/powerpc/libem/and.s +++ b/mach/powerpc/libem/and.s @@ -1,5 +1,3 @@ -#include "powerpc.h" - .sect .text ! Set intersection. @@ -12,7 +10,7 @@ mr r4, sp ! r4 = ptr to set a add r5, sp, r3 ! r5 = ptr to set b - rlwinm r6, r3, 30, 2, 31 + srwi r6, r3, 2 mtspr ctr, r6 ! ctr = r3 / 4 1: lwz r7, 0(r4) @@ -21,6 +19,6 @@ stw r8, 0(r5) addi r4, r4, 4 addi r5, r5, 4 - bc DNZ, 0, 1b ! loop ctr times + bdnz 1b ! loop ctr times add sp, sp, r3 - bclr ALWAYS, 0, 0 + blr diff --git a/mach/powerpc/libem/cfi8.s b/mach/powerpc/libem/cfi8.s index 7142c694b..9a87e99ae 100644 --- a/mach/powerpc/libem/cfi8.s +++ b/mach/powerpc/libem/cfi8.s @@ -1,10 +1,3 @@ -# -! $Source$ -! $State$ -! $Revision$ - -#include "powerpc.h" - .sect .text ! Converts a 64-bit double into a 32-bit integer. @@ -17,4 +10,4 @@ fctiwz f0, f0 stfd f0, 0(sp) addi sp, sp, 4 - bclr ALWAYS, 0, 0 ! ...and return + blr diff --git a/mach/powerpc/libem/cfu8.s b/mach/powerpc/libem/cfu8.s index 758df8572..915f84dd2 100644 --- a/mach/powerpc/libem/cfu8.s +++ b/mach/powerpc/libem/cfu8.s @@ -1,10 +1,3 @@ -# -! $Source$ -! $State$ -! $Revision$ - -#include "powerpc.h" - .sect .text ! Converts a 64-bit double into a 32-bit unsigned integer. @@ -13,17 +6,17 @@ .define .cfu8 .cfu8: - li32 r3, .fd_00000000 - lfd f0, 0(r3) ! f0 = 0.0 - + lis r3, ha16[.fd_00000000] + lfd f0, lo16[.fd_00000000](r3) ! f0 = 0.0 + lfd f1, 0(sp) ! value to be converted - li32 r3, .fd_FFFFFFFF - lfd f3, 0(r3) ! f3 = 0xFFFFFFFF + lis r3, ha16[.fd_FFFFFFFF] + lfd f3, lo16[.fd_FFFFFFFF](r3) ! f3 = 0xFFFFFFFF + + lis r3, ha16[.fd_80000000] + lfd f4, lo16[.fd_80000000](r3) ! f4 = 0x80000000 - li32 r3, .fd_80000000 - lfd f4, 0(r3) ! f4 = 0x80000000 - fsel f2, f1, f1, f0 fsub f5, f3, f1 fsel f2, f5, f2, f3 @@ -34,11 +27,11 @@ stfd f2, 0(sp) addi sp, sp, 4 - - bclr IFTRUE, LT, 0 - + + bltlr + lwz r3, 0(sp) xoris r3, r3, 0x8000 stw r3, 0(sp) - bclr ALWAYS, 0, 0 + blr diff --git a/mach/powerpc/libem/cif8.s b/mach/powerpc/libem/cif8.s index d2c82e54e..13abbcade 100644 --- a/mach/powerpc/libem/cif8.s +++ b/mach/powerpc/libem/cif8.s @@ -1,9 +1,4 @@ -# -! $Source$ -! $State$ -! $Revision$ - -#include "powerpc.h" +.sect .text; .sect .rom; .sect .data; .sect .bss .sect .text @@ -14,22 +9,22 @@ .define .cif8 .cif8: addi sp, sp, -4 ! make space for the double - + lwz r3, 4(sp) xoris r3, r3, 0x8000 stw r3, 4(sp) ! flip sign of integer value - + addis r3, r0, 0x4330 stw r3, 0(sp) ! set high word to construct a double - + lfd f0, 0(sp) ! load value - li32 r3, pivot - lfd f1, 0(r3) ! load pivot value + lis r3, ha16[pivot] + lfd f1, lo16[pivot](r3) ! load pivot value fsub f0, f0, f1 ! adjust - + stfd f0, 0(sp) ! save value again... - bclr ALWAYS, 0, 0 ! ...and return + blr ! ...and return .sect .rom pivot: diff --git a/mach/powerpc/libem/cms.s b/mach/powerpc/libem/cms.s index 53cb65691..30aaccd20 100644 --- a/mach/powerpc/libem/cms.s +++ b/mach/powerpc/libem/cms.s @@ -1,5 +1,3 @@ -#include "powerpc.h" - .sect .text ! Compare sets a, b. @@ -12,21 +10,21 @@ mr r4, sp ! r4 = ptr to set a add r5, sp, r3 ! r5 = ptr to set b mr r6, r3 ! r6 = size - rlwinm r3, r3, 30, 2, 31 + srwi r3, r3, 2 mtspr ctr, r3 ! ctr = size / 4 1: lwz r7, 0(r4) lwz r8, 0(r5) - cmp cr0, 0, r7, r8 ! compare words in sets + cmpw cr0, r7, r8 ! compare words in sets addi r4, r4, 4 addi r5, r5, 4 - bc IFFALSE, EQ, 2f ! branch if not equal - bc DNZ, 0, 1b ! loop ctr times + bne cr0, 2f ! branch if not equal + bdnz 1b ! loop ctr times addi r3, r0, 0 ! equal: return 0 b 3f 2: addi r3, r0, 1 ! not equal: return 1 3: - rlwinm r6, r6, 1, 0, 30 ! r6 = size * 2 + slwi r6, r6, 1 ! r6 = size * 2 add sp, sp, r6 ! remove sets from stack - bclr ALWAYS, 0, 0 + blr diff --git a/mach/powerpc/libem/com.s b/mach/powerpc/libem/com.s index 084eeeb62..3168cfe17 100644 --- a/mach/powerpc/libem/com.s +++ b/mach/powerpc/libem/com.s @@ -1,5 +1,3 @@ -#include "powerpc.h" - .sect .text ! Set complement. @@ -11,12 +9,12 @@ addi sp, sp, 4 mr r4, sp ! r4 = pointer to set a - rlwinm r5, r3, 30, 2, 31 + srwi r5, r3, 2 mtspr ctr, r5 ! ctr = r3 / 4 1: lwz r6, 0(r4) nor r6, r6, r6 ! complement of word stw r6, 0(r4) addi r4, r4, 4 - bc DNZ, 0, 1b ! loop ctr times - bclr ALWAYS, 0, 0 + bdnz 1b ! loop ctr times + blr diff --git a/mach/powerpc/libem/csa.s b/mach/powerpc/libem/csa.s index 88e6e176a..3898241c4 100644 --- a/mach/powerpc/libem/csa.s +++ b/mach/powerpc/libem/csa.s @@ -1,10 +1,3 @@ -# -! $Source$ -! $State$ -! $Revision$ - -#include "powerpc.h" - .sect .text ! this is not a subroutine, but just a @@ -25,23 +18,17 @@ lwz r5, 4(r3) ! fetch lower bound subf. r4, r5, r4 ! adjust value - bcctr IFTRUE, LT, 0 ! jump to default if out of range - + bltctr ! jump to default if out of range + lwz r5, 8(r3) ! fetch range - cmp cr0, 0, r4, r5 - bcctr IFTRUE, GT, 0 ! jump to default if out of range - + cmplw r4, r5 + bgtctr ! jump to default if out of range + addi r3, r3, 12 ! skip header - rlwinm r4, r4, 2, 0, 31-2 ! scale value (<<2) - b 1f -1: + slwi r4, r4, 2 ! scale value (<<2) lwzx r5, r3, r4 ! load target - b 1f -1: mtspr ctr, r5 - + or. r5, r5, r5 ! test it - b 1f -1: - bcctr IFFALSE, EQ, 0 ! jump to target if non-zero + bnectr ! jump to target if non-zero b .trap_ecase ! otherwise trap diff --git a/mach/powerpc/libem/csb.s b/mach/powerpc/libem/csb.s index a8df85d7f..571bfc210 100644 --- a/mach/powerpc/libem/csb.s +++ b/mach/powerpc/libem/csb.s @@ -1,10 +1,3 @@ -# -! $Source$ -! $State$ -! $Revision$ - -#include "powerpc.h" - .sect .text ! this is not a subroutine, but just a @@ -22,21 +15,21 @@ lwz r5, 0(r3) ! load default mtspr ctr, r5 - + lwz r6, 4(r3) ! fetch count - + 1: or. r6, r6, r6 ! test count - bcctr IFTRUE, EQ, 0 ! exit if zero + beqctr ! exit if zero addi r6, r6, -1 ! otherwise decrement - + lwzu r7, 8(r3) ! fetch target index, increment pointer - cmp cr0, 0, r4, r7 ! compare with value - bc IFFALSE, EQ, 1b ! if not equal, go again - + cmpw r4, r7 ! compare with value + bne 1b ! if not equal, go again + lwz r7, 4(r3) ! fetch target address mtspr ctr, r7 - + or. r7, r7, r7 ! test it - bcctr IFFALSE, EQ, 0 ! jump to target if non-zero + bnectr ! jump to target if non-zero b .trap_ecase ! otherwise trap diff --git a/mach/powerpc/libem/cuf8.s b/mach/powerpc/libem/cuf8.s index 5d5a12988..ce9932aa1 100644 --- a/mach/powerpc/libem/cuf8.s +++ b/mach/powerpc/libem/cuf8.s @@ -1,10 +1,3 @@ -# -! $Source$ -! $State$ -! $Revision$ - -#include "powerpc.h" - .sect .text ! Converts a 32-bit unsigned integer into a 64-bit double. @@ -14,18 +7,18 @@ .define .cuf8 .cuf8: addi sp, sp, -4 ! make space for the double - - addis r3, r0, 0x4330 + + lis r3, 0x4330 stw r3, 0(sp) ! set high word to construct a double - + lfd f0, 0(sp) ! load value - - li32 r3, pivot - lfd f1, 0(r3) ! load pivot value + + lis r3, ha16[pivot] + lfd f1, lo16[pivot](r3) ! load pivot value fsub f0, f0, f1 ! adjust - + stfd f0, 0(sp) ! save value again... - bclr ALWAYS, 0, 0 ! ...and return + blr ! ...and return .sect .rom pivot: diff --git a/mach/powerpc/libem/fd_00000000.s b/mach/powerpc/libem/fd_00000000.s index cefa91b8e..8ffe44a24 100644 --- a/mach/powerpc/libem/fd_00000000.s +++ b/mach/powerpc/libem/fd_00000000.s @@ -1,10 +1,5 @@ -# -! $Source$ -! $State$ -! $Revision$ +.sect .text; .sect .rom; .sect .data; .sect .bss -#include "powerpc.h" - .sect .rom ! Contains a handy double-precision zero. (Also works as a single-precision diff --git a/mach/powerpc/libem/fd_80000000.s b/mach/powerpc/libem/fd_80000000.s index 50eacd586..5c153bba8 100644 --- a/mach/powerpc/libem/fd_80000000.s +++ b/mach/powerpc/libem/fd_80000000.s @@ -1,10 +1,5 @@ -# -! $Source$ -! $State$ -! $Revision$ +.sect .text; .sect .rom; .sect .data; .sect .bss -#include "powerpc.h" - .sect .rom ! Contains a handy double-precision 0x80000000. diff --git a/mach/powerpc/libem/fd_FFFFFFFF.s b/mach/powerpc/libem/fd_FFFFFFFF.s index 9218f2726..88cf04bd9 100644 --- a/mach/powerpc/libem/fd_FFFFFFFF.s +++ b/mach/powerpc/libem/fd_FFFFFFFF.s @@ -1,15 +1,10 @@ -# -! $Source$ -! $State$ -! $Revision$ +.sect .text; .sect .rom; .sect .data; .sect .bss -#include "powerpc.h" - .sect .rom ! Contains a handy double-precision 0xFFFFFFFF. .define .fd_FFFFFFFF -.fd_FFFFFFFF: +.fd_FFFFFFFF: !float 4.294967295e+9 sz 8 .data1 0101,0357,0377,0377,0377,0340,00,00 diff --git a/mach/powerpc/libem/fef8.s b/mach/powerpc/libem/fef8.s index fc72b04f2..f71ab8e38 100644 --- a/mach/powerpc/libem/fef8.s +++ b/mach/powerpc/libem/fef8.s @@ -1,4 +1,4 @@ -#include "powerpc.h" +.sect .text; .sect .rom; .sect .data; .sect .bss .sect .text @@ -10,46 +10,44 @@ ! r3 = fraction, high word (bits 0..31) ! r4 = fraction, low word (bits 32..63) ! r5 = exponent -! Kills: cr0 f0 f1 r6 r7 .define .fef8 .fef8: ! IEEE double-precision format: ! sign exponent fraction ! 0 1..11 12..63 - rlwinm r6, r3, 12, 21, 31 ! r6 = IEEE exponent - addis r7, r0, 0x7ff0 ! r7 = exponent mask + extrwi r6, r3, 11, 1 ! r6 = IEEE exponent addi r5, r6, -1022 ! r5 = true exponent - cmpi cr0, 0, r6, 2047 - bclr IFTRUE, EQ, 0 ! return if infinity or NaN - cmpi cr0, 0, r6, 0 - bc IFFALSE, EQ, 1f ! jump if normalized number + cmpwi r6, 2047 + beqlr ! return if infinity or NaN + cmpwi r6, 0 + bne 1f ! jump if normalized number ! Got denormalized number or zero, probably zero. - rlwinm r6, r3, 0, 12, 31 + extrwi r6, r3, 22, 12 addi r5, r0, 0 ! r5 = true exponent = 0 or. r6, r6, r4 ! r6 = high|low fraction - bclr IFTRUE, EQ, 0 ! return if zero + beqlr ! return if zero ! Got denormalized number, not zero. stwu r4, -4(sp) stwu r3, -4(sp) - li32 r6, _2_64 lfd f0, 0(sp) - lfd f1, 0(r6) + lis r6, ha16[_2_64] + lfd f1, lo16[_2_64](r6) fmul f0, f0, f1 ! multiply it by 2**64 stfd f0, 0(sp) lwz r3, 0(sp) lwz r4, 4(sp) - rlwinm r6, r3, 12, 21, 31 ! r6 = IEEE exponent + extrwi r6, r3, 11, 1 ! r6 = IEEE exponent addi sp, sp, 8 addi r5, r6, -1022 - 64 ! r5 = true exponent 1: ! Put fraction in [0.5, 1) or (-1, -0.5] by setting its ! exponent to true 0, IEEE 1022. - andc r3, r3, r7 ! clear old exponent + rlwinm r3, r3, 0, 12, 0 ! clear old exponent oris r3, r3, 1022 << 4 ! set new exponent - bclr ALWAYS, 0, 0 + blr .sect .rom _2_64: diff --git a/mach/powerpc/libem/fif8.s b/mach/powerpc/libem/fif8.s index a26c77830..eda9b04f2 100644 --- a/mach/powerpc/libem/fif8.s +++ b/mach/powerpc/libem/fif8.s @@ -1,5 +1,3 @@ -#include "powerpc.h" - .sect .text ! Multiplies two double-precision floats, then splits the product into @@ -9,7 +7,6 @@ ! Yields: ! f1 = fraction ! f2 = integer -! Kills: cr0 f1 f2 r3 r4 r5 r6 .define .fif8 .fif8: @@ -25,17 +22,16 @@ ! 0 to 51, then the IEEE fraction has that many integer bits. ! (IEEE has an implicit 1 before its fraction. If the IEEE ! fraction has 0 integer bits, we still have an integer.) - rlwinm r5, r3, 12, 21, 31 ! r5 = IEEE exponent + extrwi r5, r3, 11, 1 ! r5 = IEEE exponent addic. r5, r5, -1023 ! r5 = nr of integer bits - bc IFTRUE, LT, no_int - cmpi cr0, 0, r5, 21 - bc IFTRUE, LT, small_int - cmpi cr0, 0, r5, 52 - bc IFTRUE, LT, big_int + blt no_int + cmpwi r5, 21 + blt small_int + cmpwi r5, 52 + blt big_int - ! f1 is an integer without fraction. Jump to calculate - ! fraction f1 = f2 - f1. It will be zero (or perhaps NaN). - fmr f2, f1 + ! f1 is an integer without fraction (or infinity or NaN). + fmr f2, f1 ! integer = f1 b subtract no_int: @@ -46,17 +42,17 @@ no_int: small_int: ! f1 has r5 = 0 to 20 integer bits in the IEEE fraction. ! High word has 20 - r5 fraction bits. - addi r6, r0, 20 + li r6, 20 subf r6, r5, r6 srw r3, r3, r6 - addi r4, r0, 0 ! clear low word + li r4, 0 ! clear low word slw r3, r3, r6 ! clear fraction in high word b move_int big_int: ! f1 has r5 = 21 to 51 to integer bits. ! Low word has 52 - r5 fraction bits. - addi r6, r0, 52 + li r6, 52 subf r6, r5, r6 srw r4, r4, r6 slw r4, r4, r6 ! clear fraction in low word @@ -68,4 +64,4 @@ subtract: fsub f1, f1, f2 ! fraction = value - integer done: addi sp, sp, 8 ! restore stack pointer - bclr ALWAYS, 0, 0 + blr diff --git a/mach/powerpc/libem/inn.s b/mach/powerpc/libem/inn.s index 9770ac094..8925e776e 100644 --- a/mach/powerpc/libem/inn.s +++ b/mach/powerpc/libem/inn.s @@ -1,4 +1,4 @@ -#include "powerpc.h" +# .sect .text @@ -14,13 +14,13 @@ addi r5, sp, 8 /* r5 = base address of bit set */ rlwinm r6, r4, 29, 3, 29 /* r6 = byte index of word in set */ - andi. r7, r4, 31 /* r7 = bit within word */ + extrwi r7, r4, 5, 27 /* r7 = bit number within word */ - lwzx r8, r5, r6 /* r8 = individual byte from set */ - sraw r8, r8, r7 - rlwinm r8, r8, 0, 31, 31 + lwzx r8, r5, r6 /* r8 = individual word from set */ + srw r8, r8, r7 + extrwi r8, r8, 1, 31 addi sp, sp, 8 /* retract over the two words */ add sp, sp, r3 /* retract over bitfield */ stwu r8, -4(sp) /* push result */ - bclr ALWAYS, 0, 0 /* return */ + blr /* return */ diff --git a/mach/powerpc/libem/ior.s b/mach/powerpc/libem/ior.s index 363799e1d..e6cd1844e 100644 --- a/mach/powerpc/libem/ior.s +++ b/mach/powerpc/libem/ior.s @@ -1,5 +1,3 @@ -#include "powerpc.h" - .sect .text ! Set union. @@ -12,7 +10,7 @@ mr r4, sp ! r4 = ptr to set a add r5, sp, r3 ! r5 = ptr to set b - rlwinm r6, r3, 30, 2, 31 + srwi r6, r3, 2 mtspr ctr, r6 ! ctr = r3 / 4 1: lwz r7, 0(r4) @@ -21,6 +19,6 @@ stw r8, 0(r5) addi r4, r4, 4 addi r5, r5, 4 - bc DNZ, 0, 1b ! loop ctr times + bdnz 1b ! loop ctr times add sp, sp, r3 - bclr ALWAYS, 0, 0 + blr diff --git a/mach/powerpc/libem/lar4.s b/mach/powerpc/libem/lar4.s index 6375979c4..2f5c3683c 100644 --- a/mach/powerpc/libem/lar4.s +++ b/mach/powerpc/libem/lar4.s @@ -1,6 +1,3 @@ -# -#include "powerpc.h" - .sect .text ! Load from bounds-checked array. @@ -18,19 +15,19 @@ ! r3 = ptr to element ! r0 = size of element - cmpi cr0, 0, r0, 1 - bc IFFALSE, EQ, 1f + cmpwi r0, 1 + bne 1f ! Load 1 byte. lbz r4, 0(r3) stwu r4, -4(sp) - bclr ALWAYS, 0, 0 + blr 1: - cmpi cr0, 0, r0, 2 - bc IFFALSE, EQ, 2f + cmpwi r0, 2 + bne 2f ! Load 2 bytes. lhz r4, 0(r3) stwu r4, -4(sp) - bclr ALWAYS, 0, 0 + blr 2: ! Load r0 bytes, where r0 must be a positive multiple of 4. subf sp, r0, sp ! move stack pointer down @@ -39,5 +36,5 @@ addic. r5, r5, -4 ! r5 -= 4 lwzx r4, r5, r3 stwx r4, r5, sp - bc IFTRUE, GT, 3b ! loop if r5 > 0 - bclr ALWAYS, 0, 0 + bgt 3b ! loop if r5 > 0 + blr diff --git a/mach/powerpc/libem/los.s b/mach/powerpc/libem/los.s index f867fe770..2d412bce8 100644 --- a/mach/powerpc/libem/los.s +++ b/mach/powerpc/libem/los.s @@ -1,10 +1,3 @@ -# -! $Source$ -! $State$ -! $Revision$ - -#include "powerpc.h" - .sect .text ! Loads a variable-sized structure onto the stack. @@ -15,32 +8,32 @@ .define .los .los: ! These sizes are handled specially. - - cmpi cr0, 0, r3, 1 - bc IFFALSE, GT, size1 - - cmpi cr0, 0, r3, 2 - bc IFFALSE, GT, size2 - - cmpi cr0, 0, r3, 4 - bc IFFALSE, GT, size4 - + + cmplwi r3, 1 + ble size1 + + cmplwi r3, 2 + ble size2 + + cmplwi r3, 4 + ble size4 + ! Variable-sized structure. - + addi r3, r3, 3 - andi. r3, r3, ~3 ! align size - + clrrwi r3, r3, 2 ! align size + add r4, r4, r3 ! adjust address to top of block - srawi r3, r3, 2 ! convert size to the number of words + srwi r3, r3, 2 ! convert size to the number of words mtspr ctr, r3 - + 1: lwzu r5, -4(r4) stwu r5, -4(sp) - bc DNZ, 0, 1b ! decrement CTR, jump if non-zero - bclr ALWAYS, 0, 0 - + bdnz 1b ! decrement CTR, jump if non-zero + blr + size1: lbz r3, 0(r4) b 1f @@ -51,4 +44,4 @@ size4: lwz r3, 0(r4) 1: stwu r3, -4(sp) - bclr ALWAYS, 0, 0 + blr diff --git a/mach/powerpc/libem/rck.s b/mach/powerpc/libem/rck.s index 0d5717f16..9008be610 100644 --- a/mach/powerpc/libem/rck.s +++ b/mach/powerpc/libem/rck.s @@ -1,5 +1,3 @@ -#include "powerpc.h" - .sect .text ! Bounds check. Traps if the value is out of range. @@ -12,11 +10,11 @@ addi sp, sp, 4 ! leave value on stack lwz r5, 0 (r3) - cmp cr0, 0, r4, r5 - bc IFTRUE, LT, .trap_erange + cmpw r4, r5 + blt .trap_erange lwz r5, 4 (r3) - cmp cr0, 0, r4, r5 - bc IFTRUE, GT, .trap_erange + cmpw r4, r5 + bgt .trap_erange - bclr ALWAYS, 0, 0 + blr diff --git a/mach/powerpc/libem/ret.s b/mach/powerpc/libem/ret.s index cca79ae86..c498af240 100644 --- a/mach/powerpc/libem/ret.s +++ b/mach/powerpc/libem/ret.s @@ -1,19 +1,12 @@ -# -! $Source$ -! $State$ -! $Revision$ - -#include "powerpc.h" - .sect .text - + ! Standard boilerplate for returning from functions. .define .ret .ret: lwz r0, 4(fp) mtspr lr, r0 - lwz r0, 0(fp) ! our stack frame becomes invalid as soon as... - addi sp, fp, 8 ! ...we change sp - or fp, r0, r0 - bclr ALWAYS, 0, 0 + lwz r0, 0(fp) ! our stack frame becomes invalid as soon as... + addi sp, fp, 8 ! ...we change sp + mr fp, r0 + blr diff --git a/mach/powerpc/libem/sar4.s b/mach/powerpc/libem/sar4.s index 0c1368af1..7c9778958 100644 --- a/mach/powerpc/libem/sar4.s +++ b/mach/powerpc/libem/sar4.s @@ -1,6 +1,3 @@ -# -#include "powerpc.h" - .sect .text ! Store to bounds-checked array. @@ -18,21 +15,21 @@ ! r3 = ptr to element ! r0 = size of element - cmpi cr0, 0, r0, 1 - bc IFFALSE, EQ, 1f + cmpwi r0, 1 + bne 1f ! Store 1 byte. lwz r4, 0(sp) addi sp, sp, 4 stb r4, 0(r3) - bclr ALWAYS, 0, 0 + blr 1: - cmpi cr0, 0, r0, 2 - bc IFFALSE, EQ, 2f + cmpwi r0, 2 + bne 2f ! Store 2 bytes. lwz r4, 0(sp) addi sp, sp, 4 sth r4, 0(r3) - bclr ALWAYS, 0, 0 + blr 2: ! Store r0 bytes, where r0 must be a positive multiple of 4. or r5, r0, r0 ! index r5 = length r0 @@ -40,6 +37,6 @@ addic. r5, r5, -4 ! r5 -= 4 lwzx r4, r5, sp stwx r4, r5, r3 - bc IFTRUE, GT, 3b ! loop if r5 > 0 + bgt 3b ! loop if r5 > 0 add sp, r0, sp ! move stack pointer up - bclr ALWAYS, 0, 0 + blr diff --git a/mach/powerpc/libem/set.s b/mach/powerpc/libem/set.s index b42881cd7..3c4a9e579 100644 --- a/mach/powerpc/libem/set.s +++ b/mach/powerpc/libem/set.s @@ -1,5 +1,3 @@ -#include "powerpc.h" - .sect .text ! Create singleton set. @@ -11,22 +9,22 @@ lwz r4, 4 (sp) addi sp, sp, 8 - rlwinm r7, r3, 30, 2, 31 + srwi r7, r3, 2 neg r5, r3 add sp, sp, r5 ! allocate set mr r6, sp ! r6 = ptr to set mtspr ctr, r7 ! ctr = r3 / 4 1: - rlwinm. r7, r4, 0, 0, 26 ! r7 = r4 & ~31 - bc IFTRUE, EQ, 2f ! branch if r4 in 0..31 - addi r5, r0, 0 ! no bit, word is zero + clrrwi. r7, r4, 5 ! r7 = r4 & ~31 + beq 2f ! branch if r4 in 0..31 + li r5, 0 ! no bit, word is zero b 3f 2: - addi r5, r0, 1 + li r5, 1 slw r5, r5, r4 ! yes bit, set bit in word 3: stw r5, 0(r6) ! store word in set addi r4, r4, -32 addi r6, r6, 4 - bc DNZ, 0, 1b ! loop ctr times - bclr ALWAYS, 0, 0 + bdnz 1b ! loop ctr times + blr diff --git a/mach/powerpc/libem/sts.s b/mach/powerpc/libem/sts.s index 2f8022ad9..411b0fb66 100644 --- a/mach/powerpc/libem/sts.s +++ b/mach/powerpc/libem/sts.s @@ -1,10 +1,3 @@ -# -! $Source$ -! $State$ -! $Revision$ - -#include "powerpc.h" - .sect .text ! Stores a variable-sized structure from the stack. @@ -15,35 +8,35 @@ .define .sts .sts: ! These sizes are handled specially. - + lwz r5, 0(sp) - cmpi cr0, 0, r3, 1 - bc IFFALSE, GT, size1 - - cmpi cr0, 0, r3, 2 - bc IFFALSE, GT, size2 - - cmpi cr0, 0, r3, 4 - bc IFFALSE, GT, size4 - + cmplwi r3, 1 + ble size1 + + cmplwi r3, 2 + ble size2 + + cmplwi r3, 4 + ble size4 + ! Variable-sized structure. - + addi r3, r3, 3 - andi. r3, r3, ~3 ! align size - - srawi r3, r3, 2 ! convert size to the number of words + clrrwi r3, r3, 2 ! align size + + srwi r3, r3, 2 ! convert size to the number of words mtspr ctr, r3 - + 1: lwz r5, 0(sp) addi sp, sp, 4 stw r5, 0(r4) addi r4, r4, 4 - bc DNZ, 0, 1b ! decrement CTR, jump if non-zero - bclr ALWAYS, 0, 0 - + bdnz 1b ! decrement CTR, jump if non-zero + blr + size1: stb r5, 0(r4) b 1f @@ -54,4 +47,4 @@ size4: stw r5, 0(r4) 1: addi sp, sp, 4 - bclr ALWAYS, 0, 0 + blr diff --git a/mach/powerpc/libem/xor.s b/mach/powerpc/libem/xor.s index 9d4bc76b9..acb02a032 100644 --- a/mach/powerpc/libem/xor.s +++ b/mach/powerpc/libem/xor.s @@ -1,5 +1,3 @@ -#include "powerpc.h" - .sect .text ! Set symmetric difference. @@ -10,7 +8,7 @@ .xor: mr r4, sp ! r4 = ptr to set a add r5, sp, r3 ! r5 = ptr to set b - rlwinm r6, r3, 30, 2, 31 + srwi r6, r3, 2 mtspr ctr, r6 ! ctr = r3 / 4 1: lwz r7, 0(r4) @@ -19,6 +17,6 @@ stw r8, 0(r5) addi r4, r4, 4 addi r5, r5, 4 - bc DNZ, 0, 1b ! loop ctr times + bdnz 1b ! loop ctr times add sp, sp, r3 - bclr ALWAYS, 0, 0 + blr diff --git a/mach/powerpc/libem/zer.s b/mach/powerpc/libem/zer.s index 697a5715f..a47a150cc 100644 --- a/mach/powerpc/libem/zer.s +++ b/mach/powerpc/libem/zer.s @@ -1,5 +1,3 @@ -#include "powerpc.h" - .sect .text ! Create empty set. @@ -10,8 +8,8 @@ lwz r3, 0(sp) addi sp, sp, 4 - rlwinm r7, r3, 30, 2, 31 - addi r4, r0, 0 ! r4 = zero + srwi r7, r3, 2 + li r4, 0 ! r4 = zero neg r5, r3 add sp, sp, r5 ! allocate set mr r6, sp ! r6 = ptr to set @@ -19,5 +17,5 @@ 1: stw r4, 0(r6) ! store zero in set addi r6, r6, 4 - bc DNZ, 0, 1b ! loop ctr times - bclr ALWAYS, 0, 0 + bdnz 1b ! loop ctr times + blr From bb67dbeb1151c81795b0051d068dc794ec15a340 Mon Sep 17 00:00:00 2001 From: George Koehler Date: Mon, 23 Jan 2017 17:31:29 -0500 Subject: [PATCH 152/173] Use "kills ALL" instead of a list of killed registers. This is for fef 8 and fif 8. I changed .fef8 so it no longer kills r7, but I don't want to update the list. We already use "kills ALL" for most other calls to libem. --- mach/powerpc/ncg/table | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mach/powerpc/ncg/table b/mach/powerpc/ncg/table index 1fc1f5b19..4deceefe8 100644 --- a/mach/powerpc/ncg/table +++ b/mach/powerpc/ncg/table @@ -2238,14 +2238,14 @@ PATTERNS pat fef $1==INT64 /* Split exponent, fraction */ with GPR3 GPR4 - kills FPR0, FPR1, GPR6, GPR7 + kills ALL gen bl {LABEL, ".fef8"} yields R4 R3 R5 pat fif $1==INT64 /* Multiply then split integer, fraction */ with FPR1 FPR2 - kills FPR1, FPR2, GPR3, GPR4, GPR5, GPR6 + kills ALL gen bl {LABEL, ".fif8"} yields F1 F2 From 188b23bade620afc6be386973e45ce77a5999d0f Mon Sep 17 00:00:00 2001 From: George Koehler Date: Tue, 24 Jan 2017 11:26:35 -0500 Subject: [PATCH 153/173] Add constraints for pat lab, as done in the m68020 table. Always use 'kills ALL' when reaching a label, because our registers and tokens have the wrong values if the program jumps to this label from somewhere else. When falling through a label, if the top element is in r3, then require that the rest of the stack is in the real STACK, not in registers or tokens. I'm doing this to be certain that the missing constraints are not causing bugs. I did not find any such bug, perhaps because the labels are usually near other instructions (like conditional branches and function calls) that stack or kill tokens. --- mach/powerpc/ncg/table | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/mach/powerpc/ncg/table b/mach/powerpc/ncg/table index 4deceefe8..d42eb27eb 100644 --- a/mach/powerpc/ncg/table +++ b/mach/powerpc/ncg/table @@ -1852,12 +1852,14 @@ PATTERNS /* Other branching and labelling */ pat lab topeltsize($1)==4 && !fallthrough($1) + kills ALL gen labeldef $1 yields R3 pat lab topeltsize($1)==4 && fallthrough($1) - with GPR3 + with GPR3 STACK + kills ALL gen labeldef $1 yields %1 From a348853eced4b8836e7dbb2be696829d638bfab7 Mon Sep 17 00:00:00 2001 From: George Koehler Date: Wed, 25 Jan 2017 11:24:23 -0500 Subject: [PATCH 154/173] Add missing size declarations for 8-byte registers. This fixes the coercion from IND_ALL_D to FREG. The coercion had never happened, because IND_ALL_D had 8 bytes but FREG had 4 bytes. Instead, ncg always stacked the IND_ALL_D and unstacked a FREG. The stacking rule uses f0, so the code did load f0 with the indirect value, push f0 to stack, load f1 to stack, move stack pointer. Now that FREG has 8 bytes, ncg does the coercion, and the code just loads f1 with the indirect value. --- mach/powerpc/ncg/table | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/mach/powerpc/ncg/table b/mach/powerpc/ncg/table index d42eb27eb..99c2e404c 100644 --- a/mach/powerpc/ncg/table +++ b/mach/powerpc/ncg/table @@ -42,9 +42,9 @@ PROPERTIES GPR /* any GPR */ REG /* any allocatable GPR */ - REG_PAIR /* speed hack for sti 8 */ - FPR /* any FPR */ - FREG /* any allocatable FPR */ + REG_PAIR(8) /* speed hack for sti 8 */ + FPR(8) /* any FPR */ + FREG(8) /* any allocatable FPR */ FSREG /* any allocatable single-precision FPR */ SPR /* any SPR */ CR /* any CR */ @@ -56,10 +56,10 @@ PROPERTIES CR0 CR1 - FPR0 FPR1 FPR2 FPR3 FPR4 FPR5 FPR6 FPR7 - FPR8 FPR9 FPR10 FPR11 FPR12 FPR13 FPR14 FPR15 - FPR16 FPR17 FPR18 FPR19 FPR20 FPR21 FPR22 FPR23 - FPR24 FPR25 FPR26 FPR27 FPR28 FPR29 FPR30 FPR31 + FPR0(8) FPR1(8) FPR2(8) FPR3(8) FPR4(8) FPR5(8) FPR6(8) FPR7(8) + FPR8(8) FPR9(8) FPR10(8) FPR11(8) FPR12(8) FPR13(8) FPR14(8) FPR15(8) + FPR16(8) FPR17(8) FPR18(8) FPR19(8) FPR20(8) FPR21(8) FPR22(8) FPR23(8) + FPR24(8) FPR25(8) FPR26(8) FPR27(8) FPR28(8) FPR29(8) FPR30(8) FPR31(8) REGISTERS From f64b7d8ea08a91aeb571cf38c919e2c0dd9609f0 Mon Sep 17 00:00:00 2001 From: George Koehler Date: Wed, 25 Jan 2017 19:08:55 -0500 Subject: [PATCH 155/173] Rewrite how PowerPC ncg does conditional branches and tests. The rewritten code rules bring 3 new features: 1. The new rules compare a small constant with a register by reversing the comparison and using `cmpwi` or `cmplwi`. The old rules put the constant in a register. 2. The new rules emit shorter code to yield the test results, without referencing the tables in mach/powerpc/ncg/tge.s. 3. The new rules use the extended `beq` and relatives, not the basic `bc`, in the assembly output. I delete the old tristate tokens and the old moves, because they confused me. Some of the old moves weren't really moves. For example, `move R3, C0` and then `move C0, R0` did not move r3 to r0. I rename C0 to CR0. --- mach/powerpc/ncg/table | 683 +++++++++++++++++++++++++++++------------ 1 file changed, 492 insertions(+), 191 deletions(-) diff --git a/mach/powerpc/ncg/table b/mach/powerpc/ncg/table index 99c2e404c..034c8f32d 100644 --- a/mach/powerpc/ncg/table +++ b/mach/powerpc/ncg/table @@ -27,15 +27,6 @@ PC_OFFSET = 4 /* Offset of saved PC relative to our FP */ #define los(n) (lo(n) | (((0-(lo(n)>>15)) & ~0xFFFF))) #define his(n) ((hi(n) + (lo(n)>>15)) & 0xFFFF) -#define IFFALSE {CONST, 4} -#define IFTRUE {CONST, 12} -#define ALWAYS {CONST, 20} -#define DCTRZ {CONST, 34} - -#define LT {CONST, 0} -#define GT {CONST, 1} -#define EQ {CONST, 2} - PROPERTIES @@ -54,8 +45,6 @@ PROPERTIES GPR16 GPR17 GPR18 GPR19 GPR20 GPR21 GPR22 GPR23 GPR24 GPR25 GPR26 GPR27 GPR28 GPR29 GPR30 GPR31 - CR0 CR1 - FPR0(8) FPR1(8) FPR2(8) FPR3(8) FPR4(8) FPR5(8) FPR6(8) FPR7(8) FPR8(8) FPR9(8) FPR10(8) FPR11(8) FPR12(8) FPR13(8) FPR14(8) FPR15(8) FPR16(8) FPR17(8) FPR18(8) FPR19(8) FPR20(8) FPR21(8) FPR22(8) FPR23(8) @@ -158,7 +147,7 @@ REGISTERS LR("lr") : SPR. CTR("ctr") : SPR. - C0("cr0") : CR, CR0. + CR0("cr0") : CR. #define RSCRATCH R11 #define FSCRATCH F0 @@ -200,13 +189,6 @@ TOKENS SUM_RC = { GPR reg; INT off; } 4. SUM_RR = { GPR reg1; GPR reg2; } 4. - TRISTATE_RC_S = { GPR reg; INT val; } 4. - TRISTATE_RC_U = { GPR reg; INT val; } 4. - TRISTATE_RR_S = { GPR reg1; GPR reg2; } 4. - TRISTATE_RR_U = { GPR reg1; GPR reg2; } 4. - - TRISTATE_FF = { FPR reg1; FPR reg2; } 4. - SEX_B = { GPR reg; } 4. SEX_H = { GPR reg; } 4. @@ -231,6 +213,20 @@ TOKENS XOR_RIS = { GPR reg; INT valhi; } 4. XOR_RC = { GPR reg; INT val; } 4. + COND_RC = { GPR reg; INT val; } 4. + COND_RR = { GPR reg1; GPR reg2; } 4. + CONDL_RC = { GPR reg; INT val; } 4. + CONDL_RR = { GPR reg1; GPR reg2; } 4. + COND_FS = { FSREG reg1; FSREG reg2; } 4. + COND_FD = { FREG reg1; FREG reg2; } 4. + + XEQ = { GPR reg; } 4. + XNE = { GPR reg; } 4. + XGT = { GPR reg; } 4. + XGE = { GPR reg; } 4. + XLT = { GPR reg; } 4. + XLE = { GPR reg; } 4. + SETS @@ -246,9 +242,6 @@ SETS SUM_ALL = SUM_RC + SUM_RR. - TRISTATE_ALL = TRISTATE_RC_S + TRISTATE_RC_U + TRISTATE_RR_S + - TRISTATE_RR_U + TRISTATE_FF. - SEX_ALL = SEX_B + SEX_H. LOGICAL_ALL = NOT_R + AND_RR + OR_RR + OR_RC + XOR_RR + @@ -265,8 +258,7 @@ SETS /* anything killed by sti (store indirect) */ MEMORY = IND_ALL_BHW + IND_ALL_D. - OP_ALL_W = SUM_ALL + TRISTATE_ALL + SEX_ALL + LOGICAL_ALL + - IND_ALL_W. + OP_ALL_W = SUM_ALL + SEX_ALL + LOGICAL_ALL + IND_ALL_W. INSTRUCTIONS @@ -293,14 +285,27 @@ INSTRUCTIONS andisX "andis." GPR:wo:cc, GPR:ro, CONST:ro. b LABEL:ro. bc CONST:ro, CONST:ro, LABEL:ro. + beq LABEL:ro. + bne LABEL:ro. + bgt LABEL:ro. + bge LABEL:ro. + blt LABEL:ro. + ble LABEL:ro. + bxx LABEL:ro. /* dummy */ bcctr CONST:ro, CONST:ro, CONST:ro. + bctr. bcctrl CONST:ro, CONST:ro, CONST:ro. + bctrl. bclr CONST:ro, CONST:ro, CONST:ro. bl LABEL:ro. cmp CR:ro, CONST:ro, GPR:ro, GPR:ro kills :cc. + cmpw GPR:ro, GPR:ro kills :cc. cmpi CR:ro, CONST:ro, GPR:ro, CONST:ro kills :cc. + cmpwi GPR:ro, CONST:ro kills :cc. cmpl CR:ro, CONST:ro, GPR:ro, GPR:ro kills :cc. + cmplw GPR:ro, GPR:ro kills :cc. cmpli CR:ro, CONST:ro, GPR:ro, CONST:ro kills :cc. + cmplwi GPR:ro, CONST:ro kills :cc. divw GPR:wo, GPR:ro, GPR:ro cost(4, 23). divwu GPR:wo, GPR:ro, GPR:ro cost(4, 23). eqv GPR:wo, GPR:ro, GPR:ro. @@ -308,7 +313,8 @@ INSTRUCTIONS extsh GPR:wo, GPR:ro. fadd FREG:wo, FREG:ro, FREG:ro cost(4, 5). fadds FSREG:wo, FSREG:ro, FSREG:ro cost(4, 5). - fcmpo CR:wo, FPR:ro, FPR:ro cost(4, 5). + fcmpo CR:wo, FREG:ro, FREG:ro cost(4, 5). + fcmpo CR:wo, FSREG:ro, FSREG:ro cost(4, 5). fdiv FREG:wo, FREG:ro, FREG:ro cost(4, 35). fdivs FSREG:wo, FSREG:ro, FSREG:ro cost(4, 21). fmr FPR:wo, FPR:ro cost(4, 5). @@ -349,6 +355,8 @@ INSTRUCTIONS oris GPR:wo, GPR:ro, CONST:ro. orX "or." GPR:wo:cc, GPR:ro, GPR:ro. rlwinm GPR:wo, GPR:ro, CONST:ro, CONST:ro, CONST:ro. + extlwi GPR:wo, GPR:ro, CONST:ro, CONST:ro. + extrwi GPR:wo, GPR:ro, CONST:ro, CONST:ro. slw GPR:wo, GPR:ro, GPR:ro. subf GPR:wo, GPR:ro, GPR:ro. sraw GPR:wo, GPR:ro, GPR:ro cost(4, 2). @@ -566,67 +574,6 @@ MOVES COMMENT("move FPR->IND_RR_W") stfdx %1, %2.reg1, %2.reg2 -/* Extract condition code field (actually produces (CC&3)<<2) */ - - from CR0 to GPR - gen - COMMENT("move CR0->GPR") - mfcr %2 - rlwinm %2, %2, {CONST, 4}, {CONST, 32-4}, {CONST, 31-2} - -/* Comparisons */ - - from TRISTATE_RR_S to CR0 - gen - cmp %2, {CONST, 0}, %1.reg1, %1.reg2 - - from TRISTATE_RR_U to CR0 - gen - cmpl %2, {CONST, 0}, %1.reg1, %1.reg2 - - from TRISTATE_RC_S to CR0 - gen - COMMENT("move TRISTATE_RC_S->CR0 large") - move {CONST, %1.val}, RSCRATCH - cmp %2, {CONST, 0}, %1.reg, RSCRATCH - - from TRISTATE_RC_U smallu(%val) to CR0 - gen - COMMENT("move TRISTATE_RC_U->CR0 small") - cmpli %2, {CONST, 0}, %1.reg, {CONST, %1.val} - - from TRISTATE_RC_U to CR0 - gen - COMMENT("move TRISTATE_RC_U->CR0") - move {CONST, %1.val}, RSCRATCH - cmpl %2, {CONST, 0}, %1.reg, RSCRATCH - - from TRISTATE_FF to CR0 - gen - COMMENT("move TRISTATE_FF->CR0") - fcmpo %2, %1.reg1, %1.reg2 - - from GPR to CR0 - gen - COMMENT("move GPR->CR0") - orX RSCRATCH, %1, %1 /* alas, can't call test */ - - from TRISTATE_RR_S + TRISTATE_RC_S + TRISTATE_FF to GPR - gen - COMMENT("move TRISTATE_R*_S->GPR") - move %1, C0 - move C0, RSCRATCH - move {LABEL, ".tristate_s_table"}, %2 - lwzx %2, %2, RSCRATCH - - from TRISTATE_RR_U + TRISTATE_RC_U to GPR - gen - COMMENT("move TRISTATE_R*_U->GPR") - move %1, C0 - move C0, RSCRATCH - move {LABEL, ".tristate_u_table"}, %2 - lwzx %2, %2, RSCRATCH - /* Logicals */ from NOT_R to GPR @@ -669,6 +616,71 @@ MOVES COMMENT("move XOR_RC->GPR") xori %2, %1.reg, {CONST, %1.val} +/* Conditions */ + + /* Compare values, then copy cr0 to GPR. */ + + from COND_RC to GPR + gen + cmpwi %1.reg, {CONST, %1.val} + mfcr %2 + + from COND_RR to GPR + gen + cmpw %1.reg1, %1.reg2 + mfcr %2 + + from CONDL_RC to GPR + gen + cmplwi %1.reg, {CONST, %1.val} + mfcr %2 + + from CONDL_RR to GPR + gen + cmplw %1.reg1, %1.reg2 + mfcr %2 + + from COND_FS to GPR + gen + fcmpo CR0, %1.reg1, %1.reg2 + mfcr %2 + + from COND_FD to GPR + gen + fcmpo CR0, %1.reg1, %1.reg2 + mfcr %2 + + /* Given a copy of cr0 in %1.reg, extract a condition bit + * (lt, gt, eq) and perhaps flip it. + */ + + from XEQ to GPR + gen + extrwi %2, %1.reg, {CONST, 1}, {CONST, 2} + + from XNE to GPR + gen + extrwi %2, %1.reg, {CONST, 1}, {CONST, 2} + xori %2, %2, {CONST, 1} + + from XGT to GPR + gen + extrwi %2, %1.reg, {CONST, 1}, {CONST, 1} + + from XGE to GPR + gen + extrwi %2, %1.reg, {CONST, 1}, {CONST, 0} + xori %2, %2, {CONST, 1} + + from XLT to GPR + gen + extrwi %2, %1.reg, {CONST, 1}, {CONST, 0} + + from XLE to GPR + gen + extrwi %2, %1.reg, {CONST, 1}, {CONST, 1} + xori %2, %2, {CONST, 1} + /* Miscellaneous */ from OP_ALL_W + LABEL + CONST_ALL to GPRE @@ -720,9 +732,9 @@ STACKINGRULES extsh RSCRATCH, %1.reg stwu RSCRATCH, {GPRINDIRECT, SP, 0-4} - from SUM_ALL + TRISTATE_ALL + LOGICAL_ALL to STACK + from SUM_ALL + LOGICAL_ALL to STACK gen - COMMENT("stack SUM_ALL + TRISTATE_ALL + LOGICAL_ALL") + COMMENT("stack SUM_ALL + LOGICAL_ALL") move %1, RSCRATCH stwu RSCRATCH, {GPRINDIRECT, SP, 0-4} @@ -804,7 +816,7 @@ COERCIONS extsh %a, %1.reg yields %a - from SUM_ALL + TRISTATE_ALL + LOGICAL_ALL + from SUM_ALL + LOGICAL_ALL uses REG gen move %1, %a @@ -1683,153 +1695,337 @@ PATTERNS cal ".inn" + /* Boolean resolutions */ pat teq /* top = (top == 0) */ - with TRISTATE_ALL + GPR + with REG uses reusing %1, REG gen - move %1, C0 - move C0, RSCRATCH - move {LABEL, ".teq_table"}, %a - lwzx %a, %a, RSCRATCH + test %1 + mfcr %a + move {XEQ, %a}, %a yields %a pat tne /* top = (top != 0) */ - with TRISTATE_ALL + GPR + with REG uses reusing %1, REG gen - move %1, C0 - move C0, RSCRATCH - move {LABEL, ".tne_table"}, %a - lwzx %a, %a, RSCRATCH + test %1 + mfcr %a + move {XNE, %a}, %a yields %a pat tlt /* top = (top < 0) */ - with TRISTATE_ALL + GPR + with REG uses reusing %1, REG gen - move %1, C0 - move C0, RSCRATCH - move {LABEL, ".tlt_table"}, %a - lwzx %a, %a, RSCRATCH + test %1 + mfcr %a + move {XLT, %a}, %a yields %a pat tle /* top = (top <= 0) */ - with TRISTATE_ALL + GPR + with REG uses reusing %1, REG gen - move %1, C0 - move C0, RSCRATCH - move {LABEL, ".tle_table"}, %a - lwzx %a, %a, RSCRATCH + test %1 + mfcr %a + move {XLE, %a}, %a yields %a pat tgt /* top = (top > 0) */ - with TRISTATE_ALL + GPR + with REG uses reusing %1, REG gen - move %1, C0 - move C0, RSCRATCH - move {LABEL, ".tgt_table"}, %a - lwzx %a, %a, RSCRATCH + test %1 + mfcr %a + move {XGT, %a}, %a yields %a pat tge /* top = (top >= 0) */ - with TRISTATE_ALL + GPR + with REG uses reusing %1, REG gen - move %1, C0 - move C0, RSCRATCH - move {LABEL, ".tge_table"}, %a - lwzx %a, %a, RSCRATCH + test %1 + mfcr %a + move {XGE, %a}, %a yields %a + pat cmi teq $1==4 /* Signed second == top */ + with REG CONST2 + uses reusing %1, REG={COND_RC, %1, %2.val} + gen move {XEQ, %a}, %a + yields %a + with CONST2 REG + uses reusing %1, REG={COND_RC, %2, %1.val} + gen move {XEQ, %a}, %a + yields %a + with REG REG + uses reusing %1, REG={COND_RR, %2, %1} + gen move {XEQ, %a}, %a + yields %a + + pat cmi tne $1==4 /* Signed second != top */ + with REG CONST2 + uses reusing %1, REG={COND_RC, %1, %2.val} + gen move {XNE, %a}, %a + yields %a + with CONST2 REG + uses reusing %1, REG={COND_RC, %2, %1.val} + gen move {XNE, %a}, %a + yields %a + with REG REG + uses reusing %1, REG={COND_RR, %2, %1} + gen move {XNE, %a}, %a + yields %a + + pat cmi tgt $1==4 /* Signed second > top */ + with REG CONST2 + uses reusing %1, REG={COND_RC, %1, %2.val} + gen move {XLT, %a}, %a + yields %a + with CONST2 REG + uses reusing %1, REG={COND_RC, %2, %1.val} + gen move {XGT, %a}, %a + yields %a + with REG REG + uses reusing %1, REG={COND_RR, %2, %1} + gen move {XGT, %a}, %a + yields %a + + pat cmi tge $1==4 /* Signed second >= top */ + with REG CONST2 + uses reusing %1, REG={COND_RC, %1, %2.val} + gen move {XLE, %a}, %a + yields %a + with CONST2 REG + uses reusing %1, REG={COND_RC, %2, %1.val} + gen move {XGE, %a}, %a + yields %a + with REG REG + uses reusing %1, REG={COND_RR, %2, %1} + gen move {XGE, %a}, %a + yields %a + + pat cmi tlt $1==4 /* Signed second < top */ + with REG CONST2 + uses reusing %1, REG={COND_RC, %1, %2.val} + gen move {XGT, %a}, %a + yields %a + with CONST2 REG + uses reusing %1, REG={COND_RC, %2, %1.val} + gen move {XLT, %a}, %a + yields %a + with REG REG + uses reusing %1, REG={COND_RR, %2, %1} + gen move {XLT, %a}, %a + yields %a + + pat cmi tle $1==4 /* Signed second <= top */ + with REG CONST2 + uses reusing %1, REG={COND_RC, %1, %2.val} + gen move {XGE, %a}, %a + yields %a + with CONST2 REG + uses reusing %1, REG={COND_RC, %2, %1.val} + gen move {XLE, %a}, %a + yields %a + with REG REG + uses reusing %1, REG={COND_RR, %2, %1} + gen move {XLE, %a}, %a + yields %a + + pat cmu teq $1==4 /* Unsigned second == top */ + with REG UCONST2 + uses reusing %1, REG={CONDL_RC, %1, %2.val} + gen move {XEQ, %a}, %a + yields %a + with UCONST2 REG + uses reusing %1, REG={CONDL_RC, %2, %1.val} + gen move {XEQ, %a}, %a + yields %a + with REG REG + uses reusing %1, REG={CONDL_RR, %2, %1} + gen move {XEQ, %a}, %a + yields %a + + pat cmu tne $1==4 /* Unsigned second != top */ + with REG UCONST2 + uses reusing %1, REG={CONDL_RC, %1, %2.val} + gen move {XNE, %a}, %a + yields %a + with UCONST2 REG + uses reusing %1, REG={CONDL_RC, %2, %1.val} + gen move {XNE, %a}, %a + yields %a + with REG REG + uses reusing %1, REG={CONDL_RR, %2, %1} + gen move {XNE, %a}, %a + yields %a + + pat cmu tgt $1==4 /* Unsigned second > top */ + with REG UCONST2 + uses reusing %1, REG={CONDL_RC, %1, %2.val} + gen move {XLT, %a}, %a + yields %a + with UCONST2 REG + uses reusing %1, REG={CONDL_RC, %2, %1.val} + gen move {XGT, %a}, %a + yields %a + with REG REG + uses reusing %1, REG={CONDL_RR, %2, %1} + gen move {XGT, %a}, %a + yields %a + + pat cmu tge $1==4 /* Unsigned second >= top */ + with REG UCONST2 + uses reusing %1, REG={CONDL_RC, %1, %2.val} + gen move {XLE, %a}, %a + yields %a + with UCONST2 REG + uses reusing %1, REG={CONDL_RC, %2, %1.val} + gen move {XGE, %a}, %a + yields %a + with REG REG + uses reusing %1, REG={CONDL_RR, %2, %1} + gen move {XGE, %a}, %a + yields %a + + pat cmu tlt $1==4 /* Unsigned second < top */ + with REG UCONST2 + uses reusing %1, REG={CONDL_RC, %1, %2.val} + gen move {XGT, %a}, %a + yields %a + with UCONST2 REG + uses reusing %1, REG={CONDL_RC, %2, %1.val} + gen move {XLT, %a}, %a + yields %a + with REG REG + uses reusing %1, REG={CONDL_RR, %2, %1} + gen move {XLT, %a}, %a + yields %a + + pat cmu tle $1==4 /* Unsigned second <= top */ + with REG UCONST2 + uses reusing %1, REG={CONDL_RC, %1, %2.val} + gen move {XGE, %a}, %a + yields %a + with UCONST2 REG + uses reusing %1, REG={CONDL_RC, %2, %1.val} + gen move {XLE, %a}, %a + yields %a + with REG REG + uses reusing %1, REG={CONDL_RR, %2, %1} + gen move {XLE, %a}, %a + yields %a /* Simple branches */ - pat zeq /* Branch if signed top == 0 */ - with TRISTATE_ALL+GPR STACK + proc zxx example zeq + with REG STACK gen - move %1, C0 - bc IFTRUE, EQ, {LABEL, $1} + test %1 + bxx* {LABEL, $1} - pat beq - leaving - cmi INT32 - zeq $1 + /* Pop signed int, branch if... */ + pat zeq call zxx("beq") /* top == 0 */ + pat zne call zxx("bne") /* top != 0 */ + pat zgt call zxx("bgt") /* top > 0 */ + pat zge call zxx("bge") /* top >= 0 */ + pat zlt call zxx("blt") /* top < 0 */ + pat zle call zxx("ble") /* top >= 0 */ - pat zne /* Branch if signed top != 0 */ - with TRISTATE_ALL+GPR STACK + /* The peephole optimizer rewrites + * cmi 4 zeq + * as beq, and does same for bne, bgt, and so on. + */ + + proc bxx example beq + with REG CONST2 STACK gen - move %1, C0 - bc IFFALSE, EQ, {LABEL, $1} - - pat bne - leaving - cmi INT32 - zne $1 - - pat zgt /* Branch if signed top > 0 */ - with TRISTATE_ALL+GPR STACK + cmpwi %1, {CONST, %2.val} + bxx[2] {LABEL, $1} + with CONST2 REG STACK gen - move %1, C0 - bc IFTRUE, GT, {LABEL, $1} - - pat bgt - leaving - cmi INT32 - zgt $1 - - pat zge /* Branch if signed top >= 0 */ - with TRISTATE_ALL+GPR STACK + cmpwi %2, {CONST, %1.val} + bxx[1] {LABEL, $1} + with REG REG STACK gen - move %1, C0 - bc IFFALSE, LT, {LABEL, $1} + cmpw %2, %1 + bxx[1] {LABEL, $1} - pat bge - leaving - cmi INT32 - zge $1 + /* Pop two signed ints, branch if... */ + pat beq call bxx("beq", "beq") /* second == top */ + pat bne call bxx("bne", "bne") /* second != top */ + pat bgt call bxx("bgt", "blt") /* second > top */ + pat bge call bxx("bge", "ble") /* second >= top */ + pat blt call bxx("blt", "bgt") /* second < top */ + pat ble call bxx("ble", "bge") /* second >= top */ - pat zlt /* Branch if signed top < 0 */ - with TRISTATE_ALL+GPR STACK + proc cmu4zxx example cmu zeq + with REG CONST2 STACK gen - move %1, C0 - bc IFTRUE, LT, {LABEL, $1} - - pat blt - leaving - cmi INT32 - zlt $1 - - pat zle /* Branch if signed top >= 0 */ - with TRISTATE_ALL+GPR STACK + cmplwi %1, {CONST, %2.val} + bxx[2] {LABEL, $2} + with CONST2 REG STACK gen - move %1, C0 - bc IFFALSE, GT, {LABEL, $1} + cmplwi %2, {CONST, %1.val} + bxx[1] {LABEL, $2} + with REG REG STACK + gen + cmplw %2, %1 + bxx[1] {LABEL, $2} - pat ble - leaving - cmi INT32 - zle $1 + /* Pop two unsigned ints, branch if... */ + pat cmu zeq $1==4 call cmu4zxx("beq", "beq") + pat cmu zne $1==4 call cmu4zxx("bne", "bne") + pat cmu zgt $1==4 call cmu4zxx("bgt", "blt") + pat cmu zge $1==4 call cmu4zxx("bge", "ble") + pat cmu zlt $1==4 call cmu4zxx("blt", "bgt") + pat cmu zle $1==4 call cmu4zxx("ble", "bge") -/* Compare and jump */ + +/* Comparisons */ + + /* Each comparison extracts the lt and gt bits from cr0. + * extlwi %a, %a, 2, 0 + * puts lt in the sign bit, so lt yields a negative result, + * gt yields positive. + * rlwinm %a, %a, 1, 31, 0 + * puts gt in the sign bit, to reverse the comparison. + */ pat cmi $1==INT32 /* Signed tristate compare */ - with CONST_ALL GPR - yields {TRISTATE_RC_S, %2, %1.val} - with GPR GPR - yields {TRISTATE_RR_S, %2, %1} + with REG CONST2 + uses reusing %1, REG={COND_RC, %1, %2.val} + gen rlwinm %a, %a, {CONST, 1}, {CONST, 31}, {CONST, 0} + yields %a + with CONST2 REG + uses reusing %2, REG={COND_RC, %2, %1.val} + gen extlwi %a, %a, {CONST, 2}, {CONST, 0} + yields %a + with REG REG + uses reusing %1, REG={COND_RR, %2, %1} + gen extlwi %a, %a, {CONST, 2}, {CONST, 0} + yields %a pat cmu $1==INT32 /* Unsigned tristate compare */ - with CONST_ALL GPR - yields {TRISTATE_RC_U, %2, %1.val} - with GPR GPR - yields {TRISTATE_RR_U, %2, %1} + with REG UCONST2 + uses reusing %1, REG={CONDL_RC, %1, %2.val} + gen rlwinm %a, %a, {CONST, 1}, {CONST, 31}, {CONST, 0} + yields %a + with UCONST2 REG + uses reusing %2, REG={CONDL_RC, %2, %1.val} + gen extlwi %a, %a, {CONST, 2}, {CONST, 0} + yields %a + with REG REG + uses reusing %1, REG={CONDL_RR, %2, %1} + gen extlwi %a, %a, {CONST, 2}, {CONST, 0} + yields %a pat cmp /* Compare pointers */ leaving @@ -1895,7 +2091,7 @@ PATTERNS kills ALL gen mtspr CTR, %1 - bcctrl ALWAYS, {CONST, 0}, {CONST, 0} + bctrl. pat lfr $1==INT32 /* Load function result, word */ yields R3 @@ -2022,7 +2218,7 @@ PATTERNS move {IND_RC_W, %a, 4}, SP move {IND_RC_W, %a, 0}, %a mtspr CTR, %a - bcctr ALWAYS, {CONST, 0}, {CONST, 0} + bctr. pat lor $1==0 /* Load FP */ uses REG @@ -2075,12 +2271,11 @@ PATTERNS pat lae rck $2==4 /* Range check */ with REG - uses CR0 gen - cmpli %a, {CONST, 0}, %1, {CONST, rom($1, 1)} - bc IFTRUE, LT, {LABEL, ".trap_erange"} - cmpli %a, {CONST, 0}, %1, {CONST, rom($1, 2)} - bc IFTRUE, GT, {LABEL, ".trap_erange"} + cmpwi %1, {CONST, rom($1, 1)} + blt {LABEL, ".trap_erange"} + cmpwi %1, {CONST, rom($1, 2)} + bgt {LABEL, ".trap_erange"} yields %1 @@ -2134,7 +2329,60 @@ PATTERNS pat cmf $1==INT32 /* Compare single */ with FSREG FSREG - yields {TRISTATE_FF, %2.1, %1.1} + uses REG={COND_FS, %2, %1} + gen extlwi %a, %a, {CONST, 2}, {CONST, 0} + yields %a + + pat cmf teq $1==4 /* Single second == top */ + with FSREG FSREG + uses REG={COND_FS, %2, %1} + gen move {XEQ, %a}, %a + yields %a + + pat cmf tne $1==4 /* Single second == top */ + with FSREG FSREG + uses REG={COND_FS, %2, %1} + gen move {XNE, %a}, %a + yields %a + + pat cmf tgt $1==4 /* Single second > top */ + with FSREG FSREG + uses REG={COND_FS, %2, %1} + gen move {XGT, %a}, %a + yields %a + + pat cmf tge $1==4 /* Single second >= top */ + with FSREG FSREG + uses REG={COND_FS, %2, %1} + gen move {XGE, %a}, %a + yields %a + + pat cmf tlt $1==4 /* Single second < top */ + with FSREG FSREG + uses REG={COND_FS, %2, %1} + gen move {XLT, %a}, %a + yields %a + + pat cmf tle $1==4 /* Single second <= top */ + with FSREG FSREG + uses REG={COND_FS, %2, %1} + gen move {XLE, %a}, %a + yields %a + + proc cmf4zxx example cmf zeq + with FREG FREG STACK + uses REG + gen + fcmpo CR0, %2, %1 + bxx* {LABEL, $2} + + /* Pop 2 singles, branch if... */ + pat cmf zeq $1==4 call cmf4zxx("beq") + pat cmf zne $1==4 call cmf4zxx("bne") + pat cmf zgt $1==4 call cmf4zxx("bgt") + pat cmf zge $1==4 call cmf4zxx("bge") + pat cmf zlt $1==4 call cmf4zxx("blt") + pat cmf zle $1==4 call cmf4zxx("ble") pat loc loc cff $1==INT32 && $2==INT64 /* Convert single to double */ with FSREG @@ -2208,7 +2456,60 @@ PATTERNS pat cmf $1==INT64 /* Compare double */ with FREG FREG - yields {TRISTATE_FF, %2, %1} + uses REG={COND_FD, %2, %1} + gen extlwi %a, %a, {CONST, 2}, {CONST, 0} + yields %a + + pat cmf teq $1==8 /* Double second == top */ + with FREG FREG + uses REG={COND_FD, %2, %1} + gen move {XEQ, %a}, %a + yields %a + + pat cmf tne $1==8 /* Single second == top */ + with FREG FREG + uses REG={COND_FD, %2, %1} + gen move {XNE, %a}, %a + yields %a + + pat cmf tgt $1==8 /* Double second > top */ + with FREG FREG + uses REG={COND_FD, %2, %1} + gen move {XGT, %a}, %a + yields %a + + pat cmf tge $1==8 /* Double second >= top */ + with FREG FREG + uses REG={COND_FD, %2, %1} + gen move {XGE, %a}, %a + yields %a + + pat cmf tlt $1==8 /* Double second < top */ + with FREG FREG + uses REG={COND_FD, %2, %1} + gen move {XLT, %a}, %a + yields %a + + pat cmf tle $1==8 /* Double second <= top */ + with FREG FREG + uses REG={COND_FD, %2, %1} + gen move {XLE, %a}, %a + yields %a + + proc cmf8zxx example cmf zeq + with FREG FREG STACK + uses REG + gen + fcmpo CR0, %2, %1 + bxx* {LABEL, $2} + + /* Pop 2 doubles, branch if... */ + pat cmf zeq $1==8 call cmf8zxx("beq") + pat cmf zne $1==8 call cmf8zxx("bne") + pat cmf zgt $1==8 call cmf8zxx("bgt") + pat cmf zge $1==8 call cmf8zxx("bge") + pat cmf zlt $1==8 call cmf8zxx("blt") + pat cmf zle $1==8 call cmf8zxx("ble") pat loc loc cff $1==INT64 && $2==INT32 /* Convert double to single */ with FREG From 8c8f291a073e7be90678a2e6584a7c031d6eda23 Mon Sep 17 00:00:00 2001 From: George Koehler Date: Thu, 26 Jan 2017 12:39:16 -0500 Subject: [PATCH 156/173] In PowerPC libem, remove tge.s and powerpc.h Nothing uses the tables in tge.s, after I changed the ncg table. There are no *.e files in libem, so don't try to build them. --- mach/powerpc/libem/build.lua | 4 +--- mach/powerpc/libem/powerpc.h | 22 ----------------- mach/powerpc/libem/tge.s | 46 ------------------------------------ 3 files changed, 1 insertion(+), 71 deletions(-) delete mode 100644 mach/powerpc/libem/powerpc.h delete mode 100644 mach/powerpc/libem/tge.s diff --git a/mach/powerpc/libem/build.lua b/mach/powerpc/libem/build.lua index 786be4e11..466a28fb3 100644 --- a/mach/powerpc/libem/build.lua +++ b/mach/powerpc/libem/build.lua @@ -1,14 +1,12 @@ for _, plat in ipairs(vars.plats) do acklibrary { name = "headers_"..plat, - hdrs = { "./*.h" } } acklibrary { name = "lib_"..plat, srcs = { - "./*.s", -- zer.s - "./*.e", + "./*.s", }, vars = { plat = plat }, deps = { diff --git a/mach/powerpc/libem/powerpc.h b/mach/powerpc/libem/powerpc.h deleted file mode 100644 index 3540a6856..000000000 --- a/mach/powerpc/libem/powerpc.h +++ /dev/null @@ -1,22 +0,0 @@ -# -! $Source$ -! $State$ -! $Revision$ - -! Declare segments (the order is important). - -.sect .text -.sect .rom -.sect .data -.sect .bss - -#define IFFALSE 4 -#define IFTRUE 12 -#define ALWAYS 20 -#define DNZ 16 - -#define LT 0 -#define GT 1 -#define EQ 2 -#define OV 3 - diff --git a/mach/powerpc/libem/tge.s b/mach/powerpc/libem/tge.s deleted file mode 100644 index 4740d8436..000000000 --- a/mach/powerpc/libem/tge.s +++ /dev/null @@ -1,46 +0,0 @@ -# -! $Source$ -! $State$ -! $Revision$ - -#include "powerpc.h" - -.sect .rom - -! Lookup table for tge. - -.define .teq_table -.teq_table: - .data4 1 ! . . - .data4 0 ! . G - .data4 0 ! L . - -.define .tne_table -.tne_table: - .data4 0 ! . . - .data4 1 ! . G - .data4 1 ! L . - -.define .tgt_table -.tgt_table: - .data4 0 ! . . - .data4 1 ! . G - .data4 0 ! L . - -.define .tge_table -.tge_table: - .data4 1 ! . . - .data4 1 ! . G - .data4 0 ! L . - -.define .tlt_table -.tlt_table: - .data4 0 ! . . - .data4 0 ! . G - .data4 1 ! L . - -.define .tle_table -.tle_table: - .data4 1 ! . . - .data4 0 ! . G - .data4 1 ! L . From 1dfd5524e4c5691916a27e1fc5d84dd4b20e8c09 Mon Sep 17 00:00:00 2001 From: George Koehler Date: Thu, 26 Jan 2017 12:44:32 -0500 Subject: [PATCH 157/173] In PowerPC top, don't delete addi r0, r0, 0 Also don't delete addis r0, r0, 0. These instructions are special cases that set r0 to zero. If we delete them, then r0 keeps its old value. I caught this bug because osxppc protects the .text segment against writing. (linuxppc doesn't protect it.) A program tried to set r0 to the NULL pointer, but top deleted the instruction, so r0 kept an old return address pointing into .text. Later the program checked that r0 wasn't NULL, tried to write to address r0, and crashed. --- mach/powerpc/top/table | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/mach/powerpc/top/table b/mach/powerpc/top/table index acbe543a7..fdec03b2e 100644 --- a/mach/powerpc/top/table +++ b/mach/powerpc/top/table @@ -6,15 +6,15 @@ LABEL_STARTER '.'; %%; -P, Q, R { TRUE }; +RNZ { strcmp(VAL, "r0") }; /* not r0 */ X, Y, Z { TRUE }; %%; /* Whitespace is significant here! */ -addi X, X, 0 -> ; -addis X, X, 0 -> ; +addi RNZ, RNZ, 0 -> ; +addis RNZ, RNZ, 0 -> ; mr X, X -> ; fmr X, X -> ; From c41688929c7450399451c585f1dad734eed2b158 Mon Sep 17 00:00:00 2001 From: George Koehler Date: Thu, 26 Jan 2017 13:10:08 -0500 Subject: [PATCH 158/173] In PowerPC ncg, switch the scratch register from r11 to r0. r0 is a special case and can't be used when adding a register to a constant. The few remaining users of the scratch register don't do that. I removed other usages of the scratch register in 7c64dab, 5b5f774, 19f0eb8, f64b7d8. --- mach/powerpc/ncg/table | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/mach/powerpc/ncg/table b/mach/powerpc/ncg/table index 034c8f32d..7cc4bbbca 100644 --- a/mach/powerpc/ncg/table +++ b/mach/powerpc/ncg/table @@ -10,7 +10,7 @@ INT64 = 8 FP_OFFSET = 0 /* Offset of saved FP relative to our FP */ PC_OFFSET = 4 /* Offset of saved PC relative to our FP */ -#define COMMENT(n) /* comment {LABEL, n} */ +#define COMMENT(n) comment {LABEL, n} #define nicesize(x) ((x)==INT8 || (x)==INT16 || (x)==INT32 || (x)==INT64) @@ -74,7 +74,7 @@ REGISTERS R14("r14") : GPR, REG, GPR14 regvar. R13("r13") : GPR, REG, GPR13 regvar. R12("r12") : GPR, REG, GPR12. - R11("r11") : GPR, GPR11. + R11("r11") : GPR, REG, GPR11. R10("r10") : GPR, REG, GPR10. R9("r9") : GPR, REG, GPR9. R8("r8") : GPR, REG, GPR8. @@ -149,7 +149,7 @@ REGISTERS CTR("ctr") : SPR. CR0("cr0") : CR. -#define RSCRATCH R11 +#define RSCRATCH R0 #define FSCRATCH F0 From 9ddbb66c8b0c53738d3d9607aa584a91412acd81 Mon Sep 17 00:00:00 2001 From: George Koehler Date: Mon, 30 Jan 2017 15:45:46 -0500 Subject: [PATCH 159/173] Turn off comments again. I turned them on by accident in c416889. --- mach/powerpc/ncg/table | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mach/powerpc/ncg/table b/mach/powerpc/ncg/table index 7cc4bbbca..e76cadb33 100644 --- a/mach/powerpc/ncg/table +++ b/mach/powerpc/ncg/table @@ -10,7 +10,7 @@ INT64 = 8 FP_OFFSET = 0 /* Offset of saved FP relative to our FP */ PC_OFFSET = 4 /* Offset of saved PC relative to our FP */ -#define COMMENT(n) comment {LABEL, n} +#define COMMENT(n) /* comment {LABEL, n} */ #define nicesize(x) ((x)==INT8 || (x)==INT16 || (x)==INT32 || (x)==INT64) From 48e3aab72858159e9537de9655bab8d6a0a9d97c Mon Sep 17 00:00:00 2001 From: George Koehler Date: Mon, 30 Jan 2017 15:47:09 -0500 Subject: [PATCH 160/173] Swap RA and RS when assembling "and", "or", and such instructions. They must use OP_RA_RS_RB_C instead of OP_RS_RA_RB_C. The code generator often sets RS and RA to the same register, so swapping them causes no change in many programs. I also rename OP_RS_RA_UI_CC to OP_RA_RS_UI_CC, and OP_RS_RA_C to OP_RA_RS_C, because they already swap RA and RS. --- mach/powerpc/as/mach2.c | 6 +++--- mach/powerpc/as/mach3.c | 38 +++++++++++++++++++------------------- mach/powerpc/as/mach4.c | 6 +++--- 3 files changed, 25 insertions(+), 25 deletions(-) diff --git a/mach/powerpc/as/mach2.c b/mach/powerpc/as/mach2.c index 555b92c38..4065334e6 100644 --- a/mach/powerpc/as/mach2.c +++ b/mach/powerpc/as/mach2.c @@ -51,6 +51,7 @@ %token OP_LIA %token OP_LIL %token OP_LI32 +%token OP_RA_RS_C %token OP_RA_RS_RB_C %token OP_RA_RS_RB_MB5_ME5_C %token OP_RA_RS_RB_MB6_C @@ -58,17 +59,16 @@ %token OP_RA_RS_SH5_MB5_ME5_C %token OP_RA_RS_SH6_C %token OP_RA_RS_SH6_MB6_C +%token OP_RA_RS_UI +%token OP_RA_RS_UI_CC %token OP_RS_FXM %token OP_RS_RA -%token OP_RS_RA_C %token OP_RS_RA_D %token OP_RS_RA_DS %token OP_RS_RA_NB %token OP_RS_RA_RB %token OP_RS_RA_RB_C %token OP_RS_RA_RA_C -%token OP_RS_RA_UI -%token OP_RS_RA_UI_CC %token OP_RS_RB %token OP_RS_SPR %token OP_RS_SR diff --git a/mach/powerpc/as/mach3.c b/mach/powerpc/as/mach3.c index 16c1e6ae0..91b088a6a 100644 --- a/mach/powerpc/as/mach3.c +++ b/mach/powerpc/as/mach3.c @@ -498,25 +498,25 @@ 0, OP_TOX_RA_SI, 3<<26 | 31<<21, "twui", /* page 62 */ -0, OP_RS_RA_UI_CC, 28<<26, "andi", /* C compulsory */ -0, OP_RS_RA_UI_CC, 29<<26, "andis", /* C compulsory */ -0, OP_RS_RA_UI, 24<<26, "ori", -0, OP_RS_RA_UI, 25<<26, "oris", -0, OP_RS_RA_UI, 26<<26, "xori", -0, OP_RS_RA_UI, 27<<26, "xoris", -0, OP_RS_RA_RB_C, 31<<26 | 28<<1, "and", -0, OP_RS_RA_RB_C, 31<<26 | 444<<1, "or", -0, OP_RS_RA_RB_C, 31<<26 | 316<<1, "xor", -0, OP_RS_RA_RB_C, 31<<26 | 476<<1, "nand", -0, OP_RS_RA_RB_C, 31<<26 | 124<<1, "nor", -0, OP_RS_RA_RB_C, 31<<26 | 284<<1, "eqv", -0, OP_RS_RA_RB_C, 31<<26 | 60<<1, "andc", -0, OP_RS_RA_RB_C, 31<<26 | 412<<1, "orc", -0, OP_RS_RA_C, 31<<26 | 954<<1, "extsb", -0, OP_RS_RA_C, 31<<26 | 922<<1, "extsh", -0, OP_RS_RA_C, 31<<26 | 986<<1, "extsw", -0, OP_RS_RA_C, 31<<26 | 58<<1, "cntlzd", -0, OP_RS_RA_C, 31<<26 | 26<<1, "cntlzw", +0, OP_RA_RS_UI_CC, 28<<26, "andi", /* C compulsory */ +0, OP_RA_RS_UI_CC, 29<<26, "andis", /* C compulsory */ +0, OP_RA_RS_UI, 24<<26, "ori", +0, OP_RA_RS_UI, 25<<26, "oris", +0, OP_RA_RS_UI, 26<<26, "xori", +0, OP_RA_RS_UI, 27<<26, "xoris", +0, OP_RA_RS_RB_C, 31<<26 | 28<<1, "and", +0, OP_RA_RS_RB_C, 31<<26 | 444<<1, "or", +0, OP_RA_RS_RB_C, 31<<26 | 316<<1, "xor", +0, OP_RA_RS_RB_C, 31<<26 | 476<<1, "nand", +0, OP_RA_RS_RB_C, 31<<26 | 124<<1, "nor", +0, OP_RA_RS_RB_C, 31<<26 | 284<<1, "eqv", +0, OP_RA_RS_RB_C, 31<<26 | 60<<1, "andc", +0, OP_RA_RS_RB_C, 31<<26 | 412<<1, "orc", +0, OP_RA_RS_C, 31<<26 | 954<<1, "extsb", +0, OP_RA_RS_C, 31<<26 | 922<<1, "extsh", +0, OP_RA_RS_C, 31<<26 | 986<<1, "extsw", +0, OP_RA_RS_C, 31<<26 | 58<<1, "cntlzd", +0, OP_RA_RS_C, 31<<26 | 26<<1, "cntlzw", /* extended m using logic */ 0, OP_RS_RA_RA_C, 31<<26 | 444<<1, "mr", diff --git a/mach/powerpc/as/mach4.c b/mach/powerpc/as/mach4.c index 99f7f4537..7fca36e42 100644 --- a/mach/powerpc/as/mach4.c +++ b/mach/powerpc/as/mach4.c @@ -42,6 +42,7 @@ operation | OP_FRT_RA_D FPR ',' e16 '(' GPR ')' { emit4($1 | ($2<<21) | ($6<<16) | $4); } | OP_FRT_RA_RB FPR ',' GPR ',' GPR { emit4($1 | ($2<<21) | ($4<<16) | ($6<<11)); } | OP_FRT_C c FPR { emit4($1 | $2 | ($3<<21)); } + | OP_RA_RS_C c GPR ',' GPR { emit4($1 | $2 | ($5<<21) | ($3<<16)); } | OP_RA_RS_RB_C c GPR ',' GPR ',' GPR { emit4($1 | $2 | ($5<<21) | ($3<<16) | ($7<<11)); } | OP_RA_RS_RB_MB5_ME5_C c GPR ',' GPR ',' GPR ',' u5 ',' u5 @@ -58,6 +59,8 @@ operation { emit4($1 | $2 | ($5<<21) | ($3<<16) | SH6($7)); } | OP_RA_RS_SH6_MB6_C c GPR ',' GPR ',' u6 ',' u6 { emit4($1 | $2 | ($5<<21) | ($3<<16) | SH6($7) | MB6($9)); } + | OP_RA_RS_UI GPR ',' GPR ',' e16 { emit4($1 | ($4<<21) | ($2<<16) | $6); } + | OP_RA_RS_UI_CC C GPR ',' GPR ',' e16 { emit4($1 | ($5<<21) | ($3<<16) | $7); } | OP_RT GPR { emit4($1 | ($2<<21)); } | OP_RT_RA_C c GPR ',' GPR { emit4($1 | $2 | ($3<<21) | ($5<<16)); } | OP_RT_RA_D GPR ',' e16 '(' GPR ')' { emit4($1 | ($2<<21) | ($6<<16) | $4); } @@ -73,12 +76,9 @@ operation | OP_RT_SI GPR ',' e16 { emit4($1 | ($2<<21) | $4); } | OP_RT_SPR GPR ',' spr_num { emit4($1 | ($2<<21) | ($4<<11)); } | OP_RS_FXM u7 ',' GPR { emit4($1 | ($4<<21) | ($2<<12)); } - | OP_RS_RA_C c GPR ',' GPR { emit4($1 | $2 | ($5<<21) | ($3<<16)); } | OP_RS_RA_D GPR ',' e16 '(' GPR ')' { emit4($1 | ($2<<21) | ($6<<16) | $4); } | OP_RS_RA_DS GPR ',' ds '(' GPR ')' { emit4($1 | ($2<<21) | ($6<<16) | $4); } | OP_RS_RA_NB GPR ',' GPR ',' nb { emit4($1 | ($2<<21) | ($4<<16) | ($6<<11)); } - | OP_RS_RA_UI GPR ',' GPR ',' e16 { emit4($1 | ($4<<21) | ($2<<16) | $6); } - | OP_RS_RA_UI_CC C GPR ',' GPR ',' e16 { emit4($1 | ($5<<21) | ($3<<16) | $7); } | OP_RS_RA_RB GPR ',' GPR ',' GPR { emit4($1 | ($2<<21) | ($4<<16) | ($6<<11)); } | OP_RS_RA_RB_C c GPR ',' GPR ',' GPR { emit4($1 | $2 | ($5<<21) | ($3<<16) | ($7<<11)); } | OP_RS_RA_RA_C c GPR ',' GPR { emit4($1 | $2 | ($5<<21) | ($3<<16) | ($5<<11)); } From 3c1d2d79f0817602ac5aa8e8ee7069960d90cc6d Mon Sep 17 00:00:00 2001 From: George Koehler Date: Mon, 30 Jan 2017 16:15:02 -0500 Subject: [PATCH 161/173] Remove type quad, use type word_t in PowerPC as. Type word_t is for encoding the machine instructions. It only needs 32 bits for PowerPC. It was long (which can have 32 or 64 bits), and there was a second type quad (which was uint32_t). Switch word_t to uint32_t and replace quad with word_t. Also change valu_t and ADDR_T away from long. --- mach/powerpc/as/mach0.c | 8 +++---- mach/powerpc/as/mach1.c | 4 ++-- mach/powerpc/as/mach4.c | 46 ++++++++++++++++++++--------------------- mach/powerpc/as/mach5.c | 12 +++++------ 4 files changed, 34 insertions(+), 36 deletions(-) diff --git a/mach/powerpc/as/mach0.c b/mach/powerpc/as/mach0.c index 3246828fc..1c2051753 100644 --- a/mach/powerpc/as/mach0.c +++ b/mach/powerpc/as/mach0.c @@ -11,15 +11,13 @@ #define DEBUG 0 #undef valu_t -#define valu_t long +#define valu_t int32_t #undef ADDR_T -#define ADDR_T long +#define ADDR_T uint32_t #undef word_t -#define word_t long - -typedef uint32_t quad; +#define word_t uint32_t #undef ALIGNWORD #define ALIGNWORD 4 diff --git a/mach/powerpc/as/mach1.c b/mach/powerpc/as/mach1.c index c1651fcfe..a1977f466 100644 --- a/mach/powerpc/as/mach1.c +++ b/mach/powerpc/as/mach1.c @@ -5,5 +5,5 @@ #include -extern quad emit_hi(struct expr_t* expr, bool is_signed); -extern quad emit_lo(struct expr_t* expr); +extern word_t emit_hi(struct expr_t* expr, bool is_signed); +extern word_t emit_lo(struct expr_t* expr); diff --git a/mach/powerpc/as/mach4.c b/mach/powerpc/as/mach4.c index 7fca36e42..7464dcb6a 100644 --- a/mach/powerpc/as/mach4.c +++ b/mach/powerpc/as/mach4.c @@ -94,7 +94,7 @@ operation | OP_LI32 li32 /* emitted in subrule */ | OP_clrlsldi c GPR ',' GPR ',' u6 ',' u6 { - quad mb = ($7 - $9) & 0x3f; + word_t mb = ($7 - $9) & 0x3f; fit($9 <= $7); emit4($1 | $2 | ($5<<21) | ($3<<16) | SH6($9) | MB6(mb)); } @@ -104,41 +104,41 @@ operation } | OP_clrrdi c GPR ',' GPR ',' u6 { - quad me = 63 - $7; + word_t me = 63 - $7; emit4($1 | $2 | ($5<<21) | ($3<<16) | SH6(0) | MB6(me)); } | OP_extldi c GPR ',' GPR ',' u6 ',' u6 { - quad me = ($7 - 1) & 0x3f; + word_t me = ($7 - 1) & 0x3f; fit($7 > 0); emit4($1 | $2 | ($5<<21) | ($3<<16) | SH6($9) | MB6(me)); } | OP_extrdi c GPR ',' GPR ',' u6 ',' u6 { - quad sh = ($9 + $7) & 0x3f; - quad mb = (64 - $7) & 0x3f; + word_t sh = ($9 + $7) & 0x3f; + word_t mb = (64 - $7) & 0x3f; fit($7 > 0); emit4($1 | $2 | ($5<<21) | ($3<<16) | SH6(sh) | MB6(mb)); } | OP_rotrdi c GPR ',' GPR ',' u6 { - quad sh = (64 - $7) & 0x3f; + word_t sh = (64 - $7) & 0x3f; emit4($1 | $2 | ($5<<21) | ($3<<16) | SH6(sh) | MB6(0)); } | OP_sldi c GPR ',' GPR ',' u6 { - quad me = 63 - $7; + word_t me = 63 - $7; emit4($1 | $2 | ($5<<21) | ($3<<16) | SH6($7) | MB6(me)); } | OP_srdi c GPR ',' GPR ',' u6 { - quad sh = (64 - $7) & 0x3f; + word_t sh = (64 - $7) & 0x3f; emit4($1 | $2 | ($5<<21) | ($3<<16) | SH6(sh) | MB6($7)); } | OP_clrlslwi c GPR ',' GPR ',' u5 ',' u5 { - quad mb = ($7 - $9) & 0x1f; - quad me = 31 - $9; + word_t mb = ($7 - $9) & 0x1f; + word_t me = 31 - $9; fit($9 <= $7); emit4($1 | $2 | ($5<<21) | ($3<<16) | ($9<<11) | (mb<<6) | (me<<1)); @@ -150,56 +150,56 @@ operation } | OP_clrrwi c GPR ',' GPR ',' u5 { - quad me = 31 - $7; + word_t me = 31 - $7; emit4($1 | $2 | ($5<<21) | ($3<<16) | (0<<11) | (0<<6) | (me<<1)); } | OP_extlwi c GPR ',' GPR ',' u5 ',' u5 { - quad me = ($7 - 1) & 0x1f; + word_t me = ($7 - 1) & 0x1f; fit($7 > 0); emit4($1 | $2 | ($5<<21) | ($3<<16) | ($9<<11) | (0<<6) | (me<<1)); } | OP_extrwi c GPR ',' GPR ',' u5 ',' u5 { - quad sh = ($9 + $7) & 0x1f; - quad mb = (32 - $7) & 0x1f; + word_t sh = ($9 + $7) & 0x1f; + word_t mb = (32 - $7) & 0x1f; fit($7 > 0); emit4($1 | $2 | ($5<<21) | ($3<<16) | (sh<<11) | (mb<<6) | (31<<1)); } | OP_inslwi c GPR ',' GPR ',' u5 ',' u5 { - quad sh = (32 - $9) & 0x1f; - quad me = ($9 + $7 - 1) & 0x1f; + word_t sh = (32 - $9) & 0x1f; + word_t me = ($9 + $7 - 1) & 0x1f; fit($7 > 0); emit4($1 | $2 | ($5<<21) | ($3<<16) | (sh<<11) | ($9<<6) | (me<<1)); } | OP_insrwi c GPR ',' GPR ',' u5 ',' u5 { - quad sh = (32 - $9 - $7) & 0x1f; - quad me = ($9 + $7 - 1) & 0x1f; + word_t sh = (32 - $9 - $7) & 0x1f; + word_t me = ($9 + $7 - 1) & 0x1f; fit($7 > 0); emit4($1 | $2 | ($5<<21) | ($3<<16) | (sh<<11) | ($9<<6) | (me<<1)); } | OP_rotrwi c GPR ',' GPR ',' u5 { - quad sh = (32 - $7) & 0x1f; + word_t sh = (32 - $7) & 0x1f; emit4($1 | $2 | ($5<<21) | ($3<<16) | (sh<<11) | (0<<6) | (31<<1)); } | OP_slwi c GPR ',' GPR ',' u5 { - quad me = 31 - $7; + word_t me = 31 - $7; emit4($1 | $2 | ($5<<21) | ($3<<16) | ($7<<11) | (0<<6) | (me<<1)); } | OP_srwi c GPR ',' GPR ',' u5 { - quad sh = (32 - $7) & 0x1f; + word_t sh = (32 - $7) & 0x1f; emit4($1 | $2 | ($5<<21) | ($3<<16) | (sh<<11) | ($7<<6) | (31<<1)); } @@ -367,8 +367,8 @@ bda li32 : GPR ',' expr { - quad type = $3.typ & S_TYP; - quad val = $3.val; + word_t type = $3.typ & S_TYP; + word_t val = $3.val; if ((type == S_ABS) && (val <= 0xffff)) emit4((14<<26) | ($1<<21) | (0<<16) | val); /* addi */ else diff --git a/mach/powerpc/as/mach5.c b/mach/powerpc/as/mach5.c index e3e23f272..87d514053 100644 --- a/mach/powerpc/as/mach5.c +++ b/mach/powerpc/as/mach5.c @@ -1,10 +1,10 @@ -quad emit_hi(struct expr_t* expr, bool is_signed) +word_t emit_hi(struct expr_t* expr, bool is_signed) { /* If this is a symbol reference, discard the symbol and keep only the * offset part. */ - quad type = expr->typ & S_TYP; - quad val = expr->val; + word_t type = expr->typ & S_TYP; + word_t val = expr->val; uint16_t hi = val >> 16; uint16_t lo = val & 0xffff; @@ -23,10 +23,10 @@ quad emit_hi(struct expr_t* expr, bool is_signed) return hi; } -quad emit_lo(struct expr_t* expr) +word_t emit_lo(struct expr_t* expr) { - quad type = expr->typ & S_TYP; - quad val = expr->val; + word_t type = expr->typ & S_TYP; + word_t val = expr->val; /* If the assembler stored a symbol for relocation later, we need to * abandon it (because the relocation was generated by emit_ha). */ From f4cfbedd5c74e82494770afd62f9fe22e1cba8c7 Mon Sep 17 00:00:00 2001 From: George Koehler Date: Mon, 30 Jan 2017 16:39:23 -0500 Subject: [PATCH 162/173] Remove #include from mach/powerpc/as/mach1.c We should not include a system header file here, because mach/proto/as/comm2.y goes through cpp twice. The include can cause problems like https://github.com/davidgiven/ack/issues/1 Remove this include # and leave a comment pointing to the includes in comm0.h. Change the few instances of bool, false, true, to int, 0, 1. --- mach/powerpc/as/mach1.c | 6 ++++-- mach/powerpc/as/mach4.c | 4 ++-- mach/powerpc/as/mach5.c | 2 +- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/mach/powerpc/as/mach1.c b/mach/powerpc/as/mach1.c index a1977f466..44b415ff8 100644 --- a/mach/powerpc/as/mach1.c +++ b/mach/powerpc/as/mach1.c @@ -3,7 +3,9 @@ * $State$ */ -#include +/* + * Do not #include anything here. Do it in mach/proto/as/comm0.h + */ -extern word_t emit_hi(struct expr_t* expr, bool is_signed); +extern word_t emit_hi(struct expr_t* expr, int is_signed); extern word_t emit_lo(struct expr_t* expr); diff --git a/mach/powerpc/as/mach4.c b/mach/powerpc/as/mach4.c index 7464dcb6a..640573fa1 100644 --- a/mach/powerpc/as/mach4.c +++ b/mach/powerpc/as/mach4.c @@ -218,8 +218,8 @@ e16 serror("16-bit value out of range"); $$ = (uint16_t) $1; } - | OP_HI ASC_LPAR expr ASC_RPAR { $$ = emit_hi(&$3, false); } - | OP_HA ASC_LPAR expr ASC_RPAR { $$ = emit_hi(&$3, true); } + | OP_HI ASC_LPAR expr ASC_RPAR { $$ = emit_hi(&$3, 0); } + | OP_HA ASC_LPAR expr ASC_RPAR { $$ = emit_hi(&$3, 1); } | OP_LO ASC_LPAR expr ASC_RPAR { $$ = emit_lo(&$3); } ; diff --git a/mach/powerpc/as/mach5.c b/mach/powerpc/as/mach5.c index 87d514053..47460790c 100644 --- a/mach/powerpc/as/mach5.c +++ b/mach/powerpc/as/mach5.c @@ -1,5 +1,5 @@ -word_t emit_hi(struct expr_t* expr, bool is_signed) +word_t emit_hi(struct expr_t* expr, int is_signed) { /* If this is a symbol reference, discard the symbol and keep only the * offset part. */ From 1bf58cf51c9bff076485e249ef5b708483055b4a Mon Sep 17 00:00:00 2001 From: George Koehler Date: Wed, 8 Feb 2017 11:46:31 -0500 Subject: [PATCH 163/173] Add RELOLIS for PowerPC lis with ha16 or hi16. The new relocation type RELOLIS handles these instructions: lis RT, ha16[expr] == addis RT, r0, ha16[expr] lis RT, hi16[expr] == addis RT, r0, hi16[expr] RELOLIS stores a 32-bit value in the program text. In this value, the high bit is a ha16 flag, the next 5 bits are the target register RT, and the low bits are a signed 26-bit offset. The linker replaces this value with the lis instruction. The old RELOPPC relocated a ha16/lo16 or hi16/lo16 pair. The new RELOLIS relocates only a ha16 or hi16, so it is no longer necessary to have a matching lo16 in the next instruction. The disadvantage is that RELOLIS has only a signed 26-bit offset, not a 32-bit offset. Switch the assembler to use RELOLIS for ha16 or hi16 and RELO2 for lo16. The li32 instruction still uses the old RELOPPC relocation. This is not the same as my RELOPPC change from my recent mail to tack-devel (https://sourceforge.net/p/tack/mailman/message/35651528/). This commit is on a different branch. Here I am throwing away my RELOPPC change and instead trying RELOLIS. --- h/out.h | 6 +-- mach/powerpc/as/mach1.c | 5 ++- mach/powerpc/as/mach4.c | 41 ++++++++--------- mach/powerpc/as/mach5.c | 99 ++++++++++++++++++++++++++++------------- util/amisc/ashow.c | 3 ++ util/led/relocate.c | 48 ++++++++++++++++++-- 6 files changed, 142 insertions(+), 60 deletions(-) diff --git a/h/out.h b/h/out.h index 45289f313..6aeffc446 100644 --- a/h/out.h +++ b/h/out.h @@ -65,9 +65,9 @@ struct outname { #define RELO1 1 /* 1 byte */ #define RELO2 2 /* 2 bytes */ #define RELO4 3 /* 4 bytes */ -#define RELOPPC 4 /* PowerPC 26-bit address */ -/* relo 5 is unused */ -#define RELOVC4 6 /* VideoCore IV address in 32-bit instruction */ +#define RELOPPC 4 /* PowerPC 26-bit address */ +#define RELOLIS 5 /* PowerPC lis */ +#define RELOVC4 6 /* VideoCore IV address in 32-bit instruction */ #define RELPC 0x2000 /* pc relative */ #define RELBR 0x4000 /* High order byte lowest address. */ diff --git a/mach/powerpc/as/mach1.c b/mach/powerpc/as/mach1.c index 44b415ff8..50f799684 100644 --- a/mach/powerpc/as/mach1.c +++ b/mach/powerpc/as/mach1.c @@ -7,5 +7,6 @@ * Do not #include anything here. Do it in mach/proto/as/comm0.h */ -extern word_t emit_hi(struct expr_t* expr, int is_signed); -extern word_t emit_lo(struct expr_t* expr); +void no_hl(void); +word_t eval_hl(struct expr_t* expr, int token); +void emit_hl(word_t in); diff --git a/mach/powerpc/as/mach4.c b/mach/powerpc/as/mach4.c index 640573fa1..8a0cca9de 100644 --- a/mach/powerpc/as/mach4.c +++ b/mach/powerpc/as/mach4.c @@ -10,11 +10,11 @@ operation | OP_BF_BFA CR ',' CR { emit4($1 | ($2<<23) | ($4<<18)); } | OP_BF_FRA_FRB CR ',' FPR ',' FPR { emit4($1 | ($2<<23) | ($4<<16) | ($6<<11)); } | OP_BF_L_RA_RB CR ',' u1 ',' GPR ',' GPR { emit4($1 | ($2<<23) | ($4<<21) | ($6<<16) | ($8<<11)); } - | OP_BF_L_RA_SI CR ',' u1 ',' GPR ',' e16 { emit4($1 | ($2<<23) | ($4<<21) | ($6<<16) | $8); } - | OP_BF_L_RA_UI CR ',' u1 ',' GPR ',' e16 { emit4($1 | ($2<<23) | ($4<<21) | ($6<<16) | $8); } + | OP_BF_L_RA_SI CR ',' u1 ',' GPR ',' e16 { emit_hl($1 | ($2<<23) | ($4<<21) | ($6<<16) | $8); } + | OP_BF_L_RA_UI CR ',' u1 ',' GPR ',' e16 { emit_hl($1 | ($2<<23) | ($4<<21) | ($6<<16) | $8); } | OP_BF_RA_RB cr_opt GPR ',' GPR { emit4($1 | ($2<<23) | ($3<<16) | ($5<<11)); } - | OP_BF_RA_SI cr_opt GPR ',' e16 { emit4($1 | ($2<<23) | ($3<<16) | $5); } - | OP_BF_RA_UI cr_opt GPR ',' e16 { emit4($1 | ($2<<23) | ($3<<16) | $5); } + | OP_BF_RA_SI cr_opt GPR ',' e16 { emit_hl($1 | ($2<<23) | ($3<<16) | $5); } + | OP_BF_RA_UI cr_opt GPR ',' e16 { emit_hl($1 | ($2<<23) | ($3<<16) | $5); } | OP_BF_U_C c CR ',' u4 { emit4($1 | $2 | ($3<<23) | ($5<<12)); } | OP_BH { emit4($1); } | OP_BH u2 { emit4($1 | ($2<<11)); } @@ -33,13 +33,13 @@ operation | OP_BT_BT_BT u5 { emit4($1 | ($2<<21) | ($2<<16) | ($2<<11)); } | OP_BT_C c u5 { emit4($1 | $2 | ($3<<21)); } | OP_FLM_FRB_C c u8 ',' FPR { emit4($1 | $2 | ($3<<17) | ($5<<11)); } - | OP_FRS_RA_D FPR ',' e16 '(' GPR ')' { emit4($1 | ($2<<21) | ($6<<16) | $4); } + | OP_FRS_RA_D FPR ',' e16 '(' GPR ')' { emit_hl($1 | ($2<<21) | ($6<<16) | $4); } | OP_FRS_RA_RB FPR ',' GPR ',' GPR { emit4($1 | ($2<<21) | ($4<<16) | ($6<<11)); } | OP_FRT_FRA_FRB_C c FPR ',' FPR ',' FPR { emit4($1 | $2 | ($3<<21) | ($5<<16) | ($7<<11)); } | OP_FRT_FRA_FRC_FRB_C c FPR ',' FPR ',' FPR ',' FPR { emit4($1 | $2 | ($3<<21) | ($5<<16) | ($9<<11) | ($7<<6)); } | OP_FRT_FRA_FRC_C c FPR ',' FPR ',' FPR { emit4($1 | $2 | ($3<<21) | ($5<<16) | ($7<<6)); } | OP_FRT_FRB_C c FPR ',' FPR { emit4($1 | $2 | ($3<<21) | ($5<<11)); } - | OP_FRT_RA_D FPR ',' e16 '(' GPR ')' { emit4($1 | ($2<<21) | ($6<<16) | $4); } + | OP_FRT_RA_D FPR ',' e16 '(' GPR ')' { emit_hl($1 | ($2<<21) | ($6<<16) | $4); } | OP_FRT_RA_RB FPR ',' GPR ',' GPR { emit4($1 | ($2<<21) | ($4<<16) | ($6<<11)); } | OP_FRT_C c FPR { emit4($1 | $2 | ($3<<21)); } | OP_RA_RS_C c GPR ',' GPR { emit4($1 | $2 | ($5<<21) | ($3<<16)); } @@ -59,34 +59,34 @@ operation { emit4($1 | $2 | ($5<<21) | ($3<<16) | SH6($7)); } | OP_RA_RS_SH6_MB6_C c GPR ',' GPR ',' u6 ',' u6 { emit4($1 | $2 | ($5<<21) | ($3<<16) | SH6($7) | MB6($9)); } - | OP_RA_RS_UI GPR ',' GPR ',' e16 { emit4($1 | ($4<<21) | ($2<<16) | $6); } - | OP_RA_RS_UI_CC C GPR ',' GPR ',' e16 { emit4($1 | ($5<<21) | ($3<<16) | $7); } + | OP_RA_RS_UI GPR ',' GPR ',' e16 { emit_hl($1 | ($4<<21) | ($2<<16) | $6); } + | OP_RA_RS_UI_CC C GPR ',' GPR ',' e16 { emit_hl($1 | ($5<<21) | ($3<<16) | $7); } | OP_RT GPR { emit4($1 | ($2<<21)); } | OP_RT_RA_C c GPR ',' GPR { emit4($1 | $2 | ($3<<21) | ($5<<16)); } - | OP_RT_RA_D GPR ',' e16 '(' GPR ')' { emit4($1 | ($2<<21) | ($6<<16) | $4); } - | OP_RT_RA_DS GPR ',' ds '(' GPR ')' { emit4($1 | ($2<<21) | ($6<<16) | $4); } + | OP_RT_RA_D GPR ',' e16 '(' GPR ')' { emit_hl($1 | ($2<<21) | ($6<<16) | $4); } + | OP_RT_RA_DS GPR ',' ds '(' GPR ')' { emit_hl($1 | ($2<<21) | ($6<<16) | $4); } | OP_RT_RA_NB GPR ',' GPR ',' nb { emit4($1 | ($2<<21) | ($4<<16) | ($6<<11)); } | OP_RT_RA_RB GPR ',' GPR ',' GPR { emit4($1 | ($2<<21) | ($4<<16) | ($6<<11)); } | OP_RT_RA_RB_C c GPR ',' GPR ',' GPR { emit4($1 | $2 | ($3<<21) | ($5<<16) | ($7<<11)); } - | OP_RT_RA_SI GPR ',' GPR ',' e16 { emit4($1 | ($2<<21) | ($4<<16) | $6); } - | OP_RT_RA_SI_addic c GPR ',' GPR ',' e16 { emit4($1 | ($2<<26) | ($3<<21) | ($5<<16) | $7); } + | OP_RT_RA_SI GPR ',' GPR ',' e16 { emit_hl($1 | ($2<<21) | ($4<<16) | $6); } + | OP_RT_RA_SI_addic c GPR ',' GPR ',' e16 { emit_hl($1 | ($2<<26) | ($3<<21) | ($5<<16) | $7); } | OP_RT_RA_SI_subi GPR ',' GPR ',' negate16 { emit4($1 | ($2<<21) | ($4<<16) | $6); } | OP_RT_RA_SI_subic c GPR ',' GPR ',' negate16 { emit4($1 | ($2<<26) | ($3<<21) | ($5<<16) | $7); } | OP_RT_RB_RA_C c GPR ',' GPR ',' GPR { emit4($1 | $2 | ($3<<21) | ($7<<16) | ($5<<11)); } - | OP_RT_SI GPR ',' e16 { emit4($1 | ($2<<21) | $4); } + | OP_RT_SI GPR ',' e16 { emit_hl($1 | ($2<<21) | $4); } | OP_RT_SPR GPR ',' spr_num { emit4($1 | ($2<<21) | ($4<<11)); } | OP_RS_FXM u7 ',' GPR { emit4($1 | ($4<<21) | ($2<<12)); } - | OP_RS_RA_D GPR ',' e16 '(' GPR ')' { emit4($1 | ($2<<21) | ($6<<16) | $4); } - | OP_RS_RA_DS GPR ',' ds '(' GPR ')' { emit4($1 | ($2<<21) | ($6<<16) | $4); } + | OP_RS_RA_D GPR ',' e16 '(' GPR ')' { emit_hl($1 | ($2<<21) | ($6<<16) | $4); } + | OP_RS_RA_DS GPR ',' ds '(' GPR ')' { emit_hl($1 | ($2<<21) | ($6<<16) | $4); } | OP_RS_RA_NB GPR ',' GPR ',' nb { emit4($1 | ($2<<21) | ($4<<16) | ($6<<11)); } | OP_RS_RA_RB GPR ',' GPR ',' GPR { emit4($1 | ($2<<21) | ($4<<16) | ($6<<11)); } | OP_RS_RA_RB_C c GPR ',' GPR ',' GPR { emit4($1 | $2 | ($5<<21) | ($3<<16) | ($7<<11)); } | OP_RS_RA_RA_C c GPR ',' GPR { emit4($1 | $2 | ($5<<21) | ($3<<16) | ($5<<11)); } | OP_RS_SPR spr_num ',' GPR { emit4($1 | ($4<<21) | ($2<<11)); } | OP_TO_RA_RB u5 ',' GPR ',' GPR { emit4($1 | ($2<<21) | ($4<<16) | ($6<<11)); } - | OP_TO_RA_SI u5 ',' GPR ',' e16 { emit4($1 | ($2<<21) | ($4<<16) | $6); } + | OP_TO_RA_SI u5 ',' GPR ',' e16 { emit_hl($1 | ($2<<21) | ($4<<16) | $6); } | OP_TOX_RA_RB GPR ',' GPR { emit4($1 | ($2<<16) | ($4<<11)); } - | OP_TOX_RA_SI GPR ',' e16 { emit4($1 | ($2<<16) | $4); } + | OP_TOX_RA_SI GPR ',' e16 { emit_hl($1 | ($2<<16) | $4); } | OP_LEV { emit4($1); } | OP_LEV u7 { emit4($1 | ($2<<5)); } | OP_LIA lia { emit4($1 | $2); } @@ -217,10 +217,11 @@ e16 if (($1 < -0x8000) || ($1 > 0xffff)) serror("16-bit value out of range"); $$ = (uint16_t) $1; + no_hl(); } - | OP_HI ASC_LPAR expr ASC_RPAR { $$ = emit_hi(&$3, 0); } - | OP_HA ASC_LPAR expr ASC_RPAR { $$ = emit_hi(&$3, 1); } - | OP_LO ASC_LPAR expr ASC_RPAR { $$ = emit_lo(&$3); } + | OP_HI ASC_LPAR expr ASC_RPAR { $$ = eval_hl(&$3, OP_HI); } + | OP_HA ASC_LPAR expr ASC_RPAR { $$ = eval_hl(&$3, OP_HA); } + | OP_LO ASC_LPAR expr ASC_RPAR { $$ = eval_hl(&$3, OP_LO); } ; negate16 diff --git a/mach/powerpc/as/mach5.c b/mach/powerpc/as/mach5.c index 47460790c..d72b8514a 100644 --- a/mach/powerpc/as/mach5.c +++ b/mach/powerpc/as/mach5.c @@ -1,38 +1,75 @@ +static int hl_token; +static expr_t hl_expr; -word_t emit_hi(struct expr_t* expr, int is_signed) -{ - /* If this is a symbol reference, discard the symbol and keep only the - * offset part. */ - word_t type = expr->typ & S_TYP; - word_t val = expr->val; - uint16_t hi = val >> 16; - uint16_t lo = val & 0xffff; - - if (type != S_ABS) - newrelo(expr->typ, RELOPPC | FIXUPFLAGS); - - /* If the low half of this relocation is going to be a memory operation, - * then it'll be treated as a signed value. That means that values greater - * than 0x7fff will cause the high word to have 1 subtracted from it; so - * we apply an adjustment here. - */ - - if (is_signed && (lo > 0x7fff)) - hi++; - - return hi; +void no_hl(void) { + hl_token = 0; } -word_t emit_lo(struct expr_t* expr) +word_t eval_hl(expr_t* expr, int token) { - word_t type = expr->typ & S_TYP; - word_t val = expr->val; + word_t val = expr->val; + uint16_t hi = val >> 16; + uint16_t lo = val & 0xffff; - /* If the assembler stored a symbol for relocation later, we need to - * abandon it (because the relocation was generated by emit_ha). */ + hl_token = token; + hl_expr = *expr; - if (type != S_ABS) - relonami = 0; - - return val & 0xffff; + switch (token) { + case OP_HI: /* hi16[expr] */ + return hi; + case OP_HA: /* ha16[expr]*/ + /* + * If the low half will be treated as a signed value, + * then values greater than 0x7fff will cause the high + * half to have 1 subtracted from it; so we apply an + * adjustment here. + */ + if (lo > 0x7fff) + hi++; + return hi; + case OP_LO: /* lo16[expr] */ + return lo; + } +} + +void emit_hl(word_t in) +{ + word_t reg; + int type; + + switch (hl_token) { + case OP_HI: /* hi16[expr] */ + case OP_HA: /* ha16[expr] */ + if (PASS_RELO && (hl_expr.typ & S_TYP) != S_ABS) { + /* + * RELOLIS only works with lis _, _ (same as + * addis _, r0, _). Check if instruction + * isn't addis or register RA isn't r0. + */ + if ((in & 0xfc1f0000) != (0x3c000000)) + serror("relocation only works with lis"); + + /* + * High bit: ha16 flag + * Next 5 bits: register RT + * Low 26 bits: signed offset + */ + fit(fitx(hl_expr.val, 26)); + newrelo(hl_expr.typ, RELOLIS | FIXUPFLAGS); + reg = (in >> 21) & 0x1f; + in = (hl_token == OP_HA) << 31; + in |= reg << 26; + in |= hl_expr.val & 0x03ffffff; + } + break; + case OP_LO: /* lo16[expr] */ + if (PASS_RELO && (hl_expr.typ & S_TYP) != S_ABS) { + DOTVAL += 2; + newrelo(hl_expr.typ, RELO2 | FIXUPFLAGS); + DOTVAL -= 2; + } + break; + } + + emit4(in); } diff --git a/util/amisc/ashow.c b/util/amisc/ashow.c index 498ae3980..ec85de30d 100644 --- a/util/amisc/ashow.c +++ b/util/amisc/ashow.c @@ -140,6 +140,9 @@ showrelo() case RELOPPC: printf("\tPowerPC 26-bit address\n"); break; + case RELOLIS: + printf("\tPowerPC lis instruction\n"); + break; case RELOVC4: printf("\tVideoCore IV address in 32-bit instruction\n"); break; diff --git a/util/led/relocate.c b/util/led/relocate.c index 036b7dbb8..1b8960938 100644 --- a/util/led/relocate.c +++ b/util/led/relocate.c @@ -165,8 +165,17 @@ static uint32_t get_powerpc_valu(char* addr, uint16_t type) return ((hi << 16) | lo); } - fatal("Don't know how to read from PowerPC fixup on instructions 0x%08x+0x%08x", - opcode1, opcode2); + fatal("Don't know how to read from PowerPC fixup on instructions 0x%08lx+0x%08lx", + (unsigned long)opcode1, (unsigned long)opcode2); +} + +/* RELOLIS stores a signed 26-bit offset in the low bits. */ +static uint32_t get_lis_valu(char *addr, uint16_t type) +{ + uint32_t valu = read4(addr, type) & 0x03ffffff; + if (valu & 0x02000000) + valu |= 0xfc000000; /* sign extension */ + return valu; } /* @@ -184,6 +193,8 @@ static uint32_t getvalu(char* addr, uint16_t type) return read4(addr, type); case RELOPPC: return get_powerpc_valu(addr, type); + case RELOLIS: + return get_lis_valu(addr, type); case RELOVC4: return get_vc4_valu(addr); default: @@ -327,8 +338,34 @@ static void put_powerpc_valu(char* addr, uint32_t value, uint16_t type) } else - fatal("Don't know how to write a PowerPC fixup to instructions 0x%08x+0x%08x", - opcode1, opcode2); + fatal("Don't know how to write a PowerPC fixup to instructions 0x%08lx+0x%08lx", + (unsigned long)opcode1, (unsigned long)opcode2); +} + +/* Writes a PowerPC lis instruction. */ +static void put_lis_valu(char* addr, uint32_t value, uint16_t type) +{ + uint32_t opcode, reg; + uint16_t hi, lo; + bool ha16; + + /* ha16 flag in high bit, register in next 5 bits */ + opcode = read4(addr, type); + ha16 = opcode >> 31; + reg = (opcode >> 26) & 0x1f; + + /* + * Apply the sign adjustment if the ha16 flag is set and the + * low half is a negative signed 16-bit integer. + */ + hi = value >> 16; + lo = value & 0xffff; + if (ha16 && lo > 0x7fff) + hi++; + + /* Assemble lis reg, hi == addis reg, r0, hi. */ + opcode = (15 << 26) | (reg << 21) | (0 << 16) | hi; + write4(opcode, addr, type); } /* @@ -352,6 +389,9 @@ static putvalu(uint32_t valu, char* addr, uint16_t type) case RELOPPC: put_powerpc_valu(addr, valu, type); break; + case RELOLIS: + put_lis_valu(addr, valu, type); + break; case RELOVC4: put_vc4_valu(addr, valu); break; From 7255ed403f0876321587dffff96a23a222c9e784 Mon Sep 17 00:00:00 2001 From: George Koehler Date: Wed, 8 Feb 2017 12:12:28 -0500 Subject: [PATCH 164/173] Tweak some tokens in PowerPC ncg. Remove the GPRINDIRECT token, and use the IND_RC_* tokens as operands to instructions. We no longer need to unpack an IND_RC_* token and repack it as a GPRINDIRECT to use it in an instruction. Allow storing IND_ALL_B and IND_ALL_H in register variables. Create a set ANY_BHW for anything that we can store in a regvar. Push register variables on the stack without using GPRE, by changing stwu to accept LOCAL. Then ncg will replace the string ">>> BUG IN LOCAL" with the register name. (I copied ">>> BUG IN LOCAL" from mach/arm/ncg/table.) Fix the rule for "pat lil inreg($1)>0" to yield a IND_RC_W token, not a register. We might need to kill the token with "kills MEMORY". Rename CONST_ALL to CONST_STACK, because it only includes constants on the stack, and excludes CONST tokens. Instructions still don't allow CONST_STACK operands, so we still need to repack each CONST_STACK as a CONST to use it in an instruction. Rename LABEL_OFFSET_HI to just LABEL_HI, and same for LABEL_HA and LABEL_HO. --- mach/powerpc/ncg/table | 237 ++++++++++++++++++++--------------------- 1 file changed, 117 insertions(+), 120 deletions(-) diff --git a/mach/powerpc/ncg/table b/mach/powerpc/ncg/table index e76cadb33..fb5e6b3ff 100644 --- a/mach/powerpc/ncg/table +++ b/mach/powerpc/ncg/table @@ -157,17 +157,16 @@ TOKENS /* Used only in instruction descriptions (to generate the correct syntax). */ - GPRINDIRECT = { GPR reg; INT off; } 4 off "(" reg ")". GPRINDIRECT_OFFSET_LO = { GPR reg; ADDR adr; } 4 "lo16[" adr "](" reg ")". CONST = { INT val; } 4 val. /* Primitives */ LABEL = { ADDR adr; } 4 adr. - LABEL_OFFSET_HI = { ADDR adr; } 4 "hi16[" adr "]". - LABEL_OFFSET_HA = { ADDR adr; } 4 "ha16[" adr "]". - LABEL_OFFSET_LO = { ADDR adr; } 4 "lo16[" adr "]". - LOCAL = { INT off; } 4. + LABEL_HI = { ADDR adr; } 4 "hi16[" adr "]". + LABEL_HA = { ADDR adr; } 4 "ha16[" adr "]". + LABEL_LO = { ADDR adr; } 4 "lo16[" adr "]". + LOCAL = { INT off; } 4 ">>> BUG IN LOCAL". /* Allows us to use regvar() to refer to registers */ @@ -192,15 +191,15 @@ TOKENS SEX_B = { GPR reg; } 4. SEX_H = { GPR reg; } 4. - IND_RC_B = { GPR reg; INT off; } 4. + IND_RC_B = { GPR reg; INT off; } 4 off "(" reg ")". IND_RR_B = { GPR reg1; GPR reg2; } 4. - IND_RC_H = { GPR reg; INT off; } 4. + IND_RC_H = { GPR reg; INT off; } 4 off "(" reg ")". IND_RR_H = { GPR reg1; GPR reg2; } 4. - IND_RC_H_S = { GPR reg; INT off; } 4. + IND_RC_H_S = { GPR reg; INT off; } 4 off "(" reg ")". IND_RR_H_S = { GPR reg1; GPR reg2; } 4. - IND_RC_W = { GPR reg; INT off; } 4. + IND_RC_W = { GPR reg; INT off; } 4 off "(" reg ")". IND_RR_W = { GPR reg1; GPR reg2; } 4. - IND_RC_D = { GPR reg; INT off; } 8. + IND_RC_D = { GPR reg; INT off; } 8 off "(" reg ")". IND_RR_D = { GPR reg1; GPR reg2; } 8. NOT_R = { GPR reg; } 4. @@ -237,7 +236,7 @@ SETS /* unsigned 16-bit integer */ UCONST2 = CONST_0000_7FFF + CONST_8000 + CONST_8001_FFFF. /* any constant on stack */ - CONST_ALL = CONST_N8000 + CONST_N7FFF_N0001 + CONST_0000_7FFF + + CONST_STACK = CONST_N8000 + CONST_N7FFF_N0001 + CONST_0000_7FFF + CONST_8000 + CONST_8001_FFFF + CONST_HZ + CONST_HL. SUM_ALL = SUM_RC + SUM_RR. @@ -247,18 +246,19 @@ SETS LOGICAL_ALL = NOT_R + AND_RR + OR_RR + OR_RC + XOR_RR + XOR_RC. - /* indirect 4-byte value */ + /* indirect values */ + IND_ALL_B = IND_RC_B + IND_RR_B. + IND_ALL_H = IND_RC_H + IND_RR_H + IND_RC_H_S + IND_RR_H_S. IND_ALL_W = IND_RC_W + IND_RR_W. - /* indirect 8-byte value */ IND_ALL_D = IND_RC_D + IND_RR_D. - /* any indirect value that fits in a GPR */ - IND_ALL_BHW = IND_RC_B + IND_RR_B + IND_RC_H + IND_RR_H + - IND_RC_H_S + IND_RR_H_S + IND_ALL_W. + IND_ALL_BHW = IND_ALL_B + IND_ALL_H + IND_ALL_W. /* anything killed by sti (store indirect) */ MEMORY = IND_ALL_BHW + IND_ALL_D. - OP_ALL_W = SUM_ALL + SEX_ALL + LOGICAL_ALL + IND_ALL_W. + /* any stack token that we can easily move to GPR */ + ANY_BHW = REG + CONST_STACK + LABEL + SEX_ALL + + SUM_ALL + IND_ALL_BHW + LOGICAL_ALL. INSTRUCTIONS @@ -278,7 +278,9 @@ INSTRUCTIONS add GPR:wo, GPR:ro, GPR:ro. addX "add." GPR:wo, GPR:ro, GPR:ro. addi GPR:wo, GPR:ro, CONST:ro. - addis GPR:wo, GPR:ro, CONST+LABEL_OFFSET_HI+LABEL_OFFSET_HA:ro. + li GPR:wo, CONST:ro. + addis GPR:wo, GPR:ro, CONST+LABEL_HI+LABEL_HA:ro. + lis GPR:wo, CONST+LABEL_HI+LABEL_HA:ro. and GPR:wo, GPR:ro, GPR:ro. andc GPR:wo, GPR:ro, GPR:ro. andiX "andi." GPR:wo:cc, GPR:ro, CONST:ro. @@ -326,22 +328,22 @@ INSTRUCTIONS frsp FSREG:wo, FREG:ro cost(4, 5). fsub FREG:wo, FREG:ro, FREG:ro cost(4, 5). fsubs FSREG:wo, FSREG:ro, FSREG:ro cost(4, 5). - lbz GPR:wo, GPRINDIRECT:ro cost(4, 3). + lbz GPR:wo, IND_RC_B:ro cost(4, 3). lbzx GPR:wo, GPR:ro, GPR:ro cost(4, 3). - lfd FPR:wo, GPRINDIRECT:ro cost(4, 5). - lfdu FPR:wo, GPRINDIRECT:ro cost(4, 5). + lfd FPR:wo, IND_RC_D:ro cost(4, 5). + lfdu FPR:wo, IND_RC_D:ro cost(4, 5). lfdx FPR:wo, GPR:ro, GPR:ro cost(4, 5). - lfs FSREG:wo, GPRINDIRECT:ro cost(4, 4). - lfsu FSREG:wo, GPRINDIRECT:rw cost(4, 4). + lfs FSREG:wo, IND_RC_W:ro cost(4, 4). + lfsu FSREG:wo, IND_RC_W:rw cost(4, 4). lfsx FSREG:wo, GPR:ro, GPR:ro cost(4, 4). - lha GPR:wo, GPRINDIRECT:ro cost(4, 3). + lha GPR:wo, IND_RC_H_S:ro cost(4, 3). lhax GPR:wo, GPR:ro, GPR:ro cost(4, 3). - lhz GPR:wo, GPRINDIRECT:ro cost(4, 3). + lhz GPR:wo, IND_RC_H:ro cost(4, 3). lhzx GPR:wo, GPR:ro, GPR:ro cost(4, 3). li32 GPR:wo, CONST:ro cost(8, 2). - lwzu GPR:wo, GPRINDIRECT:ro cost(4, 3). + lwzu GPR:wo, IND_RC_W:ro cost(4, 3). lwzx GPR:wo, GPR:ro, GPR:ro cost(4, 3). - lwz GPR:wo, GPRINDIRECT+GPRINDIRECT_OFFSET_LO:ro cost(4, 3). + lwz GPR:wo, IND_RC_W+GPRINDIRECT_OFFSET_LO:ro cost(4, 3). nand GPR:wo, GPR:ro, GPR:ro. neg GPR:wo, GPR:ro. nor GPR:wo, GPR:ro, GPR:ro. @@ -351,7 +353,7 @@ INSTRUCTIONS mtspr SPR:wo, GPR:ro cost(4, 2). or GPR:wo, GPR:ro, GPR:ro. orc GPR:wo, GPR:ro, GPR:ro. - ori GPR:wo, GPR:ro, CONST+LABEL_OFFSET_LO:ro. + ori GPR:wo, GPR:ro, CONST+LABEL_LO:ro. oris GPR:wo, GPR:ro, CONST:ro. orX "or." GPR:wo:cc, GPR:ro, GPR:ro. rlwinm GPR:wo, GPR:ro, CONST:ro, CONST:ro, CONST:ro. @@ -362,19 +364,19 @@ INSTRUCTIONS sraw GPR:wo, GPR:ro, GPR:ro cost(4, 2). srawi GPR:wo, GPR:ro, CONST:ro cost(4, 2). srw GPR:wo, GPR:ro, GPR:ro. - stb GPR:ro, GPRINDIRECT:rw cost(4, 3). + stb GPR:ro, IND_RC_B:rw cost(4, 3). stbx GPR:ro, GPR:ro, GPR:ro cost(4, 3). - stfd FPR:ro, GPRINDIRECT:rw cost(4, 4). - stfdu FPR:ro, GPRINDIRECT:rw cost(4, 4). + stfd FPR:ro, IND_RC_D:rw cost(4, 4). + stfdu FPR:ro, IND_RC_D:rw cost(4, 4). stfdx FPR:ro, GPR:ro, GPR:ro cost(4, 4). - stfs FSREG:ro, GPRINDIRECT:rw cost(4, 3). - stfsu FSREG:ro, GPRINDIRECT:rw cost(4, 3). + stfs FSREG:ro, IND_RC_W:rw cost(4, 3). + stfsu FSREG:ro, IND_RC_W:rw cost(4, 3). stfsx FSREG:ro, GPR:ro, GPR:ro cost(4, 3). - sth GPR:ro, GPRINDIRECT:rw cost(4, 3). + sth GPR:ro, IND_RC_H:rw cost(4, 3). sthx GPR:ro, GPR:ro, GPR:ro cost(4, 3). - stw GPR:ro, GPRINDIRECT:rw cost(4, 3). + stw GPR:ro, IND_RC_W:rw cost(4, 3). stwx GPR:ro, GPR:ro, GPR:ro cost(4, 3). - stwu GPR+GPRE:ro, GPRINDIRECT:rw cost(4, 3). + stwu GPR+LOCAL:ro, IND_RC_W:rw cost(4, 3). xor GPR:wo, GPR:ro, GPR:ro. xori GPR:wo, GPR:ro, CONST:ro. xoris GPR:wo, GPR:ro, CONST:ro. @@ -390,25 +392,22 @@ MOVES COMMENT("move GPR->GPR") or %2, %1, %1 -/* GPRE exists solely to allow us to use regvar() (which can only be used in - an expression) as a register constant. */ - - from GPR to GPRE - gen - COMMENT("move GPR->GPRE") - or %2.reg, %1, %1 - /* Constants */ - from CONST_ALL + CONST smalls(%val) to GPR + from CONST + CONST_STACK smalls(%val) to GPR gen - COMMENT("move CONST_ALL->GPR smalls") - addi %2, R0, {CONST, %1.val} + COMMENT("move CONST->GPR smalls") + li %2, {CONST, %1.val} - from CONST_ALL + CONST to GPR + from CONST + CONST_STACK lo(%val)==0 to GPR gen - COMMENT("move CONST_ALL->GPR") - addis %2, R0, {CONST, hi(%1.val)} + COMMENT("move CONST->GPR shifted") + lis %2, {CONST, hi(%1.val)} + + from CONST + CONST_STACK to GPR + gen + COMMENT("move CONST->GPR") + lis %2, {CONST, hi(%1.val)} ori %2, %2, {CONST, lo(%1.val)} /* Can't use addi %2, %2, {CONST, los(%1.val)} * because %2 might be R0. */ @@ -416,8 +415,8 @@ MOVES from LABEL to GPR gen COMMENT("move LABEL->GPR") - addis %2, R0, {LABEL_OFFSET_HI, %1.adr} - ori %2, %2, {LABEL_OFFSET_LO, %1.adr} + lis %2, {LABEL_HI, %1.adr} + ori %2, %2, {LABEL_LO, %1.adr} /* Sign extension */ @@ -453,7 +452,7 @@ MOVES from IND_RC_B to GPR gen COMMENT("move IND_RC_B->GPR") - lbz %2, {GPRINDIRECT, %1.reg, %1.off} + lbz %2, %1 from IND_RR_B to GPR gen @@ -465,7 +464,7 @@ MOVES from GPR to IND_RC_B gen COMMENT("move GPR->IND_RC_B") - stb %1, {GPRINDIRECT, %2.reg, %2.off} + stb %1, %2 from GPR to IND_RR_B gen @@ -477,7 +476,7 @@ MOVES from IND_RC_H to GPR gen COMMENT("move IND_RC_H->GPR") - lhz %2, {GPRINDIRECT, %1.reg, %1.off} + lhz %2, %1 from IND_RR_H to GPR gen @@ -487,7 +486,7 @@ MOVES from IND_RC_H_S to GPR gen COMMENT("move IND_RC_H_S->GPR") - lha %2, {GPRINDIRECT, %1.reg, %1.off} + lha %2, %1 from IND_RR_H_S to GPR gen @@ -499,7 +498,7 @@ MOVES from GPR to IND_RC_H gen COMMENT("move GPR->IND_RC_H") - sth %1, {GPRINDIRECT, %2.reg, %2.off} + sth %1, %2 from GPR to IND_RR_H gen @@ -511,7 +510,7 @@ MOVES from IND_RC_W to GPR gen COMMENT("move IND_RC_W->GPR") - lwz %2, {GPRINDIRECT, %1.reg, %1.off} + lwz %2, %1 from IND_RR_W to GPR gen @@ -521,7 +520,7 @@ MOVES from IND_RC_W to FSREG gen COMMENT("move IND_RC_W->FSREG") - lfs %2, {GPRINDIRECT, %1.reg, %1.off} + lfs %2, %1 from IND_RR_W to FSREG gen @@ -533,7 +532,7 @@ MOVES from GPR to IND_RC_W gen COMMENT("move GPR->IND_RC_W") - stw %1, {GPRINDIRECT, %2.reg, %2.off} + stw %1, %2 from GPR to IND_RR_W gen @@ -543,7 +542,7 @@ MOVES from FSREG to IND_RC_W gen COMMENT("move FSREG->IND_RC_W") - stfs %1, {GPRINDIRECT, %2.reg, %2.off} + stfs %1, %2 from FSREG to IND_RR_W gen @@ -555,7 +554,7 @@ MOVES from IND_RC_D to FPR gen COMMENT("move IND_RC_D->FPR") - lfd %2, {GPRINDIRECT, %1.reg, %1.off} + lfd %2, {IND_RC_D, %1.reg, %1.off} from IND_RR_D to FPR gen @@ -567,7 +566,7 @@ MOVES from FPR to IND_RC_D gen COMMENT("move FPR->IND_RC_D") - stfd %1, {GPRINDIRECT, %2.reg, %2.off} + stfd %1, {IND_RC_D, %2.reg, %2.off} from FPR to IND_RR_D gen @@ -681,9 +680,10 @@ MOVES extrwi %2, %1.reg, {CONST, 1}, {CONST, 1} xori %2, %2, {CONST, 1} -/* Miscellaneous */ +/* GPRE exists solely to allow us to use regvar() (which can only be used in + an expression) as a register constant. */ - from OP_ALL_W + LABEL + CONST_ALL to GPRE + from ANY_BHW to GPRE gen move %1, %2.reg @@ -701,64 +701,64 @@ STACKINGRULES from LOCAL to STACK gen COMMENT("stack LOCAL") - stwu {GPRE, regvar(%1.off)}, {GPRINDIRECT, SP, 0-4} + stwu %1, {IND_RC_W, SP, 0-4} from REG to STACK gen COMMENT("stack REG") - stwu %1, {GPRINDIRECT, SP, 0-4} + stwu %1, {IND_RC_W, SP, 0-4} from REG_PAIR to STACK gen COMMENT("stack REG_PAIR") - stwu %1.2, {GPRINDIRECT, SP, 0-4} - stwu %1.1, {GPRINDIRECT, SP, 0-4} + stwu %1.2, {IND_RC_W, SP, 0-4} + stwu %1.1, {IND_RC_W, SP, 0-4} - from CONST_ALL + LABEL to STACK + from CONST_STACK + LABEL to STACK gen - COMMENT("stack CONST_ALL + LABEL") + COMMENT("stack CONST_STACK + LABEL") move %1, RSCRATCH - stwu RSCRATCH, {GPRINDIRECT, SP, 0-4} + stwu RSCRATCH, {IND_RC_W, SP, 0-4} from SEX_B to STACK gen COMMENT("stack SEX_B") extsb RSCRATCH, %1.reg - stwu RSCRATCH, {GPRINDIRECT, SP, 0-4} + stwu RSCRATCH, {IND_RC_W, SP, 0-4} from SEX_H to STACK gen COMMENT("stack SEX_H") extsh RSCRATCH, %1.reg - stwu RSCRATCH, {GPRINDIRECT, SP, 0-4} + stwu RSCRATCH, {IND_RC_W, SP, 0-4} from SUM_ALL + LOGICAL_ALL to STACK gen COMMENT("stack SUM_ALL + LOGICAL_ALL") move %1, RSCRATCH - stwu RSCRATCH, {GPRINDIRECT, SP, 0-4} + stwu RSCRATCH, {IND_RC_W, SP, 0-4} from IND_ALL_BHW to STACK gen COMMENT("stack IND_ALL_BHW") move %1, RSCRATCH - stwu RSCRATCH, {GPRINDIRECT, SP, 0-4} + stwu RSCRATCH, {IND_RC_W, SP, 0-4} from IND_ALL_D to STACK gen COMMENT("stack IND_ALL_D") move %1, FSCRATCH - stfdu FSCRATCH, {GPRINDIRECT, SP, 0-8} + stfdu FSCRATCH, {IND_RC_D, SP, 0-8} from FREG to STACK gen COMMENT("stack FPR") - stfdu %1, {GPRINDIRECT, SP, 0-8} + stfdu %1, {IND_RC_D, SP, 0-8} from FSREG to STACK gen COMMENT("stack FSREG") - stfsu %1, {GPRINDIRECT, SP, 0-4} + stfsu %1, {IND_RC_W, SP, 0-4} @@ -771,10 +771,10 @@ COERCIONS move %1, %a yields %a - from CONST_ALL + from CONST + CONST_STACK uses REG gen - COMMENT("coerce CONST_ALL->REG") + COMMENT("coerce CONST->REG") move %1, %a yields %a @@ -789,7 +789,7 @@ COERCIONS uses REG gen COMMENT("coerce STACK->REG") - lwz %a, {GPRINDIRECT, SP, 0} + lwz %a, {IND_RC_W, SP, 0} addi SP, SP, {CONST, 4} yields %a @@ -797,8 +797,8 @@ COERCIONS uses REG_PAIR gen COMMENT("coerce STACK->REG_PAIR") - lwz %a.1, {GPRINDIRECT, SP, 0} - lwz %a.2, {GPRINDIRECT, SP, 4} + lwz %a.1, {IND_RC_W, SP, 0} + lwz %a.2, {IND_RC_W, SP, 4} addi SP, SP, {CONST, 8} yields %a @@ -838,7 +838,7 @@ COERCIONS uses FREG gen COMMENT("coerce STACK->FREG") - lfd %a, {GPRINDIRECT, SP, 0} + lfd %a, {IND_RC_D, SP, 0} addi SP, SP, {CONST, 8} yields %a @@ -846,7 +846,7 @@ COERCIONS uses FSREG gen COMMENT("coerce STACK->FSREG") - lfs %a, {GPRINDIRECT, SP, 0} + lfs %a, {IND_RC_W, SP, 0} addi SP, SP, {CONST, 4} yields %a @@ -1003,7 +1003,7 @@ PATTERNS loi INT32*2 pat stl inreg($1)>0 /* Store to local */ - with CONST_ALL + LABEL + GPR + OP_ALL_W + with ANY_BHW kills regvar($1), LOCAL %off==$1 gen move %1, {GPRE, regvar($1)} @@ -1019,10 +1019,7 @@ PATTERNS sti INT32*2 pat lil inreg($1)>0 /* Load from indirected local */ - uses REG - gen - lwz %a, {GPRINDIRECT, regvar($1), 0} - yields %a + yields {IND_RC_W, regvar($1), 0} pat lil /* Load from indirected local */ leaving @@ -1092,17 +1089,17 @@ PATTERNS kills MEMORY uses REG={LABEL, $1}, REG gen - lwz %b, {GPRINDIRECT, %a, 0} + lwz %b, {IND_RC_W, %a, 0} addi %b, %b, {CONST, 1} - stw %b, {GPRINDIRECT, %a, 0} + stw %b, {IND_RC_W, %a, 0} pat dee /* Decrement external */ kills MEMORY uses REG={LABEL, $1}, REG gen - lwz %b, {GPRINDIRECT, %a, 0} + lwz %b, {IND_RC_W, %a, 0} addi %b, %b, {CONST, 0-1} - stw %b, {GPRINDIRECT, %a, 0} + stw %b, {IND_RC_W, %a, 0} @@ -1161,7 +1158,7 @@ PATTERNS with LABEL uses REG gen - addis %a, R0, {LABEL_OFFSET_HA, %1.adr} + lis %a, {LABEL_HA, %1.adr} lwz %a, {GPRINDIRECT_OFFSET_LO, %a, %1.adr} yields %a with GPR @@ -1194,7 +1191,7 @@ PATTERNS with GPR GPR kills MEMORY gen - stb %2, {GPRINDIRECT, %1, 0} + stb %2, {IND_RC_B, %1, 0} with SUM_RR GPR kills MEMORY gen @@ -1206,7 +1203,7 @@ PATTERNS with GPR SEX_B kills MEMORY gen - stb %2.reg, {GPRINDIRECT, %1, 0} + stb %2.reg, {IND_RC_B, %1, 0} with SUM_RR SEX_B kills MEMORY gen @@ -1220,7 +1217,7 @@ PATTERNS with GPR GPR kills MEMORY gen - sth %2, {GPRINDIRECT, %1, 0} + sth %2, {IND_RC_H, %1, 0} with SUM_RR GPR kills MEMORY gen @@ -1232,7 +1229,7 @@ PATTERNS with GPR SEX_H kills MEMORY gen - sth %2.reg, {GPRINDIRECT, %1, 0} + sth %2.reg, {IND_RC_H, %1, 0} with SUM_RR SEX_H kills MEMORY gen @@ -1381,13 +1378,13 @@ PATTERNS with REG CONST_HZ uses reusing %1, REG={SUM_RIS, %1, his(%2.val)} yields %a - with CONST_ALL-CONST2-CONST_HZ REG + with CONST_STACK-CONST2-CONST_HZ REG uses reusing %2, REG={SUM_RIS, %2, his(%1.val)} yields {SUM_RC, %a, los(%1.val)} - with REG CONST_ALL-CONST2-CONST_HZ + with REG CONST_STACK-CONST2-CONST_HZ uses reusing %1, REG={SUM_RIS, %1, his(%2.val)} yields {SUM_RC, %a, los(%2.val)} - with CONST_ALL LABEL + with CONST_STACK LABEL yields {LABEL, %2.adr+%1.val} pat sbi $1==4 /* Subtract word (second - top) */ @@ -1401,10 +1398,10 @@ PATTERNS with CONST_HZ REG uses reusing %2, REG={SUM_RIS, %2, his(0-%1.val)} yields %a - with CONST_ALL-CONST2_WHEN_NEG-CONST_HZ REG + with CONST_STACK-CONST2_WHEN_NEG-CONST_HZ REG uses reusing %2, REG={SUM_RIS, %2, his(0-%1.val)} yields {SUM_RC, %a, los(0-%1.val)} - with CONST_ALL LABEL + with CONST_STACK LABEL yields {LABEL, %2.adr+(0-%1.val)} pat ngi $1==4 /* Negate word */ @@ -1519,10 +1516,10 @@ PATTERNS with CONST_HZ REG uses reusing %2, REG={OR_RIS, %2, hi(%1.val)} yields %a - with REG CONST_ALL-UCONST2-CONST_HZ + with REG CONST_STACK-UCONST2-CONST_HZ uses reusing %1, REG={OR_RIS, %1, hi(%2.val)} yields {OR_RC, %1, lo(%2.val)} - with CONST_ALL-UCONST2-CONST_HZ REG + with CONST_STACK-UCONST2-CONST_HZ REG uses reusing %2, REG={OR_RIS, %2, hi(%1.val)} yields {OR_RC, %2, lo(%1.val)} @@ -1549,10 +1546,10 @@ PATTERNS with CONST_HZ REG uses reusing %2, REG={XOR_RIS, %2, hi(%1.val)} yields %a - with REG CONST_ALL-UCONST2-CONST_HZ + with REG CONST_STACK-UCONST2-CONST_HZ uses reusing %1, REG={XOR_RIS, %1, hi(%2.val)} yields {XOR_RC, %1, lo(%2.val)} - with CONST_ALL-UCONST2-CONST_HZ REG + with CONST_STACK-UCONST2-CONST_HZ REG uses reusing %2, REG={XOR_RIS, %2, hi(%1.val)} yields {XOR_RC, %2, lo(%1.val)} @@ -1601,7 +1598,7 @@ PATTERNS cal ".zer" pat sli $1==4 /* Shift left (second << top) */ - with CONST_ALL GPR + with CONST_STACK GPR uses reusing %2, REG gen rlwinm %a, %2, {CONST, (%1.val & 0x1F)}, {CONST, 0}, {CONST, 31-(%1.val & 0x1F)} @@ -1613,7 +1610,7 @@ PATTERNS yields %a pat sri $1==4 /* Shift right signed (second >> top) */ - with CONST_ALL GPR + with CONST_STACK GPR uses reusing %2, REG gen srawi %a, %2, {CONST, %1.val & 0x1F} @@ -1625,7 +1622,7 @@ PATTERNS yields %a pat sru $1==4 /* Shift right unsigned (second >> top) */ - with CONST_ALL GPR + with CONST_STACK GPR uses reusing %2, REG gen rlwinm %a, %2, {CONST, 32-(%1.val & 0x1F)}, {CONST, (%1.val & 0x1F)}, {CONST, 31} @@ -2121,18 +2118,18 @@ PATTERNS uses REG gen move {CONST, $1}, %a - stwu %a, {GPRINDIRECT, SP, 0-4} - stwu %2, {GPRINDIRECT, SP, 0-4} - stwu %1, {GPRINDIRECT, SP, 0-4} + stwu %a, {IND_RC_W, SP, 0-4} + stwu %2, {IND_RC_W, SP, 0-4} + stwu %1, {IND_RC_W, SP, 0-4} bl {LABEL, "_memmove"} addi SP, SP, {CONST, 12} pat bls /* Block move variable length */ with GPR GPR GPR STACK gen - stwu %1, {GPRINDIRECT, SP, 0-4} - stwu %3, {GPRINDIRECT, SP, 0-4} - stwu %2, {GPRINDIRECT, SP, 0-4} + stwu %1, {IND_RC_W, SP, 0-4} + stwu %3, {IND_RC_W, SP, 0-4} + stwu %2, {IND_RC_W, SP, 0-4} bl {LABEL, "_memmove"} addi SP, SP, {CONST, 12} @@ -2198,7 +2195,7 @@ PATTERNS with GPR uses reusing %1, REG gen - lwz %a, {GPRINDIRECT, %1, FP_OFFSET} + lwz %a, {IND_RC_W, %1, FP_OFFSET} yields %a pat lpb /* Convert FP to argument address */ @@ -2256,7 +2253,7 @@ PATTERNS with CONST_HZ STACK gen move {SUM_RC, SP, his(%1.val)}, SP - with CONST_ALL-CONST2-CONST_HZ STACK + with CONST_STACK-CONST2-CONST_HZ STACK gen move {SUM_RC, SP, his(%1.val)}, SP move {SUM_RC, SP, los(%1.val)}, SP From 754e96ef16a9a145ad72926950a40479bf31c4e5 Mon Sep 17 00:00:00 2001 From: George Koehler Date: Thu, 2 Feb 2017 10:48:25 -0500 Subject: [PATCH 165/173] Use ha16/lo16 to emit pairs of lis/stw, lis/lfs, lis/stfs. A 4-byte load from a label yields a token IND_RL_W. This token emits either lis/lwz or lis/lfs, if we want a general-purpose register or a floating-point register. --- mach/powerpc/ncg/table | 114 +++++++++++++++++++++++++++-------------- 1 file changed, 75 insertions(+), 39 deletions(-) diff --git a/mach/powerpc/ncg/table b/mach/powerpc/ncg/table index fb5e6b3ff..2794292a3 100644 --- a/mach/powerpc/ncg/table +++ b/mach/powerpc/ncg/table @@ -155,17 +155,14 @@ REGISTERS TOKENS -/* Used only in instruction descriptions (to generate the correct syntax). */ - - GPRINDIRECT_OFFSET_LO = { GPR reg; ADDR adr; } 4 "lo16[" adr "](" reg ")". - CONST = { INT val; } 4 val. - /* Primitives */ + CONST = { INT val; } 4 val. LABEL = { ADDR adr; } 4 adr. LABEL_HI = { ADDR adr; } 4 "hi16[" adr "]". LABEL_HA = { ADDR adr; } 4 "ha16[" adr "]". LABEL_LO = { ADDR adr; } 4 "lo16[" adr "]". + LABEL_STACK = { GPR reg; ADDR adr; } 4. LOCAL = { INT off; } 4 ">>> BUG IN LOCAL". /* Allows us to use regvar() to refer to registers */ @@ -191,16 +188,17 @@ TOKENS SEX_B = { GPR reg; } 4. SEX_H = { GPR reg; } 4. - IND_RC_B = { GPR reg; INT off; } 4 off "(" reg ")". - IND_RR_B = { GPR reg1; GPR reg2; } 4. - IND_RC_H = { GPR reg; INT off; } 4 off "(" reg ")". - IND_RR_H = { GPR reg1; GPR reg2; } 4. - IND_RC_H_S = { GPR reg; INT off; } 4 off "(" reg ")". - IND_RR_H_S = { GPR reg1; GPR reg2; } 4. - IND_RC_W = { GPR reg; INT off; } 4 off "(" reg ")". - IND_RR_W = { GPR reg1; GPR reg2; } 4. - IND_RC_D = { GPR reg; INT off; } 8 off "(" reg ")". - IND_RR_D = { GPR reg1; GPR reg2; } 8. + IND_RC_B = { GPR reg; INT off; } 4 off "(" reg ")". + IND_RR_B = { GPR reg1; GPR reg2; } 4. + IND_RC_H = { GPR reg; INT off; } 4 off "(" reg ")". + IND_RR_H = { GPR reg1; GPR reg2; } 4. + IND_RC_H_S = { GPR reg; INT off; } 4 off "(" reg ")". + IND_RR_H_S = { GPR reg1; GPR reg2; } 4. + IND_RC_W = { GPR reg; INT off; } 4 off "(" reg ")". + IND_RL_W = { GPR reg; ADDR adr; } 4 "lo16[" adr "](" reg ")". + IND_RR_W = { GPR reg1; GPR reg2; } 4. + IND_RC_D = { GPR reg; INT off; } 8 off "(" reg ")". + IND_RR_D = { GPR reg1; GPR reg2; } 8. NOT_R = { GPR reg; } 4. @@ -249,7 +247,7 @@ SETS /* indirect values */ IND_ALL_B = IND_RC_B + IND_RR_B. IND_ALL_H = IND_RC_H + IND_RR_H + IND_RC_H_S + IND_RR_H_S. - IND_ALL_W = IND_RC_W + IND_RR_W. + IND_ALL_W = IND_RC_W + IND_RL_W + IND_RR_W. IND_ALL_D = IND_RC_D + IND_RR_D. IND_ALL_BHW = IND_ALL_B + IND_ALL_H + IND_ALL_W. @@ -277,7 +275,7 @@ INSTRUCTIONS add GPR:wo, GPR:ro, GPR:ro. addX "add." GPR:wo, GPR:ro, GPR:ro. - addi GPR:wo, GPR:ro, CONST:ro. + addi GPR:wo, GPR:ro, CONST+LABEL_LO:ro. li GPR:wo, CONST:ro. addis GPR:wo, GPR:ro, CONST+LABEL_HI+LABEL_HA:ro. lis GPR:wo, CONST+LABEL_HI+LABEL_HA:ro. @@ -333,7 +331,7 @@ INSTRUCTIONS lfd FPR:wo, IND_RC_D:ro cost(4, 5). lfdu FPR:wo, IND_RC_D:ro cost(4, 5). lfdx FPR:wo, GPR:ro, GPR:ro cost(4, 5). - lfs FSREG:wo, IND_RC_W:ro cost(4, 4). + lfs FSREG:wo, IND_RC_W+IND_RL_W:ro cost(4, 4). lfsu FSREG:wo, IND_RC_W:rw cost(4, 4). lfsx FSREG:wo, GPR:ro, GPR:ro cost(4, 4). lha GPR:wo, IND_RC_H_S:ro cost(4, 3). @@ -343,7 +341,7 @@ INSTRUCTIONS li32 GPR:wo, CONST:ro cost(8, 2). lwzu GPR:wo, IND_RC_W:ro cost(4, 3). lwzx GPR:wo, GPR:ro, GPR:ro cost(4, 3). - lwz GPR:wo, IND_RC_W+GPRINDIRECT_OFFSET_LO:ro cost(4, 3). + lwz GPR:wo, IND_RC_W+IND_RL_W:ro cost(4, 3). nand GPR:wo, GPR:ro, GPR:ro. neg GPR:wo, GPR:ro. nor GPR:wo, GPR:ro, GPR:ro. @@ -369,12 +367,12 @@ INSTRUCTIONS stfd FPR:ro, IND_RC_D:rw cost(4, 4). stfdu FPR:ro, IND_RC_D:rw cost(4, 4). stfdx FPR:ro, GPR:ro, GPR:ro cost(4, 4). - stfs FSREG:ro, IND_RC_W:rw cost(4, 3). + stfs FSREG:ro, IND_RC_W+IND_RL_W:rw cost(4, 3). stfsu FSREG:ro, IND_RC_W:rw cost(4, 3). stfsx FSREG:ro, GPR:ro, GPR:ro cost(4, 3). sth GPR:ro, IND_RC_H:rw cost(4, 3). sthx GPR:ro, GPR:ro, GPR:ro cost(4, 3). - stw GPR:ro, IND_RC_W:rw cost(4, 3). + stw GPR:ro, IND_RC_W+IND_RL_W:rw cost(4, 3). stwx GPR:ro, GPR:ro, GPR:ro cost(4, 3). stwu GPR+LOCAL:ro, IND_RC_W:rw cost(4, 3). xor GPR:wo, GPR:ro, GPR:ro. @@ -418,6 +416,16 @@ MOVES lis %2, {LABEL_HI, %1.adr} ori %2, %2, {LABEL_LO, %1.adr} + from LABEL_HA to GPR + gen + lis %2, %1 + + from LABEL_STACK to GPR + gen + move {LABEL_HA, %1.adr}, %1.reg + addi %2, %1.reg, {LABEL_LO, %1.adr} + + /* Sign extension */ from SEX_B to GPR @@ -512,6 +520,11 @@ MOVES COMMENT("move IND_RC_W->GPR") lwz %2, %1 + from IND_RL_W to GPR + gen + move {LABEL_HA, %1.adr}, %1.reg + lwz %2, %1 + from IND_RR_W to GPR gen COMMENT("move IND_RR_W->GPR") @@ -522,6 +535,11 @@ MOVES COMMENT("move IND_RC_W->FSREG") lfs %2, %1 + from IND_RL_W to FSREG + gen + move {LABEL_HA, %1.adr}, %1.reg + lfs %2, %1 + from IND_RR_W to FSREG gen COMMENT("move IND_RR_W->FSREG") @@ -714,9 +732,15 @@ STACKINGRULES stwu %1.2, {IND_RC_W, SP, 0-4} stwu %1.1, {IND_RC_W, SP, 0-4} - from CONST_STACK + LABEL to STACK + from CONST_STACK to STACK gen - COMMENT("stack CONST_STACK + LABEL") + COMMENT("stack CONST_STACK") + move %1, RSCRATCH + stwu RSCRATCH, {IND_RC_W, SP, 0-4} + + from LABEL_STACK to STACK + gen + COMMENT("stack LABEL_STACK") move %1, RSCRATCH stwu RSCRATCH, {IND_RC_W, SP, 0-4} @@ -1058,7 +1082,8 @@ PATTERNS lae $1 pat lae /* Load address of external */ - yields {LABEL, $1} + uses REG + yields {LABEL_STACK, %a, $1} pat loe /* Load word external */ leaving @@ -1155,17 +1180,13 @@ PATTERNS yields {IND_RC_H, %1.reg, %1.off} pat loi $1==INT32 /* Load word indirect */ - with LABEL - uses REG - gen - lis %a, {LABEL_HA, %1.adr} - lwz %a, {GPRINDIRECT_OFFSET_LO, %a, %1.adr} - yields %a with GPR yields {IND_RC_W, %1, 0} - with SUM_RC + with exact LABEL_STACK + yields {IND_RL_W, %1.reg, %1.adr} + with exact SUM_RC yields {IND_RC_W, %1.reg, %1.off} - with SUM_RR + with exact SUM_RR yields {IND_RR_W, %1.reg1, %1.reg2} pat loi $1==INT64 /* Load double-word indirect */ @@ -1240,15 +1261,25 @@ PATTERNS move %2.reg, {IND_RC_H, %1.reg, %1.off} pat sti $1==INT32 /* Store word indirect */ - with GPR GPR+FSREG + with REG REG+FSREG kills MEMORY gen move %2, {IND_RC_W, %1, 0} - with SUM_RR GPR+FSREG + with LABEL_STACK REG + kills MEMORY + gen + move {LABEL_HA, %1.adr}, %1.reg + stw %2, {IND_RL_W, %1.reg, %1.adr} + with LABEL_STACK FSREG + kills MEMORY + gen + move {LABEL_HA, %1.adr}, %1.reg + stfs %2, {IND_RL_W, %1.reg, %1.adr} + with SUM_RR REG+FSREG kills MEMORY gen move %2, {IND_RR_W, %1.reg1, %1.reg2} - with SUM_RC GPR+FSREG + with SUM_RC REG+FSREG kills MEMORY gen move %2, {IND_RC_W, %1.reg, %1.off} @@ -1384,8 +1415,12 @@ PATTERNS with REG CONST_STACK-CONST2-CONST_HZ uses reusing %1, REG={SUM_RIS, %1, his(%2.val)} yields {SUM_RC, %a, los(%2.val)} - with CONST_STACK LABEL - yields {LABEL, %2.adr+%1.val} + with exact CONST_STACK LABEL_STACK + uses reusing %2.reg, REG + yields {LABEL_STACK, %a, %2.adr+%1.val} + with exact LABEL_STACK CONST_STACK + uses reusing %1.reg, REG + yields {LABEL_STACK, %a, %1.adr+%2.val} pat sbi $1==4 /* Subtract word (second - top) */ with REG REG @@ -1401,8 +1436,9 @@ PATTERNS with CONST_STACK-CONST2_WHEN_NEG-CONST_HZ REG uses reusing %2, REG={SUM_RIS, %2, his(0-%1.val)} yields {SUM_RC, %a, los(0-%1.val)} - with CONST_STACK LABEL - yields {LABEL, %2.adr+(0-%1.val)} + with exact CONST_STACK LABEL_STACK + uses reusing %2.reg, REG + yields {LABEL_STACK, %a, %2.adr+(0-%1.val)} pat ngi $1==4 /* Negate word */ with REG From ed21a59a8217de116ee4b908cff2cafba825d337 Mon Sep 17 00:00:00 2001 From: George Koehler Date: Wed, 8 Feb 2017 12:23:06 -0500 Subject: [PATCH 166/173] In PowerPC ncg, allocate register for ha16[label]. Use it to generate code like lis r12,ha16[__II0] lis r11,ha16[_f] lfs f1,lo16[_f](r11) lfs f2,lo16[__II0](r12) fadds f13,f2,f1 stfs f13,lo16[_f](r11) Here ncg has allocated r11 for ha16[_f]. We use r11 in lfs and again in stfs. Before this change, we needed an extra lis before stfs, because ncg did not remember that ha16[_f] was in a register. This example has a gap between ha16[__II0] and lo16[__II0], because the lo16 is not in the next instruction. This requires my previous commit 1bf58cf for RELOLIS. There is a gap because ncg emits the lis as soon as I allocate it. The "lfs f2,lo16[__II0](r12)" happens in a coercion from IND_RL_W to FSREG. The coercion allocates one FSREG but may not allocate any other registers. So I must allocate r12 earlier. I allocate r12 in pat lae, but this causes a gap. --- mach/powerpc/ncg/table | 88 ++++++++++++++++-------------------------- 1 file changed, 34 insertions(+), 54 deletions(-) diff --git a/mach/powerpc/ncg/table b/mach/powerpc/ncg/table index 2794292a3..6d2d785bb 100644 --- a/mach/powerpc/ncg/table +++ b/mach/powerpc/ncg/table @@ -162,7 +162,6 @@ TOKENS LABEL_HI = { ADDR adr; } 4 "hi16[" adr "]". LABEL_HA = { ADDR adr; } 4 "ha16[" adr "]". LABEL_LO = { ADDR adr; } 4 "lo16[" adr "]". - LABEL_STACK = { GPR reg; ADDR adr; } 4. LOCAL = { INT off; } 4 ">>> BUG IN LOCAL". /* Allows us to use regvar() to refer to registers */ @@ -181,9 +180,10 @@ TOKENS /* Expression partial results */ - SUM_RIS = { GPR reg; INT offhi; } 4. - SUM_RC = { GPR reg; INT off; } 4. - SUM_RR = { GPR reg1; GPR reg2; } 4. + SUM_RIS = { GPR reg; INT offhi; } 4. /* reg + (offhi << 16) */ + SUM_RC = { GPR reg; INT off; } 4. /* reg + off */ + SUM_RL = { GPR reg; ADDR adr; } 4. /* reg + lo16[adr] */ + SUM_RR = { GPR reg1; GPR reg2; } 4. /* reg1 + reg2 */ SEX_B = { GPR reg; } 4. SEX_H = { GPR reg; } 4. @@ -237,7 +237,7 @@ SETS CONST_STACK = CONST_N8000 + CONST_N7FFF_N0001 + CONST_0000_7FFF + CONST_8000 + CONST_8001_FFFF + CONST_HZ + CONST_HL. - SUM_ALL = SUM_RC + SUM_RR. + SUM_ALL = SUM_RC + SUM_RL + SUM_RR. SEX_ALL = SEX_B + SEX_H. @@ -420,12 +420,6 @@ MOVES gen lis %2, %1 - from LABEL_STACK to GPR - gen - move {LABEL_HA, %1.adr}, %1.reg - addi %2, %1.reg, {LABEL_LO, %1.adr} - - /* Sign extension */ from SEX_B to GPR @@ -450,6 +444,11 @@ MOVES COMMENT("move SUM_RC->GPR") addi %2, %1.reg, {CONST, %1.off} + from SUM_RL to GPR + gen + COMMENT("move SUM_RL->GPR") + addi %2, %1.reg, {LABEL_LO, %1.adr} + from SUM_RR to GPR gen COMMENT("move SUM_RR->GPR") @@ -522,7 +521,6 @@ MOVES from IND_RL_W to GPR gen - move {LABEL_HA, %1.adr}, %1.reg lwz %2, %1 from IND_RR_W to GPR @@ -537,7 +535,6 @@ MOVES from IND_RL_W to FSREG gen - move {LABEL_HA, %1.adr}, %1.reg lfs %2, %1 from IND_RR_W to FSREG @@ -552,6 +549,10 @@ MOVES COMMENT("move GPR->IND_RC_W") stw %1, %2 + from GPR to IND_RL_W + gen + stw %1, %2 + from GPR to IND_RR_W gen COMMENT("move GPR->IND_RR_W") @@ -562,6 +563,10 @@ MOVES COMMENT("move FSREG->IND_RC_W") stfs %1, %2 + from FSREG to IND_RL_W + gen + stfs %1, %2 + from FSREG to IND_RR_W gen COMMENT("move FSREG->IND_RR_W") @@ -738,12 +743,6 @@ STACKINGRULES move %1, RSCRATCH stwu RSCRATCH, {IND_RC_W, SP, 0-4} - from LABEL_STACK to STACK - gen - COMMENT("stack LABEL_STACK") - move %1, RSCRATCH - stwu RSCRATCH, {IND_RC_W, SP, 0-4} - from SEX_B to STACK gen COMMENT("stack SEX_B") @@ -1082,8 +1081,8 @@ PATTERNS lae $1 pat lae /* Load address of external */ - uses REG - yields {LABEL_STACK, %a, $1} + uses REG={LABEL_HA, $1} + yields {SUM_RL, %a, $1} pat loe /* Load word external */ leaving @@ -1111,20 +1110,16 @@ PATTERNS ste $1 pat ine /* Increment external */ - kills MEMORY - uses REG={LABEL, $1}, REG - gen - lwz %b, {IND_RC_W, %a, 0} - addi %b, %b, {CONST, 1} - stw %b, {IND_RC_W, %a, 0} + leaving + loe $1 + inc + ste $1 pat dee /* Decrement external */ - kills MEMORY - uses REG={LABEL, $1}, REG - gen - lwz %b, {IND_RC_W, %a, 0} - addi %b, %b, {CONST, 0-1} - stw %b, {IND_RC_W, %a, 0} + leaving + loe $1 + dec + ste $1 @@ -1182,10 +1177,10 @@ PATTERNS pat loi $1==INT32 /* Load word indirect */ with GPR yields {IND_RC_W, %1, 0} - with exact LABEL_STACK - yields {IND_RL_W, %1.reg, %1.adr} with exact SUM_RC yields {IND_RC_W, %1.reg, %1.off} + with exact SUM_RL + yields {IND_RL_W, %1.reg, %1.adr} with exact SUM_RR yields {IND_RR_W, %1.reg1, %1.reg2} @@ -1265,20 +1260,14 @@ PATTERNS kills MEMORY gen move %2, {IND_RC_W, %1, 0} - with LABEL_STACK REG - kills MEMORY - gen - move {LABEL_HA, %1.adr}, %1.reg - stw %2, {IND_RL_W, %1.reg, %1.adr} - with LABEL_STACK FSREG - kills MEMORY - gen - move {LABEL_HA, %1.adr}, %1.reg - stfs %2, {IND_RL_W, %1.reg, %1.adr} with SUM_RR REG+FSREG kills MEMORY gen move %2, {IND_RR_W, %1.reg1, %1.reg2} + with SUM_RL REG+FSREG + kills MEMORY + gen + move %2, {IND_RL_W, %1.reg, %1.adr} with SUM_RC REG+FSREG kills MEMORY gen @@ -1415,12 +1404,6 @@ PATTERNS with REG CONST_STACK-CONST2-CONST_HZ uses reusing %1, REG={SUM_RIS, %1, his(%2.val)} yields {SUM_RC, %a, los(%2.val)} - with exact CONST_STACK LABEL_STACK - uses reusing %2.reg, REG - yields {LABEL_STACK, %a, %2.adr+%1.val} - with exact LABEL_STACK CONST_STACK - uses reusing %1.reg, REG - yields {LABEL_STACK, %a, %1.adr+%2.val} pat sbi $1==4 /* Subtract word (second - top) */ with REG REG @@ -1436,9 +1419,6 @@ PATTERNS with CONST_STACK-CONST2_WHEN_NEG-CONST_HZ REG uses reusing %2, REG={SUM_RIS, %2, his(0-%1.val)} yields {SUM_RC, %a, los(0-%1.val)} - with exact CONST_STACK LABEL_STACK - uses reusing %2.reg, REG - yields {LABEL_STACK, %a, %2.adr+(0-%1.val)} pat ngi $1==4 /* Negate word */ with REG From 5e00e1fce2583e08447324bdd0c3c60c51302445 Mon Sep 17 00:00:00 2001 From: George Koehler Date: Wed, 8 Feb 2017 12:27:16 -0500 Subject: [PATCH 167/173] Trimming mach/powerpc/ncg/table Remove coercion from LABEL to REG. The coercion never happens because I have stopped putting LABEL on the stack. Also remove LABEL from set ANY_BHW. Retain the move from LABEL to REG because pat gto uses it. Remove li32 instruction, unused after the switch to the hi16, ha16, lo16 syntax. Remove COMMENT(...) lines from most moves. In my opinion, they took too much space, both in the table and in the assembly output. The stacking rules and coercions keep their COMMENT(...) lines. In test GPR, don't write to RSCRATCH. Fold several coercions into a single coercion from ANY_BHW uses REG. Use REG instead of GPR in stack patterns. REG and GPR act the same, because every GPR on the stack is a REG, but I want to be clear that I expect a REG, not r0. In code rules, sort SUM_RC before SORT_RR, so I can add SUM_RL later. Remove rules to optimize loc loc cii loc loc cii. If $2==$4, the peephole optimizer can optimize it. If $2!=$4, then the EM program is missing a conversion from size $2 to size $4. Remove rules to store a SEX_B with sti 1 or a SEX_H with sti 2. These rules would never get used, unless the EM program is missing a conversion from size 4 to size 1 or 2. --- mach/powerpc/ncg/table | 418 ++++++++++++----------------------------- 1 file changed, 117 insertions(+), 301 deletions(-) diff --git a/mach/powerpc/ncg/table b/mach/powerpc/ncg/table index 6d2d785bb..c608b2fd6 100644 --- a/mach/powerpc/ncg/table +++ b/mach/powerpc/ncg/table @@ -28,7 +28,6 @@ PC_OFFSET = 4 /* Offset of saved PC relative to our FP */ #define his(n) ((hi(n) + (lo(n)>>15)) & 0xFFFF) - PROPERTIES GPR /* any GPR */ @@ -50,6 +49,7 @@ PROPERTIES FPR16(8) FPR17(8) FPR18(8) FPR19(8) FPR20(8) FPR21(8) FPR22(8) FPR23(8) FPR24(8) FPR25(8) FPR26(8) FPR27(8) FPR28(8) FPR29(8) FPR30(8) FPR31(8) + REGISTERS /* Reverse order to encourage ncg to allocate them from r31 down */ @@ -255,7 +255,7 @@ SETS MEMORY = IND_ALL_BHW + IND_ALL_D. /* any stack token that we can easily move to GPR */ - ANY_BHW = REG + CONST_STACK + LABEL + SEX_ALL + + ANY_BHW = REG + CONST_STACK + SEX_ALL + SUM_ALL + IND_ALL_BHW + LOGICAL_ALL. @@ -338,7 +338,6 @@ INSTRUCTIONS lhax GPR:wo, GPR:ro, GPR:ro cost(4, 3). lhz GPR:wo, IND_RC_H:ro cost(4, 3). lhzx GPR:wo, GPR:ro, GPR:ro cost(4, 3). - li32 GPR:wo, CONST:ro cost(8, 2). lwzu GPR:wo, IND_RC_W:ro cost(4, 3). lwzx GPR:wo, GPR:ro, GPR:ro cost(4, 3). lwz GPR:wo, IND_RC_W+IND_RL_W:ro cost(4, 3). @@ -354,6 +353,7 @@ INSTRUCTIONS ori GPR:wo, GPR:ro, CONST+LABEL_LO:ro. oris GPR:wo, GPR:ro, CONST:ro. orX "or." GPR:wo:cc, GPR:ro, GPR:ro. + orX_readonly "or." GPR:ro:cc, GPR:ro, GPR:ro. rlwinm GPR:wo, GPR:ro, CONST:ro, CONST:ro, CONST:ro. extlwi GPR:wo, GPR:ro, CONST:ro, CONST:ro. extrwi GPR:wo, GPR:ro, CONST:ro, CONST:ro. @@ -382,13 +382,10 @@ INSTRUCTIONS comment "!" LABEL:ro cost(0, 0). - MOVES from GPR to GPR - gen - COMMENT("move GPR->GPR") - or %2, %1, %1 + gen or %2, %1, %1 /* Constants */ @@ -417,226 +414,149 @@ MOVES ori %2, %2, {LABEL_LO, %1.adr} from LABEL_HA to GPR - gen - lis %2, %1 + gen lis %2, %1 /* Sign extension */ from SEX_B to GPR - gen - COMMENT("move SEX_B->GPR") - extsb %2, %1.reg + gen extsb %2, %1.reg from SEX_H to GPR - gen - COMMENT("move SEX_H->GPR") - extsh %2, %1.reg + gen extsh %2, %1.reg /* Register + something */ from SUM_RIS to GPR - gen - COMMENT("move SUM_RIS->GPR") - addis %2, %1.reg, {CONST, %1.offhi} + gen addis %2, %1.reg, {CONST, %1.offhi} from SUM_RC to GPR - gen - COMMENT("move SUM_RC->GPR") - addi %2, %1.reg, {CONST, %1.off} + gen addi %2, %1.reg, {CONST, %1.off} from SUM_RL to GPR - gen - COMMENT("move SUM_RL->GPR") - addi %2, %1.reg, {LABEL_LO, %1.adr} + gen addi %2, %1.reg, {LABEL_LO, %1.adr} from SUM_RR to GPR - gen - COMMENT("move SUM_RR->GPR") - add %2, %1.reg1, %1.reg2 + gen add %2, %1.reg1, %1.reg2 /* Read byte */ from IND_RC_B to GPR - gen - COMMENT("move IND_RC_B->GPR") - lbz %2, %1 + gen lbz %2, %1 from IND_RR_B to GPR - gen - COMMENT("move IND_RR_B->GPR") - lbzx %2, %1.reg1, %1.reg2 + gen lbzx %2, %1.reg1, %1.reg2 /* Write byte */ from GPR to IND_RC_B - gen - COMMENT("move GPR->IND_RC_B") - stb %1, %2 + gen stb %1, %2 from GPR to IND_RR_B - gen - COMMENT("move GPR->IND_RR_B") - stbx %1, %2.reg1, %2.reg2 + gen stbx %1, %2.reg1, %2.reg2 /* Read halfword (short) */ from IND_RC_H to GPR - gen - COMMENT("move IND_RC_H->GPR") - lhz %2, %1 + gen lhz %2, %1 from IND_RR_H to GPR - gen - COMMENT("move IND_RR_H->GPR") - lhzx %2, %1.reg1, %1.reg2 + gen lhzx %2, %1.reg1, %1.reg2 from IND_RC_H_S to GPR - gen - COMMENT("move IND_RC_H_S->GPR") - lha %2, %1 + gen lha %2, %1 from IND_RR_H_S to GPR - gen - COMMENT("move IND_RR_H_S->GPR") - lhax %2, %1.reg1, %1.reg2 + gen lhax %2, %1.reg1, %1.reg2 /* Write halfword */ from GPR to IND_RC_H - gen - COMMENT("move GPR->IND_RC_H") - sth %1, %2 + gen sth %1, %2 from GPR to IND_RR_H - gen - COMMENT("move GPR->IND_RR_H") - sthx %1, %2.reg1, %2.reg2 + gen sthx %1, %2.reg1, %2.reg2 /* Read word */ from IND_RC_W to GPR - gen - COMMENT("move IND_RC_W->GPR") - lwz %2, %1 + gen lwz %2, %1 from IND_RL_W to GPR - gen - lwz %2, %1 + gen lwz %2, %1 from IND_RR_W to GPR - gen - COMMENT("move IND_RR_W->GPR") - lwzx %2, %1.reg1, %1.reg2 + gen lwzx %2, %1.reg1, %1.reg2 from IND_RC_W to FSREG - gen - COMMENT("move IND_RC_W->FSREG") - lfs %2, %1 + gen lfs %2, %1 from IND_RL_W to FSREG - gen - lfs %2, %1 + gen lfs %2, %1 from IND_RR_W to FSREG - gen - COMMENT("move IND_RR_W->FSREG") - lfsx %2, %1.reg1, %1.reg2 + gen lfsx %2, %1.reg1, %1.reg2 /* Write word */ from GPR to IND_RC_W - gen - COMMENT("move GPR->IND_RC_W") - stw %1, %2 + gen stw %1, %2 from GPR to IND_RL_W - gen - stw %1, %2 + gen stw %1, %2 from GPR to IND_RR_W - gen - COMMENT("move GPR->IND_RR_W") - stwx %1, %2.reg1, %2.reg2 + gen stwx %1, %2.reg1, %2.reg2 from FSREG to IND_RC_W - gen - COMMENT("move FSREG->IND_RC_W") - stfs %1, %2 + gen stfs %1, %2 from FSREG to IND_RL_W - gen - stfs %1, %2 + gen stfs %1, %2 from FSREG to IND_RR_W - gen - COMMENT("move FSREG->IND_RR_W") - stfsx %1, %2.reg1, %2.reg2 + gen stfsx %1, %2.reg1, %2.reg2 /* Read double */ from IND_RC_D to FPR - gen - COMMENT("move IND_RC_D->FPR") - lfd %2, {IND_RC_D, %1.reg, %1.off} + gen lfd %2, {IND_RC_D, %1.reg, %1.off} from IND_RR_D to FPR - gen - COMMENT("move IND_RR_D->FPR") - lfdx %2, %1.reg1, %1.reg2 + gen lfdx %2, %1.reg1, %1.reg2 /* Write double */ from FPR to IND_RC_D - gen - COMMENT("move FPR->IND_RC_D") - stfd %1, {IND_RC_D, %2.reg, %2.off} + gen stfd %1, {IND_RC_D, %2.reg, %2.off} from FPR to IND_RR_D - gen - COMMENT("move FPR->IND_RR_W") - stfdx %1, %2.reg1, %2.reg2 + gen stfdx %1, %2.reg1, %2.reg2 /* Logicals */ from NOT_R to GPR - gen - COMMENT("move NOT_R->GPR") - nor %2, %1.reg, %1.reg + gen nor %2, %1.reg, %1.reg from AND_RR to GPR - gen - COMMENT("move AND_RR->GPR") - and %2, %1.reg1, %1.reg2 + gen and %2, %1.reg1, %1.reg2 from OR_RR to GPR - gen - COMMENT("move OR_RR->GPR") - or %2, %1.reg1, %1.reg2 + gen or %2, %1.reg1, %1.reg2 from OR_RIS to GPR - gen - COMMENT("move OR_RIS->GPR") - oris %2, %1.reg, {CONST, %1.valhi} + gen oris %2, %1.reg, {CONST, %1.valhi} from OR_RC to GPR - gen - COMMENT("move OR_RC->GPR") - ori %2, %1.reg, {CONST, %1.val} + gen ori %2, %1.reg, {CONST, %1.val} from XOR_RR to GPR - gen - COMMENT("move XOR_RR->GPR") - xor %2, %1.reg1, %1.reg2 + gen xor %2, %1.reg1, %1.reg2 from XOR_RIS to GPR - gen - COMMENT("move XOR_RIS->GPR") - xoris %2, %1.reg, {CONST, %1.valhi} + gen xoris %2, %1.reg, {CONST, %1.valhi} from XOR_RC to GPR - gen - COMMENT("move XOR_RC->GPR") - xori %2, %1.reg, {CONST, %1.val} + gen xori %2, %1.reg, {CONST, %1.val} /* Conditions */ @@ -707,16 +627,17 @@ MOVES an expression) as a register constant. */ from ANY_BHW to GPRE - gen - move %1, %2.reg + gen move %1, %2.reg TESTS + /* Given orX %1, %1, %1, ncgg says, "Instruction destroys %1, + * not allowed here". We use orX_readonly to trick ncgg. + */ to test GPR gen - orX RSCRATCH, %1, %1 - + orX_readonly %1, %1, %1 STACKINGRULES @@ -787,24 +708,10 @@ STACKINGRULES COERCIONS - from REG + from ANY_BHW uses REG gen - COMMENT("coerce REG->REG") - move %1, %a - yields %a - - from CONST + CONST_STACK - uses REG - gen - COMMENT("coerce CONST->REG") - move %1, %a - yields %a - - from LABEL - uses REG - gen - COMMENT("coerce LABEL->REG") + COMMENT("coerce ANY_BHW->REG") move %1, %a yields %a @@ -825,26 +732,6 @@ COERCIONS addi SP, SP, {CONST, 8} yields %a - from SEX_B - uses REG - gen - COMMENT("coerce SEX_B->REG") - extsb %a, %1.reg - yields %a - - from SEX_H - uses REG - gen - COMMENT("coerce SEX_H->REG") - extsh %a, %1.reg - yields %a - - from SUM_ALL + LOGICAL_ALL - uses REG - gen - move %1, %a - yields %a - from FSREG uses FSREG gen @@ -873,12 +760,6 @@ COERCIONS addi SP, SP, {CONST, 4} yields %a - from IND_ALL_BHW - uses REG - gen - move %1, %a - yields %a - from IND_ALL_W uses FSREG gen @@ -958,18 +839,6 @@ PATTERNS /* Type conversions */ - pat loc loc cii loc loc cii $1==$4 && $2==$5 /* madness, generated by the C compiler */ - leaving - loc $1 - loc $2 - cii - - pat loc loc cii loc loc cii $2==INT32 && $5==INT32 && $4<$2 /* madness, generated by the C compiler */ - leaving - loc $4 - loc $5 - cii - pat loc loc ciu /* signed X -> unsigned X */ leaving loc $1 @@ -992,17 +861,14 @@ PATTERNS /* nop */ pat loc loc cii $1==INT8 && $2==INT32 /* signed char -> signed int */ - with GPR + with REG yields {SEX_B, %1} pat loc loc cii $1==2 && $2==4 /* signed char -> signed short */ - with GPR + with REG yields {SEX_H, %1} - - - /* Local variables */ pat lal smalls($1) /* Load address of local */ @@ -1122,7 +988,6 @@ PATTERNS ste $1 - /* Structures */ pat lof /* Load word offsetted */ @@ -1146,36 +1011,35 @@ PATTERNS sti INT64 - /* Loads and stores */ pat loi $1==INT8 /* Load byte indirect */ - with GPR + with REG yields {IND_RC_B, %1, 0} - with SUM_RR - yields {IND_RR_B, %1.reg1, %1.reg2} - with SUM_RC + with exact SUM_RC yields {IND_RC_B, %1.reg, %1.off} + with exact SUM_RR + yields {IND_RR_B, %1.reg1, %1.reg2} pat loi loc loc cii $1==INT16 && $2==INT16 && $3==INT32 /* Load half-word indirect and sign extend */ - with GPR + with REG yields {IND_RC_H_S, %1, 0} - with SUM_RR - yields {IND_RR_H_S, %1.reg1, %1.reg2} - with SUM_RC + with exact SUM_RC yields {IND_RC_H_S, %1.reg, %1.off} + with exact SUM_RR + yields {IND_RR_H_S, %1.reg1, %1.reg2} pat loi $1==INT16 /* Load half-word indirect */ - with GPR + with REG yields {IND_RC_H, %1, 0} - with SUM_RR - yields {IND_RR_H, %1.reg1, %1.reg2} - with SUM_RC + with exact SUM_RC yields {IND_RC_H, %1.reg, %1.off} + with exact SUM_RR + yields {IND_RR_H, %1.reg1, %1.reg2} pat loi $1==INT32 /* Load word indirect */ - with GPR + with REG yields {IND_RC_W, %1, 0} with exact SUM_RC yields {IND_RC_W, %1.reg, %1.off} @@ -1185,11 +1049,11 @@ PATTERNS yields {IND_RR_W, %1.reg1, %1.reg2} pat loi $1==INT64 /* Load double-word indirect */ - with GPR + with REG yields {IND_RC_D, %1, 0} - with SUM_RC + with exact SUM_RC yields {IND_RC_D, %1.reg, %1.off} - with SUM_RR + with exact SUM_RR yields {IND_RR_D, %1.reg1, %1.reg2} pat loi /* Load arbitrary size */ @@ -1204,88 +1068,51 @@ PATTERNS bl {LABEL, ".los"} pat sti $1==INT8 /* Store byte indirect */ - with GPR GPR + with REG REG kills MEMORY - gen - stb %2, {IND_RC_B, %1, 0} - with SUM_RR GPR + gen move %2, {IND_RC_B, %1, 0} + with SUM_RC REG kills MEMORY - gen - stbx %2, %1.reg1, %1.reg2 - with SUM_RC GPR + gen move %2, {IND_RC_B, %1.reg, %1.off} + with SUM_RR REG kills MEMORY - gen - move %2, {IND_RC_B, %1.reg, %1.off} - with GPR SEX_B - kills MEMORY - gen - stb %2.reg, {IND_RC_B, %1, 0} - with SUM_RR SEX_B - kills MEMORY - gen - stbx %2.reg, %1.reg1, %1.reg2 - with SUM_RC SEX_B - kills MEMORY - gen - move %2.reg, {IND_RC_B, %1.reg, %1.off} + gen move %2, {IND_RR_B, %1.reg1, %1.reg2} pat sti $1==INT16 /* Store half-word indirect */ - with GPR GPR + with REG REG kills MEMORY - gen - sth %2, {IND_RC_H, %1, 0} - with SUM_RR GPR + gen move %2, {IND_RC_H, %1, 0} + with SUM_RC REG kills MEMORY - gen - sthx %2, %1.reg1, %1.reg2 - with SUM_RC GPR + gen move %2, {IND_RC_H, %1.reg, %1.off} + with SUM_RR REG kills MEMORY - gen - move %2, {IND_RC_H, %1.reg, %1.off} - with GPR SEX_H - kills MEMORY - gen - sth %2.reg, {IND_RC_H, %1, 0} - with SUM_RR SEX_H - kills MEMORY - gen - sthx %2.reg, %1.reg1, %1.reg2 - with SUM_RC SEX_H - kills MEMORY - gen - move %2.reg, {IND_RC_H, %1.reg, %1.off} + gen move %2, {IND_RR_H, %1.reg1, %1.reg2} pat sti $1==INT32 /* Store word indirect */ with REG REG+FSREG kills MEMORY - gen - move %2, {IND_RC_W, %1, 0} - with SUM_RR REG+FSREG - kills MEMORY - gen - move %2, {IND_RR_W, %1.reg1, %1.reg2} - with SUM_RL REG+FSREG - kills MEMORY - gen - move %2, {IND_RL_W, %1.reg, %1.adr} + gen move %2, {IND_RC_W, %1, 0} with SUM_RC REG+FSREG kills MEMORY - gen - move %2, {IND_RC_W, %1.reg, %1.off} + gen move %2, {IND_RC_W, %1.reg, %1.off} + with SUM_RL REG+FSREG + kills MEMORY + gen move %2, {IND_RL_W, %1.reg, %1.adr} + with SUM_RR REG+FSREG + kills MEMORY + gen move %2, {IND_RR_W, %1.reg1, %1.reg2} pat sti $1==INT64 /* Store double-word indirect */ with REG FREG kills MEMORY - gen - move %2, {IND_RC_D, %1, 0} - with SUM_RR FREG - kills MEMORY - gen - move %2, {IND_RR_D, %1.reg1, %1.reg2} + gen move %2, {IND_RC_D, %1, 0} with SUM_RC FREG kills MEMORY - gen - move %2, {IND_RC_D, %1.reg, %1.off} + gen move %2, {IND_RC_D, %1.reg, %1.off} + with SUM_RR FREG + kills MEMORY + gen move %2, {IND_RR_D, %1.reg1, %1.reg2} /* * This pattern would be too slow: * with REG REG REG @@ -1331,7 +1158,6 @@ PATTERNS bl {LABEL, ".sts"} - /* Arithmetic wrappers */ pat ads $1==4 /* Add var to pointer */ @@ -1382,7 +1208,6 @@ PATTERNS sli $1 - /* Word arithmetic */ pat adi $1==4 /* Add word (second + top) */ @@ -1467,34 +1292,34 @@ PATTERNS yields %a pat and $1==4 /* AND word */ - with GPR NOT_R + with REG NOT_R uses reusing %1, REG gen andc %a, %1, %2.reg yields %a - with NOT_R GPR + with NOT_R REG uses reusing %1, REG gen andc %a, %2, %1.reg yields %a - with GPR GPR + with REG REG yields {AND_RR, %1, %2} - with GPR UCONST2 + with REG UCONST2 uses reusing %1, REG gen andiX %a, %1, {CONST, %2.val} yields %a - with UCONST2 GPR + with UCONST2 REG uses reusing %2, REG gen andiX %a, %2, {CONST, %1.val} yields %a - with GPR CONST_HZ + with REG CONST_HZ uses reusing %1, REG gen andisX %a, %1, {CONST, hi(%2.val)} yields %a - with CONST_HZ GPR + with CONST_HZ REG uses reusing %2, REG gen andisX %a, %2, {CONST, hi(%1.val)} @@ -1592,7 +1417,7 @@ PATTERNS gen eqv %a, %1.reg1, %1.reg2 yields %a - with GPR + with REG yields {NOT_R, %1} pat com defined($1) /* NOT set */ @@ -1614,36 +1439,36 @@ PATTERNS cal ".zer" pat sli $1==4 /* Shift left (second << top) */ - with CONST_STACK GPR + with CONST_STACK REG uses reusing %2, REG gen rlwinm %a, %2, {CONST, (%1.val & 0x1F)}, {CONST, 0}, {CONST, 31-(%1.val & 0x1F)} yields %a - with GPR GPR + with REG REG uses reusing %2, REG gen slw %a, %2, %1 yields %a pat sri $1==4 /* Shift right signed (second >> top) */ - with CONST_STACK GPR + with CONST_STACK REG uses reusing %2, REG gen srawi %a, %2, {CONST, %1.val & 0x1F} yields %a - with GPR GPR + with REG REG uses reusing %2, REG gen sraw %a, %2, %1 yields %a pat sru $1==4 /* Shift right unsigned (second >> top) */ - with CONST_STACK GPR + with CONST_STACK REG uses reusing %2, REG gen rlwinm %a, %2, {CONST, 32-(%1.val & 0x1F)}, {CONST, (%1.val & 0x1F)}, {CONST, 31} yields %a - with GPR GPR + with REG REG uses reusing %2, REG gen srw %a, %2, %1 @@ -1685,7 +1510,6 @@ PATTERNS bl {LABEL, ".sar4"} - /* Sets */ pat set defined($1) /* Create singleton set */ @@ -1708,7 +1532,6 @@ PATTERNS cal ".inn" - /* Boolean resolutions */ pat teq /* top = (top == 0) */ @@ -1934,7 +1757,6 @@ PATTERNS yields %a - /* Simple branches */ proc zxx example zeq @@ -2001,7 +1823,6 @@ PATTERNS pat cmu zle $1==4 call cmu4zxx("ble", "bge") - /* Comparisons */ /* Each comparison extracts the lt and gt bits from cr0. @@ -2057,7 +1878,6 @@ PATTERNS yields R3 - /* Other branching and labelling */ pat lab topeltsize($1)==4 && !fallthrough($1) @@ -2090,7 +1910,6 @@ PATTERNS b {LABEL, $1} - /* Miscellaneous */ pat cal /* Call procedure */ @@ -2100,7 +1919,7 @@ PATTERNS bl {LABEL, $1} pat cai /* Call procedure indirect */ - with GPR STACK + with REG STACK kills ALL gen mtspr CTR, %1 @@ -2130,7 +1949,7 @@ PATTERNS b {LABEL, ".ret"} pat blm /* Block move constant length */ - with GPR GPR STACK + with REG REG STACK uses REG gen move {CONST, $1}, %a @@ -2141,7 +1960,7 @@ PATTERNS addi SP, SP, {CONST, 12} pat bls /* Block move variable length */ - with GPR GPR GPR STACK + with REG REG REG STACK gen stwu %1, {IND_RC_W, SP, 0-4} stwu %3, {IND_RC_W, SP, 0-4} @@ -2160,7 +1979,6 @@ PATTERNS b {LABEL, ".csb"} - /* EM specials */ pat fil /* Set current filename */ @@ -2208,7 +2026,7 @@ PATTERNS dch pat dch /* FP -> caller FP */ - with GPR + with REG uses reusing %1, REG gen lwz %a, {IND_RC_W, %1, FP_OFFSET} @@ -2246,17 +2064,17 @@ PATTERNS yields %a pat str $1==0 /* Store FP */ - with GPR + with REG gen move %1, FP pat str $1==1 /* Store SP */ - with GPR + with REG gen move %1, SP pat loc ass $1==4 && $2==4 /* Drop 4 bytes from stack */ - with exact GPR + with exact REG /* nop */ with STACK gen @@ -2273,7 +2091,7 @@ PATTERNS gen move {SUM_RC, SP, his(%1.val)}, SP move {SUM_RC, SP, los(%1.val)}, SP - with GPR STACK + with REG STACK gen move {SUM_RR, SP, %1}, SP @@ -2292,8 +2110,6 @@ PATTERNS yields %1 - - /* Floating point support */ /* All very cheap and nasty --- this needs to be properly integrated into From 85391399a407abc734216a88952d90195a7fd3d4 Mon Sep 17 00:00:00 2001 From: George Koehler Date: Wed, 8 Feb 2017 12:31:14 -0500 Subject: [PATCH 168/173] Use ha16/lo16 to load or store 1, 2, 8 bytes from labels. Add the tokens IND_RL_B, IND_RL_H, IND_RL_H_S, IND_RL_D, along with the rules to use them. These rules emit shorter code. For example, loading a byte becomes lis, lbz instead of lis, addi, lbz. While making this, I wrongly set IND_RL_D to size 4. Then ncg made infinite recursion in codegen() and stackupto(), until it crashed by stack overflow. I correctly set IND_RL_D to size 8, preventing the crash. --- mach/powerpc/ncg/table | 81 +++++++++++++++++++++++------------------- 1 file changed, 45 insertions(+), 36 deletions(-) diff --git a/mach/powerpc/ncg/table b/mach/powerpc/ncg/table index c608b2fd6..5a5d7ce52 100644 --- a/mach/powerpc/ncg/table +++ b/mach/powerpc/ncg/table @@ -189,15 +189,19 @@ TOKENS SEX_H = { GPR reg; } 4. IND_RC_B = { GPR reg; INT off; } 4 off "(" reg ")". + IND_RL_B = { GPR reg; ADDR adr; } 4 "lo16[" adr "](" reg ")". IND_RR_B = { GPR reg1; GPR reg2; } 4. IND_RC_H = { GPR reg; INT off; } 4 off "(" reg ")". + IND_RL_H = { GPR reg; ADDR adr; } 4 "lo16[" adr "](" reg ")". IND_RR_H = { GPR reg1; GPR reg2; } 4. IND_RC_H_S = { GPR reg; INT off; } 4 off "(" reg ")". + IND_RL_H_S = { GPR reg; ADDR adr; } 4 "lo16[" adr "](" reg ")". IND_RR_H_S = { GPR reg1; GPR reg2; } 4. IND_RC_W = { GPR reg; INT off; } 4 off "(" reg ")". IND_RL_W = { GPR reg; ADDR adr; } 4 "lo16[" adr "](" reg ")". IND_RR_W = { GPR reg1; GPR reg2; } 4. IND_RC_D = { GPR reg; INT off; } 8 off "(" reg ")". + IND_RL_D = { GPR reg; ADDR adr; } 8 "lo16[" adr "](" reg ")". IND_RR_D = { GPR reg1; GPR reg2; } 8. NOT_R = { GPR reg; } 4. @@ -244,11 +248,11 @@ SETS LOGICAL_ALL = NOT_R + AND_RR + OR_RR + OR_RC + XOR_RR + XOR_RC. - /* indirect values */ - IND_ALL_B = IND_RC_B + IND_RR_B. - IND_ALL_H = IND_RC_H + IND_RR_H + IND_RC_H_S + IND_RR_H_S. + IND_ALL_B = IND_RC_B + IND_RL_B + IND_RR_B. + IND_ALL_H = IND_RC_H + IND_RL_H + IND_RR_H + + IND_RC_H_S + IND_RL_H_S + IND_RR_H_S. IND_ALL_W = IND_RC_W + IND_RL_W + IND_RR_W. - IND_ALL_D = IND_RC_D + IND_RR_D. + IND_ALL_D = IND_RC_D + IND_RL_D + IND_RR_D. IND_ALL_BHW = IND_ALL_B + IND_ALL_H + IND_ALL_W. /* anything killed by sti (store indirect) */ @@ -326,17 +330,17 @@ INSTRUCTIONS frsp FSREG:wo, FREG:ro cost(4, 5). fsub FREG:wo, FREG:ro, FREG:ro cost(4, 5). fsubs FSREG:wo, FSREG:ro, FSREG:ro cost(4, 5). - lbz GPR:wo, IND_RC_B:ro cost(4, 3). + lbz GPR:wo, IND_RC_B+IND_RL_B:ro cost(4, 3). lbzx GPR:wo, GPR:ro, GPR:ro cost(4, 3). - lfd FPR:wo, IND_RC_D:ro cost(4, 5). + lfd FPR:wo, IND_RC_D+IND_RL_D:ro cost(4, 5). lfdu FPR:wo, IND_RC_D:ro cost(4, 5). lfdx FPR:wo, GPR:ro, GPR:ro cost(4, 5). lfs FSREG:wo, IND_RC_W+IND_RL_W:ro cost(4, 4). lfsu FSREG:wo, IND_RC_W:rw cost(4, 4). lfsx FSREG:wo, GPR:ro, GPR:ro cost(4, 4). - lha GPR:wo, IND_RC_H_S:ro cost(4, 3). + lha GPR:wo, IND_RC_H_S+IND_RL_H_S:ro cost(4, 3). lhax GPR:wo, GPR:ro, GPR:ro cost(4, 3). - lhz GPR:wo, IND_RC_H:ro cost(4, 3). + lhz GPR:wo, IND_RC_H+IND_RL_H:ro cost(4, 3). lhzx GPR:wo, GPR:ro, GPR:ro cost(4, 3). lwzu GPR:wo, IND_RC_W:ro cost(4, 3). lwzx GPR:wo, GPR:ro, GPR:ro cost(4, 3). @@ -362,15 +366,15 @@ INSTRUCTIONS sraw GPR:wo, GPR:ro, GPR:ro cost(4, 2). srawi GPR:wo, GPR:ro, CONST:ro cost(4, 2). srw GPR:wo, GPR:ro, GPR:ro. - stb GPR:ro, IND_RC_B:rw cost(4, 3). + stb GPR:ro, IND_RC_B+IND_RL_B:rw cost(4, 3). stbx GPR:ro, GPR:ro, GPR:ro cost(4, 3). - stfd FPR:ro, IND_RC_D:rw cost(4, 4). + stfd FPR:ro, IND_RC_D+IND_RL_D:rw cost(4, 4). stfdu FPR:ro, IND_RC_D:rw cost(4, 4). stfdx FPR:ro, GPR:ro, GPR:ro cost(4, 4). stfs FSREG:ro, IND_RC_W+IND_RL_W:rw cost(4, 3). stfsu FSREG:ro, IND_RC_W:rw cost(4, 3). stfsx FSREG:ro, GPR:ro, GPR:ro cost(4, 3). - sth GPR:ro, IND_RC_H:rw cost(4, 3). + sth GPR:ro, IND_RC_H+IND_RL_H:rw cost(4, 3). sthx GPR:ro, GPR:ro, GPR:ro cost(4, 3). stw GPR:ro, IND_RC_W+IND_RL_W:rw cost(4, 3). stwx GPR:ro, GPR:ro, GPR:ro cost(4, 3). @@ -440,7 +444,7 @@ MOVES /* Read byte */ - from IND_RC_B to GPR + from IND_RC_B+IND_RL_B to GPR gen lbz %2, %1 from IND_RR_B to GPR @@ -448,7 +452,7 @@ MOVES /* Write byte */ - from GPR to IND_RC_B + from GPR to IND_RC_B+IND_RL_B gen stb %1, %2 from GPR to IND_RR_B @@ -456,13 +460,13 @@ MOVES /* Read halfword (short) */ - from IND_RC_H to GPR + from IND_RC_H+IND_RL_H to GPR gen lhz %2, %1 from IND_RR_H to GPR gen lhzx %2, %1.reg1, %1.reg2 - from IND_RC_H_S to GPR + from IND_RC_H_S+IND_RL_H_S to GPR gen lha %2, %1 from IND_RR_H_S to GPR @@ -470,7 +474,7 @@ MOVES /* Write halfword */ - from GPR to IND_RC_H + from GPR to IND_RC_H+IND_RL_H gen sth %1, %2 from GPR to IND_RR_H @@ -478,19 +482,13 @@ MOVES /* Read word */ - from IND_RC_W to GPR - gen lwz %2, %1 - - from IND_RL_W to GPR + from IND_RC_W+IND_RL_W to GPR gen lwz %2, %1 from IND_RR_W to GPR gen lwzx %2, %1.reg1, %1.reg2 - from IND_RC_W to FSREG - gen lfs %2, %1 - - from IND_RL_W to FSREG + from IND_RC_W+IND_RL_W to FSREG gen lfs %2, %1 from IND_RR_W to FSREG @@ -498,19 +496,13 @@ MOVES /* Write word */ - from GPR to IND_RC_W - gen stw %1, %2 - - from GPR to IND_RL_W + from GPR to IND_RC_W+IND_RL_W gen stw %1, %2 from GPR to IND_RR_W gen stwx %1, %2.reg1, %2.reg2 - from FSREG to IND_RC_W - gen stfs %1, %2 - - from FSREG to IND_RL_W + from FSREG to IND_RC_W+IND_RL_W gen stfs %1, %2 from FSREG to IND_RR_W @@ -518,16 +510,16 @@ MOVES /* Read double */ - from IND_RC_D to FPR - gen lfd %2, {IND_RC_D, %1.reg, %1.off} + from IND_RC_D+IND_RL_D to FPR + gen lfd %2, %1 from IND_RR_D to FPR gen lfdx %2, %1.reg1, %1.reg2 /* Write double */ - from FPR to IND_RC_D - gen stfd %1, {IND_RC_D, %2.reg, %2.off} + from FPR to IND_RC_D+IND_RL_D + gen stfd %1, %2 from FPR to IND_RR_D gen stfdx %1, %2.reg1, %2.reg2 @@ -1018,6 +1010,8 @@ PATTERNS yields {IND_RC_B, %1, 0} with exact SUM_RC yields {IND_RC_B, %1.reg, %1.off} + with exact SUM_RL + yields {IND_RL_B, %1.reg, %1.adr} with exact SUM_RR yields {IND_RR_B, %1.reg1, %1.reg2} @@ -1027,6 +1021,8 @@ PATTERNS yields {IND_RC_H_S, %1, 0} with exact SUM_RC yields {IND_RC_H_S, %1.reg, %1.off} + with exact SUM_RL + yields {IND_RL_H_S, %1.reg, %1.adr} with exact SUM_RR yields {IND_RR_H_S, %1.reg1, %1.reg2} @@ -1035,6 +1031,8 @@ PATTERNS yields {IND_RC_H, %1, 0} with exact SUM_RC yields {IND_RC_H, %1.reg, %1.off} + with exact SUM_RL + yields {IND_RL_H, %1.reg, %1.adr} with exact SUM_RR yields {IND_RR_H, %1.reg1, %1.reg2} @@ -1053,6 +1051,8 @@ PATTERNS yields {IND_RC_D, %1, 0} with exact SUM_RC yields {IND_RC_D, %1.reg, %1.off} + with exact SUM_RL + yields {IND_RL_D, %1.reg, %1.adr} with exact SUM_RR yields {IND_RR_D, %1.reg1, %1.reg2} @@ -1074,6 +1074,9 @@ PATTERNS with SUM_RC REG kills MEMORY gen move %2, {IND_RC_B, %1.reg, %1.off} + with SUM_RL REG + kills MEMORY + gen move %2, {IND_RL_B, %1.reg, %1.adr} with SUM_RR REG kills MEMORY gen move %2, {IND_RR_B, %1.reg1, %1.reg2} @@ -1085,6 +1088,9 @@ PATTERNS with SUM_RC REG kills MEMORY gen move %2, {IND_RC_H, %1.reg, %1.off} + with SUM_RL REG + kills MEMORY + gen move %2, {IND_RL_H, %1.reg, %1.adr} with SUM_RR REG kills MEMORY gen move %2, {IND_RR_H, %1.reg1, %1.reg2} @@ -1110,6 +1116,9 @@ PATTERNS with SUM_RC FREG kills MEMORY gen move %2, {IND_RC_D, %1.reg, %1.off} + with SUM_RL FREG + kills MEMORY + gen move %2, {IND_RL_D, %1.reg, %1.adr} with SUM_RR FREG kills MEMORY gen move %2, {IND_RR_D, %1.reg1, %1.reg2} From 83c13597e104c031a753365efce2b4f3bdb21480 Mon Sep 17 00:00:00 2001 From: George Koehler Date: Fri, 10 Feb 2017 11:45:50 -0500 Subject: [PATCH 169/173] Use "mr" and make a few other tweaks in PowerPC ncg table. Use extended "mr" instead of basic "or" to move registers. Both "mr" and "or" encode the same machine instruction. With "mr", I can more easily search the assembly output for register moves. Fold several stacking rules into a single rule ANY_BHW-REG to STACK. Remove the EM patterns for loc mlu $2==2 and loc slu. The first pattern had the wrong size (should be $2==4, not $2==2). Both patterns were redundant. They rewrote loc mlu as loc mli and loc slu as loc sli, but this table doesn't have patterns for loc mli or loc sli, so it is enough to rewrite mlu as mli and slu as sli. --- mach/powerpc/ncg/table | 52 +++++++++--------------------------------- 1 file changed, 11 insertions(+), 41 deletions(-) diff --git a/mach/powerpc/ncg/table b/mach/powerpc/ncg/table index 5a5d7ce52..24822482c 100644 --- a/mach/powerpc/ncg/table +++ b/mach/powerpc/ncg/table @@ -353,11 +353,12 @@ INSTRUCTIONS mfspr GPR:wo, SPR:ro cost(4, 3). mtspr SPR:wo, GPR:ro cost(4, 2). or GPR:wo, GPR:ro, GPR:ro. + mr GPR:wo, GPR:ro. + orX "or." GPR:wo:cc, GPR:ro, GPR:ro. + orX_readonly "or." GPR:ro:cc, GPR:ro, GPR:ro. orc GPR:wo, GPR:ro, GPR:ro. ori GPR:wo, GPR:ro, CONST+LABEL_LO:ro. oris GPR:wo, GPR:ro, CONST:ro. - orX "or." GPR:wo:cc, GPR:ro, GPR:ro. - orX_readonly "or." GPR:ro:cc, GPR:ro, GPR:ro. rlwinm GPR:wo, GPR:ro, CONST:ro, CONST:ro, CONST:ro. extlwi GPR:wo, GPR:ro, CONST:ro, CONST:ro. extrwi GPR:wo, GPR:ro, CONST:ro, CONST:ro. @@ -389,7 +390,7 @@ INSTRUCTIONS MOVES from GPR to GPR - gen or %2, %1, %1 + gen mr %2, %1 /* Constants */ @@ -626,6 +627,9 @@ TESTS /* Given orX %1, %1, %1, ncgg says, "Instruction destroys %1, * not allowed here". We use orX_readonly to trick ncgg. + * + * Using "or." and not "mr." because mach/powerpc/top/table + * was optimizing "or." and not "mr.". */ to test GPR gen @@ -650,33 +654,9 @@ STACKINGRULES stwu %1.2, {IND_RC_W, SP, 0-4} stwu %1.1, {IND_RC_W, SP, 0-4} - from CONST_STACK to STACK + from ANY_BHW-REG to STACK gen - COMMENT("stack CONST_STACK") - move %1, RSCRATCH - stwu RSCRATCH, {IND_RC_W, SP, 0-4} - - from SEX_B to STACK - gen - COMMENT("stack SEX_B") - extsb RSCRATCH, %1.reg - stwu RSCRATCH, {IND_RC_W, SP, 0-4} - - from SEX_H to STACK - gen - COMMENT("stack SEX_H") - extsh RSCRATCH, %1.reg - stwu RSCRATCH, {IND_RC_W, SP, 0-4} - - from SUM_ALL + LOGICAL_ALL to STACK - gen - COMMENT("stack SUM_ALL + LOGICAL_ALL") - move %1, RSCRATCH - stwu RSCRATCH, {IND_RC_W, SP, 0-4} - - from IND_ALL_BHW to STACK - gen - COMMENT("stack IND_ALL_BHW") + COMMENT("stack ANY_BHW-REG") move %1, RSCRATCH stwu RSCRATCH, {IND_RC_W, SP, 0-4} @@ -1198,21 +1178,11 @@ PATTERNS loc 1 sbi 4 - pat loc mlu $2==2 /* Unsigned multiply by constant */ - leaving - loc $1 - mli 4 - - pat mlu /* Unsigned multiply by var */ + pat mlu /* Multiply unsigned */ leaving mli $1 - pat loc slu /* Shift left unsigned by constant amount */ - leaving - loc $1 - sli $2 - - pat slu /* Shift left unsigned by variable amount */ + pat slu /* Shift left unsigned */ leaving sli $1 From 13beb5e336002c314d36f729b5aea4bb181e2a23 Mon Sep 17 00:00:00 2001 From: George Koehler Date: Fri, 10 Feb 2017 11:59:34 -0500 Subject: [PATCH 170/173] Document RELOLIS from commit 1bf58cf. I hastily chose the name RELOLIS for this relocation type. If we want to rename it, we only need to edit these files: - h/out.h - mach/powerpc/as/mach5.c - util/amisc/ashow.c - util/led/ack.out.5 - util/led/relocate.c --- util/led/ack.out.5 | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/util/led/ack.out.5 b/util/led/ack.out.5 index fa997e8ca..c8b9fc8fa 100644 --- a/util/led/ack.out.5 +++ b/util/led/ack.out.5 @@ -161,12 +161,13 @@ struct outrelo { /* * relocation type bits */ -#define RELSZ 0x0fff /* relocation length */ +#define RELSZ 0x0fff /* relocation length */ #define RELO1 0x01 /* 1 byte */ #define RELO2 0x02 /* 2 bytes */ #define RELO4 0x03 /* 4 bytes */ #define RELOPPC 0x04 /* 26-bit PowerPC address */ -#define RELOVC4 0x06 /* VideoCore IV address in 32-bit insruction */ +#define RELOLIS 0x05 /* PowerPC lis */ +#define RELOVC4 0x06 /* VideoCore IV address in 32-bit insruction */ #define RELPC 0x2000 /* pc relative */ #define RELBR 0x4000 /* High order byte lowest address. */ #define RELWR 0x8000 /* High order word lowest address. */ @@ -225,10 +226,23 @@ is an absolute number, and the datum is relocated pc relative. The relocatable datum must then be relocated with respect to the base address of its section. .PP +For RELOPPC and RELOVC4, the relocatable datum is a PowerPC or +VideoCore IV instruction. +The relocation depends on the instruction, and uses an offset encoded +in the instruction. +.PP +RELOLIS assembles a PowerPC \fBlis\fR instruction. +The relocatable datum is a 4-byte integer. +The high bit is set for ha16 or clear for hi16. +The next 5 bits are the register \fIRT\fR. +The low 26 bits are a signed offset. +The relocation replaces the datum with the PowerPC instruction +\(oq\fBlis\fR\ \fIRT\fR,\ ha16[\fIsymbol\fR\ +\ \fIoffset\fR]\(cq. +.PP .B The symbol table. .br -This table contains definitions of symbols. It is referred to by -outrelo-structures, and can be used by debuggers. +This table contains definitions of symbols. +It is referred to by outrelo-structures, and can be used by debuggers. Entries in this table have the following structure: .PP .nf From f2e3d7b38ce2db0901278960c65b9de9267472c0 Mon Sep 17 00:00:00 2001 From: David Given Date: Sun, 23 Jul 2017 21:19:07 +0200 Subject: [PATCH 171/173] Don't define functions called itoa(), because this causes problems on platforms that define itoa() in their libcs. --- lang/basic/src/basic.lex | 2 +- lang/basic/src/bem.h | 2 +- lang/basic/src/gencode.c | 2 +- lang/basic/src/util.c | 2 +- lang/occam/comp/em.c | 4 ++-- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/lang/basic/src/basic.lex b/lang/basic/src/basic.lex index 4eb9e1659..3ee185e3f 100644 --- a/lang/basic/src/basic.lex +++ b/lang/basic/src/basic.lex @@ -522,7 +522,7 @@ scanstring() yylval.integer= genemlabel(); C_rom_dlb((label)i,(arith)0); C_rom_icon("9999",(arith)BEMINTSIZE); - C_rom_icon(itoa(length),(arith)BEMINTSIZE); + C_rom_icon(myitoa(length),(arith)BEMINTSIZE); } #ifdef YYDEBUG if (yydebug) print("STRVALUE found\n"); diff --git a/lang/basic/src/bem.h b/lang/basic/src/bem.h index deb6eb435..d49523cd4 100644 --- a/lang/basic/src/bem.h +++ b/lang/basic/src/bem.h @@ -71,7 +71,7 @@ extern int dataused; extern Linerecord *currline; -extern char *itoa(); +extern char *myitoa(); extern char *salloc(); extern char *strcpy(); diff --git a/lang/basic/src/gencode.c b/lang/basic/src/gencode.c index 8fb611dc0..710de169d 100644 --- a/lang/basic/src/gencode.c +++ b/lang/basic/src/gencode.c @@ -670,7 +670,7 @@ gendata() C_df_dnam("datfdes"); C_rom_dnam("datfname",(arith)0); C_rom_cst((arith)1); - C_rom_cst((arith)(itoa(strlen(datfname)))); + C_rom_cst((arith)(myitoa(strlen(datfname)))); C_df_dnam("dattdes"); C_rom_dnam("dattyp",(arith)0); C_rom_cst((arith)1); diff --git a/lang/basic/src/util.c b/lang/basic/src/util.c index ff98cf82b..a85339bc5 100644 --- a/lang/basic/src/util.c +++ b/lang/basic/src/util.c @@ -69,7 +69,7 @@ illegalcmd() -char *itoa(i) +char *myitoa(i) int i; { static char buf[30]; diff --git a/lang/occam/comp/em.c b/lang/occam/comp/em.c index ecd779824..605817371 100644 --- a/lang/occam/comp/em.c +++ b/lang/occam/comp/em.c @@ -355,7 +355,7 @@ void zgt(lab) int lab; { C_zgt((label) lab); } void zlt(lab) int lab; { C_zlt((label) lab); } void zne(lab) int lab; { C_zne((label) lab); } -char *itoa(i) long i; +char *myitoa(i) long i; { static char a[sizeof(long)*3]; sprint(a, "%ld", i); @@ -364,7 +364,7 @@ char *itoa(i) long i; void rom(size, c) int size; long c; { - C_rom_icon(itoa(c), (arith) size); + C_rom_icon(myitoa(c), (arith) size); } void lin() From 064fd52d52aeaa4d0ca549bfbcac416d3a6b7056 Mon Sep 17 00:00:00 2001 From: David Given Date: Wed, 2 Aug 2017 00:07:51 +0200 Subject: [PATCH 172/173] Update man page not to mention the filename length restriction removed in 893471a42eb4d189cc0ba1dac1864d6f151bccd7. --- lang/m2/comp/modula-2.1 | 5 ----- 1 file changed, 5 deletions(-) diff --git a/lang/m2/comp/modula-2.1 b/lang/m2/comp/modula-2.1 index 206d33bb7..ee9bc94bd 100644 --- a/lang/m2/comp/modula-2.1 +++ b/lang/m2/comp/modula-2.1 @@ -19,11 +19,6 @@ Implementation modules and program modules must reside in files having a .PP The name of the file in which a definition module is stored must be the same as the module-name, apart from the extension. -Also, in most Unix systems filenames are only 14 characters long. -So, given an IMPORT declaration for a module called "LongModulName", -the compiler will try to open a file called "LongModulN.def". -The requirement does not hold for implementation or program modules, -but is certainly recommended. .SH CALLING THE COMPILER The easiest way to do this is to let the \fIack\fR(1) program do it. So, to compile a program module "prog.mod", just call From 7ff0b65a0dbc7de4d908a424a5c043194a241826 Mon Sep 17 00:00:00 2001 From: David Given Date: Sat, 5 Aug 2017 21:46:43 +0200 Subject: [PATCH 173/173] Add missing headers. --- modules/src/object/obj.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/modules/src/object/obj.h b/modules/src/object/obj.h index 8f7fd8d32..9000b32ce 100644 --- a/modules/src/object/obj.h +++ b/modules/src/object/obj.h @@ -6,6 +6,8 @@ #include #include #include +#include +#include #include #include #include