8 #include "Musashi/m68k.h"
10 #include "cpu_68000.h"
13 #define EXCEPTION_TRAP_BASE 0x20
18 #define MEM_SIZE 0x8000
19 #if __BYTE_ORDER == __LITTLE_ENDIAN
20 #define MEM_SIZE_M1 (MEM_SIZE - 1)
21 #define MEM_SIZE_M2 (MEM_SIZE - 2)
22 #define MEM_SIZE_M4 (MEM_SIZE - 4)
30 uint16_t w[MEM_SIZE >> 1];
31 uint32_t l[MEM_SIZE >> 2];
34 void load_s19(char *name) {
35 FILE *fp = fopen(name, "r");
42 while (fgets(line, 0x100, fp)) {
43 for (char *p = line; *p; ++p)
49 // allow comments and concatenation
50 if (line[0] != 'S' || line[1] != '1')
55 for (len = 0; len < 0x7f; ++len) {
56 char *p = line + 2 + len * 2;
67 buf[len] = (uint8_t)strtol(p, &q, 16);
70 fprintf(stderr, "not hex byte: %s\n", p);
76 fprintf(stderr, "too short: %s\n", line);
81 for (int i = 0; i < len; ++i)
83 if (checksum != 0xff) {
84 checksum -= 0xff + buf[len - 1];
87 "checksum %02x, should be %02x\n",
94 if (len != buf[0] + 1) {
95 fprintf(stderr, "incorrect length: %s\n", line);
100 int addr = (buf[1] << 8) | buf[2], end_addr;
101 end_addr = addr + len;
102 if (end_addr < addr || end_addr > MEM_SIZE) {
103 fprintf(stderr, "invalid load range: [0x%x, 0x%x)\n", addr, end_addr);
106 for (int i = 0; i < len; ++i)
107 mem.b[(addr + i) ^ MEM_SIZE_M1] = buf[3 + i];
113 int read_byte(void *context, int addr) {
117 data = 3; // bit 0 = rdrf, bit 1 = tdre
128 #if 0 // just keep sending 0xff at EOF
136 if (addr < 0 || addr >= MEM_SIZE) {
137 fprintf(stderr, "invalid read byte: %06x\n", addr);
140 data = mem.b[addr ^ MEM_SIZE_M1];
144 fprintf(stderr, "addr=%06x rd=%02x\n", addr, data);
149 int read_word(void *context, int addr) {
150 if (addr < 0 || addr >= MEM_SIZE || (addr & 1)) {
151 fprintf(stderr, "invalid read word: %06x\n", addr);
154 int data = mem.w[(addr ^ MEM_SIZE_M2) >> 1];
156 fprintf(stderr, "addr=%06x rd=%04x\n", addr, data);
161 int read_long(void *context, int addr) {
162 if (addr < 0 || addr >= MEM_SIZE - 2 || (addr & 1)) {
163 fprintf(stderr, "invalid read long: %06x\n", addr);
167 (mem.w[(addr ^ MEM_SIZE_M2) >> 1] << 16) |
168 mem.w[((addr + 2) ^ MEM_SIZE_M2) >> 1];
170 fprintf(stderr, "addr=%06x rd=%08x\n", addr, data);
175 void write_byte(void *context, int addr, int data) {
177 fprintf(stderr, "addr=%06x wr=%02x\n", addr, data);
196 if (addr < 0 || addr >= MEM_SIZE) {
197 fprintf(stderr, "invalid write byte: %06x\n", addr);
200 mem.b[addr ^ MEM_SIZE_M1] = data;
204 void write_word(void *context, int addr, int data) {
206 fprintf(stderr, "addr=%06x wr=%04x\n", addr, data);
208 if (addr < 0 || addr >= MEM_SIZE || (addr & 1)) {
209 fprintf(stderr, "invalid write word: %06x\n", addr);
212 mem.w[(addr ^ MEM_SIZE_M2) >> 1] = data;
215 void write_long(void *context, int addr, int data) {
217 fprintf(stderr, "addr=%06x wr=%08x\n", addr, data);
219 if (addr < 0 || addr >= MEM_SIZE - 2 || (addr & 1)) {
220 fprintf(stderr, "invalid write long: %06x\n", addr);
223 mem.w[(addr ^ MEM_SIZE_M2) >> 1] = data >> 16;
224 mem.w[((addr + 2) ^ MEM_SIZE_M2) >> 1] = data;
228 unsigned int m68k_read_memory_8(unsigned int address) {
229 return read_byte(NULL, address);
232 unsigned int m68k_read_memory_16(unsigned int address) {
233 return read_word(NULL, address);
236 unsigned int m68k_read_memory_32(unsigned int address) {
237 return read_long(NULL, address);
240 void m68k_write_memory_8(unsigned int address, unsigned int value) {
241 write_byte(NULL, address, value);
244 void m68k_write_memory_16(unsigned int address, unsigned int value) {
245 write_word(NULL, address, value);
248 void m68k_write_memory_32(unsigned int address, unsigned int value) {
249 write_long(NULL, address, value);
252 /* Called when the CPU pulses the RESET line */
253 void cpu_pulse_reset(void)
255 // nmi_device_reset();
256 // output_device_reset();
257 // input_device_reset();
260 /* Called when the CPU changes the function code pins */
261 void cpu_set_fc(unsigned int fc)
266 /* Called when the CPU acknowledges an interrupt */
267 int cpu_irq_ack(int level)
271 // case IRQ_NMI_DEVICE:
272 // return nmi_device_ack();
273 // case IRQ_INPUT_DEVICE:
274 // return input_device_ack();
275 // case IRQ_OUTPUT_DEVICE:
276 // return output_device_ack();
278 // return M68K_INT_ACK_SPURIOUS;
282 int m68k_service_trap(unsigned int vector) {
283 //fprintf(stderr, "trap %x\n", vector);
284 if (vector == EXCEPTION_TRAP_BASE + 0xe) // TBI68K bye command
290 int main(int argc, char **argv) {
292 printf("usage: %s image.s19\n", argv[0]);
297 // emulate Tutor firmware for TBI68K
298 mem.l[(0 ^ MEM_SIZE_M4) >> 2] = 0x8000; // initial SP
299 mem.l[(4 ^ MEM_SIZE_M4) >> 2] = 0x900; // initial PC
303 m68k_set_cpu_type(M68K_CPU_TYPE_68000);
308 int sr = m68k_get_reg(NULL, M68K_REG_SR);
311 "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",
312 m68k_get_reg(NULL, M68K_REG_PC),
313 m68k_get_reg(NULL, M68K_REG_D0),
314 m68k_get_reg(NULL, M68K_REG_D1),
315 m68k_get_reg(NULL, M68K_REG_D2),
316 m68k_get_reg(NULL, M68K_REG_D3),
317 m68k_get_reg(NULL, M68K_REG_D4),
318 m68k_get_reg(NULL, M68K_REG_D5),
319 m68k_get_reg(NULL, M68K_REG_D6),
320 m68k_get_reg(NULL, M68K_REG_D7),
321 m68k_get_reg(NULL, M68K_REG_A0),
322 m68k_get_reg(NULL, M68K_REG_A1),
323 m68k_get_reg(NULL, M68K_REG_A2),
324 m68k_get_reg(NULL, M68K_REG_A3),
325 m68k_get_reg(NULL, M68K_REG_A4),
326 m68k_get_reg(NULL, M68K_REG_A5),
327 m68k_get_reg(NULL, M68K_REG_A6),
328 m68k_get_reg(NULL, M68K_REG_A7),
341 struct cpu_68000 cpu;
342 cpu_68000_init(&cpu, read_byte, NULL, write_byte, NULL);
343 cpu_68000_reset(&cpu);
349 "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",
365 cpu_68000_execute(&cpu);