1
//============================================================================
3
// MM MM 6666 555555 0000 2222
4
// MMMM MMMM 66 66 55 00 00 22 22
5
// MM MMM MM 66 55 00 00 22
6
// MM M MM 66666 55555 00 00 22222 -- "A 6502 Microprocessor Emulator"
7
// MM MM 66 66 55 00 00 22
8
// MM MM 66 66 55 55 00 00 22
9
// MM MM 6666 5555 0000 222222
11
// Copyright (c) 1995-2005 by Bradford W. Mott and the Stella team
13
// See the file "license" for information on usage and redistribution of
14
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
16
// $Id: M6502Low.m4,v 1.4 2006/02/05 02:49:47 stephena Exp $
17
//============================================================================
20
Code to handle addressing modes and branch instructions for
21
low compatibility emulation
23
@author Bradford W. Mott
24
@version $Id: M6502Low.m4,v 1.4 2006/02/05 02:49:47 stephena Exp $
28
#define NOTSAMEPAGE(_addr1, _addr2) (((_addr1) ^ (_addr2)) & 0xff00)
31
define(M6502_IMPLIED, `{
34
define(M6502_IMMEDIATE_READ, `{
35
operandAddress = PC++;
36
operand = peek(operandAddress);
39
define(M6502_ABSOLUTE_READ, `{
40
operandAddress = (uInt16)peek(PC) | ((uInt16)peek(PC + 1) << 8);
42
operand = peek(operandAddress);
45
define(M6502_ABSOLUTE_WRITE, `{
46
operandAddress = (uInt16)peek(PC) | ((uInt16)peek(PC + 1) << 8);
50
define(M6502_ABSOLUTE_READMODIFYWRITE, `{
51
operandAddress = (uInt16)peek(PC) | ((uInt16)peek(PC + 1) << 8);
53
operand = peek(operandAddress);
56
define(M6502_ABSOLUTEX_READ, `{
57
operandAddress = (uInt16)peek(PC) | ((uInt16)peek(PC + 1) << 8);
60
// See if we need to add one cycle for indexing across a page boundary
61
if(NOTSAMEPAGE(operandAddress, operandAddress + X))
63
mySystem->incrementCycles(mySystemCyclesPerProcessorCycle);
67
operand = peek(operandAddress);
70
define(M6502_ABSOLUTEX_WRITE, `{
71
operandAddress = (uInt16)peek(PC) | ((uInt16)peek(PC + 1) << 8);
76
define(M6502_ABSOLUTEX_READMODIFYWRITE, `{
77
operandAddress = (uInt16)peek(PC) | ((uInt16)peek(PC + 1) << 8);
80
operand = peek(operandAddress);
83
define(M6502_ABSOLUTEY_READ, `{
84
operandAddress = (uInt16)peek(PC) | ((uInt16)peek(PC + 1) << 8);
87
// See if we need to add one cycle for indexing across a page boundary
88
if(NOTSAMEPAGE(operandAddress, operandAddress + Y))
90
mySystem->incrementCycles(mySystemCyclesPerProcessorCycle);
94
operand = peek(operandAddress);
97
define(M6502_ABSOLUTEY_WRITE, `{
98
operandAddress = (uInt16)peek(PC) | ((uInt16)peek(PC + 1) << 8);
103
define(M6502_ABSOLUTEY_READMODIFYWRITE, `{
104
operandAddress = (uInt16)peek(PC) | ((uInt16)peek(PC + 1) << 8);
107
operand = peek(operandAddress);
110
define(M6502_ZERO_READ, `{
111
operandAddress = peek(PC++);
112
operand = peek(operandAddress);
115
define(M6502_ZERO_WRITE, `{
116
operandAddress = peek(PC++);
119
define(M6502_ZERO_READMODIFYWRITE, `{
120
operandAddress = peek(PC++);
121
operand = peek(operandAddress);
124
define(M6502_ZEROX_READ, `{
125
operandAddress = (uInt8)(peek(PC++) + X);
126
operand = peek(operandAddress);
129
define(M6502_ZEROX_WRITE, `{
130
operandAddress = (uInt8)(peek(PC++) + X);
133
define(M6502_ZEROX_READMODIFYWRITE, `{
134
operandAddress = (uInt8)(peek(PC++) + X);
135
operand = peek(operandAddress);
138
define(M6502_ZEROY_READ, `{
139
operandAddress = (uInt8)(peek(PC++) + Y);
140
operand = peek(operandAddress);
143
define(M6502_ZEROY_WRITE, `{
144
operandAddress = (uInt8)(peek(PC++) + Y);
147
define(M6502_ZEROY_READMODIFYWRITE, `{
148
operandAddress = (uInt8)(peek(PC++) + Y);
149
operand = peek(operandAddress);
152
define(M6502_INDIRECT, `{
153
uInt16 addr = peek(PC) | ((uInt16)peek(PC + 1) << 8);
156
// Simulate the error in the indirect addressing mode!
157
uInt16 high = NOTSAMEPAGE(addr, addr + 1) ? (addr & 0xff00) : (addr + 1);
159
operandAddress = peek(addr) | ((uInt16)peek(high) << 8);
162
define(M6502_INDIRECTX_READ, `{
163
uInt8 pointer = peek(PC++) + X;
164
operandAddress = peek(pointer) | ((uInt16)peek(pointer + 1) << 8);
165
operand = peek(operandAddress);
168
define(M6502_INDIRECTX_WRITE, `{
169
uInt8 pointer = peek(PC++) + X;
170
operandAddress = peek(pointer) | ((uInt16)peek(pointer + 1) << 8);
173
define(M6502_INDIRECTX_READMODIFYWRITE, `{
174
uInt8 pointer = peek(PC++) + X;
175
operandAddress = peek(pointer) | ((uInt16)peek(pointer + 1) << 8);
176
operand = peek(operandAddress);
179
define(M6502_INDIRECTY_READ, `{
180
uInt8 pointer = peek(PC++);
181
operandAddress = (uInt16)peek(pointer) | ((uInt16)peek(pointer + 1) << 8);
183
if(NOTSAMEPAGE(operandAddress, operandAddress + Y))
185
mySystem->incrementCycles(mySystemCyclesPerProcessorCycle);
189
operand = peek(operandAddress);
192
define(M6502_INDIRECTY_WRITE, `{
193
uInt8 pointer = peek(PC++);
194
operandAddress = (uInt16)peek(pointer) | ((uInt16)peek(pointer + 1) << 8);
198
define(M6502_INDIRECTY_READMODIFYWRITE, `{
199
uInt8 pointer = peek(PC++);
200
operandAddress = (uInt16)peek(pointer) | ((uInt16)peek(pointer + 1) << 8);
202
operand = peek(operandAddress);
209
uInt16 address = PC + (Int8)operand;
210
mySystem->incrementCycles(NOTSAMEPAGE(PC, address) ?
211
mySystemCyclesPerProcessorCycle << 1 : mySystemCyclesPerProcessorCycle);
219
uInt16 address = PC + (Int8)operand;
220
mySystem->incrementCycles(NOTSAMEPAGE(PC, address) ?
221
mySystemCyclesPerProcessorCycle << 1 : mySystemCyclesPerProcessorCycle);
229
uInt16 address = PC + (Int8)operand;
230
mySystem->incrementCycles(NOTSAMEPAGE(PC, address) ?
231
mySystemCyclesPerProcessorCycle << 1 : mySystemCyclesPerProcessorCycle);
239
uInt16 address = PC + (Int8)operand;
240
mySystem->incrementCycles(NOTSAMEPAGE(PC, address) ?
241
mySystemCyclesPerProcessorCycle << 1 : mySystemCyclesPerProcessorCycle);
249
uInt16 address = PC + (Int8)operand;
250
mySystem->incrementCycles(NOTSAMEPAGE(PC, address) ?
251
mySystemCyclesPerProcessorCycle << 1 : mySystemCyclesPerProcessorCycle);
259
uInt16 address = PC + (Int8)operand;
260
mySystem->incrementCycles(NOTSAMEPAGE(PC, address) ?
261
mySystemCyclesPerProcessorCycle << 1 : mySystemCyclesPerProcessorCycle);
269
uInt16 address = PC + (Int8)operand;
270
mySystem->incrementCycles(NOTSAMEPAGE(PC, address) ?
271
mySystemCyclesPerProcessorCycle << 1 : mySystemCyclesPerProcessorCycle);
279
uInt16 address = PC + (Int8)operand;
280
mySystem->incrementCycles(NOTSAMEPAGE(PC, address) ?
281
mySystemCyclesPerProcessorCycle << 1 : mySystemCyclesPerProcessorCycle);