00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include "hwstack.h"
00027 #include "avrerror.h"
00028 #include "avrmalloc.h"
00029 #include "flash.h"
00030 #include <assert.h>
00031 #include <cstdio>
00032
00033 using namespace std;
00034
00035 HWStack::HWStack(AvrDevice *c):
00036 m_ThreadList(*c),
00037 core(c) {
00038 Reset();
00039 }
00040
00041 void HWStack::Reset(void) {
00042 returnPointList.clear();
00043 stackPointer = 0;
00044 lowestStackPointer = 0;
00045 }
00046
00047 void HWStack::CheckReturnPoints() {
00048 typedef multimap<unsigned long, Funktor *>::iterator I;
00049 pair<I,I> l = returnPointList.equal_range(stackPointer);
00050
00051 for(I i = l.first; i != l.second; i++) {
00052 (*(i->second))();
00053 delete i->second;
00054 }
00055 returnPointList.erase(l.first, l.second);
00056 }
00057
00058 void HWStack::SetReturnPoint(unsigned long stackPointer, Funktor *f) {
00059 returnPointList.insert(make_pair(stackPointer, f));
00060 }
00061
00062 HWStackSram::HWStackSram(AvrDevice *c, int bs, bool initRE):
00063 HWStack(c),
00064 TraceValueRegister(c, "STACK"),
00065 sph_reg(this, "SPH",
00066 this, &HWStackSram::GetSph, &HWStackSram::SetSph),
00067 spl_reg(this, "SPL",
00068 this, &HWStackSram::GetSpl, &HWStackSram::SetSpl),
00069 initRAMEND(initRE) {
00070 stackCeil = 1 << bs;
00071 Reset();
00072 }
00073
00074 void HWStackSram::Reset() {
00075 returnPointList.clear();
00076 if(initRAMEND)
00077 stackPointer = core->GetMemIRamSize() +
00078 core->GetMemIOSize() +
00079 core->GetMemRegisterSize() - 1;
00080 else
00081 stackPointer = 0;
00082 lowestStackPointer = stackPointer;
00083 }
00084
00085 void HWStackSram::Push(unsigned char val) {
00086 core->SetRWMem(stackPointer, val);
00087 stackPointer--;
00088 stackPointer %= stackCeil;
00089
00090 spl_reg.hardwareChange(stackPointer & 0x0000ff);
00091 sph_reg.hardwareChange((stackPointer & 0x00ff00)>>8);
00092
00093 if(core->trace_on == 1)
00094 traceOut << "SP=0x" << hex << stackPointer << " 0x" << int(val) << dec << " ";
00095 m_ThreadList.OnPush();
00096 CheckReturnPoints();
00097
00098
00099 if(lowestStackPointer > stackPointer)
00100 lowestStackPointer = stackPointer;
00101 }
00102
00103 unsigned char HWStackSram::Pop() {
00104 stackPointer++;
00105 stackPointer %= stackCeil;
00106
00107 spl_reg.hardwareChange(stackPointer & 0x0000ff);
00108 sph_reg.hardwareChange((stackPointer & 0x00ff00)>>8);
00109
00110 if(core->trace_on == 1)
00111 traceOut << "SP=0x" << hex << stackPointer << " 0x" << int(core->GetRWMem(stackPointer)) << dec << " ";
00112 m_ThreadList.OnPop();
00113 CheckReturnPoints();
00114 return core->GetRWMem(stackPointer);
00115 }
00116
00117 void HWStackSram::PushAddr(unsigned long addr) {
00118
00119 Push(addr & 0xff);
00120 addr >>= 8;
00121 Push(addr & 0xff);
00122 if(core->PC_size == 3) {
00123 addr >>= 8;
00124 Push(addr & 0xff);
00125 }
00126 }
00127
00128 unsigned long HWStackSram::PopAddr() {
00129
00130 unsigned long val = Pop();
00131 val <<= 8;
00132 val += Pop();
00133 if(core->PC_size == 3) {
00134 val <<= 8;
00135 val += Pop();
00136 }
00137 return val;
00138 }
00139
00140 void HWStackSram::SetSpl(unsigned char val) {
00141 uint32_t oldSP = stackPointer;
00142 stackPointer &= ~0xff;
00143 stackPointer += val;
00144 stackPointer %= stackCeil;
00145
00146 spl_reg.hardwareChange(stackPointer & 0x0000ff);
00147
00148 if(core->trace_on == 1)
00149 traceOut << "SP=0x" << hex << stackPointer << dec << " " ;
00150 if(oldSP != stackPointer)
00151 m_ThreadList.OnSPWrite(stackPointer);
00152 CheckReturnPoints();
00153 }
00154
00155 void HWStackSram::SetSph(unsigned char val) {
00156 uint32_t oldSP = stackPointer;
00157 if(stackCeil <= 0x100)
00158 avr_warning("assignment to non existent SPH (value=0x%x)", (unsigned int)val);
00159 stackPointer &= ~0xff00;
00160 stackPointer += val << 8;
00161 stackPointer %= stackCeil;
00162
00163 sph_reg.hardwareChange((stackPointer & 0x00ff00)>>8);
00164
00165 if(core->trace_on == 1)
00166 traceOut << "SP=0x" << hex << stackPointer << dec << " " ;
00167 if(oldSP != stackPointer)
00168 m_ThreadList.OnSPWrite(stackPointer);
00169 CheckReturnPoints();
00170 }
00171
00172 unsigned char HWStackSram::GetSph() {
00173 OnSPReadByTarget();
00174 return (stackPointer & 0xff00) >> 8;
00175 }
00176
00177 unsigned char HWStackSram::GetSpl() {
00178 OnSPReadByTarget();
00179 return stackPointer & 0xff;
00180 }
00181 void HWStackSram::OnSPReadByTarget() {
00182 m_ThreadList.OnSPRead(stackPointer);
00183 }
00184
00185 ThreeLevelStack::ThreeLevelStack(AvrDevice *c):
00186 HWStack(c),
00187 TraceValueRegister(c, "STACK") {
00188 stackArea = avr_new(unsigned long, 3);
00189 trace_direct(this, "PTR", &stackPointer);
00190 Reset();
00191 }
00192
00193 ThreeLevelStack::~ThreeLevelStack() {
00194 avr_free(stackArea);
00195 }
00196
00197 void ThreeLevelStack::Reset(void) {
00198 returnPointList.clear();
00199 stackPointer = 3;
00200 lowestStackPointer = stackPointer;
00201 }
00202
00203 void ThreeLevelStack::Push(unsigned char val) {
00204 avr_error("Push method isn't available on TreeLevelStack");
00205 }
00206
00207 unsigned char ThreeLevelStack::Pop() {
00208 avr_error("Pop method isn't available on TreeLevelStack");
00209 return 0;
00210 }
00211
00212 void ThreeLevelStack::PushAddr(unsigned long addr) {
00213 stackArea[2] = stackArea[1];
00214 stackArea[1] = stackArea[0];
00215 stackArea[0] = addr;
00216 if(stackPointer > 0)
00217 stackPointer--;
00218 if(lowestStackPointer > stackPointer)
00219 lowestStackPointer = stackPointer;
00220 if(stackPointer == 0)
00221 avr_warning("stack overflow");
00222 }
00223
00224 unsigned long ThreeLevelStack::PopAddr() {
00225 unsigned long val = stackArea[0];
00226 stackArea[0] = stackArea[1];
00227 stackArea[1] = stackArea[2];
00228 stackPointer++;
00229 if(stackPointer > 3) {
00230 stackPointer = 3;
00231 avr_warning("stack underflow");
00232 }
00233 return val;
00234 }
00235
00236 ThreadList::ThreadList(AvrDevice & core)
00237 : m_core(core)
00238 {
00239 m_phase_of_switch = eNormal;
00240 m_last_SP_read = 0x0000;
00241 m_last_SP_writen = 0x0000;
00242 m_cur_thread = 0;
00243
00244 Thread * main_thread = new Thread;
00245 main_thread->m_sp = 0;
00246 main_thread->m_ip = 0;
00247 main_thread->m_alive = true;
00248 m_threads.push_back(main_thread);
00249 }
00250 ThreadList::~ThreadList()
00251 {
00252 OnReset();
00253 }
00254 void ThreadList::OnReset()
00255 {
00256 for(unsigned int i = 0; i < m_threads.size(); i++) {
00257 Thread * p = m_threads[i];
00258 delete p;
00259 }
00260 m_threads.resize(0);
00261 }
00262
00263 void ThreadList::OnCall()
00264 {
00265 m_on_call_sp = m_core.stack->GetStackPointer();
00266 assert(m_on_call_sp != 0x0000);
00267 m_on_call_ip = m_core.PC * 2;
00268 Thread * old = m_threads[m_cur_thread];
00269 for(unsigned int i = 0; i < 32; i++) {
00270 old->registers[i] = m_core.GetCoreReg(i);
00271 }
00272
00273 if(0xc9c <= m_on_call_ip && m_on_call_ip <= 0xca4)
00274 fprintf(stderr, "Pripravit se ke startu: proc_switch()\n");
00275 if(0x80a <= m_on_call_ip && m_on_call_ip <= 0x810)
00276 fprintf(stderr, "Pripravit se ke startu: asm_switch_context()\n");
00277 }
00278
00279 void ThreadList::OnSPRead(int SP_value)
00280 {
00281 assert(0 <= SP_value && SP_value <= 0xFFFF);
00282 assert(0 != SP_value);
00283 m_phase_of_switch = eReaded;
00284 m_last_SP_read = SP_value;
00285 }
00286
00287 void ThreadList::OnSPWrite( int new_SP )
00288 {
00289 if( ! m_core.Flash->LooksLikeContextSwitch(m_core.PC*2))
00290 return;
00291 m_phase_of_switch = (m_phase_of_switch==eWritten) ? eWritten2 : eWritten;
00292 m_last_SP_writen = new_SP;
00293 }
00294
00295 void ThreadList::OnPush()
00296 {
00297 m_phase_of_switch = eNormal;
00298 m_last_SP_read = 0x0000;
00299 m_last_SP_writen = 0x0000;
00300 }
00301
00302 void ThreadList::OnPop()
00303 {
00304 if(m_phase_of_switch != eWritten2)
00305 {
00306 m_phase_of_switch = eNormal;
00307 m_last_SP_read = 0x0000;
00308 m_last_SP_writen = 0x0000;
00309 return;
00310 }
00311 m_phase_of_switch = eNormal;
00312 int addr = m_core.PC * 2;
00313 assert(0 <= m_cur_thread && m_cur_thread < (int) m_threads.size());
00314 Thread * old = m_threads[m_cur_thread];
00315 assert(m_on_call_sp != 0x0000);
00316 old->m_sp = m_on_call_sp;
00317 old->m_ip = m_on_call_ip;
00318 old->m_alive = true;
00319
00320 int n = GetThreadBySP(m_last_SP_writen);
00321 if(n == -1) {
00322 m_threads.push_back( new Thread);
00323 n = m_threads.size() - 1;
00324 }
00325 Thread * new_thread = m_threads[n];
00326 new_thread->m_sp = 0x0000;
00327 new_thread->m_ip = 0x0000;
00328 new_thread->m_alive = true;
00329
00330 if(global_verbose_on)
00331 fprintf(stderr, "Context switch at PC 0x%05x from thread %d to %d\n", addr, m_cur_thread, n);
00332 m_cur_thread = n;
00333 }
00334
00335 int ThreadList::GetThreadBySP(int sp) const
00336 {
00337 for(unsigned int i = 0; i < m_threads.size(); i++) {
00338 Thread * p = m_threads[i];
00339 if(p->m_sp == sp)
00340 return i;
00341 }
00342 return -1;
00343 }
00344
00345 int ThreadList::GetCurrentThreadForGDB() const
00346 {
00347 return m_cur_thread + 1;
00348 }
00349
00350 const Thread * ThreadList::GetThreadFromGDB(int thread_id) const
00351 {
00352 assert(thread_id >= 1);
00353 unsigned int index = thread_id - 1;
00354 assert(index < m_threads.size());
00355 return m_threads[index];
00356 }
00357 bool ThreadList::IsGDBThreadAlive(int thread_id) const
00358 {
00359 assert(thread_id >= 1);
00360 unsigned int index = thread_id - 1;
00361 if(index >= m_threads.size())
00362 return false;
00363
00364 Thread * p = m_threads[index];
00365 return p->m_alive;
00366 }
00367 int ThreadList::GetCount() const
00368 {
00369 return m_threads.size();
00370 }
00371
00372