* sim/ucsim/cmd.src/newcmd.cc, sim/ucsim/cmd.src/newcmdcl.h,
[fw/sdcc] / sim / ucsim / sim.src / uc.cc
index 026648b0b50088e26106200c6add1570d3af8a1f..9eff9810db352a385024d3da06a5bd4f2bdee78f 100644 (file)
@@ -30,14 +30,33 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #include <stdio.h>
 #include <stdlib.h>
 #include <errno.h>
+#include <ctype.h>
 #include "i_string.h"
 
+// prj
+#include "globals.h"
+#include "utils.h"
+
+// cmd.src
+#include "newcmdcl.h"
+#include "cmduccl.h"
+#include "bpcl.h"
+#include "getcl.h"
+#include "setcl.h"
+#include "infocl.h"
+#include "timercl.h"
+#include "cmdstatcl.h"
+#include "cmdmemcl.h"
+#include "cmdutil.h"
+
+// local, sim.src
 #include "uccl.h"
 #include "hwcl.h"
 #include "memcl.h"
 #include "simcl.h"
 #include "itsrccl.h"
 
+static class cl_uc_error_registry uc_error_registry;
 
 /*
  * Clock counter
@@ -50,14 +69,10 @@ cl_ticker::cl_ticker(int adir, int in_isr, char *aname)
     options|= TICK_INISR;
   dir= adir;
   ticks= 0;
-  name= aname?strdup(aname):0;
+  set_name(aname);
 }
 
-cl_ticker::~cl_ticker(void)
-{
-  if (name)
-    free(name);
-}
+cl_ticker::~cl_ticker(void) {}
 
 int
 cl_ticker::tick(int nr)
@@ -79,11 +94,32 @@ cl_ticker::get_rtime(double xtal)
 void
 cl_ticker::dump(int nr, double xtal, class cl_console *con)
 {
-  con->printf("timer #%d(\"%s\") %s%s: %g sec (%lu clks)\n",
-             nr, name?name:"unnamed",
-             (options&TICK_RUN)?"ON":"OFF",
-             (options&TICK_INISR)?",ISR":"",
-             get_rtime(xtal), ticks);
+  con->dd_printf("timer #%d(\"%s\") %s%s: %g sec (%lu clks)\n",
+                 nr, get_name("unnamed"),
+                 (options&TICK_RUN)?"ON":"OFF",
+                 (options&TICK_INISR)?",ISR":"",
+                 get_rtime(xtal), ticks);
+}
+
+
+/*
+ * Options of uc
+ */
+
+cl_xtal_option::cl_xtal_option(class cl_uc *the_uc):
+  cl_optref(the_uc)
+{
+  uc= the_uc;
+}
+
+void
+cl_xtal_option::option_changed(void)
+{
+  if (!uc)
+    return;
+  double d;
+  option->get_value(&d);
+  uc->xtal= d;
 }
 
 
@@ -95,65 +131,93 @@ cl_ticker::dump(int nr, double xtal, class cl_console *con)
 cl_uc::cl_uc(class cl_sim *asim):
   cl_base()
 {
-  int i;
+  //int i;
   sim = asim;
-  mems= new cl_list(MEM_TYPES, 1);
-  hws = new cl_list(2, 1);
-  options= new cl_list(2, 2);
-  for (i= MEM_ROM; i < MEM_TYPES; i++)
-    mems->add(0);
+  //mems= new cl_list(MEM_TYPES, 1);
+  memchips= new cl_list(2, 2, "memchips");
+  address_spaces= new cl_address_space_list(this);
+  //address_decoders= new cl_list(2, 2);
+  rom= 0;
+
+  hws = new cl_hws();
+  //options= new cl_list(2, 2);
+  //for (i= MEM_ROM; i < MEM_TYPES; i++) mems->add(0);
+  xtal_option= new cl_xtal_option(this);
+  xtal_option->init();
   ticks= new cl_ticker(+1, 0, "time");
   isr_ticks= new cl_ticker(+1, TICK_INISR, "isr");
   idle_ticks= new cl_ticker(+1, TICK_IDLE, "idle");
-  counters= new cl_list(2, 2);
-  it_levels= new cl_list(2, 2);
-  it_sources= new cl_list(2, 2);
+  counters= new cl_list(2, 2, "counters");
+  it_levels= new cl_list(2, 2, "it levels");
+  it_sources= new cl_irqs(2, 2);
   class it_level *il= new it_level(-1, 0, 0, 0);
   it_levels->push(il);
-  st_ops= new cl_list(2, 2);
+  stack_ops= new cl_list(2, 2, "stack operations");
+  errors= new cl_list(2, 2, "errors in uc");
+  events= new cl_list(2, 2, "events in uc");
   sp_max= 0;
   sp_avg= 0;
+  inst_exec= DD_FALSE;
 }
 
 
 cl_uc::~cl_uc(void)
 {
-  delete mems;
+  //delete mems;
   delete hws;
-  delete options;
+  //delete options;
   delete ticks;
   delete isr_ticks;
   delete idle_ticks;
   delete counters;
+  events->disconn_all();
+  delete events;
   delete fbrk;
   delete ebrk;
   delete it_levels;
   delete it_sources;
-  delete st_ops;
+  delete stack_ops;
+  errors->free_all();
+  delete errors;
+  delete xtal_option;
+  delete address_spaces;
+  delete memchips;
+  //delete address_decoders;
 }
 
 
 int
 cl_uc::init(void)
 {
-  int mc;
+  int i;
 
+  set_name("controller");
   cl_base::init();
-  if (!(sim->arg_avail('X')) ||
-      sim->get_farg('X', 0) == 0)
-    xtal= 11059200;
+  if (xtal_option->use("xtal"))
+    xtal= xtal_option->get_value(xtal);
   else
-    xtal= sim->get_farg('X', 0);
-  for (mc= MEM_ROM; mc < MEM_TYPES; mc++)
-    {
-      class cl_mem *m= mk_mem((enum mem_class)mc);
-      mems->put_at(mc, m);
-    }
-  ebrk= new brk_coll(2, 2, (class cl_rom *)mem(MEM_ROM));
-  fbrk= new brk_coll(2, 2, (class cl_rom *)mem(MEM_ROM));
+    xtal= 11059200;
+  make_memories();
+  rom= address_space(MEM_ROM_ID);
+  ebrk= new brk_coll(2, 2, rom);
+  fbrk= new brk_coll(2, 2, rom);
   fbrk->Duplicates= DD_FALSE;
+  brk_counter= 0;
   mk_hw_elements();
   reset();
+  class cl_cmdset *cs= sim->app->get_commander()->cmdset;
+  build_cmdset(cs);
+
+  for (i= 0; i < sim->app->in_files->count; i++)
+    {
+      char *fname= (char *)(sim->app->in_files->at(i));
+      long l;
+      if ((l= read_hex_file(fname)) >= 0)
+        {
+          sim->app->get_commander()->all_printf("%ld words read from %s\n",
+                                                l, fname);
+        }
+    }
   return(0);
 }
 
@@ -168,7 +232,7 @@ cl_uc::reset(void)
 {
   class it_level *il;
 
-  PC= 0;
+  instPC= PC= 0;
   state = stGO;
   ticks->ticks= 0;
   isr_ticks->ticks= 0;
@@ -176,7 +240,7 @@ cl_uc::reset(void)
   /*FIXME should we clear user counters?*/
   il= (class it_level *)(it_levels->top());
   while (il &&
-        il->level >= 0)
+         il->level >= 0)
     {
       il= (class it_level *)(it_levels->pop());
       delete il;
@@ -184,131 +248,448 @@ cl_uc::reset(void)
     }
   sp_max= 0;
   sp_avg= 0;
