* sim/ucsim/*.*, sim/ucsim/configure, sim/ucsim/configure.in:
[fw/sdcc] / sim / ucsim / s51.src / uc51.cc
index 02e4aedbb584b41531b95529dc998d42e2a96a54..29012a2715ca65fad25fef619f91d496a001c622 100644 (file)
@@ -30,9 +30,10 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #include <stdio.h>
 #include <stdlib.h>
 #include <ctype.h>
-#include <termios.h>
-#include <fcntl.h>
+#ifdef HAVE_UNISTD_H
 #include <unistd.h>
+#endif
+#include <fcntl.h>
 #include <errno.h>
 #include <sys/types.h>
 #include <sys/time.h>
@@ -41,9 +42,16 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #endif
 #include "i_string.h"
 
+// prj
+#include "utils.h"
+#include "globals.h"
+
 // sim
 #include "optioncl.h"
 
+//cmd.src
+#include "cmduccl.h"
+
 // local
 #include "uc51cl.h"
 #include "glob.h"
@@ -56,97 +64,47 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #include "types51.h"
 
 
+/*
+ * Options of uc51
+ */
+
+cl_irq_stop_option::cl_irq_stop_option(class cl_51core *the_uc51):
+  cl_optref(the_uc51)
+{
+  uc51= the_uc51;
+}
+
+int
+cl_irq_stop_option::init(void)
+{
+  cl_optref::init();
+  create(uc51, bool_opt, "irq_stop", "Stop when IRQ accepted");
+  return(0);
+}
+
+void
+cl_irq_stop_option::option_changed(void)
+{
+  if (!uc51)
+    return;
+  bool b;
+  option->get_value(&b);
+  uc51->stop_at_it= b;
+}
+
+
 /*
  * Making a new micro-controller and reset it
  */
 
-t_uc51::t_uc51(int Itype, int Itech, class cl_sim *asim):
+cl_51core::cl_51core(int Itype, int Itech, class cl_sim *asim):
   cl_uc(asim)
 {
-  //int i;
-  /*
-  struct termios tattr;
-  */  
   type= Itype;
   technology= Itech;
 
-  debug= asim->app->args->get_iarg('V', 0);
+  irq_stop_option= new cl_irq_stop_option(this);
   stop_at_it= DD_FALSE;
-  options->add(new cl_bool_opt(&debug, "verbose", "Verbose flag."));
-  options->add(new cl_bool_opt(&stop_at_it, "stopit",
-                              "Stop if interrupt accepted."));
-  options->add(new cl_cons_debug_opt(asim->app, "debug",
-                                    "Debug messages appears on this console."));
-
-  /*
-  serial_in = (FILE*)asim->app->args->get_parg(0, "Ser_in");
-  serial_out= (FILE*)asim->app->args->get_parg(0, "Ser_out");
-  if (serial_in)
-    {
-      // making `serial' unbuffered
-      if (setvbuf(serial_in, NULL, _IONBF, 0))
-       perror("Unbuffer serial input channel");
-      // setting O_NONBLOCK
-      if ((i= fcntl(fileno(serial_in), F_GETFL, 0)) < 0)
-       perror("Get flags of serial input");
-      i|= O_NONBLOCK;
-      if (fcntl(fileno(serial_in), F_SETFL, i) < 0)
-       perror("Set flags of serial input");
-      // switching terminal to noncanonical mode
-      if (isatty(fileno(serial_in)))
-       {
-         tcgetattr(fileno(serial_in), &saved_attributes_in);
-         tcgetattr(fileno(serial_in), &tattr);
-         tattr.c_lflag&= ~(ICANON|ECHO);
-         tattr.c_cc[VMIN] = 1;
-         tattr.c_cc[VTIME]= 0;
-         tcsetattr(fileno(serial_in), TCSAFLUSH, &tattr);
-       }
-      else
-       fprintf(stderr, "Warning: serial input interface connected to a "
-               "non-terminal file.\n");
-    }
-  if (serial_out)
-    {
-      // making `serial' unbuffered
-      if (setvbuf(serial_out, NULL, _IONBF, 0))
-       perror("Unbuffer serial output channel");
-      // setting O_NONBLOCK
-      if ((i= fcntl(fileno(serial_out), F_GETFL, 0)) < 0)
-       perror("Get flags of serial output");
-      i|= O_NONBLOCK;
-      if (fcntl(fileno(serial_out), F_SETFL, i) < 0)
-       perror("Set flags of serial output");
-      // switching terminal to noncanonical mode
-      if (isatty(fileno(serial_out)))
-       {
-         tcgetattr(fileno(serial_out), &saved_attributes_out);
-         tcgetattr(fileno(serial_out), &tattr);
-         tattr.c_lflag&= ~(ICANON|ECHO);
-         tattr.c_cc[VMIN] = 1;
-         tattr.c_cc[VTIME]= 0;
-         tcsetattr(fileno(serial_out), TCSAFLUSH, &tattr);
-       }
-      else
-       fprintf(stderr, "Warning: serial output interface connected to a "
-               "non-terminal file.\n");
-    }
-  */
-
-  /*for (i= 0; i < 4; i++)
-    port_pins[i]= 0xff;*/
-  /*it_sources->add(new cl_it_src(bmEX0, TCON, bmIE0, 0x0003, true,
-    "external #0"));*/
-  /*it_sources->add(new cl_it_src(bmET0, TCON, bmTF0, 0x000b, true,
-    "timer #0"));*/
-  /*it_sources->add(new cl_it_src(bmEX1, TCON, bmIE1, 0x0013, true,
-    "external #1"));*/
-  /*it_sources->add(new cl_it_src(bmET1, TCON, bmTF1, 0x001b, true,
-    "timer #1"));*/
-  /*it_sources->add(new cl_it_src(bmES , SCON, bmTI , 0x0023, false,
-                               "serial transmit"));
-  it_sources->add(new cl_it_src(bmES , SCON, bmRI , 0x0023, false,
-  "serial receive"));*/
 }
 
 
@@ -156,29 +114,30 @@ t_uc51::t_uc51(int Itype, int Itech, class cl_sim *asim):
  */
 
 int
-t_uc51::init(void)
+cl_51core::init(void)
 {
+  irq_stop_option->init();
   cl_uc::init();
+  set_name("mcs51_controller");
   reset();
   return(0);
 }
 
-static char id_string_51[100];
-
-char *
-t_uc51::id_string(void)
+const char *
+cl_51core::id_string(void)
 {
+  static char id_string_51[100];
   int i;
 
   for (i= 0; cpus_51[i].type_str != NULL && cpus_51[i].type != type; i++) ;
   sprintf(id_string_51, "%s %s",
-         cpus_51[i].type_str?cpus_51[i].type_str:"51",
-         (technology==CPU_HMOS)?"HMOS":"CMOS");
+          cpus_51[i].type_str?cpus_51[i].type_str:"51",
+          (technology==CPU_HMOS)?"HMOS":"CMOS");
   return(id_string_51);
 }
 
 void
-t_uc51::mk_hw_elements(void)
+cl_51core::mk_hw_elements(void)
 {
   class cl_hw *h;
 
@@ -209,50 +168,127 @@ t_uc51::mk_hw_elements(void)
   */
 }
 
