OXYGENHUB
◆ riscv-1 x16-emulator / src / cpu / modes.h
6.7 KiB · Objective-C · last changed chore(): initial commit 15 days ago source blame history raw
03a3459e Andy McCall 1
/*
2
3
						Extracted from original single fake6502.c file
4
5
*/
6
7
//
8
//          65C02 changes.
9
//
10
//          ind         absolute indirect
11
//
12
//                      A 6502 has a bug whereby if you jmp ($12FF) it reads the address from
13
//                      $12FF and $1200. This has been fixed in the 65C02.
14
//
15
static void imp() { //implied
16
}
17
18
static void imp8() { // brk / cop
19
}
20
21
static void acc() { //accumulator
22
}
23
24
static void imm8() { //immediate, 8bit
25
    ea = regs.pc++;
26
}
27
28
static void immm() { //immediate, 16bit if M = 0
29
    ea = regs.pc++;
30
31
    if (memory_16bit()) {
32
        regs.pc++;
33
    }
34
}
35
36
static void immx() { //immediate, 16bit if M = 0
37
    ea = regs.pc++;
38
39
    if (index_16bit()) {
40
        regs.pc++;
41
    }
42
}
43
44
static void imm16() {
45
    ea = regs.pc;
46
    regs.pc += 2;
47
}
48
49
static void _zp_with_offset(uint16_t offset) {
50
    uint16_t imm_value = (uint16_t) read6502((uint16_t)regs.pc++, regs.k);
51
52
    if (regs.dp & 0x00FF) {
53
        penaltyd = 1;
54
    }
55
56
    ea = direct_page_add(imm_value + offset);
57
}
58
59
static void _zp_long_with_offset(uint16_t offset) {
60
    uint16_t eahelp;
61
    eahelp = (uint16_t)read6502(regs.pc++, regs.k);
62
63
    ea = (uint16_t)read6502(regs.dp + eahelp, regs.k) | ((uint16_t)read6502(regs.dp + eahelp + 1, regs.k) << 8) | ((uint16_t)read6502(regs.dp + eahelp + 2, regs.k) << 16);
64
    ea = mask_long_addr(ea + offset);
65
66
    if (regs.dp & 0x00FF) {
67
        penaltyd = 1;
68
    }
69
}
70
71
static void zp() { //zero-page
72
    _zp_with_offset(0);
73
}
74
75
static void zpx() { //zero-page,X
76
    _zp_with_offset(regs.x);
77
}
78
79
static void zpy() { //zero-page,Y
80
    _zp_with_offset(regs.y);
81
}
82
83
static void rel() { //relative for branch ops (8-bit immediate value, sign-extended)
84
    reladdr = (uint16_t)read6502(regs.pc++, regs.k);
85
    if (reladdr & 0x80) reladdr |= 0xFF00;
86
}
87
88
static void rel16() { //relative for PER and BRL (16-bit immediate value)
89
    reladdr = (uint16_t)read6502(regs.pc, regs.k) | ((uint16_t)read6502(regs.pc+1, regs.k) << 8);
90
    regs.pc += 2;
91
}
92
93
static void abso() { //absolute
94
    ea = addr_with_db((uint16_t) read6502(regs.pc, regs.k) | ((uint16_t)read6502(regs.pc+1, regs.k) << 8));
95
    regs.pc += 2;
96
}
97
98
static void absl() { // absolute long
99
    ea = (uint32_t) read6502(regs.pc, regs.k) | ((uint32_t)read6502(regs.pc+1, regs.k) << 8) | ((uint32_t)read6502(regs.pc+2, regs.k) << 16);
100
    regs.pc += 3;
101
}
102
103
static void absx() { //absolute,X
104
    uint16_t startpage;
105
    ea = addr_with_db((uint16_t)read6502(regs.pc, regs.k) | ((uint16_t)read6502(regs.pc+1, regs.k) << 8));
106
    startpage = ea & 0xFF00;
107
    ea = mask_long_addr(ea + regs.x);
108
109
    if (startpage != (ea & 0xFF00)) { //one cycle penlty for page-crossing on some opcodes
110
        penaltyaddr = 1;
111
    }
112
113
    regs.pc += 2;
114
}
115
116
static void abslx() { // absolute long, X
117
    uint16_t startpage;
118
    ea = (uint32_t)read6502(regs.pc, regs.k) | ((uint32_t)read6502(regs.pc+1, regs.k) << 8) | ((uint32_t)read6502(regs.pc+2, regs.k) << 16);
119
    startpage = ea & 0xFF00;
120
    ea = mask_long_addr(ea + regs.x);
121
122
    if (startpage != (ea & 0xFF00)) { //one cycle penlty for page-crossing on some opcodes
123
        penaltyaddr = 1;
124
    }
125
126
    regs.pc += 3;
127
}
128
129
static void absy() { //absolute,Y
130
    uint16_t startpage;
131
    ea = addr_with_db((uint16_t)read6502(regs.pc, regs.k) | ((uint16_t)read6502(regs.pc+1, regs.k) << 8));
132
    startpage = ea & 0xFF00;
133
    ea = mask_long_addr(ea + regs.y);
134
135
    if (startpage != (ea & 0xFF00)) { //one cycle penlty for page-crossing on some opcodes
136
        penaltyaddr = 1;
137
    }
138
139
    regs.pc += 2;
140
}
141
142
static void ind() { //indirect - used for jmp, which assumes the pointer is in bank 0!
143
    uint16_t eahelp, eahelp2;
144
    eahelp = (uint16_t)read6502(regs.pc, regs.k) | (uint16_t)((uint16_t)read6502(regs.pc+1, regs.k) << 8);
145
    //
146
    //      The 6502 page boundary wraparound bug does not occur on a 65C02.
147
    //
148
    //eahelp2 = (eahelp & 0xFF00) | ((eahelp + 1) & 0x00FF); //replicate 6502 page-boundary wraparound bug
149
    eahelp2 = (eahelp+1) & 0xFFFF;
150
    ea = (uint16_t)read6502(eahelp, 0) | ((uint16_t)read6502(eahelp2, 0) << 8);
151
    regs.pc += 2;
152
}
153
154
static void aindl() { // [addr]    uint16_t eahelp, eahelp2;
155
    uint16_t eahelp, eahelp2;
156
    eahelp = (uint16_t)read6502(regs.pc, regs.k) | (uint16_t)((uint16_t)read6502(regs.pc+1, regs.k) << 8);
157
    eahelp2 = (eahelp+1) & 0xFFFF;
158
    ea = (uint32_t)read6502(eahelp, 0) | ((uint32_t)read6502(eahelp2, 0) << 8) | ((uint16_t)read6502((eahelp2 + 1) & 0xFFFF, 0) << 16);
159
    regs.pc += 2;
160
}
161
162
static void ind0() { // (zp)
163
    uint16_t eahelp;
164
    eahelp = (uint16_t)read6502(regs.pc++, regs.k);
165
    ea = (uint16_t)read6502(direct_page_add(eahelp), 0) | ((uint16_t)read6502(direct_page_add(eahelp + 1), 0) << 8);
166
167
    if (regs.dp & 0x00FF) {
168
        penaltyd = 1;
169
    }
170
}
171
172
static void indl0() { // [dp]
173
    _zp_long_with_offset(0);
174
}
175
176
static void indx() { // (indirect,X)
177
    uint16_t eahelp;
178
    eahelp = (uint16_t)read6502(regs.pc++, regs.k) + regs.x;
179
    ea = (uint16_t)read6502(direct_page_add(eahelp), 0) | ((uint16_t)read6502(direct_page_add(eahelp + 1), 0) << 8);
180
181
    if (regs.dp & 0x00FF) {
182
        penaltyd = 1;
183
    }
184
}
185
186
static void indy() { // (indirect),Y
187
    uint16_t eahelp, startpage;
188
    eahelp = (uint16_t)read6502(regs.pc++, regs.k);
189
    ea = (uint16_t)read6502(direct_page_add(eahelp), 0) | ((uint16_t)read6502(direct_page_add(eahelp + 1), 0) << 8);
190
    startpage = ea & 0xFF00;
191
    ea += regs.y;
192
193
    if (regs.dp & 0x00FF) {
194
        penaltyd = 1;
195
    }
196
197
    if (startpage != (ea & 0xFF00)) { //one cycle penlty for page-crossing on some opcodes
198
        penaltyaddr = 1;
199
    }
200
}
201
202
static void indly() { // [dp],Y
203
    _zp_long_with_offset(regs.y);
204
}
205
206
static void ind0p() { // (zp) used by PEI, which doesn't do wraparound calculations
207
    uint16_t eahelp;
208
    eahelp = (uint16_t)read6502(regs.pc++, regs.k);
209
    ea = (uint16_t)read6502(regs.dp + eahelp, 0) | ((uint16_t)read6502(regs.dp + eahelp + 1, 0) << 8);
210
211
    if (regs.dp & 0x00FF) {
212
        penaltyd = 1;
213
    }
214
}
215
216
static void zprel() { // zero-page, relative for branch ops (8-bit immediatel value, sign-extended) - only used for the 65C02's Rockwell extensions
217
	ea = (uint16_t)read6502(regs.pc, 0);
218
	reladdr = (uint16_t)read6502(regs.pc+1, 0);
219
	if (reladdr & 0x80) reladdr |= 0xFF00;
220
221
	regs.pc += 2;
222
}
223
224
static void sr() { // absolute,S
225
    ea = regs.sp + (uint16_t)read6502(regs.pc++, regs.k);
226
}
227
228
static void sridy() { // (indirect,S),Y
229
    uint16_t eahelp, startpage;
230
    eahelp = regs.sp + (uint16_t)read6502(regs.pc++, regs.k);
231
    ea = (uint16_t)read6502(eahelp, 0) | ((uint16_t)read6502(eahelp + 1, 0) << 8);
232
    startpage = ea & 0xFF00;
233
    ea += (uint16_t)regs.y;
234
235
    if (startpage != (ea & 0xFF00)) { //one cycle penlty for page-crossing on some opcodes
236
        penaltyaddr = 1;
237
    }
238
}
239
240
static void bmv() { // block move
241
    uint8_t dest = read6502(regs.pc++, regs.k);
242
    ea = (read6502(regs.pc++, regs.k) << 8) | dest;
243
}