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 10:c898b37506e0
prev9:2784c7660165
next11:0a82ef380c45
author nkeynes
date Sun Dec 11 05:15:36 2005 +0000 (15 years ago)
permissions -rw-r--r--
last change Add CPU disasembly options to mode dropdown
Split sh4/mem.c into core mem.c and sh4/mem.c
Start adding copyright comments to file headers
file annotate diff log raw
nkeynes@10
     1
/**
nkeynes@10
     2
 * $Id: debug_win.c,v 1.4 2005-12-11 05:15:36 nkeynes Exp $
nkeynes@10
     3
 * This file is responsible for the main debugger gui frame.
nkeynes@10
     4
 *
nkeynes@10
     5
 * Copyright (c) 2005 Nathan Keynes.
nkeynes@10
     6
 *
nkeynes@10
     7
 * This program is free software; you can redistribute it and/or modify
nkeynes@10
     8
 * it under the terms of the GNU General Public License as published by
nkeynes@10
     9
 * the Free Software Foundation; either version 2 of the License, or
nkeynes@10
    10
 * (at your option) any later version.
nkeynes@10
    11
 *
nkeynes@10
    12
 * This program is distributed in the hope that it will be useful,
nkeynes@10
    13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
nkeynes@10
    14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
nkeynes@10
    15
 * GNU General Public License for more details.
nkeynes@10
    16
 */
nkeynes@2
    17
#include <stdlib.h>
nkeynes@2
    18
#include <stdarg.h>
nkeynes@2
    19
#include <gnome.h>
nkeynes@2
    20
#include <math.h>
nkeynes@2
    21
#include "gui.h"
nkeynes@2
    22
#include "mem.h"
nkeynes@9
    23
#include "disasm.h"
nkeynes@2
    24
nkeynes@2
    25
GdkColor *msg_colors[] = { &clrError, &clrError, &clrWarn, &clrNormal,
nkeynes@2
    26
                           &clrDebug, &clrTrace };
nkeynes@2
    27
nkeynes@9
    28
struct debug_info_struct {
nkeynes@9
    29
    int disasm_from;
nkeynes@9
    30
    int disasm_to;
nkeynes@9
    31
    int disasm_pc;
nkeynes@9
    32
    struct cpu_desc_struct *cpu;
nkeynes@9
    33
    GtkCList *msgs_list;
nkeynes@9
    34
    GtkCList *regs_list;
nkeynes@9
    35
    GtkCList *disasm_list;
nkeynes@9
    36
    GtkEntry *page_field;
nkeynes@9
    37
    GtkProgressBar *icounter;
nkeynes@9
    38
    char icounter_text[16];
nkeynes@9
    39
    char saved_regs[0];
nkeynes@8
    40
};
nkeynes@8
    41
nkeynes@9
    42
debug_info_t init_debug_win(GtkWidget *win, struct cpu_desc_struct *cpu )
nkeynes@2
    43
{
nkeynes@2
    44
    int i;
nkeynes@2
    45
    char buf[20];
nkeynes@2
    46
    char *arr[2];
nkeynes@2
    47
    GnomeAppBar *appbar;
nkeynes@9
    48
    
nkeynes@9
    49
    debug_info_t data = g_malloc0( sizeof(struct debug_info_struct) + cpu->regs_size );
nkeynes@9
    50
    data->disasm_from = -1;
nkeynes@9
    51
    data->disasm_to = -1;
nkeynes@9
    52
    data->disasm_pc = -1;
nkeynes@9
    53
    data->cpu = cpu;
nkeynes@9
    54
    
nkeynes@9
    55
    data->regs_list= gtk_object_get_data(GTK_OBJECT(win), "reg_list");
nkeynes@9
    56
    arr[1] = buf;
nkeynes@9
    57
    for( i=0; data->cpu->regs_info[i].name != NULL; i++ ) {
nkeynes@9
    58
        arr[0] = data->cpu->regs_info[i].name;
nkeynes@9
    59
        if( data->cpu->regs_info->type == REG_INT )
nkeynes@9
    60
            sprintf( buf, "%08X", *((uint32_t *)data->cpu->regs_info->value) );
nkeynes@9
    61
        else
nkeynes@9
    62
            sprintf( buf, "%f", *((float *)data->cpu->regs_info->value) );
nkeynes@9
    63
        gtk_clist_append( data->regs_list, arr );
nkeynes@9
    64
    }
nkeynes@9
    65
    gtk_widget_modify_font( GTK_WIDGET(data->regs_list), fixed_list_font );
nkeynes@2
    66
nkeynes@9
    67
    data->msgs_list = gtk_object_get_data(GTK_OBJECT(win), "output_list");
nkeynes@9
    68
    data->disasm_list = gtk_object_get_data(GTK_OBJECT(win), "disasm_list");
nkeynes@9
    69
    gtk_clist_set_column_width( data->disasm_list, 1, 16 );
nkeynes@9
    70
    data->page_field = gtk_object_get_data(GTK_OBJECT(win), "page_field");
nkeynes@2
    71
nkeynes@2
    72
    appbar = gtk_object_get_data(GTK_OBJECT(win), "debug_appbar");
nkeynes@9
    73
    data->icounter = gnome_appbar_get_progress( appbar );
nkeynes@9
    74
    gtk_progress_bar_set_text(data->icounter, "1");
nkeynes@10
    75
    
nkeynes@9
    76
    gtk_object_set_data( GTK_OBJECT(win), "debug_data", data );
nkeynes@9
    77
    return data;
nkeynes@2
    78
}
nkeynes@2
    79
