Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
alexbevi
GitHub Repository: alexbevi/BizHawk
Path: blob/master/libmeteor/source/interpreter.cpp
2 views
1
// Meteor - A Nintendo Gameboy Advance emulator
2
// Copyright (C) 2009-2011 Philippe Daouadi
3
//
4
// This program is free software: you can redistribute it and/or modify
5
// it under the terms of the GNU General Public License as published by
6
// the Free Software Foundation, either version 3 of the License, or
7
// (at your option) any later version.
8
//
9
// This program is distributed in the hope that it will be useful,
10
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
// GNU General Public License for more details.
13
//
14
// You should have received a copy of the GNU General Public License
15
// along with this program. If not, see <http://www.gnu.org/licenses/>.
16
17
#include "ameteor/interpreter.hpp"
18
#include "ameteor/cpu.hpp"
19
#include "ameteor/memory.hpp"
20
#include "ameteor/bios.hpp"
21
#include "ameteor/disassembler/instruction.hpp"
22
#include "globals.hpp"
23
#include "cpu_globals.hpp"
24
#include "ameteor.hpp"
25
26
#include "debug.hpp"
27
#include <sstream>
28
29
namespace AMeteor
30
{
31
Interpreter::Interpreter() :
32
m_run(false),
33
m_interrupt_(false),
34
m_haltcnt(IO.GetRef8(Io::HALTCNT)),
35
m_if(IO.GetRef16(Io::IF)),
36
m_ie(IO.GetRef16(Io::IE))
37
{
38
}
39
40
void Interpreter::SendInterrupt (uint16_t interrupt)
41
{
42
IO.GetRef16(Io::IF) |= interrupt;
43
if ((interrupt & IO.DRead16(Io::IE)) &&
44
(IO.DRead16(Io::IME) & 0x1) &&
45
!m_st.icpsr.irq_d)
46
// irq are enabled and theses irq are enabled...
47
m_interrupt = true;
48
}
49
50
void Interpreter::CheckInterrupt ()
51
{
52
m_interrupt =
53
(IO.DRead16(Io::IF) & IO.DRead16(Io::IE)) &&
54
(IO.DRead16(Io::IME) & 0x1) &&
55
!m_st.icpsr.irq_d;
56
}
57
58
void Interpreter::Run (unsigned int cycles)
59
{
60
m_run = true;
61
CLOCK.ResetCounter();
62
while(m_run && CLOCK.GetCounter() < cycles)
63
{
64
switch (m_haltcnt)
65
{
66
case 255: // normal mode
67
PrintRegs();
68
if (FLAG_T)
69
{
70
if (R(15) & 0x1)
71
met_abort("PC not 16 bit aligned : " << IOS_ADD << R(15));
72
73
code = MEM.Read16(R(15)-2);
74
if (traceenabled)
75
{
76
std::stringstream ss;
77
ss << IOS_TRACE << R(15) - 2 << ':' << std::setw(4) << code << " ";
78
ss.setf(std::ios::left, std::ios::adjustfield);
79
ss << std::setw(32) << std::setfill(' ') << Disassembler::Instruction(R(15), (uint16_t)code).ToString();
80
ss.setf(std::ios::right, std::ios::adjustfield);
81
ss << IOS_TRACE;
82
for (int i = 0; i < 16; i++)
83
ss << std::setw(8) << R(i) << ' ';
84
UpdateCpsr();
85
ss << std::setw(8) << m_st.cpsr.dw << ' ';
86
ss << std::setw(8) << m_st.spsr.dw << ' ';
87
trace_bizhawk(ss.str());
88
}
89
R(15) += 2;
90
t_Code();
91
}
92
else
93
{
94
if (R(15) & 0x3)
95
met_abort("PC not 32 bit aligned : " << IOS_ADD << R(15));
96
97
if (R(15) < 0x01000000 && !MEM.HasBios())
98
{
99
switch (R(15))
100
{
101
case 0x004:
102
Bios::Bios000h();
103
break;
104
case 0x00C:
105
Bios::Bios008h();
106
break;
107
case 0x01C:
108
Bios::Bios018h();
109
break;
110
case 0x134:
111
Bios::Bios130h();
112
break;
113
case 0x33C:
114
Bios::Bios338h();
115
break;
116
case 0x16C:
117
Bios::Bios168h();
118
break;
119
default:
120
met_abort("Jump to " << IOS_ADD << R(15));
121
}
122
}
123
else
124
{
125
code = MEM.Read32(R(15)-4);
126
if (traceenabled)
127
{
128
std::stringstream ss;
129
ss << IOS_TRACE << R(15) - 4 << ':' << std::setw(8) << code << ' ';
130
ss.setf(std::ios::left, std::ios::adjustfield);
131
ss << std::setw(32) << std::setfill(' ') << Disassembler::Instruction(R(15), (uint32_t)code).ToString();
132
ss.setf(std::ios::right, std::ios::adjustfield);
133
ss << IOS_TRACE;
134
for (int i = 0; i < 16; i++)
135
ss << std::setw(8) << R(i) << ' ';
136
UpdateCpsr();
137
ss << std::setw(8) << m_st.cpsr.dw << ' ';
138
ss << std::setw(8) << m_st.spsr.dw << ' ';
139
trace_bizhawk(ss.str());
140
}
141
R(15) += 4;
142
a_Code();
143
}
144
}
145
if (R(15) < 0x01000000 && FLAG_T && !MEM.HasBios())
146
met_abort("Jump to " << IOS_ADD << R(15));
147
148
CLOCK.Commit();
149
150
if (m_interrupt)
151
// irq are enabled and there are irq waiting...
152
{
153
// FIXME : do we really need this ??
154
// if not, we can get rid of save and load state and reset
155
if (m_interrupt_)
156
{
157
m_interrupt_ = false;
158
// XXX we must be sure the cpu isn't halted when an interrupt
159
// occurs
160
// should be removed after since it takes no time to make a new
161
// iteration of the loop
162
m_haltcnt = 255;
163
CPU.Interrupt();
164
}
165
else
166
{
167
// XXX
168
if (m_haltcnt != 255)
169
{
170
m_haltcnt = 255;
171
CPU.Interrupt();
172
}
173
else
174
m_interrupt_ = true;
175
}
176
}
177
178
break;
179
case 0: // halt mode
180
if (m_if & m_ie) // interrupt occured
181
{
182
m_haltcnt = 255; // return to normal mode
183
CPU.Interrupt();
184
// XXX use an else
185
break;
186
}
187
188
CLOCK.WaitForNext();
189
190
// XXX remove this block
191
if (m_if & m_ie) // interrupt occured
192
{
193
m_haltcnt = 255; // return to normal mode
194
CPU.Interrupt();
195
}
196
197
break;
198
case 1: // stop mode
199
met_abort("Stop mode not implemented");
200
break;
201
default:
202
met_abort("Unknown HALTCNT value : " << (int)m_haltcnt);
203
break;
204
}
205
}
206
m_run = false;
207
}
208
209
bool Interpreter::SaveState (std::ostream& stream)
210
{
211
SS_WRITE_VAR(m_interrupt_);
212
213
return Cpu::SaveState(stream);
214
}
215
216
bool Interpreter::LoadState (std::istream& stream)
217
{
218
SS_READ_VAR(m_interrupt_);
219
220
return Cpu::LoadState(stream);
221
}
222
}
223
224