+  
+  stack_ops->free_all();
+
+  int i;
+  for (i= 0; i < hws->count; i++)
+    {
+      class cl_hw *hw= (class cl_hw *)(hws->at(i));
+      hw->reset();
+    }
 }
 
 /*
  * Making elements
  */
 
-class cl_mem *
-cl_uc::mk_mem(enum mem_class type)
-{
-  class cl_mem *m;
-
-  if (get_mem_size(type) <= 0)
-    return(0);
-  if (type == MEM_ROM)
-    m= new cl_rom(get_mem_size(type), get_mem_width(type));
-  else
-    m= new cl_mem(type, get_mem_size(type), get_mem_width(type));
-  m->init();
-  return(m);
-}
+void
+cl_uc::make_memories(void)
+{}
 
-t_addr
-cl_uc::get_mem_size(enum mem_class type)
+/*t_addr
+cl_uc::get_mem_size(char *id)
 {
-  switch (type)
-    {
-    case MEM_ROM: return(0x10000);
-    case MEM_XRAM: return(0x10000);
-    case MEM_IRAM: return(0x100);
-    case MEM_SFR: return(0x100);
-    case MEM_TYPES:
-    default: return(0);
-    }
-  return(0);
+  class cl_memory *m= memory(id);
+  return(m?(m->get_size()):0);
 }
 
 int
-cl_uc::get_mem_width(enum mem_class type)
+cl_uc::get_mem_width(char *id)
 {
-  return(8);
+  class cl_memory *m= memory(id);
+  return(m?(m->width):8);
 }
-
+*/
 void
 cl_uc::mk_hw_elements(void)
 {
 }
 
+void
+cl_uc::build_cmdset(class cl_cmdset *cmdset)
+{
+  class cl_cmd *cmd;
+  class cl_super_cmd *super_cmd;
+  class cl_cmdset *cset;
+
+  cmdset->add(cmd= new cl_state_cmd("state", 0,
+"state              State of microcontroller",
+"long help of state"));
+  cmd->init();
+
+#ifdef STATISTIC
+  cmdset->add(cmd= new cl_statistic_cmd("statistic", 0,
+"statistic [mem [startaddr [endaddr]]]\n"
+"                   Statistic of memory accesses",
+"long help of statistic"));
+  cmd->init();
+#endif
+
+  cmdset->add(cmd= new cl_file_cmd("file", 0,
+"file \"FILE\"        Load FILE into ROM",
+"long help of file"));
+  cmd->init();
+  cmd->add_name("load");
+
+  cmdset->add(cmd= new cl_dl_cmd("download", 0,
+"download           Load (intel.hex) data",
+"long help of download"));
+  cmd->init();
+  cmd->add_name("dl");
+
+  cmdset->add(cmd= new cl_pc_cmd("pc", 0,
+"pc [addr]          Set/get PC",
+"long help of pc"));
+  cmd->init();
+
+  cmdset->add(cmd= new cl_reset_cmd("reset", 0,
+"reset              Reset",
+"long help of reset"));
+  cmd->init();
+
+  cmdset->add(cmd= new cl_dump_cmd("dump", DD_TRUE,
+"dump memory_type [start [stop [bytes_per_line]]]\n"
+"                   Dump memory of specified type\n"
+"dump bit...        Dump bits",
+"long help of dump"));
+  cmd->init();
+
+  cmdset->add(cmd= new cl_dch_cmd("dch", DD_TRUE,
+"dch [start [stop]] Dump code in hex form",
+"long help of dch"));
+  cmd->init();
+
+  cmdset->add(cmd= new cl_dc_cmd("dc", DD_TRUE,
+"dc [start [stop]]  Dump code in disass form",
+"long help of dc"));
+  cmd->init();
+
+  cmdset->add(cmd= new cl_disassemble_cmd("disassemble", DD_TRUE,
+"disassemble [start [offset [lines]]]\n"
+"                   Disassemble code",
+"long help of disassemble"));
+  cmd->init();
+
+  cmdset->add(cmd= new cl_fill_cmd("fill", 0,
+"fill memory_type start end data\n"
+"                   Fill memory region with data",
+"long help of fill"));
+  cmd->init();
+
+  cmdset->add(cmd= new cl_where_cmd("where", 0,
+"where memory_type data...\n"
+"                   Case unsensitive search for data",
+"long help of where"));
+  cmd->init();
+
+  cmdset->add(cmd= new cl_Where_cmd("Where", 0,
+"Where memory_type data...\n"
+"                   Case sensitive search for data",
+"long help of Where"));
+  cmd->init();
+
+  cmdset->add(cmd= new cl_break_cmd("break", 0,
+"break addr [hit]   Set fix breakpoint\n"
+"break mem_type r|w addr [hit]\n"
+"                   Set fix event breakpoint",
+"long help of break"));
+  cmd->init();
+
+  cmdset->add(cmd= new cl_tbreak_cmd("tbreak", 0,
+"tbreak addr [hit]  Set temporary breakpoint\n"
+"tbreak mem_type r|w addr [hit]\n"
+"                   Set temporary event breakpoint",
+"long help of tbreak"));
+  cmd->init();
+
+  cmdset->add(cmd= new cl_clear_cmd("clear", 0,
+"clear [addr...]    Clear fix breakpoint",
+"long help of clear"));
+  cmd->init();
+
+  cmdset->add(cmd= new cl_delete_cmd("delete", 0,
+"delete [nr...]     Delete breakpoint(s)",
+"long help of clear"));
+  cmd->init();
+
+  {
+    super_cmd= (class cl_super_cmd *)(cmdset->get_cmd("get"));
+    if (super_cmd)
+      cset= super_cmd->commands;
+    else {
+      cset= new cl_cmdset();
+      cset->init();
+    }
+    cset->add(cmd= new cl_get_sfr_cmd("sfr", 0,
+"get sfr address...\n"
+"                   Get value of addressed SFRs",
+"long help of get sfr"));
+    cmd->init();
+    /*cset->add(cmd= new cl_get_option_cmd("option", 0,
+"get option name\n"
+"                   Get value of an option",
+"long help of get option"));
+cmd->init();*/
+  }
+  if (!super_cmd)
+    {
+      cmdset->add(cmd= new cl_super_cmd("get", 0,
+"get subcommand     Get, see `get' command for more help",
+"long help of get", cset));
+      cmd->init();
+    }
+
+  {
+    super_cmd= (class cl_super_cmd *)(cmdset->get_cmd("set"));
+    if (super_cmd)
+      cset= super_cmd->commands;
+    else {
+      cset= new cl_cmdset();
+      cset->init();
+    }
+    cset->add(cmd= new cl_set_mem_cmd("memory", 0,
+"set memory memory_type address data...\n"
+"                   Place list of data into memory",
+"long help of set memory"));
+    cmd->init();
+    cset->add(cmd= new cl_set_bit_cmd("bit", 0,
+"set bit addr 0|1   Set specified bit to 0 or 1",
+"long help of set bit"));
+    cmd->init();
+    cset->add(cmd= new cl_set_hw_cmd("hardware", 0,
+"set hardware cathegory params...\n"
+"                   Set parameters of specified hardware element",
+"long help of set hardware"));
+    cmd->add_name("hw");
+    cmd->init();
+  }
+  if (!super_cmd)
+    {
+      cmdset->add(cmd= new cl_super_cmd("set", 0,
+"set subcommand     Set, see `set' command for more help",
+"long help of set", cset));
+      cmd->init();
+    }
+
+  { // info
+    super_cmd= (class cl_super_cmd *)(cmdset->get_cmd("info"));
+    if (super_cmd)
+      cset= super_cmd->get_subcommands();
+    else {
+      cset= new cl_cmdset();
+      cset->init();
+    }
+    cset->add(cmd= new cl_info_bp_cmd("breakpoints", 0, 
+"info breakpoints   Status of user-settable breakpoints",
+"long help of info breakpoints"));
+    cmd->add_name("bp");
+    cmd->init();
+    cset->add(cmd= new cl_info_reg_cmd("registers", 0, 
+"info registers     List of integer registers and their contents",
+"long help of info registers"));
+    cmd->init();
+    cset->add(cmd= new cl_info_hw_cmd("hardware", 0, 
+"info hardware cathegory\n"
+"                   Status of hardware elements of the CPU",
+"long help of info hardware"));
+    cmd->add_name("hw");
+    cmd->init();
+    cset->add(cmd= new cl_info_stack_cmd("stack", 0, 
+"info stack         Status of stack of the CPU",
+"long help of info stack"));
+    cmd->init();
+    cset->add(cmd= new cl_info_memory_cmd("memory", 0,
+"info memory        Information about memory system",
+"long help of info memory"));
+    cmd->init();
+  }
+  if (!super_cmd) {
+    cmdset->add(cmd= new cl_super_cmd("info", 0,
+"info subcommand    Information, see `info' command for more help",
+"long help of info", cset));
+    cmd->init();
+  }
+
+  {
+    super_cmd= (class cl_super_cmd *)(cmdset->get_cmd("timer"));
+    if (super_cmd)
+      cset= super_cmd->get_subcommands();
+    else {
+      cset= new cl_cmdset();
+      cset->init();
+    }
+    cset->add(cmd= new cl_timer_add_cmd("add", 0,
+"timer add id [direction [in_isr]]\n"
+"                   Create a clock counter (timer)",
+"log help of timer add"));
+    cmd->init();
+    cmd->add_name("create");
+    cmd->add_name("make");
+    cset->add(cmd= new cl_timer_delete_cmd("delete", 0,
+"timer delete id    Delete a timer",
+"long help of timer delete"));
+    cmd->init();
+    cmd->add_name("remove");
+    cset->add(cmd= new cl_timer_get_cmd("get", 0,
+"timer get [id]     Get value of a timer, or all",
+"long help of timer get"));
+    cmd->init();
+    cset->add(cmd= new cl_timer_run_cmd("run", 0,
+"timer start id     Start a timer",
+"long help of timer run"));
+    cmd->init();
+    cmd->add_name("start");
+    cset->add(cmd= new cl_timer_stop_cmd("stop", 0,
+"timer stop id      Stop a timer",
+"long help of timer stop"));
+    cmd->init();
+    cset->add(cmd= new cl_timer_value_cmd("set", 0,
+"timer set id value\n"
+"                   Set a timer value",
+"long help of timer set"));
+    cmd->init();
+    cmd->add_name("value");
+  }
+  if (!super_cmd) {
+    cmdset->add(cmd= new cl_super_cmd("timer", 0,
+"timer subcommand   Manage timers",
+"long help of timer", cset));
+    cmd->init();
+  }
+
+  {
+    super_cmd= (class cl_super_cmd *)(cmdset->get_cmd("memory"));
+    if (super_cmd)
+      cset= super_cmd->get_subcommands();
+    else {
+      cset= new cl_cmdset();
+      cset->init();
+    }
+    /*
+    cset->add(cmd= new cl_memory_cmd("_no_parameters_", 0,
+"memory             Information about memory system",
+"long help of memory"));
+    cmd->init();
+    */
+    cset->add(cmd= new cl_memory_createchip_cmd("createchip", 0,
+"memory createchip id size cellsize\n"
+"                   Create a new memory chip",
+"long help of memory createchip"));
+    cmd->init();
+    cmd->add_name("cchip");
+    cset->add(cmd= new cl_memory_createaddressspace_cmd("createaddressspace", 0,
+"memory createaddressspace id startaddr size\n"
+"                   Create address space",
+"long help of memory createaddressspace"));
+    cmd->init();
+    cmd->add_name("createaddrspace");
+    cmd->add_name("createaspace");
+    cmd->add_name("caddressspace");
+    cmd->add_name("caddrspace");
+    cmd->add_name("caspace");
+    cset->add(cmd= new cl_memory_createaddressdecoder_cmd("createaddressdecoder", 0,
+"memory createaddressdecoder addressspace begin end chip begin\n"
+"                   Create address decoder",
+"long help of memory createaddressdecoder"));
+    cmd->init();
+    cmd->add_name("createaddrdecoder");
+    cmd->add_name("createadecoder");
+    cmd->add_name("caddressdecoder");
+    cmd->add_name("caddrdecoder");
+    cmd->add_name("cadecoder");
+  }
+  if (!super_cmd) {
+    cmdset->add(cmd= new cl_super_cmd("memory", 0,
+"memory subcommand  Manage memory chips and address spaces",
+"long help of memory", cset));
+    cmd->init();
+  }
+}
+
 
 /*
  * Read/write simulated memory
  */
 