-class cl_mem *
-t_uc51::mk_mem(enum mem_class type, char *class_name)
+void
+cl_51core::build_cmdset(class cl_cmdset *cmdset)
 {
-  class cl_mem *m= cl_uc::mk_mem(type, class_name);
+  class cl_cmd *cmd;
+  //class cl_super_cmd *super_cmd;
+  //class cl_cmdset *cset;
+
+  cl_uc::build_cmdset(cmdset);
+
+  cmdset->add(cmd= new cl_di_cmd("di", DD_TRUE,
+"di [start [stop]]  Dump Internal RAM",
+"long help of di"));
+  cmd->init();
+
+  cmdset->add(cmd= new cl_dx_cmd("dx", DD_TRUE,
+"dx [start [stop]]  Dump External RAM",
+"long help of dx"));
+  cmd->init();
+
+  cmdset->add(cmd= new cl_ds_cmd("ds", DD_TRUE,
+"ds [start [stop]]  Dump SFR",
+"long help of ds"));
+  cmd->init();
+}
+
+/*
+class cl_m *
+cl_51core::mk_mem(enum mem_class type, char *class_name)
+{
+  class cl_address_space *m= cl_uc::mk_mem(type, class_name);
   if (type == MEM_SFR)
     sfr= m;
   if (type == MEM_IRAM)
     iram= m;
   return(m);
 }
+*/
+
+void
+cl_51core::make_memories(void)
+{
+  class cl_address_space *as;
+
+  rom= as= new cl_address_space(MEM_ROM_ID/*"rom"*/, 0, 0x10000, 8);
+  as->init();
+  address_spaces->add(as);
+  iram= as= new cl_address_space(MEM_IRAM_ID/*"iram"*/, 0, 0x80, 8);
+  as->init();
+  address_spaces->add(as);
+  sfr= as= new cl_address_space(MEM_SFR_ID/*"sfr"*/, 0x80, 0x80, 8);
+  as->init();
+  address_spaces->add(as);
+  xram= as= new cl_address_space(MEM_XRAM_ID/*"xram"*/, 0, 0x10000, 8);
+  as->init();
+  address_spaces->add(as);
+
+  class cl_address_decoder *ad;
+  class cl_memory_chip *chip;
+
+  chip= new cl_memory_chip("rom_chip", 0x10000, 8/*, 0xff*/);
+  chip->init();
+  memchips->add(chip);
+  ad= new cl_address_decoder(as= rom/*address_space(MEM_ROM_ID)*/,
+                             chip, 0, 0xffff, 0);
+  ad->init();
+  as->decoders->add(ad);
+  ad->activate(0);
+
+  chip= new cl_memory_chip("iram_chip", 0x80, 8);
+  chip->init();
+  memchips->add(chip);
+  ad= new cl_address_decoder(as= iram/*address_space(MEM_IRAM_ID)*/,
+                             chip, 0, 0x7f, 0);
+  ad->init();
+  as->decoders->add(ad);
+  ad->activate(0);
+
+  chip= new cl_memory_chip("xram_chip", 0x10000, 8);
+  chip->init();
+  memchips->add(chip);
+  ad= new cl_address_decoder(as= xram/*address_space(MEM_XRAM_ID)*/,
+                             chip, 0, 0xffff, 0);
+  ad->init();
+  as->decoders->add(ad);
+  ad->activate(0);
+
+  chip= new cl_memory_chip("sfr_chip", 0x80, 8, 0);
+  chip->init();
+  memchips->add(chip);
+  ad= new cl_address_decoder(as= sfr/*address_space(MEM_SFR_ID)*/,
+                             chip, 0x80, 0xff, 0);
+  ad->init();
+  as->decoders->add(ad);
+  ad->activate(0);
+
+  acc= sfr->get_cell(ACC);
+  psw= sfr->get_cell(PSW);
+}
 
 
 /*
  * Destroying the micro-controller object
  */
 
-t_uc51::~t_uc51(void)
+cl_51core::~cl_51core(void)
 {
   /*
   if (serial_out)
     {
       if (isatty(fileno(serial_out)))
-       tcsetattr(fileno(serial_out), TCSANOW, &saved_attributes_out);
+        tcsetattr(fileno(serial_out), TCSANOW, &saved_attributes_out);
       fclose(serial_out);
     }
   if (serial_in)
     {
       if (isatty(fileno(serial_in)))
-       tcsetattr(fileno(serial_in), TCSANOW, &saved_attributes_in);
+        tcsetattr(fileno(serial_in), TCSANOW, &saved_attributes_in);
       fclose(serial_in);
     }
   */
-}
-
-
-/*
- * Writing data to EROM
- */
-
-void
-t_uc51::write_rom(t_addr addr, ulong data)
-{
-  if (addr < EROM_SIZE)
-    set_mem(MEM_ROM, addr, data);
+  delete irq_stop_option;
 }
 
 
@@ -261,104 +297,105 @@ t_uc51::write_rom(t_addr addr, ulong data)
  */
 
 struct dis_entry *
-t_uc51::dis_tbl(void)
+cl_51core::dis_tbl(void)
 {
   return(disass_51);
 }
 
 struct name_entry *
-t_uc51::sfr_tbl(void)
+cl_51core::sfr_tbl(void)
 {
   return(sfr_tab51);
 }
 
 struct name_entry *
-t_uc51::bit_tbl(void)
+cl_51core::bit_tbl(void)
 {
   return(bit_tab51);
 }
 
 char *
