blob: ce489cc5b94f102e3b7bdb172afec880a7f18269 [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
swissChili6c61a792020-07-28 16:29:20 -070014
swissChili6264a3b2020-07-30 19:02:07 -070015#define warn(m, ...) \
16 printf("\033[33m" m "\033[0m\n", ##__VA_ARGS__);
17
swissChili94ba1f52020-08-08 11:39:10 -070018
19sdl_screen_t *g_scr = NULL;
20
21
swissChilidbbd5402020-08-07 15:07:39 -070022void reset(cpu_t *cpu)
23{
swissChilib04a4022020-08-09 12:51:00 -070024 cpu->regs[SP] = 0xFF; // stack at is 0x100 + SP
swissChilibb478f12020-08-07 20:45:07 -070025 cpu->pc = 0x600; // arbitrary program counter start
swissChilidbbd5402020-08-07 15:07:39 -070026 cpu->running = true;
swissChilie7ee6da2020-08-08 16:14:21 -070027 memset(cpu->mem + 0x100, 0, 0xFE);
swissChilidbbd5402020-08-07 15:07:39 -070028}
29
swissChili6c61a792020-07-28 16:29:20 -070030cpu_t new_cpu()
31{
32 cpu_t cpu = { 0 };
swissChilib04a4022020-08-09 12:51:00 -070033 cpu.regs[SP] = 0xFF; // stack at is 0x100 + SP
swissChilibb478f12020-08-07 20:45:07 -070034 cpu.pc = 0x600; // arbitrary program counter start
swissChili6264a3b2020-07-30 19:02:07 -070035 cpu.running = true;
swissChili6c61a792020-07-28 16:29:20 -070036 cpu.mem = malloc(0xFFFF);
swissChilicc27cfe2020-08-08 12:57:57 -070037 cpu.screen_dirty = true;
swissChili6c61a792020-07-28 16:29:20 -070038 memset(cpu.mem, 0, 0xFFFF);
39
swissChilib71e0272020-08-08 15:56:14 -070040 ASSERT("Allocate memory for CPU", cpu.mem);
swissChili6c61a792020-07-28 16:29:20 -070041
42 return cpu;
43}
44
swissChilida4803e2020-08-06 20:06:04 -070045uint16_t le_to_native(uint8_t a, uint8_t b)
46{
47#ifdef LITTLE_ENDIAN
48 return b << 8 | a;
49#else
50 return a << 8 | b;
51#endif
52}
53
54void native_to_le(uint16_t n, uint8_t *a, uint8_t *b)
55{
56#ifdef LITTLE_ENDIAN
57 *a = n >> 8;
58 *b = n & 0xFF;
59#else
60 *a = n & 0xFF;
61 *b = n >> 8;
62#endif
63}
64
swissChili6264a3b2020-07-30 19:02:07 -070065void stack_push(cpu_t *cpu, uint8_t v)
66{
67 cpu->mem[cpu->regs[SP]-- + 0x100] = v;
68}
69
swissChilida4803e2020-08-06 20:06:04 -070070void stack_pushle(cpu_t *cpu, uint16_t v)
71{
72 uint8_t a, b;
73 native_to_le(v, &a, &b);
74 // push in "reverse" order so that the address is stored as LE
75 stack_push(cpu, b);
76 stack_push(cpu, a);
77}
78
swissChili6264a3b2020-07-30 19:02:07 -070079uint8_t stack_pop(cpu_t *cpu)
80{
81 return cpu->mem[cpu->regs[SP]++ + 0x100];
82}
83
swissChilida4803e2020-08-06 20:06:04 -070084uint16_t stack_pople(cpu_t *cpu)
85{
86 uint8_t a = stack_pop(cpu);
87 uint8_t b = stack_pop(cpu);
88 return le_to_native(a, b);
89}
90
swissChili6c61a792020-07-28 16:29:20 -070091void free_cpu(cpu_t *cpu)
92{
93 free(cpu->mem);
94}
95
swissChilida4803e2020-08-06 20:06:04 -070096// rotate right
swissChilicc27cfe2020-08-08 12:57:57 -070097uint8_t ror(uint8_t a, uint8_t n)
swissChilida4803e2020-08-06 20:06:04 -070098{
99 return (a >> n) | (a << (8 - n));
100}
101
102// rotate left
swissChilicc27cfe2020-08-08 12:57:57 -0700103uint8_t rol(uint8_t a, uint8_t n)
swissChilida4803e2020-08-06 20:06:04 -0700104{
105 return (a << n) | (a >> (8 - n));
106}
107
swissChilicc27cfe2020-08-08 12:57:57 -0700108void stat_nz(cpu_t *cpu, int8_t v)
swissChili6c61a792020-07-28 16:29:20 -0700109{
swissChili6264a3b2020-07-30 19:02:07 -0700110 cpu->status.negative = v < 0;
111 cpu->status.zero = v == 0;
112}
113
114// Used to check for overflow, is c unique?
swissChilicc27cfe2020-08-08 12:57:57 -0700115bool last_unique(bool a, bool b, bool c)
swissChili6264a3b2020-07-30 19:02:07 -0700116{
117 return a == b && a != c;
118}
119
swissChilicc27cfe2020-08-08 12:57:57 -0700120void stat_cv(cpu_t *cpu, uint8_t a, uint8_t b, uint8_t c)
swissChili6264a3b2020-07-30 19:02:07 -0700121{
122 cpu->status.overflow = last_unique(a >> 7, b >> 7, c >> 7);
123 cpu->status.carry = c < a || c < b;
124}
125
swissChilicc27cfe2020-08-08 12:57:57 -0700126void cmp(cpu_t *cpu, uint8_t reg, uint8_t mem)
swissChilida4803e2020-08-06 20:06:04 -0700127{
128 cpu->status.negative = 0;
129 cpu->status.zero = 0;
130 cpu->status.carry = 0;
131 if (cpu->regs[reg] < mem)
132 {
133 cpu->status.negative = 1;
134 }
135 else if (cpu->regs[reg] == mem)
136 {
137 cpu->status.zero = 1;
138 cpu->status.carry = 1;
139 }
140 else
141 {
142 cpu->status.carry = 1;
143 }
144}
145
146void execute(cpu_t *cpu, const char *mnemonic, uint8_t op, arg_t a, uint8_t am)
swissChili6264a3b2020-07-30 19:02:07 -0700147{
148 // used to save space
149 #define REGS \
150 R(X) R(A) R(Y)
151
swissChili710d18d2020-07-29 19:43:20 -0700152 switch (op) {
swissChili6264a3b2020-07-30 19:02:07 -0700153 // Load and store instructions:
154 #define R(reg) \
155 case LD##reg: \
156 cpu->regs[reg] = a.val; \
157 stat_nz(cpu, a.val); \
158 break;
159
160 REGS
161
162 #undef R
163
164 #define R(reg) \
165 case ST##reg: \
swissChili1970cb82020-08-10 13:22:39 -0700166 cpu->mem[a.ptr] = cpu->regs[reg]; \
swissChili6264a3b2020-07-30 19:02:07 -0700167 break; \
168
169 REGS
170
171 #undef R
172
173 // Arithmetic instructions:
174 // NOTE: binary coded decimals are NOT SUPPORTED because I don't want
175 // to implement them.
176 case ADC:
177 {
178 uint8_t sum = cpu->regs[A] + a.val + cpu->status.carry;
179 // signed overflow
180 stat_cv(cpu, cpu->regs[A], a.val + cpu->status.carry, sum);
181 stat_nz(cpu, sum);
182 cpu->regs[A] = sum;
183 break;
184 }
185
186 case SBC:
187 {
188 uint8_t diff = cpu->regs[A] - a.val - !cpu->status.carry;
189 stat_cv(cpu, cpu->regs[A], a.val - !cpu->status.carry, diff);
190 stat_nz(cpu, diff);
191 cpu->regs[A] = diff;
192 break;
193 }
194
195 case INC:
swissChili1970cb82020-08-10 13:22:39 -0700196 cpu->mem[a.ptr]++;
197 stat_nz(cpu, cpu->mem[a.ptr]);
swissChili6264a3b2020-07-30 19:02:07 -0700198 break;
199
200 case INX:
201 cpu->regs[X]++;
202 stat_nz(cpu, cpu->regs[X]);
203 break;
204
205 case INY:
206 cpu->regs[Y]++;
207 stat_nz(cpu, cpu->regs[Y]);
208 break;
209
210 case DEC:
swissChili1970cb82020-08-10 13:22:39 -0700211 cpu->mem[a.ptr]--;
212 stat_nz(cpu, cpu->mem[a.ptr]);
swissChili6264a3b2020-07-30 19:02:07 -0700213 break;
swissChilida4803e2020-08-06 20:06:04 -0700214
215 case DEX:
216 cpu->regs[X]--;
217 stat_nz(cpu, cpu->regs[X]);
218 break;
219
220 case DEY:
221 cpu->regs[Y]--;
222 stat_nz(cpu, cpu->regs[Y]);
223 break;
224
225 case ASL:
226 // This check must be done here unfortunately, it would be nice
227 // to do this while decoding operands but it would require
228 // a substantial change to the architecture of the emulator
229 if (am == AM_ACC)
230 {
231 cpu->status.carry = cpu->regs[A] >> 7;
232 cpu->regs[A] <<= 1;
233 stat_nz(cpu, cpu->regs[A]);
234 }
235 else
236 {
swissChili1970cb82020-08-10 13:22:39 -0700237 cpu->status.carry = cpu->mem[a.val] >> 7;
238 cpu->mem[a.ptr] <<= 1;
239 stat_nz(cpu, cpu->mem[a.ptr]);
swissChilida4803e2020-08-06 20:06:04 -0700240 }
241 break;
242
243 case LSR:
244 if (am == AM_ACC)
245 {
246 cpu->status.carry = cpu->regs[A] & 1;
247 cpu->regs[A] >>= 1;
248 stat_nz(cpu, cpu->regs[A]);
249 }
250 else
251 {
swissChili1970cb82020-08-10 13:22:39 -0700252 cpu->status.carry = cpu->mem[a.val] & 7;
253 cpu->mem[a.ptr] >>= 1;
254 stat_nz(cpu, cpu->mem[a.ptr]);
swissChilida4803e2020-08-06 20:06:04 -0700255 }
256 break;
257
258 case ROL:
259 if (am == AM_ACC)
260 {
261 cpu->status.carry = cpu->regs[A] >> 7;
262 cpu->regs[A] = rol(cpu->regs[A], 1);
263 stat_nz(cpu, cpu->regs[A]);
264 }
265 else
266 {
swissChili1970cb82020-08-10 13:22:39 -0700267 cpu->status.carry = cpu->mem[a.val] >> 7;
268 cpu->mem[a.ptr] = rol(a.val, 1);
269 stat_nz(cpu, cpu->mem[a.ptr]);
swissChilida4803e2020-08-06 20:06:04 -0700270 }
271 break;
272
273 case ROR:
274 if (am == AM_ACC)
275 {
276 cpu->status.carry = cpu->regs[A] & 1;
277 cpu->regs[A] = ror(cpu->regs[A], 1);
278 stat_nz(cpu, cpu->regs[A]);
279 }
280 else
281 {
swissChili1970cb82020-08-10 13:22:39 -0700282 cpu->status.carry = cpu->mem[a.val] & 1;
283 cpu->mem[a.ptr] = ror(a.val, 1);
284 stat_nz(cpu, cpu->mem[a.ptr]);
swissChilida4803e2020-08-06 20:06:04 -0700285 }
286 break;
287
288 case AND:
289 cpu->regs[A] &= a.val;
290 stat_nz(cpu, cpu->regs[A]);
291 break;
292
293 case ORA:
294 cpu->regs[A] |= a.val;
295 stat_nz(cpu, cpu->regs[A]);
296 break;
297
298 case EOR:
299 cpu->regs[A] ^= a.val;
300 stat_nz(cpu, cpu->regs[A]);
301 break;
302
303 case CMP:
304 cmp(cpu, A, a.val);
305 break;
306
307 case CPX:
308 cmp(cpu, X, a.val);
309 break;
310
311 case CPY:
312 cmp(cpu, Y, a.val);
313 break;
314
315 // TODO: implement BIT here
316
317 #define BRANCHES \
318 B(BCC, carry == 0) \
319 B(BCS, carry == 1) \
320 B(BNE, zero == 0) \
321 B(BEQ, zero == 1) \
322 B(BPL, negative == 0) \
323 B(BMI, negative == 1) \
324 B(BVC, overflow == 0) \
325 B(BVS, overflow == 1)
326
327 #define B(i, c) \
328 case i: \
329 if (cpu->status . c) \
330 cpu->pc = a.ptr;\
331 break;
332
333 BRANCHES
334
335 #undef B
336 #undef BRANCHES
337
338 #define TRANSFERS \
339 T(A, X) \
340 T(X, A) \
341 T(A, Y) \
342 T(Y, A)
343
344 #define T(a, b) \
345 case T ## a ## b: \
346 cpu->regs[b] = cpu->regs[a]; \
347 stat_nz(cpu, cpu->regs[b]); \
348 break;
349
350 TRANSFERS
351
352 #undef T
353 #undef TRANSFERS
354
355 case TSX:
356 cpu->regs[X] = cpu->regs[SP];
357 stat_nz(cpu, cpu->regs[X]);
358 break;
359
360 case TXS:
361 cpu->regs[SP] = cpu->regs[X];
362 stat_nz(cpu, cpu->regs[X]);
363 break;
364
365 case PHA:
366 stack_push(cpu, cpu->regs[A]);
367 break;
368
369 case PLA:
370 cpu->regs[A] = stack_pop(cpu);
371 stat_nz(cpu, cpu->regs[A]);
372 break;
373
374 case PHP:
375 stack_push(cpu, *(uint8_t *)(&cpu->status));
376 break;
377
378 case PLP:
379 {
380 uint8_t s = stack_pop(cpu);
381 *(uint8_t *)(&cpu->status) = s;
382 }
383
384 case JMP:
385 cpu->pc = a.ptr;
386 break;
387
388 case JSR:
389 stack_pushle(cpu, cpu->pc);
swissChilib04a4022020-08-09 12:51:00 -0700390 cpu->pc = a.ptr;
swissChilida4803e2020-08-06 20:06:04 -0700391 break;
392
393 case RTS:
394 cpu->pc = stack_pople(cpu);
395 break;
396
397 // TODO: implement RTI
398 // TODO: implement flag instructions
399
400 case BRK:
401 // TODO: trigger an interrupt
402 cpu->running = false;
403 break;
404
405 case NOP:
406 break;
407
408 default:
swissChilib71e0272020-08-08 15:56:14 -0700409 warn("Unsupported opcode: %x\n", op);
410 THROW("Unsupported opcode");
swissChili710d18d2020-07-29 19:43:20 -0700411 }
swissChili6264a3b2020-07-30 19:02:07 -0700412 #undef REGS
swissChili6c61a792020-07-28 16:29:20 -0700413}
414
swissChili1970cb82020-08-10 13:22:39 -0700415uint16_t fetch_le(cpu_t *cpu, uint16_t *pc)
swissChili6c61a792020-07-28 16:29:20 -0700416{
swissChili1970cb82020-08-10 13:22:39 -0700417 uint8_t a = cpu->mem[(*pc)++];
418 uint8_t b = cpu->mem[(*pc)++];
swissChili6c61a792020-07-28 16:29:20 -0700419 return le_to_native(a, b);
420}
421
swissChilicc27cfe2020-08-08 12:57:57 -0700422arg_t arg_imm(uint16_t a)
swissChili710d18d2020-07-29 19:43:20 -0700423{
424 return (arg_t){ a, a };
425}
426
swissChilicc27cfe2020-08-08 12:57:57 -0700427arg_t arg_ptr(cpu_t *c, uint flags, uint16_t p)
swissChili710d18d2020-07-29 19:43:20 -0700428{
429 if (flags & FETCH_NO_INDIRECTION)
430 return arg_imm(p);
431
432 return (arg_t){ c->mem[p], p };
433}
434
swissChilicc27cfe2020-08-08 12:57:57 -0700435arg_t arg(uint16_t v, uint16_t a)
swissChili710d18d2020-07-29 19:43:20 -0700436{
437 return (arg_t){ v, a };
438}
439
swissChili1970cb82020-08-10 13:22:39 -0700440arg_t fetch_addr(cpu_t *cpu, uint8_t am, uint f, uint16_t *pc)
swissChili6c61a792020-07-28 16:29:20 -0700441{
442 switch (am)
443 {
444 case AM_ACC:
445 case AM_IMP:
swissChili710d18d2020-07-29 19:43:20 -0700446 return arg_imm(0);
swissChili6c61a792020-07-28 16:29:20 -0700447
448 // In both cases return immediate 8 bit value
449 case AM_IMM:
450 case AM_ZP:
swissChili1970cb82020-08-10 13:22:39 -0700451 return arg_imm(cpu->mem[(*pc)++]);
swissChili6c61a792020-07-28 16:29:20 -0700452
453 case AM_ABS:
swissChili1970cb82020-08-10 13:22:39 -0700454 return arg_ptr(cpu, f, fetch_le(cpu, pc));
swissChili6c61a792020-07-28 16:29:20 -0700455
456 case AM_REL:
457 {
swissChili1970cb82020-08-10 13:22:39 -0700458 uint16_t pc_hi = * pc + 1;
459 return arg_ptr(cpu, f, (int8_t)cpu->mem[(*pc)++] + pc_hi);
swissChili6c61a792020-07-28 16:29:20 -0700460 }
461
462 case AM_IND:
463 {
swissChili1970cb82020-08-10 13:22:39 -0700464 uint16_t addr = fetch_le(cpu, pc);
swissChili6264a3b2020-07-30 19:02:07 -0700465
466 if (f & FETCH_NO_INDIRECTION)
467 return arg_imm(addr);
468
swissChili1970cb82020-08-10 13:22:39 -0700469 uint8_t low = cpu->mem[addr],
470 high = cpu->mem[addr + 1];
swissChili6c61a792020-07-28 16:29:20 -0700471
swissChili710d18d2020-07-29 19:43:20 -0700472 return arg_ptr(cpu, f, le_to_native(low, high));
swissChili6c61a792020-07-28 16:29:20 -0700473 }
474
475 case AM_AX:
swissChili94ba1f52020-08-08 11:39:10 -0700476 if (f & FETCH_NO_INDIRECTION)
swissChili1970cb82020-08-10 13:22:39 -0700477 return arg_ptr(cpu, f, fetch_le(cpu, pc));
swissChili94ba1f52020-08-08 11:39:10 -0700478
swissChili1970cb82020-08-10 13:22:39 -0700479 return arg_ptr(cpu, f, fetch_le(cpu, pc) + cpu->regs[X]);
swissChili6c61a792020-07-28 16:29:20 -0700480
481 case AM_AY:
swissChili94ba1f52020-08-08 11:39:10 -0700482 if (f & FETCH_NO_INDIRECTION)
swissChili1970cb82020-08-10 13:22:39 -0700483 return arg_ptr(cpu, f, fetch_le(cpu, pc));
swissChili94ba1f52020-08-08 11:39:10 -0700484
swissChili1970cb82020-08-10 13:22:39 -0700485 return arg_ptr(cpu, f, fetch_le(cpu, pc) + cpu->regs[Y]);
swissChili6c61a792020-07-28 16:29:20 -0700486
487 case AM_ZPX:
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[X]);
swissChili6c61a792020-07-28 16:29:20 -0700491
492 case AM_ZPY:
swissChili94ba1f52020-08-08 11:39:10 -0700493 if (f & FETCH_NO_INDIRECTION)
swissChili1970cb82020-08-10 13:22:39 -0700494 return arg_ptr(cpu, f, cpu->mem[(*pc)++]);
495 return arg_ptr(cpu, f, cpu->mem[(*pc)++] + cpu->regs[Y]);
swissChili6c61a792020-07-28 16:29:20 -0700496
497 case AM_ZIX:
498 {
swissChili1970cb82020-08-10 13:22:39 -0700499 uint8_t zp = cpu->mem[(*pc)++];
swissChili6264a3b2020-07-30 19:02:07 -0700500
501 if (f & FETCH_NO_INDIRECTION)
502 return arg_imm(zp);
503
swissChili710d18d2020-07-29 19:43:20 -0700504 uint16_t addr = zp + cpu->regs[X];
swissChilib71e0272020-08-08 15:56:14 -0700505 uint16_t indirect = le_to_native(cpu->mem[addr], cpu->mem[addr + 1]);
swissChili710d18d2020-07-29 19:43:20 -0700506 return arg_ptr(cpu, f, indirect);
swissChili6c61a792020-07-28 16:29:20 -0700507 }
508
509 case AM_ZIY:
510 {
swissChili1970cb82020-08-10 13:22:39 -0700511 uint8_t zp = cpu->mem[(*pc)++];
swissChili6264a3b2020-07-30 19:02:07 -0700512
513 if (f & FETCH_NO_INDIRECTION)
514 return arg_imm(zp);
515
swissChili1970cb82020-08-10 13:22:39 -0700516 uint16_t base = le_to_native(cpu->mem[zp], cpu->mem[zp + 1]);
swissChili710d18d2020-07-29 19:43:20 -0700517 return arg_ptr(cpu, f, base + cpu->regs[Y]);
swissChili6c61a792020-07-28 16:29:20 -0700518 }
519
520 default:
swissChilib71e0272020-08-08 15:56:14 -0700521 warn("Unknown address mode %x", am);
522 THROW("Unknowng address mode");
swissChili710d18d2020-07-29 19:43:20 -0700523 __builtin_unreachable();
swissChili6c61a792020-07-28 16:29:20 -0700524 }
525}
526
swissChilicc27cfe2020-08-08 12:57:57 -0700527void step(cpu_t *cpu)
swissChili6c61a792020-07-28 16:29:20 -0700528{
swissChilicc27cfe2020-08-08 12:57:57 -0700529 cpu->screen_dirty = false;
swissChilib71e0272020-08-08 15:56:14 -0700530 uint8_t pc = cpu->pc;
531 uint8_t op = cpu->mem[cpu->pc++];
532 switch (op)
swissChili6c61a792020-07-28 16:29:20 -0700533 {
swissChili97b5d8b2020-08-15 20:00:54 -0700534#define INST(mn, am, op, len) \
swissChili6c61a792020-07-28 16:29:20 -0700535 case op: \
swissChili1970cb82020-08-10 13:22:39 -0700536 execute(cpu, #mn, mn, fetch_addr(cpu, am, 0, &cpu->pc), am); \
swissChili6c61a792020-07-28 16:29:20 -0700537 break;
538
539 INSTRUCTIONS
540
541#undef INST
542
543 default:
swissChilib71e0272020-08-08 15:56:14 -0700544 warn("Undefined opcode %x near %x [%x]", op, pc, cpu->mem[pc]);
545 THROW("Undefined opcode");
swissChili6c61a792020-07-28 16:29:20 -0700546 }
547}
548
swissChilic51e9222020-08-07 16:09:14 -0700549int dump_inst(cpu_t *cpu, char *buf, const char *mn, uint16_t addr, uint8_t am)
swissChili6c61a792020-07-28 16:29:20 -0700550{
swissChilic51e9222020-08-07 16:09:14 -0700551 char *end = buf;
552 end += sprintf(end, "%s ", mn);
swissChili6c61a792020-07-28 16:29:20 -0700553
554 switch (am)
555 {
556 case AM_IMM:
swissChilic51e9222020-08-07 16:09:14 -0700557 end += sprintf(end, "#");
swissChili6c61a792020-07-28 16:29:20 -0700558 case AM_REL:
559 case AM_ABS:
560 case AM_ZP:
swissChilic51e9222020-08-07 16:09:14 -0700561 end += sprintf(end, "$%x", addr);
swissChili6c61a792020-07-28 16:29:20 -0700562 break;
563
564 case AM_IND:
swissChilic51e9222020-08-07 16:09:14 -0700565 end += sprintf(end, "($%x)", addr);
swissChili6c61a792020-07-28 16:29:20 -0700566 break;
567
568 case AM_AX:
569 case AM_ZPX:
swissChilic51e9222020-08-07 16:09:14 -0700570 end += sprintf(end, "$%x, X", addr);
swissChili6c61a792020-07-28 16:29:20 -0700571 break;
572
573 case AM_AY:
574 case AM_ZPY:
swissChilic51e9222020-08-07 16:09:14 -0700575 end += sprintf(end, "$%x, Y", addr);
swissChili6c61a792020-07-28 16:29:20 -0700576 break;
577
578 case AM_ZIX:
swissChilic51e9222020-08-07 16:09:14 -0700579 end += sprintf(end, "($%x, X)", addr);
swissChili6c61a792020-07-28 16:29:20 -0700580 break;
581
582 case AM_ZIY:
swissChilic51e9222020-08-07 16:09:14 -0700583 end += sprintf(end, "($%x), Y", addr);
swissChili6c61a792020-07-28 16:29:20 -0700584 break;
585 }
586
swissChilic51e9222020-08-07 16:09:14 -0700587 return end - buf;
swissChili6c61a792020-07-28 16:29:20 -0700588}
589
swissChili1970cb82020-08-10 13:22:39 -0700590char *disas_step(cpu_t *cpu, uint16_t *pc)
swissChili6c61a792020-07-28 16:29:20 -0700591{
swissChilic51e9222020-08-07 16:09:14 -0700592 char *buffer = malloc(80);
593 char *end = buffer;
594
595 // end += sprintf(buffer, "$%x", cpu->pc);
swissChili1970cb82020-08-10 13:22:39 -0700596 uint8_t op = cpu->mem[(*pc)++];
swissChili6c61a792020-07-28 16:29:20 -0700597 switch (op)
598 {
swissChili97b5d8b2020-08-15 20:00:54 -0700599#define INST(mn, am, op, len) \
swissChili6c61a792020-07-28 16:29:20 -0700600 case op: \
swissChilic51e9222020-08-07 16:09:14 -0700601 end += dump_inst(cpu, end, #mn, \
swissChili1970cb82020-08-10 13:22:39 -0700602 fetch_addr(cpu, am, FETCH_NO_INDIRECTION, pc).ptr, am); \
swissChili6c61a792020-07-28 16:29:20 -0700603 break;
604
605 INSTRUCTIONS
606
607#undef INST
608
609 default:
swissChilic51e9222020-08-07 16:09:14 -0700610 end += sprintf(end, "Undefined opcode %x", op);
swissChili6c61a792020-07-28 16:29:20 -0700611 }
swissChilic51e9222020-08-07 16:09:14 -0700612
613 *end = 0;
614
615 return buffer;
swissChili6c61a792020-07-28 16:29:20 -0700616}
617
swissChilida4803e2020-08-06 20:06:04 -0700618void disas_num(cpu_t *cpu, uint16_t num)
619{
swissChili1970cb82020-08-10 13:22:39 -0700620 uint16_t pc = 0x600;
swissChilida4803e2020-08-06 20:06:04 -0700621 for (int i = 0; i < num; i++)
622 {
swissChili1970cb82020-08-10 13:22:39 -0700623 uint16_t last_pc = pc;
624 char *line = disas_step(cpu, &pc);
swissChilic51e9222020-08-07 16:09:14 -0700625 printf("$%x\t%s\n", last_pc, line);
626 free(line);
swissChilida4803e2020-08-06 20:06:04 -0700627 }
628}
629
swissChili6c61a792020-07-28 16:29:20 -0700630void disas(cpu_t *cpu)
631{
swissChili1970cb82020-08-10 13:22:39 -0700632 uint16_t pc = 0x600;
swissChili6264a3b2020-07-30 19:02:07 -0700633 // Raw binary, no way to know what's code what isn't
swissChili6c61a792020-07-28 16:29:20 -0700634 while (cpu->pc < 0xFFFF)
635 {
swissChili1970cb82020-08-10 13:22:39 -0700636 uint16_t last_pc = pc;
637 char *line = disas_step(cpu, &pc);
swissChilic51e9222020-08-07 16:09:14 -0700638 printf("$%x\t%s\n", last_pc, line);
639 free(line);
swissChili6c61a792020-07-28 16:29:20 -0700640 }
641}
swissChilic51e9222020-08-07 16:09:14 -0700642
swissChilida4803e2020-08-06 20:06:04 -0700643void run(cpu_t *cpu)
644{
645 while (cpu->running)
646 {
647 step(cpu);
648 }
649
650 printf("CPU Halted\n");
651}
swissChilic6b4f7e2020-08-09 16:36:36 -0700652
653void run_mq(cpu_t *cpu, mqd_t mq)
654{
655 char buf[MQ_BUF_LEN];
656 bool running;
657
658 while (true)
659 {
660 if (running)
661 {
662 if (cpu->running)
663 step(cpu);
664 else
665 running = false;
666 }
667
668 ssize_t recvd = mq_receive(mq, buf, MQ_BUF_LEN * 2, NULL);
669
670 if (recvd == -1 && errno != EAGAIN)
671 {
672 printf("errno = %d\n", errno);
673 THROW("mq_receive returned -1");
674 }
675
676 if (recvd > 0)
677 {
678 if (debug_stmt(cpu, buf, &running))
679 break;
680 }
681 }
682}