-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathaddressingmodes.cpp
153 lines (141 loc) · 3.54 KB
/
addressingmodes.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
#include "system.h"
/*
* This file includes function for the various addressing modes used by the 6502
* http://www.emulator101.com/6502-addressing-modes.html
* http://www.obelisk.me.uk/6502/addressing.html
* https://www.youtube.com/watch?v=kk0aW_p8EeE
*
* These functions will resolve the addressing mode to the final address
* All functions in this file have the same inputs and outputs:
* Take arguments of cpu and memory pointers
* We assume that the pc is pointing at the current opcode
* return resolution of final address of data
*
* We must return the final address because some instructions read and write from a memory location
* with one addressing mode, but don't for another (e.g. accumulator, immediate)
*
* todo: double check these, unit test
* todo: update cycle count for every memory access
*/
/**
* immediate addressing is passing the value specified in code, a constant
* Return the 16 bit address of the constant
*/
uint16_t immediate(cpustate * cpu)
{
cpu->pc++;
return cpu->pc;
}
/**
* Return 8 bit address from ROM
* @param cpu
* @param mem
* @return
*/
uint8_t zeropage(cpustate * cpu, Memory * mem)
{
cpu->pc++;
uint8_t finaladdr = mem->readmem(cpu->pc);
return finaladdr;
}
/**
* Return full 16 bit address from ROM
* @param cpu
* @param mem
* @return
*/
uint16_t absolute(cpustate * cpu, Memory * mem)
{
cpu->pc+=2;
return revlendianbytes(mem->readmem(cpu->pc-1), mem->readmem(cpu->pc));
}
/**
* Return zero page address offset by x
* @param cpu
* @param mem
* @return
*/
uint8_t zeropagex(cpustate * cpu, Memory * mem)
{
cpu->pc++;
return mem->readmem(cpu->pc)+cpu->x;
}
/**
* Return zero page address offset by y
* @param cpu
* @param mem
* @return
*/
uint8_t zeropagey(cpustate * cpu, Memory * mem)
{
cpu->pc++;
return mem->readmem(cpu->pc)+cpu->y;
}
/**
* (Indirect,X) aka (zero page,X)
* The address of the table is taken from the instruction and the X register added to it (with zero page wrap around)
* to give the location of the least significant byte of the target address.
* @param cpu
* @param mem
* @return Final resolved address
*/
uint16_t indexedindirect(cpustate * cpu, Memory * mem)
{
cpu->pc++;
uint8_t zpageaddr = mem->readmem(cpu->pc);
uint16_t addr = zpageaddr + cpu->x;
uint16_t finaladdr = revlendianbytes(mem->readmem(addr), mem->readmem(addr+1));
return finaladdr;
}
/**
* (Indirect),Y aka (zero page),Y
* Y is added to final address at very end
* @param cpu
* @param mem
* @return Final resolved address
*/
uint16_t indirectindexed(cpustate * cpu, Memory * mem)
{
cpu->pc++;
uint8_t zpageaddr = mem->readmem(cpu->pc);
uint16_t addr = (revlendianbytes(mem->readmem(zpageaddr), mem->readmem(zpageaddr+1))) + cpu->y;
return addr;
}
/**
* Return absolute address offset by y
* @param cpu
* @param mem
* @return
*/
uint16_t absolutey(cpustate * cpu, Memory * mem)
{
cpu->pc+=2;
uint16_t addr = revlendianbytes(mem->readmem(cpu->pc-1), mem->readmem(cpu->pc));
addr += cpu->y;
return addr;
}
/**
* Return absolute address offset by x
* @param cpu
* @param mem
* @return
*/
uint16_t absolutex(cpustate * cpu, Memory * mem)
{
cpu->pc+=2;
uint16_t addr = revlendianbytes(mem->readmem(cpu->pc-1), mem->readmem(cpu->pc));
addr += cpu->x;
return addr;
}
/**
* Relative addressing
* used for branch instructions
* @param cpu
* @param mem
* @return
*/
uint16_t relative(cpustate * cpu, Memory * mem)
{
cpu->pc += 1;
return cpu->pc + decode_twos_comp(mem->readmem(cpu->pc));
}