X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=sim%2Fucsim%2Fsim.src%2Fstack.cc;h=d9c5fe8d1296610c6b75ac3d8f25cdd69f57719a;hb=f27da39dbcab5678aca6d8462f1cc37a643f37e9;hp=c8941d678fb12eabf557d312b20efa3935e17a61;hpb=7fe573ea83f6e0762dc73bc493f15fa2a8f6273d;p=fw%2Fsdcc diff --git a/sim/ucsim/sim.src/stack.cc b/sim/ucsim/sim.src/stack.cc index c8941d67..d9c5fe8d 100644 --- a/sim/ucsim/sim.src/stack.cc +++ b/sim/ucsim/sim.src/stack.cc @@ -25,18 +25,24 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /*@1@*/ +#include + +// 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 */