-t_uc51::disass(t_addr addr, char *sep)
+cl_51core::disass(t_addr addr, char *sep)
 {
   char work[256], temp[20], c[2];
-  char *buf, *p, *b, *t;
-  t_mem code= get_mem(MEM_ROM, addr);
+  const char *b;
+  char *buf, *p, *t;
+  t_mem code= rom->get(addr);
 
   p= work;
   b= dis_tbl()[code].mnemonic;
   while (*b)
     {
       if (*b == '%')
-       {
-         b++;
-         switch (*(b++))
-           {
-           case 'A': // absolute address
-             sprintf(temp, "%04"_A_"x",
-                     t_addr((addr&0xf800)|
-                            (((code>>5)&0x07)*256 +
-                             get_mem(MEM_ROM, addr+1))));
-             break;
-           case 'l': // long address
-             sprintf(temp, "%04"_A_"x",
-                     t_addr(get_mem(MEM_ROM, addr+1)*256 +
-                            get_mem(MEM_ROM, addr+2)));
-             break;
-           case 'a': // addr8 (direct address) at 2nd byte
-             if (!get_name(get_mem(MEM_ROM, addr+1), sfr_tbl(), temp))
-               sprintf(temp, "%02"_M_"x", get_mem(MEM_ROM, addr+1));
-             break;
-           case '8': // addr8 (direct address) at 3rd byte
-             if (!get_name(get_mem(MEM_ROM, addr+2), sfr_tbl(), temp))
-               sprintf(temp, "%02"_M_"x", get_mem(MEM_ROM, addr+1));
-             sprintf(temp, "%02"_M_"x", get_mem(MEM_ROM, addr+2));
-             break;
-           case 'b': // bitaddr at 2nd byte
-             {
-               t_addr ba= get_mem(MEM_ROM, addr+1);
-               if (get_name(ba, bit_tbl(), temp))
-                 break;
-               if (get_name((ba<128)?((ba/8)+32):(ba&0xf8), sfr_tbl(), temp))
-                 {
-                   strcat(temp, ".");
-                   sprintf(c, "%1"_M_"d", ba & 0x07);
-                   strcat(temp, c);
-                   break;
-                 }
-               sprintf(temp, "%02x.%"_M_"d", (ba<128)?((ba/8)+32):(ba&0xf8),
-                       ba & 0x07);
-               break;
-             }
-           case 'r': // rel8 address at 2nd byte
-             sprintf(temp, "%04"_A_"x",
-                     t_addr(addr+2+(signed char)(get_mem(MEM_ROM, addr+1))));
-             break;
-           case 'R': // rel8 address at 3rd byte
-             sprintf(temp, "%04"_A_"x",
-                     t_addr(addr+3+(signed char)(get_mem(MEM_ROM, addr+2))));
-             break;
-           case 'd': // data8 at 2nd byte
-             sprintf(temp, "%02"_M_"x", get_mem(MEM_ROM, addr+1));
-             break;
-           case 'D': // data8 at 3rd byte
-             sprintf(temp, "%02"_M_"x", get_mem(MEM_ROM, addr+2));
-             break;
-           case '6': // data16 at 2nd(H)-3rd(L) byte
-             sprintf(temp, "%04"_A_"x",
-                     t_addr(get_mem(MEM_ROM, addr+1)*256 +
-                            get_mem(MEM_ROM, addr+2)));
-             break;
-           default:
-             strcpy(temp, "?");
-             break;
-           }
-         t= temp;
-         while (*t)
-           *(p++)= *(t++);
-       }
+        {
+          b++;
+          switch (*(b++))
+            {
+            case 'A': // absolute address
+              sprintf(temp, "%04"_A_"x",
+                      t_addr((addr&0xf800)|
+                             (((code>>5)&0x07)*256 +
+                              rom->get(addr+1))));
+              break;
+            case 'l': // long address
+              sprintf(temp, "%04"_A_"x",
+                      t_addr(rom->get(addr+1)*256 +
+                             rom->get(addr+2)));
+              break;
+            case 'a': // addr8 (direct address) at 2nd byte
+              if (!get_name(rom->get(addr+1), sfr_tbl(), temp))
+                sprintf(temp, "%02"_M_"x", rom->get(addr+1));
+              break;
+            case '8': // addr8 (direct address) at 3rd byte
+              if (!get_name(rom->get(addr+2), sfr_tbl(), temp))
+                sprintf(temp, "%02"_M_"x", rom->get(addr+2));
+              //sprintf(temp, "%02"_M_"x", rom->get(addr+2));
+              break;
+            case 'b': // bitaddr at 2nd byte
+              {
+                t_addr ba= rom->get(addr+1);
+                if (get_name(ba, bit_tbl(), temp))
+                  break;
+                if (get_name((ba<128)?((ba/8)+32):(ba&0xf8), sfr_tbl(), temp))
+                  {
+                    strcat(temp, ".");
+                    sprintf(c, "%1"_M_"d", ba & 0x07);
+                    strcat(temp, c);
+                    break;
+                  }
+                sprintf(temp, "%02x.%"_M_"d", (ba<128)?((ba/8)+32):(ba&0xf8),
+                        ba & 0x07);
+                break;
+              }
+            case 'r': // rel8 address at 2nd byte
+              sprintf(temp, "%04"_A_"x",
+                      t_addr(addr+2+(signed char)(rom->get(addr+1))));
+              break;
+            case 'R': // rel8 address at 3rd byte
+              sprintf(temp, "%04"_A_"x",
+                      t_addr(addr+3+(signed char)(rom->get(addr+2))));
+              break;
+            case 'd': // data8 at 2nd byte
+              sprintf(temp, "%02"_M_"x", rom->get(addr+1));
+              break;
+            case 'D': // data8 at 3rd byte
+              sprintf(temp, "%02"_M_"x", rom->get(addr+2));
+              break;
+            case '6': // data16 at 2nd(H)-3rd(L) byte
+              sprintf(temp, "%04"_A_"x",
+                      t_addr(rom->get(addr+1)*256 +
+                             rom->get(addr+2)));
+              break;
+            default:
+              strcpy(temp, "?");
+              break;
+            }
+          t= temp;
+          while (*t)
+            *(p++)= *(t++);
+        }
       else
-       *(p++)= *(b++);
+        *(p++)= *(b++);
     }
   *p= '\0';
 
@@ -372,14 +409,14 @@ t_uc51::disass(t_addr addr, char *sep)
     buf= (char *)malloc(6+strlen(p)+1);
   else
     buf= (char *)malloc((p-work)+strlen(sep)+strlen(p)+1);
-  for (p= work, b= buf; *p != ' '; p++, b++)
-    *b= *p;
+  for (p= work, t= buf; *p != ' '; p++, t++)
+    *t= *p;
   p++;
-  *b= '\0';
+  *t= '\0';
   if (sep == NULL)
     {
       while (strlen(buf) < 6)
-       strcat(buf, " ");
+        strcat(buf, " ");
     }
   else
     strcat(buf, sep);
@@ -389,7 +426,7 @@ t_uc51::disass(t_addr addr, char *sep)
 
 
 void
-t_uc51::print_regs(class cl_console *con)
+cl_51core::print_regs(class cl_console_base *con)
 {
   t_addr start;
   uchar data;
@@ -400,22 +437,22 @@ t_uc51::print_regs(class cl_console *con)
   start= psw->get() & 0x18;
   data= iram->get(iram->get(start));
   con->dd_printf("%06x %02x %c",
-             iram->get(start), data, isprint(data)?data:'.');
+              iram->get(start), data, isprint(data)?data:'.');
 
   con->dd_printf("  ACC= 0x%02x %3d %c  B= 0x%02x", sfr->get(ACC), sfr->get(ACC),
-             isprint(sfr->get(ACC))?(sfr->get(ACC)):'.', sfr->get(B)); 
-  eram2xram();
-  data= get_mem(MEM_XRAM, sfr->get(DPH)*256+sfr->get(DPL));
+              isprint(sfr->get(ACC))?(sfr->get(ACC)):'.', sfr->get(B)); 
+  //eram2xram();
+  data= xram->get(sfr->get(DPH)*256+sfr->get(DPL));
   con->dd_printf("   DPTR= 0x%02x%02x @DPTR= 0x%02x %3d %c\n", sfr->get(DPH),
-             sfr->get(DPL), data, data, isprint(data)?data:'.');
+              sfr->get(DPL), data, data, isprint(data)?data:'.');
 
   data= iram->get(iram->get(start+1));
   con->dd_printf("%06x %02x %c", iram->get(start+1), data,
-             isprint(data)?data:'.');
+              isprint(data)?data:'.');
   data= psw->get();
   con->dd_printf("  PSW= 0x%02x CY=%c AC=%c OV=%c P=%c\n", data,
-             (data&bmCY)?'1':'0', (data&bmAC)?'1':'0',
-             (data&bmOV)?'1':'0', (data&bmP)?'1':'0');
+              (data&bmCY)?'1':'0', (data&bmAC)?'1':'0',
+              (data&bmOV)?'1':'0', (data&bmP)?'1':'0');
 
   print_disass(PC, con);
 }
@@ -425,10 +462,10 @@ t_uc51::print_regs(class cl_console *con)
  * Converting bit address into real memory
  */
 