-ulong
-cl_uc::read_mem(enum mem_class type, long addr)
+t_mem
+cl_uc::read_mem(char *id, t_addr addr)
 {
-  class cl_mem *m;
+  class cl_address_space *m= address_space(id);
 
-  if ((m= (class cl_mem*)mems->at(type)))
-    return(m->read(addr));
-  //FIXME
-fprintf(stderr, "cl_uc::read_mem(type= %d, 0x%06lx) TROUBLE\n", type, addr);
-  return(0);
+  return(m?(m->read(addr)):0);
 }
 
-ulong
-cl_uc::get_mem(enum mem_class type, long addr)
+t_mem
+cl_uc::get_mem(char *id, t_addr addr)
 {
-  class cl_mem *m;
+  class cl_address_space *m= address_space(id);
 
-  if ((m= (class cl_mem*)mems->at(type)))
-    return(m->get(addr));
-  //FIXME
-printf("cl_uc::get_mem(type= %d, 0x%06lx) TROUBLE\n", type, addr);
-  return(0);
+  return(m?(m->get(addr)):0);
 }
 
 void
-cl_uc::write_mem(enum mem_class type, long addr, ulong val)
+cl_uc::write_mem(char *id, t_addr addr, t_mem val)
 {
-  class cl_mem *m;
+  class cl_address_space *m= address_space(id);
 
-  if ((m= (class cl_mem*)mems->at(type)))
-    {
-      m->write(addr, &val);
-      //m->mem[addr]= val;
-    }
-  //FIXME
-else printf("cl_uc::write_mem(type= %d, 0x%06lx, 0x%lx) TROUBLE\n", type, addr, val);
+  if (m)
+    m->write(addr, val);
 }
 
 void
