diff options
Diffstat (limited to 'emulator.c')
-rw-r--r-- | emulator.c | 193 |
1 files changed, 131 insertions, 62 deletions
@@ -16,23 +16,6 @@ #define IO2_START (0xC00000) #define IO2_SIZE (0x20) - -/* Read/write macros */ -#define READ_8(BASE, ADDR) ((BASE)[ADDR]) -#define READ_16(BASE, ADDR) (((BASE)[ADDR]<<8) | (BASE)[(ADDR)+1]) -#define READ_32(BASE, ADDR) (((BASE)[ADDR]<<24) | \ - ((BASE)[(ADDR)+1]<<16) | \ - ((BASE)[(ADDR)+2]<<8) | \ - (BASE)[(ADDR)+3]) - -#define WRITE_8(BASE, ADDR, VAL) ((BASE)[ADDR] = (VAL)&0xff) -#define WRITE_16(BASE, ADDR, VAL) (((BASE)[ADDR] = ((VAL)>>8) & 0xff), \ - ((BASE)[(ADDR)+1] = (VAL)&0xff)) -#define WRITE_32(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)) - /* Data */ unsigned char g_rom[ROM_SIZE]; unsigned char g_ram[RAM_SIZE]; @@ -68,98 +51,184 @@ static inline bool is_in_range(uint32_t value, uint32_t begin, uint32_t length) return value >= begin && value <= begin + length; } -#define MEMORY_READ(BITNESS, ADDR) \ - do { \ - if (is_in_range(ADDR, ROM_START, ROM_SIZE)) \ - return READ_##BITNESS(g_rom, ADDR - ROM_START); \ - else if (is_in_range(ADDR, RAM_START, RAM_SIZE)) \ - return READ_##BITNESS(g_ram, ADDR - RAM_START); \ - else if (is_in_range(ADDR, IO1_START, IO1_SIZE)) \ - return READ_##BITNESS(g_io1, ADDR - IO1_START); \ - else if (is_in_range(ADDR, IO2_START, IO2_SIZE)) \ - return READ_##BITNESS(g_io2, ADDR - IO2_START); \ - } while (0) - -#define MEMORY_WRITE(BITNESS, ADDR, VAL) \ - do { \ - if (is_in_range(ADDR, ROM_START, ROM_SIZE)) { \ - WRITE_##BITNESS(g_rom, ADDR - ROM_START, VAL); return; \ - } else if (is_in_range(ADDR, RAM_START, RAM_SIZE)) { \ - WRITE_##BITNESS(g_ram, ADDR - RAM_START, VAL); return; \ - } else if (is_in_range(ADDR, IO1_START, IO1_SIZE)) { \ - WRITE_##BITNESS(g_io1, ADDR - IO1_START, VAL); return; \ - } else if (is_in_range(ADDR, IO2_START, IO2_SIZE)) { \ - WRITE_##BITNESS(g_io2, ADDR - IO2_START, VAL); return; \ - } \ - } while (0) +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 - MEMORY_READ(8, address); - exit_error("Attempted to read u8 from address %08x", address); - return 0; + 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 - MEMORY_READ(16, address); - exit_error("Attempted to read u16 from address %08x", address); - return 0; + 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 - MEMORY_READ(32, address); - exit_error("Attempted to read u32 from address %08x", address); - return 0; + 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 - MEMORY_READ(16, address); - exit_error("Disassembler attempted to read u16 from address %08x", address); - return 0; + 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 - MEMORY_READ(32, address); - exit_error("Disassembler attempted to read u32 from address %08x", address); - return 0; + 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 - MEMORY_WRITE(8, address, value); - exit_error("Attempted to write %02x (u8) to address %08x", value&0xff, address); + 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 - MEMORY_WRITE(16, address, value); - exit_error("Attempted to write %04x (u16) to address %08x", value&0xffff, address); + 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 - MEMORY_WRITE(16, address, value); - exit_error("Attempted to write %08x (u32) to address %08x", value, address); + 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) { + // TODO } /* Called when the CPU acknowledges an interrupt */ |