-class cl_mem *
-t_uc51::bit2mem(t_addr bitaddr, t_addr *memaddr, t_mem *bitmask)
+class cl_address_space *
+cl_51core::bit2mem(t_addr bitaddr, t_addr *memaddr, t_mem *bitmask)
 {
-  class cl_mem *m;
+  class cl_address_space *m;
   t_addr ma;
 
   bitaddr&= 0xff;
@@ -449,13 +486,45 @@ t_uc51::bit2mem(t_addr bitaddr, t_addr *memaddr, t_mem *bitmask)
   return(m);
 }
 
+t_addr
+cl_51core::bit_address(class cl_memory *mem,
+                       t_addr mem_address, int bit_number)
+{
+  if (bit_number < 0 ||
+      bit_number > 7 ||
+      mem_address < 0)
+    return(-1);
+  class cl_memory *sfrchip= memory("sfr_chip");
+  if (mem == sfrchip)
+    {
+      mem= sfr;
+      mem_address+= sfr->start_address;
+    }
+  if (mem == sfr)
+    {
+      if (mem_address < 128 ||
+          mem_address % 8 != 0 ||
+          mem_address > 255)
+        return(-1);
+      return(128 + (mem_address-128) + bit_number);
+    }
+  if (mem == iram)
+    {
+      if (mem_address < 0x20 ||
+          mem_address >= 0x20+32)
+        return(-1);
+      return((mem_address-0x20)*8 + bit_number);
+    }
+  return(-1);
+}
+
 
 /*
  * Resetting the micro-controller
  */
 
 void
-t_uc51::reset(void)
+cl_51core::reset(void)
 {
   cl_uc::reset();
 
@@ -472,19 +541,37 @@ t_uc51::reset(void)
  */
 
 void
-t_uc51::clear_sfr(void)
+cl_51core::clear_sfr(void)
 {
   int i;
   
-  for (i= 0; i < SFR_SIZE; i++)
+  for (i= 0x80; i <= 0xff; i++)
     sfr->set(i, 0);
   sfr->/*set*/write(P0, 0xff);
   sfr->/*set*/write(P1, 0xff);
   sfr->/*set*/write(P2, 0xff);
   sfr->/*set*/write(P3, 0xff);
-  sfr->/*set*/write(SP, 7);
   prev_p1= /*port_pins[1] &*/ sfr->/*get*/read(P1);
   prev_p3= /*port_pins[3] &*/ sfr->/*get*/read(P3);
+  sfr->write(ACC, 0);
+  sfr->write(B, 0);
+  sfr->write(PSW, 0);
+  sfr->write(SP, 7);
+  sfr->write(DPL, 0);
+  sfr->write(DPH, 0);
+  sfr->write(IP, 0);
+  sfr->write(IE, 0);
+  sfr->write(TMOD, 0);
+  sfr->write(TCON, 0);
+  sfr->write(TH0, 0);
+  sfr->write(TL0, 0);
+  sfr->write(TH1, 0);
+  sfr->write(TL1, 0);
+  sfr->write(SCON, 0);
+  sfr->write(PCON, 0);
+
+  sfr->set_nuof_writes(0);
+  sfr->set_nuof_reads(0);
 }
 
 
@@ -493,61 +580,59 @@ t_uc51::clear_sfr(void)
  */
 
 void
-t_uc51::analyze(t_addr addr)
+cl_51core::analyze(t_addr addr)
 {
   uint code;
   struct dis_entry *tabl;
 
-  code= get_mem(MEM_ROM, addr);
+  code= rom->get(addr);
   tabl= &(dis_tbl()[code]);
   while (!inst_at(addr) &&
-        code != 0xa5 /* break point */)
+         code != 0xa5 /* break point */)
     {
       set_inst_at(addr);
       switch (tabl->branch)
-       {
-       case 'a': // acall
-         analyze((addr & 0xf800)|
-                 ((get_mem(MEM_ROM, addr+1)&0x07)*256+
-                  get_mem(MEM_ROM, addr+2)));
-         analyze(addr+tabl->length);
-         break;
-       case 'A': // ajmp
-         addr= (addr & 0xf800)|
-           ((get_mem(MEM_ROM, addr+1) & 0x07)*256 + get_mem(MEM_ROM, addr+2));
-         break;
-       case 'l': // lcall
-         analyze(get_mem(MEM_ROM, addr+1)*256 + get_mem(MEM_ROM, addr+2));
-         analyze(addr+tabl->length);
-         break;
-       case 'L': // ljmp
-         addr= get_mem(MEM_ROM, addr+1)*256 + get_mem(MEM_ROM, addr+2);
-         break;
-       case 'r': // reljmp (2nd byte)
-         analyze((addr + (signed char)(get_mem(MEM_ROM, addr+1))) &
-                 (EROM_SIZE - 1));
-         analyze(addr+tabl->length);
-         break;
-       case 'R': // reljmp (3rd byte)
-         analyze((addr+
-                  (signed char)(get_mem(MEM_ROM, addr+2)))&(EROM_SIZE-1));
-         analyze(addr+tabl->length);
-         break;
-       case 's': // sjmp
-         {
-           signed char target;
-           target= get_mem(MEM_ROM, addr+1);
-           addr+= 2;
-           addr= (addr+target)&(EROM_SIZE-1);
-           break;
-         }
-       case '_':
-         return;
-       default:
-         addr= (addr+tabl->length) & (EROM_SIZE - 1);
-         break;
-       }
-      code= get_mem(MEM_ROM, addr);
+        {
+        case 'a': // acall
+          analyze((addr & 0xf800)|
+                  ((rom->get(addr+1)&0x07)*256+
+                   rom->get(addr+2)));
+          analyze(addr+tabl->length);
+          break;
+        case 'A': // ajmp
+          addr= (addr & 0xf800)|
+            ((rom->get(addr+1) & 0x07)*256 + rom->get(addr+2));
+          break;
+        case 'l': // lcall
+          analyze(rom->get(addr+1)*256 + rom->get(addr+2));
+          analyze(addr+tabl->length);
+          break;
+        case 'L': // ljmp
+          addr= rom->get(addr+1)*256 + rom->get(addr+2);
+          break;
+        case 'r': // reljmp (2nd byte)
+          analyze(rom->validate_address(addr+(signed char)(rom->get(addr+1))));
+          analyze(addr+tabl->length);
+          break;
+        case 'R': // reljmp (3rd byte)
+          analyze(rom->validate_address(addr+(signed char)(rom->get(addr+2))));
+          analyze(addr+tabl->length);
+          break;
+        case 's': // sjmp
+          {
+            signed char target;
+            target= rom->get(addr+1);
+            addr+= 2;
+            addr= rom->validate_address(addr+target);
+            break;
+          }
+        case '_':
+          return;
+        default:
+          addr= rom->validate_address(addr+tabl->length);
+          break;
+        }
+      code= rom->get(addr);
       tabl= &(dis_tbl()[code]);
     }
 }
@@ -558,7 +643,7 @@ t_uc51::analyze(t_addr addr)
  */
 
 /*int
-t_uc51::tick_hw(int cycles)
+cl_51core::tick_hw(int cycles)
 {
   cl_uc::tick_hw(cycles);
   //do_hardware(cycles);
@@ -566,7 +651,7 @@ t_uc51::tick_hw(int cycles)
 }*/
 
 /*int
-t_uc51::tick(int cycles)
+cl_51core::tick(int cycles)
 {
   cl_uc::tick(cycles);
   //do_hardware(cycles);
@@ -581,10 +666,10 @@ t_uc51::tick(int cycles)
  * or an SFR.
  */
 
