OXYGENHUB
# 8e8d9cad1884 x16-emulator / src / cpu / support.h
5.4 KiB · Objective-C · last changed chore(): initial commit 15 days ago source blame history raw
1
/*
2
3
						Extracted from original single fake6502.c file
4
5
*/
6
7
8
//flag modifier macros
9
#define setcarry() regs.status |= FLAG_CARRY
10
#define clearcarry() regs.status &= (~FLAG_CARRY)
11
#define setzero() regs.status |= FLAG_ZERO
12
#define clearzero() regs.status &= (~FLAG_ZERO)
13
#define setinterrupt() regs.status |= FLAG_INTERRUPT
14
#define clearinterrupt() regs.status &= (~FLAG_INTERRUPT)
15
#define setdecimal() regs.status |= FLAG_DECIMAL
16
#define cleardecimal() regs.status &= (~FLAG_DECIMAL)
17
#define setoverflow() regs.status |= FLAG_OVERFLOW
18
#define clearoverflow() regs.status &= (~FLAG_OVERFLOW)
19
#define setsign() regs.status |= FLAG_SIGN
20
#define clearsign() regs.status &= (~FLAG_SIGN)
21
22
23
//flag calculation macros
24
#define zerocalc(n, use16Bit) {\
25
    if (use16Bit) \
26
        if ((n) & 0xFFFF) clearzero();\
27
            else setzero();\
28
    else if ((n) & 0x00FF) clearzero();\
29
        else setzero();\
30
}
31
32
#define signcalc(n, use16Bit) {\
33
    if (use16Bit) \
34
        if ((n) & 0x8000) setsign();\
35
            else clearsign();\
36
    else if ((n) & 0x0080) setsign();\
37
        else clearsign();\
38
}
39
40
#define carrycalc(n, use16Bit) {\
41
    if (use16Bit) \
42
        if ((n) & 0x10000) setcarry();\
43
            else clearcarry();\
44
    else if ((n) & 0x0100) setcarry();\
45
        else clearcarry();\
46
}
47
48
#define overflowcalc8(n, m, o) { /* n = result, m = accumulator, o = memory */ \
49
    if (((n) ^ (m)) & ((n) ^ (o)) & 0x80) setoverflow();\
50
        else clearoverflow();\
51
}
52
53
#define overflowcalc16(n, m, o) { /* n = result, m = accumulator, o = memory */ \
54
    if (((n) ^ (m)) & ((n) ^ (o)) & 0x8000) setoverflow();\
55
        else clearoverflow();\
