Fixed problem in DeviceSettings::strParam, returned wrong string
[avr-sim.git] / src / Core.cpp
blob99d9d5f7b18a92d467a789970658546c8e176353
1 /*
2 * avr-sim: An atmel AVR simulator
3 * Copyright (C) 2008 Tom Haber
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
19 #include "Core.h"
20 #include "RuntimeException.h"
21 #include "ImplementationException.h"
22 #include "Instruction.h"
23 #include "Bus.h"
24 #include "Util.h"
25 #include "Analyzer.h"
26 #include "DebugInterface.h"
28 namespace avr {
30 Core::Core(Bus & bus, unsigned int ioSpaceSize, unsigned int ramSize,
31 unsigned int flashSize, unsigned int pageSize,
32 word stackMask, int pcBytes, ERam *eram /*= 0*/)
33 : mmu( ioSpaceSize, ramSize, eram ),
34 flash(bus, flashSize, pageSize),
35 stack(bus, mmu, stackMask), bus(bus),
36 pc_bytes( pcBytes ), dbgi(0) {
39 Core::~Core() {
40 std::for_each( analyzers.begin(), analyzers.end(), Delete<Analyzer>());
43 void Core::init() {
44 // Get some special registers
45 SReg = mmu.statusReg();
47 stack.attachReg("sph", mmu.getIoreg("SPH"));
48 stack.attachReg("spl", mmu.getIoreg("SPL"));
49 stack.finishBuild();
51 flash.attachReg("spmcsr", mmu.getIoreg("SPMCR"));
52 flash.finishBuild();
55 static void analyzeHelper(const std::list<Analyzer*> & ans,
56 void (Analyzer::*method)()) {
57 MethodCall<Analyzer> call(method);
58 std::for_each( ans.begin(), ans.end(), call);
61 template <class T>
62 static void analyzeHelper(const std::list<Analyzer*> & ans,
63 void (Analyzer::*method)(T), T val) {
64 MethodCall1<Analyzer,T> call(method, val);
65 std::for_each( ans.begin(), ans.end(), call);
68 template <class T1, class T2>
69 static void analyzeHelper(const std::list<Analyzer*> & ans,
70 void (Analyzer::*method)(T1,T2),
71 T1 x, T2 y) {
72 MethodCall2<Analyzer,T1,T2> call(method, x, y);
73 std::for_each( ans.begin(), ans.end(), call);
76 byte Core::readRegister(unsigned int i) const {
77 byte val = mmu.reg(i);
78 analyzeHelper( analyzers, &Analyzer::readRegister, i, val );
79 return val;
82 void Core::writeRegister(unsigned int i, byte val) {
83 mmu.reg(i) = val;
84 analyzeHelper( analyzers, &Analyzer::writeRegister, i, val );
87 byte Core::readIORegister(unsigned int r) {
88 IORegister & reg = mmu.getIoreg(r);
90 byte val = reg;
91 analyzeHelper( analyzers, &Analyzer::readRegister,
92 (unsigned int)reg.getAddress(), val );
93 return val;
96 void Core::writeIORegister(unsigned int r, byte val) {
97 IORegister & reg = mmu.getIoreg(r);
98 reg = val;
99 analyzeHelper( analyzers, &Analyzer::writeRegister,
100 (unsigned int)reg.getAddress(), val );
103 byte Core::readByte(unsigned int addr) const {
104 byte val = mmu.readByte(addr);
105 analyzeHelper( analyzers, &Analyzer::readByte, addr, val );
106 return val;
109 void Core::writeByte(unsigned int addr, byte val) {
110 mmu.writeByte(addr, val);
111 analyzeHelper( analyzers, &Analyzer::writeByte, addr, val );
114 byte Core::readFlash(unsigned int addr) const {
115 byte val = flash.readByte(addr);
116 analyzeHelper( analyzers, &Analyzer::readFlash, addr, val );
117 return val;
120 int Core::writeFlash(unsigned int Z, word data) {
121 flash.storeProgramMemory(Z, data & 0xff, (data>>8) & 0xff);
122 analyzeHelper( analyzers, &Analyzer::writeFlash, Z, data );
123 return 0; //XXX
126 void Core::push(byte val) {
127 stack.push(val);
128 analyzeHelper( analyzers, &Analyzer::push, val );
131 byte Core::pop() {
132 byte val = stack.pop();
133 analyzeHelper( analyzers, &Analyzer::push, val );
134 return val;
137 void Core::jump(sbyte offset, bool push /*= false*/) {
138 if( push ) {
139 dword val = (PC+1);
140 for(int tt = 0; tt < pc_bytes; tt++) {
141 stack.push( val & 0xff );
142 val >>= 8;
146 PC += offset;
147 analyzeHelper( analyzers, &Analyzer::jump, (PC+1)<<1, push );
150 void Core::call(dword addr, bool push /*= true*/) {
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 = addr;
160 analyzeHelper( analyzers, &Analyzer::call, (PC+1)<<1, push );
163 void Core::ret(bool interrupt /*= false*/) {
164 dword val = 0;
165 for(int tt = 0; tt < pc_bytes; tt++) {
166 val = val<<8;
167 val |= stack.pop();
170 justReturnedFromInterrupt = interrupt;
171 PC = val - 1;
172 analyzeHelper( analyzers, &Analyzer::ret, interrupt );
175 word Core::fetchOperand() {
176 PC++;
177 unsigned int addr = PC<<1;
178 word op = flash.readWord( addr );
179 analyzeHelper( analyzers, &Analyzer::fetchOperand, op );
180 return op;
183 int Core::skip() {
184 int skip = 1;
185 unsigned int addr = (PC+1)<<1;
186 word opcode = flash.readWord( addr );
187 if( decoder.is2WordInstruction(opcode) )
188 skip = 2;
190 PC += skip;
191 analyzeHelper( analyzers, &Analyzer::skip );
192 return skip;
195 void Core::reset(unsigned int type) {
196 cpuCycles = 0;
197 PC = 0;
199 mmu.reset();
200 bus.reset();
202 stoppedMode = false;
203 justReturnedFromInterrupt = false;
204 sleepMode = SLEEP_MODE_NONE;
206 analyzeHelper( analyzers, &Analyzer::reset, type );
209 void Core::sleep() {
210 IORegister & mcucr = *mmu.getIoreg("MCUCR");
211 static const byte sleepEnable = (1<<5);
212 if( mcucr & sleepEnable ) {
213 //const IORegister *emcucr = mmu.getIoreg("EMCUCR", false);
214 sleepMode = SLEEP_MODE_IDLE;
216 // TODO The bit locations for the sleep mode are different between devices...
217 throw util::ImplementationException("Instruction SLEEP not fully implemented");
220 analyzeHelper( analyzers, &Analyzer::sleep, (unsigned int)sleepMode );
223 void Core::systemBreak() {
224 stoppedMode = true;
225 analyzeHelper( analyzers, &Analyzer::systemBreak );
228 bool Core::invokeInterrupt() {
229 // TODO IVSEL bit in GICR
231 unsigned int vector = bus.pendingInterrupt();
232 unsigned int addr = bus.interruptVectorAddress(vector);
234 // Wake up from sleep
235 if( sleepMode != SLEEP_MODE_NONE )
236 sleepMode = SLEEP_MODE_NONE;
238 PC--;
240 unsigned int offset = 0;
242 dword val = (PC+1);
243 for(int tt = 0; tt < pc_bytes; tt++) {
244 stack.push( val & 0xff );
245 val >>= 8;
248 PC = offset + addr;
250 analyzeHelper( analyzers, &Analyzer::interrupt, vector, (PC+1)<<1 );
251 bus.beforeInvokeInterrupt(vector);
252 return true;
255 bool Core::step() {
256 analyzeHelper<lword>( analyzers, &Analyzer::step, bus.ticks() );
258 // Are we sleeping?
259 if( sleepMode != SLEEP_MODE_NONE )
260 return true;
262 if( cpuCycles > 0 ) {
263 // Waiting for instruction to finish
264 cpuCycles--;
265 return (cpuCycles == 0);
268 if( justReturnedFromInterrupt ) {
269 // don't process the interrupt if we just returned from
270 // an interrupt handler, because the hardware manual says
271 // that at least one instruction is executed after
272 // returning from an interrupt.
273 justReturnedFromInterrupt = false;
274 } else {
275 static const unsigned char Ibit = 0x80;
276 IORegister & S = getIoreg(SReg);
277 if( (S & Ibit) != 0 ) {
278 // check if there are any pending interrupts
279 if( bus.isInterruptPending() ) {
280 invokeInterrupt();
281 S &= (unsigned char)~Ibit;
283 cpuCycles = 0;
284 return true;
289 try {
290 unsigned int addr = PC<<1;
291 analyzeHelper( analyzers, &Analyzer::trace, addr );
293 if( (dbgi == 0) || ! dbgi->checkBreak(addr) ) {
294 // Fetch instruction
295 word opcode = flash.readWord( addr );
296 Instruction & instr = decoder.decode(opcode);
297 cpuCycles = instr(this) - 1;
299 PC++;
301 } catch( util::ImplementationException & ex ) {
302 std::cerr << ex.message() << ": continuing" << std::endl;
303 PC++;
304 cpuCycles = 0;
307 return (cpuCycles == 0);