-class cl_cell *
-t_uc51::get_direct(t_mem addr)
+class cl_memory_cell *
+cl_51core::get_direct(t_mem addr)
 {
-  if (addr < SFR_START)
+  if (addr < sfr->start_address)
     return(iram->get_cell(addr));
   else
     return(sfr->get_cell(addr));
@@ -595,8 +680,8 @@ t_uc51::get_direct(t_mem addr)
  * Calculating address of specified register cell in IRAM
  */
 
-class cl_cell *
-t_uc51::get_reg(uchar regnum)
+class cl_memory_cell *
+cl_51core::get_reg(uchar regnum)
 {
   t_addr a= (psw->get() & (bmRS0|bmRS1)) | (regnum & 0x07);
   return(iram->get_cell(a));
@@ -608,10 +693,10 @@ t_uc51::get_reg(uchar regnum)
  */
 
 int
-t_uc51::exec_inst(void)
+cl_51core::exec_inst(void)
 {
   t_mem code;
-  int res;
+  int res= resGO;
 
   //pr_inst();
   instPC= PC;
@@ -628,104 +713,105 @@ t_uc51::exec_inst(void)
     case 0x03: res= inst_rr(code); break;
     case 0x04: res= inst_inc_a(code); break;
     case 0x05: res= inst_inc_addr(code); break;
-    case 0x06: case 0x07: res= inst_inc_$ri(code); break;
+    case 0x06: case 0x07: res= inst_inc_Sri(code); break;
     case 0x08: case 0x09: case 0x0a: case 0x0b:
     case 0x0c: case 0x0d: case 0x0e: case 0x0f: res= inst_inc_rn(code); break;
     case 0x10: res= inst_jbc_bit_addr(code); break;
     case 0x11: case 0x31: case 0x51: case 0x71:
     case 0x91: case 0xb1: case 0xd1: case 0xf1:res=inst_acall_addr(code);break;
-    case 0x12: res= inst_lcall(code, 0); break;
+    case 0x12: res= inst_lcall(code, 0, DD_FALSE); break;
     case 0x13: res= inst_rrc(code); break;
     case 0x14: res= inst_dec_a(code); break;
     case 0x15: res= inst_dec_addr(code); break;
-    case 0x16: case 0x17: res= inst_dec_$ri(code); break;
+    case 0x16: case 0x17: res= inst_dec_Sri(code); break;
     case 0x18: case 0x19: case 0x1a: case 0x1b:
     case 0x1c: case 0x1d: case 0x1e: case 0x1f: res= inst_dec_rn(code); break;
     case 0x20: res= inst_jb_bit_addr(code); break;
     case 0x22: res= inst_ret(code); break;
     case 0x23: res= inst_rl(code); break;
-    case 0x24: res= inst_add_a_$data(code); break;
+    case 0x24: res= inst_add_a_Sdata(code); break;
     case 0x25: res= inst_add_a_addr(code); break;
-    case 0x26: case 0x27: res= inst_add_a_$ri(code); break;
+    case 0x26: case 0x27: res= inst_add_a_Sri(code); break;
     case 0x28: case 0x29: case 0x2a: case 0x2b:
     case 0x2c: case 0x2d: case 0x2e: case 0x2f:res= inst_add_a_rn(code);break;
     case 0x30: res= inst_jnb_bit_addr(code); break;
     case 0x32: res= inst_reti(code); break;
     case 0x33: res= inst_rlc(code); break;
-    case 0x34: res= inst_addc_a_$data(code); break;
+    case 0x34: res= inst_addc_a_Sdata(code); break;
     case 0x35: res= inst_addc_a_addr(code); break;
-    case 0x36: case 0x37: res= inst_addc_a_$ri(code); break;
+    case 0x36: case 0x37: res= inst_addc_a_Sri(code); break;
     case 0x38: case 0x39: case 0x3a: case 0x3b:
     case 0x3c: case 0x3d: case 0x3e: case 0x3f:res= inst_addc_a_rn(code);break;
     case 0x40: res= inst_jc_addr(code); break;
     case 0x42: res= inst_orl_addr_a(code); break;
-    case 0x43: res= inst_orl_addr_$data(code); break;
-    case 0x44: res= inst_orl_a_$data(code); break;
+    case 0x43: res= inst_orl_addr_Sdata(code); break;
+    case 0x44: res= inst_orl_a_Sdata(code); break;
     case 0x45: res= inst_orl_a_addr(code); break;
-    case 0x46: case 0x47: res= inst_orl_a_$ri(code); break;
+    case 0x46: case 0x47: res= inst_orl_a_Sri(code); break;
     case 0x48: case 0x49: case 0x4a: case 0x4b:
     case 0x4c: case 0x4d: case 0x4e: case 0x4f: res= inst_orl_a_rn(code);break;
     case 0x50: res= inst_jnc_addr(code); break;
     case 0x52: res= inst_anl_addr_a(code); break;
-    case 0x53: res= inst_anl_addr_$data(code); break;
-    case 0x54: res= inst_anl_a_$data(code); break;
+    case 0x53: res= inst_anl_addr_Sdata(code); break;
+    case 0x54: res= inst_anl_a_Sdata(code); break;
     case 0x55: res= inst_anl_a_addr(code); break;
-    case 0x56: case 0x57: res= inst_anl_a_$ri(code); break;
+    case 0x56: case 0x57: res= inst_anl_a_Sri(code); break;
     case 0x58: case 0x59: case 0x5a: case 0x5b:
     case 0x5c: case 0x5d: case 0x5e: case 0x5f: res= inst_anl_a_rn(code);break;
     case 0x60: res= inst_jz_addr(code); break;
     case 0x62: res= inst_xrl_addr_a(code); break;
-    case 0x63: res= inst_xrl_addr_$data(code); break;
-    case 0x64: res= inst_xrl_a_$data(code); break;
+    case 0x63: res= inst_xrl_addr_Sdata(code); break;
+    case 0x64: res= inst_xrl_a_Sdata(code); break;
     case 0x65: res= inst_xrl_a_addr(code); break;
-    case 0x66: case 0x67: res= inst_xrl_a_$ri(code); break;
+    case 0x66: case 0x67: res= inst_xrl_a_Sri(code); break;
     case 0x68: case 0x69: case 0x6a: case 0x6b:
     case 0x6c: case 0x6d: case 0x6e: case 0x6f: res= inst_xrl_a_rn(code);break;
     case 0x70: res= inst_jnz_addr(code); break;
     case 0x72: res= inst_orl_c_bit(code); break;
-    case 0x73: res= inst_jmp_$a_dptr(code); break;
-    case 0x74: res= inst_mov_a_$data(code); break;
-    case 0x75: res= inst_mov_addr_$data(code); break;
-    case 0x76: case 0x77: res= inst_mov_$ri_$data(code); break;
+    case 0x73: res= inst_jmp_Sa_dptr(code); break;
+    case 0x74: res= inst_mov_a_Sdata(code); break;
+    case 0x75: res= inst_mov_addr_Sdata(code); break;
+    case 0x76: case 0x77: res= inst_mov_Sri_Sdata(code); break;
     case 0x78: case 0x79: case 0x7a: case 0x7b: case 0x7c:
-    case 0x7d: case 0x7e: case 0x7f: res=inst_mov_rn_$data(code); break;
+    case 0x7d: case 0x7e: case 0x7f: res=inst_mov_rn_Sdata(code); break;
     case 0x80: res= inst_sjmp(code); break;
     case 0x82: res= inst_anl_c_bit(code); break;
-    case 0x83: res= inst_movc_a_$a_pc(code); break;
+    case 0x83: res= inst_movc_a_Sa_pc(code); break;
     case 0x84: res= inst_div_ab(code); break;
     case 0x85: res= inst_mov_addr_addr(code); break;
-    case 0x86: case 0x87: res= inst_mov_addr_$ri(code); break;
+    case 0x86: case 0x87: res= inst_mov_addr_Sri(code); break;
     case 0x88: case 0x89: case 0x8a: case 0x8b:
     case 0x8c: case 0x8d: case 0x8e: case 0x8f:res=inst_mov_addr_rn(code);break;
-    case 0x90: res= inst_mov_dptr_$data(code); break;
+    case 0x90: res= inst_mov_dptr_Sdata(code); break;
     case 0x92: res= inst_mov_bit_c(code); break;
-    case 0x93: res= inst_movc_a_$a_dptr(code); break;
-    case 0x94: res= inst_subb_a_$data(code); break;
+    case 0x93: res= inst_movc_a_Sa_dptr(code); break;
+    case 0x94: res= inst_subb_a_Sdata(code); break;
     case 0x95: res= inst_subb_a_addr(code); break;
-    case 0x96: case 0x97: res= inst_subb_a_$ri(code); break;
+    case 0x96: case 0x97: res= inst_subb_a_Sri(code); break;
     case 0x98: case 0x99: case 0x9a: case 0x9b:
     case 0x9c: case 0x9d: case 0x9e: case 0x9f:res= inst_subb_a_rn(code);break;
+    case 0xa0: res= inst_orl_c_Sbit(code); break;
     case 0xa2: res= inst_mov_c_bit(code); break;
     case 0xa3: res= inst_inc_dptr(code); break;
     case 0xa4: res= inst_mul_ab(code); break;
-    case 0xa5: res= inst_unknown(code); break;
-    case 0xa6: case 0xa7: res= inst_mov_$ri_addr(code); break;
+    case 0xa5: res= inst_unknown(); break;
+    case 0xa6: case 0xa7: res= inst_mov_Sri_addr(code); break;
     case 0xa8: case 0xa9: case 0xaa: case 0xab:
     case 0xac: case 0xad: case 0xae: case 0xaf:res=inst_mov_rn_addr(code);break;
-    case 0xb0: res= inst_anl_c_$bit(code); break;
+    case 0xb0: res= inst_anl_c_Sbit(code); break;
     case 0xb2: res= inst_cpl_bit(code); break;
     case 0xb3: res= inst_cpl_c(code); break;
-    case 0xb4: res= inst_cjne_a_$data_addr(code); break;
+    case 0xb4: res= inst_cjne_a_Sdata_addr(code); break;
     case 0xb5: res= inst_cjne_a_addr_addr(code); break;
-    case 0xb6: case 0xb7: res= inst_cjne_$ri_$data_addr(code); break;
+    case 0xb6: case 0xb7: res= inst_cjne_Sri_Sdata_addr(code); break;
     case 0xb8: case 0xb9: case 0xba: case 0xbb: case 0xbc:
-    case 0xbd: case 0xbe: case 0xbf: res=inst_cjne_rn_$data_addr(code); break;
+    case 0xbd: case 0xbe: case 0xbf: res=inst_cjne_rn_Sdata_addr(code); break;
     case 0xc0: res= inst_push(code); break;
     case 0xc2: res= inst_clr_bit(code); break;
     case 0xc3: res= inst_clr_c(code); break;
     case 0xc4: res= inst_swap(code); break;
     case 0xc5: res= inst_xch_a_addr(code); break;
-    case 0xc6: case 0xc7: res= inst_xch_a_$ri(code); break;
+    case 0xc6: case 0xc7: res= inst_xch_a_Sri(code); break;
     case 0xc8: case 0xc9: case 0xca: case 0xcb:
     case 0xcc: case 0xcd: case 0xce: case 0xcf: res= inst_xch_a_rn(code);break;
     case 0xd0: res= inst_pop(code); break;
@@ -733,25 +819,25 @@ t_uc51::exec_inst(void)
     case 0xd3: res= inst_setb_c(code); break;
     case 0xd4: res= inst_da_a(code); break;
     case 0xd5: res= inst_djnz_addr_addr(code); break;
-    case 0xd6: case 0xd7: res= inst_xchd_a_$ri(code); break;
+    case 0xd6: case 0xd7: res= inst_xchd_a_Sri(code); break;
     case 0xd8: case 0xd9: case 0xda: case 0xdb: case 0xdc:
     case 0xdd: case 0xde: case 0xdf: res=inst_djnz_rn_addr(code); break;
-    case 0xe0: res= inst_movx_a_$dptr(code); break;
-    case 0xe2: case 0xe3: res= inst_movx_a_$ri(code); break;
+    case 0xe0: res= inst_movx_a_Sdptr(code); break;
+    case 0xe2: case 0xe3: res= inst_movx_a_Sri(code); break;
     case 0xe4: res= inst_clr_a(code); break;
     case 0xe5: res= inst_mov_a_addr(code); break;
-    case 0xe6: case 0xe7: res= inst_mov_a_$ri(code); break;
+    case 0xe6: case 0xe7: res= inst_mov_a_Sri(code); break;
     case 0xe8: case 0xe9: case 0xea: case 0xeb:
     case 0xec: case 0xed: case 0xee: case 0xef: res= inst_mov_a_rn(code);break;
-    case 0xf0: res= inst_movx_$dptr_a(code); break;
-    case 0xf2: case 0xf3: res= inst_movx_$ri_a(code); break;
+    case 0xf0: res= inst_movx_Sdptr_a(code); break;
+    case 0xf2: case 0xf3: res= inst_movx_Sri_a(code); break;
     case 0xf4: res= inst_cpl_a(code); break;
     case 0xf5: res= inst_mov_addr_a(code); break;
-    case 0xf6: case 0xf7: res= inst_mov_$ri_a(code); break;
+    case 0xf6: case 0xf7: res= inst_mov_Sri_a(code); break;
     case 0xf8: case 0xf9: case 0xfa: case 0xfb:
     case 0xfc: case 0xfd: case 0xfe: case 0xff: res= inst_mov_rn_a(code);break;
     default:
-      res= inst_unknown(code);
+      res= inst_unknown();
       break;
     }
   //post_inst();
@@ -771,74 +857,95 @@ t_uc51::exec_inst(void)
  * (inp_avail will be TRUE if ENTER is pressed) and it can confuse
  * command interepter.
  */
-
+//static class cl_console_base *c= NULL;
 int
-t_uc51::do_inst(int step)
+cl_51core::do_inst(int step)
 {
   result= resGO;
   while ((result == resGO) &&
-        (state != stPD) &&
-        (step != 0))
+         (state != stPD) &&
+         (step != 0))
     {
       if (step > 0)
-       step--;
+        step--;
       if (state == stGO)
-       {
-         interrupt->was_reti= DD_FALSE;
-         pre_inst();
-         result= exec_inst();
-         post_inst();
-         /*if (result == resGO)
-           result= check_events();*/
-       }
+        {
+          interrupt->was_reti= DD_FALSE;
+          pre_inst();
+          result= exec_inst();
+          post_inst();
+          /*
+          {
+            if (c)
+              print_regs(c);
+            else
+              {
+                if (sim->app->get_commander()==NULL)
+                  printf("no commander PC=0x%x\n",PC);
+                else
+                  if (sim->app->get_commander()->frozen_console==NULL)
+                    printf("no frozen console PC=0x%x\n",PC);
+                  else
+                    c= sim->app->get_commander()->frozen_console;
+                if (c)
+                  print_regs(c);
+                else
+                  printf("no console PC=0x%x\n",PC);
+              }
+          }
+          */
+          /*if (result == resGO)
+            result= check_events();*/
+        }
       else
-       {
-         // tick hw in idle state
-         post_inst();
-         tick(1);
-       }
+        {
+          // tick hw in idle state
+          inst_ticks= 1;
+          post_inst();
+          tick(1);
+        }
       if (result == resGO)
-       {
-         int res;
-         if ((res= do_interrupt()) != resGO)
-           result= res;
-         else
-           result= idle_pd();
-       }
+        {
+          int res;
+          if ((res= do_interrupt()) != resGO)
+            result= res;
+          else
+            result= idle_pd();
+        }
       if ((step < 0) &&
-         ((ticks->ticks % 100000) < 50))
-       {
-         if (sim->app->get_commander()->input_avail_on_frozen())
-           {
-             result= resUSER;
-           }
-         else
-           if (sim->app->get_commander()->input_avail())
-             break;
-       }
+          ((ticks->ticks % 100000) < 50))
+        {
+          if (sim->app->get_commander()->input_avail_on_frozen())
+            {
+              result= resUSER;
+            }
+          else
+            if (sim->app->get_commander()->input_avail())
+              break;
+        }
       if (((result == resINTERRUPT) &&
-          stop_at_it) ||
-         result >= resSTOP)
-       {
-         sim->stop(result);
-         break;
-       }
+           stop_at_it) ||
+          result >= resSTOP)
+        {
+          sim->stop(result);
+          break;
+        }
     }
   if (state == stPD)
     {
       //FIXME: tick outsiders eg. watchdog
       if (sim->app->get_commander()->input_avail_on_frozen())
-       {
-         //fprintf(stderr,"uc: inp avail in PD mode, user stop\n");
+        {
+          //fprintf(stderr,"uc: inp avail in PD mode, user stop\n");
           result= resUSER;
           sim->stop(result); 
-       }
+        }
     }
   return(result);
 }
 
 /*void
-t_uc51::post_inst(void)
+cl_51core::post_inst(void)
 {*/
   //uint tcon= sfr->get(TCON);
   //uint p3= sfr->read(P3);
