2 #include "RuntimeException.h"
3 #include "ImplementationException.h"
4 #include "Instruction.h"
9 #include "DebugInterface.h"
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",
30 for(int i
= 0; i
< 32; ++i
)
31 R
[i
].init(i
, Rnames
[i
]);
39 void Core::addIOReg(unsigned int address
,
40 const std::string
& name
, byte initial
) {
42 new IORegister(address
+ registerSpaceSize
, name
, initial
);
43 regs
.addReg( address
, r
);
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
);
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
),
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");
79 analyzeHelper( analyzers
, &Analyzer::readRegister
, i
, 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");
88 analyzeHelper( analyzers
, &Analyzer::writeRegister
, i
, val
);
91 byte
Core::readStatus() const {
92 byte val
= readIORegister(SReg
);
93 analyzeHelper( analyzers
, &Analyzer::readStatus
, 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
);
106 analyzeHelper( analyzers
, &Analyzer::readIORegister
, r
, val
);
110 void Core::writeIORegister(int r
, byte val
) {
111 IORegister
& reg
= regs
.getIoreg(r
);
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
);
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
);
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
) {
141 analyzeHelper( analyzers
, &Analyzer::push
, val
);
145 byte val
= stack
.pop();
146 analyzeHelper( analyzers
, &Analyzer::push
, val
);
150 void Core::jump(sbyte offset
, bool push
/*= false*/) {
153 for(int tt
= 0; tt
< pc_bytes
; tt
++) {
154 stack
.push( val
& 0xff );
160 analyzeHelper( analyzers
, &Analyzer::jump
, offset
, push
);
163 void Core::call(dword addr
, bool push
/*= true*/) {
166 for(int tt
= 0; tt
< pc_bytes
; tt
++) {
167 stack
.push( val
& 0xff );
173 analyzeHelper( analyzers
, &Analyzer::call
, addr
, push
);
176 void Core::ret(bool interrupt
/*= false*/) {
178 for(int tt
= 0; tt
< pc_bytes
; tt
++) {
184 analyzeHelper( analyzers
, &Analyzer::ret
, interrupt
);
187 word
Core::fetchOperand() {
189 unsigned int addr
= PC
<<1;
190 word op
= flash
.readWord( addr
);
191 analyzeHelper( analyzers
, &Analyzer::fetchOperand
, op
);
197 unsigned int addr
= (PC
+1)<<1;
198 word opcode
= flash
.readWord( addr
);
199 if( decoder
.is2WordInstruction(opcode
) )
203 analyzeHelper( analyzers
, &Analyzer::skip
);
207 void Core::reset(unsigned int type
) {
208 Trace::instance().reset(type
);
214 analyzeHelper( analyzers
, &Analyzer::reset
, type
);
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
) {
233 // TODO IVSEL bit in GICR
235 static const unsigned char Ibit
= 0x80;
237 IORegister
& S
= getIoreg(SReg
);
238 if( (S
& Ibit
) == 0 )
241 Trace::instance().interrupt( addr
);
245 unsigned int offset
= 0;
246 call( offset
+ addr
, true );
248 S
&= (unsigned char)~Ibit
;
249 analyzeHelper( analyzers
, &Analyzer::interrupt
, vector
, addr
);
254 unsigned int addr
= PC
<<1;
255 if( cpuCycles
<= 0 ) {
257 if( (dbgi
== 0) || ! dbgi
->checkBreak(addr
) ) {
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;
267 } catch( util::ImplementationException
& ex
) {
268 std::cerr
<< ex
.message() << ": continuing" << std::endl
;
273 // Waiting for instruction to finish
277 analyzeHelper( analyzers
, &Analyzer::step
, addr
, bus
.ticks() );
278 return (cpuCycles
== 0);