/* Copyright (C) 2000,2001 Ralf Forsberg This file is part of gpsim. gpsim is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. gpsim is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with gpsim; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include #include "../config.h" #ifdef HAVE_GUI #include #include #include #include #include #include #include "../src/sim_context.h" #include "../src/interface.h" #include "../src/symbol.h" #include "gui.h" #include "gui_stack.h" #include "gui_src.h" struct stack_entry { unsigned int depth; // index in stack array unsigned int retaddress; // last known return address }; #define COLUMNS 2 #define DEPTHCOL 0 #define RETADDRCOL 1 static char *stack_titles[COLUMNS]={"depth", "return address"}; /* */ static gint sigh_button_event(GtkWidget *widget, GdkEventButton *event, Stack_Window *sw) { struct stack_entry *entry; assert(event&&sw); if(!sw->gp || !sw->gp->cpu) return 0; if(event->type==GDK_2BUTTON_PRESS && event->button==1) { int row=sw->current_row; entry = (struct stack_entry*) gtk_clist_get_row_data(GTK_CLIST(sw->stack_clist), row); if(entry) sw->gp->cpu->pma->toggle_break_at_address(entry->retaddress); return 1; } return 0; } static gint stack_list_row_selected(GtkCList *stacklist,gint row, gint column,GdkEvent *event, Stack_Window *sw) { struct stack_entry *entry; GUI_Processor *gp; sw->current_row=row; sw->current_column=column; gp=sw->gp; entry = (struct stack_entry*) gtk_clist_get_row_data(GTK_CLIST(sw->stack_clist), row); if(!entry) return TRUE; sw->gp->source_browser->SelectAddress(entry->retaddress); sw->gp->program_memory->SelectAddress(entry->retaddress); return 0; } static void stack_click_column(GtkCList *clist, int column) { static int last_col=-1; static GtkSortType last_sort_type=GTK_SORT_DESCENDING; if(last_col==-1) last_col=column; if(last_col == column) { if(last_sort_type==GTK_SORT_DESCENDING) { gtk_clist_set_sort_type(clist,GTK_SORT_ASCENDING); last_sort_type=GTK_SORT_ASCENDING; } else { gtk_clist_set_sort_type(clist,GTK_SORT_DESCENDING); last_sort_type=GTK_SORT_DESCENDING; } } gtk_clist_set_sort_column(clist,column); gtk_clist_sort(clist); last_col=column; } static int delete_event(GtkWidget *widget, GdkEvent *event, Stack_Window *sw) { sw->ChangeView(VIEW_HIDE); return TRUE; } // find name of label closest before 'address' and copy found data // into name and offset static int get_closest_label(Stack_Window *sw, int address, char *name, int *offset) { // this function assumes that address symbols are sorted Value *closest_symbol = 0; int minimum_delta=0x2000000; int delta; Symbol_Table &st = CSimulationContext::GetContext()->GetSymbolTable(); Symbol_Table::iterator symIt; Symbol_Table::iterator symItEnd = st.end(); for(symIt=st.begin(); symIt != symItEnd; symIt++) { Value *s = *symIt; if( (typeid(*s) == typeid(address_symbol)) /*|| (typeid(*s) == typeid(line_number_symbol))*/) { int i; s->get(i); delta = abs( i - address); if(delta < minimum_delta) { minimum_delta = delta; closest_symbol = s; } } } if(closest_symbol) { strcpy(name,closest_symbol->name().data()); int i; closest_symbol->get(i); *offset=address-i; return 1; } return 0; } void Stack_Window::Update(void) { int i=0; int nrofentries; //unsigned int pic_id; char depth_string[64]; char retaddress_string[64]; char labelname[64]; int labeloffset; char *entry[COLUMNS]={depth_string,retaddress_string}; unsigned int retaddress; struct stack_entry *stack_entry; if(!gp || !enabled) return; //pic_id = gp->pic_id; pic_processor *pic = dynamic_cast(gp->cpu); if(!pic) return; nrofentries = pic->stack->pointer & pic->stack->stack_mask; if(last_stacklen!=nrofentries) { // stack has changed, update stack clist gtk_clist_freeze (GTK_CLIST (stack_clist)); while(last_stacklen!=nrofentries) { if(last_stacklen>nrofentries) { // Stack has shrunk // remove row 0 stack_entry = (struct stack_entry*) gtk_clist_get_row_data(GTK_CLIST(stack_clist), 0); free(stack_entry); gtk_clist_remove(GTK_CLIST(stack_clist),0); last_stacklen--; } else { // stack has grown strcpy(depth_string,""); retaddress=pic->stack->contents[last_stacklen & pic->stack->stack_mask]; if(get_closest_label(this,retaddress,labelname,&labeloffset)) sprintf(retaddress_string,"0x%04x (%s+%d)",retaddress,labelname,labeloffset); else sprintf(retaddress_string,"0x%04x",retaddress); gtk_clist_insert (GTK_CLIST(stack_clist), 0, entry); // FIXME this memory is never freed? stack_entry = (struct stack_entry*) malloc(sizeof(struct stack_entry)); stack_entry->retaddress=retaddress; stack_entry->depth=i; gtk_clist_set_row_data(GTK_CLIST(stack_clist), 0, (gpointer)stack_entry); last_stacklen++; } } // update depth column for(i=0;i