Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
alexbevi
GitHub Repository: alexbevi/BizHawk
Path: blob/master/libsnes/bsnes/snes/cpu/cpu.cpp
2 views
1
#include <snes/snes.hpp>
2
3
#define CPU_CPP
4
namespace SNES {
5
6
CPU cpu;
7
8
#include "serialization.cpp"
9
#include "dma/dma.cpp"
10
#include "memory/memory.cpp"
11
#include "mmio/mmio.cpp"
12
#include "timing/timing.cpp"
13
14
void CPU::step(unsigned clocks) {
15
smp.clock -= clocks * (uint64)smp.frequency;
16
ppu.clock -= clocks;
17
for(unsigned i = 0; i < coprocessors.size(); i++) {
18
Processor &chip = *coprocessors[i];
19
chip.clock -= clocks * (uint64)chip.frequency;
20
}
21
input.port1->clock -= clocks * (uint64)input.port1->frequency;
22
input.port2->clock -= clocks * (uint64)input.port2->frequency;
23
synchronize_controllers();
24
}
25
26
void CPU::synchronize_smp() {
27
if(SMP::Threaded == true) {
28
if(smp.clock < 0) co_switch(smp.thread);
29
} else {
30
while(smp.clock < 0) smp.enter();
31
}
32
}
33
34
void CPU::synchronize_ppu() {
35
if(PPU::Threaded == true) {
36
if(ppu.clock < 0) co_switch(ppu.thread);
37
} else {
38
while(ppu.clock < 0) ppu.enter();
39
}
40
}
41
42
void CPU::synchronize_coprocessors() {
43
for(unsigned i = 0; i < coprocessors.size(); i++) {
44
Processor &chip = *coprocessors[i];
45
if(chip.clock < 0) co_switch(chip.thread);
46
}
47
}
48
49
void CPU::synchronize_controllers() {
50
if(input.port1->clock < 0) co_switch(input.port1->thread);
51
if(input.port2->clock < 0) co_switch(input.port2->thread);
52
}
53
54
void CPU::Enter() { cpu.enter(); }
55
56
void CPU::enter() {
57
while(true) {
58
if(scheduler.sync == Scheduler::SynchronizeMode::CPU) {
59
// we can only stop if there's enough time for at least one more event
60
// on both the PPU and the SMP
61
if (smp.clock < 0 && ppu.clock < 0) {
62
scheduler.sync = Scheduler::SynchronizeMode::All;
63
scheduler.exit(Scheduler::ExitReason::SynchronizeEvent);
64
}
65
}
66
67
if(status.interrupt_pending) {
68
status.interrupt_pending = false;
69
if(status.nmi_pending) {
70
status.nmi_pending = false;
71
regs.vector = (regs.e == false ? 0xffea : 0xfffa);
72
op_irq();
73
debugger.op_nmi();
74
} else if(status.irq_pending) {
75
status.irq_pending = false;
76
regs.vector = (regs.e == false ? 0xffee : 0xfffe);
77
op_irq();
78
debugger.op_irq();
79
} else if(status.reset_pending) {
80
status.reset_pending = false;
81
add_clocks(186);
82
regs.pc.l = bus.read(0xfffc);
83
regs.pc.h = bus.read(0xfffd);
84
}
85
}
86
87
op_step();
88
}
89
}
90
91
void CPU::op_step() {
92
debugger.op_exec(regs.pc.d);
93
94
if (interface()->wanttrace)
95
{
96
char tmp[512];
97
disassemble_opcode(tmp, regs.pc.d);
98
tmp[511] = 0;
99
interface()->cpuTrace(tmp);
100
}
101
102
(this->*opcode_table[op_readpcfirst()])();
103
}
104
105
void CPU::enable() {
106
function<uint8 (unsigned)> read = { &CPU::mmio_read, (CPU*)&cpu };
107
function<void (unsigned, uint8)> write = { &CPU::mmio_write, (CPU*)&cpu };
108
109
bus.map(Bus::MapMode::Direct, 0x00, 0x3f, 0x2140, 0x2183, read, write);
110
bus.map(Bus::MapMode::Direct, 0x80, 0xbf, 0x2140, 0x2183, read, write);
111
112
bus.map(Bus::MapMode::Direct, 0x00, 0x3f, 0x4016, 0x4017, read, write);
113
bus.map(Bus::MapMode::Direct, 0x80, 0xbf, 0x4016, 0x4017, read, write);
114
115
bus.map(Bus::MapMode::Direct, 0x00, 0x3f, 0x4200, 0x421f, read, write);
116
bus.map(Bus::MapMode::Direct, 0x80, 0xbf, 0x4200, 0x421f, read, write);
117
118
bus.map(Bus::MapMode::Direct, 0x00, 0x3f, 0x4300, 0x437f, read, write);
119
bus.map(Bus::MapMode::Direct, 0x80, 0xbf, 0x4300, 0x437f, read, write);
120
121
read = [](unsigned addr) { cdlInfo.set(eCDLog_AddrType_WRAM, addr); return cpu.wram[addr]; };
122
write = [](unsigned addr, uint8 data) { cpu.wram[addr] = data; };
123
124
bus.map(Bus::MapMode::Linear, 0x00, 0x3f, 0x0000, 0x1fff, read, write, 0x000000, 0x002000);
125
bus.map(Bus::MapMode::Linear, 0x80, 0xbf, 0x0000, 0x1fff, read, write, 0x000000, 0x002000);
126
bus.map(Bus::MapMode::Linear, 0x7e, 0x7f, 0x0000, 0xffff, read, write);
127
}
128
129
void CPU::power() {
130
cpu_version = config.cpu.version;
131
for(int i=0;i<128*1024;i++) wram[i] = random(config.cpu.wram_init_value);
132
133
regs.a = regs.x = regs.y = 0x0000;
134
regs.s = 0x01ff;
135
136
mmio_power();
137
dma_power();
138
timing_power();
139
140
//zero 01-dec-2012
141
//gotta clear these to something, sometime
142
aa.d = rd.d = sp = dp = 0;
143
}
144
145
void CPU::reset() {
146
create(Enter, system.cpu_frequency());
147
coprocessors.reset();
148
PPUcounter::reset();
149
150
//note: some registers are not fully reset by SNES
151
regs.pc = 0x000000;
152
regs.x.h = 0x00;
153
regs.y.h = 0x00;
154
regs.s.h = 0x01;
155
regs.d = 0x0000;
156
regs.db = 0x00;
157
regs.p = 0x34;
158
regs.e = 1;
159
regs.mdr = 0x00;
160
regs.wai = false;
161
regs.vector = 0xfffc; //reset vector address
162
update_table();
163
164
mmio_reset();
165
dma_reset();
166
timing_reset();
167
}
168
169
CPU::CPU()
170
: wram(nullptr)
171
{
172
PPUcounter::scanline = { &CPU::scanline, this };
173
}
174
175
CPU::~CPU() {
176
interface()->freeSharedMemory(wram);
177
}
178
179
void CPU::initialize()
180
{
181
wram = (uint8*)interface()->allocSharedMemory("WRAM",128 * 1024);
182
}
183
184
}
185
186