56
}
57
58
#define index_16bit() (regs.is65c816 && !(regs.status & FLAG_INDEX_WIDTH))
59
#define memory_16bit() (regs.is65c816 && !(regs.status & FLAG_MEMORY_WIDTH))
60
#define acc_for_mode() (memory_16bit() ? regs.c : ((uint16_t) regs.a))
61
62
63
#define saveaccum(n) (memory_16bit() ? (regs.c = (n)) : (regs.a = (uint8_t)((n) & 0x00FF)))
64
65
#define mask_long_addr(addr) ((addr) & 0xFFFFFF)
66
#define as_bank_byte(b) ((uint32_t) (((uint8_t) (b)) << 16))
67
#define bank_byte(b) ((uint8_t) ((b) >> 16))
68
69
//a few general functions used by various other functions
70
71
uint16_t add_wrap_at_page_boundary(uint16_t value, uint8_t add) {
72
    if (regs.e) {
73
        return (value & 0xFF00) | ((uint16_t) (((uint8_t) (value & 0x00FF)) + add) & 0x00FF);
74
    } else {
75
        return value + add;
76
    }
77
}
78
79
uint16_t subtract_wrap_at_page_boundary(uint16_t value, uint8_t subtract) {
80
    if (regs.e) {
81
        return (value & 0xFF00) | ((uint16_t) (((uint8_t) (value & 0x00FF)) - subtract) & 0x00FF);
82
    } else {
83
        return value - subtract;
84
    }
85
}
86
87
void increment_wrap_at_page_boundary(uint16_t *value) {
88
    if (regs.e) {
89
        *value = (*value & 0xFF00) | ((uint16_t) (((uint8_t) (*value & 0x00FF)) + 1) & 0x00FF);
90
    } else {
91
        (*value)++;
92
    }
93
}
94
95
void decrement_wrap_at_page_boundary(uint16_t *value) {
96
    if (regs.e) {
97
        *value = (*value & 0xFF00) | ((uint16_t) (((uint8_t) (*value & 0x00FF)) - 1) & 0x00FF);
98
    } else {
99
        (*value)--;
100
    }
101
}
102
103
uint16_t direct_page_add(uint16_t offset) {
104
    if (regs.e && (regs.dp & 0x00FF) == 0) {
105
        return (regs.dp & 0xFF00) | ((uint16_t) ((uint8_t) (regs.dp & 0x00FF)) + (offset & 0xFF));
106
    } else {
107
        return regs.dp + offset;
108
    }
109
}
110
111
#define incsp() increment_wrap_at_page_boundary(&regs.sp)
112
#define decsp() decrement_wrap_at_page_boundary(&regs.sp)
113
114
void push16(uint16_t pushval) {
115
    write6502(regs.sp, 0, (pushval >> 8) & 0xFF);
116
    decsp();
117
    write6502(regs.sp, 0, pushval & 0xFF);
118
    decsp();
119
}
120
121
void push8(uint8_t pushval) {
122
    write6502(regs.sp, 0, pushval);
123
    decsp();
124
}
125
126
uint16_t pull16() {
127
    incsp();
128
    uint16_t temp16 = read6502(regs.sp, 0);
129
    incsp();
130
    temp16 |= (uint16_t) read6502(regs.sp, 0) << 8;
131
    return temp16;
132
}
133
134
uint8_t pull8() {
135
    incsp();
136
    uint8_t value = read6502(regs.sp, 0);
137
    return value;
138
}
139
140
void reset6502(bool c816) {
141
    regs.pc = (uint16_t)read6502(0xFFFC, 0) | ((uint16_t)read6502(0xFFFD, 0) << 8);
142
    regs.c = 0;
143
    regs.x = 0;
144
    regs.y = 0;
145
    regs.dp = 0;
146
    regs.sp = 0x1FD;
147
    regs.e = 1;
148
    regs.k = 0;
149
    regs.db = 0;
150
    if (c816) {
151
        regs.status |= FLAG_INDEX_WIDTH | FLAG_MEMORY_WIDTH;
152
        regs.is65c816 = true;
153
        ticktable = ticktable_c816;
154
        optable = optable_c816;
155
        addrtable = addrtable_c816;
156
    } else {
157
        regs.status |= FLAG_CONSTANT;
158
        regs.is65c816 = false;
159
        ticktable = ticktable_c02;
160
        optable = optable_c02;
161
        addrtable = addrtable_c02;
162
    }
163
    setinterrupt();
164
    cleardecimal();
165
    waiting = 0;
166
}
167
168
enum InterruptType {
169
    INT_COP = 0x4,
170
    INT_BRK = 0x6,
171
    INT_NMI = 0xA,
172
    INT_IRQ = 0xE
173
};
174
175
void interrupt6502(enum InterruptType vector) {
176
    if (!regs.e) {
177
        push8(regs.k);
178
    }
179
180
    regs.k = 0; // also in emulated mode
181
182
    push16(regs.pc);
183
184
    if (regs.e) {
185
        if (vector == INT_BRK) {
186
            push8(regs.status | FLAG_BREAK);
187
            vector = INT_IRQ;
188
        } else {
189
            push8(regs.status & ~FLAG_BREAK);
190
        }
191
    } else {
192
        push8(regs.status);
193
    }
194
195
    setinterrupt();
196
    cleardecimal();
197
    vp6502();
198
199
    uint16_t vector_address = (regs.e ? 0xFFF0 : 0xFFE0) + (uint8_t) vector;
200
    regs.pc = (uint16_t) read6502(vector_address, 0) | ((uint16_t) read6502(vector_address + 1, 0) << 8);
201
202
    clockticks6502 += 7; // consumed by CPU to process interrupt
203
}
204
205
static uint32_t addr_with_db(uint16_t addr) {
206
    return mask_long_addr(as_bank_byte(regs.db) | addr);
207
}
208