Get the emulator to the point where it'll start to run code; it then fails,
authorDavid Given <dg@cowlark.com>
Tue, 5 Jun 2018 14:17:22 +0000 (23:17 +0900)
committerDavid Given <dg@cowlark.com>
Tue, 5 Jun 2018 14:17:22 +0000 (23:17 +0900)
because the version of Musashi I imported doesn't support floating point...

plat/linux68k/emu/m68kconf.h
plat/linux68k/emu/sim.c
plat/linux68k/tests/build.lua [new file with mode: 0644]

index 05cc6ad..c5c9b1a 100755 (executable)
-/* ======================================================================== */\r
-/* ========================= LICENSING & COPYRIGHT ======================== */\r
-/* ======================================================================== */\r
-/*\r
- *                                  MUSASHI\r
- *                                Version 3.4\r
- *\r
- * A portable Motorola M680x0 processor emulation engine.\r
- * Copyright 1998-2001 Karl Stenerud.  All rights reserved.\r
- *\r
- * This code may be freely used for non-commercial purposes as long as this\r
- * copyright notice remains unaltered in the source code and any binary files\r
- * containing this code in compiled form.\r
- *\r
- * All other lisencing terms must be negotiated with the author\r
- * (Karl Stenerud).\r
- *\r
- * The latest version of this code can be obtained at:\r
- * http://kstenerud.cjb.net\r
- */\r
-\r
-\r
-\r
-#ifndef M68KCONF__HEADER\r
-#define M68KCONF__HEADER\r
-\r
-\r
-/* Configuration switches.\r
- * Use OPT_SPECIFY_HANDLER for configuration options that allow callbacks.\r
- * OPT_SPECIFY_HANDLER causes the core to link directly to the function\r
- * or macro you specify, rather than using callback functions whose pointer\r
- * must be passed in using m68k_set_xxx_callback().\r
- */\r
-#define OPT_OFF             0\r
-#define OPT_ON              1\r
-#define OPT_SPECIFY_HANDLER 2\r
-\r
-\r
-/* ======================================================================== */\r
-/* ============================== MAME STUFF ============================== */\r
-/* ======================================================================== */\r
-\r
-/* If you're compiling this for MAME, only change M68K_COMPILE_FOR_MAME\r
- * to OPT_ON and use m68kmame.h to configure the 68k core.\r
- */\r
-#ifndef M68K_COMPILE_FOR_MAME\r
-#define M68K_COMPILE_FOR_MAME      OPT_OFF\r
-#endif /* M68K_COMPILE_FOR_MAME */\r
-\r
-\r
-#if M68K_COMPILE_FOR_MAME == OPT_OFF\r
-\r
-\r
-/* ======================================================================== */\r
-/* ============================= CONFIGURATION ============================ */\r
-/* ======================================================================== */\r
-\r
-/* Turn ON if you want to use the following M68K variants */\r
-#define M68K_EMULATE_010            OPT_ON\r
-#define M68K_EMULATE_EC020          OPT_ON\r
-#define M68K_EMULATE_020            OPT_ON\r
-\r
-\r
-/* If ON, the CPU will call m68k_read_immediate_xx() for immediate addressing\r
- * and m68k_read_pcrelative_xx() for PC-relative addressing.\r
- * If off, all read requests from the CPU will be redirected to m68k_read_xx()\r
- */\r
-#define M68K_SEPARATE_READS         OPT_OFF\r
-\r
-/* If ON, the CPU will call m68k_write_32_pd() when it executes move.l with a\r
- * predecrement destination EA mode instead of m68k_write_32().\r
- * To simulate real 68k behavior, m68k_write_32_pd() must first write the high\r
- * word to [address+2], and then write the low word to [address].\r
- */\r
-#define M68K_SIMULATE_PD_WRITES     OPT_OFF\r
-\r
-/* If ON, CPU will call the interrupt acknowledge callback when it services an\r
- * interrupt.\r
- * If off, all interrupts will be autovectored and all interrupt requests will\r
- * auto-clear when the interrupt is serviced.\r
- */\r
-#define M68K_EMULATE_INT_ACK        OPT_SPECIFY_HANDLER\r
-#define M68K_INT_ACK_CALLBACK(A)    cpu_irq_ack(A)\r
-\r
-\r
-/* If ON, CPU will call the breakpoint acknowledge callback when it encounters\r
- * a breakpoint instruction and it is running a 68010+.\r
- */\r
-#define M68K_EMULATE_BKPT_ACK       OPT_OFF\r
-#define M68K_BKPT_ACK_CALLBACK()    your_bkpt_ack_handler_function()\r
-\r
-\r
-/* If ON, the CPU will monitor the trace flags and take trace exceptions\r
- */\r
-#define M68K_EMULATE_TRACE          OPT_OFF\r
-\r
-\r
-/* If ON, CPU will call the output reset callback when it encounters a reset\r
- * instruction.\r
- */\r
-#define M68K_EMULATE_RESET          OPT_SPECIFY_HANDLER\r
-#define M68K_RESET_CALLBACK()       cpu_pulse_reset()\r
-\r
-\r
-/* If ON, CPU will call the set fc callback on every memory access to\r
- * differentiate between user/supervisor, program/data access like a real\r
- * 68000 would.  This should be enabled and the callback should be set if you\r
- * want to properly emulate the m68010 or higher. (moves uses function codes\r
- * to read/write data from different address spaces)\r
- */\r
-#define M68K_EMULATE_FC             OPT_SPECIFY_HANDLER\r
-#define M68K_SET_FC_CALLBACK(A)     cpu_set_fc(A)\r
-\r
-\r
-/* If ON, CPU will call the pc changed callback when it changes the PC by a\r
- * large value.  This allows host programs to be nicer when it comes to\r
- * fetching immediate data and instructions on a banked memory system.\r
- */\r
-#define M68K_MONITOR_PC             OPT_OFF\r
-#define M68K_SET_PC_CALLBACK(A)     your_pc_changed_handler_function(A)\r
-\r
-\r
-/* If ON, CPU will call the instruction hook callback before every\r
- * instruction.\r
- */\r
-#define M68K_INSTRUCTION_HOOK       OPT_SPECIFY_HANDLER\r
-#define M68K_INSTRUCTION_CALLBACK() cpu_instr_callback()\r
-\r
-\r
-/* If ON, the CPU will emulate the 4-byte prefetch queue of a real 68000 */\r
-#define M68K_EMULATE_PREFETCH       OPT_ON\r
-\r
-\r
-/* If ON, the CPU will generate address error exceptions if it tries to\r
- * access a word or longword at an odd address.\r
- * NOTE: This is only emulated properly for 68000 mode.\r
- */\r
-#define M68K_EMULATE_ADDRESS_ERROR  OPT_ON\r
-\r
-\r
-/* Turn ON to enable logging of illegal instruction calls.\r
- * M68K_LOG_FILEHANDLE must be #defined to a stdio file stream.\r
- * Turn on M68K_LOG_1010_1111 to log all 1010 and 1111 calls.\r
- */\r
-#define M68K_LOG_ENABLE             OPT_OFF\r
-#define M68K_LOG_1010_1111          OPT_OFF\r
-#define M68K_LOG_FILEHANDLE         some_file_handle\r
-\r
-\r
-/* ----------------------------- COMPATIBILITY ---------------------------- */\r
-\r
-/* The following options set optimizations that violate the current ANSI\r
- * standard, but will be compliant under the forthcoming C9X standard.\r
- */\r
-\r
-\r
-/* If ON, the enulation core will use 64-bit integers to speed up some\r
- * operations.\r
-*/\r
-#define M68K_USE_64_BIT  OPT_OFF\r
-\r
-\r
-/* Set to your compiler's static inline keyword to enable it, or\r
- * set it to blank to disable it.\r
- * If you define INLINE in the makefile, it will override this value.\r
- * NOTE: not enabling inline functions will SEVERELY slow down emulation.\r
- */\r
-#ifndef INLINE\r
-#define INLINE static __inline__\r
-#endif /* INLINE */\r
-\r
-#endif /* M68K_COMPILE_FOR_MAME */\r
-\r
-#include "sim.h"\r
-\r
-#define m68k_read_memory_8(A) cpu_read_byte(A)\r
-#define m68k_read_memory_16(A) cpu_read_word(A)\r
-#define m68k_read_memory_32(A) cpu_read_long(A)\r
-\r
-#define m68k_read_disassembler_16(A) cpu_read_word_dasm(A)\r
-#define m68k_read_disassembler_32(A) cpu_read_long_dasm(A)\r
-\r
-#define m68k_write_memory_8(A, V) cpu_write_byte(A, V)\r
-#define m68k_write_memory_16(A, V) cpu_write_word(A, V)\r
-#define m68k_write_memory_32(A, V) cpu_write_long(A, V)\r
-\r
-\r
-/* ======================================================================== */\r
-/* ============================== END OF FILE ============================= */\r
-/* ======================================================================== */\r
-\r
-#endif /* M68KCONF__HEADER */\r
+/* ======================================================================== */
+/* ========================= LICENSING & COPYRIGHT ======================== */
+/* ======================================================================== */
+/*
+ *                                  MUSASHI
+ *                                Version 3.4
+ *
+ * A portable Motorola M680x0 processor emulation engine.
+ * Copyright 1998-2001 Karl Stenerud.  All rights reserved.
+ *
+ * This code may be freely used for non-commercial purposes as long as this
+ * copyright notice remains unaltered in the source code and any binary files
+ * containing this code in compiled form.
+ *
+ * All other lisencing terms must be negotiated with the author
+ * (Karl Stenerud).
+ *
+ * The latest version of this code can be obtained at:
+ * http://kstenerud.cjb.net
+ */
+
+
+
+#ifndef M68KCONF__HEADER
+#define M68KCONF__HEADER
+
+
+/* Configuration switches.
+ * Use OPT_SPECIFY_HANDLER for configuration options that allow callbacks.
+ * OPT_SPECIFY_HANDLER causes the core to link directly to the function
+ * or macro you specify, rather than using callback functions whose pointer
+ * must be passed in using m68k_set_xxx_callback().
+ */
+#define OPT_OFF             0
+#define OPT_ON              1
+#define OPT_SPECIFY_HANDLER 2
+
+
+/* ======================================================================== */
+/* ============================== MAME STUFF ============================== */
+/* ======================================================================== */
+
+/* If you're compiling this for MAME, only change M68K_COMPILE_FOR_MAME
+ * to OPT_ON and use m68kmame.h to configure the 68k core.
+ */
+#ifndef M68K_COMPILE_FOR_MAME
+#define M68K_COMPILE_FOR_MAME      OPT_OFF
+#endif /* M68K_COMPILE_FOR_MAME */
+
+
+#if M68K_COMPILE_FOR_MAME == OPT_OFF
+
+
+/* ======================================================================== */
+/* ============================= CONFIGURATION ============================ */
+/* ======================================================================== */
+
+/* Turn ON if you want to use the following M68K variants */
+#define M68K_EMULATE_010            OPT_ON
+#define M68K_EMULATE_EC020          OPT_ON
+#define M68K_EMULATE_020            OPT_ON
+
+
+/* If ON, the CPU will call m68k_read_immediate_xx() for immediate addressing
+ * and m68k_read_pcrelative_xx() for PC-relative addressing.
+ * If off, all read requests from the CPU will be redirected to m68k_read_xx()
+ */
+#define M68K_SEPARATE_READS         OPT_OFF
+
+/* If ON, the CPU will call m68k_write_32_pd() when it executes move.l with a
+ * predecrement destination EA mode instead of m68k_write_32().
+ * To simulate real 68k behavior, m68k_write_32_pd() must first write the high
+ * word to [address+2], and then write the low word to [address].
+ */
+#define M68K_SIMULATE_PD_WRITES     OPT_OFF
+
+/* If ON, CPU will call the interrupt acknowledge callback when it services an
+ * interrupt.
+ * If off, all interrupts will be autovectored and all interrupt requests will
+ * auto-clear when the interrupt is serviced.
+ */
+#define M68K_EMULATE_INT_ACK        OPT_OFF
+#define M68K_INT_ACK_CALLBACK(A)    cpu_irq_ack(A)
+
+
+/* If ON, CPU will call the breakpoint acknowledge callback when it encounters
+ * a breakpoint instruction and it is running a 68010+.
+ */
+#define M68K_EMULATE_BKPT_ACK       OPT_OFF
+#define M68K_BKPT_ACK_CALLBACK()    your_bkpt_ack_handler_function()
+
+
+/* If ON, the CPU will monitor the trace flags and take trace exceptions
+ */
+#define M68K_EMULATE_TRACE          OPT_OFF
+
+
+/* If ON, CPU will call the output reset callback when it encounters a reset
+ * instruction.
+ */
+#define M68K_EMULATE_RESET          OPT_OFF
+#define M68K_RESET_CALLBACK()       cpu_pulse_reset()
+
+
+/* If ON, CPU will call the set fc callback on every memory access to
+ * differentiate between user/supervisor, program/data access like a real
+ * 68000 would.  This should be enabled and the callback should be set if you
+ * want to properly emulate the m68010 or higher. (moves uses function codes
+ * to read/write data from different address spaces)
+ */
+#define M68K_EMULATE_FC             OPT_OFF
+#define M68K_SET_FC_CALLBACK(A)     cpu_set_fc(A)
+
+
+/* If ON, CPU will call the pc changed callback when it changes the PC by a
+ * large value.  This allows host programs to be nicer when it comes to
+ * fetching immediate data and instructions on a banked memory system.
+ */
+#define M68K_MONITOR_PC             OPT_OFF
+#define M68K_SET_PC_CALLBACK(A)     your_pc_changed_handler_function(A)
+
+
+/* If ON, CPU will call the instruction hook callback before every
+ * instruction.
+ */
+#define M68K_INSTRUCTION_HOOK       OPT_SPECIFY_HANDLER
+#define M68K_INSTRUCTION_CALLBACK() cpu_instr_callback()
+
+
+/* If ON, the CPU will emulate the 4-byte prefetch queue of a real 68000 */
+#define M68K_EMULATE_PREFETCH       OPT_ON
+
+
+/* If ON, the CPU will generate address error exceptions if it tries to
+ * access a word or longword at an odd address.
+ * NOTE: This is only emulated properly for 68000 mode.
+ */
+#define M68K_EMULATE_ADDRESS_ERROR  OPT_ON
+
+
+/* Turn ON to enable logging of illegal instruction calls.
+ * M68K_LOG_FILEHANDLE must be #defined to a stdio file stream.
+ * Turn on M68K_LOG_1010_1111 to log all 1010 and 1111 calls.
+ */
+#define M68K_LOG_ENABLE             OPT_OFF
+#define M68K_LOG_1010_1111          OPT_OFF
+#define M68K_LOG_FILEHANDLE         stderr
+
+
+/* ----------------------------- COMPATIBILITY ---------------------------- */
+
+/* The following options set optimizations that violate the current ANSI
+ * standard, but will be compliant under the forthcoming C9X standard.
+ */
+
+
+/* If ON, the enulation core will use 64-bit integers to speed up some
+ * operations.
+*/
+#define M68K_USE_64_BIT  OPT_OFF
+
+
+/* Set to your compiler's static inline keyword to enable it, or
+ * set it to blank to disable it.
+ * If you define INLINE in the makefile, it will override this value.
+ * NOTE: not enabling inline functions will SEVERELY slow down emulation.
+ */
+#ifndef INLINE
+//#define INLINE static __inline__
+#define INLINE static
+#endif /* INLINE */
+
+#endif /* M68K_COMPILE_FOR_MAME */
+
+#include "sim.h"
+
+#define m68k_read_memory_8(A) cpu_read_byte(A)
+#define m68k_read_memory_16(A) cpu_read_word(A)
+#define m68k_read_memory_32(A) cpu_read_long(A)
+
+#define m68k_read_disassembler_16(A) cpu_read_word_dasm(A)
+#define m68k_read_disassembler_32(A) cpu_read_long_dasm(A)
+
+#define m68k_write_memory_8(A, V) cpu_write_byte(A, V)
+#define m68k_write_memory_16(A, V) cpu_write_word(A, V)
+#define m68k_write_memory_32(A, V) cpu_write_long(A, V)
+
+
+/* ======================================================================== */
+/* ============================== END OF FILE ============================= */
+/* ======================================================================== */
+
+#endif /* M68KCONF__HEADER */
index 97ea5fd..d15ca1e 100755 (executable)
-#include <stdio.h>\r
-#include <stdlib.h>\r
-#include <stdarg.h>\r
-#include <time.h>\r
-#include "sim.h"\r
-#include "m68k.h"\r
-\r
-void disassemble_program();\r
-\r
-/* Memory-mapped IO ports */\r
-#define INPUT_ADDRESS 0x800000\r
-#define OUTPUT_ADDRESS 0x400000\r
-\r
-/* IRQ connections */\r
-#define IRQ_NMI_DEVICE 7\r
-#define IRQ_INPUT_DEVICE 2\r
-#define IRQ_OUTPUT_DEVICE 1\r
-\r
-/* Time between characters sent to output device (seconds) */\r
-#define OUTPUT_DEVICE_PERIOD 1\r
-\r
-/* ROM and RAM sizes */\r
-#define MAX_ROM 0xfff\r
-#define MAX_RAM 0xff\r
-\r
-\r
-/* Read/write macros */\r
-#define READ_BYTE(BASE, ADDR) (BASE)[ADDR]\r
-#define READ_WORD(BASE, ADDR) (((BASE)[ADDR]<<8) |                     \\r
-                                                         (BASE)[(ADDR)+1])\r
-#define READ_LONG(BASE, ADDR) (((BASE)[ADDR]<<24) |                    \\r
-                                                         ((BASE)[(ADDR)+1]<<16) |              \\r
-                                                         ((BASE)[(ADDR)+2]<<8) |               \\r
-                                                         (BASE)[(ADDR)+3])\r
-\r
-#define WRITE_BYTE(BASE, ADDR, VAL) (BASE)[ADDR] = (VAL)&0xff\r
-#define WRITE_WORD(BASE, ADDR, VAL) (BASE)[ADDR] = ((VAL)>>8) & 0xff;          \\r
-                                                                       (BASE)[(ADDR)+1] = (VAL)&0xff\r
-#define WRITE_LONG(BASE, ADDR, VAL) (BASE)[ADDR] = ((VAL)>>24) & 0xff;         \\r
-                                                                       (BASE)[(ADDR)+1] = ((VAL)>>16)&0xff;    \\r
-                                                                       (BASE)[(ADDR)+2] = ((VAL)>>8)&0xff;             \\r
-                                                                       (BASE)[(ADDR)+3] = (VAL)&0xff\r
-\r
-\r
-/* Prototypes */\r
-void exit_error(char* fmt, ...);\r
-\r
-unsigned int cpu_read_byte(unsigned int address);\r
-unsigned int cpu_read_word(unsigned int address);\r
-unsigned int cpu_read_long(unsigned int address);\r
-void cpu_write_byte(unsigned int address, unsigned int value);\r
-void cpu_write_word(unsigned int address, unsigned int value);\r
-void cpu_write_long(unsigned int address, unsigned int value);\r
-void cpu_pulse_reset(void);\r
-void cpu_set_fc(unsigned int fc);\r
-int cpu_irq_ack(int level);\r
-\r
-void nmi_device_reset(void);\r
-void nmi_device_update(void);\r
-int nmi_device_ack(void);\r
-\r
-void input_device_reset(void);\r
-void input_device_update(void);\r
-int input_device_ack(void);\r
-unsigned int input_device_read(void);\r
-void input_device_write(unsigned int value);\r
-\r
-void output_device_reset(void);\r
-void output_device_update(void);\r
-int output_device_ack(void);\r
-unsigned int output_device_read(void);\r
-void output_device_write(unsigned int value);\r
-\r
-void int_controller_set(unsigned int value);\r
-void int_controller_clear(unsigned int value);\r
-\r
-void get_user_input(void);\r
-\r
-\r
-/* Data */\r
-unsigned int g_quit = 0;                        /* 1 if we want to quit */\r
-unsigned int g_nmi = 0;                         /* 1 if nmi pending */\r
-\r
-int          g_input_device_value = -1;         /* Current value in input device */\r
-\r
-unsigned int g_output_device_ready = 0;         /* 1 if output device is ready */\r
-time_t       g_output_device_last_output;       /* Time of last char output */\r
-\r
-unsigned int g_int_controller_pending = 0;      /* list of pending interrupts */\r
-unsigned int g_int_controller_highest_int = 0;  /* Highest pending interrupt */\r
-\r
-unsigned char g_rom[MAX_ROM+1];                 /* ROM */\r
-unsigned char g_ram[MAX_RAM+1];                 /* RAM */\r
-unsigned int  g_fc;                             /* Current function code from CPU */\r
-\r
-\r
-/* Exit with an error message.  Use printf syntax. */\r
-void exit_error(char* fmt, ...)\r
-{\r
-       static int guard_val = 0;\r
-       char buff[100];\r
-       unsigned int pc;\r
-       va_list args;\r
-\r
-       if(guard_val)\r
-               return;\r
-       else\r
-               guard_val = 1;\r
-\r
-       va_start(args, fmt);\r
-       vfprintf(stderr, fmt, args);\r
-       va_end(args);\r
-       fprintf(stderr, "\n");\r
-       pc = m68k_get_reg(NULL, M68K_REG_PPC);\r
-       m68k_disassemble(buff, pc, M68K_CPU_TYPE_68000);\r
-       fprintf(stderr, "At %04x: %s\n", pc, buff);\r
-\r
-       exit(EXIT_FAILURE);\r
-}\r
-\r
-\r
-/* Read data from RAM, ROM, or a device */\r
-unsigned int cpu_read_byte(unsigned int address)\r
-{\r
-       if(g_fc & 2)    /* Program */\r
-       {\r
-               if(address > MAX_ROM)\r
-                       exit_error("Attempted to read byte from ROM address %08x", address);\r
-               return READ_BYTE(g_rom, address);\r
-       }\r
-\r
-       /* Otherwise it's data space */\r
-       switch(address)\r
-       {\r
-               case INPUT_ADDRESS:\r
-                       return input_device_read();\r
-               case OUTPUT_ADDRESS:\r
-                       return output_device_read();\r
-               default:\r
-                       break;\r
-       }\r
-       if(address > MAX_RAM)\r
-               exit_error("Attempted to read byte from RAM address %08x", address);\r
-               return READ_BYTE(g_ram, address);\r
-}\r
-\r
-unsigned int cpu_read_word(unsigned int address)\r
-{\r
-       if(g_fc & 2)    /* Program */\r
-       {\r
-               if(address > MAX_ROM)\r
-                       exit_error("Attempted to read word from ROM address %08x", address);\r
-               return READ_WORD(g_rom, address);\r
-       }\r
-\r
-       /* Otherwise it's data space */\r
-       switch(address)\r
-       {\r
-               case INPUT_ADDRESS:\r
-                       return input_device_read();\r
-               case OUTPUT_ADDRESS:\r
-                       return output_device_read();\r
-               default:\r
-                       break;\r
-       }\r
-       if(address > MAX_RAM)\r
-               exit_error("Attempted to read word from RAM address %08x", address);\r
-               return READ_WORD(g_ram, address);\r
-}\r
-\r
-unsigned int cpu_read_long(unsigned int address)\r
-{\r
-       if(g_fc & 2)    /* Program */\r
-       {\r
-               if(address > MAX_ROM)\r
-                       exit_error("Attempted to read long from ROM address %08x", address);\r
-               return READ_LONG(g_rom, address);\r
-       }\r
-\r
-       /* Otherwise it's data space */\r
-       switch(address)\r
-       {\r
-               case INPUT_ADDRESS:\r
-                       return input_device_read();\r
-               case OUTPUT_ADDRESS:\r
-                       return output_device_read();\r
-               default:\r
-                       break;\r
-       }\r
-       if(address > MAX_RAM)\r
-               exit_error("Attempted to read long from RAM address %08x", address);\r
-               return READ_LONG(g_ram, address);\r
-}\r
-\r
-\r
-unsigned int cpu_read_word_dasm(unsigned int address)\r
-{\r
-       if(address > MAX_ROM)\r
-               exit_error("Disassembler attempted to read word from ROM address %08x", address);\r
-       return READ_WORD(g_rom, address);\r
-}\r
-\r
-unsigned int cpu_read_long_dasm(unsigned int address)\r
-{\r
-       if(address > MAX_ROM)\r
-               exit_error("Dasm attempted to read long from ROM address %08x", address);\r
-       return READ_LONG(g_rom, address);\r
-}\r
-\r
-\r
-/* Write data to RAM or a device */\r
-void cpu_write_byte(unsigned int address, unsigned int value)\r
-{\r
-       if(g_fc & 2)    /* Program */\r
-               exit_error("Attempted to write %02x to ROM address %08x", value&0xff, address);\r
-\r
-       /* Otherwise it's data space */\r
-       switch(address)\r
-       {\r
-               case INPUT_ADDRESS:\r
-                       input_device_write(value&0xff);\r
-                       return;\r
-               case OUTPUT_ADDRESS:\r
-                       output_device_write(value&0xff);\r
-                       return;\r
-               default:\r
-                       break;\r
-       }\r
-       if(address > MAX_RAM)\r
-               exit_error("Attempted to write %02x to RAM address %08x", value&0xff, address);\r
-       WRITE_BYTE(g_ram, address, value);\r
-}\r
-\r
-void cpu_write_word(unsigned int address, unsigned int value)\r
-{\r
-       if(g_fc & 2)    /* Program */\r
-               exit_error("Attempted to write %04x to ROM address %08x", value&0xffff, address);\r
-\r
-       /* Otherwise it's data space */\r
-       switch(address)\r
-       {\r
-               case INPUT_ADDRESS:\r
-                       input_device_write(value&0xffff);\r
-                       return;\r
-               case OUTPUT_ADDRESS:\r
-                       output_device_write(value&0xffff);\r
-                       return;\r
-               default:\r
-                       break;\r
-       }\r
-       if(address > MAX_RAM)\r
-               exit_error("Attempted to write %04x to RAM address %08x", value&0xffff, address);\r
-       WRITE_WORD(g_ram, address, value);\r
-}\r
-\r
-void cpu_write_long(unsigned int address, unsigned int value)\r
-{\r
-       if(g_fc & 2)    /* Program */\r
-               exit_error("Attempted to write %08x to ROM address %08x", value, address);\r
-\r
-       /* Otherwise it's data space */\r
-       switch(address)\r
-       {\r
-               case INPUT_ADDRESS:\r
-                       input_device_write(value);\r
-                       return;\r
-               case OUTPUT_ADDRESS:\r
-                       output_device_write(value);\r
-                       return;\r
-               default:\r
-                       break;\r
-       }\r
-       if(address > MAX_RAM)\r
-               exit_error("Attempted to write %08x to RAM address %08x", value, address);\r
-       WRITE_LONG(g_ram, address, value);\r
-}\r
-\r
-/* Called when the CPU pulses the RESET line */\r
-void cpu_pulse_reset(void)\r
-{\r
-       nmi_device_reset();\r
-       output_device_reset();\r
-       input_device_reset();\r
-}\r
-\r
-/* Called when the CPU changes the function code pins */\r
-void cpu_set_fc(unsigned int fc)\r
-{\r
-       g_fc = fc;\r
-}\r
-\r
-/* Called when the CPU acknowledges an interrupt */\r
-int cpu_irq_ack(int level)\r
-{\r
-       switch(level)\r
-       {\r
-               case IRQ_NMI_DEVICE:\r
-                       return nmi_device_ack();\r
-               case IRQ_INPUT_DEVICE:\r
-                       return input_device_ack();\r
-               case IRQ_OUTPUT_DEVICE:\r
-                       return output_device_ack();\r
-       }\r
-       return M68K_INT_ACK_SPURIOUS;\r
-}\r
-\r
-\r
-\r
-\r
-/* Implementation for the NMI device */\r
-void nmi_device_reset(void)\r
-{\r
-       g_nmi = 0;\r
-}\r
-\r
-void nmi_device_update(void)\r
-{\r
-       if(g_nmi)\r
-       {\r
-               g_nmi = 0;\r
-               int_controller_set(IRQ_NMI_DEVICE);\r
-       }\r
-}\r
-\r
-int nmi_device_ack(void)\r
-{\r
-       printf("\nNMI\n");fflush(stdout);\r
-       int_controller_clear(IRQ_NMI_DEVICE);\r
-       return M68K_INT_ACK_AUTOVECTOR;\r
-}\r
-\r
-\r
-/* Implementation for the input device */\r
-void input_device_reset(void)\r
-{\r
-       g_input_device_value = -1;\r
-       int_controller_clear(IRQ_INPUT_DEVICE);\r
-}\r
-\r
-void input_device_update(void)\r
-{\r
-       if(g_input_device_value >= 0)\r
-               int_controller_set(IRQ_INPUT_DEVICE);\r
-}\r
-\r
-int input_device_ack(void)\r
-{\r
-       return M68K_INT_ACK_AUTOVECTOR;\r
-}\r
-\r
-unsigned int input_device_read(void)\r
-{\r
-       int value = g_input_device_value > 0 ? g_input_device_value : 0;\r
-       int_controller_clear(IRQ_INPUT_DEVICE);\r
-       g_input_device_value = -1;\r
-       return value;\r
-}\r
-\r
-void input_device_write(unsigned int value)\r
-{\r
-}\r
-\r
-\r
-/* Implementation for the output device */\r
-void output_device_reset(void)\r
-{\r
-       g_output_device_last_output = time(NULL);\r
-       g_output_device_ready = 0;\r
-       int_controller_clear(IRQ_OUTPUT_DEVICE);\r
-}\r
-\r
-void output_device_update(void)\r
-{\r
-       if(!g_output_device_ready)\r
-       {\r
-               if((time(NULL) - g_output_device_last_output) >= OUTPUT_DEVICE_PERIOD)\r
-               {\r
-                       g_output_device_ready = 1;\r
-                       int_controller_set(IRQ_OUTPUT_DEVICE);\r
-               }\r
-       }\r
-}\r
-\r
-int output_device_ack(void)\r
-{\r
-       return M68K_INT_ACK_AUTOVECTOR;\r
-}\r
-\r
-unsigned int output_device_read(void)\r
-{\r
-       int_controller_clear(IRQ_OUTPUT_DEVICE);\r
-       return 0;\r
-}\r
-\r
-void output_device_write(unsigned int value)\r
-{\r
-       char ch;\r
-       if(g_output_device_ready)\r
-       {\r
-               ch = value & 0xff;\r
-               printf("%c", ch);\r
-               g_output_device_last_output = time(NULL);\r
-               g_output_device_ready = 0;\r
-               int_controller_clear(IRQ_OUTPUT_DEVICE);\r
-       }\r
-}\r
-\r
-\r
-/* Implementation for the interrupt controller */\r
-void int_controller_set(unsigned int value)\r
-{\r
-       unsigned int old_pending = g_int_controller_pending;\r
-\r
-       g_int_controller_pending |= (1<<value);\r
-\r
-       if(old_pending != g_int_controller_pending && value > g_int_controller_highest_int)\r
-       {\r
-               g_int_controller_highest_int = value;\r
-               m68k_set_irq(g_int_controller_highest_int);\r
-       }\r
-}\r
-\r
-void int_controller_clear(unsigned int value)\r
-{\r
-       g_int_controller_pending &= ~(1<<value);\r
-\r
-       for(g_int_controller_highest_int = 7;g_int_controller_highest_int > 0;g_int_controller_highest_int--)\r
-               if(g_int_controller_pending & (1<<g_int_controller_highest_int))\r
-                       break;\r
-\r
-       m68k_set_irq(g_int_controller_highest_int);\r
-}\r
-\r
-\r
-/* Parse user input and update any devices that need user input */\r
-void get_user_input(void)\r
-{\r
-       static int last_ch = -1;\r
-       int ch = -1; /* not supported */\r
-       //int ch = osd_get_char();\r
-\r
-       if(ch >= 0)\r
-       {\r
-               switch(ch)\r
-               {\r
-                       case 0x1b:\r
-                               g_quit = 1;\r
-                               break;\r
-                       case '~':\r
-                               if(last_ch != ch)\r
-                                       g_nmi = 1;\r
-                               break;\r
-                       default:\r
-                               g_input_device_value = ch;\r
-               }\r
-       }\r
-       last_ch = ch;\r
-}\r
-\r
-/* Disassembler */\r
-void make_hex(char* buff, unsigned int pc, unsigned int length)\r
-{\r
-       char* ptr = buff;\r
-\r
-       for(;length>0;length -= 2)\r
-       {\r
-               sprintf(ptr, "%04x", cpu_read_word_dasm(pc));\r
-               pc += 2;\r
-               ptr += 4;\r
-               if(length > 2)\r
-                       *ptr++ = ' ';\r
-       }\r
-}\r
-\r
-void disassemble_program()\r
-{\r
-       unsigned int pc;\r
-       unsigned int instr_size;\r
-       char buff[100];\r
-       char buff2[100];\r
-\r
-       pc = cpu_read_long_dasm(4);\r
-\r
-       while(pc <= 0x16e)\r
-       {\r
-               instr_size = m68k_disassemble(buff, pc, M68K_CPU_TYPE_68000);\r
-               make_hex(buff2, pc, instr_size);\r
-               printf("%03x: %-20s: %s\n", pc, buff2, buff);\r
-               pc += instr_size;\r
-       }\r
-       fflush(stdout);\r
-}\r
-\r
-void cpu_instr_callback()\r
-{\r
-/* The following code would print out instructions as they are executed */\r
-/*\r
-       static char buff[100];\r
-       static char buff2[100];\r
-       static unsigned int pc;\r
-       static unsigned int instr_size;\r
-\r
-       pc = m68k_get_reg(NULL, M68K_REG_PC);\r
-       instr_size = m68k_disassemble(buff, pc, M68K_CPU_TYPE_68000);\r
-       make_hex(buff2, pc, instr_size);\r
-       printf("E %03x: %-20s: %s\n", pc, buff2, buff);\r
-       fflush(stdout);\r
-*/\r
-}\r
-\r
-\r
-\r
-/* The main loop */\r
-int main(int argc, char* argv[])\r
-{\r
-       FILE* fhandle;\r
-\r
-       if(argc != 2)\r
-       {\r
-               printf("Usage: sim <program file>\n");\r
-               exit(-1);\r
-       }\r
-\r
-       if((fhandle = fopen(argv[1], "rb")) == NULL)\r
-               exit_error("Unable to open %s", argv[1]);\r
-\r
-       if(fread(g_rom, 1, MAX_ROM+1, fhandle) <= 0)\r
-               exit_error("Error reading %s", argv[1]);\r
-\r
-//     disassemble_program();\r
-\r
-       m68k_init();\r
-       m68k_set_cpu_type(M68K_CPU_TYPE_68000);\r
-       m68k_pulse_reset();\r
-       input_device_reset();\r
-       output_device_reset();\r
-       nmi_device_reset();\r
-\r
-       g_quit = 0;\r
-       while(!g_quit)\r
-       {\r
-               // Our loop requires some interleaving to allow us to update the\r
-               // input, output, and nmi devices.\r
-\r
-               get_user_input();\r
-\r
-               // Values to execute determine the interleave rate.\r
-               // Smaller values allow for more accurate interleaving with multiple\r
-               // devices/CPUs but is more processor intensive.\r
-               // 100000 is usually a good value to start at, then work from there.\r
-\r
-               // Note that I am not emulating the correct clock speed!\r
-               m68k_execute(100000);\r
-               output_device_update();\r
-               input_device_update();\r
-               nmi_device_update();\r
-       }\r
-\r
-       return 0;\r
-}\r
-\r
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <time.h>
+#include "sim.h"
+#include "m68k.h"
+
+void disassemble_program();
+
+#define ADDRESS_MASK 0xffffffff
+#define RAM_BASE 0x08000000
+#define RAM_TOP  0x08100000
+
+#define INIT_SP RAM_TOP
+#define INIT_PC 0x08000054
+
+/* Read/write macros */
+#define READ_BYTE(BASE, ADDR) (BASE)[ADDR]
+#define READ_WORD(BASE, ADDR) (((BASE)[ADDR]<<8) |                     \
+                                                         (BASE)[(ADDR)+1])
+#define READ_LONG(BASE, ADDR) (((BASE)[ADDR]<<24) |                    \
+                                                         ((BASE)[(ADDR)+1]<<16) |              \
+                                                         ((BASE)[(ADDR)+2]<<8) |               \
+                                                         (BASE)[(ADDR)+3])
+
+#define WRITE_BYTE(BASE, ADDR, VAL) (BASE)[ADDR] = (VAL)&0xff
+#define WRITE_WORD(BASE, ADDR, VAL) (BASE)[ADDR] = ((VAL)>>8) & 0xff;          \
+                                                                       (BASE)[(ADDR)+1] = (VAL)&0xff
+#define WRITE_LONG(BASE, ADDR, VAL) (BASE)[ADDR] = ((VAL)>>24) & 0xff;         \
+                                                                       (BASE)[(ADDR)+1] = ((VAL)>>16)&0xff;    \
+                                                                       (BASE)[(ADDR)+2] = ((VAL)>>8)&0xff;             \
+                                                                       (BASE)[(ADDR)+3] = (VAL)&0xff
+
+
+static void exit_error(char* fmt, ...);
+static void syscall(void);
+
+unsigned int cpu_read_byte(unsigned int address);
+unsigned int cpu_read_word(unsigned int address);
+unsigned int cpu_read_long(unsigned int address);
+void cpu_write_byte(unsigned int address, unsigned int value);
+void cpu_write_word(unsigned int address, unsigned int value);
+void cpu_write_long(unsigned int address, unsigned int value);
+
+unsigned char g_ram[RAM_TOP - RAM_BASE];
+
+
+/* Exit with an error message.  Use printf syntax. */
+void exit_error(char* fmt, ...)
+{
+       static int guard_val = 0;
+       char buff[100];
+       unsigned int pc;
+       va_list args;
+
+       if(guard_val)
+               return;
+       else
+               guard_val = 1;
+
+       va_start(args, fmt);
+       vfprintf(stderr, fmt, args);
+       va_end(args);
+       fprintf(stderr, "\n");
+       pc = m68k_get_reg(NULL, M68K_REG_PPC);
+       m68k_disassemble(buff, pc, M68K_CPU_TYPE_68000);
+       fprintf(stderr, "At %04x: %s\n", pc, buff);
+
+       exit(EXIT_FAILURE);
+}
+
+static inline unsigned int transform_address(unsigned int address)
+{
+       unsigned int i = (address & ADDRESS_MASK) - RAM_BASE;
+       if (i >= (unsigned int)(RAM_TOP - RAM_BASE))
+               exit_error("Attempted to read from RAM address %08x %08x", address, i);
+       return i;
+}
+
+unsigned int cpu_read_long(unsigned int address)
+{
+       switch (address)
+       {
+               case 0x00: return INIT_SP;
+               case 0x04: return INIT_PC;
+               case 0x80: syscall(); return 0x10000;
+               case 0x10000: return 0x4e73; /* rte */
+               case 0x10004: return 0;
+               default: return READ_LONG(g_ram, transform_address(address));
+       }
+}
+
+
+unsigned int cpu_read_word(unsigned int address)
+{
+       unsigned int l = cpu_read_long(address & ~3);
+       l >>= (address & 2) * 8;
+       return l & 0xffff;
+}
+
+unsigned int cpu_read_byte(unsigned int address)
+{
+       unsigned int l = cpu_read_long(address & ~3);
+       l >>= (address & 3) * 8;
+       return l & 0xff;
+}
+
+unsigned int cpu_read_word_dasm(unsigned int address)
+{
+       return cpu_read_word(address);
+}
+
+unsigned int cpu_read_long_dasm(unsigned int address)
+{
+       return cpu_read_long(address);
+}
+
+
+/* Write data to RAM or a device */
+void cpu_write_byte(unsigned int address, unsigned int value)
+{
+       WRITE_BYTE(g_ram, transform_address(address), value);
+}
+
+void cpu_write_word(unsigned int address, unsigned int value)
+{
+       WRITE_WORD(g_ram, transform_address(address), value);
+}
+
+void cpu_write_long(unsigned int address, unsigned int value)
+{
+       WRITE_LONG(g_ram, transform_address(address), value);
+}
+
+/* Disassembler */
+void make_hex(char* buff, unsigned int pc, unsigned int length)
+{
+       char* ptr = buff;
+
+       for(;length>0;length -= 2)
+       {
+               sprintf(ptr, "%04x", cpu_read_word_dasm(pc));
+               pc += 2;
+               ptr += 4;
+               if(length > 2)
+                       *ptr++ = ' ';
+       }
+}
+
+void disassemble_program()
+{
+       unsigned int pc;
+       unsigned int instr_size;
+       char buff[100];
+       char buff2[100];
+
+       pc = cpu_read_long_dasm(4);
+
+       while(pc <= 0x16e)
+       {
+               instr_size = m68k_disassemble(buff, pc, M68K_CPU_TYPE_68000);
+               make_hex(buff2, pc, instr_size);
+               printf("%03x: %-20s: %s\n", pc, buff2, buff);
+               pc += instr_size;
+       }
+       fflush(stdout);
+}
+
+void cpu_instr_callback()
+{
+       /* The following code would print out instructions as they are executed */
+
+#if 1
+       static char buff[100];
+       static char buff2[100];
+       static unsigned int pc;
+       static unsigned int instr_size;
+
+       pc = m68k_get_reg(NULL, M68K_REG_PC);
+       instr_size = m68k_disassemble(buff, pc, M68K_CPU_TYPE_68020);
+       make_hex(buff2, pc, instr_size);
+       printf("E %03x: %-20s: %s\n", pc, buff2, buff);
+       fflush(stdout);
+#endif
+}
+
+static void syscall(void)
+{
+       int s = m68k_get_reg(NULL, M68K_REG_D0);
+       switch (s)
+       {
+               case 45: /* brk */
+                       m68k_set_reg(M68K_REG_D0, RAM_TOP-0x1000);
+                       break;
+
+               default:
+                       exit_error("unknown system call %d", s);
+       }
+}
+
+/* The main loop */
+int main(int argc, char* argv[])
+{
+       FILE* fhandle;
+
+       if(argc != 2)
+       {
+               printf("Usage: sim <program file>\n");
+               exit(-1);
+       }
+
+       if((fhandle = fopen(argv[1], "rb")) == NULL)
+               exit_error("Unable to open %s", argv[1]);
+
+       if(fread(g_ram, 1, RAM_TOP - RAM_BASE, fhandle) <= 0)
+               exit_error("Error reading %s", argv[1]);
+
+//     disassemble_program();
+
+       m68k_init();
+       m68k_set_cpu_type(M68K_CPU_TYPE_68020);
+       m68k_pulse_reset();
+
+       /* On entry, the Linux 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
+        *
+        * We'll set it up with a bodgy stack frame with argc=0 just to keep the
+        * startup code happy.
+        */
+
+       {
+               unsigned int sp = INIT_SP;
+               cpu_write_long(sp -= 4, 0);
+               unsigned int envp = sp;
+               cpu_write_long(sp -= 4, envp);
+               cpu_write_long(sp -= 4, 0);
+               unsigned long argv = sp;
+               cpu_write_long(sp -= 4, argv);
+               cpu_write_long(sp -= 4, 0);
+               m68k_set_reg(M68K_REG_SP, sp);
+       }
+
+       for (;;)
+               m68k_execute(100000);
+
+       return 0;
+}
+
diff --git a/plat/linux68k/tests/build.lua b/plat/linux68k/tests/build.lua
new file mode 100644 (file)
index 0000000..a025310
--- /dev/null
@@ -0,0 +1,7 @@
+include("tests/plat/build.lua")
+
+plat_testsuite {
+    name = "tests",
+    plat = "linux68k",
+    method = "plat/linux68k/emu+emu68k"
+}