version 0.5.2
[fw/sdcc] / sim / ucsim / sim.src / stack.cc
index c8941d678fb12eabf557d312b20efa3935e17a61..d9c5fe8d1296610c6b75ac3d8f25cdd69f57719a 100644 (file)
@@ -25,18 +25,24 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 02111-1307, USA. */
 /*@1@*/
 
+#include <stdlib.h>
+
+// cmd.src
+#include "newcmdcl.h"
+
+// sim.src
 #include "stackcl.h"
 
 
-cl_stack_op::cl_stack_op(enum stack_op itype,
-                        t_addr iPC, t_addr iaddr, t_mem idata,
+cl_stack_op::cl_stack_op(enum stack_op op,
+                        t_addr iPC,
                         t_addr iSP_before, t_addr iSP_after):
   cl_base()
 {
-  type= itype;
+  operation= op;
   PC= iPC;
-  addr= iaddr;
-  data= idata;
+  //addr= iaddr;
+  //data= idata;
   SP_before= iSP_before;
   SP_after= iSP_after;
 }
@@ -46,4 +52,487 @@ cl_stack_op::~cl_stack_op(void)
 }
 
 
+class cl_stack_op *
+cl_stack_op::mk_copy(void)
+{
+  class cl_stack_op *so= new cl_stack_op(*this);
+  return(so);
+}
+
+void
+cl_stack_op::info_head(class cl_console *con)
+{
+  con->dd_printf("OP   SP before-after   L DATA/ADDR   INSTRUCTION\n");
+}
+
+void
+cl_stack_op::info(class cl_console *con, class cl_uc *uc)
+{
+  con->dd_printf("%-4s 0x%06"_A_"x-0x%06"_A_"x %d ",
+                get_op_name(), SP_before, SP_after, abs(SP_before-SP_after));
+  print_info(con);
+  con->dd_printf(" ");
+  uc->print_disass(PC, con);
+  //con->dd_printf("\n");
+}
+
+char *
+cl_stack_op::get_op_name(void)
+{
+  return("op");
+}
+
+void
+cl_stack_op::print_info(class cl_console *con)
+{
+  con->dd_printf("-");
+}
+
+bool
+cl_stack_op::sp_increased(void)
+{
+  if (operation & stack_write_operation)
+    return(SP_after > SP_before);
+  else // read operation
+    return(SP_after < SP_before);
+}
+
+int
+cl_stack_op::data_size(void)
+{
+  int r= SP_after - SP_before;
+
+  return(r<0?-r:r);
+}
+
+int
+cl_stack_op::match(class cl_stack_op *op)
+{
+  return(DD_FALSE);
+}
+
+bool
+cl_stack_op::can_removed(class cl_stack_op *op)
+{
+  bool incr= sp_increased(); // FIXME
+  bool op_incr= op->sp_increased(); // FIXME
+
+  if ((incr && !op_incr) ||
+      (!incr && op_incr))
+    {
+      printf("BIGBIG ERROR!\n");
+      return(DD_FALSE);
+    }
+  if (incr)
+    {
+      t_mem opa= op->get_after();
+      return(SP_before >= opa);
+    }
+  else
+    {
+      t_mem opa= op->get_after();
+      return(SP_before <= opa);
+    }
+}
+
+
+/*
+ * CALL operation on stack
+ */
+
+cl_stack_call::cl_stack_call(t_addr iPC, t_addr called, t_addr pushed,
+                            t_addr iSP_before, t_addr iSP_after):
+  cl_stack_op(stack_call, iPC, iSP_before, iSP_after)
+{
+  called_addr= called;
+  pushed_addr= pushed;
+}
+
+class cl_stack_op *
+cl_stack_call::mk_copy(void)
+{
+  class cl_stack_call *so= new cl_stack_call(*this);
+  return(so);
+}
+
+char *
+cl_stack_call::get_op_name(void)
+{
+  return("call");
+}
+
+void
+cl_stack_call::print_info(class cl_console *con)
+{
+  con->dd_printf("0x%06"_A_"x", called_addr);
+}
+
+char *
+cl_stack_call::get_matching_name(void)
+{
+  return("ret");
+}
+
+enum stack_op
+cl_stack_call::get_matching_op(void)
+{
+  return(stack_ret);
+}
+
+bool
+cl_stack_call::match(class cl_stack_op *op)
+{
+  return(op->get_op() == stack_ret);
+}
+
+
+/*
+ * INTERRUPT operation (call) on stack
+ */
+
+cl_stack_intr::cl_stack_intr(t_addr iPC, t_addr called, t_addr pushed,
+                            t_addr iSP_before, t_addr iSP_after):
+  cl_stack_call(iPC, called, pushed, iSP_before, iSP_after)
+{
+  //called_addr= called;
+  //pushed_addr= pushed;
+  operation= stack_intr;
+}
+
+class cl_stack_op *
+cl_stack_intr::mk_copy(void)
+{
+  class cl_stack_intr *so= new cl_stack_intr(*this);
+  return(so);
+}
+
+char *
+cl_stack_intr::get_op_name(void)
+{
+  return("intr");
+}
+
+void
+cl_stack_intr::print_info(class cl_console *con)
+{
+  con->dd_printf("0x%06"_A_"x", called_addr);
+}
+
+char *
+cl_stack_intr::get_matching_name(void)
+{
+  return("iret");
+}
+
+enum stack_op
+cl_stack_intr::get_matching_op(void)
+{
+  return(stack_iret);
+}
+
+int
+cl_stack_intr::match(class cl_stack_op *op)
+{
+  return(op->get_op() == stack_iret);
+}
+
+
+/*
+ * PUSH operation on stack
+ */
+
+cl_stack_push::cl_stack_push(t_addr iPC, t_mem idata,
+                            t_addr iSP_before, t_addr iSP_after):
+  cl_stack_op(stack_push, iPC, iSP_before, iSP_after)
+{
+  data= idata;
+}
+
+class cl_stack_op *
+cl_stack_push::mk_copy(void)
+{
+  class cl_stack_push *so= new cl_stack_push(*this);
+  return(so);
+}
+
+char *
+cl_stack_push::get_op_name(void)
+{
+  return("push");
+}
+
+char *
+cl_stack_push::get_matching_name(void)
+{
+  return("pop");
+}
+
+enum stack_op
+cl_stack_push::get_matching_op(void)
+{
+  return(stack_pop);
+}
+
+void
+cl_stack_push::print_info(class cl_console *con)
+{
+  t_addr d= data;
+  con->dd_printf("0x%06"_A_"x", d);
+}
+
+int
+cl_stack_push::match(class cl_stack_op *op)
+{
+  return(op->get_op() == stack_pop);
+}
+
+
+/*
+ * RETURN operation on stack
+ */
+
+cl_stack_ret::cl_stack_ret(t_addr iPC, t_addr iaddr,
+                          t_addr iSP_before, t_addr iSP_after):
+  cl_stack_call(iPC, iaddr, 0, iSP_before, iSP_after)
+{
+  operation= stack_ret;
+}
+
+class cl_stack_op *
+cl_stack_ret::mk_copy(void)
+{
+  class cl_stack_ret *so= new cl_stack_ret(*this);
+  return(so);
+}
+
+char *
+cl_stack_ret::get_op_name(void)
+{
+  return("ret");
+}
+
+char *
+cl_stack_ret::get_matching_name(void)
+{
+  return("call");
+}
+
+enum stack_op
+cl_stack_ret::get_matching_op(void)
+{
+  return(stack_call);
+}
+
+int
+cl_stack_ret::match(class cl_stack_op *op)
+{
+  return(op->get_op() == stack_call);
+}
+
+
+/*
+ * RETURN from interrupt operation on stack
+ */
+
+cl_stack_iret::cl_stack_iret(t_addr iPC, t_addr iaddr,
+                            t_addr iSP_before, t_addr iSP_after):
+  cl_stack_ret(iPC, iaddr, iSP_before, iSP_after)
+{
+  operation= stack_iret;
+}
+
+class cl_stack_op *
+cl_stack_iret::mk_copy(void)
+{
+  class cl_stack_iret *so= new cl_stack_iret(*this);
+  return(so);
+}
+
+char *
+cl_stack_iret::get_op_name(void)
+{
+  return("iret");
+}
+
+char *
+cl_stack_iret::get_matching_name(void)
+{
+  return("intr");
+}
+
+enum stack_op
+cl_stack_iret::get_matching_op(void)
+{
+  return(stack_intr);
+}
+
+int
+cl_stack_iret::match(class cl_stack_op *op)
+{
+  return(op->get_op() == stack_intr);
+}
+
+
+/*
+ * POP operation on stack
+ */
+
+cl_stack_pop::cl_stack_pop(t_addr iPC, t_mem idata,
+                          t_addr iSP_before, t_addr iSP_after):
+  cl_stack_push(iPC, idata, iSP_before, iSP_after)
+{
+  operation= stack_pop;
+}
+
+class cl_stack_op *
+cl_stack_pop::mk_copy(void)
+{
+  class cl_stack_pop *so= new cl_stack_pop(*this);
+  return(so);
+}
+
+char *
+cl_stack_pop::get_op_name(void)
+{
+  return("pop");
+}
+
+char *
+cl_stack_pop::get_matching_name(void)
+{
+  return("push");
+}
+
+enum stack_op
+cl_stack_pop::get_matching_op(void)
+{
+  return(stack_push);
+}
+
+int
+cl_stack_pop::match(class cl_stack_op *op)
+{
+  return(op->get_op() == stack_push);
+}
+
+
+/*
+ * Stack Errors
+ */
+
+ERROR_CLASS_DEF_PARENT_ON(err_error, stack, "stack",
+                         error_class_base, ERROR_OFF);
+
+/* Stack Tracker Errors */
+ERROR_CLASS_DEF_PARENT(err_error, stack_tracker, "stack_tracker",
+                      error_stack_class);
+
+/* Stack Tracker: wrong handle */
+ERROR_CLASS_DEF_PARENT(err_error,
+                      stack_tracker_wrong_handle,
+                      "stack_tracker_wrong_handle",
+                      error_stack_tracker_class)
+
+cl_error_stack_tracker_wrong_handle::cl_error_stack_tracker_wrong_handle(bool write_op):
+  cl_error_stack_tracker()
+{
+  write_operation= write_op;
+  classification= &error_stack_tracker_wrong_handle_class;
+}
+
+void
+cl_error_stack_tracker_wrong_handle::print(class cl_commander *c)
+{
+  c->dd_printf("%s: wrong stack tracker handle called for %s operation\n",
+              get_type_name(), write_operation?"write":"read");
+}
+
+/* Stack Tracker: operation on empty stack */
+ERROR_CLASS_DEF_PARENT(err_error,
+                      stack_tracker_empty,
+                      "operation_on_empty_stack",
+                      error_stack_tracker_class);
+
+cl_error_stack_tracker_empty::
+cl_error_stack_tracker_empty(class cl_stack_op *op):
+  cl_error_stack_tracker()
+{
+  operation= op->mk_copy();
+  classification= &error_stack_tracker_empty_class;
+}
+
+cl_error_stack_tracker_empty::~cl_error_stack_tracker_empty(void)
+{
+  delete operation;
+}
+
+void
+cl_error_stack_tracker_empty::print(class cl_commander *c)
+{
+  c->dd_printf("%s(0x%06"_A_"x: %s on empty stack, PC="
+              "0x06"_A_"x, SP=0x%06"_A_"x->0x%06"_A_"x\n",
+              get_type_name(), operation->get_pc(), operation->get_op_name(),
+              operation->get_before(), operation->get_after());
+}
+
+/* Stack Tracker: operation on empty stack */
+ERROR_CLASS_DEF_PARENT(err_warning,
+                      stack_tracker_unmatch,
+                      "stack_operation_unmatched_to_top_of_stack",
+                      error_stack_tracker_class);
+
+cl_error_stack_tracker_unmatch::
+cl_error_stack_tracker_unmatch(class cl_stack_op *Top, class cl_stack_op *op):
+  cl_error_stack_tracker()
+{
+  top= Top->mk_copy();
+  operation= op->mk_copy();
+  classification= &error_stack_tracker_unmatch_class;
+}
+
+cl_error_stack_tracker_unmatch::~cl_error_stack_tracker_unmatch(void)
+{
+  delete operation;
+  delete top;
+}
+
+void
+cl_error_stack_tracker_unmatch::print(class cl_commander *c)
+{
+  c->dd_printf("%s(0x%06"_A_"x): %s when %s expected, "
+              "SP=0x%06"_A_"x->0x%06"_A_"x\n",
+              get_type_name(), operation->get_pc(),
+              operation->get_op_name(), top->get_matching_name(),
+              operation->get_before(), operation->get_after());
+}
+
+/* Stack Tracker: stack is inconsistent */
+ERROR_CLASS_DEF_PARENT(err_warning,
+                      stack_tracker_inconsistent,
+                      "stack_looks_corrupted",
+                      error_stack_tracker_class);
+
+cl_error_stack_tracker_inconsistent::
+cl_error_stack_tracker_inconsistent(class cl_stack_op *op,
+                                   int the_unread_data_size)
+{
+  operation= op->mk_copy();
+  unread_data_size= the_unread_data_size;
+  classification= &error_stack_tracker_inconsistent_class;
+}
+
+cl_error_stack_tracker_inconsistent::~cl_error_stack_tracker_inconsistent(void)
+{
+  delete operation;
+}
+
+void
+cl_error_stack_tracker_inconsistent::print(class cl_commander *c)
+{
+  c->dd_printf("%s(0x%06"_A_"x): %d byte(s) unread from the stack\n",
+              get_type_name(), operation->get_pc(),
+              unread_data_size);
+}
+
+
 /* End of sim.src/stack.cc */