blob: ef544a7e60403846f37189f6b0ad549e1744be17 [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"
4
swissChilic6b4f7e2020-08-09 16:36:36 -07005#include "dbg.h"
6#include <errno.h>
swissChili6c61a792020-07-28 16:29:20 -07007#include <endian.h>
8#include <stdio.h>
9#include <stdlib.h>
10#include <string.h>
11
swissChili6c61a792020-07-28 16:29:20 -070012
swissChili6264a3b2020-07-30 19:02:07 -070013#define warn(m, ...) \
14 printf("\033[33m" m "\033[0m\n", ##__VA_ARGS__);
15
swissChili94ba1f52020-08-08 11:39:10 -070016
swissChilidbbd5402020-08-07 15:07:39 -070017void reset(cpu_t *cpu)
18{
swissChilib04a4022020-08-09 12:51:00 -070019 cpu->regs[SP] = 0xFF; // stack at is 0x100 + SP
swissChilibb478f12020-08-07 20:45:07 -070020 cpu->pc = 0x600; // arbitrary program counter start
swissChilidbbd5402020-08-07 15:07:39 -070021 cpu->running = true;
swissChilie7ee6da2020-08-08 16:14:21 -070022 memset(cpu->mem + 0x100, 0, 0xFE);
swissChilidbbd5402020-08-07 15:07:39 -070023}
24
swissChili6c61a792020-07-28 16:29:20 -070025cpu_t new_cpu()
26{
27 cpu_t cpu = { 0 };
swissChilib04a4022020-08-09 12:51:00 -070028 cpu.regs[SP] = 0xFF; // stack at is 0x100 + SP
swissChilibb478f12020-08-07 20:45:07 -070029 cpu.pc = 0x600; // arbitrary program counter start
swissChili6264a3b2020-07-30 19:02:07 -070030 cpu.running = true;
swissChili6c61a792020-07-28 16:29:20 -070031 cpu.mem = malloc(0xFFFF);
swissChilicc27cfe2020-08-08 12:57:57 -070032 cpu.screen_dirty = true;
swissChili6c61a792020-07-28 16:29:20 -070033 memset(cpu.mem, 0, 0xFFFF);
34
swissChilib71e0272020-08-08 15:56:14 -070035 ASSERT("Allocate memory for CPU", cpu.mem);
swissChili6c61a792020-07-28 16:29:20 -070036
37 return cpu;
38}
39
swissChilida4803e2020-08-06 20:06:04 -070040uint16_t le_to_native(uint8_t a, uint8_t b)
41{
42#ifdef LITTLE_ENDIAN
43 return b << 8 | a;
44#else
45 return a << 8 | b;
46#endif
47}
48
49void native_to_le(uint16_t n, uint8_t *a, uint8_t *b)
50{
51#ifdef LITTLE_ENDIAN
52 *a = n >> 8;
53 *b = n & 0xFF;
54#else
55 *a = n & 0xFF;
56 *b = n >> 8;
57#endif
58}
59
swissChili6264a3b2020-07-30 19:02:07 -070060void stack_push(cpu_t *cpu, uint8_t v)
61{
62 cpu->mem[cpu->regs[SP]-- + 0x100] = v;
63}
64
swissChilida4803e2020-08-06 20:06:04 -070065void stack_pushle(cpu_t *cpu, uint16_t v)
66{
67 uint8_t a, b;
68 native_to_le(v, &a, &b);
69 // push in "reverse" order so that the address is stored as LE
70 stack_push(cpu, b);
71 stack_push(cpu, a);
72}
73
swissChili6264a3b2020-07-30 19:02:07 -070074uint8_t stack_pop(cpu_t *cpu)
75{
76 return cpu->mem[cpu->regs[SP]++ + 0x100];
77}
78
swissChilida4803e2020-08-06 20:06:04 -070079uint16_t stack_pople(cpu_t *cpu)
80{
81 uint8_t a = stack_pop(cpu);
82 uint8_t b = stack_pop(cpu);
83 return le_to_native(a, b);
84}
85
swissChili6c61a792020-07-28 16:29:20 -070086void free_cpu(cpu_t *cpu)
87{
88 free(cpu->mem);
89}
90
swissChilida4803e2020-08-06 20:06:04 -070091// rotate right
swissChilicc27cfe2020-08-08 12:57:57 -070092uint8_t ror(uint8_t a, uint8_t n)
swissChilida4803e2020-08-06 20:06:04 -070093{
94 return (a >> n) | (a << (8 - n));
95}
96
97// rotate left
swissChilicc27cfe2020-08-08 12:57:57 -070098uint8_t rol(uint8_t a, uint8_t n)
swissChilida4803e2020-08-06 20:06:04 -070099{
100 return (a << n) | (a >> (8 - n));
101}
102
swissChilicc27cfe2020-08-08 12:57:57 -0700103void stat_nz(cpu_t *cpu, int8_t v)
swissChili6c61a792020-07-28 16:29:20 -0700104{
swissChili6264a3b2020-07-30 19:02:07 -0700105 cpu->status.negative = v < 0;
106 cpu->status.zero = v == 0;
107}
108
109// Used to check for overflow, is c unique?
swissChilicc27cfe2020-08-08 12:57:57 -0700110bool last_unique(bool a, bool b, bool c)
swissChili6264a3b2020-07-30 19:02:07 -0700111{
112 return a == b && a != c;
113}
114
swissChilicc27cfe2020-08-08 12:57:57 -0700115void stat_cv(cpu_t *cpu, uint8_t a, uint8_t b, uint8_t c)
swissChili6264a3b2020-07-30 19:02:07 -0700116{
117 cpu->status.overflow = last_unique(a >> 7, b >> 7, c >> 7);
118 cpu->status.carry = c < a || c < b;
119}
120
swissChilicc27cfe2020-08-08 12:57:57 -0700121void cmp(cpu_t *cpu, uint8_t reg, uint8_t mem)
swissChilida4803e2020-08-06 20:06:04 -0700122{
123 cpu->status.negative = 0;
124 cpu->status.zero = 0;
125 cpu->status.carry = 0;
126 if (cpu->regs[reg] < mem)
127 {
128 cpu->status.negative = 1;
129 }
130 else if (cpu->regs[reg] == mem)
131 {
132 cpu->status.zero = 1;
133 cpu->status.carry = 1;
134 }
135 else
136 {
137 cpu->status.carry = 1;
138 }
139}
140
141void execute(cpu_t *cpu, const char *mnemonic, uint8_t op, arg_t a, uint8_t am)
swissChili6264a3b2020-07-30 19:02:07 -0700142{
143 // used to save space
144 #define REGS \
145 R(X) R(A) R(Y)
146
swissChili710d18d2020-07-29 19:43:20 -0700147 switch (op) {
swissChili6264a3b2020-07-30 19:02:07 -0700148 // Load and store instructions:
149 #define R(reg) \
150 case LD##reg: \
151 cpu->regs[reg] = a.val; \
152 stat_nz(cpu, a.val); \
153 break;
154
155 REGS
156
157 #undef R
158
159 #define R(reg) \
160 case ST##reg: \
swissChili1970cb82020-08-10 13:22:39 -0700161 cpu->mem[a.ptr] = cpu->regs[reg]; \
swissChili6264a3b2020-07-30 19:02:07 -0700162 break; \
163
164 REGS
165
166 #undef R
167
168 // Arithmetic instructions:
169 // NOTE: binary coded decimals are NOT SUPPORTED because I don't want
170 // to implement them.
171 case ADC:
172 {
173 uint8_t sum = cpu->regs[A] + a.val + cpu->status.carry;
174 // signed overflow
175 stat_cv(cpu, cpu->regs[A], a.val + cpu->status.carry, sum);
176 stat_nz(cpu, sum);
177 cpu->regs[A] = sum;
178 break;
179 }
180
181 case SBC:
182 {
183 uint8_t diff = cpu->regs[A] - a.val - !cpu->status.carry;
184 stat_cv(cpu, cpu->regs[A], a.val - !cpu->status.carry, diff);
185 stat_nz(cpu, diff);
186 cpu->regs[A] = diff;
187 break;
188 }
189
190 case INC:
swissChili1970cb82020-08-10 13:22:39 -0700191 cpu->mem[a.ptr]++;
192 stat_nz(cpu, cpu->mem[a.ptr]);
swissChili6264a3b2020-07-30 19:02:07 -0700193 break;
194
195 case INX:
196 cpu->regs[X]++;
197 stat_nz(cpu, cpu->regs[X]);
198 break;
199
200 case INY:
201 cpu->regs[Y]++;
202 stat_nz(cpu, cpu->regs[Y]);
203 break;
204
205 case DEC:
swissChili1970cb82020-08-10 13:22:39 -0700206 cpu->mem[a.ptr]--;
207 stat_nz(cpu, cpu->mem[a.ptr]);
swissChili6264a3b2020-07-30 19:02:07 -0700208 break;
swissChilida4803e2020-08-06 20:06:04 -0700209
210 case DEX:
211 cpu->regs[X]--;
212 stat_nz(cpu, cpu->regs[X]);
213 break;
214
215 case DEY:
216 cpu->regs[Y]--;
217 stat_nz(cpu, cpu->regs[Y]);
218 break;
219
220 case ASL:
221 // This check must be done here unfortunately, it would be nice
222 // to do this while decoding operands but it would require
223 // a substantial change to the architecture of the emulator
224 if (am == AM_ACC)
225 {
226 cpu->status.carry = cpu->regs[A] >> 7;
227 cpu->regs[A] <<= 1;
228 stat_nz(cpu, cpu->regs[A]);
229 }
230 else
231 {
swissChili1970cb82020-08-10 13:22:39 -0700232 cpu->status.carry = cpu->mem[a.val] >> 7;
233 cpu->mem[a.ptr] <<= 1;
234 stat_nz(cpu, cpu->mem[a.ptr]);
swissChilida4803e2020-08-06 20:06:04 -0700235 }
236 break;
237
238 case LSR:
239 if (am == AM_ACC)
240 {
241 cpu->status.carry = cpu->regs[A] & 1;
242 cpu->regs[A] >>= 1;
243 stat_nz(cpu, cpu->regs[A]);
244 }
245 else
246 {
swissChili1970cb82020-08-10 13:22:39 -0700247 cpu->status.carry = cpu->mem[a.val] & 7;
248 cpu->mem[a.ptr] >>= 1;
249 stat_nz(cpu, cpu->mem[a.ptr]);
swissChilida4803e2020-08-06 20:06:04 -0700250 }
251 break;
252
253 case ROL:
254 if (am == AM_ACC)
255 {
256 cpu->status.carry = cpu->regs[A] >> 7;
257 cpu->regs[A] = rol(cpu->regs[A], 1);
258 stat_nz(cpu, cpu->regs[A]);
259 }
260 else
261 {
swissChili1970cb82020-08-10 13:22:39 -0700262 cpu->status.carry = cpu->mem[a.val] >> 7;
263 cpu->mem[a.ptr] = rol(a.val, 1);
264 stat_nz(cpu, cpu->mem[a.ptr]);
swissChilida4803e2020-08-06 20:06:04 -0700265 }
266 break;
267
268 case ROR:
269 if (am == AM_ACC)
270 {
271 cpu->status.carry = cpu->regs[A] & 1;
272 cpu->regs[A] = ror(cpu->regs[A], 1);
273 stat_nz(cpu, cpu->regs[A]);
274 }
275 else
276 {
swissChili1970cb82020-08-10 13:22:39 -0700277 cpu->status.carry = cpu->mem[a.val] & 1;
278 cpu->mem[a.ptr] = ror(a.val, 1);
279 stat_nz(cpu, cpu->mem[a.ptr]);
swissChilida4803e2020-08-06 20:06:04 -0700280 }
281 break;
282
283 case AND:
284 cpu->regs[A] &= a.val;
285 stat_nz(cpu, cpu->regs[A]);
286 break;
287
288 case ORA:
289 cpu->regs[A] |= a.val;
290 stat_nz(cpu, cpu->regs[A]);
291 break;
292
293 case EOR:
294 cpu->regs[A] ^= a.val;
295 stat_nz(cpu, cpu->regs[A]);
296 break;
297
298 case CMP:
299 cmp(cpu, A, a.val);
300 break;
301
302 case CPX:
303 cmp(cpu, X, a.val);
304 break;
305
306 case CPY:
307 cmp(cpu, Y, a.val);
308 break;
309
310 // TODO: implement BIT here
311
312 #define BRANCHES \
313 B(BCC, carry == 0) \
314 B(BCS, carry == 1) \
315 B(BNE, zero == 0) \
316 B(BEQ, zero == 1) \
317 B(BPL, negative == 0) \
318 B(BMI, negative == 1) \
319 B(BVC, overflow == 0) \
320 B(BVS, overflow == 1)
321
322 #define B(i, c) \
323 case i: \
324 if (cpu->status . c) \
325 cpu->pc = a.ptr;\
326 break;
327
328 BRANCHES
329
330 #undef B
331 #undef BRANCHES
332
333 #define TRANSFERS \
334 T(A, X) \
335 T(X, A) \
336 T(A, Y) \
337 T(Y, A)
338
339 #define T(a, b) \
340 case T ## a ## b: \
341 cpu->regs[b] = cpu->regs[a]; \
342 stat_nz(cpu, cpu->regs[b]); \
343 break;
344
345 TRANSFERS
346
347 #undef T
348 #undef TRANSFERS
349
350 case TSX:
351 cpu->regs[X] = cpu->regs[SP];
352 stat_nz(cpu, cpu->regs[X]);
353 break;
354
355 case TXS:
356 cpu->regs[SP] = cpu->regs[X];
357 stat_nz(cpu, cpu->regs[X]);
358 break;
359
360 case PHA:
361 stack_push(cpu, cpu->regs[A]);
362 break;
363
364 case PLA:
365 cpu->regs[A] = stack_pop(cpu);
366 stat_nz(cpu, cpu->regs[A]);
367 break;
368
369 case PHP:
370 stack_push(cpu, *(uint8_t *)(&cpu->status));
371 break;
372
373 case PLP:
374 {
375 uint8_t s = stack_pop(cpu);
376 *(uint8_t *)(&cpu->status) = s;
377 }
378
379 case JMP:
380 cpu->pc = a.ptr;
381 break;
382
383 case JSR:
384 stack_pushle(cpu, cpu->pc);
swissChilib04a4022020-08-09 12:51:00 -0700385 cpu->pc = a.ptr;
swissChilida4803e2020-08-06 20:06:04 -0700386 break;
387
388 case RTS:
389 cpu->pc = stack_pople(cpu);
390 break;
391
392 // TODO: implement RTI
393 // TODO: implement flag instructions
394
395 case BRK:
396 // TODO: trigger an interrupt
397 cpu->running = false;
398 break;
399
400 case NOP:
401 break;
402
403 default:
swissChilib71e0272020-08-08 15:56:14 -0700404 warn("Unsupported opcode: %x\n", op);
405 THROW("Unsupported opcode");
swissChili710d18d2020-07-29 19:43:20 -0700406 }
swissChili6264a3b2020-07-30 19:02:07 -0700407 #undef REGS
swissChili6c61a792020-07-28 16:29:20 -0700408}
409
swissChili1970cb82020-08-10 13:22:39 -0700410uint16_t fetch_le(cpu_t *cpu, uint16_t *pc)
swissChili6c61a792020-07-28 16:29:20 -0700411{
swissChili1970cb82020-08-10 13:22:39 -0700412 uint8_t a = cpu->mem[(*pc)++];
413 uint8_t b = cpu->mem[(*pc)++];
swissChili6c61a792020-07-28 16:29:20 -0700414 return le_to_native(a, b);
415}
416
swissChilicc27cfe2020-08-08 12:57:57 -0700417arg_t arg_imm(uint16_t a)
swissChili710d18d2020-07-29 19:43:20 -0700418{
419 return (arg_t){ a, a };
420}
421
swissChilicc27cfe2020-08-08 12:57:57 -0700422arg_t arg_ptr(cpu_t *c, uint flags, uint16_t p)
swissChili710d18d2020-07-29 19:43:20 -0700423{
424 if (flags & FETCH_NO_INDIRECTION)
425 return arg_imm(p);
426
427 return (arg_t){ c->mem[p], p };
428}
429
swissChilicc27cfe2020-08-08 12:57:57 -0700430arg_t arg(uint16_t v, uint16_t a)
swissChili710d18d2020-07-29 19:43:20 -0700431{
432 return (arg_t){ v, a };
433}
434
swissChili1970cb82020-08-10 13:22:39 -0700435arg_t fetch_addr(cpu_t *cpu, uint8_t am, uint f, uint16_t *pc)
swissChili6c61a792020-07-28 16:29:20 -0700436{
437 switch (am)
438 {
439 case AM_ACC:
440 case AM_IMP:
swissChili710d18d2020-07-29 19:43:20 -0700441 return arg_imm(0);
swissChili6c61a792020-07-28 16:29:20 -0700442
443 // In both cases return immediate 8 bit value
444 case AM_IMM:
445 case AM_ZP:
swissChili1970cb82020-08-10 13:22:39 -0700446 return arg_imm(cpu->mem[(*pc)++]);
swissChili6c61a792020-07-28 16:29:20 -0700447
448 case AM_ABS:
swissChili1970cb82020-08-10 13:22:39 -0700449 return arg_ptr(cpu, f, fetch_le(cpu, pc));
swissChili6c61a792020-07-28 16:29:20 -0700450
451 case AM_REL:
452 {
swissChili1970cb82020-08-10 13:22:39 -0700453 uint16_t pc_hi = * pc + 1;
454 return arg_ptr(cpu, f, (int8_t)cpu->mem[(*pc)++] + pc_hi);
swissChili6c61a792020-07-28 16:29:20 -0700455 }
456
457 case AM_IND:
458 {
swissChili1970cb82020-08-10 13:22:39 -0700459 uint16_t addr = fetch_le(cpu, pc);
swissChili6264a3b2020-07-30 19:02:07 -0700460
461 if (f & FETCH_NO_INDIRECTION)
462 return arg_imm(addr);
463
swissChili1970cb82020-08-10 13:22:39 -0700464 uint8_t low = cpu->mem[addr],
465 high = cpu->mem[addr + 1];
swissChili6c61a792020-07-28 16:29:20 -0700466
swissChili710d18d2020-07-29 19:43:20 -0700467 return arg_ptr(cpu, f, le_to_native(low, high));
swissChili6c61a792020-07-28 16:29:20 -0700468 }
469
470 case AM_AX:
swissChili94ba1f52020-08-08 11:39:10 -0700471 if (f & FETCH_NO_INDIRECTION)
swissChili1970cb82020-08-10 13:22:39 -0700472 return arg_ptr(cpu, f, fetch_le(cpu, pc));
swissChili94ba1f52020-08-08 11:39:10 -0700473
swissChili1970cb82020-08-10 13:22:39 -0700474 return arg_ptr(cpu, f, fetch_le(cpu, pc) + cpu->regs[X]);
swissChili6c61a792020-07-28 16:29:20 -0700475
476 case AM_AY:
swissChili94ba1f52020-08-08 11:39:10 -0700477 if (f & FETCH_NO_INDIRECTION)
swissChili1970cb82020-08-10 13:22:39 -0700478 return arg_ptr(cpu, f, fetch_le(cpu, pc));
swissChili94ba1f52020-08-08 11:39:10 -0700479
swissChili1970cb82020-08-10 13:22:39 -0700480 return arg_ptr(cpu, f, fetch_le(cpu, pc) + cpu->regs[Y]);
swissChili6c61a792020-07-28 16:29:20 -0700481
482 case AM_ZPX:
swissChili94ba1f52020-08-08 11:39:10 -0700483 if (f & FETCH_NO_INDIRECTION)
swissChili1970cb82020-08-10 13:22:39 -0700484 return arg_ptr(cpu, f, cpu->mem[(*pc)++]);
485 return arg_ptr(cpu, f, cpu->mem[(*pc)++] + cpu->regs[X]);
swissChili6c61a792020-07-28 16:29:20 -0700486
487 case AM_ZPY:
swissChili94ba1f52020-08-08 11:39:10 -0700488 if (f & FETCH_NO_INDIRECTION)
swissChili1970cb82020-08-10 13:22:39 -0700489 return arg_ptr(cpu, f, cpu->mem[(*pc)++]);
490 return arg_ptr(cpu, f, cpu->mem[(*pc)++] + cpu->regs[Y]);
swissChili6c61a792020-07-28 16:29:20 -0700491
492 case AM_ZIX:
493 {
swissChili1970cb82020-08-10 13:22:39 -0700494 uint8_t zp = cpu->mem[(*pc)++];
swissChili6264a3b2020-07-30 19:02:07 -0700495
496 if (f & FETCH_NO_INDIRECTION)
497 return arg_imm(zp);
498
swissChili710d18d2020-07-29 19:43:20 -0700499 uint16_t addr = zp + cpu->regs[X];
swissChilib71e0272020-08-08 15:56:14 -0700500 uint16_t indirect = le_to_native(cpu->mem[addr], cpu->mem[addr + 1]);
swissChili710d18d2020-07-29 19:43:20 -0700501 return arg_ptr(cpu, f, indirect);
swissChili6c61a792020-07-28 16:29:20 -0700502 }
503
504 case AM_ZIY:
505 {
swissChili1970cb82020-08-10 13:22:39 -0700506 uint8_t zp = cpu->mem[(*pc)++];
swissChili6264a3b2020-07-30 19:02:07 -0700507
508 if (f & FETCH_NO_INDIRECTION)
509 return arg_imm(zp);
510
swissChili1970cb82020-08-10 13:22:39 -0700511 uint16_t base = le_to_native(cpu->mem[zp], cpu->mem[zp + 1]);
swissChili710d18d2020-07-29 19:43:20 -0700512 return arg_ptr(cpu, f, base + cpu->regs[Y]);
swissChili6c61a792020-07-28 16:29:20 -0700513 }
514
515 default:
swissChilib71e0272020-08-08 15:56:14 -0700516 warn("Unknown address mode %x", am);
517 THROW("Unknowng address mode");
swissChili710d18d2020-07-29 19:43:20 -0700518 __builtin_unreachable();
swissChili6c61a792020-07-28 16:29:20 -0700519 }
520}
521
swissChilicc27cfe2020-08-08 12:57:57 -0700522void step(cpu_t *cpu)
swissChili6c61a792020-07-28 16:29:20 -0700523{
swissChilicc27cfe2020-08-08 12:57:57 -0700524 cpu->screen_dirty = false;
swissChilib71e0272020-08-08 15:56:14 -0700525 uint8_t pc = cpu->pc;
526 uint8_t op = cpu->mem[cpu->pc++];
527 switch (op)
swissChili6c61a792020-07-28 16:29:20 -0700528 {
swissChili97b5d8b2020-08-15 20:00:54 -0700529#define INST(mn, am, op, len) \
swissChili6c61a792020-07-28 16:29:20 -0700530 case op: \
swissChili1970cb82020-08-10 13:22:39 -0700531 execute(cpu, #mn, mn, fetch_addr(cpu, am, 0, &cpu->pc), am); \
swissChili6c61a792020-07-28 16:29:20 -0700532 break;
533
534 INSTRUCTIONS
535
536#undef INST
537
538 default:
swissChilib71e0272020-08-08 15:56:14 -0700539 warn("Undefined opcode %x near %x [%x]", op, pc, cpu->mem[pc]);
540 THROW("Undefined opcode");
swissChili6c61a792020-07-28 16:29:20 -0700541 }
542}
543
swissChilic51e9222020-08-07 16:09:14 -0700544int dump_inst(cpu_t *cpu, char *buf, const char *mn, uint16_t addr, uint8_t am)
swissChili6c61a792020-07-28 16:29:20 -0700545{
swissChilic51e9222020-08-07 16:09:14 -0700546 char *end = buf;
547 end += sprintf(end, "%s ", mn);
swissChili6c61a792020-07-28 16:29:20 -0700548
549 switch (am)
550 {
551 case AM_IMM:
swissChilic51e9222020-08-07 16:09:14 -0700552 end += sprintf(end, "#");
swissChili6c61a792020-07-28 16:29:20 -0700553 case AM_REL:
554 case AM_ABS:
555 case AM_ZP:
swissChilic51e9222020-08-07 16:09:14 -0700556 end += sprintf(end, "$%x", addr);
swissChili6c61a792020-07-28 16:29:20 -0700557 break;
558
559 case AM_IND:
swissChilic51e9222020-08-07 16:09:14 -0700560 end += sprintf(end, "($%x)", addr);
swissChili6c61a792020-07-28 16:29:20 -0700561 break;
562
563 case AM_AX:
564 case AM_ZPX:
swissChilic51e9222020-08-07 16:09:14 -0700565 end += sprintf(end, "$%x, X", addr);
swissChili6c61a792020-07-28 16:29:20 -0700566 break;
567
568 case AM_AY:
569 case AM_ZPY:
swissChilic51e9222020-08-07 16:09:14 -0700570 end += sprintf(end, "$%x, Y", addr);
swissChili6c61a792020-07-28 16:29:20 -0700571 break;
572
573 case AM_ZIX:
swissChilic51e9222020-08-07 16:09:14 -0700574 end += sprintf(end, "($%x, X)", addr);
swissChili6c61a792020-07-28 16:29:20 -0700575 break;
576
577 case AM_ZIY:
swissChilic51e9222020-08-07 16:09:14 -0700578 end += sprintf(end, "($%x), Y", addr);
swissChili6c61a792020-07-28 16:29:20 -0700579 break;
580 }
581
swissChilic51e9222020-08-07 16:09:14 -0700582 return end - buf;
swissChili6c61a792020-07-28 16:29:20 -0700583}
584
swissChili1970cb82020-08-10 13:22:39 -0700585char *disas_step(cpu_t *cpu, uint16_t *pc)
swissChili6c61a792020-07-28 16:29:20 -0700586{
swissChilic51e9222020-08-07 16:09:14 -0700587 char *buffer = malloc(80);
588 char *end = buffer;
589
590 // end += sprintf(buffer, "$%x", cpu->pc);
swissChili1970cb82020-08-10 13:22:39 -0700591 uint8_t op = cpu->mem[(*pc)++];
swissChili6c61a792020-07-28 16:29:20 -0700592 switch (op)
593 {
swissChili97b5d8b2020-08-15 20:00:54 -0700594#define INST(mn, am, op, len) \
swissChili6c61a792020-07-28 16:29:20 -0700595 case op: \
swissChilic51e9222020-08-07 16:09:14 -0700596 end += dump_inst(cpu, end, #mn, \
swissChili1970cb82020-08-10 13:22:39 -0700597 fetch_addr(cpu, am, FETCH_NO_INDIRECTION, pc).ptr, am); \
swissChili6c61a792020-07-28 16:29:20 -0700598 break;
599
600 INSTRUCTIONS
601
602#undef INST
603
604 default:
swissChilic51e9222020-08-07 16:09:14 -0700605 end += sprintf(end, "Undefined opcode %x", op);
swissChili6c61a792020-07-28 16:29:20 -0700606 }
swissChilic51e9222020-08-07 16:09:14 -0700607
608 *end = 0;
609
610 return buffer;
swissChili6c61a792020-07-28 16:29:20 -0700611}
612
swissChilida4803e2020-08-06 20:06:04 -0700613void disas_num(cpu_t *cpu, uint16_t num)
614{
swissChili1970cb82020-08-10 13:22:39 -0700615 uint16_t pc = 0x600;
swissChilida4803e2020-08-06 20:06:04 -0700616 for (int i = 0; i < num; i++)
617 {
swissChili1970cb82020-08-10 13:22:39 -0700618 uint16_t last_pc = pc;
619 char *line = disas_step(cpu, &pc);
swissChilic51e9222020-08-07 16:09:14 -0700620 printf("$%x\t%s\n", last_pc, line);
621 free(line);
swissChilida4803e2020-08-06 20:06:04 -0700622 }
623}
624
swissChili6c61a792020-07-28 16:29:20 -0700625void disas(cpu_t *cpu)
626{
swissChili1970cb82020-08-10 13:22:39 -0700627 uint16_t pc = 0x600;
swissChili6264a3b2020-07-30 19:02:07 -0700628 // Raw binary, no way to know what's code what isn't
swissChili6c61a792020-07-28 16:29:20 -0700629 while (cpu->pc < 0xFFFF)
630 {
swissChili1970cb82020-08-10 13:22:39 -0700631 uint16_t last_pc = pc;
632 char *line = disas_step(cpu, &pc);
swissChilic51e9222020-08-07 16:09:14 -0700633 printf("$%x\t%s\n", last_pc, line);
634 free(line);
swissChili6c61a792020-07-28 16:29:20 -0700635 }
636}
swissChilic51e9222020-08-07 16:09:14 -0700637
swissChilida4803e2020-08-06 20:06:04 -0700638void run(cpu_t *cpu)
639{
640 while (cpu->running)
641 {
642 step(cpu);
643 }
644
645 printf("CPU Halted\n");
646}
swissChilic6b4f7e2020-08-09 16:36:36 -0700647
648void run_mq(cpu_t *cpu, mqd_t mq)
649{
650 char buf[MQ_BUF_LEN];
651 bool running;
652
653 while (true)
654 {
655 if (running)
656 {
657 if (cpu->running)
658 step(cpu);
659 else
660 running = false;
661 }
662
663 ssize_t recvd = mq_receive(mq, buf, MQ_BUF_LEN * 2, NULL);
664
665 if (recvd == -1 && errno != EAGAIN)
666 {
667 printf("errno = %d\n", errno);
668 THROW("mq_receive returned -1");
669 }
670
671 if (recvd > 0)
672 {
673 if (debug_stmt(cpu, buf, &running))
674 break;
675 }
676 }
677}