-cl_uc::set_mem(enum mem_class type, long addr, ulong val)
+cl_uc::set_mem(char *id, t_addr addr, t_mem val)
 {
-  class cl_mem *m;
+  class cl_address_space *m= address_space(id);
 
-  if ((m= (class cl_mem*)mems->at(type)))
+  if(m)
     m->set(addr, val);
-  //FIXME
-else printf("cl_uc::set_mem(type= %d, 0x%06lx, 0x%lx) TROUBLE\n", type, addr, val);
 }
 
-class cl_mem *
+
+/*
+class cl_memory *
 cl_uc::mem(enum mem_class type)
 {
+  class cl_m *m;
+    
   if (mems->count < type)
-    //FIXME
-{printf("TROUBLE\n");    return(0);
-}
-  return((class cl_mem *)(mems->at(type)));
+    m= (class cl_m *)(mems->at(MEM_DUMMY));
+  else
+    m= (class cl_m *)(mems->at(type));
+  return(m);
 }
+*/
 
-TYPE_UBYTE *
-cl_uc::MEM(enum mem_class type)
+class cl_address_space *
+cl_uc::address_space(char *id)
 {
-  class cl_mem *m;
+  int i;
 
-  if ((m= mem(type)) == 0)
-    //FIXME
-{printf("TROUBLE\n");    return(0);
-}
-  return((uchar *)(m->mem));
+  if (!id ||
+      !(*id))
+    return(0);
+  for (i= 0; i < address_spaces->count; i++)
+    {
+      class cl_address_space *m= (cl_address_space *)(address_spaces->at(i));
+      if (!m ||
+          !m->have_real_name())
+        continue;
+      if (m->is_inamed(id))
+        return(m);
+    }
+  return(0);
 }
 
+class cl_memory *
+cl_uc::memory(char *id)
+{
+  int i;
+
+  if (!id ||
+      !(*id))
+    return(0);
+  for (i= 0; i < address_spaces->count; i++)
+    {
+      class cl_memory *m= (cl_memory *)(address_spaces->at(i));
+      if (!m ||
+          !m->have_real_name())
+        continue;
+      if (m->is_inamed(id))
+        return(m);
+    }
+  for (i= 0; i < memchips->count; i++)
+    {
+      class cl_memory *m= (cl_memory *)(memchips->at(i));
+      if (!m ||
+          !m->have_real_name())
+        continue;
+      if (m->is_inamed(id))
+        return(m);
+    }
+  return(0);
+}
 
-/* Local function for `read_hex_file' method to read some bytes */
 
 static long
 ReadInt(FILE *f, bool *ok, int bytes)
@@ -320,7 +701,7 @@ ReadInt(FILE *f, bool *ok, int bytes)
   while (bytes)
     {
       if (fscanf(f, "%2c", &s2[0]) == EOF)
-       return(0);
+        return(0);
       s2[2]= '\0';
       l= l*256 + strtol(s2, NULL, 16);
       bytes--;
@@ -339,10 +720,10 @@ ReadInt(FILE *f, bool *ok, int bytes)
  */
 
 long
-cl_uc::read_hex_file(const char *name)
+cl_uc::read_hex_file(const char *nam)
 {
   FILE *f;
-  char c;
+  int c;
   long written= 0, recnum= 0;
 
   uchar dnum;     // data number
@@ -355,27 +736,35 @@ cl_uc::read_hex_file(const char *name)
   bool ok, get_low= 1;
   uchar low= 0, high;
 
-  if (!name)
+  if (!rom)
     {
-      sim->cmd->printf("cl_uc::read_hex_file File name not specified\n");
+      sim->app->get_commander()->
+        dd_printf("No ROM address space to read in.\n");
+      return(-1);
+    }
+
+  if (!nam)
+    {
+      sim->app->get_commander()->
+        dd_printf("cl_uc::read_hex_file File name not specified\n");
       return(-1);
     }
   else
-    if ((f= fopen(name, "r")) == NULL)
+    if ((f= fopen(nam, "r")) == NULL)
       {
-       fprintf(stderr, "Can't open `%s': %s\n", name, strerror(errno));
-       return(-1);
+        fprintf(stderr, "Can't open `%s': %s\n", nam, strerror(errno));
+        return(-1);
       }
 
   //memset(inst_map, '\0', sizeof(inst_map));
   ok= DD_TRUE;
   while (ok &&
-        rtyp != 1)
+         rtyp != 1)
     {
       while (((c= getc(f)) != ':') &&
-            (c != EOF)) ;
+             (c != EOF)) ;
       if (c != ':')
-       {fprintf(stderr, ": not found\n");break;}
+        {fprintf(stderr, ": not found\n");break;}
       recnum++;
       dnum= ReadInt(f, &ok, 1);//printf("dnum=%02x",dnum);
       chk = dnum;
@@ -385,71 +774,67 @@ cl_uc::read_hex_file(const char *name)
       rtyp= ReadInt(f, &ok, 1);//printf("rtyp=%02x ",rtyp);
       chk+= rtyp;
       for (i= 0; ok && (i < dnum); i++)
-       {
-         rec[i]= ReadInt(f, &ok, 1);//printf("%02x",rec[i]);
-         chk+= rec[i];
-       }
+        {
+          rec[i]= ReadInt(f, &ok, 1);//printf("%02x",rec[i]);
+          chk+= rec[i];
+        }
       if (ok)
-       {
-         sum= ReadInt(f, &ok, 1);//printf(" sum=%02x\n",sum);
-         if (ok)
-           {
-             if (((sum + chk) & 0xff) == 0)
-               {
-                 if (rtyp == 0)
-                   {
-                     if (get_mem_width(MEM_ROM) > 8)
-                       addr/= 2;
-                     for (i= 0; i < dnum; i++)
-                       {
-                         if (get_mem_width(MEM_ROM) <= 8)
-                           {
-                             set_mem(MEM_ROM, addr, rec[i]);
-                             addr++;
-                             written++;
-                           }
-                         else if (get_mem_width(MEM_ROM) <= 16)
-                           {
-                             if (get_low)
-                               {
-                                 low= rec[i];
-                                 get_low= 0;
-                               }
-                             else
-                               {
-                                 high= rec[i];
-                                 set_mem(MEM_ROM, addr, (high*256)+low);
-                                 addr++;
-                                 written++;
-                                 get_low= 1;
-                               }
-                           }
-                       }
-                   }
-                 else
-                   if (sim->get_iarg('V', 0) &&
-                       rtyp != 1)
-                     sim->cmd->printf("Unknown record type %d(0x%x)\n",
-                                      rtyp, rtyp);
-               }
-             else
-               if (sim->get_iarg('V', 0))
-                 sim->cmd->printf("Checksum error (%x instead of %x) in "
-                                  "record %ld.\n", chk, sum, recnum);
-           }
-         else
-           if (sim->get_iarg('V', 0))
-             sim->cmd->printf("Read error in record %ld.\n", recnum);
-       }
-    }
-  if (get_mem_width(MEM_ROM) > 8 &&
+        {
+          sum= ReadInt(f, &ok, 1);//printf(" sum=%02x\n",sum);
+          if (ok)
+            {
+              if (((sum + chk) & 0xff) == 0)
+                {
+                  if (rtyp == 0)
+                    {
+                      if (rom->width > 8)
+                        addr/= 2;
+                      for (i= 0; i < dnum; i++)
+                        {
+                          if (rom->width <= 8)
+                            {
+                              rom->set(addr, rec[i]);
+                              addr++;
+                              written++;
+                            }
+                          else if (rom->width <= 16)
+                            {
+                              if (get_low)
+                                {
+                                  low= rec[i];
+                                  get_low= 0;
+                                }
+                              else
+                                {
+                                  high= rec[i];
+                                  rom->set(addr, (high*256)+low);
+                                  addr++;
+                                  written++;
+                                  get_low= 1;
+                                }
+                            }
+                        }
+                    }
+                  else
+                    if (rtyp != 1)
+                      application->debug("Unknown record type %d(0x%x)\n",
+                                         rtyp, rtyp);
+                }
+              else
+                application->debug("Checksum error (%x instead of %x) in "
+                                   "record %ld.\n", chk, sum, recnum);
+            }
+          else
+            application->debug("Read error in record %ld.\n", recnum);
+        }
+    }
+  if (rom->width > 8 &&
       !get_low)
