Add xified hp300/exec.h from 4.4BSD, can recognize a.out magic and machine ID
authorNick Downing <nick@ndcode.org>
Sun, 21 Aug 2022 12:41:31 +0000 (22:41 +1000)
committerNick Downing <nick@ndcode.org>
Sun, 21 Aug 2022 12:41:31 +0000 (22:41 +1000)
Makefile
emu_68000.c
x_exec.h [new file with mode: 0644]
xify.h [new file with mode: 0644]

index 4985e36..5582254 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -25,7 +25,9 @@ softfloat.o
 
 emu_68000_alt.o: \
 emu_68000.c \
-Musashi/m68k.h
+Musashi/m68k.h \
+x_exec.h \
+xify.h
        ${CC} ${CFLAGS} ${ALT_68000_CFLAGS} -o $@ -c $<
 
 m68kcpu.o: Musashi/m68kcpu.c Musashi/m68kfpu.c
index 762038d..691e5ea 100644 (file)
@@ -1,21 +1,24 @@
 #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)
@@ -31,83 +34,87 @@ union {
   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) {
@@ -288,10 +295,10 @@ int m68k_service_trap(unsigned int vector) {
 
 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
diff --git a/x_exec.h b/x_exec.h
new file mode 100644 (file)
index 0000000..d3bea7e
--- /dev/null
+++ b/x_exec.h
@@ -0,0 +1,130 @@
+/*-
+ * 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
diff --git a/xify.h b/xify.h
new file mode 100644 (file)
index 0000000..7bc3bdc
--- /dev/null
+++ b/xify.h
@@ -0,0 +1,16 @@
+#ifndef _XIFY_H
+#define _XIFY_H
+
+#include <stdint.h>
+
+typedef int16_t x_short;
+typedef int32_t x_int;
+typedef int32_t x_long;
+typedef uint16_t x_u_short;
+typedef uint32_t x_u_int;
+typedef uint32_t x_u_long;
+typedef uint16_t x_unsigned_short;
+typedef uint32_t x_unsigned_int;
+typedef uint32_t x_unsigned_long;
+
+#endif