Search
lxdream.org :: lxdream/src/gui/debug_win.c
lxdream 0.9.1
released Jun 29
Download Now
filename src/gui/debug_win.c
changeset 33:e74b5bc9d14b
prev30:89b30313d757
next35:21a4be098304
author nkeynes
date Mon Dec 26 03:10:41 2005 +0000 (14 years ago)
permissions -rw-r--r--
last change Update inst counter when switching CPUs
view annotate diff log raw
     1 /**
     2  * $Id: debug_win.c,v 1.11 2005-12-26 03:10:41 nkeynes Exp $
     3  * This file is responsible for the main debugger gui frame.
     4  *
     5  * Copyright (c) 2005 Nathan Keynes.
     6  *
     7  * This program is free software; you can redistribute it and/or modify
     8  * it under the terms of the GNU General Public License as published by
     9  * the Free Software Foundation; either version 2 of the License, or
    10  * (at your option) any later version.
    11  *
    12  * This program is distributed in the hope that it will be useful,
    13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
    14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    15  * GNU General Public License for more details.
    16  */
    17 #include <stdlib.h>
    18 #include <stdarg.h>
    19 #include <gnome.h>
    20 #include <math.h>
    21 #include "gui.h"
    22 #include "mem.h"
    23 #include "cpu.h"
    25 GdkColor *msg_colors[] = { &clrError, &clrError, &clrWarn, &clrNormal,
    26                            &clrDebug, &clrTrace };
    28 struct debug_info_struct {
    29     int disasm_from;
    30     int disasm_to;
    31     int disasm_pc;
    32     struct cpu_desc_struct *cpu;
    33     struct cpu_desc_struct **cpu_list;
    34     GtkCList *msgs_list;
    35     GtkCList *regs_list;
    36     GtkCList *disasm_list;
    37     GtkEntry *page_field;
    38     GtkWidget *win;
    39     GtkProgressBar *icounter;
    40     char icounter_text[16];
    41     char saved_regs[0];
    42 };
    44 debug_info_t init_debug_win(GtkWidget *win, const cpu_desc_t *cpu_list )
    45 {
    46     GnomeAppBar *appbar;
    48     debug_info_t data = g_malloc0( sizeof(struct debug_info_struct) + cpu_list[0]->regs_size );
    49     data->disasm_from = -1;
    50     data->disasm_to = -1;
    51     data->disasm_pc = -1;
    52     data->cpu = cpu_list[0];
    53     data->cpu_list = cpu_list;
    55     data->regs_list= gtk_object_get_data(GTK_OBJECT(win), "reg_list");
    56     data->win = win;
    57     gtk_widget_modify_font( GTK_WIDGET(data->regs_list), fixed_list_font );
    58     init_register_list( data );
    59     data->msgs_list = gtk_object_get_data(GTK_OBJECT(win), "output_list");
    60     data->disasm_list = gtk_object_get_data(GTK_OBJECT(win), "disasm_list");
    61     gtk_clist_set_column_width( data->disasm_list, 1, 16 );
    62     data->page_field = gtk_object_get_data(GTK_OBJECT(win), "page_field");
    64     appbar = gtk_object_get_data(GTK_OBJECT(win), "debug_appbar");
    65     data->icounter = gnome_appbar_get_progress( appbar );
    66     gtk_progress_bar_set_text(data->icounter, "1");
    68     gtk_object_set_data( GTK_OBJECT(win), "debug_data", data );
    69     set_disassembly_pc( data, *data->cpu->pc, FALSE );
    70     debug_win_set_running( data, FALSE );
    71     return data;
    72 }
    74 void init_register_list( debug_info_t data ) 
    75 {
    76     int i;
    77     char buf[20];
    78     char *arr[2];
    80     gtk_clist_clear( data->regs_list );
    81     arr[1] = buf;
    82     for( i=0; data->cpu->regs_info[i].name != NULL; i++ ) {
    83         arr[0] = data->cpu->regs_info[i].name;
    84         if( data->cpu->regs_info->type == REG_INT )
    85             sprintf( buf, "%08X", *((uint32_t *)data->cpu->regs_info[i].value) );
    86         else
    87             sprintf( buf, "%f", *((float *)data->cpu->regs_info[i].value) );
    88         gtk_clist_append( data->regs_list, arr );
    89     }
    90 }
    92 /*
    93  * Check for changed registers and update the display
    94  */
    95 void update_registers( debug_info_t data )
    96 {
    97     int i;
    98     for( i=0; data->cpu->regs_info[i].name != NULL; i++ ) {
    99         if( data->cpu->regs_info[i].type == REG_INT ) {
   100             /* Yes this _is_ probably fairly evil */
   101             if( *((uint32_t *)data->cpu->regs_info[i].value) !=
   102                 *((uint32_t *)((char *)data->saved_regs + ((char *)data->cpu->regs_info[i].value - (char *)data->cpu->regs))) ) {
   103                 char buf[20];
   104                 sprintf( buf, "%08X", *((uint32_t *)data->cpu->regs_info[i].value) );
   105                 gtk_clist_set_text( data->regs_list, i, 1, buf );
   106                 gtk_clist_set_foreground( data->regs_list, i, &clrChanged );
   107             } else {
   108                 gtk_clist_set_foreground( data->regs_list, i, &clrNormal );
   109             }
   110         } else {
   111             if( *((float *)data->cpu->regs_info[i].value) !=
   112                 *((float *)((char *)data->saved_regs + ((char *)data->cpu->regs_info[i].value - (char *)data->cpu->regs))) ) {
   113                 char buf[20];
   114                 sprintf( buf, "%f", *((float *)data->cpu->regs_info[i].value) );
   115                 gtk_clist_set_text( data->regs_list, i, 1, buf );
   116                 gtk_clist_set_foreground( data->regs_list, i, &clrChanged );
   117             } else {
   118                 gtk_clist_set_foreground( data->regs_list, i, &clrNormal );
   119             }
   120         }
   121     }
   123     set_disassembly_pc( data, *data->cpu->pc, FALSE );
   124     memcpy( data->saved_regs, data->cpu->regs, data->cpu->regs_size );
   125 }
   127 void update_icount( debug_info_t data )
   128 {
   129     sprintf( data->icounter_text, "%d", *data->cpu->icount );
   130     gtk_progress_bar_set_text( data->icounter, data->icounter_text );
   131 }
   133 void set_disassembly_region( debug_info_t data, unsigned int page )
   134 {
   135     uint32_t i, posn, next;
   136     uint16_t op;
   137     char buf[80];
   138     char addr[10];
   139     char opcode[16] = "";
   140     char *arr[4] = { addr, " ", opcode, buf };
   141     unsigned int from = page & 0xFFFFF000;
   142     unsigned int to = from + 4096;
   144     gtk_clist_clear(data->disasm_list);
   146     sprintf( addr, "%08X", from );
   147     gtk_entry_set_text( data->page_field, addr );
   149     if( !data->cpu->is_valid_page_func( from ) ) {
   150         arr[3] = "This page is currently unmapped";
   151         gtk_clist_append( data->disasm_list, arr );
   152         gtk_clist_set_foreground( data->disasm_list, 0, &clrError );
   153     } else {
   154         for( i=from; i<to; i = next ) {
   155 	    next = data->cpu->disasm_func( i, buf, sizeof(buf), opcode );
   156             sprintf( addr, "%08X", i );
   157             op = sh4_read_phys_word(i);
   158             posn = gtk_clist_append( data->disasm_list, arr );
   159             if( buf[0] == '?' )
   160                 gtk_clist_set_foreground( data->disasm_list, posn, &clrWarn );
   161         }
   162         if( data->disasm_pc != -1 && data->disasm_pc >= from && data->disasm_pc < to )
   163             gtk_clist_set_foreground( data->disasm_list, address_to_row(data, data->disasm_pc),
   164                                       &clrPC );
   165     }
   167     if( page != from ) { /* not a page boundary */
   168         gtk_clist_moveto( data->disasm_list, (page-from)>>1, 0, 0.5, 0.0 );
   169     }
   170     data->disasm_from = from;
   171     data->disasm_to = to;
   172 }
   174 void jump_to_disassembly( debug_info_t data, unsigned int addr, gboolean select )
   175 {
   176     int row;
   178     if( addr < data->disasm_from || addr >= data->disasm_to )
   179         set_disassembly_region(data,addr);
   181     row = address_to_row( data, addr );
   182     if(select) {
   183         gtk_clist_select_row( data->disasm_list, row, 0 );
   184     }
   185     if( gtk_clist_row_is_visible( data->disasm_list, row ) != GTK_VISIBILITY_FULL ){
   186         gtk_clist_moveto( data->disasm_list, row, 0, 0.5, 0.0 );
   187     }
   188 }
   190 void jump_to_pc( debug_info_t data, gboolean select )
   191 {
   192     jump_to_disassembly( data, *data->cpu->pc, select );
   193 }
   195 void set_disassembly_pc( debug_info_t data, unsigned int pc, gboolean select )
   196 {
   197     int row;
   199     jump_to_disassembly( data, pc, select );
   200     if( data->disasm_pc != -1 && data->disasm_pc >= data->disasm_from && 
   201 	data->disasm_pc < data->disasm_to )
   202         gtk_clist_set_foreground( data->disasm_list, 
   203 				  (data->disasm_pc - data->disasm_from) / data->cpu->instr_size,
   204                                   &clrNormal );
   205     row = address_to_row( data, pc );
   206     gtk_clist_set_foreground( data->disasm_list, row, &clrPC );
   207     data->disasm_pc = pc;
   208 }
   210 void set_disassembly_cpu( debug_info_t data, const gchar *cpu )
   211 {
   212     int i;
   213     for( i=0; data->cpu_list[i] != NULL; i++ ) {
   214 	if( strcmp( data->cpu_list[i]->name, cpu ) == 0 ) {
   215 	    if( data->cpu != data->cpu_list[i] ) {
   216 		data->cpu = data->cpu_list[i];
   217 		set_disassembly_pc( data, *data->cpu->pc, FALSE );
   218 		init_register_list( data );
   219 		update_icount( data );
   220 	    }
   221 	    return;
   222 	}
   223     }
   224 }
   226 /**
   227  * Execute a single instruction using the current CPU mode.
   228  */
   229 void debug_win_single_step( debug_info_t data )
   230 {
   231     data->cpu->step_func();
   232     gtk_gui_update();
   233 }
   235 uint32_t row_to_address( debug_info_t data, int row ) {
   236     return data->cpu->instr_size * row + data->disasm_from;
   237 }
   239 int address_to_row( debug_info_t data, uint32_t address ) {
   240     if( data->disasm_from > address || data->disasm_to <= address )
   241 	return -1;
   242     return (address - data->disasm_from) / data->cpu->instr_size;
   243 }
   246 void emit( void *ptr, int level, int source, const char *msg, ... )
   247 {
   248     char buf[20], addr[10] = "", *p;
   249     char *arr[3] = {buf, addr};
   250     int posn;
   251     time_t tm = time(NULL);
   252     va_list ap;
   253     debug_info_t data;
   254     if( ptr == NULL )
   255 	data = main_debug;
   256     else data = (debug_info_t)ptr;
   258     va_start(ap, msg);
   259     p = g_strdup_vprintf( msg, ap );
   260     strftime( buf, sizeof(buf), "%H:%M:%S", localtime(&tm) );
   261     if( source != -1 )
   262         sprintf( addr, "%08X", *data->cpu->pc );
   263     arr[2] = p;
   264     posn = gtk_clist_append(data->msgs_list, arr);
   265     free(p);
   266     va_end(ap);
   268     gtk_clist_set_foreground( data->msgs_list, posn, msg_colors[level] );
   269     gtk_clist_moveto( data->msgs_list, posn, 0, 1.0, 0.0 );
   271     /* emit _really_ slows down the emu, to the point where the gui can be
   272      * completely unresponsive if I don't include this:
   273      */
   274     while( gtk_events_pending() )
   275         gtk_main_iteration();
   276 }
   278 debug_info_t get_debug_info( GtkWidget *widget ) {
   280     GtkWidget *win = gtk_widget_get_toplevel(widget);
   281     debug_info_t data = (debug_info_t)gtk_object_get_data( GTK_OBJECT(win), "debug_data" );
   282     return data;
   283 }
   285 void debug_win_enable_widget( debug_info_t data, const char *name, 
   286 			      gboolean enabled )
   287 {
   288     GtkWidget *widget = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(data->win), name));
   289     gtk_widget_set_sensitive( widget, enabled );
   290 }    
   292 void debug_win_set_running( debug_info_t data, gboolean isRunning ) 
   293 {
   294     debug_win_enable_widget( data, "stop_btn", isRunning );
   295     debug_win_enable_widget( data, "step_btn", !isRunning );
   296     debug_win_enable_widget( data, "run_btn", !isRunning );
   297     debug_win_enable_widget( data, "runto_btn", !isRunning );
   298 }
.