-    set_mem(MEM_ROM, addr, low);
+    rom->set(addr, low);
 
-  if (name)
+  if (nam)
     fclose(f);
-  if (sim->get_iarg('V', 0))
-    sim->cmd->printf("%ld records have been read\n", recnum);
+  application->debug("%ld records have been read\n", recnum);
   analyze(0);
   return(written);
 }
@@ -465,41 +850,37 @@ cl_uc::read_hex_file(const char *name)
  */
 
 bool
-cl_uc::inst_at(uint addr)
+cl_uc::inst_at(t_addr addr)
 {
-  class cl_rom *rom= (class cl_rom *)mem(MEM_ROM);
-  
   if (!rom)
     return(0);
-  return(rom->inst_map->get(addr));
+  return(rom->get_cell_flag(addr, CELL_INST));
 }
 
 void
-cl_uc::set_inst_at(uint addr)
+cl_uc::set_inst_at(t_addr addr)
 {
-  class cl_rom *rom= (class cl_rom *)mem(MEM_ROM);
-  
   if (rom)
-    rom->inst_map->set(addr);
+    rom->set_cell_flag(addr, DD_TRUE, CELL_INST);
 }
 
 void
-cl_uc::del_inst_at(uint addr)
+cl_uc::del_inst_at(t_addr addr)
 {
-  class cl_rom *rom= (class cl_rom *)mem(MEM_ROM);
-  
   if (rom)
-    rom->inst_map->clear(addr);
+    rom->set_cell_flag(addr, DD_FALSE, CELL_INST);
 }
 
 bool
 cl_uc::there_is_inst(void)
 {
-  class cl_rom *rom= (class cl_rom *)mem(MEM_ROM);
-  
   if (!rom)
     return(0);
-  return(!(rom->inst_map->empty()));
+  bool got= DD_FALSE;
+  t_addr addr;
+  for (addr= 0; rom->valid_address(addr) && !got; addr++)
+    got= rom->get_cell_flag(addr, CELL_INST);
+  return(got);
 }
 
 
@@ -510,30 +891,30 @@ cl_uc::there_is_inst(void)
 
 /* Register callback hw objects for mem read/write */
 
-void
-cl_uc::register_hw_read(enum mem_class type, long addr, class cl_hw *hw)
+/*void
+cl_uc::register_hw_read(enum mem_class type, t_addr addr, class cl_hw *hw)
 {
-  class cl_mem *m;
+  class cl_m *m;
   class cl_memloc *l;
 
-  if ((m= (class cl_mem*)mems->at(type)))
+  if ((m= (class cl_m*)mems->at(type)))
     {
       if ((l= m->read_locs->get_loc(addr)) == 0)
-       {
-         l= new cl_memloc(addr);
-         l->init();
-         m->read_locs->add(l);
-       }
+        {
+          l= new cl_memloc(addr);
+          l->init();
+          m->read_locs->add(l);
+        }
       l->hws->add(hw);
     }
   else
     printf("cl_uc::register_hw_read TROUBLE\n");
-}
+}*/
 
-void
-cl_uc::register_hw_write(enum mem_class type, long addr, class cl_hw *hw)
+/*void
+cl_uc::register_hw_write(enum mem_class type, t_addr addr, class cl_hw *hw)
 {
-}
+}*/
 
 /* Looking for a specific HW element */
 
@@ -549,7 +930,28 @@ cl_uc::get_hw(enum hw_cath cath, int *idx)
     {
       hw= (class cl_hw *)(hws->at(i));
       if (hw->cathegory == cath)
-       break;
+        break;
+    }
+  if (i >= hws->count)
+    return(0);
+  if (idx)
+    *idx= i;
+  return(hw);
+}
+
+class cl_hw *
+cl_uc::get_hw(char *id_string, int *idx)
+{
+  class cl_hw *hw= 0;
+  int i= 0;
+
+  if (idx)
+    i= *idx;
+  for (; i < hws->count; i++)
+    {
+      hw= (class cl_hw *)(hws->at(i));
+      if (strstr(hw->id_string, id_string) == hw->id_string)
+        break;
     }
   if (i >= hws->count)
     return(0);
@@ -568,7 +970,7 @@ cl_uc::get_hw(enum hw_cath cath, int hwid, int *idx)
     i= *idx;
   hw= get_hw(cath, &i);
   while (hw &&
-        hw->id != hwid)
+         hw->id != hwid)
     {
       i++;
       hw= get_hw(cath, &i);
@@ -579,6 +981,27 @@ cl_uc::get_hw(enum hw_cath cath, int hwid, int *idx)
   return(hw);
 }
 
