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/>.
20 #include "RuntimeException.h"
21 #include "ImplementationException.h"
22 #include "Instruction.h"
26 #include "DebugInterface.h"
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) {
40 std::for_each( analyzers
.begin(), analyzers
.end(), Delete
<Analyzer
>());
44 // Get some special registers
45 SReg
= mmu
.statusReg();
47 stack
.attachReg("sph", mmu
.getIoreg("SPH"));
48 stack
.attachReg("spl", mmu
.getIoreg("SPL"));
51 flash
.attachReg("spmcsr", mmu
.getIoreg("SPMCR"));
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
);
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
),
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
);
82 void Core::writeRegister(unsigned int i
, byte val
) {
84 analyzeHelper( analyzers
, &Analyzer::writeRegister
, i
, val
);
87 byte
Core::readIORegister(unsigned int r
) {
88 IORegister
& reg
= mmu
.getIoreg(r
);
91 analyzeHelper( analyzers
, &Analyzer::readRegister
,
92 (unsigned int)reg
.getAddress(), val
);
96 void Core::writeIORegister(unsigned int r
, byte val
) {
97 IORegister
& reg
= mmu
.getIoreg(r
);
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
);
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
);
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
);
126 void Core::push(byte val
) {
128 analyzeHelper( analyzers
, &Analyzer::push
, val
);
132 byte val
= stack
.pop();
133 analyzeHelper( analyzers
, &Analyzer::push
, val
);
137 void Core::jump(sbyte offset
, bool push
/*= false*/) {
140 for(int tt
= 0; tt
< pc_bytes
; tt
++) {
141 stack
.push( val
& 0xff );
147 analyzeHelper( analyzers
, &Analyzer::jump
, (PC
+1)<<1, push
);
150 void Core::call(dword addr
, bool push
/*= true*/) {
153 for(int tt
= 0; tt
< pc_bytes
; tt
++) {
154 stack
.push( val
& 0xff );
160 analyzeHelper( analyzers
, &Analyzer::call
, (PC
+1)<<1, push
);
163 void Core::ret(bool interrupt
/*= false*/) {
165 for(int tt
= 0; tt
< pc_bytes
; tt
++) {
170 justReturnedFromInterrupt
= interrupt
;
172 analyzeHelper( analyzers
, &Analyzer::ret
, interrupt
);
175 word
Core::fetchOperand() {
177 unsigned int addr
= PC
<<1;
178 word op
= flash
.readWord( addr
);
179 analyzeHelper( analyzers
, &Analyzer::fetchOperand
, op
);
185 unsigned int addr
= (PC
+1)<<1;
186 word opcode
= flash
.readWord( addr
);
187 if( decoder
.is2WordInstruction(opcode
) )
191 analyzeHelper( analyzers
, &Analyzer::skip
);
195 void Core::reset(unsigned int type
) {
203 justReturnedFromInterrupt
= false;
204 sleepMode
= SLEEP_MODE_NONE
;
206 analyzeHelper( analyzers
, &Analyzer::reset
, type
);
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() {
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
;
240 unsigned int offset
= 0;
243 for(int tt
= 0; tt
< pc_bytes
; tt
++) {
244 stack
.push( val
& 0xff );
250 analyzeHelper( analyzers
, &Analyzer::interrupt
, vector
, (PC
+1)<<1 );
251 bus
.beforeInvokeInterrupt(vector
);
256 analyzeHelper
<lword
>( analyzers
, &Analyzer::step
, bus
.ticks() );
259 if( sleepMode
!= SLEEP_MODE_NONE
)
262 if( cpuCycles
> 0 ) {
263 // Waiting for instruction to finish
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;
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() ) {
281 S
&= (unsigned char)~Ibit
;
290 unsigned int addr
= PC
<<1;
291 analyzeHelper( analyzers
, &Analyzer::trace
, addr
);
293 if( (dbgi
== 0) || ! dbgi
->checkBreak(addr
) ) {
295 word opcode
= flash
.readWord( addr
);
296 Instruction
& instr
= decoder
.decode(opcode
);
297 cpuCycles
= instr(this) - 1;
301 } catch( util::ImplementationException
& ex
) {
302 std::cerr
<< ex
.message() << ": continuing" << std::endl
;
307 return (cpuCycles
== 0);