nkeynes@2
    80
/*
nkeynes@2
    81
 * Check for changed registers and update the display
nkeynes@2
    82
 */
nkeynes@9
    83
void update_registers( debug_info_t data )
nkeynes@2
    84
{
nkeynes@2
    85
    int i;
nkeynes@9
    86
    for( i=0; data->cpu->regs_info[i].name != NULL; i++ ) {
nkeynes@9
    87
        if( data->cpu->regs_info[i].type == REG_INT ) {
nkeynes@2
    88
            /* Yes this _is_ probably fairly evil */
nkeynes@9
    89
            if( *((uint32_t *)data->cpu->regs_info[i].value) !=
nkeynes@9
    90
                *((uint32_t *)((char *)data->saved_regs + ((char *)data->cpu->regs_info[i].value - (char *)data->cpu->regs))) ) {
nkeynes@2
    91
                char buf[20];
nkeynes@9
    92
                sprintf( buf, "%08X", *((uint32_t *)data->cpu->regs_info[i].value) );
nkeynes@9
    93
                gtk_clist_set_text( data->regs_list, i, 1, buf );
nkeynes@9
    94
                gtk_clist_set_foreground( data->regs_list, i, &clrChanged );
nkeynes@2
    95
            } else {
nkeynes@9
    96
                gtk_clist_set_foreground( data->regs_list, i, &clrNormal );
nkeynes@2
    97
            }
nkeynes@2
    98
        } else {
nkeynes@9
    99
            if( *((float *)data->cpu->regs_info[i].value) !=
nkeynes@9
   100
                *((float *)((char *)data->saved_regs + ((char *)data->cpu->regs_info[i].value - (char *)data->cpu->regs))) ) {
nkeynes@2
   101
                char buf[20];
nkeynes@9
   102
                sprintf( buf, "%f", *((float *)data->cpu->regs_info[i].value) );
nkeynes@9
   103
                gtk_clist_set_text( data->regs_list, i, 1, buf );
nkeynes@9
   104
                gtk_clist_set_foreground( data->regs_list, i, &clrChanged );
nkeynes@2
   105
            } else {
nkeynes@9
   106
                gtk_clist_set_foreground( data->regs_list, i, &clrNormal );
nkeynes@2
   107
            }
nkeynes@2
   108
        }
nkeynes@2
   109
    }
nkeynes@9
   110
nkeynes@9
   111
    set_disassembly_pc( data, *data->cpu->pc, FALSE );
nkeynes@9
   112
    memcpy( data->saved_regs, data->cpu->regs, data->cpu->regs_size );
nkeynes@2
   113
}
nkeynes@2
   114
nkeynes@9
   115
void update_icount( debug_info_t data )
nkeynes@2
   116
{
nkeynes@9
   117
    sprintf( data->icounter_text, "%d", *data->cpu->icount );
nkeynes@9
   118
    gtk_progress_bar_set_text( data->icounter, data->icounter_text );
nkeynes@2
   119
}
nkeynes@2
   120
