Bug fix: check if vm exists
[avr-sim.git] / Core.cpp
blob8728ee62ba0e25d863dada486770d3a0b1125fcf
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 "DebugInterface.h"
9 namespace avr {
11 Core::Core(Bus & bus, unsigned int ioSpaceSize,
12 unsigned int ramSize, unsigned int flashSize,
13 word stackMask, int pcBytes, ERam *eram /*= 0*/)
14 : regs( ioSpaceSize ),
15 sram( ramSize ), flash(flashSize),
16 eram(eram), mmu( R, regs, sram, eram ),
17 stack(bus, mmu, stackMask), bus(bus),
18 pc_bytes( pcBytes ), dbgi(0) {
20 static const char * Rnames[32] = {
21 "r0", "r1", "r2", "r3", "r4", "r5",
22 "r6", "r7", "r8", "r9", "r10", "r11",
23 "r12", "r13", "r14", "r15", "r16", "r17",
24 "r18", "r19", "r20", "r21", "r22", "r23",
25 "r24", "r25", "r26", "r27", "r28", "r29",
26 "r30", "r31"
28 for(int i = 0; i < 32; ++i)
29 R[i].init(i, Rnames[i]);
32 Core::~Core() {
33 // if( eram != 0 )
34 // delete eram;
37 void Core::addIOReg(unsigned int address,
38 const std::string & name, byte initial) {
39 IORegister *r =
40 new IORegister(address + registerSpaceSize, name, initial);
41 regs.addReg( address, r );
44 void Core::init() {
45 // Get some special registers
46 SReg = regs.getIoreg("SREG")->getAddress() - registerSpaceSize;
47 stack.attachReg("sph", regs.getIoreg("SPH"));
48 stack.attachReg("spl", regs.getIoreg("SPL"));
51 int Core::writeFlash(unsigned int addr, word data) {
52 //flash.write(addr, (unsigned char *)&data, 2);
53 throw util::RuntimeException("Writing to flash is not yet supported");
56 byte Core::readRegister(int i) const {
57 if( (unsigned int)i >= registerSpaceSize )
58 throw util::RuntimeException("Tried to access not existing register");
60 return R[i];
63 void Core::writeRegister(int i, byte val) {
64 if( (unsigned int)i >= registerSpaceSize )
65 throw util::RuntimeException("Tried to access not existing register");
67 R[i] = val;
70 void Core::jump(sbyte offset, bool push /*= false*/) {
71 if( push ) {
72 dword val = (PC+1);
73 for(int tt = 0; tt < pc_bytes; tt++) {
74 stack.push( val & 0xff );
75 val >>= 8;
79 PC += offset;
82 void Core::call(dword addr, bool push /*= true*/) {
83 if( push ) {
84 dword val = (PC+1);
85 for(int tt = 0; tt < pc_bytes; tt++) {
86 stack.push( val & 0xff );
87 val >>= 8;
91 PC = addr;
94 void Core::ret(bool interrupt /*= false*/) {
95 dword val = 0;
96 for(int tt = 0; tt < pc_bytes; tt++) {
97 val = val<<8;
98 val |= stack.pop();
101 PC = val - 1;
104 word Core::fetchOperand() {
105 PC++;
106 unsigned int addr = PC<<1;
107 word op = flash.readWord( addr );
108 return op;
111 int Core::skip() {
112 int skip = 1;
113 unsigned int addr = (PC+1)<<1;
114 word opcode = flash.readWord( addr );
115 if( decoder.is2WordInstruction(opcode) )
116 skip = 2;
118 PC += skip;
119 return skip;
122 void Core::reset(unsigned int type) {
123 Trace::instance().reset(type);
124 cpuCycles = 0;
125 PC = 0;
127 regs.reset();
128 bus.reset();
131 void Core::sleep() {
132 const IORegister & mcucr = *regs.getIoreg("MCUCR");
133 static const byte sleepEnable = (1<<5);
134 if( mcucr & sleepEnable ) {
135 //const IORegister *emcucr = regs.getIoreg("EMCUCR", false);
136 sleepMode = SLEEP_MODE_IDLE;
138 // TODO The bit locations for the sleep mode are different between devices...
139 throw util::ImplementationException("Instruction SLEEP not fully implemented");
143 bool Core::interrupt(unsigned int vector, unsigned int addr) {
144 // TODO sleep
145 // TODO IVSEL bit in GICR
147 static const unsigned char Ibit = 0x80;
149 IORegister & S = getIoreg(SReg);
150 if( (S & Ibit) == 0 )
151 return false;
153 Trace::instance().interrupt( addr );
155 PC--;
157 unsigned int offset = 0;
158 call( offset + addr, true );
160 S &= (unsigned char)~Ibit;
161 return true;
164 bool Core::step() {
165 if( cpuCycles <= 0 ) {
166 try {
167 unsigned int addr = PC<<1;
168 if( (dbgi == 0) || ! dbgi->checkBreak(addr) ) {
169 // Fetch instruction
170 word opcode = flash.readWord( addr );
171 Trace::instance().pc_trace( addr );
172 //std::cout << "Fetch opcode: " << std::hex << opcode << std::dec << std::endl;
173 Instruction & instr = decoder.decode(opcode);
174 cpuCycles = instr(this) - 1;
176 PC++;
178 } catch( util::ImplementationException & ex ) {
179 std::cerr << ex.message() << ": continuing" << std::endl;
180 PC++;
181 cpuCycles = 0;
183 } else {
184 // Waiting for instruction to finish
185 cpuCycles--;
188 return (cpuCycles == 0);