TraceEngine.cpp

Go to the documentation of this file.
00001 /* ES40 emulator.
00002  * Copyright (C) 2007-2008 by the ES40 Emulator Project
00003  *
00004  * Website: http://sourceforge.net/projects/es40
00005  * E-mail : camiel@camicom.com
00006  * 
00007  * This program is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU General Public License
00009  * as published by the Free Software Foundation; either version 2
00010  * of the License, or (at your option) any later version.
00011  * 
00012  * This program is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  * GNU General Public License for more details.
00016  * 
00017  * You should have received a copy of the GNU General Public License
00018  * along with this program; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
00020  * 
00021  * Although this is not required, the author would appreciate being notified of, 
00022  * and receiving any modifications you may make to the source code that might serve
00023  * the general public.
00024  */
00025 
00155 #include "StdAfx.h"
00156 
00157 #if defined(IDB)
00158 #include "TraceEngine.h"
00159 #include "AlphaCPU.h"
00160 #include "System.h"
00161 #include "DPR.h"
00162 #include "Flash.h"
00163 #include "lockstep.h"
00164 #include <signal.h>
00165 
00166 CTraceEngine*   trc;
00167 
00176 inline void write_printable_s(char* dest, const char* org)
00177 {
00178   int cnt = 100;
00179   while(*org && cnt--)
00180   {
00181     *(dest++) = printable(*(org++));
00182   }
00183 
00184   *dest = '\0';
00185 }
00186 
00192 inline u64 real_address(u64 address, CAlphaCPU* c, bool bIBOX)
00193 {
00194   bool  b;
00195   u64   a;
00196 
00197   if(bIBOX && (address & 1))
00198     return address & U64(0xfffffffffffffffc);
00199 
00200   if(!(c->virt2phys(address, &a, ACCESS_READ | NO_CHECK | FAKE, &b, 0)))
00201     return a & (bIBOX ? U64(0xfffffffffffffffc) : U64(0xffffffffffffffff));
00202 
00203   return
00204     ((address & U64(0xfffffffff0000000)) == U64(0x0000000020000000)) ? address -
00205     U64(0x000000001fe00000) :
00206       (
00207         ((address & U64(0xfffffffff0000000)) == U64(0x0000000010000000)) ? address -
00208         U64(0x000000000fffe000) : address
00209       ) & (bIBOX ? U64(0xfffffffffffffffc) : U64(0xffffffffffffffff));
00210 }
00211 
00215 CTraceEngine::CTraceEngine(CSystem* sys)
00216 {
00217   int i;
00218   iNumFunctions = 0;
00219   iNumPRBRs = 0;
00220   cSystem = sys;
00221   for(i = 0; i < 4; i++)
00222   {
00223     asCPUs[0].last_prbr = -1;
00224   }
00225 
00226   current_trace_file = stdout;
00227   bBreakPoint = false;
00228 }
00229 
00233 CTraceEngine::~CTraceEngine(void)
00234 {
00235   int i;
00236   for(i = 0; i < iNumPRBRs; i++)
00237     fclose(asPRBRs[i].f);
00238 }
00239 
00251 void CTraceEngine::trace(CAlphaCPU*  cpu, u64 f, u64 t, bool down, bool up,
00252                          const char*  x, int y)
00253 {
00254   // Not a real jump.
00255   if((t == f + 4) || (t == f))
00256     return;
00257 
00258   // p = new process context
00259   int p = get_prbr(cpu->get_prbr(), cpu->get_hwpcb());
00260 
00261   // o = old process context
00262   int o = asCPUs[cpu->get_cpuid()].last_prbr;
00263 
00264   // Check for process context switch
00265   if(p != o)
00266   {
00267     if(o != -1)
00268     {
00269       /* Process context switch has happened. Print this in the trace files for
00270          both the old and the new process context. */
00271       fprintf(asPRBRs[o].f, "\n==>   Switch to PRBR %08"LL "x %08"LL "x (%s)\n",
00272               asPRBRs[p].prbr, asPRBRs[p].hwpcb, asPRBRs[p].procname);
00273       fprintf(asPRBRs[p].f, "        This is PRBR %08"LL "x %08"LL "x (%s)\n",
00274               asPRBRs[p].prbr, asPRBRs[p].hwpcb, asPRBRs[p].procname);
00275       fprintf(asPRBRs[p].f, "<== Switch from PRBR %08"LL "x %08"LL "x (%s)\n\n",
00276               asPRBRs[o].prbr, asPRBRs[o].hwpcb, asPRBRs[o].procname);
00277     }
00278 
00279     // save process context in cpu record
00280     asCPUs[cpu->get_cpuid()].last_prbr = p;
00281   }
00282 
00283   // Has tracing been temporarily disabled for this process?
00284   if(asPRBRs[p].trc_waitfor)
00285   {
00286     // Have we reached the point where tracing should be re-enabled?
00287     if((t &~U64(0x3)) == asPRBRs[p].trc_waitfor)
00288       asPRBRs[p].trc_waitfor = 0;
00289 
00290     // Don't trace for now.
00291     return;
00292   }
00293 
00294   // Get the physical to/from addresses.
00295   u64 pc_f = real_address(f, cpu, true);
00296   u64 pc_t = real_address(f, cpu, true);
00297 
00298   /* This is where it gets tricky...
00299    *
00300    * If the up parameter is true, we check if the to address of this trace is equal 
00301    * to the from address of a previous trace (that was a function call), or equal to 
00302    * that from address + 4 (next instruction). If this is the case, we consider this
00303    * a function return. (decreasing the trace level).
00304    *
00305    * If this is not the case, we then check if tracing is hidden at this level. If 
00306    * this is the case, we don't trace this call.
00307    *
00308    * Next, we check if the down parameter is false, if this is the case, we handle
00309    * the trace through trace_br.
00310    *
00311    * Otherwise, we treat the trace as a function call (increasing the trace level).
00312    * We will then check if the to address is a known function address. In either
00313    * case we will print the address or the function name and either the formatted
00314    * function list or the first few function argument registers.
00315    */
00316   int oldlvl = asPRBRs[p].trclvl;
00317   int i;
00318   int j;
00319 
00320   if(up)
00321   {
00322     // Check if this is a function return
00323     for(i = oldlvl - 1; i >= 0; i--)
00324     {
00325       // Is this a return to an old "from" address?
00326       if((asPRBRs[p].trcadd[i] == (pc_t - 4)) || (asPRBRs[p].trcadd[i] == (pc_t)))
00327       {
00328         // Yes, return to this address' tracelevel
00329         asPRBRs[p].trclvl = i;
00330         // Should we stop hiding the trace again?
00331         if(asPRBRs[p].trchide > i)
00332           asPRBRs[p].trchide = -1;
00333 
00334         // Is tracing hidden at this level?
00335         if(asPRBRs[p].trchide != -1)
00336           return;
00337 
00338         // Indent to the pevious (higher) trace level
00339         for(j = 0; j < oldlvl; j++)
00340           fprintf(asPRBRs[p].f, " ");
00341         
00342         // And print the from address, and the value of the r0 register (return value)
00343         fprintf(asPRBRs[p].f, "%016"LL "x(%08"LL "x) ($r0 = %"LL "x)\n", f,
00344                 pc_f, cpu->get_r(0, true));
00345 
00346         // Indent to the new (lower) trace level
00347         for(j = 0; j < asPRBRs[p].trclvl; j++)
00348           fprintf(asPRBRs[p].f, " ");
00349 
00350         // Print the to address
00351         fprintf(asPRBRs[p].f, "%016"LL "x(%08"LL "x) <--\n", t, pc_t);
00352         return;
00353       }
00354     }
00355   }
00356 
00357   // Are traces hidden at this level?
00358   if(asPRBRs[p].trchide != -1)
00359     return;
00360 
00361   if(!down)
00362   {
00363     // If we're not allowed to consider this a function call, handle the trace through trace_br
00364     trace_br(cpu, f, t);
00365     return;
00366   }
00367 
00368   // Maximum trace level reached?
00369   if(oldlvl < 700)
00370     asPRBRs[p].trclvl = oldlvl + 1;
00371 
00372   // Set the from address for the old (lower) trace level
00373   asPRBRs[p].trcadd[oldlvl] = pc_f;
00374 
00375   // Is there a special message to print?
00376   if(x)
00377   {
00378     // Indent to the old (lower) trace level
00379     for(i = 0; i < oldlvl; i++)
00380       fprintf(asPRBRs[p].f, " ");
00381 
00382     // Print the special message
00383     fprintf(asPRBRs[p].f, x, y);
00384     fprintf(asPRBRs[p].f, "\n");
00385   }
00386 
00387   // Indent to the old (lower) trace level
00388   for(i = 0; i < oldlvl; i++)
00389     fprintf(asPRBRs[p].f, " ");
00390 
00391   // Print the from address
00392   fprintf(asPRBRs[p].f, "%016"LL "x(%08"LL "x) -->\n", f, pc_f);
00393 
00394   // Indent to the new (higher) trace level
00395   for(i = 0; i < asPRBRs[p].trclvl; i++)
00396     fprintf(asPRBRs[p].f, " ");
00397 
00398   // Check if this is a known function
00399   for(i = 0; i < iNumFunctions; i++)
00400   {
00401     if(asFunctions[i].address == pc_t)
00402     {
00403       // Function found
00404 
00405       // Print function name
00406       fprintf(asPRBRs[p].f, "%016"LL "x(%s)", t, asFunctions[i].fn_name);
00407 
00408       // And print the argument list
00409       write_arglist(cpu, asPRBRs[p].f, asFunctions[i].fn_arglist);
00410       fprintf(asPRBRs[p].f, "\n");
00411 
00412       // If this is a "step-over" function, we hide tracing for higher levels.
00413       if(asFunctions[i].step_over)
00414         asPRBRs[p].trchide = asPRBRs[p].trclvl;
00415       return;
00416     }
00417   }
00418 
00419   // No known function
00420 
00421   // Print the to address
00422   fprintf(asPRBRs[p].f, "%016"LL "x(%08"LL "x)", t, pc_t);
00423 
00424   // Print a default argument list
00425   write_arglist(cpu, asPRBRs[p].f, "(%s|16%, %s|17%, %s|18%, %s|19%)");
00426   fprintf(asPRBRs[p].f, "\n");
00427 }
00428 
00438 void CTraceEngine::trace_br(CAlphaCPU* cpu, u64 f, u64 t)
00439 {
00440   int p;
00441   int o;
00442 
00443   // Get the physical to/from addresses.
00444   u64 pc_f = real_address(f, cpu, true);
00445   u64 pc_t = real_address(t, cpu, true);
00446 
00447   // p = new process context
00448   p = get_prbr(cpu->get_prbr(), cpu->get_hwpcb());
00449 
00450   // o = old process context
00451   o = asCPUs[cpu->get_cpuid()].last_prbr;
00452 
00453   // Has tracing been temporarily disabled for this process?
00454   if(asPRBRs[p].trc_waitfor)
00455   {
00456     // Have we reached the point where tracing should be re-enabled?
00457     if((t &~U64(0x3)) == asPRBRs[p].trc_waitfor)
00458       asPRBRs[p].trc_waitfor = 0;
00459 
00460     // Don't trace for now
00461     return;
00462   }
00463 
00464   // Is tracing hidden at this level?
00465   if(asPRBRs[p].trchide != -1)
00466     return;
00467 
00468   // Check for process context switch
00469   if(p != o)
00470   {
00471     if(o != -1)
00472     {
00473       /* Process context switch has happened. Print this in the trace files for
00474          both the old and the new process context. */
00475       fprintf(asPRBRs[o].f, "\n==>   Switch to PRBR %08"LL "x %08"LL "x (%s)\n",
00476               asPRBRs[p].prbr, asPRBRs[p].hwpcb, asPRBRs[p].procname);
00477       fprintf(asPRBRs[p].f, "        This is PRBR %08"LL "x %08"LL "x (%s)\n",
00478               asPRBRs[p].prbr, asPRBRs[p].hwpcb, asPRBRs[p].procname);
00479       fprintf(asPRBRs[p].f, "<== Switch from PRBR %08"LL "x %08"LL "x (%s)\n\n",
00480               asPRBRs[o].prbr, asPRBRs[o].hwpcb, asPRBRs[o].procname);
00481     }
00482 
00483     // save process context in cpu record
00484     asCPUs[cpu->get_cpuid()].last_prbr = p;
00485   }
00486 
00487   int i;
00488 
00489   // Is this a real jump?
00490   if((pc_t > pc_f + 4) || (pc_t < pc_f))
00491   {
00492     // Indent to the trace level
00493     for(i = 0; i < asPRBRs[p].trclvl; i++)
00494       fprintf(asPRBRs[p].f, " ");
00495     
00496     // Print from address
00497     fprintf(asPRBRs[p].f, "%016"LL "x(%08"LL "x) --+\n", f, pc_f);
00498 
00499     // Indent to the trace level
00500     for(i = 0; i < asPRBRs[p].trclvl; i++)
00501       fprintf(asPRBRs[p].f, " ");
00502 
00503     // Is this a known function?
00504     for(i = 0; i < iNumFunctions; i++)
00505     {
00506       if(asFunctions[i].address == pc_t)
00507       {
00508         // Yes, this is a known function
00509 
00510         // Print the function name
00511         fprintf(asPRBRs[p].f, "%016"LL "x(%s)", t, asFunctions[i].fn_name);
00512 
00513         // Print the argument list
00514         write_arglist(cpu, asPRBRs[p].f, asFunctions[i].fn_arglist);
00515         fprintf(asPRBRs[p].f, " <-+\n");
00516 
00517         // If this is a "step-over" function, we hide tracing for higher levels.
00518         if(asFunctions[i].step_over)
00519           asPRBRs[p].trchide = asPRBRs[p].trclvl;
00520         return;
00521       }
00522     }
00523 
00524     // Print the to address. (No function call, so, no argument list)
00525     fprintf(asPRBRs[p].f, "%016"LL "x(%08"LL "x) <-+\n", t, pc_t);
00526   }
00527 }
00528 
00532 void CTraceEngine::add_function(u64 address, const char*  fn_name, const char*  fn_arglist,
00533                                 bool step_over)
00534 {
00535   asFunctions[iNumFunctions].address = (u32) address &~3;
00536   asFunctions[iNumFunctions].fn_name = _strdup(fn_name);
00537   asFunctions[iNumFunctions].fn_arglist = _strdup(fn_arglist);
00538   asFunctions[iNumFunctions].step_over = step_over;
00539   iNumFunctions++;
00540 }
00541 
00545 void CTraceEngine::set_waitfor(CAlphaCPU* cpu, u64 address)
00546 {
00547   int p;
00548   p = get_prbr(cpu->get_prbr(), cpu->get_hwpcb());
00549 
00550   if(asPRBRs[p].trc_waitfor == 0)
00551     asPRBRs[p].trc_waitfor = address &~U64(0x3);
00552 }
00553 
00557 bool CTraceEngine::get_fnc_name(CAlphaCPU* c, u64 address, char ** p_fn_name)
00558 {
00559   int i;
00560 
00561   u64 a = real_address(address, c, true);
00562 
00563   for(i = 0; i < iNumFunctions; i++)
00564   {
00565     if(asFunctions[i].address == a)
00566     {
00567       *p_fn_name = asFunctions[i].fn_name;
00568       return true;
00569     }
00570   }
00571 
00572   *p_fn_name = (char*) 0;
00573   return false;
00574 }
00575 
00579 int CTraceEngine::get_prbr(u64 prbr, u64 hwpcb)
00580 {
00581   int   i;
00582   char  filename[100];
00583 
00584   for(i = 0; i < iNumPRBRs; i++)
00585   {
00586     if((asPRBRs[i].prbr == prbr) && (asPRBRs[i].hwpcb == hwpcb))
00587     {
00588       if(asPRBRs[i].f == current_trace_file)
00589         return i;
00590       if(!strncmp(asPRBRs[i].procname, cSystem->PtrToMem(prbr + 0x154), 20))
00591       {
00592         current_trace_file = asPRBRs[i].f;
00593         return i;
00594       }
00595 
00596       fclose(asPRBRs[i].f);
00597       break;
00598     }
00599   }
00600 
00601   if(i == iNumPRBRs)
00602   {
00603     asPRBRs[i].generation = 0;
00604     iNumPRBRs++;
00605   }
00606 
00607   asPRBRs[i].generation++;
00608 
00609   asPRBRs[i].prbr = prbr;
00610   asPRBRs[i].hwpcb = hwpcb;
00611   if(prbr > 0 && prbr < (U64(0x1) << cSystem->get_memory_bits()))
00612     strncpy(asPRBRs[i].procname, cSystem->PtrToMem(prbr + 0x154), 20);
00613   else
00614     strcpy(asPRBRs[i].procname, "");
00615   sprintf(filename, "trace_%08"LL "x_%08"LL "x_%02d_%s.trc", prbr, hwpcb,
00616           asPRBRs[i].generation, asPRBRs[i].procname);
00617   asPRBRs[i].f = fopen(filename, "w");
00618   if(asPRBRs[i].f == 0)
00619     printf("Failed to open file!!\n");
00620   asPRBRs[i].trclvl = 0;
00621   asPRBRs[i].trchide = -1;
00622   asPRBRs[i].trc_waitfor = 0;
00623   current_trace_file = asPRBRs[i].f;
00624   printf("Add PRBR: %08"LL "x_%08"LL "x\n", prbr, hwpcb);
00625   return i;
00626 }
00627 
00632 void CTraceEngine::write_arglist(CAlphaCPU* c, FILE* fl, const char* a)
00633 {
00634   char    o[500];
00635   char*   op = o;
00636   const char*   ap = a;
00637   char    f[20];
00638   char*   fp;
00639   char*   rp;
00640   int     r;
00641   u64     value;
00642 
00643   while(*ap)
00644   {
00645     if(*ap == '%')
00646     {
00647       ap++;
00648       fp = f;
00649       *(fp++) = '%';
00650       while(*ap != '%')
00651         *(fp++) = *(ap++);
00652       ap++;
00653       *fp = '\0';
00654 
00655       // now we have a formatter in f.
00656       rp = strchr(f, '|');
00657       *(rp++) = '\0';
00658 
00659       // and the register in rp;
00660       r = atoi(rp);
00661       value = c->get_r(r, true);
00662       if(!strcmp(f, "%s"))
00663       {
00664         sprintf(op, "%"LL "x (", value);
00665         while(*op)
00666           op++;
00667         value = real_address(value, c, false);
00668         if((value > 0) && (value < (U64(0x1) << cSystem->get_memory_bits())))
00669           write_printable_s(op, cSystem->PtrToMem(value));
00670         else
00671           sprintf(op, "INVPTR");
00672         while(*op)
00673           op++;
00674         *(op++) = ')';
00675         *(op) = '\0';
00676       }
00677       else if(!strcmp(f, "%c"))
00678         sprintf(op, "%02"LL "x (%c)", value, printable((char) value));
00679       else if(!strcmp(f, "%d"))
00680         sprintf(op, "%"LL "d", value);
00681       else if(!strcmp(f, "%x"))
00682         sprintf(op, "%"LL "x", value);
00683       else if(!strcmp(f, "%0x"))
00684         sprintf(op, "%016"LL "x", value);
00685       else if(!strcmp(f, "%016x"))
00686         sprintf(op, "%016"LL "x", value);
00687       else if(!strcmp(f, "%08x"))
00688         sprintf(op, "%08"LL "x", value);
00689       else if(!strcmp(f, "%04x"))
00690         sprintf(op, "%04"LL "x", value);
00691       else if(!strcmp(f, "%02x"))
00692         sprintf(op, "%02"LL "x", value);
00693       else
00694         sprintf(op, f, value);
00695       while(*op)
00696         op++;
00697     }
00698     else
00699     {
00700       *(op++) = *(ap++);
00701     }
00702   }
00703 
00704   *op = '\0';
00705 
00706   fprintf(fl, "%s", o);
00707 }
00708 
00713 void CTraceEngine::read_procfile(const char* filename)
00714 {
00715   FILE*   f;
00716   u64     address;
00717   char    linebuffer[1000];
00718   char*   fn_name;
00719   char*   fn_args;
00720   char*   sov;
00721   int     step_over;
00722   int     result;
00723   int     i = 0;
00724 
00725   f = fopen(filename, "r");
00726 
00727   if(f)
00728   {
00729     while(fscanf(f, "%[^\n] ", linebuffer) != EOF)
00730     {
00731       address = U64(0x0);
00732       fn_name = strchr(linebuffer, ';');
00733       if(fn_name)
00734       {
00735         *fn_name = '\0';
00736         fn_name++;
00737         result = sscanf(linebuffer, "%"LL "x", &address);
00738         if((result == 1) && address)
00739         {
00740           fn_args = strchr(fn_name, ';');
00741           if(fn_args)
00742           {
00743             *fn_args = '\0';
00744             fn_args++;
00745             sov = strchr(fn_args, ';');
00746             if(sov)
00747             {
00748               *sov = '\0';
00749               sov++;
00750               result = sscanf(sov, "%d", &step_over);
00751               if(result == 1)
00752               {
00753                 add_function(address, fn_name, fn_args, step_over ? true : false);
00754                 i++;
00755               }
00756             }
00757           }
00758         }
00759       }
00760     }
00761 
00762     fclose(f);
00763     printf("%%IDB-I-RDTRC : Read %d entries from trace-file %s\n", i, filename);
00764   }
00765 }
00766 
00770 void CTraceEngine::trace_dev(const char* text)
00771 {
00772   fprintf(current_trace_file, "%s", text);
00773 }
00774 
00778 FILE* CTraceEngine::trace_file()
00779 {
00780   return current_trace_file;
00781 }
00782 
00786 void CTraceEngine::run_script(const char* filename)
00787 {
00788   char    s[100][100];
00789   int     i;
00790 
00791 #if !defined(LS_SLAVE)
00792   char    c = '\0';
00793   int     j;
00794   FILE*   f = NULL;
00795 
00796   if(filename)
00797   {
00798     f = fopen(filename, "r");
00799     if(!f)
00800     {
00801       printf("%%IDB-F-NOLOAD: File %s could not be opened.\n", filename);
00802       return;
00803     }
00804   }
00805   else
00806   {
00807     printf("This is the ES40 interactive debugger. To start non-interactively, run es40,\n");
00808     printf("Or run this executable (es40_idb) with a last argument of @<script-file>\n");
00809     f = stdin;
00810   }
00811 #endif
00812   for(;;)
00813   {
00814 #if !defined(LS_SLAVE)
00815     if(filename)
00816     {
00817       if(feof(f))
00818         break;
00819     }
00820     else
00821     {
00822       printf("IDB %016"LL "x %c>", theSystem->get_cpu(0)->get_clean_pc(),
00823              (theSystem->get_cpu(0)->get_pc() & U64(0x1)) ? 'P' : '-');
00824     }
00825 #endif
00826     for(i = 0; i < 100;)
00827     {
00828 #if defined(LS_SLAVE)
00829       lockstep_receive(s[i], 100);
00830       if(!strcmp(s[i], "TERM"))
00831         break;
00832 #else
00833       bool  u = false;
00834       for(j = 0; j < 100;)
00835       {
00836         fscanf(f, "%c", &c);
00837         if(c != '\n' && c != '\r' && c != ' ' && c != '\t')
00838         {
00839           s[i][j++] = c;
00840           u = true;
00841         }
00842 
00843         if(c == ' ' || c == '\t' || c == '\n')
00844           break;
00845       }
00846 
00847       s[i][j] = '\0';
00848 
00849       if(u)
00850 #endif
00851       {
00852 #if defined(LS_MASTER)
00853         lockstep_send(s[i]);
00854 #endif
00855         i++;
00856       }
00857 
00858 #if !defined(LS_SLAVE)
00859       if(c == '\n')
00860       {
00861 #if defined(LS_MASTER)
00862         lockstep_send("TERM");
00863 #endif
00864         break;
00865       }
00866 #endif
00867     }
00868 
00869     s[i][0] = '\0';
00870     if(parse(s))
00871       break;
00872   }
00873 
00874 #if !defined(LS_SLAVE)
00875   if(filename)
00876     fclose(f);
00877 #endif
00878 }
00879 
00883 int CTraceEngine::parse(char command[100][100])
00884 {
00885   int i = 0;
00886   int numargs;
00887   int result;
00888   int RunCycles;
00889   u64 iFrom;
00890   u64 iTo;
00891   u64 iJump;
00892 
00893   for(numargs = 0; command[numargs][0] != '\0'; numargs++);
00894 
00895   if((numargs > 0) && (command[0][0] == '#' || command[0][0] == ';'
00896    || command[0][0] == '!' || (command[0][0] == '/' && command[0][1] == '/')))
00897 
00898     //comment
00899     return 0;
00900   switch(numargs)
00901   {
00902   case 0:
00903 
00904     // empty command
00905     return 0;
00906 
00907   case 1:
00908     if(!strncasecmp(command[0], "EXIT", strlen(command[0]))
00909      || !strncasecmp(command[0], "QUIT", strlen(command[0]))) return 1;
00910     if(!strncasecmp(command[0], "HELP", strlen(command[0]))
00911      || !strncasecmp(command[0], "?", strlen(command[0])))
00912     {
00913       printf("                                                                     \n");
00914       printf("Available commands:                                                  \n");
00915       printf("  HELP | ?                                                           \n");
00916       printf("  EXIT | QUIT                                                        \n");
00917       printf("  STEP                                                               \n");
00918       printf("  TRACE [ ON | OFF ]                                                 \n");
00919       printf("  HASHING [ ON | OFF ]                                               \n");
00920       printf("  BREAKPOINT [ OFF | [ > | < | = | INSTRUCTION ] <hex value> ]                         \n");
00921       printf("  DISASSEMBLE [ON | OFF ]                                            \n");
00922 #if defined(DEBUG_TB)
00923       printf("  TBDEBUG [ON | OFF ]                                                \n");
00924 #endif
00925       printf("  LIST [ ALL |<hex address> - <hex address> ]                        \n");
00926       printf("  RUN [ <max cycles> ]                                               \n");
00927       printf("  LOAD [ STATE | DPR | FLASH | CSV ] <file>                          \n");
00928       printf("  SAVE [ STATE | DPR | FLASH ] <file>                                \n");
00929       printf("  JUMP <hex address>                                                 \n");
00930       printf("  PAL [ ON | OFF ]                                                   \n");
00931       printf("  DUMPREGS                                                           \n");
00932       printf("  LOADREG <register> <value>                                         \n");
00933       printf("  LOADFPREG <register> <value>                                       \n");
00934       printf("  @<script-file>                                                     \n");
00935       printf("  # | // | ; | ! <comment>                                           \n");
00936       printf("                                                                     \n");
00937       printf("The words of each command can be abbreviated, e.g. B or BRE for      \n");
00938       printf("BREAKPOINT; S F for save flash.                                      \n");
00939       printf("                                                                     \n");
00940       return 0;
00941     }
00942 
00943     if(!strncasecmp(command[0], "STEP", strlen(command[0])))
00944     {
00945       printf("%%IDB-I-SSTEP : Single step.\n");
00946       theSystem->SingleStep();
00947       return 0;
00948     }
00949 
00950     if(!strncasecmp(command[0], "DUMPREGS", strlen(command[0])))
00951     {
00952       printf("\n==================== SYSTEM STATE =======================\n");
00953       printf("PC: %"LL "x\n", theSystem->get_cpu(0)->get_pc());
00954       printf("Physical PC: %"LL "x\n",
00955              theSystem->get_cpu(0)->get_current_pc_physical());
00956       printf("Instruction count: %"LL "d\n",
00957              theSystem->get_cpu(0)->get_instruction_count());
00958       printf("\n==================== REGISTER VALUES ====================\n");
00959       for(i = 0; i < 32; i++)
00960       {
00961         if(i < 10)
00962           printf("R");
00963         printf("%d:%016"LL "x", i, theSystem->get_cpu(0)->get_r(i, false));
00964         if(i % 4 == 3)
00965           printf("\n");
00966         else
00967           printf(" ");
00968       }
00969 
00970       printf("\n");
00971       for(i = 4; i < 8; i++)
00972       {
00973         if(i < 10)
00974           printf("S");
00975         printf("%d:%016"LL "x", i, theSystem->get_cpu(0)->get_r(i + 32, false));
00976         if(i % 4 == 3)
00977           printf("\n");
00978         else
00979           printf(" ");
00980       }
00981 
00982       for(i = 20; i < 24; i++)
00983       {
00984         if(i < 10)
00985           printf("S");
00986         printf("%d:%016"LL "x", i, theSystem->get_cpu(0)->get_r(i + 32, false));
00987         if(i % 4 == 3)
00988           printf("\n");
00989         else
00990           printf(" ");
00991       }
00992 
00993       printf("\n");
00994       for(i = 0; i < 32; i++)
00995       {
00996         if(i < 10)
00997           printf("F");
00998         printf("%d:%016"LL "x", i, theSystem->get_cpu(0)->get_f(i));
00999         if(i % 4 == 3)
01000           printf("\n");
01001         else
01002           printf(" ");
01003       }
01004 
01005       printf("=========================================================\n");
01006       return 0;
01007     }
01008 
01009     if(!strncasecmp(command[0], "RUN", strlen(command[0])))
01010     {
01011       if(!bBreakPoint)
01012       {
01013         printf("%%IDB-F-NOBRKP: No breakpoint set, press Ctrl-C to end run.\n");
01014 
01015         /* catch CTRL-C and shutdown gracefully */
01016         extern int  got_sigint;
01017         void        sigint_handler(int);
01018         signal(SIGINT, &sigint_handler);
01019         while(!got_sigint)
01020         {
01021           theSystem->SingleStep();
01022         }
01023 
01024         got_sigint = 0;
01025         return 0;
01026       }
01027 
01028       printf("%%IDB-I-RUNBPT: Running until breakpoint found.\n");
01029       switch(iBreakPointMode)
01030       {
01031       case -1:
01032         for(i = 0;; i++)
01033         {
01034           if(theSystem->SingleStep())
01035           {
01036             printf("%%IDB-I-ABORT : Abort run requested (probably from serial port)\n");
01037             break;
01038           }
01039 
01040           if(theSystem->get_cpu(0)->get_clean_pc() < iBreakPoint)
01041           {
01042             printf("%%IDB-I-BRKPT : Breakpoint encountered.\n");
01043             break;
01044           }
01045         }
01046         break;
01047 
01048       case 0:
01049         for(i = 0;; i++)
01050         {
01051           if(theSystem->SingleStep())
01052           {
01053             printf("%%IDB-I-ABORT : Abort run requested (probably from serial port)\n");
01054             break;
01055           }
01056 
01057           if(theSystem->get_cpu(0)->get_clean_pc() == iBreakPoint)
01058           {
01059             printf("%%IDB-I-BRKPT : Breakpoint encountered.\n");
01060             break;
01061           }
01062         }
01063         break;
01064 
01065       case 1:
01066         for(i = 0;; i++)
01067         {
01068           if(theSystem->SingleStep())
01069           {
01070             printf("%%IDB-I-ABORT : Abort run requested (probably from serial port)\n");
01071             break;
01072           }
01073 
01074           if(theSystem->get_cpu(0)->get_clean_pc() > iBreakPoint)
01075           {
01076             printf("%%IDB-I-BRKPT : Breakpoint encountered.\n");
01077             break;
01078           }
01079         }
01080         break;
01081 
01082       case 2:
01083 
01084         // break when the instruction matches.  Great for stopping when
01085         // pal_halt is called!
01086         extern int got_sigint;
01087 
01088         void  sigint_handler(int);
01089         signal(SIGINT, &sigint_handler);
01090         while(1)
01091         {
01092           theSystem->SingleStep();
01093           if(theSystem->get_cpu(0)->get_last_instruction()
01094                == iBreakPointInstruction || got_sigint)
01095           {
01096             printf("%%IDB-I-BRKPT: Found trapped instruction or control-c\n");
01097             break;
01098           }
01099         }
01100 
01101         got_sigint = 0;
01102         break;
01103 
01104       default:
01105         break;
01106       }
01107 
01108       printf("%%IDB-I-ENDRUN: End of run.\n");
01109       return 0;
01110     }
01111 
01112 #if !defined(IDB) || !defined(LS_SLAVE)
01113     if(command[0][0] == '@')
01114     {
01115       run_script(command[0] + 1);
01116       return 0;
01117     }
01118 #endif // !defined(IDB) || !defined(LS_SLAVE)
01119     break;
01120 
01121   case 2:
01122     if(!strncasecmp(command[0], "LIST", strlen(command[0]))
01123      && !strncasecmp(command[1], "ALL", strlen(command[1])))
01124     {
01125       list_all();
01126       return 0;
01127     }
01128 
01129     if(!strncasecmp(command[0], "TRACE", strlen(command[0])))
01130     {
01131       if(!strcasecmp(command[1], "ON"))
01132       {
01133         printf("%%IDB-I-TRCON : Tracing enabled.\n");
01134         bTrace = true;
01135         return 0;
01136       }
01137 
01138       if(!strcasecmp(command[1], "OFF"))
01139       {
01140         printf("%%IDB-I-TRCOFF: Tracing disabled.\n");
01141         bTrace = false;
01142         return 0;
01143       }
01144     }
01145 
01146 #if defined(DEBUG_TB)
01147     if(!strncasecmp(command[0], "TBDEBUG", strlen(command[0])))
01148     {
01149       if(!strcasecmp(command[1], "ON"))
01150       {
01151         printf("%%IDB-I-TBDON : Translation Buffer Debugging enabled.\n");
01152         bTB_Debug = true;
01153         return 0;
01154       }
01155 
01156       if(!strcasecmp(command[1], "OFF"))
01157       {
01158         printf("%%IDB-I-TBDOFF: Translation Buffer Debugging disabled.\n");
01159         bTB_Debug = false;
01160         return 0;
01161       }
01162     }
01163 #endif
01164     if(!strncasecmp(command[0], "HASHING", strlen(command[0])))
01165     {
01166       if(!strcasecmp(command[1], "ON"))
01167       {
01168         printf("%%IDB-I-HSHON : Hashing enabled.\n");
01169         bHashing = true;
01170         return 0;
01171       }
01172 
01173       if(!strcasecmp(command[1], "OFF"))
01174       {
01175         printf("%%IDB-I-HSHOFF: Hashing disabled.\n");
01176         bHashing = false;
01177         return 0;
01178       }
01179     }
01180 
01181     if(!strncasecmp(command[0], "PAL", strlen(command[0])))
01182     {
01183       if(!strcasecmp(command[1], "ON"))
01184       {
01185         printf("%%IDB-I-PALON : PALmode enabled.\n");
01186         theSystem->get_cpu(0)->set_pc(theSystem->get_cpu(0)->get_clean_pc() + 1);
01187         return 0;
01188       }
01189 
01190       if(!strcasecmp(command[1], "OFF"))
01191       {
01192         printf("%%IDB-I-PALOFF: PALmode disabled.\n");
01193         theSystem->get_cpu(0)->set_pc(theSystem->get_cpu(0)->get_clean_pc());
01194         return 0;
01195       }
01196     }
01197 
01198     if(!strncasecmp(command[0], "DISASSEMBLE", strlen(command[0])))
01199     {
01200       if(!strcasecmp(command[1], "ON"))
01201       {
01202         printf("%%IDB-I-DISON : Disassembling enabled.\n");
01203         bDisassemble = true;
01204         return 0;
01205       }
01206 
01207       if(!strcasecmp(command[1], "OFF"))
01208       {
01209         printf("%%IDB-I-DISOFF: Disassembling disabled.\n");
01210         bDisassemble = false;
01211         return 0;
01212       }
01213     }
01214 
01215     if(!strncasecmp(command[0], "BREAKPOINT", strlen(command[0])))
01216     {
01217       if(!strncasecmp(command[1], "OFF", strlen(command[1])))
01218       {
01219         printf("%%IDB-I-BRKOFF: Breakpoint disabled.\n");
01220         bBreakPoint = false;
01221         return 0;
01222       }
01223     }
01224 
01225     if(!strncasecmp(command[0], "RUN", strlen(command[0])))
01226     {
01227       result = sscanf(command[1], "%d", &RunCycles);
01228       if(result != 1)
01229       {
01230         printf("%%IDB-F-INVVAL: Invalid decimal value.\n");
01231         return 0;
01232       }
01233 
01234       if(bBreakPoint)
01235       {
01236         printf("%%IDB-I-RUNCBP: Running until breakpoint found or max cycles reached.\n");
01237         switch(iBreakPointMode)
01238         {
01239         case -1:
01240           for(i = 0; i < RunCycles; i++)
01241           {
01242             if(theSystem->SingleStep())
01243             {
01244               printf("%%IDB-I-ABORT : Abort run requested (probably from serial port)\n");
01245               break;
01246             }
01247 
01248             if(theSystem->get_cpu(0)->get_clean_pc() < iBreakPoint)
01249             {
01250               printf("%%IDB-I-BRKPT : Breakpoint encountered.\n");
01251               break;
01252             }
01253           }
01254           break;
01255 
01256         case 0:
01257           for(i = 0; i < RunCycles; i++)
01258           {
01259             if(theSystem->SingleStep())
01260             {
01261               printf("%%IDB-I-ABORT : Abort run requested (probably from serial port)\n");
01262               break;
01263             }
01264 
01265             if(theSystem->get_cpu(0)->get_clean_pc() == iBreakPoint)
01266             {
01267               printf("%%IDB-I-BRKPT : Breakpoint encountered.\n");
01268               break;
01269             }
01270           }
01271           break;
01272 
01273         case 1:
01274           for(i = 0; i < RunCycles; i++)
01275           {
01276             if(theSystem->SingleStep())
01277             {
01278               printf("%%IDB-I-ABORT : Abort run requested (probably from serial port)\n");
01279               break;
01280             }
01281 
01282             if(theSystem->get_cpu(0)->get_clean_pc() > iBreakPoint)
01283             {
01284               printf("%%IDB-I-BRKPT : Breakpoint encountered.\n");
01285               break;
01286             }
01287           }
01288           break;
01289 
01290         case 2:
01291           for(i = 0; i < RunCycles; i++)
01292           {
01293             if(theSystem->SingleStep())
01294             {
01295               printf("%%IDB-I-ABORT : Abort run requested (probably from serial port)\n");
01296               break;
01297             }
01298 
01299             if(theSystem->get_cpu(0)->get_last_instruction()
01300                  == iBreakPointInstruction)
01301             {
01302               printf("%%IDB-I-BRKPT: Found trapped instruction\n");
01303               break;
01304             }
01305           }
01306           break;
01307 
01308         default:
01309           break;
01310         }
01311       }
01312       else
01313       {
01314         printf("%%IDB-I-RUNCYC: Running until max cycles reached.\n");
01315 
01316         extern int  got_sigint;
01317         void        sigint_handler(int);
01318         signal(SIGINT, &sigint_handler);
01319         for(i = 0; i < RunCycles; i++)
01320         {
01321           if(theSystem->SingleStep())
01322           {
01323             printf("%%IDB-I-ABORT : Abort run requested (probably from serial port)\n");
01324             break;
01325           }
01326 
01327           if(got_sigint)
01328             break;
01329         }
01330 
01331         got_sigint = 0;
01332       }
01333 
01334       printf("%%IDB-I-ENDRUN: End of run.\n");
01335       return 0;
01336     }
01337 
01338     if(!strncasecmp(command[0], "JUMP", strlen(command[0])))
01339     {
01340       result = sscanf(command[1], "%"LL "x", &iJump);
01341       if(result != 1)
01342       {
01343         printf("%%IDB-F-INVVAL: Invalid hexadecimal value.\n");
01344         return 0;
01345       }
01346 
01347       if(iJump & U64(0x3))
01348       {
01349         printf("%%IDB-F-ALGVAL: Value not aligned on a 4-byte bounday.\n");
01350         return 0;
01351       }
01352 
01353       printf("%%IDB-I-JUMPTO: Jumping.\n");
01354       theSystem->get_cpu(0)->set_pc(iJump + (theSystem->get_cpu(0)->get_pc() & U64(0x1)));
01355       return 0;
01356     }
01357     break;
01358 
01359   case 3:
01360     if(!strncasecmp(command[0], "BREAKPOINT", strlen(command[0])))
01361     {
01362       if(!strcmp(command[1], "=") || !strcmp(command[1], ">")
01363        || !strcmp(command[1], "<"))
01364       {
01365         result = sscanf(command[2], "%"LL "x", &iBreakPoint);
01366         if(result != 1)
01367         {
01368           printf("%%IDB-F-INVVAL: Invalid hexadecimal value.\n");
01369           bBreakPoint = false;
01370           return 0;
01371         }
01372 
01373         if(iBreakPoint & U64(0x3))
01374         {
01375           printf("%%IDB-F-ALGVAL: Value not aligned on a 4-byte bounday.\n");
01376           bBreakPoint = false;
01377           return 0;
01378         }
01379 
01380         switch(command[1][0])
01381         {
01382         case '=': iBreakPointMode = 0; break;
01383         case '>': iBreakPointMode = 1; break;
01384         case '<': iBreakPointMode = -1; break;
01385         }
01386 
01387         printf("%%IDB-I-BRKSET: Breakpoint set when PC %c %016"LL "x.\n",
01388                command[1][0], iBreakPoint);
01389         bBreakPoint = true;
01390         return 0;
01391       }
01392       else
01393       {
01394         if(!strncasecmp(command[1], "INSTRUCTION", strlen(command[1])))
01395         {
01396           result = sscanf(command[2], "%"LL "x", &iBreakPointInstruction);
01397           if(result != 1)
01398           {
01399             printf("%%IDB-F-INVVAL: Invalid hexadecimal value.\n");
01400             bBreakPoint = false;
01401             return 0;
01402           }
01403 
01404           printf("%%IDB-I-BRKSET: Breakpoint set when instruction %08x is executed.\n",
01405                iBreakPointInstruction);
01406           bBreakPoint = true;
01407           iBreakPointMode = 2;
01408           return 0;
01409         }
01410       }
01411     }
01412 
01413     if(!strncasecmp(command[0], "LOAD", strlen(command[0])))
01414     {
01415       if(!strncasecmp(command[1], "CSV", strlen(command[1])))
01416       {
01417         read_procfile(command[2]);
01418         return 0;
01419       }
01420 
01421       if(!strncasecmp(command[1], "STATE", strlen(command[1])))
01422       {
01423         theSystem->RestoreState(command[2]);
01424         return 0;
01425       }
01426 
01427       if(!strncasecmp(command[1], "DPR", strlen(command[1])))
01428       {
01429         theDPR->RestoreStateF(command[2]);
01430         return 0;
01431       }
01432 
01433       if(!strncasecmp(command[1], "FLASH", strlen(command[1])))
01434       {
01435         theSROM->RestoreStateF(command[2]);
01436         return 0;
01437       }
01438     }
01439 
01440     if(!strncasecmp(command[0], "SAVE", strlen(command[0])))
01441     {
01442       if(!strncasecmp(command[1], "STATE", strlen(command[1])))
01443       {
01444         theSystem->SaveState(command[2]);
01445         return 0;
01446       }
01447 
01448       if(!strncasecmp(command[1], "DPR", strlen(command[1])))
01449       {
01450         theDPR->SaveStateF(command[2]);
01451         return 0;
01452       }
01453 
01454       if(!strncasecmp(command[1], "FLASH", strlen(command[1])))
01455       {
01456         theSROM->SaveStateF(command[2]);
01457         return 0;
01458       }
01459     }
01460 
01461     if(!strncasecmp(command[0], "LOADREG", strlen(command[0])))
01462     {
01463       int reg;
01464       u64 value;
01465       result = sscanf(command[1], "%d", &reg);
01466       if(result != 1 || reg > 31)
01467       {
01468         printf("%%IDB-F-INVREG: Invalid register number.\n");
01469         return 0;
01470       }
01471 
01472       result = sscanf(command[2], "%"LL "x", &value);
01473       if(result != 1)
01474       {
01475         printf("%%IDB-F-INVVAL: Invalid hexadecimal value.\n");
01476         return 0;
01477       }
01478 
01479       theSystem->get_cpu(0)->set_r(reg, value);
01480       return 0;
01481     }
01482 
01483     if(!strncasecmp(command[0], "LOADFPREG", strlen(command[0])))
01484     {
01485       int reg;
01486       u64 value;
01487       result = sscanf(command[1], "%d", &reg);
01488       if(result != 1 || reg > 31)
01489       {
01490         printf("%%IDB-F-INVREG: Invalid register number.\n");
01491         return 0;
01492       }
01493 
01494       result = sscanf(command[2], "%"LL "x", &value);
01495       if(result != 1)
01496       {
01497         printf("%%IDB-F-INVVAL: Invalid hexadecimal value.\n");
01498         return 0;
01499       }
01500 
01501       theSystem->get_cpu(0)->set_f(reg, value);
01502       return 0;
01503     }
01504     break;
01505 
01506   case 4:
01507     if(!strncasecmp(command[0], "LIST", strlen(command[0]))
01508      && !strcmp(command[2], "-"))
01509     {
01510       result = sscanf(command[1], "%"LL "x", &iFrom);
01511       if(result == 1)
01512         result = sscanf(command[3], "%"LL "x", &iTo);
01513       if(result != 1)
01514       {
01515         printf("%%IDB-F-INVVAL: Invalid hexadecimal value.\n");
01516         return 0;
01517       }
01518 
01519       if(iFrom & U64(0x3) || iTo & U64(0x3))
01520       {
01521         printf("%%IDB-F-ALGVAL: Value not aligned on a 4-byte bounday.\n");
01522         return 0;
01523       }
01524 
01525       if(iFrom > iTo)
01526       {
01527         printf("%%IDB-F-FRLTTO: From value exceeds to value.\n");
01528         return 0;
01529       }
01530 
01531       theSystem->get_cpu(0)->listing(iFrom, iTo);
01532       return 0;
01533     }
01534     break;
01535 
01536   default:
01537     break;
01538   }
01539 
01540   printf("%%IDB-F-SYNTAX: Syntax error. Type \"?\" or \"HELP\" for help.\n");
01541   return 0;
01542 }
01543 
01544 struct sRegion
01545 {
01546   u64               from;
01547   u64               to;
01548   struct sRegion*   pNext;
01549 };
01550 
01554 void CTraceEngine::list_all()
01555 {
01556   struct sRegion*   pR = NULL;
01557   struct sRegion **  ppN = &pR;
01558   struct sRegion*   p = NULL;
01559   int               f = 0;
01560   int               t = 0;
01561   int               ms = 1 << (theSystem->get_memory_bits() - 3);
01562   u64*              pM = (u64*) theSystem->PtrToMem(0);
01563 
01564   for(;;)
01565   {
01566     while
01567     (
01568       (!pM[f] || pM[f] == U64(0xefefefefefefefef) || pM[f] == U64(0xffffffffffffffff))
01569     && f < ms
01570     )
01571     {
01572       f++;
01573       if(!(f & 0x1ffff))
01574         printf(".");
01575     }
01576 
01577     if(f >= ms)
01578       break;
01579     t = f;
01580     for(;;)
01581     {
01582       while
01583       (
01584         pM[t]
01585       && pM[t] != U64(0xefefefefefefefef)
01586       && pM[t] != U64(0xffffffffffffffff)
01587       && t < ms
01588       )
01589       {
01590         t++;
01591         if(!(t & 0x1ffff))
01592           printf("x");
01593       }
01594 
01595       if(t + 3 < ms)
01596       {
01597         if((!pM[t + 1] || pM[t + 1] == U64(0xefefefefefefefef)
01598          || pM[t + 1] == U64(0xffffffffffffffff)) && (!pM[t + 2]
01599          || pM[t + 2] == U64(0xefefefefefefefef)
01600          || pM[t + 2] == U64(0xffffffffffffffff)) && (!pM[t + 3]
01601          || pM[t + 3] == U64(0xefefefefefefefef)
01602          || pM[t + 3] == U64(0xffffffffffffffff)))
01603           break;
01604       }
01605 
01606       if(t >= ms)
01607         break;
01608       t++;
01609       if(!(t & 0x1ffff))
01610         printf("x");
01611     }
01612 
01613     *ppN = new sRegion;
01614     (*ppN)->from = (u64) f * 8;
01615     (*ppN)->to = (u64) ((t - 1) * 8) + 4;
01616     (*ppN)->pNext = NULL;
01617     ppN = &((*ppN)->pNext);
01618     f = t;
01619   }
01620 
01621   printf("\n");
01622 
01623   p = pR;
01624 
01625   while(p)
01626   {
01627     printf("\n======== DISASSEMBLING %08"LL "x TO %08"LL "x ========\n\n",
01628            p->from, p->to);
01629     theSystem->get_cpu(0)->listing(p->from, p->to);
01630     p = p->pNext;
01631   }
01632 }
01633 
01634 bool  bTrace = false;
01635 bool  bDisassemble = false;
01636 bool  bHashing = false;
01637 bool  bListing = false;
01638 
01639 #if defined(DEBUG_TB)
01640 bool  bTB_Debug = false;
01641 #endif
01642 #endif // IDB

SourceForge.net Logo
Project space on SourceForge.net