summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt14
-rw-r--r--bus.c206
-rw-r--r--bus.h15
-rw-r--r--emulator.c227
4 files changed, 240 insertions, 222 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index da8a870..c1261b1 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -14,14 +14,15 @@ set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -fsanitize=address -fno-omit
set(CMAKE_LINKER_FLAGS_DEBUG "${CMAKE_LINKER_FLAGS_DEBUG} -fsanitize=address -fno-omit-frame-pointer")
set(emulator_sources
- "emulator.c"
- )
+ bus.c
+ emulator.c
+ )
set(musashi_m68k_sources
musashi-m68k/m68kcpu.c
musashi-m68k/m68kdasm.c
musashi-m68k/softfloat/softfloat.c
${CMAKE_CURRENT_BINARY_DIR}/m68kops.c
- )
+ )
add_executable(m68kmake musashi-m68k/m68kmake.c)
target_include_directories(m68kmake PRIVATE musashi-m68k)
add_custom_command(
@@ -41,8 +42,11 @@ target_include_directories(musashi_m68k PRIVATE
add_executable(emulator ${emulator_sources})
target_link_libraries(emulator musashi_m68k)
+target_compile_definitions(emulator PRIVATE
+ DEBUG_TRACE_INSTRUCTIONS=1
+ )
include_directories(
- .
- )
+ .
+ )
diff --git a/bus.c b/bus.c
new file mode 100644
index 0000000..9e23586
--- /dev/null
+++ b/bus.c
@@ -0,0 +1,206 @@
+#include "bus.h"
+
+#include <assert.h>
+#include <stdarg.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+#include "musashi-m68k/m68k.h"
+
+unsigned char g_rom[ROM_SIZE] = {0};
+unsigned char g_ram[RAM_SIZE] = {0};
+unsigned char g_io1[IO1_SIZE] = {0};
+unsigned char g_io2[IO2_SIZE] = {0};
+
+static void exit_error(char* fmt, ...)
+{
+ va_list args;
+ va_start(args, fmt);
+ vfprintf(stderr, fmt, args);
+ va_end(args);
+ fprintf(stderr, "\n");
+ unsigned int pc = m68k_get_reg(NULL, M68K_REG_PPC);
+ char buff[100];
+ m68k_disassemble(buff, pc, M68K_CPU_TYPE_68000);
+ fprintf(stderr, "%08x: %s\n", pc, buff);
+ exit(EXIT_FAILURE);
+}
+
+static inline bool is_in_range(uint32_t value, uint32_t begin, uint32_t length)
+{
+ return value >= begin && value <= begin + length;
+}
+
+enum bitness {
+ BITNESS_8,
+ BITNESS_16,
+ BITNESS_32,
+};
+
+struct read_result {
+ unsigned int result;
+ bool successful;
+};
+
+static inline unsigned int memory_read_concrete(
+ enum bitness bitness,
+ unsigned char const * base,
+ unsigned int address)
+{
+ switch (bitness) {
+ case BITNESS_8:
+ return base[address];
+ case BITNESS_16:
+ return (base[address] << 8) | base[address + 1];
+ case BITNESS_32:
+ return (base[address] << 24) |
+ (base[address + 1] << 16) |
+ (base[address + 2] << 8) |
+ base[address + 3];
+ }
+ __builtin_unreachable();
+}
+
+static inline struct read_result memory_read(
+ enum bitness bitness,
+ unsigned int address)
+{
+ if (is_in_range(address, ROM_START, ROM_SIZE))
+ return (struct read_result){
+ memory_read_concrete(bitness, g_rom, address - ROM_START),
+ true,
+ };
+ else if (is_in_range(address, RAM_START, RAM_SIZE))
+ return (struct read_result){
+ memory_read_concrete(bitness, g_ram, address - RAM_START),
+ true,
+ };
+ else if (is_in_range(address, IO1_START, IO1_SIZE))
+ return (struct read_result){
+ memory_read_concrete(bitness, g_io1, address - IO1_START),
+ true,
+ };
+ else if (is_in_range(address, IO2_START, IO2_SIZE))
+ return (struct read_result){
+ memory_read_concrete(bitness, g_io2, address - IO2_START),
+ true,
+ };
+ return (struct read_result){0, false};
+}
+
+static inline void memory_write_concrete(
+ enum bitness bitness,
+ unsigned char * base,
+ unsigned int address,
+ unsigned int value)
+{
+ switch (bitness) {
+ case BITNESS_8:
+ base[address] = value & 0xff;
+ break;
+ case BITNESS_16:
+ base[address + 0] = (value >> 8) & 0xff;
+ base[address + 1] = value & 0xff;
+ break;
+ case BITNESS_32:
+ base[address + 0] = (value >> 24) & 0xff;
+ base[address + 1] = (value >> 16) & 0xff;
+ base[address + 2] = (value >> 8) & 0xff;
+ base[address + 3] = value & 0xff;
+ break;
+ }
+}
+
+static inline bool memory_write(
+ enum bitness bitness,
+ unsigned int address,
+ unsigned int value)
+{
+ if (is_in_range(address, ROM_START, ROM_SIZE)) {
+ memory_write_concrete(bitness, g_rom, address - ROM_START, value);
+ return true;
+ } else if (is_in_range(address, RAM_START, RAM_SIZE)) {
+ memory_write_concrete(bitness, g_ram, address - RAM_START, value);
+ return true;
+ } else if (is_in_range(address, IO1_START, IO1_SIZE)) {
+ memory_write_concrete(bitness, g_io1, address - IO1_START, value);
+ return true;
+ } else if (is_in_range(address, IO2_START, IO2_SIZE)) {
+ memory_write_concrete(bitness, g_io2, address - IO2_START, value);
+ return true;
+ }
+ return false;
+}
+
+#define MASK_24(X) ((X) & (0xFF << 24))
+
+unsigned int m68k_read_memory_8(unsigned int address)
+{
+ assert(MASK_24(address) == 0); // Just curious
+ const struct read_result ret = memory_read(BITNESS_8, address);
+ if (!ret.successful)
+ exit_error("Read error u8 @%08x", address);
+ return ret.result;
+}
+
+unsigned int m68k_read_memory_16(unsigned int address)
+{
+ assert(MASK_24(address) == 0); // Just curious
+ const struct read_result ret = memory_read(BITNESS_16, address);
+ if (!ret.successful)
+ exit_error("Read error u16 @%08x", address);
+ return ret.result;
+}
+
+unsigned int m68k_read_memory_32(unsigned int address)
+{
+ assert(MASK_24(address) == 0); // Just curious
+ const struct read_result ret = memory_read(BITNESS_32, address);
+ if (!ret.successful)
+ exit_error("Read error u32 @%08x", address);
+ return ret.result;
+}
+
+unsigned int m68k_read_disassembler_16(unsigned int address)
+{
+ assert(MASK_24(address) == 0); // Just curious
+ const struct read_result ret = memory_read(BITNESS_16, address);
+ if (!ret.successful)
+ exit_error("Disasm read error u16 @0x%08x", address);
+ return ret.result;
+}
+
+unsigned int m68k_read_disassembler_32(unsigned int address)
+{
+ assert(MASK_24(address) == 0); // Just curious
+ const struct read_result ret = memory_read(BITNESS_32, address);
+ if (!ret.successful)
+ exit_error("Disasm read error u32 @0x%08x", address);
+ return ret.result;
+}
+
+void m68k_write_memory_8(unsigned int address, unsigned int value)
+{
+ assert(MASK_24(address) == 0); // Just curious
+ const bool successful = memory_write(BITNESS_8, address, value);
+ if (!successful)
+ exit_error("Attempted to write %02x (u8) to address %08x", value&0xff, address);
+}
+
+void m68k_write_memory_16(unsigned int address, unsigned int value)
+{
+ assert(MASK_24(address) == 0); // Just curious
+ const bool successful = memory_write(BITNESS_16, address, value);
+ if (!successful)
+ exit_error("Attempted to write %04x (u16) to address %08x", value&0xffff, address);
+}
+
+void m68k_write_memory_32(unsigned int address, unsigned int value)
+{
+ assert(MASK_24(address) == 0); // Just curious
+ const bool successful = memory_write(BITNESS_16, address, value);
+ if (!successful)
+ exit_error("Attempted to write %08x (u32) to address %08x", value, address);
+}
diff --git a/bus.h b/bus.h
new file mode 100644
index 0000000..4be9527
--- /dev/null
+++ b/bus.h
@@ -0,0 +1,15 @@
+#pragma once
+
+#define ROM_START (0)
+#define ROM_SIZE (0x400000)
+#define RAM_START (0xFF0000)
+#define RAM_SIZE (0x10000)
+#define IO1_START (0xA10000)
+#define IO1_SIZE (0x4004)
+#define IO2_START (0xC00000)
+#define IO2_SIZE (0x20)
+
+extern unsigned char g_rom[ROM_SIZE];
+extern unsigned char g_ram[RAM_SIZE];
+extern unsigned char g_io1[IO1_SIZE];
+extern unsigned char g_io2[IO2_SIZE];
diff --git a/emulator.c b/emulator.c
index abe94a3..bd16f76 100644
--- a/emulator.c
+++ b/emulator.c
@@ -1,230 +1,25 @@
-#include <assert.h>
-#include <stdbool.h>
+#include "bus.h"
+
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
-#include <stdint.h>
#include <time.h>
#include "musashi-m68k/m68k.h"
-#define ROM_START (0)
-#define ROM_SIZE (0x400000)
-#define RAM_START (0xFF0000)
-#define RAM_SIZE (0x10000)
-#define IO1_START (0xA10000)
-#define IO1_SIZE (0x4004)
-#define IO2_START (0xC00000)
-#define IO2_SIZE (0x20)
-
-/* Data */
-unsigned char g_rom[ROM_SIZE];
-unsigned char g_ram[RAM_SIZE];
-unsigned char g_io1[IO1_SIZE];
-unsigned char g_io2[IO2_SIZE];
+#if !defined(DEBUG_TRACE_INSTRUCTIONS)
+# define DEBUG_TRACE_INSTRUCTIONS 0
+#endif
-/* Exit with an error message. Use printf syntax. */
static 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, "%08x: %s\n", pc, buff);
-
exit(EXIT_FAILURE);
}
-static inline bool is_in_range(uint32_t value, uint32_t begin, uint32_t length)
-{
- return value >= begin && value <= begin + length;
-}
-
-enum bitness {
- BITNESS_8,
- BITNESS_16,
- BITNESS_32,
-};
-
-struct read_result {
- unsigned int result;
- bool successful;
-};
-
-static inline unsigned int memory_read_concrete(
- enum bitness bitness,
- unsigned char const * base,
- unsigned int address)
-{
- switch (bitness) {
- case BITNESS_8:
- return base[address];
- case BITNESS_16:
- return (base[address] << 8) | base[address + 1];
- case BITNESS_32:
- return (base[address] << 24) |
- (base[address + 1] << 16) |
- (base[address + 2] << 8) |
- base[address + 3];
- }
- __builtin_unreachable();
-}
-
-static inline struct read_result memory_read(
- enum bitness bitness,
- unsigned int address)
-{
- if (is_in_range(address, ROM_START, ROM_SIZE))
- return (struct read_result){
- memory_read_concrete(bitness, g_rom, address - ROM_START),
- true,
- };
- else if (is_in_range(address, RAM_START, RAM_SIZE))
- return (struct read_result){
- memory_read_concrete(bitness, g_ram, address - RAM_START),
- true,
- };
- else if (is_in_range(address, IO1_START, IO1_SIZE))
- return (struct read_result){
- memory_read_concrete(bitness, g_io1, address - IO1_START),
- true,
- };
- else if (is_in_range(address, IO2_START, IO2_SIZE))
- return (struct read_result){
- memory_read_concrete(bitness, g_io2, address - IO2_START),
- true,
- };
- return (struct read_result){0, false};
-}
-
-static inline void memory_write_concrete(
- enum bitness bitness,
- unsigned char * base,
- unsigned int address,
- unsigned int value)
-{
- switch (bitness) {
- case BITNESS_8:
- base[address] = value & 0xff;
- return;
- case BITNESS_16:
- base[address] = (value >> 8) & 0xff;
- base[address + 1] = value & 0xff;
- return;
- case BITNESS_32:
- base[address + 0] = (value >> 24) & 0xff;
- base[address + 1] = (value >> 16) & 0xff;
- base[address + 2] = (value >> 8) & 0xff;
- base[address + 3] = value & 0xff;
- return;
- }
- __builtin_unreachable();
-}
-
-static inline bool memory_write(
- enum bitness bitness,
- unsigned int address,
- unsigned int value)
-{
- if (is_in_range(address, ROM_START, ROM_SIZE)) {
- memory_write_concrete(bitness, g_rom, address - ROM_START, value);
- return true;
- } else if (is_in_range(address, RAM_START, RAM_SIZE)) {
- memory_write_concrete(bitness, g_ram, address - RAM_START, value);
- return true;
- } else if (is_in_range(address, IO1_START, IO1_SIZE)) {
- memory_write_concrete(bitness, g_io1, address - IO1_START, value);
- return true;
- } else if (is_in_range(address, IO2_START, IO2_SIZE)) {
- memory_write_concrete(bitness, g_io2, address - IO2_START, value);
- return true;
- }
- return false;
-}
-
-#define MASK_24(X) ((X) & (0xFF << 24))
-
-unsigned int m68k_read_memory_8(unsigned int address)
-{
- assert(MASK_24(address) == 0); // Just curious
- const struct read_result ret = memory_read(BITNESS_8, address);
- if (!ret.successful)
- exit_error("Read error u8 @%08x", address);
- return ret.result;
-}
-
-unsigned int m68k_read_memory_16(unsigned int address)
-{
- assert(MASK_24(address) == 0); // Just curious
- const struct read_result ret = memory_read(BITNESS_16, address);
- if (!ret.successful)
- exit_error("Read error u16 @%08x", address);
- return ret.result;
-}
-
-unsigned int m68k_read_memory_32(unsigned int address)
-{
- assert(MASK_24(address) == 0); // Just curious
- const struct read_result ret = memory_read(BITNESS_32, address);
- if (!ret.successful)
- exit_error("Read error u32 @%08x", address);
- return ret.result;
-}
-
-unsigned int m68k_read_disassembler_16(unsigned int address)
-{
- assert(MASK_24(address) == 0); // Just curious
- const struct read_result ret = memory_read(BITNESS_16, address);
- if (!ret.successful)
- exit_error("Disasm read error u16 @0x%08x", address);
- return ret.result;
-}
-
-unsigned int m68k_read_disassembler_32(unsigned int address)
-{
- assert(MASK_24(address) == 0); // Just curious
- const struct read_result ret = memory_read(BITNESS_32, address);
- if (!ret.successful)
- exit_error("Disasm read error u32 @0x%08x", address);
- return ret.result;
-}
-
-/* Write data to RAM or a device */
-void m68k_write_memory_8(unsigned int address, unsigned int value)
-{
- assert(MASK_24(address) == 0); // Just curious
- const bool successful = memory_write(BITNESS_8, address, value);
- if (!successful)
- exit_error("Attempted to write %02x (u8) to address %08x", value&0xff, address);
-}
-
-void m68k_write_memory_16(unsigned int address, unsigned int value)
-{
- assert(MASK_24(address) == 0); // Just curious
- const bool successful = memory_write(BITNESS_16, address, value);
- if (!successful)
- exit_error("Attempted to write %04x (u16) to address %08x", value&0xffff, address);
-}
-
-void m68k_write_memory_32(unsigned int address, unsigned int value)
-{
- assert(MASK_24(address) == 0); // Just curious
- const bool successful = memory_write(BITNESS_16, address, value);
- if (!successful)
- exit_error("Attempted to write %08x (u32) to address %08x", value, address);
-}
-
/* Called when the CPU pulses the RESET line */
void m68k_reset_callback(void)
{
@@ -256,14 +51,12 @@ static void make_hex(char* buff, unsigned int pc, unsigned int length)
void m68k_instr_callback(int pc)
{
- if (0)
+ if (!DEBUG_TRACE_INSTRUCTIONS)
return;
- static char buff[100];
- static char buff2[100];
- static unsigned int instr_size;
-
- pc = m68k_get_reg(NULL, M68K_REG_PC);
- instr_size = m68k_disassemble(buff, pc, M68K_CPU_TYPE_68000);
+ char buff[100];
+ unsigned int instr_size =
+ m68k_disassemble(buff, pc, M68K_CPU_TYPE_68000);
+ char buff2[100];
make_hex(buff2, pc, instr_size);
printf("E %08X: %-20s: %s\n", pc, buff2, buff);
fflush(stdout);