@@ -851,41 +958,41 @@ t_uc51::post_inst(void)
     {
       // IE0 edge triggered
       if (p3_int0_edge)
-       {
-         // falling edge on INT0
-         sim->app->get_commander()->
-           debug("%g sec (%d clks): Falling edge detected on INT0 (P3.2)\n",
-                         get_rtime(), ticks->ticks);
-         sfr->set_bit1(TCON, bmIE0);
-         p3_int0_edge= 0;
-       }
+        {
+          // falling edge on INT0
+          sim->app->get_commander()->
+            debug("%g sec (%d clks): Falling edge detected on INT0 (P3.2)\n",
+                          get_rtime(), ticks->ticks);
+          sfr->set_bit1(TCON, bmIE0);
+          p3_int0_edge= 0;
+        }
     }
   else
     {
       // IE0 level triggered
       if (p3 & bm_INT0)
-       sfr->set_bit0(TCON, bmIE0);
+        sfr->set_bit0(TCON, bmIE0);
       else
-       sfr->set_bit1(TCON, bmIE0);
+        sfr->set_bit1(TCON, bmIE0);
     }
   if ((tcon & bmIT1))
     {
       // IE1 edge triggered
       if (p3_int1_edge)
-       {
-         // falling edge on INT1
-         sfr->set_bit1(TCON, bmIE1);
-         p3_int1_edge= 0;
-       }
+        {
+          // falling edge on INT1
+          sfr->set_bit1(TCON, bmIE1);
+          p3_int1_edge= 0;
+        }
     }
   else
     {
       // IE1 level triggered
       if (p3 & bm_INT1)
-       sfr->set_bit0(TCON, bmIE1);
+        sfr->set_bit0(TCON, bmIE1);
       else
-       sfr->set_bit1(TCON, bmIE1);
-       }*/
+        sfr->set_bit1(TCON, bmIE1);
+        }*/
   //prev_p3= p3 & port_pins[3];
   //prev_p1= p3 & port_pins[1];
 //}