+class cl_hw *
+cl_uc::get_hw(char *id_string, int hwid, int *idx)
+{
+  class cl_hw *hw;
+  int i= 0;
+
+  if (idx)
+    i= *idx;
+  hw= get_hw(id_string, &i);
+  while (hw &&
+         hw->id != hwid)
+    {
+      i++;
+      hw= get_hw(id_string, &i);
+    }
+  if (hw && 
+      idx)
+    *idx= i;
+  return(hw);
+}
+
 
 /*
  * Help of the command interpreter
@@ -606,61 +1029,347 @@ cl_uc::bit_tbl(void)
 }
 
 char *
-cl_uc::disass(uint addr, char *sep)
+cl_uc::disass(t_addr addr, char *sep)
 {
   char *buf;
 
   buf= (char*)malloc(100);
-  strcpy(buf, "uc::do_disass unimplemented\n");
+  strcpy(buf, "uc::disass() unimplemented\n");
   return(buf);
 }
 
 void
-cl_uc::print_disass(uint addr, class cl_console *con)
+cl_uc::print_disass(t_addr addr, class cl_console *con)
 {
-  con->printf("uc::print_disass unimplemented\n");
+  char *dis;
+  class cl_brk *b;
+  int i;
+
+  if (!rom)
+    return;
+
+  t_mem code= rom->get(addr);
+  b= fbrk_at(addr);
+  dis= disass(addr, NULL);
+  if (b)
+    con->dd_printf("%c", (b->perm == brkFIX)?'F':'D');
+  else
+    con->dd_printf(" ");
+  con->dd_printf("%c ", inst_at(addr)?' ':'?');
+  con->dd_printf(rom->addr_format, addr); con->dd_printf(" ");
+  con->dd_printf(rom->data_format, code);
+  for (i= 1; i < inst_length(addr); i++)
+    {
+      con->dd_printf(" ");
+      con->dd_printf(rom->data_format, rom->get(addr+i));
+    }
+  int li= longest_inst();
+  while (i < li)
+    {
+      int j;
+      j= rom->width/4 + ((rom->width%4)?1:0) + 1;
+      while (j)
+        con->dd_printf(" "), j--;
+      i++;
+    }
+  con->dd_printf(" %s\n", dis);
+  free(dis);
 }
 
 void
 cl_uc::print_regs(class cl_console *con)
 {
-  con->printf("No registers\n");
+  con->dd_printf("No registers\n");
 }
 
 int
-cl_uc::inst_length(uint code)
+cl_uc::inst_length(t_addr addr)
 {
   struct dis_entry *tabl= dis_tbl();
   int i;
+  t_mem code;
+
+  if (!rom)
+    return(0);
 
+  code = rom->get(addr);
   for (i= 0; tabl[i].mnemonic && (code & tabl[i].mask) != tabl[i].code; i++) ;
-  return(tabl[i].mnemonic?tabl[i].length:1);    
+  return(tabl[i].mnemonic?tabl[i].length:1);
+}
+
+int
+cl_uc::inst_branch(t_addr addr)
+{
+  struct dis_entry *tabl= dis_tbl();
+  int i;
+  t_mem code;
+
+  if (!rom)
+    return(0);
+
+  code = rom->get(addr);
+  for (i= 0; tabl[i].mnemonic && (code & tabl[i].mask) != tabl[i].code; i++)
+    ;
+  return tabl[i].branch;
+}
+
+int
+cl_uc::longest_inst(void)
+{
+  struct dis_entry *de= dis_tbl();
+  int max= 0;
+
+  while (de &&
+         de->mnemonic)
+    {
+      if (de->length > max)
+        max= de->length;
+      de++;
+    }
+  return(max);
 }
 
 bool
-cl_uc::get_name(uint addr, struct name_entry tab[], char *buf)
+cl_uc::get_name(t_addr addr, struct name_entry tab[], char *buf)
 {
   int i;
 
   i= 0;
   while (tab[i].name &&
-        (!(tab[i].cpu_type & type) ||
-        (tab[i].addr != addr)))
+         (!(tab[i].cpu_type & type) ||
+         (tab[i].addr != addr)))
     i++;
   if (tab[i].name)
     strcpy(buf, tab[i].name);
   return(tab[i].name != NULL);
 }
 
+bool
+cl_uc::symbol2address(char *sym, struct name_entry tab[],
+                      t_addr *addr)
+{
+  int i;
+
+  if (!sym ||
+      !*sym)
+    return(DD_FALSE);
+  i= 0;
+  while (tab[i].name &&
+         (!(tab[i].cpu_type & type) ||
+          strcasecmp(sym, tab[i].name) != 0))
+    i++;
+  if (tab[i].name)
+    {
+      if (addr)
+        *addr= tab[i].addr;
+      return(DD_TRUE);
+    }
+  return(DD_FALSE);
+}
+
+char *
+cl_uc::symbolic_bit_name(t_addr bit_address,
+                         class cl_memory *mem,
+                         t_addr mem_addr,
+                         t_mem bit_mask)
+{
+  char *sym_name= 0;
+  int i;
+
+  i= 0;
+  while (bit_tbl()[i].name &&
+         (bit_tbl()[i].addr != bit_address))
+    i++;
+  if (bit_tbl()[i].name)
+    {
+      sym_name= strdup(bit_tbl()[i].name);
+      return(sym_name);
+    }
+
+  if (mem &&
+      mem->have_real_name() &&
+      strstr(mem->get_name(), "sfr") == mem->get_name())
+    {
+      i= 0;
+      while (sfr_tbl()[i].name &&
+             (sfr_tbl()[i].addr != mem_addr))
+        i++;
+      if (sfr_tbl()[i].name)
+        sym_name= strdup(sfr_tbl()[i].name);
+      else
+        sym_name= 0;
+    }
+  if (!sym_name)
+    {
+      sym_name= (char *)malloc(16);
+      sprintf(sym_name, mem?(mem->addr_format):"0x%06x", mem_addr);
+    }
+  sym_name= (char *)realloc(sym_name, strlen(sym_name)+2);
+  strcat(sym_name, ".");
+  i= 0;
+  while (bit_mask > 1)
+    {
+      bit_mask>>=1;
+      i++;
+    }
+  char bitnumstr[10];
+  sprintf(bitnumstr, "%1d", i);
+  strcat(sym_name, bitnumstr);
+  return(sym_name);
+}
+
+
+/*
+ * Messages to broadcast
+ */
+
+bool
+cl_uc::handle_event(class cl_event &event)
+{
+  switch (event.what)
+    {
+    case ev_address_space_added:
+      {
+        try {
+          class cl_event_address_space_added &e=
+            dynamic_cast<class cl_event_address_space_added &>(event);
+          address_space_added(e.as);
+          e.handle();
+        }
+        catch (...)
+          { break; }
+        break;
+      }
+    default:
+      return(pass_event_down(event));
+      break;
+    }
+  return(DD_FALSE);
+}
+
+/*
+void
+cl_uc::mem_cell_changed(class cl_address_space *mem, t_addr addr)
+{
+  if (hws)
+    hws->mem_cell_changed(mem, addr);
+  else
+    printf("JAJ uc\n");//FIXME
+  if (mems &&
+      mems->count)
+    {
+      int i;
+      for (i= 0; i < mems->count; i++)
+        {
+        }
+    }
+}
+*/
+
+void
+cl_uc::address_space_added(class cl_address_space *as)
+{
+  if (hws)
+    hws->address_space_added(as);
+  else
+    printf("JAJ uc\n");//FIXME
+}
+
+
+/*
+ * Error handling
+ */
+
+void
+cl_uc::error(class cl_error *error)
+{
+  errors->add(error);
+  if ((error->inst= inst_exec))
+    error->PC= instPC;
+}
+
+void
+cl_uc::check_errors(void)
+{
+  int i;
+  class cl_commander *c= sim->app->get_commander();
+  bool must_stop= DD_FALSE;
+
+  if (c)
+    {
+      for (i= 0; i < errors->count; i++)
+        {
+          class cl_error *error= (class cl_error *)(errors->at(i));
+          if (!error->is_on())
+            continue;
+          error->print(c);
+          must_stop= must_stop || (error->get_type() & err_stop);
+          if (error->inst)
+            {
+              class cl_console *con;
+              con= c->actual_console;
+              if (!con)
+                con= c->frozen_console;
+              if (con)
+                {
+                  con->dd_printf("Erronouse instruction: ");
+                  print_disass(error->PC, con);
+                }
+            }
+        }
+      errors->free_all();
+    }
+  else
+    fprintf(stderr, "no actual console, %d errors\n", errors->count);
+  if (must_stop)
+    sim->stop(resERROR);
+}
+
+
+/*
+ * Converting bit address into real memory
+ */
+
+class cl_address_space *
+cl_uc::bit2mem(t_addr bitaddr, t_addr *memaddr, t_mem *bitmask)
+{
+  if (memaddr)
+    *memaddr= bitaddr;
+  if (bitmask)
+    *bitmask= 1 << (bitaddr & 0x7);
+  return(0); // abstract...
+}
+
 
 /*
  * Execution
  */
 
 int