nkeynes@9
   121
void set_disassembly_region( debug_info_t data, unsigned int page )
nkeynes@2
   122
{
nkeynes@2
   123
    uint32_t i, posn;
nkeynes@2
   124
    uint16_t op;
nkeynes@2
   125
    char buf[80];
nkeynes@2
   126
    char addr[10];
nkeynes@2
   127
    char opcode[6] = "";
nkeynes@2
   128
    char *arr[4] = { addr, " ", opcode, buf };
nkeynes@2
   129
    unsigned int from = page & 0xFFFFF000;
nkeynes@2
   130
    unsigned int to = from + 4096;
nkeynes@2
   131
    
nkeynes@9
   132
    gtk_clist_clear(data->disasm_list);
nkeynes@2
   133
nkeynes@2
   134
    sprintf( addr, "%08X", from );
nkeynes@9
   135
    gtk_entry_set_text( data->page_field, addr );
nkeynes@2
   136
nkeynes@2
   137
    if( !mem_has_page( from ) ) {
nkeynes@2
   138
        arr[3] = "This page is currently unmapped";
nkeynes@9
   139
        gtk_clist_append( data->disasm_list, arr );
nkeynes@9
   140
        gtk_clist_set_foreground( data->disasm_list, 0, &clrError );
nkeynes@2
   141
    } else {
nkeynes@9
   142
        for( i=from; i<to; ) {
nkeynes@9
   143
	    i = data->cpu->disasm_func( i, buf, sizeof(buf) );
nkeynes@2
   144
            sprintf( addr, "%08X", i );
nkeynes@10
   145
            op = sh4_read_phys_word(i);
nkeynes@2
   146
            sprintf( opcode, "%02X %02X", op&0xFF, op>>8 );
nkeynes@9
   147
            posn = gtk_clist_append( data->disasm_list, arr );
nkeynes@2
   148
            if( buf[0] == '?' )
nkeynes@9
   149
                gtk_clist_set_foreground( data->disasm_list, posn, &clrWarn );
nkeynes@2
   150
        }
nkeynes@9
   151
        if( data->disasm_pc != -1 && data->disasm_pc >= from && data->disasm_pc < to )
nkeynes@9
   152
            gtk_clist_set_foreground( data->disasm_list, address_to_row(data, data->disasm_pc),
nkeynes@2
   153
                                      &clrPC );
nkeynes@2
   154
    }
nkeynes@2
   155
nkeynes@2
   156
    if( page != from ) { /* not a page boundary */
nkeynes@9
   157
        gtk_clist_moveto( data->disasm_list, (page-from)>>1, 0, 0.5, 0.0 );
nkeynes@2
   158
    }
nkeynes@9
   159
    data->disasm_from = from;
nkeynes@9
   160
    data->disasm_to = to;
nkeynes@2
   161
}
nkeynes@2
   162
nkeynes@9
   163
void jump_to_disassembly( debug_info_t data, unsigned int addr, gboolean select )
nkeynes@2
   164
{
nkeynes@2
   165
    int row;
nkeynes@2
   166
    
nkeynes@9
   167
    if( addr < data->disasm_from || addr >= data->disasm_to )
nkeynes@9
   168
        set_disassembly_region(data,addr);
nkeynes@2
   169
nkeynes@9
   170
    row = address_to_row( data, addr );
nkeynes@2
   171
    if(select) {
nkeynes@9
   172
        gtk_clist_select_row( data->disasm_list, row, 0 );
nkeynes@2
   173
    }
nkeynes@9
   174
    if( gtk_clist_row_is_visible( data->disasm_list, row ) != GTK_VISIBILITY_FULL ){
nkeynes@9
   175
        gtk_clist_moveto( data->disasm_list, row, 0, 0.5, 0.0 );
nkeynes@2
   176
    }
nkeynes@2
   177
}
nkeynes@2
   178
nkeynes@9
   179
void jump_to_pc( debug_info_t data, gboolean select )
nkeynes@9
   180
{
nkeynes@9
   181
    jump_to_disassembly( data, *data->cpu->pc, select );
nkeynes@9
   182
}
nkeynes@9
   183
nkeynes@9
   184
