10 #include "Musashi/m68k.h"
12 #include "cpu_68000.h"
16 #define PAGE_SIZE 0x1000
17 #define EXCEPTION_TRAP_BASE 0x20
22 #define MEM_SIZE 0x20000
23 #if __BYTE_ORDER == __LITTLE_ENDIAN
24 #define MEM_SIZE_M1 (MEM_SIZE - 1)
25 #define MEM_SIZE_M2 (MEM_SIZE - 2)
26 #define MEM_SIZE_M4 (MEM_SIZE - 4)
34 uint16_t w[MEM_SIZE >> 1];
35 uint32_t l[MEM_SIZE >> 2];
38 // used with be_read() and be_write()
39 // when host/target endianness differs, pass pointer to end of buffer,
40 // and then the buffer will be read or written backwards from the end
41 #if __BYTE_ORDER == __LITTLE_ENDIAN
42 #define BE_ARR(name) ((uint8_t *)(name) + sizeof(name))
43 #define BE_PTR(name) ((uint8_t *)&(name) + sizeof(name))
44 #define BE_XOR ((size_t)-1)
46 #define BE_ARR(name) ((uint8_t *)(name) + sizeof(name))
47 #define BE_PTR(name) ((uint8_t *)&(name))
54 void be_resize(size_t count) {
56 be_buf = malloc(count);
64 ssize_t be_read(int fd, uint8_t *buf, size_t count) {
65 if (count > be_buf_size)
68 ssize_t result = read(fd, be_buf, count);
69 if (result == (ssize_t)-1)
72 for (size_t i = 0; i < (size_t)result; ++i)
73 buf[i ^ BE_XOR] = be_buf[i];
78 ssize_t be_write(int fd, uint8_t *buf, size_t count) {
79 if (count > be_buf_size)
82 for (size_t i = 0; i < count; ++i)
83 be_buf[i] = buf[i ^ BE_XOR];
85 return write(fd, be_buf, count);
88 int load_aout(char *name) {
89 int fd = open(name, O_RDONLY);
95 struct x_exec aout_header;
96 ssize_t result = be_read(fd, BE_PTR(aout_header), sizeof(aout_header));
97 if (result == (ssize_t)-1) {
101 if (result != sizeof(aout_header)) {
102 fprintf(stderr, "short read\n");
106 if (aout_header.x_a_magic != x_ZMAGIC) {
107 fprintf(stderr, "unrecognized magic 0%o\n", aout_header.x_a_magic);
111 if (aout_header.x_a_mid != x_MID_HP300) {
112 fprintf(stderr, "unrecognized machine ID 0%o\n", aout_header.x_a_mid);
118 ((size_t)aout_header.x_a_text + (PAGE_SIZE - 1)) & ~PAGE_SIZE
120 size_t bss_base = data_base + (
121 ((size_t)aout_header.x_a_data + (PAGE_SIZE - 1)) & ~PAGE_SIZE
123 size_t end = bss_base + (size_t)aout_header.x_a_bss;
124 if (end > MEM_SIZE) {
125 fprintf(stderr, "too large\n");
130 if (lseek(fd, PAGE_SIZE, SEEK_SET) == (off_t)-1) {
135 /*ssize_t*/ result = be_read(fd, BE_PTR(mem), aout_header.x_a_text);
136 if (result == (ssize_t)-1) {
140 if (result != aout_header.x_a_text) {
141 fprintf(stderr, "short read\n");
146 if (lseek(fd, PAGE_SIZE + data_base, SEEK_SET) == (off_t)-1) {
151 /*ssize_t*/ result = be_read(
153 BE_PTR(mem) + (data_base ^ BE_XOR),
156 if (result == (ssize_t)-1) {
160 if (result != aout_header.x_a_data) {
161 fprintf(stderr, "short read\n");
167 return aout_header.x_a_entry;
170 int read_byte(void *context, int addr) {
174 return 3; // bit 0 = rdrf, bit 1 = tdre
184 #if 0 // just keep sending 0xff at EOF
192 if (addr < 0 || addr >= MEM_SIZE) {
193 fprintf(stderr, "invalid read byte: %06x\n", addr);
196 data = mem.b[addr ^ MEM_SIZE_M1];
200 fprintf(stderr, "addr=%06x rd=%02x\n", addr, data);
205 int read_word(void *context, int addr) {
206 if (addr < 0 || addr >= MEM_SIZE || (addr & 1)) {
207 fprintf(stderr, "invalid read word: %06x\n", addr);
210 int data = mem.w[(addr ^ MEM_SIZE_M2) >> 1];
212 fprintf(stderr, "addr=%06x rd=%04x\n", addr, data);
217 int read_long(void *context, int addr) {
218 if (addr < 0 || addr >= MEM_SIZE - 2 || (addr & 1)) {
219 fprintf(stderr, "invalid read long: %06x\n", addr);
223 (mem.w[(addr ^ MEM_SIZE_M2) >> 1] << 16) |
224 mem.w[((addr + 2) ^ MEM_SIZE_M2) >> 1];
226 fprintf(stderr, "addr=%06x rd=%08x\n", addr, data);
231 void write_byte(void *context, int addr, int data) {
233 fprintf(stderr, "addr=%06x wr=%02x\n", addr, data);
252 if (addr < 0 || addr >= MEM_SIZE) {
253 fprintf(stderr, "invalid write byte: %06x\n", addr);
256 mem.b[addr ^ MEM_SIZE_M1] = data;
260 void write_word(void *context, int addr, int data) {
262 fprintf(stderr, "addr=%06x wr=%04x\n", addr, data);
264 if (addr < 0 || addr >= MEM_SIZE || (addr & 1)) {
265 fprintf(stderr, "invalid write word: %06x\n", addr);
268 mem.w[(addr ^ MEM_SIZE_M2) >> 1] = data;
271 void write_long(void *context, int addr, int data) {
273 fprintf(stderr, "addr=%06x wr=%08x\n", addr, data);
275 if (addr < 0 || addr >= MEM_SIZE - 2 || (addr & 1)) {
276 fprintf(stderr, "invalid write long: %06x\n", addr);
279 mem.w[(addr ^ MEM_SIZE_M2) >> 1] = data >> 16;
280 mem.w[((addr + 2) ^ MEM_SIZE_M2) >> 1] = data;
284 unsigned int m68k_read_memory_8(unsigned int address) {
285 return read_byte(NULL, address);
288 unsigned int m68k_read_memory_16(unsigned int address) {
289 return read_word(NULL, address);
292 unsigned int m68k_read_memory_32(unsigned int address) {
293 return read_long(NULL, address);
296 void m68k_write_memory_8(unsigned int address, unsigned int value) {
297 write_byte(NULL, address, value);
300 void m68k_write_memory_16(unsigned int address, unsigned int value) {
301 write_word(NULL, address, value);
304 void m68k_write_memory_32(unsigned int address, unsigned int value) {
305 write_long(NULL, address, value);
308 /* Called when the CPU pulses the RESET line */
309 void cpu_pulse_reset(void)
311 // nmi_device_reset();
312 // output_device_reset();
313 // input_device_reset();
316 /* Called when the CPU changes the function code pins */
317 void cpu_set_fc(unsigned int fc)
322 /* Called when the CPU acknowledges an interrupt */
323 int cpu_irq_ack(int level)
327 // case IRQ_NMI_DEVICE:
328 // return nmi_device_ack();
329 // case IRQ_INPUT_DEVICE:
330 // return input_device_ack();
331 // case IRQ_OUTPUT_DEVICE:
332 // return output_device_ack();
334 // return M68K_INT_ACK_SPURIOUS;
338 int m68k_service_trap(unsigned int vector) {
339 //fprintf(stderr, "trap %x\n", vector);
340 if (vector == EXCEPTION_TRAP_BASE + 0xe) // TBI68K bye command
346 int main(int argc, char **argv) {
348 printf("usage: %s executable\n", argv[0]);
351 int entry_point = load_aout(argv[1]);
352 printf("entry_point %08x\n", entry_point);
356 m68k_set_cpu_type(M68K_CPU_TYPE_68000);
358 m68k_set_reg(M68K_REG_PC, entry_point);
359 m68k_set_reg(M68K_REG_SP, MEM_SIZE);
363 int sr = m68k_get_reg(NULL, M68K_REG_SR);
366 "pc=%08x d0=%08x d1=%08x d2=%08x d3=%08x d4=%08x d5=%08x d6=%08x d7=%08x a0=%08x a1=%08x a2=%08x a3=%08x a4=%08x a5=%08x a6=%08x a7=%08x sr=%04x xf=%d nf=%d zf=%d vf=%d cf=%d\n",
367 m68k_get_reg(NULL, M68K_REG_PC),
368 m68k_get_reg(NULL, M68K_REG_D0),
369 m68k_get_reg(NULL, M68K_REG_D1),
370 m68k_get_reg(NULL, M68K_REG_D2),
371 m68k_get_reg(NULL, M68K_REG_D3),
372 m68k_get_reg(NULL, M68K_REG_D4),
373 m68k_get_reg(NULL, M68K_REG_D5),
374 m68k_get_reg(NULL, M68K_REG_D6),
375 m68k_get_reg(NULL, M68K_REG_D7),
376 m68k_get_reg(NULL, M68K_REG_A0),
377 m68k_get_reg(NULL, M68K_REG_A1),
378 m68k_get_reg(NULL, M68K_REG_A2),
379 m68k_get_reg(NULL, M68K_REG_A3),
380 m68k_get_reg(NULL, M68K_REG_A4),
381 m68k_get_reg(NULL, M68K_REG_A5),
382 m68k_get_reg(NULL, M68K_REG_A6),
383 m68k_get_reg(NULL, M68K_REG_A7),
396 struct cpu_68000 cpu;
397 cpu_68000_init(&cpu, read_byte, NULL, write_byte, NULL);
398 cpu_68000_reset(&cpu);
404 "pc=%04x a=%02x b=%02x s=%04x x=%04x p=%02x hf=%d if=%d nf=%d zf=%d vf=%d cf=%d\n",
420 cpu_68000_execute(&cpu);