-cl_uc::tick(int cycles)
+cl_uc::tick_hw(int cycles)
 {
   class cl_hw *hw;
+  int i;//, cpc= clock_per_cycle();
+
+  // tick hws
+  for (i= 0; i < hws->count; i++)
+    {
+      hw= (class cl_hw *)(hws->at(i));
+      if (hw->flags & HWF_INSIDE)
+        hw->tick(cycles);
+    }
+  do_extra_hw(cycles);
+  return(0);
+}
+
+void
+cl_uc::do_extra_hw(int cycles)
+{}
+
+int
+cl_uc::tick(int cycles)
+{
+  //class cl_hw *hw;
   int i, cpc= clock_per_cycle();
 
   // increase time
@@ -674,20 +1383,15 @@ cl_uc::tick(int cycles)
     {
       class cl_ticker *t= (class cl_ticker *)(counters->at(i));
       if (t)
-       {
-         if ((t->options&TICK_INISR) ||
-             il->level < 0)
-           t->tick(cycles * cpc);
-       }
+        {
+          if ((t->options&TICK_INISR) ||
+              il->level < 0)
+            t->tick(cycles * cpc);
+        }
     }
 
-  // tick hws
-  for (i= 0; i < hws->count; i++)
-    {
-      hw= (class cl_hw *)(hws->at(i));
-      if (hw->flags & HWF_INSIDE)
-       hw->tick(cycles);
-    }
+  // tick for hardwares
+  inst_ticks+= cycles;
   return(0);
 }
 
@@ -700,19 +1404,19 @@ cl_uc::get_counter(int nr)
 }
 
 class cl_ticker *
-cl_uc::get_counter(char *name)
+cl_uc::get_counter(char *nam)
 {
   int i;
 
-  if (!name)
+  if (!nam)
     return(0);
   for (i= 0; i < counters->count; i++)
     {
       class cl_ticker *t= (class cl_ticker *)(counters->at(i));
       if (t &&
-         t->name &&
-         strcmp(t->name, name) == 0)
-       return(t);
+          t->get_name() &&
+          strcmp(t->get_name(), nam) == 0)
+        return(t);
     }
   return(0);
 }
@@ -726,7 +1430,7 @@ cl_uc::add_counter(class cl_ticker *ticker, int nr)
 }
 
 void
-cl_uc::add_counter(class cl_ticker *ticker, char */*name*/)
+cl_uc::add_counter(class cl_ticker *ticker, char */*nam*/)
 {
   int i;
 
@@ -736,10 +1440,10 @@ cl_uc::add_counter(class cl_ticker *ticker, char */*name*/)
     {
       class cl_ticker *t= (class cl_ticker *)(counters->at(i));
       if (!t)
-       {
-         counters->put_at(i, ticker);
-         return;
-       }
+        {
+          counters->put_at(i, ticker);
+          return;
+        }
     }
   counters->add(ticker);
 }
@@ -757,23 +1461,23 @@ cl_uc::del_counter(int nr)
 }
 
 void
-cl_uc::del_counter(char *name)
+cl_uc::del_counter(char *nam)
 {
   int i;
   
-  if (!name)
+  if (!nam)
     return;
   for (i= 0; i < counters->count; i++)
     {
       class cl_ticker *t= (class cl_ticker *)(counters->at(i));
       if (t &&
-         t->name &&
-         strcmp(t->name, name) == 0)
-       {
-         delete t;
-         counters->put_at(i, 0);
-         return;
-       }
+          t->get_name() &&
+          strcmp(t->get_name(), nam) == 0)
+        {
+          delete t;
+          counters->put_at(i, 0);
+          return;
+        }
     }
 }
 
@@ -785,35 +1489,39 @@ t_mem
 cl_uc::fetch(void)
 {
   ulong code;
+  
+  if (!rom)
+    return(0);
 
-  code= read_mem(MEM_ROM, PC);
-  PC++;
-  if (PC >= get_mem_size(MEM_ROM))
-    PC= 0;
+  code= rom->read(PC);
+  PC= rom->inc_address(PC);
   return(code);
 }
 
 /*
- * Fetch but checking for breakpoint hit first
+ * Fetch but checking for breakpoint hit first, returns TRUE if
+ * a breakpoint is hit
  */
 
 bool
-cl_uc::fetch(ulong *code)
+cl_uc::fetch(t_mem *code)
 {
   class cl_brk *brk;
   int idx;
 
   if (!code)
     return(0);
-  if (sim->state & SIM_GO)
+  if ((sim->state & SIM_GO) &&
+      rom)
     {
-      if ((brk= fbrk->get_bp(PC, &idx)) &&
-         (brk->do_hit()))
-       {
-         if (brk->perm == brkDYNAMIC)
-           fbrk->del_bp(PC);
-         return(1);
-       }
+      if (rom->get_cell_flag(PC, CELL_FETCH_BRK) &&
+          (brk= fbrk->get_bp(PC, &idx)) &&
+          (brk->do_hit()))
+        {
+          if (brk->perm == brkDYNAMIC)
+            fbrk->del_bp(PC);
+          return(1);
+        }
     }
   *code= fetch();
   return(0);
@@ -827,7 +1535,7 @@ cl_uc::do_inst(int step)
   if (step < 0)
     step= 1;
   while (step-- &&
-        res == resGO)
+         res == resGO)
     {
       pre_inst();
       res= exec_inst();
@@ -840,17 +1548,29 @@ cl_uc::do_inst(int step)
 
 void
 cl_uc::pre_inst(void)
-{}
+{
+  inst_exec= DD_TRUE;
+  inst_ticks= 0;
+  events->disconn_all();
+}
 
 int
 cl_uc::exec_inst(void)
 {
+  instPC= PC;
   return(resGO);
 }
 
 void
 cl_uc::post_inst(void)
-{}
+{
+  tick_hw(inst_ticks);
+  if (errors->count)
+    check_errors();
+  if (events->count)
+    check_events();
+  inst_exec= DD_FALSE;
+}
 
 
 /*
@@ -879,35 +1599,103 @@ cl_uc::clock_per_cycle(void)
  */
 
 void
-cl_uc::st_push(class cl_stack_op *op)
+cl_uc::stack_write(class cl_stack_op *op)
 {
-  st_ops->push(op);
+  if (op->get_op() & stack_read_operation)
+    {
+      class cl_error_stack_tracker_wrong_handle *e= new
+        cl_error_stack_tracker_wrong_handle(DD_FALSE);
+      //fprintf(stderr, "%06"_A_"x cl_uc::stack_read() should be called for "
+      //"%s\n", op->get_pc(), op->get_op_name());
+      e->init();
+      error(e);
+      return;
+    }
+  stack_ops->push(op);
 }
 
 void
-cl_uc::st_call(class cl_stack_op *op)
-{
-  st_ops->push(op);
-}
-
-int
-cl_uc::st_pop(class cl_stack_op *op)
+cl_uc::stack_read(class cl_stack_op *op)
 {
-  class cl_stack_op *sop= (class cl_stack_op *)(st_ops->pop());
-
-  if (!sop)
-    return(1);
-  return(0);
-}
+  class cl_stack_op *top= (class cl_stack_op *)(stack_ops->top());
+  
+  if (op->get_op() & stack_write_operation)
+    {
+      class cl_error_stack_tracker_wrong_handle *e= new
+        cl_error_stack_tracker_wrong_handle(DD_TRUE);
+      e->init();
+      error(e);
+      //fprintf(stderr, "%06"_A_"x cl_uc::stack_write() should be called for "
+      //"%s\n", op->get_pc(), op->get_op_name());
+      return;
+    }
+  if (!top)
+    {
+      class cl_error *e= new cl_error_stack_tracker_empty(op);
+      /*printf("0x%06"_A_"x %s operation on stack but no operation was before\n
+        ",
+        op->get_pc(), op->get_op_name());*/
+      e->init();
+      error(e);
+      return;
+    }
 
-int
-cl_uc::st_ret(class cl_stack_op *op)
-{
-  class cl_stack_op *sop= (class cl_stack_op *)(st_ops->pop());
+  if (top)
+    {
+      if (!top->match(op))
+        {
+          class cl_error *e= new cl_error_stack_tracker_unmatch(top, op);
+          e->init();
+          error(e);
+          /*printf("0x%06"_A_"x %s operation on stack but last was %s\n",
+            op->get_pc(), op->get_op_name(), top->get_op_name());*/
+        }
+      int top_size= top->data_size(), op_size= op->data_size();
+      if (top_size != op_size)
+        {
+          application->debug("0x%06"_A_"x %d bytes to read out of stack "
+                             "but %d was pushed in last operation\n",
+                             op->get_pc(), op_size, top_size);
+        }
+    }
 
-  if (!sop)
-    return(1);
-  return(0);
+  int removed= 0;
+  while (top &&
+         top->can_removed(op))
+    {
+      top= (class cl_stack_op *)stack_ops->pop();
+      delete top;
+      top= (class cl_stack_op *)stack_ops->top();
+      removed++;
+    }
+  if (removed != 1)
+    {
+      application->debug("0x%06"_A_"x %d ops removed from stack-tracker "
+                         "when %s happened, top pc=0x%06"_A_"x "
+                         "top before=0x%06"_A_"x op after=0x%06"_A_"x\n",
+                         op->get_pc(), removed, op->get_op_name(),
+                         top?(top->get_pc()):0, top?(top->get_before()):0,
+                         op->get_after());
+    }
+  
+  if (top)
+    {
+      int ta= top->get_after(), oa= op->get_after();
+      if (ta != oa)
+        {
+          application->debug("0x%06"_A_"x stack still inconsistent after %s, "
+                             "%d byte(s) should be read out; top after"
+                             "=0x%06"_A_"x op after=0x%06"_A_"x\n",
+                             op->get_pc(), op->get_op_name(), abs(ta-oa),
+                             ta, oa);
+          class cl_error *e=
+            new cl_error_stack_tracker_inconsistent(op, abs(ta-oa));
+          e->init();
+          error(e);
+        }
+    }
+  
+  delete op;
 }
 
 
@@ -916,7 +1704,7 @@ cl_uc::st_ret(class cl_stack_op *op)
  */
 
 class cl_fetch_brk *
-cl_uc::fbrk_at(long addr)
+cl_uc::fbrk_at(t_addr addr)
 {
   int idx;
   
@@ -933,8 +1721,8 @@ cl_uc::ebrk_at(t_addr addr, char *id)
     {
       eb= (class cl_ev_brk *)(ebrk->at(i));
       if (eb->addr == addr &&
-         !strcmp(eb->id, id))
-       return(eb);
+          !strcmp(eb->id, id))
+        return(eb);
     }
   return(0);
 }
