#include <endian.h>
+#include <fcntl.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <unistd.h>
#if ALT_BACKEND
#include "Musashi/m68k.h"
#else
#include "cpu_68000.h"
#endif
+#include "x_exec.h"
#define EXCEPTION_TRAP_BASE 0x20
#define REG_TRACE 0
#define MEM_TRACE 0
-#define MEM_SIZE 0x8000
+#define MEM_SIZE 0x10000
#if __BYTE_ORDER == __LITTLE_ENDIAN
#define MEM_SIZE_M1 (MEM_SIZE - 1)
#define MEM_SIZE_M2 (MEM_SIZE - 2)
uint32_t l[MEM_SIZE >> 2];
} mem;
-void load_s19(char *name) {
- FILE *fp = fopen(name, "r");
- if (fp == NULL) {
- perror(name);
+// used with be_read() and be_write()
+// when host/target endianness differs, pass pointer to end of buffer,
+// and then the buffer will be read or written backwards from the end
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+#define BE_PTR(name) ((uint8_t *)&(name) + sizeof(name))
+#define BE_XOR ((size_t)-1)
+#else
+#define BE_PTR(name) ((uint8_t *)&(name))
+#define BE_XOR 0
+#endif
+
+uint8_t *be_buf;
+size_t be_buf_size;
+
+void be_resize(size_t count) {
+ free(be_buf);
+ be_buf = malloc(count);
+ if (be_buf == NULL) {
+ perror("realloc()");
exit(EXIT_FAILURE);
}
+ be_buf_size = count;
+}
- char line[0x100];
- while (fgets(line, 0x100, fp)) {
- for (char *p = line; *p; ++p)
- if (*p == '\n') {
- *p = 0;
- break;
- }
-
- // allow comments and concatenation
- if (line[0] != 'S' || line[1] != '1')
- continue;
-
- uint8_t buf[0x7f];
- int len;
- for (len = 0; len < 0x7f; ++len) {
- char *p = line + 2 + len * 2;
- if (*p == 0)
- break;
- if (*p == '\n') {
- *p = 0;
- break;
- }
- uint8_t c = p[2];
- p[2] = 0;
-
- char *q;
- buf[len] = (uint8_t)strtol(p, &q, 16);
- p[2] = c;
- if (q != p + 2) {
- fprintf(stderr, "not hex byte: %s\n", p);
- exit(EXIT_FAILURE);
- }
- }
+ssize_t be_read(int fd, uint8_t *buf, size_t count) {
+ if (count > be_buf_size)
+ be_resize(count);
- if (len < 4) {
- fprintf(stderr, "too short: %s\n", line);
- exit(EXIT_FAILURE);
- }
+ ssize_t result = read(fd, be_buf, count);
+ if (result == (ssize_t)-1)
+ return (ssize_t)-1;
- uint8_t checksum = 0;
- for (int i = 0; i < len; ++i)
- checksum += buf[i];
- if (checksum != 0xff) {
- checksum -= 0xff + buf[len - 1];
- fprintf(
- stderr,
- "checksum %02x, should be %02x\n",
- checksum,
- buf[len - 1]
- );
- exit(EXIT_FAILURE);
- }
+ for (size_t i = 0; i < (size_t)result; ++i)
+ buf[i ^ BE_XOR] = be_buf[i];
- if (len != buf[0] + 1) {
- fprintf(stderr, "incorrect length: %s\n", line);
- exit(EXIT_FAILURE);
- }
- len -= 4;
+ return result;
+}
- int addr = (buf[1] << 8) | buf[2], end_addr;
- end_addr = addr + len;
- if (end_addr < addr || end_addr > MEM_SIZE) {
- fprintf(stderr, "invalid load range: [0x%x, 0x%x)\n", addr, end_addr);
- exit(EXIT_FAILURE);
- }
- for (int i = 0; i < len; ++i)
- mem.b[(addr + i) ^ MEM_SIZE_M1] = buf[3 + i];
+ssize_t be_write(int fd, uint8_t *buf, size_t count) {
+ if (count > be_buf_size)
+ be_resize(count);
+
+ for (size_t i = 0; i < count; ++i)
+ be_buf[i] = buf[i ^ BE_XOR];
+
+ return write(fd, be_buf, count);
+}
+
+void load_aout(char *name) {
+ int fd = open(name, O_RDONLY);
+ if (fd == -1) {
+ perror(name);
+ exit(EXIT_FAILURE);
}
- fclose(fp);
+ struct x_exec aout_header;
+ switch (be_read(fd, BE_PTR(aout_header), sizeof(aout_header))) {
+ case sizeof(aout_header):
+ break;
+ case (ssize_t)-1:
+ perror("read()");
+ exit(EXIT_FAILURE);
+ default:
+ fprintf(stderr, "short read\n");
+ exit(EXIT_FAILURE);
+ }
+
+ if (aout_header.x_a_magic != x_ZMAGIC) {
+ fprintf(stderr, "unrecognized magic 0%o\n", aout_header.x_a_magic);
+ exit(EXIT_FAILURE);
+ }
+
+ if (aout_header.x_a_mid != x_MID_HP300) {
+ fprintf(stderr, "unrecognized machine ID 0%o\n", aout_header.x_a_mid);
+ exit(EXIT_FAILURE);
+ }
+
+ fprintf(stderr, "ok\n");
+ exit(EXIT_FAILURE);
+
+ close(fd);
}
int read_byte(void *context, int addr) {
int main(int argc, char **argv) {
if (argc < 2) {
- printf("usage: %s image.s19\n", argv[0]);
+ printf("usage: %s executable\n", argv[0]);
exit(EXIT_FAILURE);
}
- load_s19(argv[1]);
+ load_aout(argv[1]);
// emulate Tutor firmware for TBI68K
mem.l[(0 ^ MEM_SIZE_M4) >> 2] = 0x8000; // initial SP
--- /dev/null
+/*-
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)exec.h 8.1 (Berkeley) 6/10/93
+ */
+
+/* note: this file normally goes in the machine-specific dir and is included
+ * from the generic file, hence doesn't normally have multi include protection
+ */
+#ifndef x_EXEC_H
+#define x_EXEC_H
+
+#include <endian.h>
+#include "xify.h"
+
+/* Size of a page in an object file. */
+#define x___LDPGSZ 4096
+
+/* Valid magic number check. */
+#define x_N_BADMAG(x_ex) \
+ ((x_ex).x_a_magic != x_NMAGIC && (x_ex).x_a_magic != x_OMAGIC && \
+ (x_ex).x_a_magic != x_ZMAGIC)
+
+/* Address of the bottom of the text segment. */
+#define x_N_TXTADDR(x_X) 0
+
+/* Address of the bottom of the data segment. */
+#define x_N_DATADDR(x_ex) \
+ (x_N_TXTADDR(x_ex) + ((x_ex).x_a_magic == x_OMAGIC ? (x_ex).x_a_text \
+ : x___LDPGSZ + ((x_ex).x_a_text - 1 & ~(x___LDPGSZ - 1))))
+
+/* Text segment offset. */
+#define x_N_TXTOFF(x_ex) \
+ ((x_ex).x_a_magic == x_ZMAGIC ? x___LDPGSZ : sizeof(struct x_exec))
+
+/* Data segment offset. */
+#define x_N_DATOFF(x_ex) \
+ (x_N_TXTOFF(x_ex) + ((x_ex).x_a_magic != x_ZMAGIC ? (x_ex).x_a_text : \
+ x___LDPGSZ + ((x_ex).x_a_text - 1 & ~(x___LDPGSZ - 1))))
+
+/* Symbol table offset. */
+#define x_N_SYMOFF(x_ex) \
+ (x_N_TXTOFF(x_ex) + (x_ex).x_a_text + (x_ex).x_a_data + (x_ex).x_a_trsize + \
+ (x_ex).x_a_drsize)
+
+/* String table offset. */
+#define x_N_STROFF(x_ex) (x_N_SYMOFF(x_ex) + (x_ex).x_a_syms)
+
+/* Description of the object file header (a.out format). */
+struct x_exec {
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+ x_u_long x_a_drsize; /* data relocation size */
+ x_u_long x_a_trsize; /* text relocation size */
+ x_u_long x_a_entry; /* entry point */
+ x_u_long x_a_syms; /* symbol table size */
+ x_u_long x_a_bss; /* uninitialized data size */
+ x_u_long x_a_data; /* initialized data size */
+ x_u_long x_a_text; /* text segment size */
+
+ x_u_short x_a_magic; /* magic number */
+#define x_ZMAGIC 0413 /* demand load format */
+#define x_NMAGIC 0410 /* read-only text */
+#define x_OMAGIC 0407 /* old impure format */
+
+ x_u_short x_a_mid; /* machine ID */
+#define x_MID_HPUX800 0x20B /* hp800 HP-UX binary */
+#define x_MID_HPUX 0x20C /* hp200/300 HP-UX binary */
+#define x_MID_HP300 300 /* hp300 (68020+68881) BSD binary */
+#define x_MID_HP200 200 /* hp200 (68010) BSD binary */
+#define x_MID_SUN_SPARC 3 /* sparc binary */
+#define x_MID_SUN020 2 /* sun 68020-only binary */
+#define x_MID_SUN010 1 /* sun 68010/68020 binary */
+#define x_MID_ZERO 0 /* unknown - implementation dependent */
+#else
+#define x_MID_ZERO 0 /* unknown - implementation dependent */
+#define x_MID_SUN010 1 /* sun 68010/68020 binary */
+#define x_MID_SUN020 2 /* sun 68020-only binary */
+#define x_MID_SUN_SPARC 3 /* sparc binary */
+#define x_MID_HP200 200 /* hp200 (68010) BSD binary */
+#define x_MID_HP300 300 /* hp300 (68020+68881) BSD binary */
+#define x_MID_HPUX 0x20C /* hp200/300 HP-UX binary */
+#define x_MID_HPUX800 0x20B /* hp800 HP-UX binary */
+ x_u_short x_a_mid; /* machine ID */
+
+#define x_OMAGIC 0407 /* old impure format */
+#define x_NMAGIC 0410 /* read-only text */
+#define x_ZMAGIC 0413 /* demand load format */
+ x_u_short x_a_magic; /* magic number */
+
+ x_u_long x_a_text; /* text segment size */
+ x_u_long x_a_data; /* initialized data size */
+ x_u_long x_a_bss; /* uninitialized data size */
+ x_u_long x_a_syms; /* symbol table size */
+ x_u_long x_a_entry; /* entry point */
+ x_u_long x_a_trsize; /* text relocation size */
+ x_u_long x_a_drsize; /* data relocation size */
+#endif
+};
+#define x_a_machtype x_a_mid /* SUN compatibility */
+
+#endif