Clean up build system and code layout.
This uses real, big-boy makefiles instead of a shell script and moves
all of the opcode-handling weird .h files all into one directory.
Will Haldean Brown
8 years ago
0 | CC=clang | |
1 | PYTHON=python | |
2 | COPTS=-o x6502 -O3 -lpthread -Wall | |
3 | DEBUGOPTS=-DDEBUG -O0 -g | |
4 | ||
5 | all: release | |
6 | ||
7 | debug-names.h: generate_debug_names.py opcodes.h | |
8 | $(PYTHON) generate_debug_names.py > debug-names.h | |
9 | ||
10 | release: debug-names.h *.c *.h | |
11 | $(CC) $(COPTS) *.c | |
12 | ||
13 | debug: debug-names.h *.c *.h | |
14 | $(CC) $(COPTS) $(DEBUGOPTS) *.c |
8 | 8 | It currently supports the full instruction set of the |
9 | 9 | 6502 (plus a few extensions) and has an extremely |
10 | 10 | rudimentary simulated I/O bus. It should be able to run |
11 | arbitrary x6502 bytecode with "correct" results, | |
11 | arbitrary x6502 bytecode with ``correct'' results, | |
12 | 12 | although most binaries for common 6502 systems (Amiga, |
13 | 13 | C64, Apple II, etc) won't function as expected, since |
14 | 14 | they expect I/O devices to be mapped into memory where |
16 | 16 | |
17 | 17 | Building and running x6502 |
18 | 18 | |
19 | To build x6502, just run ./make.sh. You will need clang | |
20 | and Python installed. No libraries beyond POSIX libc are | |
21 | used. This will produce the x6502 binary. | |
19 | To build x6502, just run `make' in the project root. You | |
20 | will need clang and Python installed. To use gcc, change | |
21 | the $(CC) var in the Makefile. No libraries beyond POSIX | |
22 | libc are used. This will produce the x6502 binary. | |
22 | 23 | |
23 | 24 | x6502 takes the compiled 6502 object file as an |
24 | 25 | argument, and runs it until it encounters an EXT |
30 | 31 | either tell your assembler that that's the base address |
31 | 32 | for the text section of your binary or override the |
32 | 33 | default load address using the `-b' flag of x6502. |
34 | ||
35 | If you want to compile a version of x6502 that dumps | |
36 | machine state after every instruction, run `make debug' | |
37 | instead of `make'. This will also disable compiler | |
38 | optimizations. | |
33 | 39 | |
34 | 40 | Extensions to the 6502 instruction set |
35 | 41 | |
58 | 64 | character is available on standard in, an interrupt is |
59 | 65 | raised and FF01 is set to the character that was |
60 | 66 | received. Note that one character is delivered per |
61 | interrupt; if the user types "abc", they will get three | |
62 | interrupts one after the other. | |
67 | interrupt; if the user types ``abc'', they will get | |
68 | three interrupts one after the other. | |
63 | 69 | |
64 | 70 | A commented example of how to use the I/O capabilities |
65 | 71 | of x6502 is provided in test-programs/echo.s. |
72 | ||
73 | Source code formatting | |
74 | ||
75 | The code for opcode handling is a little strange; there | |
76 | are lots of ``header'' files in the opcode_handlers | |
77 | directory that are not really header files at all. These | |
78 | files all contain code for handling opcode parsing and | |
79 | interpretation; with over 150 opcodes, having all of the | |
80 | code to handle these in one file would be excessive and | |
81 | difficult to navigate, and dispatching out to functions | |
82 | to handle each opcode carries unnecessary overhead in | |
83 | what should be the tightest loop in the project. Thus, | |
84 | each of these header files is #included in emu.c in the | |
85 | middle of a select statement, and gets access to the | |
86 | local scope within the main_loop function. It's weird | |
87 | but it gets the job done, and is the least bad of all | |
88 | considered options. | |
66 | 89 | |
67 | 90 | TODO: |
68 | 91 | - switch to Makefiles like a real person |
0 | case ADC_AB: | |
1 | arg1 = NEXT_BYTE(m); | |
2 | arg2 = NEXT_BYTE(m); | |
3 | add(m, m->mem[mem_abs(arg1, arg2, 0)]); | |
4 | break; | |
5 | ||
6 | case ADC_ABX: | |
7 | arg1 = NEXT_BYTE(m); | |
8 | arg2 = NEXT_BYTE(m); | |
9 | add(m, m->mem[mem_abs(arg1, arg2, m->x)]); | |
10 | break; | |
11 | ||
12 | case ADC_ABY: | |
13 | arg1 = NEXT_BYTE(m); | |
14 | arg2 = NEXT_BYTE(m); | |
15 | add(m, m->mem[mem_abs(arg1, arg2, m->y)]); | |
16 | break; | |
17 | ||
18 | case ADC_IMM: | |
19 | add(m, NEXT_BYTE(m)); | |
20 | break; | |
21 | ||
22 | case ADC_INX: | |
23 | add(m, m->mem[mem_indexed_indirect(m, NEXT_BYTE(m), m->x)]); | |
24 | break; | |
25 | ||
26 | case ADC_INY: | |
27 | add(m, m->mem[mem_indirect_index(m, NEXT_BYTE(m), m->y)]); | |
28 | break; | |
29 | ||
30 | case ADC_ZP: | |
31 | add(m, m->mem[NEXT_BYTE(m)]); | |
32 | break; | |
33 | ||
34 | case ADC_ZPX: | |
35 | add(m, m->mem[ZP(NEXT_BYTE(m) + m->x)]); | |
36 | break; | |
37 | ||
38 | case SBC_AB: | |
39 | arg1 = NEXT_BYTE(m); | |
40 | arg2 = NEXT_BYTE(m); | |
41 | sub(m, m->mem[mem_abs(arg1, arg2, 0)]); | |
42 | break; | |
43 | ||
44 | case SBC_ABX: | |
45 | arg1 = NEXT_BYTE(m); | |
46 | arg2 = NEXT_BYTE(m); | |
47 | sub(m, m->mem[mem_abs(arg1, arg2, m->x)]); | |
48 | break; | |
49 | ||
50 | case SBC_ABY: | |
51 | arg1 = NEXT_BYTE(m); | |
52 | arg2 = NEXT_BYTE(m); | |
53 | sub(m, m->mem[mem_abs(arg1, arg2, m->y)]); | |
54 | break; | |
55 | ||
56 | case SBC_IMM: | |
57 | sub(m, NEXT_BYTE(m)); | |
58 | break; | |
59 | ||
60 | case SBC_INX: | |
61 | sub(m, m->mem[mem_indexed_indirect(m, NEXT_BYTE(m), m->x)]); | |
62 | break; | |
63 | ||
64 | case SBC_INY: | |
65 | sub(m, m->mem[mem_indirect_index(m, NEXT_BYTE(m), m->y)]); | |
66 | break; | |
67 | ||
68 | case SBC_ZP: | |
69 | sub(m, m->mem[NEXT_BYTE(m)]); | |
70 | break; | |
71 | ||
72 | case SBC_ZPX: | |
73 | sub(m, m->mem[ZP(NEXT_BYTE(m) + m->x)]); | |
74 | break; |
0 | case BCC_REL: | |
1 | s1 = NEXT_BYTE(m); | |
2 | if (!get_flag(m, FLAG_CARRY)) { | |
3 | branch_offset = s1; | |
4 | } | |
5 | break; | |
6 | ||
7 | case BCS_REL: | |
8 | s1 = NEXT_BYTE(m); | |
9 | if (get_flag(m, FLAG_CARRY)) { | |
10 | branch_offset = s1; | |
11 | } | |
12 | break; | |
13 | ||
14 | case BEQ_REL: | |
15 | s1 = NEXT_BYTE(m); | |
16 | if (get_flag(m, FLAG_ZERO)) { | |
17 | branch_offset = s1; | |
18 | } | |
19 | break; | |
20 | ||
21 | case BMI_REL: | |
22 | s1 = NEXT_BYTE(m); | |
23 | if (get_flag(m, FLAG_NEGATIVE)) { | |
24 | branch_offset = s1; | |
25 | } | |
26 | break; | |
27 | ||
28 | case BNE_REL: | |
29 | s1 = NEXT_BYTE(m); | |
30 | if (!get_flag(m, FLAG_ZERO)) { | |
31 | branch_offset = s1; | |
32 | } | |
33 | break; | |
34 | ||
35 | case BPL_REL: | |
36 | s1 = NEXT_BYTE(m); | |
37 | if (!get_flag(m, FLAG_NEGATIVE)) { | |
38 | branch_offset = s1; | |
39 | } | |
40 | break; | |
41 | ||
42 | case BVC_REL: | |
43 | s1 = NEXT_BYTE(m); | |
44 | if (!get_flag(m, FLAG_OVERFLOW)) { | |
45 | branch_offset = s1; | |
46 | } | |
47 | break; | |
48 | ||
49 | case BVS_REL: | |
50 | s1 = NEXT_BYTE(m); | |
51 | if (get_flag(m, FLAG_OVERFLOW)) { | |
52 | branch_offset = s1; | |
53 | } | |
54 | break; |
0 | case CMP_AB: | |
1 | arg1 = NEXT_BYTE(m); | |
2 | arg2 = NEXT_BYTE(m); | |
3 | cmp(m, m->mem[mem_abs(arg1, arg2, 0)], m->ac); | |
4 | break; | |
5 | ||
6 | case CMP_ABX: | |
7 | arg1 = NEXT_BYTE(m); | |
8 | arg2 = NEXT_BYTE(m); | |
9 | cmp(m, m->mem[mem_abs(arg1, arg2, m->x)], m->ac); | |
10 | break; | |
11 | ||
12 | case CMP_ABY: | |
13 | arg1 = NEXT_BYTE(m); | |
14 | arg2 = NEXT_BYTE(m); | |
15 | cmp(m, m->mem[mem_abs(arg1, arg2, m->y)], m->ac); | |
16 | break; | |
17 | ||
18 | case CMP_IMM: | |
19 | cmp(m, NEXT_BYTE(m), m->ac); | |
20 | break; | |
21 | ||
22 | case CMP_INX: | |
23 | cmp(m, m->mem[mem_indexed_indirect(m, NEXT_BYTE(m), m->x)], m->ac); | |
24 | break; | |
25 | ||
26 | case CMP_INY: | |
27 | cmp(m, m->mem[mem_indirect_index(m, NEXT_BYTE(m), m->y)], m->ac); | |
28 | break; | |
29 | ||
30 | case CMP_ZP: | |
31 | cmp(m, m->mem[NEXT_BYTE(m)], m->ac); | |
32 | break; | |
33 | ||
34 | case CMP_ZPX: | |
35 | cmp(m, m->mem[ZP(NEXT_BYTE(m) + m->x)], m->ac); | |
36 | break; | |
37 | ||
38 | case CPX_AB: | |
39 | arg1 = NEXT_BYTE(m); | |
40 | arg2 = NEXT_BYTE(m); | |
41 | cmp(m, m->mem[mem_abs(arg1, arg2, 0)], m->x); | |
42 | break; | |
43 | ||
44 | case CPX_IMM: | |
45 | cmp(m, NEXT_BYTE(m), m->x); | |
46 | break; | |
47 | ||
48 | case CPX_ZP: | |
49 | cmp(m, m->mem[NEXT_BYTE(m)], m->x); | |
50 | break; | |
51 | ||
52 | case CPY_AB: | |
53 | arg1 = NEXT_BYTE(m); | |
54 | arg2 = NEXT_BYTE(m); | |
55 | cmp(m, m->mem[mem_abs(arg1, arg2, 0)], m->y); | |
56 | break; | |
57 | ||
58 | case CPY_IMM: | |
59 | cmp(m, NEXT_BYTE(m), m->y); | |
60 | break; | |
61 | ||
62 | case CPY_ZP: | |
63 | cmp(m, m->mem[NEXT_BYTE(m)], m->y); | |
64 | break; |
50 | 50 | break; |
51 | 51 | #endif |
52 | 52 | |
53 | #include "arithmetic.h" | |
54 | #include "branch.h" | |
55 | #include "compare.h" | |
56 | #include "flags.h" | |
57 | #include "incdec.h" | |
58 | #include "jump.h" | |
59 | #include "load.h" | |
60 | #include "logical.h" | |
61 | #include "shift.h" | |
62 | #include "stack.h" | |
63 | #include "store.h" | |
64 | #include "transfer.h" | |
53 | #include "opcode_handlers/arithmetic.h" | |
54 | #include "opcode_handlers/branch.h" | |
55 | #include "opcode_handlers/compare.h" | |
56 | #include "opcode_handlers/flags.h" | |
57 | #include "opcode_handlers/incdec.h" | |
58 | #include "opcode_handlers/jump.h" | |
59 | #include "opcode_handlers/load.h" | |
60 | #include "opcode_handlers/logical.h" | |
61 | #include "opcode_handlers/shift.h" | |
62 | #include "opcode_handlers/stack.h" | |
63 | #include "opcode_handlers/store.h" | |
64 | #include "opcode_handlers/transfer.h" | |
65 | 65 | |
66 | 66 | default: |
67 | 67 | printf("ERROR: got unknown opcode %02x\n", opcode); |
0 | case CLC: | |
1 | set_flag(m, FLAG_CARRY, 0); | |
2 | break; | |
3 | ||
4 | case CLD: | |
5 | set_flag(m, FLAG_DECIMAL, 0); | |
6 | break; | |
7 | ||
8 | case CLI: | |
9 | set_flag(m, FLAG_INTERRUPT, 0); | |
10 | break; | |
11 | ||
12 | case CLV: | |
13 | set_flag(m, FLAG_OVERFLOW, 0); | |
14 | break; | |
15 | ||
16 | case SEC: | |
17 | set_flag(m, FLAG_CARRY, 1); | |
18 | break; | |
19 | ||
20 | case SED: | |
21 | set_flag(m, FLAG_DECIMAL, 1); | |
22 | break; | |
23 | ||
24 | case SEI: | |
25 | set_flag(m, FLAG_INTERRUPT, 1); | |
26 | break; |
0 | // CALL MARK_DIRTY IN HERE! | |
1 | case INC_AB: | |
2 | arg1 = NEXT_BYTE(m); | |
3 | arg2 = NEXT_BYTE(m); | |
4 | r1 = mem_abs(arg1, arg2, 0); | |
5 | set_flags(m, ++m->mem[r1]); | |
6 | mark_dirty(m, r1); | |
7 | break; | |
8 | ||
9 | case INC_ABX: | |
10 | arg1 = NEXT_BYTE(m); | |
11 | arg2 = NEXT_BYTE(m); | |
12 | r1 = mem_abs(arg1, arg2, m->x); | |
13 | set_flags(m, ++m->mem[r1]); | |
14 | mark_dirty(m, r1); | |
15 | break; | |
16 | ||
17 | case INC_ZP: | |
18 | r1 = NEXT_BYTE(m); | |
19 | set_flags(m, ++m->mem[r1]); | |
20 | mark_dirty(m, r1); | |
21 | break; | |
22 | ||
23 | case INC_ZPX: | |
24 | r1 = ZP(NEXT_BYTE(m) + m->x); | |
25 | set_flags(m, ++m->mem[r1]); | |
26 | mark_dirty(m, r1); | |
27 | break; | |
28 | ||
29 | case INX: | |
30 | set_flags(m, ++m->x); | |
31 | break; | |
32 | ||
33 | case INY: | |
34 | set_flags(m, ++m->y); | |
35 | break; | |
36 | ||
37 | case DEC_AB: | |
38 | arg1 = NEXT_BYTE(m); | |
39 | arg2 = NEXT_BYTE(m); | |
40 | r1 = mem_abs(arg1, arg2, 0); | |
41 | set_flags(m, --m->mem[r1]); | |
42 | mark_dirty(m, r1); | |
43 | break; | |
44 | ||
45 | case DEC_ABX: | |
46 | arg1 = NEXT_BYTE(m); | |
47 | arg2 = NEXT_BYTE(m); | |
48 | r1 = mem_abs(arg1, arg2, m->x); | |
49 | set_flags(m, --m->mem[r1]); | |
50 | mark_dirty(m, r1); | |
51 | break; | |
52 | ||
53 | case DEC_ZP: | |
54 | r1 = NEXT_BYTE(m); | |
55 | set_flags(m, --m->mem[r1]); | |
56 | mark_dirty(m, r1); | |
57 | break; | |
58 | ||
59 | case DEC_ZPX: | |
60 | r1 = ZP(NEXT_BYTE(m) + m->x); | |
61 | set_flags(m, --m->mem[r1]); | |
62 | mark_dirty(m, r1); | |
63 | break; | |
64 | ||
65 | case DEX: | |
66 | set_flags(m, --m->x); | |
67 | break; | |
68 | ||
69 | case DEY: | |
70 | set_flags(m, --m->y); | |
71 | break; |
0 | case JMP_AB: | |
1 | arg1 = NEXT_BYTE(m); | |
2 | m->pc = mem_abs(arg1, NEXT_BYTE(m), 0); | |
3 | break; | |
4 | ||
5 | case JMP_IN: | |
6 | arg1 = NEXT_BYTE(m); | |
7 | r1 = mem_abs(arg1, NEXT_BYTE(m), 0); | |
8 | m->pc = mem_abs(m->mem[r1], m->mem[r1+1], 0); | |
9 | break; | |
10 | ||
11 | case JSR_AB: | |
12 | arg1 = NEXT_BYTE(m); | |
13 | r1 = mem_abs(arg1, NEXT_BYTE(m), 0); | |
14 | // we push the address of the byte immediately before where we want to | |
15 | // return to because reasons: | |
16 | r2 = m->pc + pc_offset - 1; | |
17 | STACK_PUSH(m) = (r2 & 0xFF00) >> 8; | |
18 | STACK_PUSH(m) = r2 & 0xFF; | |
19 | m->pc = r1; | |
20 | break; | |
21 | ||
22 | case RTS: | |
23 | arg1 = STACK_POP(m); | |
24 | m->pc = mem_abs(arg1, STACK_POP(m), 0) + 1; | |
25 | break; | |
26 | ||
27 | case BRK: | |
28 | set_flag(m, FLAG_BREAK, 1); | |
29 | m->interrupt_waiting = 1; | |
30 | break; | |
31 | ||
32 | case RTI: | |
33 | m->sr = STACK_POP(m); | |
34 | arg1 = STACK_POP(m); | |
35 | m->pc = mem_abs(arg1, STACK_POP(m), 0); | |
36 | break; |
0 | case LDA_AB: | |
1 | arg1 = NEXT_BYTE(m); | |
2 | arg2 = NEXT_BYTE(m); | |
3 | m->ac = m->mem[mem_abs(arg1, arg2, 0)]; | |
4 | set_flags(m, m->ac); | |
5 | break; | |
6 | ||
7 | case LDA_ABX: | |
8 | arg1 = NEXT_BYTE(m); | |
9 | arg2 = NEXT_BYTE(m); | |
10 | m->ac = m->mem[mem_abs(arg1, arg2, m->x)]; | |
11 | set_flags(m, m->ac); | |
12 | break; | |
13 | ||
14 | case LDA_ABY: | |
15 | arg1 = NEXT_BYTE(m); | |
16 | arg2 = NEXT_BYTE(m); | |
17 | m->ac = m->mem[mem_abs(arg1, arg2, m->y)]; | |
18 | set_flags(m, m->ac); | |
19 | break; | |
20 | ||
21 | case LDA_IMM: | |
22 | m->ac = NEXT_BYTE(m); | |
23 | set_flags(m, m->ac); | |
24 | break; | |
25 | ||
26 | case LDA_INX: | |
27 | m->ac = m->mem[mem_indexed_indirect(m, NEXT_BYTE(m), m->x)]; | |
28 | set_flags(m, m->ac); | |
29 | break; | |
30 | ||
31 | case LDA_INY: | |
32 | m->ac = m->mem[mem_indirect_index(m, NEXT_BYTE(m), m->y)]; | |
33 | set_flags(m, m->ac); | |
34 | break; | |
35 | ||
36 | case LDA_ZP: | |
37 | m->ac = m->mem[NEXT_BYTE(m)]; | |
38 | set_flags(m, m->ac); | |
39 | break; | |
40 | ||
41 | case LDA_ZPX: | |
42 | m->ac = m->mem[NEXT_BYTE(m) + m->x]; | |
43 | set_flags(m, m->ac); | |
44 | break; | |
45 | ||
46 | case LDX_AB: | |
47 | arg1 = NEXT_BYTE(m); | |
48 | arg2 = NEXT_BYTE(m); | |
49 | m->x = m->mem[mem_abs(arg1, arg2, 0)]; | |
50 | set_flags(m, m->x); | |
51 | break; | |
52 | ||
53 | case LDX_ABY: | |
54 | arg1 = NEXT_BYTE(m); | |
55 | arg2 = NEXT_BYTE(m); | |
56 | m->x = m->mem[mem_abs(arg1, arg2, m->y)]; | |
57 | set_flags(m, m->x); | |
58 | break; | |
59 | ||
60 | case LDX_IMM: | |
61 | m->x = NEXT_BYTE(m); | |
62 | set_flags(m, m->x); | |
63 | break; | |
64 | ||
65 | case LDX_ZP: | |
66 | m->x = m->mem[NEXT_BYTE(m)]; | |
67 | set_flags(m, m->x); | |
68 | break; | |
69 | ||
70 | case LDX_ZPY: | |
71 | m->x = m->mem[NEXT_BYTE(m) + m->y]; | |
72 | set_flags(m, m->x); | |
73 | break; | |
74 | ||
75 | case LDY_AB: | |
76 | arg1 = NEXT_BYTE(m); | |
77 | arg2 = NEXT_BYTE(m); | |
78 | m->y = m->mem[mem_abs(arg1, arg2, 0)]; | |
79 | set_flags(m, m->y); | |
80 | break; | |
81 | ||
82 | case LDY_ABX: | |
83 | arg1 = NEXT_BYTE(m); | |
84 | arg2 = NEXT_BYTE(m); | |
85 | m->y = m->mem[mem_abs(arg1, arg2, m->x)]; | |
86 | set_flags(m, m->y); | |
87 | break; | |
88 | ||
89 | case LDY_IMM: | |
90 | m->y = NEXT_BYTE(m); | |
91 | set_flags(m, m->y); | |
92 | break; | |
93 | ||
94 | case LDY_ZP: | |
95 | m->y = m->mem[NEXT_BYTE(m)]; | |
96 | set_flags(m, m->y); | |
97 | break; | |
98 | ||
99 | case LDY_ZPX: | |
100 | m->y = m->mem[NEXT_BYTE(m) + m->x]; | |
101 | set_flags(m, m->y); | |
102 | break; |
0 | case AND_IMM: | |
1 | m->ac &= NEXT_BYTE(m); | |
2 | set_flags(m, m->ac); | |
3 | break; | |
4 | ||
5 | case AND_ZP: | |
6 | m->ac &= m->mem[NEXT_BYTE(m)]; | |
7 | set_flags(m, m->ac); | |
8 | break; | |
9 | ||
10 | case AND_ZPX: | |
11 | m->ac &= m->mem[ZP(NEXT_BYTE(m) + m->x)]; | |
12 | set_flags(m, m->ac); | |
13 | break; | |
14 | ||
15 | case AND_AB: | |
16 | arg1 = NEXT_BYTE(m); | |
17 | arg2 = NEXT_BYTE(m); | |
18 | m->ac &= m->mem[mem_abs(arg1, arg2, 0)]; | |
19 | set_flags(m, m->ac); | |
20 | break; | |
21 | ||
22 | case AND_ABX: | |
23 | arg1 = NEXT_BYTE(m); | |
24 | arg2 = NEXT_BYTE(m); | |
25 | m->ac &= m->mem[mem_abs(arg1, arg2, m->x)]; | |
26 | set_flags(m, m->ac); | |
27 | break; | |
28 | ||
29 | case AND_ABY: | |
30 | arg1 = NEXT_BYTE(m); | |
31 | arg2 = NEXT_BYTE(m); | |
32 | m->ac &= m->mem[mem_abs(arg1, arg2, m->y)]; | |
33 | set_flags(m, m->ac); | |
34 | break; | |
35 | ||
36 | case AND_INX: | |
37 | m->ac &= m->mem[mem_indexed_indirect(m, NEXT_BYTE(m), m->x)]; | |
38 | set_flags(m, m->ac); | |
39 | break; | |
40 | ||
41 | case AND_INY: | |
42 | m->ac &= m->mem[mem_indirect_index(m, NEXT_BYTE(m), m->y)]; | |
43 | set_flags(m, m->ac); | |
44 | break; | |
45 | ||
46 | case EOR_IMM: | |
47 | m->ac ^= NEXT_BYTE(m); | |
48 | set_flags(m, m->ac); | |
49 | break; | |
50 | ||
51 | case EOR_ZP: | |
52 | m->ac ^= m->mem[NEXT_BYTE(m)]; | |
53 | set_flags(m, m->ac); | |
54 | break; | |
55 | ||
56 | case EOR_ZPX: | |
57 | m->ac ^= m->mem[ZP(NEXT_BYTE(m) + m->x)]; | |
58 | set_flags(m, m->ac); | |
59 | break; | |
60 | ||
61 | case EOR_AB: | |
62 | arg1 = NEXT_BYTE(m); | |
63 | arg2 = NEXT_BYTE(m); | |
64 | m->ac ^= m->mem[mem_abs(arg1, arg2, 0)]; | |
65 | set_flags(m, m->ac); | |
66 | break; | |
67 | ||
68 | case EOR_ABX: | |
69 | arg1 = NEXT_BYTE(m); | |
70 | arg2 = NEXT_BYTE(m); | |
71 | m->ac ^= m->mem[mem_abs(arg1, arg2, m->x)]; | |
72 | set_flags(m, m->ac); | |
73 | break; | |
74 | ||
75 | case EOR_ABY: | |
76 | arg1 = NEXT_BYTE(m); | |
77 | arg2 = NEXT_BYTE(m); | |
78 | m->ac ^= m->mem[mem_abs(arg1, arg2, m->y)]; | |
79 | set_flags(m, m->ac); | |
80 | break; | |
81 | ||
82 | case EOR_INX: | |
83 | m->ac ^= m->mem[mem_indexed_indirect(m, NEXT_BYTE(m), m->x)]; | |
84 | set_flags(m, m->ac); | |
85 | break; | |
86 | ||
87 | case EOR_INY: | |
88 | m->ac ^= m->mem[mem_indirect_index(m, NEXT_BYTE(m), m->y)]; | |
89 | set_flags(m, m->ac); | |
90 | break; | |
91 | ||
92 | case ORA_IMM: | |
93 | m->ac |= NEXT_BYTE(m); | |
94 | set_flags(m, m->ac); | |
95 | break; | |
96 | ||
97 | case ORA_ZP: | |
98 | m->ac |= m->mem[NEXT_BYTE(m)]; | |
99 | set_flags(m, m->ac); | |
100 | break; | |
101 | ||
102 | case ORA_ZPX: | |
103 | m->ac |= m->mem[ZP(NEXT_BYTE(m) + m->x)]; | |
104 | set_flags(m, m->ac); | |
105 | break; | |
106 | ||
107 | case ORA_AB: | |
108 | arg1 = NEXT_BYTE(m); | |
109 | arg2 = NEXT_BYTE(m); | |
110 | m->ac |= m->mem[mem_abs(arg1, arg2, 0)]; | |
111 | set_flags(m, m->ac); | |
112 | break; | |
113 | ||
114 | case ORA_ABX: | |
115 | arg1 = NEXT_BYTE(m); | |
116 | arg2 = NEXT_BYTE(m); | |
117 | m->ac |= m->mem[mem_abs(arg1, arg2, m->x)]; | |
118 | set_flags(m, m->ac); | |
119 | break; | |
120 | ||
121 | case ORA_ABY: | |
122 | arg1 = NEXT_BYTE(m); | |
123 | arg2 = NEXT_BYTE(m); | |
124 | m->ac |= m->mem[mem_abs(arg1, arg2, m->y)]; | |
125 | set_flags(m, m->ac); | |
126 | break; | |
127 | ||
128 | case ORA_INX: | |
129 | m->ac |= m->mem[mem_indexed_indirect(m, NEXT_BYTE(m), m->x)]; | |
130 | set_flags(m, m->ac); | |
131 | break; | |
132 | ||
133 | case ORA_INY: | |
134 | m->ac |= m->mem[mem_indirect_index(m, NEXT_BYTE(m), m->y)]; | |
135 | set_flags(m, m->ac); | |
136 | break; | |
137 | ||
138 | case BIT_AB: | |
139 | arg1 = NEXT_BYTE(m); | |
140 | arg2 = NEXT_BYTE(m); | |
141 | t1 = m->mem[mem_abs(arg1, arg2, 0)]; | |
142 | set_flag(m, FLAG_ZERO, !(t1 & m->ac)); | |
143 | set_flag(m, FLAG_OVERFLOW, t1 & 0x40); | |
144 | set_flag(m, FLAG_NEGATIVE, t1 & 0x80); | |
145 | break; | |
146 | ||
147 | case BIT_ZP: | |
148 | t1 = m->mem[NEXT_BYTE(m)]; | |
149 | set_flag(m, FLAG_ZERO, !(t1 & m->ac)); | |
150 | set_flag(m, FLAG_OVERFLOW, t1 & 0x40); | |
151 | set_flag(m, FLAG_NEGATIVE, t1 & 0x80); | |
152 | break; |
0 | #!/bin/bash | |
1 | ||
2 | python generate_debug_names.py > debug-names.h | |
3 | clang *.c -o x6502 -O3 -lpthread -Wall |
0 | case ADC_AB: | |
1 | arg1 = NEXT_BYTE(m); | |
2 | arg2 = NEXT_BYTE(m); | |
3 | add(m, m->mem[mem_abs(arg1, arg2, 0)]); | |
4 | break; | |
5 | ||
6 | case ADC_ABX: | |
7 | arg1 = NEXT_BYTE(m); | |
8 | arg2 = NEXT_BYTE(m); | |
9 | add(m, m->mem[mem_abs(arg1, arg2, m->x)]); | |
10 | break; | |
11 | ||
12 | case ADC_ABY: | |
13 | arg1 = NEXT_BYTE(m); | |
14 | arg2 = NEXT_BYTE(m); | |
15 | add(m, m->mem[mem_abs(arg1, arg2, m->y)]); | |
16 | break; | |
17 | ||
18 | case ADC_IMM: | |
19 | add(m, NEXT_BYTE(m)); | |
20 | break; | |
21 | ||
22 | case ADC_INX: | |
23 | add(m, m->mem[mem_indexed_indirect(m, NEXT_BYTE(m), m->x)]); | |
24 | break; | |
25 | ||
26 | case ADC_INY: | |
27 | add(m, m->mem[mem_indirect_index(m, NEXT_BYTE(m), m->y)]); | |
28 | break; | |
29 | ||
30 | case ADC_ZP: | |
31 | add(m, m->mem[NEXT_BYTE(m)]); | |
32 | break; | |
33 | ||
34 | case ADC_ZPX: | |
35 | add(m, m->mem[ZP(NEXT_BYTE(m) + m->x)]); | |
36 | break; | |
37 | ||
38 | case SBC_AB: | |
39 | arg1 = NEXT_BYTE(m); | |
40 | arg2 = NEXT_BYTE(m); | |
41 | sub(m, m->mem[mem_abs(arg1, arg2, 0)]); | |
42 | break; | |
43 | ||
44 | case SBC_ABX: | |
45 | arg1 = NEXT_BYTE(m); | |
46 | arg2 = NEXT_BYTE(m); | |
47 | sub(m, m->mem[mem_abs(arg1, arg2, m->x)]); | |
48 | break; | |
49 | ||
50 | case SBC_ABY: | |
51 | arg1 = NEXT_BYTE(m); | |
52 | arg2 = NEXT_BYTE(m); | |
53 | sub(m, m->mem[mem_abs(arg1, arg2, m->y)]); | |
54 | break; | |
55 | ||
56 | case SBC_IMM: | |
57 | sub(m, NEXT_BYTE(m)); | |
58 | break; | |
59 | ||
60 | case SBC_INX: | |
61 | sub(m, m->mem[mem_indexed_indirect(m, NEXT_BYTE(m), m->x)]); | |
62 | break; | |
63 | ||
64 | case SBC_INY: | |
65 | sub(m, m->mem[mem_indirect_index(m, NEXT_BYTE(m), m->y)]); | |
66 | break; | |
67 | ||
68 | case SBC_ZP: | |
69 | sub(m, m->mem[NEXT_BYTE(m)]); | |
70 | break; | |
71 | ||
72 | case SBC_ZPX: | |
73 | sub(m, m->mem[ZP(NEXT_BYTE(m) + m->x)]); | |
74 | break; |
0 | case BCC_REL: | |
1 | s1 = NEXT_BYTE(m); | |
2 | if (!get_flag(m, FLAG_CARRY)) { | |
3 | branch_offset = s1; | |
4 | } | |
5 | break; | |
6 | ||
7 | case BCS_REL: | |
8 | s1 = NEXT_BYTE(m); | |
9 | if (get_flag(m, FLAG_CARRY)) { | |
10 | branch_offset = s1; | |
11 | } | |
12 | break; | |
13 | ||
14 | case BEQ_REL: | |
15 | s1 = NEXT_BYTE(m); | |
16 | if (get_flag(m, FLAG_ZERO)) { | |
17 | branch_offset = s1; | |
18 | } | |
19 | break; | |
20 | ||
21 | case BMI_REL: | |
22 | s1 = NEXT_BYTE(m); | |
23 | if (get_flag(m, FLAG_NEGATIVE)) { | |
24 | branch_offset = s1; | |
25 | } | |
26 | break; | |
27 | ||
28 | case BNE_REL: | |
29 | s1 = NEXT_BYTE(m); | |
30 | if (!get_flag(m, FLAG_ZERO)) { | |
31 | branch_offset = s1; | |
32 | } | |
33 | break; | |
34 | ||
35 | case BPL_REL: | |
36 | s1 = NEXT_BYTE(m); | |
37 | if (!get_flag(m, FLAG_NEGATIVE)) { | |
38 | branch_offset = s1; | |
39 | } | |
40 | break; | |
41 | ||
42 | case BVC_REL: | |
43 | s1 = NEXT_BYTE(m); | |
44 | if (!get_flag(m, FLAG_OVERFLOW)) { | |
45 | branch_offset = s1; | |
46 | } | |
47 | break; | |
48 | ||
49 | case BVS_REL: | |
50 | s1 = NEXT_BYTE(m); | |
51 | if (get_flag(m, FLAG_OVERFLOW)) { | |
52 | branch_offset = s1; | |
53 | } | |
54 | break; |
0 | case CMP_AB: | |
1 | arg1 = NEXT_BYTE(m); | |
2 | arg2 = NEXT_BYTE(m); | |
3 | cmp(m, m->mem[mem_abs(arg1, arg2, 0)], m->ac); | |
4 | break; | |
5 | ||
6 | case CMP_ABX: | |
7 | arg1 = NEXT_BYTE(m); | |
8 | arg2 = NEXT_BYTE(m); | |
9 | cmp(m, m->mem[mem_abs(arg1, arg2, m->x)], m->ac); | |
10 | break; | |
11 | ||
12 | case CMP_ABY: | |
13 | arg1 = NEXT_BYTE(m); | |
14 | arg2 = NEXT_BYTE(m); | |
15 | cmp(m, m->mem[mem_abs(arg1, arg2, m->y)], m->ac); | |
16 | break; | |
17 | ||
18 | case CMP_IMM: | |
19 | cmp(m, NEXT_BYTE(m), m->ac); | |
20 | break; | |
21 | ||
22 | case CMP_INX: | |
23 | cmp(m, m->mem[mem_indexed_indirect(m, NEXT_BYTE(m), m->x)], m->ac); | |
24 | break; | |
25 | ||
26 | case CMP_INY: | |
27 | cmp(m, m->mem[mem_indirect_index(m, NEXT_BYTE(m), m->y)], m->ac); | |
28 | break; | |
29 | ||
30 | case CMP_ZP: | |
31 | cmp(m, m->mem[NEXT_BYTE(m)], m->ac); | |
32 | break; | |
33 | ||
34 | case CMP_ZPX: | |
35 | cmp(m, m->mem[ZP(NEXT_BYTE(m) + m->x)], m->ac); | |
36 | break; | |
37 | ||
38 | case CPX_AB: | |
39 | arg1 = NEXT_BYTE(m); | |
40 | arg2 = NEXT_BYTE(m); | |
41 | cmp(m, m->mem[mem_abs(arg1, arg2, 0)], m->x); | |
42 | break; | |
43 | ||
44 | case CPX_IMM: | |
45 | cmp(m, NEXT_BYTE(m), m->x); | |
46 | break; | |
47 | ||
48 | case CPX_ZP: | |
49 | cmp(m, m->mem[NEXT_BYTE(m)], m->x); | |
50 | break; | |
51 | ||
52 | case CPY_AB: | |
53 | arg1 = NEXT_BYTE(m); | |
54 | arg2 = NEXT_BYTE(m); | |
55 | cmp(m, m->mem[mem_abs(arg1, arg2, 0)], m->y); | |
56 | break; | |
57 | ||
58 | case CPY_IMM: | |
59 | cmp(m, NEXT_BYTE(m), m->y); | |
60 | break; | |
61 | ||
62 | case CPY_ZP: | |
63 | cmp(m, m->mem[NEXT_BYTE(m)], m->y); | |
64 | break; |
0 | case CLC: | |
1 | set_flag(m, FLAG_CARRY, 0); | |
2 | break; | |
3 | ||
4 | case CLD: | |
5 | set_flag(m, FLAG_DECIMAL, 0); | |
6 | break; | |
7 | ||
8 | case CLI: | |
9 | set_flag(m, FLAG_INTERRUPT, 0); | |
10 | break; | |
11 | ||
12 | case CLV: | |
13 | set_flag(m, FLAG_OVERFLOW, 0); | |
14 | break; | |
15 | ||
16 | case SEC: | |
17 | set_flag(m, FLAG_CARRY, 1); | |
18 | break; | |
19 | ||
20 | case SED: | |
21 | set_flag(m, FLAG_DECIMAL, 1); | |
22 | break; | |
23 | ||
24 | case SEI: | |
25 | set_flag(m, FLAG_INTERRUPT, 1); | |
26 | break; |
0 | // CALL MARK_DIRTY IN HERE! | |
1 | case INC_AB: | |
2 | arg1 = NEXT_BYTE(m); | |
3 | arg2 = NEXT_BYTE(m); | |
4 | r1 = mem_abs(arg1, arg2, 0); | |
5 | set_flags(m, ++m->mem[r1]); | |
6 | mark_dirty(m, r1); | |
7 | break; | |
8 | ||
9 | case INC_ABX: | |
10 | arg1 = NEXT_BYTE(m); | |
11 | arg2 = NEXT_BYTE(m); | |
12 | r1 = mem_abs(arg1, arg2, m->x); | |
13 | set_flags(m, ++m->mem[r1]); | |
14 | mark_dirty(m, r1); | |
15 | break; | |
16 | ||
17 | case INC_ZP: | |
18 | r1 = NEXT_BYTE(m); | |
19 | set_flags(m, ++m->mem[r1]); | |
20 | mark_dirty(m, r1); | |
21 | break; | |
22 | ||
23 | case INC_ZPX: | |
24 | r1 = ZP(NEXT_BYTE(m) + m->x); | |
25 | set_flags(m, ++m->mem[r1]); | |
26 | mark_dirty(m, r1); | |
27 | break; | |
28 | ||
29 | case INX: | |
30 | set_flags(m, ++m->x); | |
31 | break; | |
32 | ||
33 | case INY: | |
34 | set_flags(m, ++m->y); | |
35 | break; | |
36 | ||
37 | case DEC_AB: | |
38 | arg1 = NEXT_BYTE(m); | |
39 | arg2 = NEXT_BYTE(m); | |
40 | r1 = mem_abs(arg1, arg2, 0); | |
41 | set_flags(m, --m->mem[r1]); | |
42 | mark_dirty(m, r1); | |
43 | break; | |
44 | ||
45 | case DEC_ABX: | |
46 | arg1 = NEXT_BYTE(m); | |
47 | arg2 = NEXT_BYTE(m); | |
48 | r1 = mem_abs(arg1, arg2, m->x); | |
49 | set_flags(m, --m->mem[r1]); | |
50 | mark_dirty(m, r1); | |
51 | break; | |
52 | ||
53 | case DEC_ZP: | |
54 | r1 = NEXT_BYTE(m); | |
55 | set_flags(m, --m->mem[r1]); | |
56 | mark_dirty(m, r1); | |
57 | break; | |
58 | ||
59 | case DEC_ZPX: | |
60 | r1 = ZP(NEXT_BYTE(m) + m->x); | |
61 | set_flags(m, --m->mem[r1]); | |
62 | mark_dirty(m, r1); | |
63 | break; | |
64 | ||
65 | case DEX: | |
66 | set_flags(m, --m->x); | |
67 | break; | |
68 | ||
69 | case DEY: | |
70 | set_flags(m, --m->y); | |
71 | break; |
0 | case JMP_AB: | |
1 | arg1 = NEXT_BYTE(m); | |
2 | m->pc = mem_abs(arg1, NEXT_BYTE(m), 0); | |
3 | break; | |
4 | ||
5 | case JMP_IN: | |
6 | arg1 = NEXT_BYTE(m); | |
7 | r1 = mem_abs(arg1, NEXT_BYTE(m), 0); | |
8 | m->pc = mem_abs(m->mem[r1], m->mem[r1+1], 0); | |
9 | break; | |
10 | ||
11 | case JSR_AB: | |
12 | arg1 = NEXT_BYTE(m); | |
13 | r1 = mem_abs(arg1, NEXT_BYTE(m), 0); | |
14 | // we push the address of the byte immediately before where we want to | |
15 | // return to because reasons: | |
16 | r2 = m->pc + pc_offset - 1; | |
17 | STACK_PUSH(m) = (r2 & 0xFF00) >> 8; | |
18 | STACK_PUSH(m) = r2 & 0xFF; | |
19 | m->pc = r1; | |
20 | break; | |
21 | ||
22 | case RTS: | |
23 | arg1 = STACK_POP(m); | |
24 | m->pc = mem_abs(arg1, STACK_POP(m), 0) + 1; | |
25 | break; | |
26 | ||
27 | case BRK: | |
28 | set_flag(m, FLAG_BREAK, 1); | |
29 | m->interrupt_waiting = 1; | |
30 | break; | |
31 | ||
32 | case RTI: | |
33 | m->sr = STACK_POP(m); | |
34 | arg1 = STACK_POP(m); | |
35 | m->pc = mem_abs(arg1, STACK_POP(m), 0); | |
36 | break; |
0 | case LDA_AB: | |
1 | arg1 = NEXT_BYTE(m); | |
2 | arg2 = NEXT_BYTE(m); | |
3 | m->ac = m->mem[mem_abs(arg1, arg2, 0)]; | |
4 | set_flags(m, m->ac); | |
5 | break; | |
6 | ||
7 | case LDA_ABX: | |
8 | arg1 = NEXT_BYTE(m); | |
9 | arg2 = NEXT_BYTE(m); | |
10 | m->ac = m->mem[mem_abs(arg1, arg2, m->x)]; | |
11 | set_flags(m, m->ac); | |
12 | break; | |
13 | ||
14 | case LDA_ABY: | |
15 | arg1 = NEXT_BYTE(m); | |
16 | arg2 = NEXT_BYTE(m); | |
17 | m->ac = m->mem[mem_abs(arg1, arg2, m->y)]; | |
18 | set_flags(m, m->ac); | |
19 | break; | |
20 | ||
21 | case LDA_IMM: | |
22 | m->ac = NEXT_BYTE(m); | |
23 | set_flags(m, m->ac); | |
24 | break; | |
25 | ||
26 | case LDA_INX: | |
27 | m->ac = m->mem[mem_indexed_indirect(m, NEXT_BYTE(m), m->x)]; | |
28 | set_flags(m, m->ac); | |
29 | break; | |
30 | ||
31 | case LDA_INY: | |
32 | m->ac = m->mem[mem_indirect_index(m, NEXT_BYTE(m), m->y)]; | |
33 | set_flags(m, m->ac); | |
34 | break; | |
35 | ||
36 | case LDA_ZP: | |
37 | m->ac = m->mem[NEXT_BYTE(m)]; | |
38 | set_flags(m, m->ac); | |
39 | break; | |
40 | ||
41 | case LDA_ZPX: | |
42 | m->ac = m->mem[NEXT_BYTE(m) + m->x]; | |
43 | set_flags(m, m->ac); | |
44 | break; | |
45 | ||
46 | case LDX_AB: | |
47 | arg1 = NEXT_BYTE(m); | |
48 | arg2 = NEXT_BYTE(m); | |
49 | m->x = m->mem[mem_abs(arg1, arg2, 0)]; | |
50 | set_flags(m, m->x); | |
51 | break; | |
52 | ||
53 | case LDX_ABY: | |
54 | arg1 = NEXT_BYTE(m); | |
55 | arg2 = NEXT_BYTE(m); | |
56 | m->x = m->mem[mem_abs(arg1, arg2, m->y)]; | |
57 | set_flags(m, m->x); | |
58 | break; | |
59 | ||
60 | case LDX_IMM: | |
61 | m->x = NEXT_BYTE(m); | |
62 | set_flags(m, m->x); | |
63 | break; | |
64 | ||
65 | case LDX_ZP: | |
66 | m->x = m->mem[NEXT_BYTE(m)]; | |
67 | set_flags(m, m->x); | |
68 | break; | |
69 | ||
70 | case LDX_ZPY: | |
71 | m->x = m->mem[NEXT_BYTE(m) + m->y]; | |
72 | set_flags(m, m->x); | |
73 | break; | |
74 | ||
75 | case LDY_AB: | |
76 | arg1 = NEXT_BYTE(m); | |
77 | arg2 = NEXT_BYTE(m); | |
78 | m->y = m->mem[mem_abs(arg1, arg2, 0)]; | |
79 | set_flags(m, m->y); | |
80 | break; | |
81 | ||
82 | case LDY_ABX: | |
83 | arg1 = NEXT_BYTE(m); | |
84 | arg2 = NEXT_BYTE(m); | |
85 | m->y = m->mem[mem_abs(arg1, arg2, m->x)]; | |
86 | set_flags(m, m->y); | |
87 | break; | |
88 | ||
89 | case LDY_IMM: | |
90 | m->y = NEXT_BYTE(m); | |
91 | set_flags(m, m->y); | |
92 | break; | |
93 | ||
94 | case LDY_ZP: | |
95 | m->y = m->mem[NEXT_BYTE(m)]; | |
96 | set_flags(m, m->y); | |
97 | break; | |
98 | ||
99 | case LDY_ZPX: | |
100 | m->y = m->mem[NEXT_BYTE(m) + m->x]; | |
101 | set_flags(m, m->y); | |
102 | break; |
0 | case AND_IMM: | |
1 | m->ac &= NEXT_BYTE(m); | |
2 | set_flags(m, m->ac); | |
3 | break; | |
4 | ||
5 | case AND_ZP: | |
6 | m->ac &= m->mem[NEXT_BYTE(m)]; | |
7 | set_flags(m, m->ac); | |
8 | break; | |
9 | ||
10 | case AND_ZPX: | |
11 | m->ac &= m->mem[ZP(NEXT_BYTE(m) + m->x)]; | |
12 | set_flags(m, m->ac); | |
13 | break; | |
14 | ||
15 | case AND_AB: | |
16 | arg1 = NEXT_BYTE(m); | |
17 | arg2 = NEXT_BYTE(m); | |
18 | m->ac &= m->mem[mem_abs(arg1, arg2, 0)]; | |
19 | set_flags(m, m->ac); | |
20 | break; | |
21 | ||
22 | case AND_ABX: | |
23 | arg1 = NEXT_BYTE(m); | |
24 | arg2 = NEXT_BYTE(m); | |
25 | m->ac &= m->mem[mem_abs(arg1, arg2, m->x)]; | |
26 | set_flags(m, m->ac); | |
27 | break; | |
28 | ||
29 | case AND_ABY: | |
30 | arg1 = NEXT_BYTE(m); | |
31 | arg2 = NEXT_BYTE(m); | |
32 | m->ac &= m->mem[mem_abs(arg1, arg2, m->y)]; | |
33 | set_flags(m, m->ac); | |
34 | break; | |
35 | ||
36 | case AND_INX: | |
37 | m->ac &= m->mem[mem_indexed_indirect(m, NEXT_BYTE(m), m->x)]; | |
38 | set_flags(m, m->ac); | |
39 | break; | |
40 | ||
41 | case AND_INY: | |
42 | m->ac &= m->mem[mem_indirect_index(m, NEXT_BYTE(m), m->y)]; | |
43 | set_flags(m, m->ac); | |
44 | break; | |
45 | ||
46 | case EOR_IMM: | |
47 | m->ac ^= NEXT_BYTE(m); | |
48 | set_flags(m, m->ac); | |
49 | break; | |
50 | ||
51 | case EOR_ZP: | |
52 | m->ac ^= m->mem[NEXT_BYTE(m)]; | |
53 | set_flags(m, m->ac); | |
54 | break; | |
55 | ||
56 | case EOR_ZPX: | |
57 | m->ac ^= m->mem[ZP(NEXT_BYTE(m) + m->x)]; | |
58 | set_flags(m, m->ac); | |
59 | break; | |
60 | ||
61 | case EOR_AB: | |
62 | arg1 = NEXT_BYTE(m); | |
63 | arg2 = NEXT_BYTE(m); | |
64 | m->ac ^= m->mem[mem_abs(arg1, arg2, 0)]; | |
65 | set_flags(m, m->ac); | |
66 | break; | |
67 | ||
68 | case EOR_ABX: | |
69 | arg1 = NEXT_BYTE(m); | |
70 | arg2 = NEXT_BYTE(m); | |
71 | m->ac ^= m->mem[mem_abs(arg1, arg2, m->x)]; | |
72 | set_flags(m, m->ac); | |
73 | break; | |
74 | ||
75 | case EOR_ABY: | |
76 | arg1 = NEXT_BYTE(m); | |
77 | arg2 = NEXT_BYTE(m); | |
78 | m->ac ^= m->mem[mem_abs(arg1, arg2, m->y)]; | |
79 | set_flags(m, m->ac); | |
80 | break; | |
81 | ||
82 | case EOR_INX: | |
83 | m->ac ^= m->mem[mem_indexed_indirect(m, NEXT_BYTE(m), m->x)]; | |
84 | set_flags(m, m->ac); | |
85 | break; | |
86 | ||
87 | case EOR_INY: | |
88 | m->ac ^= m->mem[mem_indirect_index(m, NEXT_BYTE(m), m->y)]; | |
89 | set_flags(m, m->ac); | |
90 | break; | |
91 | ||
92 | case ORA_IMM: | |
93 | m->ac |= NEXT_BYTE(m); | |
94 | set_flags(m, m->ac); | |
95 | break; | |
96 | ||
97 | case ORA_ZP: | |
98 | m->ac |= m->mem[NEXT_BYTE(m)]; | |
99 | set_flags(m, m->ac); | |
100 | break; | |
101 | ||
102 | case ORA_ZPX: | |
103 | m->ac |= m->mem[ZP(NEXT_BYTE(m) + m->x)]; | |
104 | set_flags(m, m->ac); | |
105 | break; | |
106 | ||
107 | case ORA_AB: | |
108 | arg1 = NEXT_BYTE(m); | |
109 | arg2 = NEXT_BYTE(m); | |
110 | m->ac |= m->mem[mem_abs(arg1, arg2, 0)]; | |
111 | set_flags(m, m->ac); | |
112 | break; | |
113 | ||
114 | case ORA_ABX: | |
115 | arg1 = NEXT_BYTE(m); | |
116 | arg2 = NEXT_BYTE(m); | |
117 | m->ac |= m->mem[mem_abs(arg1, arg2, m->x)]; | |
118 | set_flags(m, m->ac); | |
119 | break; | |
120 | ||
121 | case ORA_ABY: | |
122 | arg1 = NEXT_BYTE(m); | |
123 | arg2 = NEXT_BYTE(m); | |
124 | m->ac |= m->mem[mem_abs(arg1, arg2, m->y)]; | |
125 | set_flags(m, m->ac); | |
126 | break; | |
127 | ||
128 | case ORA_INX: | |
129 | m->ac |= m->mem[mem_indexed_indirect(m, NEXT_BYTE(m), m->x)]; | |
130 | set_flags(m, m->ac); | |
131 | break; | |
132 | ||
133 | case ORA_INY: | |
134 | m->ac |= m->mem[mem_indirect_index(m, NEXT_BYTE(m), m->y)]; | |
135 | set_flags(m, m->ac); | |
136 | break; | |
137 | ||
138 | case BIT_AB: | |
139 | arg1 = NEXT_BYTE(m); | |
140 | arg2 = NEXT_BYTE(m); | |
141 | t1 = m->mem[mem_abs(arg1, arg2, 0)]; | |
142 | set_flag(m, FLAG_ZERO, !(t1 & m->ac)); | |
143 | set_flag(m, FLAG_OVERFLOW, t1 & 0x40); | |
144 | set_flag(m, FLAG_NEGATIVE, t1 & 0x80); | |
145 | break; | |
146 | ||
147 | case BIT_ZP: | |
148 | t1 = m->mem[NEXT_BYTE(m)]; | |
149 | set_flag(m, FLAG_ZERO, !(t1 & m->ac)); | |
150 | set_flag(m, FLAG_OVERFLOW, t1 & 0x40); | |
151 | set_flag(m, FLAG_NEGATIVE, t1 & 0x80); | |
152 | break; |
0 | case ASL_AB: | |
1 | arg1 = NEXT_BYTE(m); | |
2 | r1 = mem_abs(arg1, NEXT_BYTE(m), 0); | |
3 | set_flag(m, FLAG_CARRY, m->mem[r1] & 0x80); | |
4 | m->mem[r1] = (m->mem[r1] << 1) & 0xFE; | |
5 | set_flags(m, m->mem[r1]); | |
6 | mark_dirty(m, r1); | |
7 | break; | |
8 | ||
9 | case ASL_ABX: | |
10 | arg1 = NEXT_BYTE(m); | |
11 | r1 = mem_abs(arg1, NEXT_BYTE(m), m->x); | |
12 | set_flag(m, FLAG_CARRY, m->mem[r1] & 0x80); | |
13 | m->mem[r1] = (m->mem[r1] << 1) & 0xFE; | |
14 | set_flags(m, m->mem[r1]); | |
15 | mark_dirty(m, r1); | |
16 | break; | |
17 | ||
18 | case ASL_ACC: | |
19 | set_flag(m, FLAG_CARRY, m->ac & 0x80); | |
20 | m->ac = (m->ac << 1) & 0xFE; | |
21 | set_flags(m, m->ac); | |
22 | break; | |
23 | ||
24 | case ASL_ZP: | |
25 | arg1 = NEXT_BYTE(m); | |
26 | set_flag(m, FLAG_CARRY, m->mem[arg1] & 0x80); | |
27 | m->mem[arg1] = (m->mem[arg1] << 1) & 0xFE; | |
28 | set_flags(m, m->mem[arg1]); | |
29 | mark_dirty(m, arg1); | |
30 | break; | |
31 | ||
32 | case ASL_ZPX: | |
33 | arg1 = ZP(NEXT_BYTE(m) + m->x); | |
34 | set_flag(m, FLAG_CARRY, m->mem[arg1] & 0x80); | |
35 | m->mem[arg1] = (m->mem[arg1] << 1) & 0xFE; | |
36 | set_flags(m, m->mem[arg1]); | |
37 | mark_dirty(m, arg1); | |
38 | break; | |
39 | ||
40 | case LSR_AB: | |
41 | arg1 = NEXT_BYTE(m); | |
42 | r1 = mem_abs(arg1, NEXT_BYTE(m), 0); | |
43 | set_flag(m, FLAG_CARRY, m->mem[r1] & 0x01); | |
44 | m->mem[r1] = (m->mem[r1] >> 1) & 0x7F; | |
45 | set_flags(m, m->mem[r1]); | |
46 | mark_dirty(m, r1); | |
47 | break; | |
48 | ||
49 | case LSR_ABX: | |
50 | arg1 = NEXT_BYTE(m); | |
51 | r1 = mem_abs(arg1, NEXT_BYTE(m), m->x); | |
52 | set_flag(m, FLAG_CARRY, m->mem[r1] & 0x01); | |
53 | m->mem[r1] = (m->mem[r1] >> 1) & 0x7F; | |
54 | set_flags(m, m->mem[r1]); | |
55 | mark_dirty(m, r1); | |
56 | break; | |
57 | ||
58 | case LSR_ACC: | |
59 | set_flag(m, FLAG_CARRY, m->ac & 0x01); | |
60 | m->ac = (m->ac >> 1) & 0x7F; | |
61 | set_flags(m, m->ac); | |
62 | break; | |
63 | ||
64 | case LSR_ZP: | |
65 | arg1 = NEXT_BYTE(m); | |
66 | set_flag(m, FLAG_CARRY, m->mem[arg1] & 0x01); | |
67 | m->mem[arg1] = (m->mem[arg1] >> 1) & 0x7F; | |
68 | set_flags(m, m->mem[arg1]); | |
69 | mark_dirty(m, arg1); | |
70 | break; | |
71 | ||
72 | case LSR_ZPX: | |
73 | arg1 = ZP(NEXT_BYTE(m) + m->x); | |
74 | set_flag(m, FLAG_CARRY, m->mem[arg1] & 0x01); | |
75 | m->mem[arg1] = (m->mem[arg1] >> 1) & 0x7F; | |
76 | set_flags(m, m->mem[arg1]); | |
77 | mark_dirty(m, arg1); | |
78 | break; | |
79 | ||
80 | case ROL_AB: | |
81 | arg1 = NEXT_BYTE(m); | |
82 | r1 = mem_abs(arg1, NEXT_BYTE(m), 0); | |
83 | t1 = m->mem[r1] & 0x80; | |
84 | m->mem[r1] = ((m->mem[r1] << 1) & 0xFE) | get_flag(m, FLAG_CARRY); | |
85 | set_flag(m, FLAG_CARRY, t1); | |
86 | set_flags(m, m->mem[r1]); | |
87 | mark_dirty(m, r1); | |
88 | break; | |
89 | ||
90 | case ROL_ABX: | |
91 | arg1 = NEXT_BYTE(m); | |
92 | r1 = mem_abs(arg1, NEXT_BYTE(m), m->x); | |
93 | t1 = m->mem[r1] & 0x80; | |
94 | m->mem[r1] = ((m->mem[r1] << 1) & 0xFE) | get_flag(m, FLAG_CARRY); | |
95 | set_flag(m, FLAG_CARRY, t1); | |
96 | set_flags(m, m->mem[r1]); | |
97 | mark_dirty(m, r1); | |
98 | break; | |
99 | ||
100 | case ROL_ACC: | |
101 | t1 = m->ac & 0x80; | |
102 | m->ac = ((m->ac << 1) & 0xFE) | get_flag(m, FLAG_CARRY); | |
103 | set_flag(m, FLAG_CARRY, t1); | |
104 | set_flags(m, m->ac); | |
105 | break; | |
106 | ||
107 | case ROL_ZP: | |
108 | arg1 = NEXT_BYTE(m); | |
109 | t1 = m->mem[arg1] & 0x80; | |
110 | m->mem[arg1] = ((m->mem[arg1] << 1) & 0xFE) | get_flag(m, FLAG_CARRY); | |
111 | set_flag(m, FLAG_CARRY, t1); | |
112 | set_flags(m, m->mem[arg1]); | |
113 | mark_dirty(m, arg1); | |
114 | break; | |
115 | ||
116 | case ROL_ZPX: | |
117 | arg1 = ZP(NEXT_BYTE(m) + m->x); | |
118 | t1 = m->mem[arg1] & 0x80; | |
119 | m->mem[arg1] = ((m->mem[arg1] << 1) & 0xFE) | get_flag(m, FLAG_CARRY); | |
120 | set_flag(m, FLAG_CARRY, t1); | |
121 | set_flags(m, m->mem[arg1]); | |
122 | mark_dirty(m, arg1); | |
123 | break; | |
124 | ||
125 | case ROR_AB: | |
126 | arg1 = NEXT_BYTE(m); | |
127 | r1 = mem_abs(arg1, NEXT_BYTE(m), 0); | |
128 | t1 = m->mem[r1] & 0x01; | |
129 | m->mem[r1] = ((m->mem[r1] >> 1) & 0x7F) | (get_flag(m, FLAG_CARRY) << 7); | |
130 | set_flag(m, FLAG_CARRY, t1); | |
131 | set_flags(m, m->mem[r1]); | |
132 | mark_dirty(m, r1); | |
133 | break; | |
134 | ||
135 | case ROR_ABX: | |
136 | arg1 = NEXT_BYTE(m); | |
137 | r1 = mem_abs(arg1, NEXT_BYTE(m), m->x); | |
138 | t1 = m->mem[r1] & 0x01; | |
139 | m->mem[r1] = ((m->mem[r1] >> 1) & 0x7F) | (get_flag(m, FLAG_CARRY) << 7); | |
140 | set_flag(m, FLAG_CARRY, t1); | |
141 | set_flags(m, m->mem[r1]); | |
142 | mark_dirty(m, r1); | |
143 | break; | |
144 | ||
145 | case ROR_ACC: | |
146 | t1 = m->ac & 0x01; | |
147 | m->ac = ((m->ac >> 1) & 0x7F) | (get_flag(m, FLAG_CARRY) << 7); | |
148 | set_flag(m, FLAG_CARRY, t1); | |
149 | set_flags(m, m->ac); | |
150 | break; | |
151 | ||
152 | case ROR_ZP: | |
153 | arg1 = NEXT_BYTE(m); | |
154 | t1 = m->mem[arg1] & 0x01; | |
155 | m->mem[arg1] = ((m->mem[arg1] >> 1) & 0x7F) | (get_flag(m, FLAG_CARRY) << 7); | |
156 | set_flag(m, FLAG_CARRY, t1); | |
157 | set_flags(m, m->mem[arg1]); | |
158 | mark_dirty(m, arg1); | |
159 | break; | |
160 | ||
161 | case ROR_ZPX: | |
162 | arg1 = ZP(NEXT_BYTE(m) + m->x); | |
163 | t1 = m->mem[arg1] & 0x01; | |
164 | m->mem[arg1] = ((m->mem[arg1] >> 1) & 0x7F) | (get_flag(m, FLAG_CARRY) << 7); | |
165 | set_flag(m, FLAG_CARRY, t1); | |
166 | set_flags(m, m->mem[arg1]); | |
167 | mark_dirty(m, arg1); | |
168 | break; |
0 | case PHA: | |
1 | STACK_PUSH(m) = m->ac; | |
2 | break; | |
3 | ||
4 | case PHP: | |
5 | STACK_PUSH(m) = m->sr; | |
6 | break; | |
7 | ||
8 | case PLA: | |
9 | m->ac = STACK_POP(m); | |
10 | break; | |
11 | ||
12 | case PLP: | |
13 | m->sr = STACK_POP(m); | |
14 | break; |
0 | case STA_AB: | |
1 | arg1 = NEXT_BYTE(m); | |
2 | arg2 = NEXT_BYTE(m); | |
3 | r1 = mem_abs(arg1, arg2, 0); | |
4 | m->mem[r1] = m->ac; | |
5 | mark_dirty(m, r1); | |
6 | break; | |
7 | ||
8 | case STA_ABX: | |
9 | arg1 = NEXT_BYTE(m); | |
10 | arg2 = NEXT_BYTE(m); | |
11 | r1 = mem_abs(arg1, arg2, m->x); | |
12 | m->mem[r1] = m->ac; | |
13 | mark_dirty(m, r1); | |
14 | break; | |
15 | ||
16 | case STA_ABY: | |
17 | arg1 = NEXT_BYTE(m); | |
18 | arg2 = NEXT_BYTE(m); | |
19 | r1 = mem_abs(arg1, arg2, m->y); | |
20 | m->mem[r1] = m->ac; | |
21 | mark_dirty(m, r1); | |
22 | break; | |
23 | ||
24 | case STA_INX: | |
25 | r1 = mem_indexed_indirect(m, NEXT_BYTE(m), m->x); | |
26 | m->mem[r1] = m->ac; | |
27 | mark_dirty(m, r1); | |
28 | break; | |
29 | ||
30 | case STA_INY: | |
31 | r1 = mem_indirect_index(m, NEXT_BYTE(m), m->y); | |
32 | m->mem[r1] = m->ac; | |
33 | mark_dirty(m, r1); | |
34 | break; | |
35 | ||
36 | case STA_ZP: | |
37 | r1 = ZP(NEXT_BYTE(m)); | |
38 | m->mem[r1] = m->ac; | |
39 | mark_dirty(m, r1); | |
40 | break; | |
41 | ||
42 | case STA_ZPX: | |
43 | r1 = ZP(NEXT_BYTE(m) + m->x); | |
44 | m->mem[r1] = m->ac; | |
45 | mark_dirty(m, r1); | |
46 | break; | |
47 | ||
48 | case STX_ZP: | |
49 | r1 = ZP(NEXT_BYTE(m)); | |
50 | m->mem[r1] = m->x; | |
51 | mark_dirty(m, r1); | |
52 | break; | |
53 | ||
54 | case STX_ZPY: | |
55 | r1 = ZP(NEXT_BYTE(m) + m->y); | |
56 | m->mem[r1] = m->x; | |
57 | mark_dirty(m, r1); | |
58 | break; | |
59 | ||
60 | case STX_AB: | |
61 | arg1 = NEXT_BYTE(m); | |
62 | arg2 = NEXT_BYTE(m); | |
63 | r1 = mem_abs(arg1, arg2, 0); | |
64 | m->mem[r1] = m->x; | |
65 | mark_dirty(m, r1); | |
66 | break; | |
67 | ||
68 | case STY_ZP: | |
69 | r1 = ZP(NEXT_BYTE(m)); | |
70 | m->mem[r1] = m->y; | |
71 | mark_dirty(m, r1); | |
72 | break; | |
73 | ||
74 | case STY_ZPX: | |
75 | r1 = ZP(NEXT_BYTE(m) + m->x); | |
76 | m->mem[r1] = m->y; | |
77 | mark_dirty(m, r1); | |
78 | break; | |
79 | ||
80 | case STY_AB: | |
81 | arg1 = NEXT_BYTE(m); | |
82 | arg2 = NEXT_BYTE(m); | |
83 | r1 = mem_abs(arg1, arg2, 0); | |
84 | m->mem[r1] = m->y; | |
85 | mark_dirty(m, r1); | |
86 | break; |
0 | case TAX: | |
1 | m->x = m->ac; | |
2 | set_flags(m, m->x); | |
3 | break; | |
4 | ||
5 | case TAY: | |
6 | m->y = m->ac; | |
7 | set_flags(m, m->y); | |
8 | break; | |
9 | ||
10 | case TSX: | |
11 | m->x = m->sp; | |
12 | set_flags(m, m->x); | |
13 | break; | |
14 | ||
15 | case TXA: | |
16 | m->ac = m->x; | |
17 | set_flags(m, m->ac); | |
18 | break; | |
19 | ||
20 | case TXS: | |
21 | m->sp = m->x; | |
22 | break; | |
23 | ||
24 | case TYA: | |
25 | m->ac = m->y; | |
26 | set_flags(m, m->ac); | |
27 | break; |
0 | case ASL_AB: | |
1 | arg1 = NEXT_BYTE(m); | |
2 | r1 = mem_abs(arg1, NEXT_BYTE(m), 0); | |
3 | set_flag(m, FLAG_CARRY, m->mem[r1] & 0x80); | |
4 | m->mem[r1] = (m->mem[r1] << 1) & 0xFE; | |
5 | set_flags(m, m->mem[r1]); | |
6 | mark_dirty(m, r1); | |
7 | break; | |
8 | ||
9 | case ASL_ABX: | |
10 | arg1 = NEXT_BYTE(m); | |
11 | r1 = mem_abs(arg1, NEXT_BYTE(m), m->x); | |
12 | set_flag(m, FLAG_CARRY, m->mem[r1] & 0x80); | |
13 | m->mem[r1] = (m->mem[r1] << 1) & 0xFE; | |
14 | set_flags(m, m->mem[r1]); | |
15 | mark_dirty(m, r1); | |
16 | break; | |
17 | ||
18 | case ASL_ACC: | |
19 | set_flag(m, FLAG_CARRY, m->ac & 0x80); | |
20 | m->ac = (m->ac << 1) & 0xFE; | |
21 | set_flags(m, m->ac); | |
22 | break; | |
23 | ||
24 | case ASL_ZP: | |
25 | arg1 = NEXT_BYTE(m); | |
26 | set_flag(m, FLAG_CARRY, m->mem[arg1] & 0x80); | |
27 | m->mem[arg1] = (m->mem[arg1] << 1) & 0xFE; | |
28 | set_flags(m, m->mem[arg1]); | |
29 | mark_dirty(m, arg1); | |
30 | break; | |
31 | ||
32 | case ASL_ZPX: | |
33 | arg1 = ZP(NEXT_BYTE(m) + m->x); | |
34 | set_flag(m, FLAG_CARRY, m->mem[arg1] & 0x80); | |
35 | m->mem[arg1] = (m->mem[arg1] << 1) & 0xFE; | |
36 | set_flags(m, m->mem[arg1]); | |
37 | mark_dirty(m, arg1); | |
38 | break; | |
39 | ||
40 | case LSR_AB: | |
41 | arg1 = NEXT_BYTE(m); | |
42 | r1 = mem_abs(arg1, NEXT_BYTE(m), 0); | |
43 | set_flag(m, FLAG_CARRY, m->mem[r1] & 0x01); | |
44 | m->mem[r1] = (m->mem[r1] >> 1) & 0x7F; | |
45 | set_flags(m, m->mem[r1]); | |
46 | mark_dirty(m, r1); | |
47 | break; | |
48 | ||
49 | case LSR_ABX: | |
50 | arg1 = NEXT_BYTE(m); | |
51 | r1 = mem_abs(arg1, NEXT_BYTE(m), m->x); | |
52 | set_flag(m, FLAG_CARRY, m->mem[r1] & 0x01); | |
53 | m->mem[r1] = (m->mem[r1] >> 1) & 0x7F; | |
54 | set_flags(m, m->mem[r1]); | |
55 | mark_dirty(m, r1); | |
56 | break; | |
57 | ||
58 | case LSR_ACC: | |
59 | set_flag(m, FLAG_CARRY, m->ac & 0x01); | |
60 | m->ac = (m->ac >> 1) & 0x7F; | |
61 | set_flags(m, m->ac); | |
62 | break; | |
63 | ||
64 | case LSR_ZP: | |
65 | arg1 = NEXT_BYTE(m); | |
66 | set_flag(m, FLAG_CARRY, m->mem[arg1] & 0x01); | |
67 | m->mem[arg1] = (m->mem[arg1] >> 1) & 0x7F; | |
68 | set_flags(m, m->mem[arg1]); | |
69 | mark_dirty(m, arg1); | |
70 | break; | |
71 | ||
72 | case LSR_ZPX: | |
73 | arg1 = ZP(NEXT_BYTE(m) + m->x); | |
74 | set_flag(m, FLAG_CARRY, m->mem[arg1] & 0x01); | |
75 | m->mem[arg1] = (m->mem[arg1] >> 1) & 0x7F; | |
76 | set_flags(m, m->mem[arg1]); | |
77 | mark_dirty(m, arg1); | |
78 | break; | |
79 | ||
80 | case ROL_AB: | |
81 | arg1 = NEXT_BYTE(m); | |
82 | r1 = mem_abs(arg1, NEXT_BYTE(m), 0); | |
83 | t1 = m->mem[r1] & 0x80; | |
84 | m->mem[r1] = ((m->mem[r1] << 1) & 0xFE) | get_flag(m, FLAG_CARRY); | |
85 | set_flag(m, FLAG_CARRY, t1); | |
86 | set_flags(m, m->mem[r1]); | |
87 | mark_dirty(m, r1); | |
88 | break; | |
89 | ||
90 | case ROL_ABX: | |
91 | arg1 = NEXT_BYTE(m); | |
92 | r1 = mem_abs(arg1, NEXT_BYTE(m), m->x); | |
93 | t1 = m->mem[r1] & 0x80; | |
94 | m->mem[r1] = ((m->mem[r1] << 1) & 0xFE) | get_flag(m, FLAG_CARRY); | |
95 | set_flag(m, FLAG_CARRY, t1); | |
96 | set_flags(m, m->mem[r1]); | |
97 | mark_dirty(m, r1); | |
98 | break; | |
99 | ||
100 | case ROL_ACC: | |
101 | t1 = m->ac & 0x80; | |
102 | m->ac = ((m->ac << 1) & 0xFE) | get_flag(m, FLAG_CARRY); | |
103 | set_flag(m, FLAG_CARRY, t1); | |
104 | set_flags(m, m->ac); | |
105 | break; | |
106 | ||
107 | case ROL_ZP: | |
108 | arg1 = NEXT_BYTE(m); | |
109 | t1 = m->mem[arg1] & 0x80; | |
110 | m->mem[arg1] = ((m->mem[arg1] << 1) & 0xFE) | get_flag(m, FLAG_CARRY); | |
111 | set_flag(m, FLAG_CARRY, t1); | |
112 | set_flags(m, m->mem[arg1]); | |
113 | mark_dirty(m, arg1); | |
114 | break; | |
115 | ||
116 | case ROL_ZPX: | |
117 | arg1 = ZP(NEXT_BYTE(m) + m->x); | |
118 | t1 = m->mem[arg1] & 0x80; | |
119 | m->mem[arg1] = ((m->mem[arg1] << 1) & 0xFE) | get_flag(m, FLAG_CARRY); | |
120 | set_flag(m, FLAG_CARRY, t1); | |
121 | set_flags(m, m->mem[arg1]); | |
122 | mark_dirty(m, arg1); | |
123 | break; | |
124 | ||
125 | case ROR_AB: | |
126 | arg1 = NEXT_BYTE(m); | |
127 | r1 = mem_abs(arg1, NEXT_BYTE(m), 0); | |
128 | t1 = m->mem[r1] & 0x01; | |
129 | m->mem[r1] = ((m->mem[r1] >> 1) & 0x7F) | (get_flag(m, FLAG_CARRY) << 7); | |
130 | set_flag(m, FLAG_CARRY, t1); | |
131 | set_flags(m, m->mem[r1]); | |
132 | mark_dirty(m, r1); | |
133 | break; | |
134 | ||
135 | case ROR_ABX: | |
136 | arg1 = NEXT_BYTE(m); | |
137 | r1 = mem_abs(arg1, NEXT_BYTE(m), m->x); | |
138 | t1 = m->mem[r1] & 0x01; | |
139 | m->mem[r1] = ((m->mem[r1] >> 1) & 0x7F) | (get_flag(m, FLAG_CARRY) << 7); | |
140 | set_flag(m, FLAG_CARRY, t1); | |
141 | set_flags(m, m->mem[r1]); | |
142 | mark_dirty(m, r1); | |
143 | break; | |
144 | ||
145 | case ROR_ACC: | |
146 | t1 = m->ac & 0x01; | |
147 | m->ac = ((m->ac >> 1) & 0x7F) | (get_flag(m, FLAG_CARRY) << 7); | |
148 | set_flag(m, FLAG_CARRY, t1); | |
149 | set_flags(m, m->ac); | |
150 | break; | |
151 | ||
152 | case ROR_ZP: | |
153 | arg1 = NEXT_BYTE(m); | |
154 | t1 = m->mem[arg1] & 0x01; | |
155 | m->mem[arg1] = ((m->mem[arg1] >> 1) & 0x7F) | (get_flag(m, FLAG_CARRY) << 7); | |
156 | set_flag(m, FLAG_CARRY, t1); | |
157 | set_flags(m, m->mem[arg1]); | |
158 | mark_dirty(m, arg1); | |
159 | break; | |
160 | ||
161 | case ROR_ZPX: | |
162 | arg1 = ZP(NEXT_BYTE(m) + m->x); | |
163 | t1 = m->mem[arg1] & 0x01; | |
164 | m->mem[arg1] = ((m->mem[arg1] >> 1) & 0x7F) | (get_flag(m, FLAG_CARRY) << 7); | |
165 | set_flag(m, FLAG_CARRY, t1); | |
166 | set_flags(m, m->mem[arg1]); | |
167 | mark_dirty(m, arg1); | |
168 | break; |
0 | case PHA: | |
1 | STACK_PUSH(m) = m->ac; | |
2 | break; | |
3 | ||
4 | case PHP: | |
5 | STACK_PUSH(m) = m->sr; | |
6 | break; | |
7 | ||
8 | case PLA: | |
9 | m->ac = STACK_POP(m); | |
10 | break; | |
11 | ||
12 | case PLP: | |
13 | m->sr = STACK_POP(m); | |
14 | break; |
0 | case STA_AB: | |
1 | arg1 = NEXT_BYTE(m); | |
2 | arg2 = NEXT_BYTE(m); | |
3 | r1 = mem_abs(arg1, arg2, 0); | |
4 | m->mem[r1] = m->ac; | |
5 | mark_dirty(m, r1); | |
6 | break; | |
7 | ||
8 | case STA_ABX: | |
9 | arg1 = NEXT_BYTE(m); | |
10 | arg2 = NEXT_BYTE(m); | |
11 | r1 = mem_abs(arg1, arg2, m->x); | |
12 | m->mem[r1] = m->ac; | |
13 | mark_dirty(m, r1); | |
14 | break; | |
15 | ||
16 | case STA_ABY: | |
17 | arg1 = NEXT_BYTE(m); | |
18 | arg2 = NEXT_BYTE(m); | |
19 | r1 = mem_abs(arg1, arg2, m->y); | |
20 | m->mem[r1] = m->ac; | |
21 | mark_dirty(m, r1); | |
22 | break; | |
23 | ||
24 | case STA_INX: | |
25 | r1 = mem_indexed_indirect(m, NEXT_BYTE(m), m->x); | |
26 | m->mem[r1] = m->ac; | |
27 | mark_dirty(m, r1); | |
28 | break; | |
29 | ||
30 | case STA_INY: | |
31 | r1 = mem_indirect_index(m, NEXT_BYTE(m), m->y); | |
32 | m->mem[r1] = m->ac; | |
33 | mark_dirty(m, r1); | |
34 | break; | |
35 | ||
36 | case STA_ZP: | |
37 | r1 = ZP(NEXT_BYTE(m)); | |
38 | m->mem[r1] = m->ac; | |
39 | mark_dirty(m, r1); | |
40 | break; | |
41 | ||
42 | case STA_ZPX: | |
43 | r1 = ZP(NEXT_BYTE(m) + m->x); | |
44 | m->mem[r1] = m->ac; | |
45 | mark_dirty(m, r1); | |
46 | break; | |
47 | ||
48 | case STX_ZP: | |
49 | r1 = ZP(NEXT_BYTE(m)); | |
50 | m->mem[r1] = m->x; | |
51 | mark_dirty(m, r1); | |
52 | break; | |
53 | ||
54 | case STX_ZPY: | |
55 | r1 = ZP(NEXT_BYTE(m) + m->y); | |
56 | m->mem[r1] = m->x; | |
57 | mark_dirty(m, r1); | |
58 | break; | |
59 | ||
60 | case STX_AB: | |
61 | arg1 = NEXT_BYTE(m); | |
62 | arg2 = NEXT_BYTE(m); | |
63 | r1 = mem_abs(arg1, arg2, 0); | |
64 | m->mem[r1] = m->x; | |
65 | mark_dirty(m, r1); | |
66 | break; | |
67 | ||
68 | case STY_ZP: | |
69 | r1 = ZP(NEXT_BYTE(m)); | |
70 | m->mem[r1] = m->y; | |
71 | mark_dirty(m, r1); | |
72 | break; | |
73 | ||
74 | case STY_ZPX: | |
75 | r1 = ZP(NEXT_BYTE(m) + m->x); | |
76 | m->mem[r1] = m->y; | |
77 | mark_dirty(m, r1); | |
78 | break; | |
79 | ||
80 | case STY_AB: | |
81 | arg1 = NEXT_BYTE(m); | |
82 | arg2 = NEXT_BYTE(m); | |
83 | r1 = mem_abs(arg1, arg2, 0); | |
84 | m->mem[r1] = m->y; | |
85 | mark_dirty(m, r1); | |
86 | break; |
0 | case TAX: | |
1 | m->x = m->ac; | |
2 | set_flags(m, m->x); | |
3 | break; | |
4 | ||
5 | case TAY: | |
6 | m->y = m->ac; | |
7 | set_flags(m, m->y); | |
8 | break; | |
9 | ||
10 | case TSX: | |
11 | m->x = m->sp; | |
12 | set_flags(m, m->x); | |
13 | break; | |
14 | ||
15 | case TXA: | |
16 | m->ac = m->x; | |
17 | set_flags(m, m->ac); | |
18 | break; | |
19 | ||
20 | case TXS: | |
21 | m->sp = m->x; | |
22 | break; | |
23 | ||
24 | case TYA: | |
25 | m->ac = m->y; | |
26 | set_flags(m, m->ac); | |
27 | break; |