@@ -945,6 +1733,34 @@ cl_uc::rm_fbrk(long addr)
   fbrk->del_bp(addr);
 }*/
 
+/* Get a breakpoint specified by its number */
+
+class cl_brk *
+cl_uc::brk_by_nr(int nr)
+{
+  class cl_brk *bp;
+
+  if ((bp= fbrk->get_bp(nr)))
+    return(bp);
+  if ((bp= ebrk->get_bp(nr)))
+    return(bp);
+  return(0);
+}
+
+/* Get a breakpoint from the specified collection by its number */
+
+class cl_brk *
+cl_uc::brk_by_nr(class brk_coll *bpcoll, int nr)
+{
+  class cl_brk *bp;
+
+  if ((bp= bpcoll->get_bp(nr)))
+    return(bp);
+  return(0);
+}
+
+/* Remove an event breakpoint specified by its address and id */
+
 void
 cl_uc::rm_ebrk(t_addr addr, char *id)
 {
@@ -955,18 +1771,118 @@ cl_uc::rm_ebrk(t_addr addr, char *id)
     {
       eb= (class cl_ev_brk *)(ebrk->at(i));
       if (eb->addr == addr &&
-         !strcmp(eb->id, id))
-       ebrk->free_at(i);
+          !strcmp(eb->id, id))
+        ebrk->del_bp(i, 0);
+    }
+}
+
+/* Remove a breakpoint specified by its number */
+
+bool
+cl_uc::rm_brk(int nr)
+{
+  class cl_brk *bp;
+
+  if ((bp= brk_by_nr(fbrk, nr)))
+    {
+      fbrk->del_bp(bp->addr);
+      return(DD_TRUE);
+    }
+  else if ((bp= brk_by_nr(ebrk, nr)))
+    {
+      ebrk->del_bp(ebrk->index_of(bp), 0);
+      return(DD_TRUE);
     }
+  return(DD_FALSE);
 }
 
 void
 cl_uc::put_breaks(void)
 {}
 
+/* Remove all fetch and event breakpoints */
+
 void
-cl_uc::remove_breaks(void)
-{}
+cl_uc::remove_all_breaks(void)
+{
+  while (fbrk->count)
+    {
+      class cl_brk *brk= (class cl_brk *)(fbrk->at(0));
+      fbrk->del_bp(brk->addr);
+    }
+  while (ebrk->count)
+    ebrk->del_bp(ebrk->count-1, 0);
+}
+
+int
+cl_uc::make_new_brknr(void)
+{
+  if (brk_counter == 0)
+    return(brk_counter= 1);
+  if (fbrk->count == 0 &&
+      ebrk->count == 0)
+    return(brk_counter= 1);
+  return(++brk_counter);
+}
+
+class cl_ev_brk *
+cl_uc::mk_ebrk(enum brk_perm perm, class cl_address_space *mem,
+               char op, t_addr addr, int hit)
+{
+  class cl_ev_brk *b;
+  op= toupper(op);
+
+  b= new cl_ev_brk(mem, make_new_brknr(), addr, perm, hit, op);
+  b->init();
+  return(b);
+}
+
+void
+cl_uc::check_events(void)
+{
+  int i;
+  for (i= 0; i < events->count; i++)
+    {
+      class cl_ev_brk *brk=
+        dynamic_cast<class cl_ev_brk *>(events->object_at(i));
+      sim->stop(brk);
+    }
+  sim->stop(resBREAKPOINT);
+}
+
+
+/*
+ * Errors
+ *----------------------------------------------------------------------------
+ */
+
+cl_error_unknown_code::cl_error_unknown_code(class cl_uc *the_uc)
+{
+  uc= the_uc;
+  classification= uc_error_registry.find("unknown_code");
+}
+
+void
+cl_error_unknown_code::print(class cl_commander *c)
+{
+  c->dd_printf("%s: unknown instruction code at ", get_type_name());
+  if (uc->rom)
+    {
+      c->dd_printf(uc->rom->addr_format, PC);
+      c->dd_printf(" (");
+      c->dd_printf(uc->rom->data_format, uc->rom->get(PC));
+      c->dd_printf(")");
+    }
+  else
+    c->dd_printf("0x%06x", PC);
+  c->dd_printf("\n");
+}
+
+cl_uc_error_registry::cl_uc_error_registry(void)
+{
+  class cl_error_class *prev = uc_error_registry.find("non-classified");
+  prev = register_error(new cl_error_class(err_error, "unknown_code", prev, ERROR_OFF));
+}
 
 
 /* End of uc.cc */