diff options
-rw-r--r-- | inc/cpu.h | 5 | ||||
-rw-r--r-- | inc/gui.h | 5 | ||||
-rw-r--r-- | src/cpu.c | 22 | ||||
-rw-r--r-- | src/gui.c | 125 | ||||
-rw-r--r-- | src/main.c | 3 |
5 files changed, 115 insertions, 45 deletions
@@ -6,9 +6,10 @@ #include <err.h> struct cpu_interface { - void (*reg_names)(const char *names, int n); + void (*reg_names)(const char *names[], int n); void (*reg_update)(int reg, uint64_t val); - void (*instr_done)(char *instr); + void (*instr_push)(char *instr); + void (*instr_pop)(void); }; enum registers { @@ -9,9 +9,10 @@ struct gui_interface { err (*step_prev)(void); }; -void gui_reg_names(const char *names, int n); +void gui_reg_names(const char *names[], int n); void gui_reg_update(int reg, uint64_t value); -void gui_instr_done(char *instr); +void gui_instr_push(char *instr); +void gui_instr_pop(void); void gui_register_interface(struct gui_interface *gui); void gui_init(void); @@ -104,6 +104,13 @@ static err (*neg_instructions[256])(void); static uint64_t regs[REGISTERS_COUNT] = { 0 }; static struct rip_history *rip_history; +static char instruction_response_factory[256] = { 0 }; + +static const char *register_names[REGISTERS_COUNT] = { + "RAX", "RCX", "RDX", "RBX", "RSP", "RBP", "RSI", "RDI", + "R8", "R9", "R10", "R11", "R12", "R13", "R14", "R15", +}; + static void print_state(void) { logln("rip=%x, rax=%x, rcx=%x, rdx=%x, rbx=%x, rsp=%x, rbp=%x, rsi=%x, rdi=%x,\nr8=%x, r9=%x, r10=%x, r11=%x, r12=%x, r13=%x, r14=%x, r15=%x", @@ -129,6 +136,7 @@ static err pos_opcode(void) uint8_t op = U8(); // TODO: is_*, j* if (op == 0x05) { + sprintf(instruction_response_factory, "syscall"); return linux_call(); } return ERR; @@ -137,7 +145,10 @@ static err pos_opcode(void) static err pos_mov_r32_rm32(void) { uint8_t modrm = U8(); - SET_R32(REG(), GET_RM32()); + uint8_t reg = REG(); + uint32_t val = GET_RM32(); + sprintf(instruction_response_factory, "mov %s, %x", register_names[reg], + val); return OK; } @@ -145,12 +156,16 @@ static err pos_mov_r32_imm32(void) { rip--; uint8_t reg = U8() - 0xb8; - SET_R32(reg, U32()); + uint32_t val = U32(); + SET_R32(reg, val); + sprintf(instruction_response_factory, "mov %s, %#x", + register_names[reg], val); return OK; } static err pos_nop(void) { + sprintf(instruction_response_factory, "nop"); return OK; } @@ -167,6 +182,7 @@ static err pos_int(void) static void initialize(void) { + interface->reg_names(register_names, REGISTERS_COUNT); for (int i = 0; i < 256; i++) { pos_instructions[i] = pos_unknown_instruction; neg_instructions[i] = neg_unknown_instruction; @@ -220,6 +236,7 @@ err cpu_next(void) return END; logln("%x", instr); err ret = pos_instructions[instr](); + interface->instr_push(instruction_response_factory); print_state(); struct rip_history *next = malloc(sizeof(*next)); @@ -239,6 +256,7 @@ err cpu_prev(void) if (!instr) return ERR; err ret = neg_instructions[instr](); + interface->instr_pop(); print_state(); free(rip_history); @@ -9,7 +9,10 @@ enum stepper_response_type { }; static struct gui_interface *interface; +static GtkWindow *main; +static GtkStringList *execution_list; +// TODO: Either beautify or use InfoBar static void error_dialog(GtkWindow *parent, const char *msg) { GtkWidget *dialog = gtk_dialog_new_with_buttons( @@ -24,61 +27,102 @@ static void error_dialog(GtkWindow *parent, const char *msg) gtk_widget_show(dialog); } -static void stepper_response(GtkWidget *widget, enum stepper_response_type type) +static void stepper_handle_response(err ret) { - err ret = OK; - - switch (type) { - case STEP_PREV: - ret = interface->step_prev(); - break; - case STEP_NEXT: - ret = interface->step_next(); - break; - default: - break; - } - if (ret == END || ret == ERR) { - error_dialog(GTK_WINDOW(widget), + error_dialog(main, ret == END ? "Reached end" : "An error occured"); } } -static void init_stepper_dialog(GtkWindow *parent) +static void stepper_next(void) { - GtkWidget *stepper = gtk_dialog_new_with_buttons( - "Stepper", parent, - GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT, "Previous", - 1, "Next", 2, NULL); + stepper_handle_response(interface->step_next()); +} - GtkWidget *content = gtk_dialog_get_content_area(GTK_DIALOG(stepper)); - GtkWidget *label = gtk_label_new("Stepper"); +static void stepper_prev(void) +{ + stepper_handle_response(interface->step_prev()); +} - g_signal_connect_swapped(stepper, "response", - G_CALLBACK(stepper_response), stepper); +static void init_menu(void) +{ + GtkWidget *header = gtk_header_bar_new(); - gtk_box_append(GTK_BOX(content), label); - gtk_widget_show(stepper); + GtkWidget *box = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0); + gtk_widget_add_css_class(box, "linked"); + + GtkWidget *prev = gtk_button_new_from_icon_name("go-previous-symbolic"); + gtk_box_append(GTK_BOX(box), prev); + + GtkWidget *next = gtk_button_new_from_icon_name("go-next-symbolic"); + gtk_box_append(GTK_BOX(box), next); + + g_signal_connect(prev, "clicked", G_CALLBACK(stepper_prev), prev); + g_signal_connect(next, "clicked", G_CALLBACK(stepper_next), next); + + gtk_header_bar_pack_end(GTK_HEADER_BAR(header), box); + gtk_window_set_titlebar(main, header); +} + +static void setup_execution_list(GtkSignalListItemFactory *self, + GtkListItem *item, gpointer data) +{ + (void)self; + (void)data; + GtkWidget *test = gtk_label_new(0); + gtk_label_set_xalign(GTK_LABEL(test), 0); + gtk_list_item_set_child(item, test); } -static void init_execution_window(GtkApplication *app) +static void bind_execution_list(GtkSignalListItemFactory *self, + GtkListItem *item, gpointer data) { - GtkWidget *execution = gtk_application_window_new(app); - gtk_window_set_title(GTK_WINDOW(execution), "Execution"); - gtk_window_set_default_size(GTK_WINDOW(execution), 200, 200); - gtk_widget_show(execution); + (void)self; + (void)data; + GtkWidget *test = gtk_list_item_get_child(item); + GtkStringObject *str = gtk_list_item_get_item(item); + gtk_label_set_text(GTK_LABEL(test), gtk_string_object_get_string(str)); +} - init_stepper_dialog(GTK_WINDOW(execution)); +static GtkWidget *init_execution_list(void) +{ + const char *array[] = { NULL }; + execution_list = gtk_string_list_new((const char *const *)array); + GtkNoSelection *model = + gtk_no_selection_new(G_LIST_MODEL(execution_list)); + + GtkListItemFactory *factory = gtk_signal_list_item_factory_new(); + g_signal_connect(factory, "setup", G_CALLBACK(setup_execution_list), 0); + g_signal_connect(factory, "bind", G_CALLBACK(bind_execution_list), 0); + return gtk_list_view_new(GTK_SELECTION_MODEL(model), factory); +} + +static void init_main_window(GtkApplication *app) +{ + main = GTK_WINDOW(gtk_application_window_new(app)); + gtk_window_set_title(main, "Simsalasim"); + gtk_window_set_default_size(main, 200, 200); + + GtkWidget *paned = gtk_paned_new(GTK_ORIENTATION_HORIZONTAL); + gtk_window_set_child(main, paned); + + GtkWidget *left = init_execution_list(); + gtk_paned_set_start_child(GTK_PANED(paned), left); + + GtkWidget *right = gtk_label_new("end"); + gtk_paned_set_end_child(GTK_PANED(paned), right); } static void activate(GtkApplication *app, gpointer user_data) { (void)user_data; - init_execution_window(app); + init_main_window(app); + init_menu(); + gtk_widget_show(GTK_WIDGET(main)); } -void gui_reg_names(const char *names, int n) +void gui_reg_names(const char *names[], int n) { (void)names; (void)n; @@ -90,9 +134,16 @@ void gui_reg_update(int reg, uint64_t value) (void)value; } -void gui_instr_done(char *instr) +static int execution_list_length = 0; +void gui_instr_push(char *instr) +{ + gtk_string_list_take(execution_list, instr); + execution_list_length++; +} + +void gui_instr_pop(void) { - (void)instr; + gtk_string_list_remove(execution_list, --execution_list_length); } void gui_register_interface(struct gui_interface *gui) @@ -102,8 +153,6 @@ void gui_register_interface(struct gui_interface *gui) void gui_init(void) { - g_object_set(gtk_settings_get_default(), - "gtk-application-prefer-dark-theme", TRUE, NULL); GtkApplication *app = gtk_application_new("de.melvars.simsalasim", G_APPLICATION_DEFAULT_FLAGS); g_signal_connect(app, "activate", G_CALLBACK(activate), NULL); @@ -6,7 +6,8 @@ static struct cpu_interface cpu = { .reg_names = gui_reg_names, .reg_update = gui_reg_update, - .instr_done = gui_instr_done, + .instr_push = gui_instr_push, + .instr_pop = gui_instr_pop, }; static struct gui_interface gui = { |