blob: 12f9af7483fc2031b349db5639c962ba2b0709ca [file] [log] [blame]
swissChili6c61a792020-07-28 16:29:20 -07001#include "cpu.h"
swissChilib71e0272020-08-08 15:56:14 -07002#include "common.h"
swissChili6c61a792020-07-28 16:29:20 -07003#include "instructions.h"
swissChili94ba1f52020-08-08 11:39:10 -07004#define SCREEN_ONLY_SDL
5#include "screen.h"
swissChili6c61a792020-07-28 16:29:20 -07006
swissChilic6b4f7e2020-08-09 16:36:36 -07007#include "dbg.h"
8#include <errno.h>
swissChili6c61a792020-07-28 16:29:20 -07009#include <endian.h>
10#include <stdio.h>
11#include <stdlib.h>
12#include <string.h>
13
14#define die(m, ...) \
swissChili6264a3b2020-07-30 19:02:07 -070015 printf("\033[31m" m "\033[0m\n", ##__VA_ARGS__); \
swissChili6c61a792020-07-28 16:29:20 -070016 exit(1);
17
swissChili6264a3b2020-07-30 19:02:07 -070018#define warn(m, ...) \
19 printf("\033[33m" m "\033[0m\n", ##__VA_ARGS__);
20
swissChili94ba1f52020-08-08 11:39:10 -070021
22sdl_screen_t *g_scr = NULL;
23
24
swissChilidbbd5402020-08-07 15:07:39 -070025void reset(cpu_t *cpu)
26{
swissChilib04a4022020-08-09 12:51:00 -070027 cpu->regs[SP] = 0xFF; // stack at is 0x100 + SP
swissChilibb478f12020-08-07 20:45:07 -070028 cpu->pc = 0x600; // arbitrary program counter start
swissChilidbbd5402020-08-07 15:07:39 -070029 cpu->running = true;
swissChilie7ee6da2020-08-08 16:14:21 -070030 memset(cpu->mem + 0x100, 0, 0xFE);
swissChilidbbd5402020-08-07 15:07:39 -070031}
32
swissChili6c61a792020-07-28 16:29:20 -070033cpu_t new_cpu()
34{
35 cpu_t cpu = { 0 };
swissChilib04a4022020-08-09 12:51:00 -070036 cpu.regs[SP] = 0xFF; // stack at is 0x100 + SP
swissChilibb478f12020-08-07 20:45:07 -070037 cpu.pc = 0x600; // arbitrary program counter start
swissChili6264a3b2020-07-30 19:02:07 -070038 cpu.running = true;
swissChili6c61a792020-07-28 16:29:20 -070039 cpu.mem = malloc(0xFFFF);
swissChilicc27cfe2020-08-08 12:57:57 -070040 cpu.screen_dirty = true;
swissChili6c61a792020-07-28 16:29:20 -070041 memset(cpu.mem, 0, 0xFFFF);
42
swissChilib71e0272020-08-08 15:56:14 -070043 ASSERT("Allocate memory for CPU", cpu.mem);
swissChili6c61a792020-07-28 16:29:20 -070044
45 return cpu;
46}
47
swissChilida4803e2020-08-06 20:06:04 -070048uint16_t le_to_native(uint8_t a, uint8_t b)
49{
50#ifdef LITTLE_ENDIAN
51 return b << 8 | a;
52#else
53 return a << 8 | b;
54#endif
55}
56
57void native_to_le(uint16_t n, uint8_t *a, uint8_t *b)
58{
59#ifdef LITTLE_ENDIAN
60 *a = n >> 8;
61 *b = n & 0xFF;
62#else
63 *a = n & 0xFF;
64 *b = n >> 8;
65#endif
66}
67
swissChili6264a3b2020-07-30 19:02:07 -070068void stack_push(cpu_t *cpu, uint8_t v)
69{
70 cpu->mem[cpu->regs[SP]-- + 0x100] = v;
71}
72
swissChilida4803e2020-08-06 20:06:04 -070073void stack_pushle(cpu_t *cpu, uint16_t v)
74{
75 uint8_t a, b;
76 native_to_le(v, &a, &b);
77 // push in "reverse" order so that the address is stored as LE
78 stack_push(cpu, b);
79 stack_push(cpu, a);
80}
81
swissChili6264a3b2020-07-30 19:02:07 -070082uint8_t stack_pop(cpu_t *cpu)
83{
84 return cpu->mem[cpu->regs[SP]++ + 0x100];
85}
86
swissChilida4803e2020-08-06 20:06:04 -070087uint16_t stack_pople(cpu_t *cpu)
88{
89 uint8_t a = stack_pop(cpu);
90 uint8_t b = stack_pop(cpu);
91 return le_to_native(a, b);
92}
93
swissChili6c61a792020-07-28 16:29:20 -070094void free_cpu(cpu_t *cpu)
95{
96 free(cpu->mem);
97}
98
swissChilida4803e2020-08-06 20:06:04 -070099// rotate right
swissChilicc27cfe2020-08-08 12:57:57 -0700100uint8_t ror(uint8_t a, uint8_t n)
swissChilida4803e2020-08-06 20:06:04 -0700101{
102 return (a >> n) | (a << (8 - n));
103}
104
105// rotate left
swissChilicc27cfe2020-08-08 12:57:57 -0700106uint8_t rol(uint8_t a, uint8_t n)
swissChilida4803e2020-08-06 20:06:04 -0700107{
108 return (a << n) | (a >> (8 - n));
109}
110
swissChilicc27cfe2020-08-08 12:57:57 -0700111void stat_nz(cpu_t *cpu, int8_t v)
swissChili6c61a792020-07-28 16:29:20 -0700112{
swissChili6264a3b2020-07-30 19:02:07 -0700113 cpu->status.negative = v < 0;
114 cpu->status.zero = v == 0;
115}
116
117// Used to check for overflow, is c unique?
swissChilicc27cfe2020-08-08 12:57:57 -0700118bool last_unique(bool a, bool b, bool c)
swissChili6264a3b2020-07-30 19:02:07 -0700119{
120 return a == b && a != c;
121}
122
swissChilicc27cfe2020-08-08 12:57:57 -0700123void stat_cv(cpu_t *cpu, uint8_t a, uint8_t b, uint8_t c)
swissChili6264a3b2020-07-30 19:02:07 -0700124{
125 cpu->status.overflow = last_unique(a >> 7, b >> 7, c >> 7);
126 cpu->status.carry = c < a || c < b;
127}
128
swissChilicc27cfe2020-08-08 12:57:57 -0700129void cmp(cpu_t *cpu, uint8_t reg, uint8_t mem)
swissChilida4803e2020-08-06 20:06:04 -0700130{
131 cpu->status.negative = 0;
132 cpu->status.zero = 0;
133 cpu->status.carry = 0;
134 if (cpu->regs[reg] < mem)
135 {
136 cpu->status.negative = 1;
137 }
138 else if (cpu->regs[reg] == mem)
139 {
140 cpu->status.zero = 1;
141 cpu->status.carry = 1;
142 }
143 else
144 {
145 cpu->status.carry = 1;
146 }
147}
148
149void execute(cpu_t *cpu, const char *mnemonic, uint8_t op, arg_t a, uint8_t am)
swissChili6264a3b2020-07-30 19:02:07 -0700150{
151 // used to save space
152 #define REGS \
153 R(X) R(A) R(Y)
154
swissChili710d18d2020-07-29 19:43:20 -0700155 switch (op) {
swissChili6264a3b2020-07-30 19:02:07 -0700156 // Load and store instructions:
157 #define R(reg) \
158 case LD##reg: \
159 cpu->regs[reg] = a.val; \
160 stat_nz(cpu, a.val); \
161 break;
162
163 REGS
164
165 #undef R
166
167 #define R(reg) \
168 case ST##reg: \
swissChili1970cb82020-08-10 13:22:39 -0700169 cpu->mem[a.ptr] = cpu->regs[reg]; \
swissChili6264a3b2020-07-30 19:02:07 -0700170 break; \
171
172 REGS
173
174 #undef R
175
176 // Arithmetic instructions:
177 // NOTE: binary coded decimals are NOT SUPPORTED because I don't want
178 // to implement them.
179 case ADC:
180 {
181 uint8_t sum = cpu->regs[A] + a.val + cpu->status.carry;
182 // signed overflow
183 stat_cv(cpu, cpu->regs[A], a.val + cpu->status.carry, sum);
184 stat_nz(cpu, sum);
185 cpu->regs[A] = sum;
186 break;
187 }
188
189 case SBC:
190 {
191 uint8_t diff = cpu->regs[A] - a.val - !cpu->status.carry;
192 stat_cv(cpu, cpu->regs[A], a.val - !cpu->status.carry, diff);
193 stat_nz(cpu, diff);
194 cpu->regs[A] = diff;
195 break;
196 }
197
198 case INC:
swissChili1970cb82020-08-10 13:22:39 -0700199 cpu->mem[a.ptr]++;
200 stat_nz(cpu, cpu->mem[a.ptr]);
swissChili6264a3b2020-07-30 19:02:07 -0700201 break;
202
203 case INX:
204 cpu->regs[X]++;
205 stat_nz(cpu, cpu->regs[X]);
206 break;
207
208 case INY:
209 cpu->regs[Y]++;
210 stat_nz(cpu, cpu->regs[Y]);
211 break;
212
213 case DEC:
swissChili1970cb82020-08-10 13:22:39 -0700214 cpu->mem[a.ptr]--;
215 stat_nz(cpu, cpu->mem[a.ptr]);
swissChili6264a3b2020-07-30 19:02:07 -0700216 break;
swissChilida4803e2020-08-06 20:06:04 -0700217
218 case DEX:
219 cpu->regs[X]--;
220 stat_nz(cpu, cpu->regs[X]);
221 break;
222
223 case DEY:
224 cpu->regs[Y]--;
225 stat_nz(cpu, cpu->regs[Y]);
226 break;
227
228 case ASL:
229 // This check must be done here unfortunately, it would be nice
230 // to do this while decoding operands but it would require
231 // a substantial change to the architecture of the emulator
232 if (am == AM_ACC)
233 {
234 cpu->status.carry = cpu->regs[A] >> 7;
235 cpu->regs[A] <<= 1;
236 stat_nz(cpu, cpu->regs[A]);
237 }
238 else
239 {
swissChili1970cb82020-08-10 13:22:39 -0700240 cpu->status.carry = cpu->mem[a.val] >> 7;
241 cpu->mem[a.ptr] <<= 1;
242 stat_nz(cpu, cpu->mem[a.ptr]);
swissChilida4803e2020-08-06 20:06:04 -0700243 }
244 break;
245
246 case LSR:
247 if (am == AM_ACC)
248 {
249 cpu->status.carry = cpu->regs[A] & 1;
250 cpu->regs[A] >>= 1;
251 stat_nz(cpu, cpu->regs[A]);
252 }
253 else
254 {
swissChili1970cb82020-08-10 13:22:39 -0700255 cpu->status.carry = cpu->mem[a.val] & 7;
256 cpu->mem[a.ptr] >>= 1;
257 stat_nz(cpu, cpu->mem[a.ptr]);
swissChilida4803e2020-08-06 20:06:04 -0700258 }
259 break;
260
261 case ROL:
262 if (am == AM_ACC)
263 {
264 cpu->status.carry = cpu->regs[A] >> 7;
265 cpu->regs[A] = rol(cpu->regs[A], 1);
266 stat_nz(cpu, cpu->regs[A]);
267 }
268 else
269 {
swissChili1970cb82020-08-10 13:22:39 -0700270 cpu->status.carry = cpu->mem[a.val] >> 7;
271 cpu->mem[a.ptr] = rol(a.val, 1);
272 stat_nz(cpu, cpu->mem[a.ptr]);
swissChilida4803e2020-08-06 20:06:04 -0700273 }
274 break;
275
276 case ROR:
277 if (am == AM_ACC)
278 {
279 cpu->status.carry = cpu->regs[A] & 1;
280 cpu->regs[A] = ror(cpu->regs[A], 1);
281 stat_nz(cpu, cpu->regs[A]);
282 }
283 else
284 {
swissChili1970cb82020-08-10 13:22:39 -0700285 cpu->status.carry = cpu->mem[a.val] & 1;
286 cpu->mem[a.ptr] = ror(a.val, 1);
287 stat_nz(cpu, cpu->mem[a.ptr]);
swissChilida4803e2020-08-06 20:06:04 -0700288 }
289 break;
290
291 case AND:
292 cpu->regs[A] &= a.val;
293 stat_nz(cpu, cpu->regs[A]);
294 break;
295
296 case ORA:
297 cpu->regs[A] |= a.val;
298 stat_nz(cpu, cpu->regs[A]);
299 break;
300
301 case EOR:
302 cpu->regs[A] ^= a.val;
303 stat_nz(cpu, cpu->regs[A]);
304 break;
305
306 case CMP:
307 cmp(cpu, A, a.val);
308 break;
309
310 case CPX:
311 cmp(cpu, X, a.val);
312 break;
313
314 case CPY:
315 cmp(cpu, Y, a.val);
316 break;
317
318 // TODO: implement BIT here
319
320 #define BRANCHES \
321 B(BCC, carry == 0) \
322 B(BCS, carry == 1) \
323 B(BNE, zero == 0) \
324 B(BEQ, zero == 1) \
325 B(BPL, negative == 0) \
326 B(BMI, negative == 1) \
327 B(BVC, overflow == 0) \
328 B(BVS, overflow == 1)
329
330 #define B(i, c) \
331 case i: \
332 if (cpu->status . c) \
333 cpu->pc = a.ptr;\
334 break;
335
336 BRANCHES
337
338 #undef B
339 #undef BRANCHES
340
341 #define TRANSFERS \
342 T(A, X) \
343 T(X, A) \
344 T(A, Y) \
345 T(Y, A)
346
347 #define T(a, b) \
348 case T ## a ## b: \
349 cpu->regs[b] = cpu->regs[a]; \
350 stat_nz(cpu, cpu->regs[b]); \
351 break;
352
353 TRANSFERS
354
355 #undef T
356 #undef TRANSFERS
357
358 case TSX:
359 cpu->regs[X] = cpu->regs[SP];
360 stat_nz(cpu, cpu->regs[X]);
361 break;
362
363 case TXS:
364 cpu->regs[SP] = cpu->regs[X];
365 stat_nz(cpu, cpu->regs[X]);
366 break;
367
368 case PHA:
369 stack_push(cpu, cpu->regs[A]);
370 break;
371
372 case PLA:
373 cpu->regs[A] = stack_pop(cpu);
374 stat_nz(cpu, cpu->regs[A]);
375 break;
376
377 case PHP:
378 stack_push(cpu, *(uint8_t *)(&cpu->status));
379 break;
380
381 case PLP:
382 {
383 uint8_t s = stack_pop(cpu);
384 *(uint8_t *)(&cpu->status) = s;
385 }
386
387 case JMP:
388 cpu->pc = a.ptr;
389 break;
390
391 case JSR:
392 stack_pushle(cpu, cpu->pc);
swissChilib04a4022020-08-09 12:51:00 -0700393 cpu->pc = a.ptr;
swissChilida4803e2020-08-06 20:06:04 -0700394 break;
395
396 case RTS:
397 cpu->pc = stack_pople(cpu);
398 break;
399
400 // TODO: implement RTI
401 // TODO: implement flag instructions
402
403 case BRK:
404 // TODO: trigger an interrupt
405 cpu->running = false;
406 break;
407
408 case NOP:
409 break;
410
411 default:
swissChilib71e0272020-08-08 15:56:14 -0700412 warn("Unsupported opcode: %x\n", op);
413 THROW("Unsupported opcode");
swissChili710d18d2020-07-29 19:43:20 -0700414 }
swissChili6264a3b2020-07-30 19:02:07 -0700415 #undef REGS
swissChili6c61a792020-07-28 16:29:20 -0700416}
417
swissChili1970cb82020-08-10 13:22:39 -0700418uint16_t fetch_le(cpu_t *cpu, uint16_t *pc)
swissChili6c61a792020-07-28 16:29:20 -0700419{
swissChili1970cb82020-08-10 13:22:39 -0700420 uint8_t a = cpu->mem[(*pc)++];
421 uint8_t b = cpu->mem[(*pc)++];
swissChili6c61a792020-07-28 16:29:20 -0700422 return le_to_native(a, b);
423}
424
swissChilicc27cfe2020-08-08 12:57:57 -0700425arg_t arg_imm(uint16_t a)
swissChili710d18d2020-07-29 19:43:20 -0700426{
427 return (arg_t){ a, a };
428}
429
swissChilicc27cfe2020-08-08 12:57:57 -0700430arg_t arg_ptr(cpu_t *c, uint flags, uint16_t p)
swissChili710d18d2020-07-29 19:43:20 -0700431{
432 if (flags & FETCH_NO_INDIRECTION)
433 return arg_imm(p);
434
435 return (arg_t){ c->mem[p], p };
436}
437
swissChilicc27cfe2020-08-08 12:57:57 -0700438arg_t arg(uint16_t v, uint16_t a)
swissChili710d18d2020-07-29 19:43:20 -0700439{
440 return (arg_t){ v, a };
441}
442
swissChili1970cb82020-08-10 13:22:39 -0700443arg_t fetch_addr(cpu_t *cpu, uint8_t am, uint f, uint16_t *pc)
swissChili6c61a792020-07-28 16:29:20 -0700444{
445 switch (am)
446 {
447 case AM_ACC:
448 case AM_IMP:
swissChili710d18d2020-07-29 19:43:20 -0700449 return arg_imm(0);
swissChili6c61a792020-07-28 16:29:20 -0700450
451 // In both cases return immediate 8 bit value
452 case AM_IMM:
453 case AM_ZP:
swissChili1970cb82020-08-10 13:22:39 -0700454 return arg_imm(cpu->mem[(*pc)++]);
swissChili6c61a792020-07-28 16:29:20 -0700455
456 case AM_ABS:
swissChili1970cb82020-08-10 13:22:39 -0700457 return arg_ptr(cpu, f, fetch_le(cpu, pc));
swissChili6c61a792020-07-28 16:29:20 -0700458
459 case AM_REL:
460 {
swissChili1970cb82020-08-10 13:22:39 -0700461 uint16_t pc_hi = * pc + 1;
462 return arg_ptr(cpu, f, (int8_t)cpu->mem[(*pc)++] + pc_hi);
swissChili6c61a792020-07-28 16:29:20 -0700463 }
464
465 case AM_IND:
466 {
swissChili1970cb82020-08-10 13:22:39 -0700467 uint16_t addr = fetch_le(cpu, pc);
swissChili6264a3b2020-07-30 19:02:07 -0700468
469 if (f & FETCH_NO_INDIRECTION)
470 return arg_imm(addr);
471
swissChili1970cb82020-08-10 13:22:39 -0700472 uint8_t low = cpu->mem[addr],
473 high = cpu->mem[addr + 1];
swissChili6c61a792020-07-28 16:29:20 -0700474
swissChili710d18d2020-07-29 19:43:20 -0700475 return arg_ptr(cpu, f, le_to_native(low, high));
swissChili6c61a792020-07-28 16:29:20 -0700476 }
477
478 case AM_AX:
swissChili94ba1f52020-08-08 11:39:10 -0700479 if (f & FETCH_NO_INDIRECTION)
swissChili1970cb82020-08-10 13:22:39 -0700480 return arg_ptr(cpu, f, fetch_le(cpu, pc));
swissChili94ba1f52020-08-08 11:39:10 -0700481
swissChili1970cb82020-08-10 13:22:39 -0700482 return arg_ptr(cpu, f, fetch_le(cpu, pc) + cpu->regs[X]);
swissChili6c61a792020-07-28 16:29:20 -0700483
484 case AM_AY:
swissChili94ba1f52020-08-08 11:39:10 -0700485 if (f & FETCH_NO_INDIRECTION)
swissChili1970cb82020-08-10 13:22:39 -0700486 return arg_ptr(cpu, f, fetch_le(cpu, pc));
swissChili94ba1f52020-08-08 11:39:10 -0700487
swissChili1970cb82020-08-10 13:22:39 -0700488 return arg_ptr(cpu, f, fetch_le(cpu, pc) + cpu->regs[Y]);
swissChili6c61a792020-07-28 16:29:20 -0700489
490 case AM_ZPX:
swissChili94ba1f52020-08-08 11:39:10 -0700491 if (f & FETCH_NO_INDIRECTION)
swissChili1970cb82020-08-10 13:22:39 -0700492 return arg_ptr(cpu, f, cpu->mem[(*pc)++]);
493 return arg_ptr(cpu, f, cpu->mem[(*pc)++] + cpu->regs[X]);
swissChili6c61a792020-07-28 16:29:20 -0700494
495 case AM_ZPY:
swissChili94ba1f52020-08-08 11:39:10 -0700496 if (f & FETCH_NO_INDIRECTION)
swissChili1970cb82020-08-10 13:22:39 -0700497 return arg_ptr(cpu, f, cpu->mem[(*pc)++]);
498 return arg_ptr(cpu, f, cpu->mem[(*pc)++] + cpu->regs[Y]);
swissChili6c61a792020-07-28 16:29:20 -0700499
500 case AM_ZIX:
501 {
swissChili1970cb82020-08-10 13:22:39 -0700502 uint8_t zp = cpu->mem[(*pc)++];
swissChili6264a3b2020-07-30 19:02:07 -0700503
504 if (f & FETCH_NO_INDIRECTION)
505 return arg_imm(zp);
506
swissChili710d18d2020-07-29 19:43:20 -0700507 uint16_t addr = zp + cpu->regs[X];
swissChilib71e0272020-08-08 15:56:14 -0700508 uint16_t indirect = le_to_native(cpu->mem[addr], cpu->mem[addr + 1]);
swissChili710d18d2020-07-29 19:43:20 -0700509 return arg_ptr(cpu, f, indirect);
swissChili6c61a792020-07-28 16:29:20 -0700510 }
511
512 case AM_ZIY:
513 {
swissChili1970cb82020-08-10 13:22:39 -0700514 uint8_t zp = cpu->mem[(*pc)++];
swissChili6264a3b2020-07-30 19:02:07 -0700515
516 if (f & FETCH_NO_INDIRECTION)
517 return arg_imm(zp);
518
swissChili1970cb82020-08-10 13:22:39 -0700519 uint16_t base = le_to_native(cpu->mem[zp], cpu->mem[zp + 1]);
swissChili710d18d2020-07-29 19:43:20 -0700520 return arg_ptr(cpu, f, base + cpu->regs[Y]);
swissChili6c61a792020-07-28 16:29:20 -0700521 }
522
523 default:
swissChilib71e0272020-08-08 15:56:14 -0700524 warn("Unknown address mode %x", am);
525 THROW("Unknowng address mode");
swissChili710d18d2020-07-29 19:43:20 -0700526 __builtin_unreachable();
swissChili6c61a792020-07-28 16:29:20 -0700527 }
528}
529
swissChilicc27cfe2020-08-08 12:57:57 -0700530void step(cpu_t *cpu)
swissChili6c61a792020-07-28 16:29:20 -0700531{
swissChilicc27cfe2020-08-08 12:57:57 -0700532 cpu->screen_dirty = false;
swissChilib71e0272020-08-08 15:56:14 -0700533 uint8_t pc = cpu->pc;
534 uint8_t op = cpu->mem[cpu->pc++];
535 switch (op)
swissChili6c61a792020-07-28 16:29:20 -0700536 {
537#define INST(mn, am, op) \
538 case op: \
swissChili1970cb82020-08-10 13:22:39 -0700539 execute(cpu, #mn, mn, fetch_addr(cpu, am, 0, &cpu->pc), am); \
swissChili6c61a792020-07-28 16:29:20 -0700540 break;
541
542 INSTRUCTIONS
543
544#undef INST
545
546 default:
swissChilib71e0272020-08-08 15:56:14 -0700547 warn("Undefined opcode %x near %x [%x]", op, pc, cpu->mem[pc]);
548 THROW("Undefined opcode");
swissChili6c61a792020-07-28 16:29:20 -0700549 }
550}
551
swissChilic51e9222020-08-07 16:09:14 -0700552int dump_inst(cpu_t *cpu, char *buf, const char *mn, uint16_t addr, uint8_t am)
swissChili6c61a792020-07-28 16:29:20 -0700553{
swissChilic51e9222020-08-07 16:09:14 -0700554 char *end = buf;
555 end += sprintf(end, "%s ", mn);
swissChili6c61a792020-07-28 16:29:20 -0700556
557 switch (am)
558 {
559 case AM_IMM:
swissChilic51e9222020-08-07 16:09:14 -0700560 end += sprintf(end, "#");
swissChili6c61a792020-07-28 16:29:20 -0700561 case AM_REL:
562 case AM_ABS:
563 case AM_ZP:
swissChilic51e9222020-08-07 16:09:14 -0700564 end += sprintf(end, "$%x", addr);
swissChili6c61a792020-07-28 16:29:20 -0700565 break;
566
567 case AM_IND:
swissChilic51e9222020-08-07 16:09:14 -0700568 end += sprintf(end, "($%x)", addr);
swissChili6c61a792020-07-28 16:29:20 -0700569 break;
570
571 case AM_AX:
572 case AM_ZPX:
swissChilic51e9222020-08-07 16:09:14 -0700573 end += sprintf(end, "$%x, X", addr);
swissChili6c61a792020-07-28 16:29:20 -0700574 break;
575
576 case AM_AY:
577 case AM_ZPY:
swissChilic51e9222020-08-07 16:09:14 -0700578 end += sprintf(end, "$%x, Y", addr);
swissChili6c61a792020-07-28 16:29:20 -0700579 break;
580
581 case AM_ZIX:
swissChilic51e9222020-08-07 16:09:14 -0700582 end += sprintf(end, "($%x, X)", addr);
swissChili6c61a792020-07-28 16:29:20 -0700583 break;
584
585 case AM_ZIY:
swissChilic51e9222020-08-07 16:09:14 -0700586 end += sprintf(end, "($%x), Y", addr);
swissChili6c61a792020-07-28 16:29:20 -0700587 break;
588 }
589
swissChilic51e9222020-08-07 16:09:14 -0700590 return end - buf;
swissChili6c61a792020-07-28 16:29:20 -0700591}
592
swissChili1970cb82020-08-10 13:22:39 -0700593char *disas_step(cpu_t *cpu, uint16_t *pc)
swissChili6c61a792020-07-28 16:29:20 -0700594{
swissChilic51e9222020-08-07 16:09:14 -0700595 char *buffer = malloc(80);
596 char *end = buffer;
597
598 // end += sprintf(buffer, "$%x", cpu->pc);
swissChili1970cb82020-08-10 13:22:39 -0700599 uint8_t op = cpu->mem[(*pc)++];
swissChili6c61a792020-07-28 16:29:20 -0700600 switch (op)
601 {
602#define INST(mn, am, op) \
603 case op: \
swissChilic51e9222020-08-07 16:09:14 -0700604 end += dump_inst(cpu, end, #mn, \
swissChili1970cb82020-08-10 13:22:39 -0700605 fetch_addr(cpu, am, FETCH_NO_INDIRECTION, pc).ptr, am); \
swissChili6c61a792020-07-28 16:29:20 -0700606 break;
607
608 INSTRUCTIONS
609
610#undef INST
611
612 default:
swissChilic51e9222020-08-07 16:09:14 -0700613 end += sprintf(end, "Undefined opcode %x", op);
swissChili6c61a792020-07-28 16:29:20 -0700614 }
swissChilic51e9222020-08-07 16:09:14 -0700615
616 *end = 0;
617
618 return buffer;
swissChili6c61a792020-07-28 16:29:20 -0700619}
620
swissChilida4803e2020-08-06 20:06:04 -0700621void disas_num(cpu_t *cpu, uint16_t num)
622{
swissChili1970cb82020-08-10 13:22:39 -0700623 uint16_t pc = 0x600;
swissChilida4803e2020-08-06 20:06:04 -0700624 for (int i = 0; i < num; i++)
625 {
swissChili1970cb82020-08-10 13:22:39 -0700626 uint16_t last_pc = pc;
627 char *line = disas_step(cpu, &pc);
swissChilic51e9222020-08-07 16:09:14 -0700628 printf("$%x\t%s\n", last_pc, line);
629 free(line);
swissChilida4803e2020-08-06 20:06:04 -0700630 }
631}
632
swissChili6c61a792020-07-28 16:29:20 -0700633void disas(cpu_t *cpu)
634{
swissChili1970cb82020-08-10 13:22:39 -0700635 uint16_t pc = 0x600;
swissChili6264a3b2020-07-30 19:02:07 -0700636 // Raw binary, no way to know what's code what isn't
swissChili6c61a792020-07-28 16:29:20 -0700637 while (cpu->pc < 0xFFFF)
638 {
swissChili1970cb82020-08-10 13:22:39 -0700639 uint16_t last_pc = pc;
640 char *line = disas_step(cpu, &pc);
swissChilic51e9222020-08-07 16:09:14 -0700641 printf("$%x\t%s\n", last_pc, line);
642 free(line);
swissChili6c61a792020-07-28 16:29:20 -0700643 }
644}
swissChilic51e9222020-08-07 16:09:14 -0700645
swissChilida4803e2020-08-06 20:06:04 -0700646void run(cpu_t *cpu)
647{
648 while (cpu->running)
649 {
650 step(cpu);
651 }
652
653 printf("CPU Halted\n");
654}
swissChilic6b4f7e2020-08-09 16:36:36 -0700655
656void run_mq(cpu_t *cpu, mqd_t mq)
657{
658 char buf[MQ_BUF_LEN];
659 bool running;
660
661 while (true)
662 {
663 if (running)
664 {
665 if (cpu->running)
666 step(cpu);
667 else
668 running = false;
669 }
670
671 ssize_t recvd = mq_receive(mq, buf, MQ_BUF_LEN * 2, NULL);
672
673 if (recvd == -1 && errno != EAGAIN)
674 {
675 printf("errno = %d\n", errno);
676 THROW("mq_receive returned -1");
677 }
678
679 if (recvd > 0)
680 {
681 if (debug_stmt(cpu, buf, &running))
682 break;
683 }
684 }
685}