Core calls analyzers
[avr-sim.git] / Core.cpp
blob6ca0f628f60e445a6c0faa37ebdd3f5ef9b8664b
1 #include "Core.h"
2 #include "RuntimeException.h"
3 #include "ImplementationException.h"
4 #include "Instruction.h"
5 #include "Trace.h"
6 #include "Bus.h"
7 #include "Util.h"
8 #include "Analyzer.h"
9 #include "DebugInterface.h"
11 namespace avr {
13 Core::Core(Bus & bus, unsigned int ioSpaceSize,
14 unsigned int ramSize, unsigned int flashSize,
15 word stackMask, int pcBytes, ERam *eram /*= 0*/)
16 : regs( ioSpaceSize ),
17 sram( ramSize ), flash(flashSize),
18 eram(eram), mmu( R, regs, sram, eram ),
19 stack(bus, mmu, stackMask), bus(bus),
20 pc_bytes( pcBytes ), dbgi(0) {
22 static const char * Rnames[32] = {
23 "r0", "r1", "r2", "r3", "r4", "r5",
24 "r6", "r7", "r8", "r9", "r10", "r11",
25 "r12", "r13", "r14", "r15", "r16", "r17",
26 "r18", "r19", "r20", "r21", "r22", "r23",
27 "r24", "r25", "r26", "r27", "r28", "r29",
28 "r30", "r31"
30 for(int i = 0; i < 32; ++i)
31 R[i].init(i, Rnames[i]);
34 Core::~Core() {
35 // if( eram != 0 )
36 // delete eram;
39 void Core::addIOReg(unsigned int address,
40 const std::string & name, byte initial) {
41 IORegister *r =
42 new IORegister(address + registerSpaceSize, name, initial);
43 regs.addReg( address, r );
46 void Core::init() {
47 // Get some special registers
48 SReg = regs.getIoreg("SREG")->getAddress() - registerSpaceSize;
49 stack.attachReg("sph", regs.getIoreg("SPH"));
50 stack.attachReg("spl", regs.getIoreg("SPL"));
53 static void analyzeHelper(const std::list<Analyzer*> & ans,
54 void (Analyzer::*method)()) {
55 MethodCall<Analyzer> call(method);
56 std::for_each( ans.begin(), ans.end(), call);
59 template <class T>
60 static void analyzeHelper(const std::list<Analyzer*> & ans,
61 void (Analyzer::*method)(T), T val) {
62 MethodCall1<Analyzer,T> call(method, val);
63 std::for_each( ans.begin(), ans.end(), call);
66 template <class T1, class T2>
67 static void analyzeHelper(const std::list<Analyzer*> & ans,
68 void (Analyzer::*method)(T1,T2),
69 T1 x, T2 y) {
70 MethodCall2<Analyzer,T1,T2> call(method, x, y);
71 std::for_each( ans.begin(), ans.end(), call);
74 byte Core::readRegister(int i) const {
75 if( (unsigned int)i >= registerSpaceSize )
76 throw util::RuntimeException("Tried to access not existing register");
78 byte val = R[i];
79 analyzeHelper( analyzers, &Analyzer::readRegister, i, val );
80 return val;
83 void Core::writeRegister(int i, byte val) {
84 if( (unsigned int)i >= registerSpaceSize )
85 throw util::RuntimeException("Tried to access not existing register");
87 R[i] = val;
88 analyzeHelper( analyzers, &Analyzer::writeRegister, i, val );
91 byte Core::readStatus() const {
92 byte val = readIORegister(SReg);
93 analyzeHelper( analyzers, &Analyzer::readStatus, val );
94 return val;
97 void Core::writeStatus(byte val) {
98 writeIORegister(SReg, val);
99 analyzeHelper( analyzers, &Analyzer::writeStatus, val );
102 byte Core::readIORegister(int r) const {
103 IORegister & reg = regs.getIoreg(r);
105 byte val = reg;
106 analyzeHelper( analyzers, &Analyzer::readIORegister, r, val );
107 return val;
110 void Core::writeIORegister(int r, byte val) {
111 IORegister & reg = regs.getIoreg(r);
112 reg = val;
113 analyzeHelper( analyzers, &Analyzer::writeIORegister, r, val );
116 byte Core::readByte(unsigned int addr) const {
117 byte val = mmu.readByte(addr);
118 analyzeHelper( analyzers, &Analyzer::readByte, addr, val );
119 return val;
122 void Core::writeByte(unsigned int addr, byte val) {
123 mmu.writeByte(addr, val);
124 analyzeHelper( analyzers, &Analyzer::writeByte, addr, val );
127 byte Core::readFlash(unsigned int addr) const {
128 byte val = flash.readByte(addr);
129 analyzeHelper( analyzers, &Analyzer::readFlash, addr, val );
130 return val;
133 int Core::writeFlash(unsigned int addr, word data) {
134 //flash.write(addr, (unsigned char *)&data, 2);
135 //analyzeHelper( analyzers, &Analyzer::writeFlash, addr, val );
136 throw util::RuntimeException("Writing to flash is not yet supported");
139 void Core::push(byte val) {
140 stack.push(val);
141 analyzeHelper( analyzers, &Analyzer::push, val );
144 byte Core::pop() {
145 byte val = stack.pop();
146 analyzeHelper( analyzers, &Analyzer::push, val );
147 return val;
150 void Core::jump(sbyte offset, bool push /*= false*/) {
151 if( push ) {
152 dword val = (PC+1);
153 for(int tt = 0; tt < pc_bytes; tt++) {
154 stack.push( val & 0xff );
155 val >>= 8;
159 PC += offset;
160 analyzeHelper( analyzers, &Analyzer::jump, offset, push );
163 void Core::call(dword addr, bool push /*= true*/) {
164 if( push ) {
165 dword val = (PC+1);
166 for(int tt = 0; tt < pc_bytes; tt++) {
167 stack.push( val & 0xff );
168 val >>= 8;
172 PC = addr;
173 analyzeHelper( analyzers, &Analyzer::call, addr, push );
176 void Core::ret(bool interrupt /*= false*/) {
177 dword val = 0;
178 for(int tt = 0; tt < pc_bytes; tt++) {
179 val = val<<8;
180 val |= stack.pop();
183 PC = val - 1;
184 analyzeHelper( analyzers, &Analyzer::ret, interrupt );
187 word Core::fetchOperand() {
188 PC++;
189 unsigned int addr = PC<<1;
190 word op = flash.readWord( addr );
191 analyzeHelper( analyzers, &Analyzer::fetchOperand, op );
192 return op;
195 int Core::skip() {
196 int skip = 1;
197 unsigned int addr = (PC+1)<<1;
198 word opcode = flash.readWord( addr );
199 if( decoder.is2WordInstruction(opcode) )
200 skip = 2;
202 PC += skip;
203 analyzeHelper( analyzers, &Analyzer::skip );
204 return skip;
207 void Core::reset(unsigned int type) {
208 Trace::instance().reset(type);
209 cpuCycles = 0;
210 PC = 0;
212 regs.reset();
213 bus.reset();
214 analyzeHelper( analyzers, &Analyzer::reset, type );
217 void Core::sleep() {
218 const IORegister & mcucr = *regs.getIoreg("MCUCR");
219 static const byte sleepEnable = (1<<5);
220 if( mcucr & sleepEnable ) {
221 //const IORegister *emcucr = regs.getIoreg("EMCUCR", false);
222 sleepMode = SLEEP_MODE_IDLE;
224 // TODO The bit locations for the sleep mode are different between devices...
225 throw util::ImplementationException("Instruction SLEEP not fully implemented");
228 analyzeHelper( analyzers, &Analyzer::sleep, (unsigned int)sleepMode );
231 bool Core::interrupt(unsigned int vector, unsigned int addr) {
232 // TODO sleep
233 // TODO IVSEL bit in GICR
235 static const unsigned char Ibit = 0x80;
237 IORegister & S = getIoreg(SReg);
238 if( (S & Ibit) == 0 )
239 return false;
241 Trace::instance().interrupt( addr );
243 PC--;
245 unsigned int offset = 0;
246 call( offset + addr, true );
248 S &= (unsigned char)~Ibit;
249 analyzeHelper( analyzers, &Analyzer::interrupt, vector, addr );
250 return true;
253 bool Core::step() {
254 unsigned int addr = PC<<1;
255 if( cpuCycles <= 0 ) {
256 try {
257 if( (dbgi == 0) || ! dbgi->checkBreak(addr) ) {
258 // Fetch instruction
259 word opcode = flash.readWord( addr );
260 Trace::instance().pc_trace( addr );
261 //std::cout << "Fetch opcode: " << std::hex << opcode << std::dec << std::endl;
262 Instruction & instr = decoder.decode(opcode);
263 cpuCycles = instr(this) - 1;
265 PC++;
267 } catch( util::ImplementationException & ex ) {
268 std::cerr << ex.message() << ": continuing" << std::endl;
269 PC++;
270 cpuCycles = 0;
272 } else {
273 // Waiting for instruction to finish
274 cpuCycles--;
277 analyzeHelper( analyzers, &Analyzer::step, addr, bus.ticks() );
278 return (cpuCycles == 0);