summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOxore <oxore@protonmail.com>2022-08-26 10:07:14 +0300
committerOxore <oxore@protonmail.com>2022-08-26 10:07:45 +0300
commit172c367b5ae9d7c56515958b511836c17f6008a1 (patch)
tree49d44e706ea7b86994b41ff4ad6063f17c5bb4ab
parentbfec175173f4e1a350729588526c4ff0be9ac949 (diff)
Get rid of macros
-rw-r--r--CMakeLists.txt6
-rw-r--r--emulator.c193
2 files changed, 134 insertions, 65 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 1c0713b..da8a870 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -6,9 +6,9 @@ set(CMAKE_CXX_STANDARD_REQUIRED True)
set(CMAKE_C_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED True)
set(CMAKE_EXPORT_COMPILE_COMMANDS True)
-set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -pedantic -O1")
-set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -fsanitize=address -fno-omit-frame-pointer")
-set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -pedantic -Wno-nested-anon-types -O1")
+set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -pedantic")
+set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -fsanitize=address -fno-omit-frame-pointer -O1")
+set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-nested-anon-types")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-exceptions -fno-rtti") # Speed up compilation
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -fsanitize=address -fno-omit-frame-pointer")
set(CMAKE_LINKER_FLAGS_DEBUG "${CMAKE_LINKER_FLAGS_DEBUG} -fsanitize=address -fno-omit-frame-pointer")
diff --git a/emulator.c b/emulator.c
index 7eb30a8..abe94a3 100644
--- a/emulator.c
+++ b/emulator.c
@@ -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 */