-
Notifications
You must be signed in to change notification settings - Fork 3
/
Cpu.h
141 lines (124 loc) · 3.7 KB
/
Cpu.h
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
#ifndef _CPU_H
#define _CPU_H
#define SETFLAGS_ZN(VALUE) ST = (ST&0x7D)|(((VALUE)==0)<<1)|((VALUE)&0x80)
#include "mem.h"
class TED;
class CPU {
protected:
//unsigned int currins;
unsigned char currins;
unsigned char nextins;
unsigned char farins;
unsigned int ptr;
unsigned int PC;
unsigned char SP;
// 76543210
unsigned int ST; // NV1BDIZC
unsigned char AC;
unsigned char X;
unsigned char Y;
void ADC(const unsigned char value);
void SBC(const unsigned char value);
void DoCompare(unsigned char reg, unsigned char value);
unsigned int cycle;
unsigned int IRQcount;
unsigned char *irq_register;
unsigned char *stack;
unsigned char irq_sequence;
MemoryHandler *mem;
virtual unsigned char CheckVFlag() { return (ST&0x40); };
inline virtual void ClearVFlag() { ST&=0xBF; };
inline void SetVFlag() { ST|=0x40; };
public:
CPU(MemoryHandler *memhandler, unsigned char *irqreg, unsigned char *cpustack);
~CPU();
void Reset(void);
void softreset(void);
void setPC(unsigned int addr);
void setST(unsigned char st) { ST = st; };
void process();
void stopcycle();
unsigned int getPC() { return PC; };
unsigned int getSP() { return SP; };
unsigned int getST() { return ST; };
unsigned int getAC() { return AC; };
unsigned int getX() { return X; };
unsigned int getY() { return Y; };
unsigned int getnextins() { return nextins; };
unsigned int getptr() { return ptr; };
unsigned int getcycle() { return cycle; };
unsigned int getcins();
bool saveshot(void *cpudump);
bool loadshot(void *cpudump);
// breakpoint variables
static bool bp_active;
static bool bp_reached;
struct {
unsigned int address;
bool enabled;
bool slot_free;
} bp[11];
unsigned int nr_activebps;
bool cpu_jammed;
static const unsigned int nr_of_bps;
};
inline void CPU::ADC(const unsigned char value)
{
if (ST&0x08) {
unsigned int bin_adc = AC + value + (ST&0x01);
unsigned char AL, AH;
AL=(AC&0x0F) + (value & 0x0F) + (ST&0x01);
AH=(AC >> 4) + (value >> 4 ) ;
// fix lower nybble
if (AL>9) {
AL+=6;
AH++;
}
// zero bit depends on the normal ADC...
(bin_adc)&0xFF ? ST&=0xFD : ST|=0x02;
// negative flag also...
( AH & 0x08 ) ? ST|=0x80 : ST&=0x7F;
// V flag
((((AH << 4) ^ AC) & 0x80) && !((AC ^ value) & 0x80)) ? SetVFlag() : ClearVFlag();
// fix upper nybble
if (AH>9)
AH+=6;
// set the Carry if the decimal add has an overflow
(AH > 0x0f) ? ST|=0x01 : ST&=0xFE;
// calculate new AC value
AC = (AH<<4)|(AL & 0x0F);
} else {
unsigned int bin_adc = AC + value + (ST&0x01);
(bin_adc>=0x100) ? ST|=0x01 : ST&=0xFE;
(!((AC ^ value) & 0x80) && ((AC ^ bin_adc) & 0x80) ) ? SetVFlag() : ClearVFlag();
AC=(unsigned char) bin_adc;
SETFLAGS_ZN(AC);
}
}
inline void CPU::SBC(const unsigned char value)
{
if (ST&0x08) { // if in decimal mode
unsigned int bin_sbc = (AC - value - (1-(ST&0x01)));
unsigned int dec_sbc = (AC & 0x0F) - (value & 0x0F) - (1-(ST&0x01));
// Calculate the upper nybble.
// fix upper nybble
if (dec_sbc&0x10)
dec_sbc = ((dec_sbc-6)&0x0F) | ((AC&0xF0) - (value&0xF0) - 0x10);
else
dec_sbc = (dec_sbc&0x0F) | ((AC&0xF0) - (value&0xF0));
if (dec_sbc&0x100)
dec_sbc-= 0x60;
// all flags depend on the normal SBC...
(bin_sbc<0x100) ? ST|=0x01 : ST&=0xFE ; // carry flag
SETFLAGS_ZN( bin_sbc & 0xFF );
((AC^bin_sbc)&0x80 && (AC^value)&0x80 ) ? SetVFlag() : ClearVFlag(); // V flag
AC=(unsigned char) dec_sbc;
} else {
unsigned int bin_sbc = (AC - value - (1-(ST&0x01)));
(bin_sbc<0x100) ? ST|=0x01 : ST&=0xFE;
(((AC ^ value) & 0x80) && ((AC ^ bin_sbc) & 0x80) ) ? SetVFlag() : ClearVFlag();
AC=(unsigned char) bin_sbc;
SETFLAGS_ZN(AC);
}
}
#endif // _CPU_H