@@ -896,7 +1003,7 @@ t_uc51::post_inst(void)
  */
 
 /*int
-t_uc51::do_wdt(int cycles)
+cl_51core::do_wdt(int cycles)
 {
   return(resGO);
 }*/
@@ -907,7 +1014,7 @@ t_uc51::do_wdt(int cycles)
  */
 
 int
-t_uc51::do_interrupt(void)
+cl_51core::do_interrupt(void)
 {
   int i, ie= 0;
 
@@ -923,34 +1030,34 @@ t_uc51::do_interrupt(void)
     {
       class cl_it_src *is= (class cl_it_src *)(it_sources->at(i));
       if (is->is_active() &&
-         (ie & is->ie_mask) &&
-         (sfr->get(is->src_reg) & is->src_mask))
-       {
-         int pr= it_priority(is->ie_mask);
-         if (il->level >= 0 &&
-             pr <= il->level)
-           continue;
-         if (state == stIDLE)
-           {
-             state= stGO;
-             sfr->set_bit0(PCON, bmIDL);
-             interrupt->was_reti= DD_TRUE;
-             return(resGO);
-           }
-         if (is->clr_bit)
-           sfr->set_bit0(is->src_reg, is->src_mask);
-         sim->app->get_commander()->
-           debug("%g sec (%d clks): Accepting interrupt `%s' PC= 0x%06x\n",
-                         get_rtime(), ticks->ticks, is->name, PC);
-         IL= new it_level(pr, is->addr, PC, is);
-         return(accept_it(IL));
-       }
+          (ie & is->ie_mask) &&
+          (sfr->get(is->src_reg) & is->src_mask))
+        {
+          int pr= it_priority(is->ie_mask);
+          if (il->level >= 0 &&
+              pr <= il->level)
+            continue;
+          if (state == stIDLE)
+            {
+              state= stGO;
+              sfr->set_bit0(PCON, bmIDL);
+              interrupt->was_reti= DD_TRUE;
+              return(resGO);
+            }
+          if (is->clr_bit)
+            sfr->set_bit0(is->src_reg, is->src_mask);
+          sim->app->get_commander()->
+            debug("%g sec (%d clks): Accepting interrupt `%s' PC= 0x%06x\n",
+                          get_rtime(), ticks->ticks, object_name(is), PC);
+          IL= new it_level(pr, is->addr, PC, is);
+          return(accept_it(IL));
+        }
     }
   return(resGO);
 }
 
 int
