PancakeNESEmu
A homebrewed NES Emulator written in C
Loading...
Searching...
No Matches
cpu.h
Go to the documentation of this file.
1#ifndef cpu_h
2#define cpu_h
3
4#include "core/mem.h"
5#include "core/types.h"
6#include "macros.h"
7
41
48void init_cpu(CPU* cpu, memory mem);
49
54void reset(CPU* processor);
55
60void free_cpu(CPU* cpu);
61
66void start_cpu(CPU* cpu);
67
74
80unsigned char get_next_instruction(CPU* cpu);
81
88
93void print_cpu_state(CPU* processor);
94
99void print_stack_state(CPU* cpu);
100
106void print_stack_expected(memory stack, data start);
107
117void print_cpu_expected(data acc, data x, data y, data flags, address pc, data sp);
118
119#define GET_C_FLAG(x) (x->flags & BIT_0_MASK)
120#define GET_Z_FLAG(x) (x->flags & BIT_1_MASK)
121#define GET_I_FLAG(x) (x->flags & BIT_2_MASK)
122#define GET_D_FLAG(x) (x->flags & BIT_3_MASK)
123#define GET_B_FLAG(x) (x->flags & BIT_4_MASK)
124#define GET_P_FLAG(x) (x->flags & BIT_5_MASK)
125#define GET_V_FLAG(x) (x->flags & BIT_6_MASK)
126#define GET_N_FLAG(x) (x->flags & BIT_7_MASK)
127
128#define SET_C_FLAG(x) (x->flags = x->flags | BIT_0_MASK)
129#define SET_Z_FLAG(x) (x->flags = x->flags | BIT_1_MASK)
130#define SET_I_FLAG(x) (x->flags = x->flags | BIT_2_MASK)
131#define SET_D_FLAG(x) (x->flags = x->flags | BIT_3_MASK)
132#define SET_B_FLAG(x) (x->flags = x->flags | BIT_4_MASK)
133#define SET_P_FLAG(x) (x->flags = x->flags | BIT_5_MASK)
134#define SET_V_FLAG(x) (x->flags = x->flags | BIT_6_MASK)
135#define SET_N_FLAG(x) (x->flags = x->flags | BIT_7_MASK)
136
137#define SET_ALL_FLAGS(x) (x->flags = x->flags | 0xFF)
138
139#define CLEAR_C_FLAG(x) (x->flags = x->flags & NBIT_0_MASK)
140#define CLEAR_Z_FLAG(x) (x->flags = x->flags & NBIT_1_MASK)
141#define CLEAR_I_FLAG(x) (x->flags = x->flags & NBIT_2_MASK)
142#define CLEAR_D_FLAG(x) (x->flags = x->flags & NBIT_3_MASK)
143#define CLEAR_B_FLAG(x) (x->flags = x->flags & NBIT_4_MASK)
144#define CLEAR_P_FLAG(x) (x->flags = x->flags & NBIT_5_MASK)
145#define CLEAR_V_FLAG(x) (x->flags = x->flags & NBIT_6_MASK)
146#define CLEAR_N_FLAG(x) (x->flags = x->flags & NBIT_7_MASK)
147
148#define CLEAR_ALL_FLAGS(x) (x->flags = x->flags & 0x00)
149
156#define indexed_indirect(cpu, addr, offset) \
157 cpu->mem[(cpu->mem[(addr + offset) & 0xFF]) | (cpu->mem[(addr + offset + 1) & 0xFF] << 8)]
158
165#define indirect_indexed(cpu, addr, offset) \
166 cpu->mem[(cpu->mem[(addr) & 0xFF] | cpu->mem[(addr + 1) & 0xFF] << 8) + offset]
167
173#define indirect(cpu, addr) cpu->mem[((cpu->mem[(addr)]) | (cpu->mem[(addr) + 1] << 8))]
174
180#define get_address(cpu) \
181 (cpu->mem[cpu->program_counter + 1] | (cpu->mem[cpu->program_counter + 2] << 8))
182
189#define is_page_crossed(addr, offset) ((addr & 0x00ff) && !((addr + offset) & 0x00ff))
190
196#define LD_FLAGS_GENERIC(cpu, reg) \
197 ({ \
198 CLEAR_C_FLAG(cpu); \
199 if (cpu->reg == 0) { \
200 SET_Z_FLAG(cpu); \
201 CLEAR_N_FLAG(cpu); \
202 } else if (cpu->reg & BIT_7_MASK) { \
203 SET_N_FLAG(cpu); \
204 CLEAR_Z_FLAG(cpu); \
205 } else { \
206 CLEAR_N_FLAG(cpu); \
207 CLEAR_Z_FLAG(cpu); \
208 } \
209 })
210
217#define LD_immediate_GENERIC(cpu, reg, d) \
218 ({ \
219 CLEAR_C_FLAG(cpu); \
220 if ((d) == 0) { \
221 SET_Z_FLAG(cpu); \
222 CLEAR_N_FLAG(cpu); \
223 } else if ((d) & BIT_7_MASK) { \
224 CLEAR_Z_FLAG(cpu); \
225 SET_N_FLAG(cpu); \
226 } else { \
227 CLEAR_Z_FLAG(cpu); \
228 CLEAR_N_FLAG(cpu); \
229 } \
230 cpu->reg = (d); \
231 })
237#define LD_immediate_ACC(processor, d) (LD_immediate_GENERIC(processor, accumulator, d))
238
244#define LD_immediate_X(processor, d) (LD_immediate_GENERIC(processor, register_x, d))
245
251#define LD_immediate_Y(processor, d) (LD_immediate_GENERIC(processor, register_y, d))
252
260#define LD_offset_GENERIC(cpu, reg, addr, offset) \
261 LD_immediate_GENERIC(cpu, reg, cpu->mem[addr + offset])
262
269#define LD_offset_ACC(processor, addr, offset) \
270 (LD_offset_GENERIC(processor, accumulator, addr, offset))
271
278#define LD_offset_X(processor, addr, offset) \
279 (LD_offset_GENERIC(processor, register_x, addr, offset))
280
287#define LD_offset_Y(processor, addr, offset) \
288 (LD_offset_GENERIC(processor, register_y, addr, offset))
289
296#define LD_absolute_GENERIC(cpu, reg, addr) LD_immediate_GENERIC(cpu, reg, cpu->mem[addr])
297
303#define LD_absolute_ACC(processor, addr) (LD_absolute_GENERIC(processor, accumulator, addr))
304
310#define LD_absolute_X(processor, addr) (LD_absolute_GENERIC(processor, register_x, addr))
311
317#define LD_absolute_Y(processor, addr) (LD_absolute_GENERIC(processor, register_y, addr))
318
325#define LD_indirect_GENERIC(cpu, reg, addr) (LD_immediate_GENERIC(cpu, reg, indirect(cpu, addr)))
326
333#define LD_indirect_ACC(processor, addr) LD_indirect_GENERIC(processor, accumulator, addr)
334
341#define LD_indirect_X(processor, addr) LD_indirect_GENERIC(processor, register_x, addr)
342
349#define LD_indirect_Y(processor, addr) LD_indirect_GENERIC(processor, register_y, addr)
350
357#define DECINC_GENERIC(cpu, reg, op) \
358 ({ \
359 op cpu->reg; \
360 if (cpu->reg == 0) { \
361 SET_Z_FLAG(cpu); \
362 CLEAR_N_FLAG(cpu); \
363 } else if (cpu->reg & BIT_7_MASK) { \
364 SET_N_FLAG(cpu); \
365 CLEAR_Z_FLAG(cpu); \
366 } else { \
367 CLEAR_N_FLAG(cpu); \
368 CLEAR_Z_FLAG(cpu); \
369 } \
370 })
371
377#define DEC_absolute(processor, addr) DECINC_GENERIC(processor, mem[addr], --)
378
384#define INC_absolute(processor, addr) DECINC_GENERIC(processor, mem[addr], ++)
385
392#define DEC_offset(processor, addr, offset) DECINC_GENERIC(processor, mem[addr + offset], --)
393
400#define INC_offset(processor, addr, offset) DECINC_GENERIC(processor, mem[addr + offset], ++)
401
406#define INC_X(processor) DECINC_GENERIC(processor, register_x, ++)
407
412#define INC_Y(processor) DECINC_GENERIC(processor, register_y, ++)
413
418#define DEC_X(processor) DECINC_GENERIC(processor, register_x, --)
419
424#define DEC_Y(processor) DECINC_GENERIC(processor, register_y, --)
425
432#define LD_indexed_indirect_ACC(processor, addr, offset) \
433 (LD_immediate_GENERIC(processor, accumulator, indexed_indirect(processor, addr, offset)))
434
441#define LD_indirect_indexed_ACC(processor, addr, offset) \
442 (LD_immediate_GENERIC(processor, accumulator, indirect_indexed(processor, addr, offset)))
443
450#define STR_absolute_GENERIC(cpu, reg, addr) ({ cpu->mem[addr] = cpu->reg; })
451
457#define STR_absolute_ACC(processor, addr) STR_absolute_GENERIC(processor, accumulator, addr)
458
464#define STR_absolute_X(processor, addr) STR_absolute_GENERIC(processor, register_x, addr)
465
471#define STR_absolute_Y(processor, addr) STR_absolute_GENERIC(processor, register_y, addr)
472
480#define STR_offset_GENERIC(cpu, reg, addr, offset) STR_absolute_GENERIC(cpu, reg, addr + offset)
481
488#define STR_offset_ACC(processor, addr, offset) \
489 STR_offset_GENERIC(processor, accumulator, addr, offset)
490
497#define STR_offset_X(processor, addr, offset) \
498 STR_offset_GENERIC(processor, register_x, addr, offset)
499
506#define STR_offset_Y(processor, addr, offset) \
507 STR_offset_GENERIC(processor, register_y, addr, offset)
508
516#define STR_indirect_indexed_ACC(processor, addr, offset) \
517 ({ indirect_indexed(processor, addr, offset) = processor->accumulator; })
518
526#define STR_indexed_indirect_ACC(processor, addr, offset) \
527 ({ indexed_indirect(processor, addr, offset) = processor->accumulator; })
528
535#define TR_GENERIC(cpu, reg1, reg2) \
536 ({ \
537 cpu->reg2 = cpu->reg1; \
538 LD_FLAGS_GENERIC(cpu, reg2); \
539 })
540
545#define TR_ACC_X(processor) TR_GENERIC(processor, accumulator, register_x)
546
551#define TR_ACC_Y(processor) TR_GENERIC(processor, accumulator, register_y)
552
557#define TR_X_ACC(processor) TR_GENERIC(processor, register_x, accumulator)
558
563#define TR_Y_ACC(processor) TR_GENERIC(processor, register_y, accumulator)
564
569#define TR_SP_X(processor) TR_GENERIC(processor, stack_pointer, register_x)
570
575#define TR_X_SP(processor) TR_GENERIC(processor, register_x, stack_pointer)
576
582#define PUSH_GENERIC(cpu, reg) \
583 ({ \
584 cpu->mem[STACK_END | cpu->stack_pointer] = cpu->reg; \
585 --(cpu->stack_pointer); \
586 })
587
593#define PUSH_immediate(cpu, d) \
594 ({ \
595 cpu->mem[STACK_END | cpu->stack_pointer] = d; \
596 --(cpu->stack_pointer); \
597 })
598
603#define PUSH_ACC(processor) PUSH_GENERIC(processor, accumulator)
604
609#define PUSH_FLAGS(processor) PUSH_GENERIC(processor, flags)
610
615#define PUSH_PC(processor) \
616 ({ \
617 PUSH_immediate(processor, GET_HIGHER(processor->program_counter)); \
618 PUSH_immediate(processor, GET_LOWER(processor->program_counter)); \
619 })
620
626#define PULL_GENERIC(cpu, reg) \
627 ({ \
628 ++(cpu->stack_pointer); \
629 cpu->reg = cpu->mem[0x1100 | cpu->stack_pointer]; \
630 })
631
636#define PULL_ACC(processor) PULL_GENERIC(processor, accumulator)
637
642#define PULL_FLAGS(processor) PULL_GENERIC(processor, flags)
643
648#define PULL_PC(processor) \
649 ({ \
650 ++(processor->stack_pointer); \
651 processor->program_counter = ((processor->mem[STACK_END | processor->stack_pointer])); \
652 ++(processor->stack_pointer); \
653 processor->program_counter = (processor->program_counter & 0x00ff) | \
654 (processor->mem[STACK_END | processor->stack_pointer] << 8); \
655 })
656
662#define ADD_immediate(processor, data) \
663 ({ \
664 processor->cache = (processor->accumulator); \
665 processor->accumulator += (data + GET_C_FLAG(processor)); \
666 if ((processor->cache & BIT_7_MASK) != (processor->accumulator & BIT_7_MASK)) { \
667 SET_V_FLAG(processor); \
668 SET_C_FLAG(processor); \
669 CLEAR_N_FLAG(processor); \
670 SET_Z_FLAG(processor); \
671 } else if (processor->accumulator & BIT_7_MASK) { \
672 CLEAR_V_FLAG(processor); \
673 SET_N_FLAG(processor); \
674 CLEAR_Z_FLAG(processor); \
675 } else if (processor->accumulator == 0) { \
676 SET_Z_FLAG(processor); \
677 CLEAR_V_FLAG(processor); \
678 CLEAR_N_FLAG(processor); \
679 } else { \
680 CLEAR_V_FLAG(processor); \
681 CLEAR_N_FLAG(processor); \
682 CLEAR_Z_FLAG(processor); \
683 } \
684 })
685
692#define ADD_absolute(processor, addr) ADD_immediate(processor, processor->mem[addr])
693
701#define ADD_offset(processor, addr, offset) ADD_immediate(processor, processor->mem[addr + offset])
702
710#define ADD_indexed_indirect(processor, addr, offset) \
711 ADD_immediate(processor, indexed_indirect(processor, addr, offset))
712
719#define ADD_indirect_indexed(processor, addr, offset) \
720 ADD_immediate(processor, indirect_indexed(processor, addr, offset))
721
726#define LOGICAL_FLAGS(processor) \
727 ({ \
728 if (processor->accumulator & BIT_7_MASK) { \
729 CLEAR_ALL_FLAGS(processor); \
730 SET_N_FLAG(processor); \
731 } else if (processor->accumulator == 0) { \
732 CLEAR_ALL_FLAGS(processor); \
733 SET_Z_FLAG(processor); \
734 } else { \
735 CLEAR_ALL_FLAGS(processor); \
736 } \
737 })
738
744#define AND_immediate(processor, data) \
745 ({ \
746 processor->accumulator &= data; \
747 LOGICAL_FLAGS(processor); \
748 })
749
755#define AND_absolute(processor, addr) AND_immediate(processor, processor->mem[addr])
756
763#define AND_offset(processor, addr, offset) AND_immediate(processor, processor->mem[addr + offset])
764
772#define AND_indexed_indirect(processor, addr, offset) \
773 AND_immediate(processor, indexed_indirect(processor, addr, offset))
774
781#define AND_indirect_indexed(processor, addr, offset) \
782 AND_immediate(processor, indirect_indexed(processor, addr, offset))
783
789#define OR_immediate(processor, data) \
790 ({ \
791 processor->accumulator |= data; \
792 LOGICAL_FLAGS(processor); \
793 })
794
800#define OR_absolute(processor, addr) OR_immediate(processor, processor->mem[addr])
801
808#define OR_offset(processor, addr, offset) OR_immediate(processor, processor->mem[addr + offset])
809
817#define OR_indexed_indirect(processor, addr, offset) \
818 OR_immediate(processor, indexed_indirect(processor, addr, offset))
819
826#define OR_indirect_indexed(processor, addr, offset) \
827 OR_immediate(processor, indirect_indexed(processor, addr, offset))
828
834#define XOR_immediate(processor, data) \
835 ({ \
836 processor->accumulator ^= data; \
837 LOGICAL_FLAGS(processor); \
838 })
839
845#define XOR_absolute(processor, addr) XOR_immediate(processor, processor->mem[addr])
846
853#define XOR_offset(processor, addr, offset) XOR_immediate(processor, processor->mem[addr + offset])
854
862#define XOR_indexed_indirect(processor, addr, offset) \
863 XOR_immediate(processor, indexed_indirect(processor, addr, offset))
864
871#define XOR_indirect_indexed(processor, addr, offset) \
872 XOR_immediate(processor, indirect_indexed(processor, addr, offset))
873
880#define SBC_immediate(processor, data) \
881 ({ \
882 processor->cache = (processor->accumulator); \
883 processor->accumulator -= (data + GET_C_FLAG(processor)); \
884 if ((processor->cache & BIT_7_MASK) != (processor->accumulator & BIT_7_MASK)) { \
885 SET_V_FLAG(processor); \
886 CLEAR_C_FLAG(processor); \
887 CLEAR_Z_FLAG(processor); \
888 SET_N_FLAG(processor); \
889 } else if (processor->accumulator & BIT_7_MASK) { \
890 CLEAR_V_FLAG(processor); \
891 SET_N_FLAG(processor); \
892 CLEAR_Z_FLAG(processor); \
893 } else if (processor->accumulator == 0) { \
894 SET_Z_FLAG(processor); \
895 CLEAR_V_FLAG(processor); \
896 CLEAR_N_FLAG(processor); \
897 } else { \
898 CLEAR_V_FLAG(processor); \
899 CLEAR_N_FLAG(processor); \
900 CLEAR_Z_FLAG(processor); \
901 } \
902 })
903
910#define SBC_absolute(processor, addr) SBC_immediate(processor, processor->mem[addr])
911
919#define SBC_offset(processor, addr, offset) SBC_immediate(processor, processor->mem[addr + offset])
920
928#define SBC_indexed_indirect(processor, addr, offset) \
929 SBC_immediate(processor, indexed_indirect(processor, addr, offset))
930
938#define SBC_indirect_indexed(processor, addr, offset) \
939 SBC_immediate(processor, indirect_indexed(processor, addr, offset))
940
944#define NO_OPERATION()
945
951#define BIT_TEST(processor, addr) \
952 ({ \
953 processor->cache = processor->accumulator & processor->mem[addr]; \
954 if (processor->cache == 0) { \
955 SET_Z_FLAG(processor); \
956 } else { \
957 CLEAR_Z_FLAG(processor); \
958 if (processor->cache & BIT_7_MASK) { \
959 SET_N_FLAG(processor); \
960 } \
961 if (processor->cache & BIT_6_MASK) { \
962 SET_V_FLAG(processor); \
963 } \
964 } \
965 })
966
973#define BRANCH_GENERIC_S(processor, flag_mask, offset) \
974 ({ \
975 if (processor->flags & flag_mask) { \
976 processor->program_counter += (signed char)(offset); \
977 } \
978 })
985#define BRANCH_GENERIC_C(processor, flag_mask, offset) \
986 ({ \
987 if (!(processor->flags & flag_mask)) { \
988 processor->program_counter += (signed char)(offset); \
989 } \
990 })
991
997#define BRANCH_If_Positive(processor, offset) BRANCH_GENERIC_C(processor, BIT_7_MASK, offset)
998
1004#define BRANCH_Overflow_C(processor, offset) BRANCH_GENERIC_C(processor, BIT_6_MASK, offset)
1005
1011#define BRANCH_Not_Equal(processor, offset) BRANCH_GENERIC_C(processor, BIT_1_MASK, offset)
1012
1018#define BRANCH_Carry_C(processor, offset) BRANCH_GENERIC_C(processor, BIT_0_MASK, offset)
1019
1025#define BRANCH_If_Minus(processor, offset) BRANCH_GENERIC_S(processor, BIT_7_MASK, offset)
1026
1032#define BRANCH_Overflow_S(processor, offset) BRANCH_GENERIC_S(processor, BIT_6_MASK, offset)
1033
1039#define BRANCH_Equal(processor, offset) BRANCH_GENERIC_S(processor, BIT_1_MASK, offset)
1040
1046#define BRANCH_Carry_S(processor, offset) BRANCH_GENERIC_S(processor, BIT_0_MASK, offset)
1047
1057#define SHIFT_GENERIC(processor, field, operator, flag_shift_offset, flag_mask) \
1058 ({ \
1059 CLEAR_C_FLAG(processor); \
1060 processor->flags |= ((processor->field & flag_mask) >> (flag_shift_offset)); \
1061 processor->field = processor->field operator(1); \
1062 if (processor->field == 0) { \
1063 SET_Z_FLAG(processor); \
1064 CLEAR_N_FLAG(processor); \
1065 } else if (processor->field & BIT_7_MASK) { \
1066 SET_N_FLAG(processor); \
1067 CLEAR_Z_FLAG(processor); \
1068 } \
1069 })
1070
1076#define SHIFT_LEFT_ACC(processor) SHIFT_GENERIC(processor, accumulator, <<, 7, BIT_7_MASK)
1077
1083#define SHIFT_RIGHT_ACC(processor) SHIFT_GENERIC(processor, accumulator, >>, 0, BIT_0_MASK)
1084
1091#define SHIFT_LEFT_absolute(processor, addr) SHIFT_GENERIC(processor, mem[addr], <<, 7, BIT_7_MASK)
1098#define SHIFT_RIGHT_absolute(processor, addr) SHIFT_GENERIC(processor, mem[addr], >>, 0, BIT_0_MASK)
1099
1107#define SHIFT_LEFT_offset(processor, addr, offset) SHIFT_LEFT_absolute(processor, addr + offset)
1108
1116#define SHIFT_RIGHT_offset(processor, addr, offset) SHIFT_RIGHT_absolute(processor, addr + offset)
1117
1128#define ROTATION_GENERIC(processor, field, operator, store_offset, pop_offset, flag_mask) \
1129 ({ \
1130 processor->cache = ((processor->field & flag_mask) >> (store_offset)); \
1131 processor->field = (processor->field operator(1)) | (GET_C_FLAG(processor) << pop_offset); \
1132 CLEAR_C_FLAG(processor); \
1133 processor->flags |= processor->cache; \
1134 if (processor->field == 0) { \
1135 SET_Z_FLAG(processor); \
1136 CLEAR_N_FLAG(processor); \
1137 } else if (processor->field & BIT_7_MASK) { \
1138 SET_N_FLAG(processor); \
1139 CLEAR_Z_FLAG(processor); \
1140 } \
1141 })
1142
1149#define ROTATION_LEFT_ACC(processor) ROTATION_GENERIC(processor, accumulator, <<, 7, 0, BIT_7_MASK)
1150
1157#define ROTATION_RIGHT_ACC(processor) ROTATION_GENERIC(processor, accumulator, >>, 0, 7, BIT_0_MASK)
1158
1166#define ROTATION_LEFT_absolute(processor, addr) \
1167 ROTATION_GENERIC(processor, mem[addr], <<, 7, 0, BIT_7_MASK)
1168
1176#define ROTATION_RIGHT_absolute(processor, addr) \
1177 ROTATION_GENERIC(processor, mem[addr], >>, 0, 7, BIT_0_MASK)
1178
1187#define ROTATION_LEFT_offset(processor, addr, offset) \
1188 ROTATION_LEFT_absolute(processor, addr + offset)
1189
1198#define ROTATION_RIGHT_offset(processor, addr, offset) \
1199 ROTATION_RIGHT_absolute(processor, addr + offset)
1200
1206#define JUMP_absolute(processor, addr) processor->program_counter = addr
1207
1213#define JUMP_indirect(processor, addr) \
1214 JUMP_absolute(processor, ((cpu->mem[(addr)]) | (cpu->mem[(addr) + 1] << 8)))
1215
1221#define GENERIC_IR(processor, vector_start) \
1222 ({ \
1223 PUSH_PC(processor); \
1224 PUSH_FLAGS(processor); \
1225 JUMP_indirect(processor, vector_start); \
1226 })
1227
1232#define BREAK(processor) \
1233 ({ \
1234 GENERIC_IR(processor, 0xfffe); \
1235 SET_B_FLAG(processor); \
1236 })
1237
1242#define IRQ(processor) \
1243 ({ \
1244 GENERIC_IR(processor, 0xfffe); \
1245 CLEAR_B_FLAG(processor); \
1246 })
1247
1252#define NMI(processor) \
1253 ({ \
1254 GENERIC_IR(processor, 0xfffa); \
1255 CLEAR_B_FLAG(processor); \
1256 })
1257
1262#define RESET(processor) \
1263 ({ \
1264 processor->stack_pointer = 0xff; \
1265 CLEAR_ALL_FLAGS(processor); \
1266 JUMP_indirect(processor, 0xfffc); \
1267 })
1268
1275#define JUMP_Subroutine(processor, addr) \
1276 ({ \
1277 processor->program_counter += 2; \
1278 PUSH_PC(processor); \
1279 JUMP_absolute(processor, addr); \
1280 })
1281
1287#define RETURN_Subroutine(processor) \
1288 ({ \
1289 PULL_PC(processor); \
1290 ++processor->program_counter; \
1291 })
1292
1298#define RETURN_Interrupt(processor) \
1299 ({ \
1300 PULL_FLAGS(processor); \
1301 PULL_PC(processor); \
1302 })
1303
1310#define COMPARE_GENERIC_Immediate(processor, value, register) \
1311 ({ \
1312 if (processor->register > value) { \
1313 SET_C_FLAG(processor); \
1314 CLEAR_Z_FLAG(processor); \
1315 CLEAR_N_FLAG(processor); \
1316 } else if (processor->register == value) { \
1317 SET_Z_FLAG(processor); \
1318 SET_C_FLAG(processor); \
1319 CLEAR_N_FLAG(processor); \
1320 } else { \
1321 CLEAR_Z_FLAG(processor); \
1322 CLEAR_C_FLAG(processor); \
1323 SET_N_FLAG(processor); \
1324 } \
1325 })
1326
1332#define COMPARE_Immediate_ACC(processor, value) \
1333 COMPARE_GENERIC_Immediate(processor, value, accumulator)
1334
1340#define COMPARE_absolute_ACC(processor, addr) COMPARE_Immediate_ACC(processor, processor->mem[addr])
1341
1349#define COMPARE_offset_ACC(processor, addr, offset) COMPARE_absolute_ACC(processor, addr + offset)
1350
1358#define COMPARE_indexed_indirect_ACC(processor, addr, offset) \
1359 COMPARE_absolute_ACC(processor, indexed_indirect(processor, addr, offset))
1360
1368#define COMPARE_indirect_indexed_ACC(processor, addr, offset) \
1369 COMPARE_absolute_ACC(processor, indirect_indexed(processor, addr, offset))
1370
1377#define COMPARE_Immediate_X(processor, value) \
1378 COMPARE_GENERIC_Immediate(processor, value, register_x)
1379
1386#define COMPARE_absolute_X(processor, addr) COMPARE_Immediate_X(processor, processor->mem[addr])
1387
1394#define COMPARE_Immediate_Y(processor, value) \
1395 COMPARE_GENERIC_Immediate(processor, value, register_y)
1396
1403#define COMPARE_absolute_Y(processor, addr) COMPARE_Immediate_X(processor, processor->mem[addr])
1404
1405#endif // !cpu_h
errcode_t step_cpu(CPU *cpu)
Function that step a clock cycle.
Definition cpu.c:1190
void print_stack_expected(memory stack, data start)
Procedure that display the expected state of the stack.
Definition cpu.c:1282
unsigned char get_next_instruction(CPU *cpu)
Function that get the next instruction written in the ROM.
Definition cpu.c:32
void init_cpu(CPU *cpu, memory mem)
Procedure that initialize the CPU to its boot/reset state.
Definition cpu.c:9
void print_cpu_state(CPU *processor)
Procedure that displays the current state of the CPU.
Definition cpu.c:1210
void print_cpu_expected(data acc, data x, data y, data flags, address pc, data sp)
Procedure that display the expected state of the CPU.
Definition cpu.c:1235
void reset(CPU *processor)
Procedure that resets the CPU by using the NES reset routine.
void print_stack_state(CPU *cpu)
Procedure that display the current state of the stack.
Definition cpu.c:1259
errcode_t execute_instruction(CPU *cpu)
Function that execute the current instruction in the ROM.
Definition cpu.c:575
void start_cpu(CPU *cpu)
Procedure that acts like the reset button of the NES.
Definition cpu.c:27
void free_cpu(CPU *cpu)
Procedure that free the memory used by the CPU and the memory array.
Definition cpu.c:21
data * memory
Definition mem.h:6
This structure will be used to represent the state of the Central Processing Unit (CPU) of our emulat...
Definition cpu.h:27
data cache
A 8 bit reserved space that I use for some operations.
Definition cpu.h:30
data accumulator
A 8 bit register used to perform operations.
Definition cpu.h:31
data register_y
A 8 bit register. Commonly used to hold offset and counters.
Definition cpu.h:33
data flags
NVPBDIZC.
Definition cpu.h:35
address program_counter
An address pointing to the next instruction to be executed.
Definition cpu.h:28
unsigned char cycle_counter
The cycle counter. The counter is decremented every step.
Definition cpu.h:37
data stack_pointer
A register that holds the 8 lower bytes of the address 0x11??.
Definition cpu.h:29
memory mem
A direct access to the Emulator Memory.
Definition cpu.h:39
data register_x
A 8 bit register. Commonly used to hold offset and counters.
Definition cpu.h:32
two_bytes_word address
Definition of the address format used by the CPU.
Definition types.h:12
byte errcode_t
Definition of the error code type used by some function.
Definition types.h:15
byte data
Definition of the data format used by the CPU.
Definition types.h:11