void set_disassembly_pc( debug_info_t data, unsigned int pc, gboolean select )
nkeynes@2
   185
{
nkeynes@2
   186
    int row;
nkeynes@2
   187
    
nkeynes@9
   188
    jump_to_disassembly( data, pc, select );
nkeynes@9
   189
    if( data->disasm_pc != -1 && data->disasm_pc >= data->disasm_from && 
nkeynes@9
   190
	data->disasm_pc < data->disasm_to )
nkeynes@9
   191
        gtk_clist_set_foreground( data->disasm_list, 
nkeynes@9
   192
				  (data->disasm_pc - data->disasm_from) / data->cpu->instr_size,
nkeynes@2
   193
                                  &clrNormal );
nkeynes@9
   194
    row = address_to_row( data, pc );
nkeynes@9
   195
    gtk_clist_set_foreground( data->disasm_list, row, &clrPC );
nkeynes@9
   196
    data->disasm_pc = pc;
nkeynes@2
   197
}
nkeynes@2
   198
nkeynes@10
   199
void set_disassembly_cpu( debug_info_t data, char *cpu )
nkeynes@10
   200
{
nkeynes@10
   201
nkeynes@10
   202
nkeynes@10
   203
}
nkeynes@10
   204
nkeynes@9
   205
uint32_t row_to_address( debug_info_t data, int row ) {
nkeynes@9
   206
    return data->cpu->instr_size * row + data->disasm_from;
nkeynes@9
   207
}
nkeynes@2
   208
nkeynes@9
   209
int address_to_row( debug_info_t data, uint32_t address ) {
nkeynes@9
   210
    if( data->disasm_from > address || data->disasm_to <= address )
nkeynes@9
   211
	return -1;
nkeynes@9
   212
    return (address - data->disasm_from) / data->cpu->instr_size;
nkeynes@9
   213
}
nkeynes@9
   214
nkeynes@10
   215
nkeynes@9
   216
void emit( void *ptr, int level, int source, char *msg, ... )
nkeynes@2
   217
{
nkeynes@2
   218
    char buf[20], addr[10] = "", *p;
nkeynes@2
   219
    char *arr[3] = {buf, addr};
nkeynes@2
   220
    int posn;
nkeynes@2
   221
    time_t tm = time(NULL);
nkeynes@2
   222
    va_list ap;
nkeynes@9
   223
    debug_info_t data;
nkeynes@9
   224
    if( ptr == NULL )
nkeynes@9
   225
	data = main_debug;
nkeynes@9
   226
    else data = (debug_info_t)ptr;
nkeynes@2
   227
nkeynes@2
   228
    va_start(ap, msg);
nkeynes@2
   229
    p = g_strdup_vprintf( msg, ap );
nkeynes@2
   230
    strftime( buf, sizeof(buf), "%H:%M:%S", localtime(&tm) );
nkeynes@2
   231
    if( source != -1 )
nkeynes@9
   232
        sprintf( addr, "%08X", *data->cpu->pc );
nkeynes@2
   233
    arr[2] = p;
nkeynes@9
   234
    posn = gtk_clist_append(data->msgs_list, arr);
nkeynes@2
   235
    free(p);
nkeynes@2
   236
    va_end(ap);
nkeynes@2
   237
nkeynes@9
   238
    gtk_clist_set_foreground( data->msgs_list, posn, msg_colors[level] );
nkeynes@9
   239
    gtk_clist_moveto( data->msgs_list, posn, 0, 1.0, 0.0 );
nkeynes@2
   240
nkeynes@2
   241
    /* emit _really_ slows down the emu, to the point where the gui can be
nkeynes@2
   242
     * completely unresponsive if I don't include this:
nkeynes@2
   243
     */
nkeynes@2
   244
    while( gtk_events_pending() )
nkeynes@2
   245
        gtk_main_iteration();
nkeynes@2
   246
}
nkeynes@9
   247
nkeynes@9
   248
debug_info_t get_debug_info( GtkWidget *widget ) {
nkeynes@9
   249
    
nkeynes@9
   250
    GtkWidget *win = gtk_widget_get_toplevel(widget);
nkeynes@9
   251
    debug_info_t data = (debug_info_t)gtk_object_get_data( GTK_OBJECT(win), "debug_data" );
nkeynes@9
   252
    return data;
nkeynes@9
   253
}
nkeynes@9
   254
.