-t_uc51::it_priority(uchar ie_mask)
+cl_51core::it_priority(uchar ie_mask)
 {
   if (sfr->get(IP) & ie_mask)
     return(1);
@@ -963,13 +1070,13 @@ t_uc51::it_priority(uchar ie_mask)
  */
 
 int
-t_uc51::accept_it(class it_level *il)
+cl_51core::accept_it(class it_level *il)
 {
   state= stGO;
   sfr->set_bit0(PCON, bmIDL);
   it_levels->push(il);
   tick(1);
-  int res= inst_lcall(0, il->addr);
+  int res= inst_lcall(0, il->addr, DD_TRUE);
   if (res != resGO)
     return(res);
   else
@@ -982,7 +1089,7 @@ t_uc51::accept_it(class it_level *il)
  */
 
 int
-t_uc51::idle_pd(void)
+cl_51core::idle_pd(void)
 {
   uint pcon= sfr->get(PCON);
 
@@ -991,18 +1098,18 @@ t_uc51::idle_pd(void)
   if (pcon & bmIDL)
     {
       if (state != stIDLE)
-       sim->app->get_commander()->
-         debug("%g sec (%d clks): CPU in Idle mode\n",
-               get_rtime(), ticks->ticks);
+        sim->app->get_commander()->
+          debug("%g sec (%d clks): CPU in Idle mode (PC=0x%x, PCON=0x%x)\n",
+                get_rtime(), ticks->ticks, PC, pcon);
       state= stIDLE;
       //was_reti= 1;
     }
   if (pcon & bmPD)
     {
       if (state != stPD)
-       sim->app->get_commander()->
-         debug("%g sec (%d clks): CPU in PowerDown mode\n",
-                       get_rtime(), ticks->ticks);
+        sim->app->get_commander()->
+          debug("%g sec (%d clks): CPU in PowerDown mode\n",
+                        get_rtime(), ticks->ticks);
       state= stPD;
     }
   return(resGO);
@@ -1014,7 +1121,7 @@ t_uc51::idle_pd(void)
  */
 
 /*int
-t_uc51::check_events(void)
+cl_51core::check_events(void)
 {
   int i;
   class cl_ev_brk *eb;
@@ -1025,7 +1132,7 @@ t_uc51::check_events(void)
     {
       eb= (class cl_ev_brk *)(ebrk->at(i));
       if (eb->match(&event_at))
-       return(resBREAKPOINT);
+        return(resBREAKPOINT);
     }
   return(resGO);
 }*/
@@ -1034,8 +1141,9 @@ t_uc51::check_events(void)
 /*
  */
 
+/*
 void
-t_uc51::mem_cell_changed(class cl_mem *mem, t_addr addr)
+cl_51core::mem_cell_changed(class cl_m *mem, t_addr addr)
 {
   if (mem == sfr)
     switch (addr)
@@ -1045,6 +1153,7 @@ t_uc51::mem_cell_changed(class cl_mem *mem, t_addr addr)
       }
   cl_uc::mem_cell_changed(mem, addr);
 }
+*/
 
 
 /*
@@ -1055,13 +1164,12 @@ t_uc51::mem_cell_changed(class cl_mem *mem, t_addr addr)
  */
 
 int
-t_uc51::inst_unknown(uchar code)
+cl_51core::inst_unknown(void)
 {
-  PC--;
-  if (1)//debug)// && sim->cmd_out())
-    sim->app->get_commander()->
-      debug("Unknown instruction %02x at %06x\n", code, PC);
-  return(resHALT);
+  //PC--;
+  class cl_error_unknown_code *e= new cl_error_unknown_code(this);
+  error(e);
+  return(resGO);
 }
 
 
@@ -1070,7 +1178,7 @@ t_uc51::inst_unknown(uchar code)
  */
 
 int
-t_uc51::inst_nop(uchar code)
+cl_51core::inst_nop(uchar code)
 {
   return(resGO);
 }
@@ -1081,7 +1189,7 @@ t_uc51::inst_nop(uchar code)
  */
 
 int
-t_uc51::inst_clr_a(uchar code)
+cl_51core::inst_clr_a(uchar code)
 {
   acc->write(0);
   return(resGO);
@@ -1093,7 +1201,7 @@ t_uc51::inst_clr_a(uchar code)
  */
 
 int
-t_uc51::inst_swap(uchar code)
+cl_51core::inst_swap(uchar code)
 {
   uchar temp;
 
@@ -1109,13 +1217,13 @@ t_uc51::inst_swap(uchar code)
 cl_uc51_dummy_hw::cl_uc51_dummy_hw(class cl_uc *auc):
   cl_hw(auc, HW_DUMMY, 0, "_51_dummy")
 {
-  //uc51= (class t_uc51 *)uc;
+  //uc51= (class cl_51core *)uc;
 }
 
 int
 cl_uc51_dummy_hw::init(void)
 {
-  class cl_mem *sfr= uc->mem(MEM_SFR);
+  class cl_address_space *sfr= uc->address_space(MEM_SFR_ID);
   if (!sfr)
     {
       fprintf(stderr, "No SFR to register %s[%d] into\n", id_string, id);
@@ -1125,11 +1233,12 @@ cl_uc51_dummy_hw::init(void)
   use_cell(sfr, PSW, &cell_psw, wtd_restore);
   register_cell(sfr, ACC, &cell_acc, wtd_restore_write);
   register_cell(sfr, SP , &cell_sp , wtd_restore);
+  //register_cell(sfr, PCON, &cell_pcon, wtd_restore);
   return(0);
 }
 
 void
-cl_uc51_dummy_hw::write(class cl_cell *cell, t_mem *val)
+cl_uc51_dummy_hw::write(class cl_memory_cell *cell, t_mem *val)
 {
   if (cell == cell_acc)
     {
@@ -1140,22 +1249,27 @@ cl_uc51_dummy_hw::write(class cl_cell *cell, t_mem *val)
       p = DD_FALSE;
       uc= *val;
       for (i= 0; i < 8; i++)
-       {
-         if (uc & 1)
-           p= !p;
-         uc>>= 1;
-       }
+        {
+          if (uc & 1)
+            p= !p;
+          uc>>= 1;
+        }
       if (p)
-       cell_psw->set_bit1(bmP);
+        cell_psw->set_bit1(bmP);
       else
-       cell_psw->set_bit0(bmP);
+        cell_psw->set_bit0(bmP);
     }
   else if (cell == cell_sp)
     {
       if (*val > uc->sp_max)
-       uc->sp_max= *val;
+        uc->sp_max= *val;
       uc->sp_avg= (uc->sp_avg+(*val))/2;
     }
+  /*else if (cell == cell_pcon)
+    {
+      printf("PCON write 0x%x (PC=0x%x)\n", *val, uc->PC);
+      uc->sim->stop(0);
+      }*/
 }
 
 /*void
@@ -1170,11 +1284,11 @@ cl_uc51_dummy_hw::happen(class cl_hw *where, enum hw_event he, void *params)
       t_mem p3o= ep->pins & ep->prev_value;
       t_mem p3n= ep->new_pins & ep->new_value;
       if ((p3o & bm_INT0) &&
-         !(p3n & bm_INT0))
-       uc51->p3_int0_edge++;
+          !(p3n & bm_INT0))
+        uc51->p3_int0_edge++;
       if ((p3o & bm_INT1) &&
-         !(p3n & bm_INT1))
-       uc51->p3_int1_edge++;
+          !(p3n & bm_INT1))
+        uc51->p3_int1_edge++;
     }
 }*/