From: Hugo Villeneuve Date: Sat, 7 Dec 2013 23:48:25 +0000 (-0500) Subject: Separate cli and gtk sources into separate directories X-Git-Tag: v2.0.0~27 X-Git-Url: http://gitweb.hugovil.com/?a=commitdiff_plain;h=1eb382f72510d50b3636fb88c4bfaf17183672b6;p=emu8051.git Separate cli and gtk sources into separate directories Also added a common directory to hold common files to both interfaces, and compiled into a static library. --- diff --git a/.gitignore b/.gitignore index f8db576..0ec666a 100644 --- a/.gitignore +++ b/.gitignore @@ -11,6 +11,7 @@ /build-aux/install-sh /build-aux/missing /build-aux/test-driver +/build-aux/ar-lib /config.cache /config.log /config.status diff --git a/Makefile.am b/Makefile.am index 0304f0a..df08920 100644 --- a/Makefile.am +++ b/Makefile.am @@ -2,7 +2,7 @@ AUTOMAKE_OPTIONS = gnu -SUBDIRS = src data doc tests +SUBDIRS = src/common src/cli src/gtk data doc tests ## We want these in the dist tarball EXTRA_DIST = autogen.sh \ @@ -20,4 +20,5 @@ MAINTAINERCLEANFILES = Makefile.in aclocal.m4 configure config-h.in \ $(ac_aux_dir)/mkinstalldirs $(ac_aux_dir)/config.guess \ $(ac_aux_dir)/config.sub $(ac_aux_dir)/ltmain.sh \ $(ac_aux_dir)/compile \ - $(ac_aux_dir)/test-driver + $(ac_aux_dir)/test-driver \ + $(ac_aux_dir)/ar-lib diff --git a/configure.ac b/configure.ac index 8b7ed65..d39a607 100644 --- a/configure.ac +++ b/configure.ac @@ -4,7 +4,7 @@ dnl Initialization stuff. AC_INIT([emu8051], [1.1.2], [hugo@hugovil.com], [emu8051], [http://www.hugovil.com/fr/emu8051/]) AC_CONFIG_AUX_DIR([build-aux]) -AC_CONFIG_SRCDIR(src/cpu8051.c) +AC_CONFIG_SRCDIR(src/common/cpu8051.c) AM_CONFIG_HEADER(config.h:config-h.in) dnl Checking if the NEWS file has been updated to reflect the current version. AM_INIT_AUTOMAKE(check-news -Wall std-options color-tests parallel-tests) @@ -13,6 +13,10 @@ AM_SILENT_RULES([yes]) dnl Testing the C compiler. AC_LANG_C +dnl Testing for libtool support. +AC_PROG_RANLIB +AM_PROG_AR + dnl Checking for typedefs, structures, and compiler characteristics. AC_C_CONST AC_TYPE_PID_T @@ -83,4 +87,10 @@ AC_SUBST(LIBS) AC_SUBST(ac_aux_dir) dnl Creating output file(s) -AC_OUTPUT(Makefile src/Makefile data/Makefile doc/Makefile tests/Makefile) +AC_OUTPUT(Makefile + src/common/Makefile + src/cli/Makefile + src/gtk/Makefile + data/Makefile + doc/Makefile + tests/Makefile) diff --git a/src/Makefile.am b/src/Makefile.am deleted file mode 100644 index 1bb89bb..0000000 --- a/src/Makefile.am +++ /dev/null @@ -1,75 +0,0 @@ -# This file is processed by GNU automake to generate Makefile.in - -AM_CPPFLAGS = \ - -I$(top_srcdir) \ - $(GLIB_CFLAGS) - -LDADD = $(GLIB_LIBS) - -bin_PROGRAMS = emu8051-cli -if USE_GTK - bin_PROGRAMS += emu8051-gtk -endif - -# instructions_8051.c must be first, because it and other files -# (instructions_8051.h and disasm.h) are automatically generated by a perl -# script, and other source files include them (the .h). -common_SOURCES = \ - instructions_8051.c \ - options.c options.h \ - log.c log.h \ - app-config.c app-config.h \ - hexfile.c hexfile.h \ - cpu8051.c cpu8051.h \ - memory.c memory.h \ - psw.c psw.h \ - sfr.c sfr.h \ - timers.c timers.h \ - common.h \ - reg8051.h - -emu8051_cli_SOURCES = \ - $(common_SOURCES) \ - emuconsole.c \ - keyboard.c keyboard.h - -if USE_GTK - emu8051_gtk_SOURCES = \ - $(common_SOURCES) \ - emugtk.c emugtk.h \ - memwin.c memwin.h \ - pgmwin.c pgmwin.h \ - regwin.c regwin.h \ - pswwin.c pswwin.h \ - filemenu.c filemenu.h \ - viewmenu.c viewmenu.h \ - helpmenu.c helpmenu.h \ - messagebox.c messagebox.h - - emu8051_gtk_CPPFLAGS = \ - -I$(top_srcdir)/pixmaps \ - $(GTK_CFLAGS) \ - $(AM_CPPFLAGS) - - emu8051_gtk_LDADD = $(GTK_LIBS) -endif - -# These files are generated automatically by a perl script. -instructions_8051.c instructions_8051.h disasm.h : opcode2c.pl opcodes.lst - ./opcode2c.pl - -CLEANFILES = *~ - -DISTCLEANFILES = .deps/*.P - -MAINTAINERCLEANFILES = \ - Makefile.in \ - instructions_8051.c \ - instructions_8051.h \ - disasm.h - -EXTRA_DIST = \ - opcode2c.pl \ - opcodes.lst \ - instructions_8051.h \ - disasm.h diff --git a/src/app-config.c b/src/app-config.c deleted file mode 100644 index 90022f2..0000000 --- a/src/app-config.c +++ /dev/null @@ -1,218 +0,0 @@ -/* - * Handle loading and saving of application configuration settings - * - * Copyright (C) 2013 Hugo Villeneuve - * - * This program 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 of the License, or - * (at your option) any later version. - * - * This program 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 this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#if HAVE_CONFIG_H -# include "config.h" -#endif - -#include -#include -#include -#include -#include - -#if STDC_HEADERS -# include -#elif HAVE_STRINGS_H -# include -#endif - -#include - -#include "common.h" -#include "app-config.h" - -static const char profile_name[] = "default"; -static struct app_config_t app_config; - -struct app_config_t *cfg = &app_config; - -static void -app_config_init(void) -{ - /* Emulation options */ - cfg->clear_ram_on_file_load = false; - - /* UI settings */ - cfg->win_width = 640; - cfg->win_height = 480; - cfg->hpane_pos = 100; - cfg->vpane_pos = 200; - cfg->main_pane_pos = 200; - - /* View menu options */ - cfg->layout = UI_LAYOUT1; - cfg->view_int_memory = 1; - cfg->view_sfr_memory = 1; - cfg->view_ext_memory = 1; - cfg->bits_per_row = 16; /* 8 or 16 */ -} - -static int -app_config_key_file_get_int(GKeyFile *kf, const char *grp, const char *key, int *value) -{ - char *str = g_key_file_get_value(kf, grp, key, NULL); - - log_debug("key: %s", key); - - if (G_LIKELY(str)) { - *value = atoi(str); - log_debug(" value = %d", *value); - g_free(str); - } - - return str != NULL; -} - -static void -app_config_load_from_key_file(GKeyFile *kf) -{ - /* Emulation options */ - app_config_key_file_get_int(kf, "emulation", "clear_ram_on_file_load", - &cfg->clear_ram_on_file_load); - - /* ui */ - app_config_key_file_get_int(kf, "ui", "win_width", &cfg->win_width); - app_config_key_file_get_int(kf, "ui", "win_height", &cfg->win_height); - app_config_key_file_get_int(kf, "ui", "hpane_pos", &cfg->hpane_pos); - app_config_key_file_get_int(kf, "ui", "vpane_pos", &cfg->vpane_pos); - app_config_key_file_get_int(kf, "ui", "main_pane_pos", - &cfg->main_pane_pos); - - /* View */ - app_config_key_file_get_int(kf, "view", "layout", &cfg->layout); - if ((cfg->layout != UI_LAYOUT1) && (cfg->layout != UI_LAYOUT2)) { - log_err("Invalid layout, defaulting to layout 1"); - cfg->layout = UI_LAYOUT1; - } - app_config_key_file_get_int(kf, "view", "int_memory", - &cfg->view_int_memory); - app_config_key_file_get_int(kf, "view", "sfr_memory", - &cfg->view_sfr_memory); - app_config_key_file_get_int(kf, "view", "ext_memory", - &cfg->view_ext_memory); - app_config_key_file_get_int(kf, "view", "bits_per_row", - &cfg->bits_per_row); -} - -static char * -app_config_get_dir_path(void) -{ - char *dir_path; - - dir_path = g_build_filename(g_get_user_config_dir(), PACKAGE, - profile_name, NULL); - - return dir_path; -} - -static char * -app_config_get_file_path(void) -{ - char *file_path; - char *dir_path; - char file[MAX_FILENAME_LENGTH]; - - sprintf(file, "%s.conf", PACKAGE); - - dir_path = app_config_get_dir_path(); - - file_path = g_build_filename(dir_path, file, NULL); - - log_info("app. config file = %s", file_path); - - g_free(dir_path); - - return file_path; -} - -int -app_config_load(void) -{ - char *file_path; - GKeyFile *kf; - - /* Load default values before config file */ - app_config_init(); - - kf = g_key_file_new(); - - file_path = app_config_get_file_path(); - - if (g_key_file_load_from_file(kf, file_path, 0, NULL)) - app_config_load_from_key_file(kf); - - g_free(file_path); - - g_key_file_free(kf); - - /* ??? */ - return 0; -} - -int -app_config_save(void) -{ - char *dir_path; - - dir_path = app_config_get_dir_path(); - - if (g_mkdir_with_parents(dir_path, 0700) != -1) - { - char *file_path; - GString* buf = g_string_sized_new(1024); - - g_string_append(buf, "\n[emulation]\n"); - - g_string_append_printf(buf, "clear_ram_on_file_load=%d\n", - cfg->clear_ram_on_file_load); - - g_string_append(buf, "\n[ui]\n"); - - g_string_append_printf(buf, "win_width=%d\n", cfg->win_width); - g_string_append_printf(buf, "win_height=%d\n", cfg->win_height); - g_string_append_printf(buf, "hpane_pos=%d\n", cfg->hpane_pos); - g_string_append_printf(buf, "vpane_pos=%d\n", cfg->vpane_pos); - g_string_append_printf(buf, "main_pane_pos=%d\n", - cfg->main_pane_pos); - - g_string_append(buf, "\n[view]\n"); - g_string_append_printf(buf, "layout=%d\n", cfg->layout); - g_string_append_printf(buf, "int_memory=%d\n", - cfg->view_int_memory); - g_string_append_printf(buf, "sfr_memory=%d\n", - cfg->view_sfr_memory); - g_string_append_printf(buf, "ext_memory=%d\n", - cfg->view_ext_memory); - g_string_append_printf(buf, "bits_per_row=%d\n", - cfg->bits_per_row); - - file_path = app_config_get_file_path(); - - g_file_set_contents(file_path, buf->str, buf->len, NULL); - g_string_free(buf, TRUE); - g_free(file_path); - } - - g_free(dir_path); - - /* ??? */ - return 0; -} diff --git a/src/app-config.h b/src/app-config.h deleted file mode 100644 index 1c418b5..0000000 --- a/src/app-config.h +++ /dev/null @@ -1,64 +0,0 @@ -/* - * app_config.h - * - * Copyright (C) 1999 Hugo Villeneuve - * - * This program 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 of the License, or - * (at your option) any later version. - * - * This program 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 this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#ifndef APP_CONFIG_H -#define APP_CONFIG_H 1 - -/* - * Layout1: Layout2: - * - * REGS | PROGRAM | | IRAM - * -------------- REGS | PROGRAM | ---- - * IRAM | | XRAM - * -------------- - * XRAM - */ -enum layout_t { - UI_LAYOUT1 = 1, - UI_LAYOUT2, -}; - -struct app_config_t -{ - /* Emulation options */ - int clear_ram_on_file_load; - - /* UI settings */ - int win_width; - int win_height; - int hpane_pos; /* For registers and program windows. */ - int vpane_pos; /* For internal and external memory windows. */ - int main_pane_pos; /* Between hpane and vpane. */ - - /* View menu options */ - int layout; /* UI Layout 1 or 2 */ - int view_int_memory; - int view_sfr_memory; - int view_ext_memory; - int bits_per_row; /* 8 or 16 */ -}; - -int -app_config_load(void); - -int -app_config_save(void); - -#endif /* APP_CONFIG_H */ diff --git a/src/cli/Makefile.am b/src/cli/Makefile.am new file mode 100644 index 0000000..deaae8a --- /dev/null +++ b/src/cli/Makefile.am @@ -0,0 +1,22 @@ +# This file is processed by GNU automake to generate Makefile.in + +AM_CPPFLAGS = \ + -Wall \ + -I@top_srcdir@ \ + -I@top_srcdir@/src/common + +LDADD = \ + $(top_builddir)/src/common/libemu8051.a + +bin_PROGRAMS = emu8051-cli + +emu8051_cli_SOURCES = \ + emuconsole.c \ + keyboard.c keyboard.h + +# we want these in the dist tarball +EXTRA_DIST = + +CLEANFILES = *~ + +MAINTAINERCLEANFILES = Makefile.in diff --git a/src/cli/emuconsole.c b/src/cli/emuconsole.c new file mode 100644 index 0000000..f29146d --- /dev/null +++ b/src/cli/emuconsole.c @@ -0,0 +1,518 @@ +/* + * emuconsole.c + * + * Copyright (C) 1999 Jonathan St-André + * Copyright (C) 1999 Hugo Villeneuve + * + * This program 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 of the License, or + * (at your option) any later version. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#define _GNU_SOURCE /* For getline() */ +#include +#include +#include /* For isblank, toupper() */ +#include "config.h" + +#include "common.h" +#include "cpu8051.h" +#include "reg8051.h" +#include "sfr.h" +#include "memory.h" +#include "options.h" +#include "hexfile.h" +#include "keyboard.h" + +extern struct options_t options; + +/* Capitalize all letters in buffer */ +static void +Capitalize(char *buffer) +{ + int k; + + for (k = 0; k < strlen(buffer); k++) + buffer[k] = toupper(buffer[k]); +} + +/* Remove leading spaces from string in buffer */ +static void +RemoveSpaces(char *buffer) +{ + int k = 0; + + while ((k < strlen(buffer)) && isblank(buffer[k])) + k++; + + if (k != 0) + strcpy(buffer, &buffer[k]); +} + +/* CPU exec and Console UI update */ +static void +console_exec(char *Address, char *NumberInst) +{ + int NbInst = -1; /* -1 is infinity */ + if (strlen(Address) == 0) { + log_err("Invalid address"); + return; + } + + if (!STREQ(Address, "PC")) + cpu8051.pc = Ascii2Hex(Address, strlen(Address)); + + if (NumberInst) + if (strlen(NumberInst) != 0) + NbInst = Ascii2Hex(NumberInst, strlen(NumberInst)); + + InitUnixKB(); + + log_info("Program executing..."); + + do { + cpu8051_Exec(); + if (NbInst > 0) + NbInst--; + } while (!IsBreakpoint(cpu8051.pc) && !IsStoppoint(cpu8051.pc) && + (NbInst != 0) && !kbhit()); + if (kbhit()) { + (void) getch(); /* Flush key */ + log_info("Caught break signal!"); + } + if (NbInst == 0) + log_info("Number of instructions reached! Stopping!"); + if (IsBreakpoint(cpu8051.pc)) + log_info("Breakpoint hit at %.4X! Stopping!", cpu8051.pc); + if (IsStoppoint(cpu8051.pc)) + log_info("Stoppoint hit at %.4X! Stopping!", cpu8051.pc); + + ResetUnixKB(); +} + +/* Disassemble NumberInst instructions at Address */ +static void +DisasmN(unsigned int Address, int NumberInst) +{ + char TextTmp[255]; + int Row; + + for (Row = 0; Row < NumberInst ; Row++) { + Address += cpu8051_Disasm(Address, TextTmp); + printf("%s\n", TextTmp); + + if (Address > 0xFFFF) + return; + } +} + +/* Disassemble 16 instructions at Address */ +static void +Disasm(char *Address, char *NumberInst) +{ + unsigned int MemAddress, NbInst; + + if ((strlen(Address) == 0) || (STREQ(Address, "PC"))) + MemAddress = cpu8051.pc; + else + MemAddress = Ascii2Hex(Address, strlen(Address)); + + if (strlen(NumberInst) == 0) + NumberInst = "10"; + NbInst = Ascii2Hex(NumberInst, strlen(NumberInst)); + DisasmN(MemAddress, NbInst); +} + +/* Set NewValue to Register */ +static void +SetRegister(char *Register, char *NewValue) +{ + if (STREQ(Register, "PC")) + cpu8051.pc = Ascii2Hex(NewValue, 4); + else if (STREQ(Register, "A")) + cpu8051_WriteD(_ACC_, Ascii2Hex(NewValue, 2)); + else if (STREQ(Register, "B")) + cpu8051_WriteD(_B_, Ascii2Hex(NewValue, 2)); + else if (STREQ(Register, "SP")) + cpu8051_WriteD(_SP_, Ascii2Hex(NewValue, 2)); + else { + printf("\nInvalid register name!\n"); + printf("Valid registers are A, B, PC and SP.\n"); + } +} + +/* Show CPU registers, one per line */ +static void +console_dump_sfr_registers_detailed(void) +{ + int k; + + for (k = 0; k < SFR_REGS; k++) { + struct regwin_infos_t *regwin_infos; + int val; + + regwin_infos = sfr_get_infos_from_row(k); + + printf("%s = ", regwin_infos->name); + + val = regwin_read(k); + if (regwin_infos->w == 2) + printf("$%02X", val); + else if (regwin_infos->w == 4) + printf("$%04X", val); + + printf("\n"); + } +} + +/* Show CPU registers, compact format */ +static void +console_dump_sfr_registers_compact(void) +{ + unsigned char PSW = cpu8051_ReadD(_PSW_); + int BankSelect = (PSW & 0x18); + + printf("---------------------------------------------------------------" + "-------\n"); + printf("| PC | SP | DPTR | ACC | B | PSW: CY AC F0 RS1 RS0 OV" + " - P |\n"); + printf("| %.4X | %.2X | %.4X | %.2X | %.2X |", cpu8051.pc, + cpu8051_ReadD(_SP_), + memory_sfr_read_dptr(), + cpu8051_ReadD(_ACC_), cpu8051_ReadD(_B_)); + printf(" %d %d %d %d %d %d %d %d |", + (PSW >> 7) & 1, (PSW >> 6) & 1, (PSW >> 5) & 1, (PSW >> 4) & 1, + (PSW >> 3) & 1, (PSW >> 2) & 1, (PSW >> 1) & 1, PSW & 1); + printf("\n"); + printf("---------------------------------------------------------------" + "-------\n"); + + printf("| TCON | TMOD | IE | IP | R0 | R1 | R2 | R3 | R4 | R5 | R6 | R7" + " | |\n"); + printf("| %.2X | %.2X | %.2X | %.2X ", cpu8051_ReadD(_TCON_), + cpu8051_ReadD(_TMOD_), cpu8051_ReadD(_IE_), cpu8051_ReadD(_IP_)); + printf("| %.2X | %.2X | %.2X | %.2X ", + cpu8051_ReadD(BankSelect + _R0_), + cpu8051_ReadD(BankSelect + _R1_), + cpu8051_ReadD(BankSelect + _R2_), + cpu8051_ReadD(BankSelect + _R3_)); + printf("| %.2X | %.2X | %.2X | %.2X ", + cpu8051_ReadD(BankSelect + _R4_), + cpu8051_ReadD(BankSelect + _R5_), + cpu8051_ReadD(BankSelect + _R6_), + cpu8051_ReadD(BankSelect + _R7_)); + printf("| |\n"); + printf("---------------------------------------------------------------" + "-------\n"); +} + +/* Show CPU registers */ +static void +console_show_registers(void) +{ + if (options.stop_address != 0) + console_dump_sfr_registers_detailed(); + else + console_dump_sfr_registers_compact(); +} + +/* CPU reset and Console UI update */ +static void +console_reset(void) +{ + log_info("Resetting..."); + cpu8051_Reset(); + log_info("Done"); +} + +/* CPU trace and Console UI update */ +static void +console_trace(char *Address) +{ + if (strlen(Address) != 0) + cpu8051.pc = Ascii2Hex(Address, strlen(Address)); + cpu8051_Exec(); + console_show_registers(); + DisasmN(cpu8051.pc, 1); +} + +/* EmuConsole main loop */ +static void +console_main(void) +{ + unsigned int Index; + char *line = NULL; + int QuitRequest = 0; + char prompt[] = "-> "; + + char *Title[] = { " *******************", + " * 8051 Emulator *", + " *******************", + "", 0 }; + + char *Menu[] = { + " Available commands, [ ] = options", + "", + " Set Breakpoint.............. SB [address]", + " Remove Breakpoint........... RB [address]", + " Display Breakpoint(s)....... DB", + " Dump External Data Memory... DE [address] [size]", + " Dump Internal Data Memory... DI [address] [size]", + " Dump Program Memory......... DP [address] [size]", + " Display Registers content... DR", + " Execute..................... EM [address" + " [number of instructions]]", + " Help........................ H or ?", + " Modify External Data Memory. ME address value", + " Modify Internal Data Memory. MI address value", + " Modify Program Memory....... MP address value", + " Modify Register............. MR register value", + " Quit Emulator............... Q", + " Trace mode.................. T [address]", + " Unassemble.................. U [address]" + " [number of instructions]", + " Reset processor............. Z", 0 }; + + console_reset(); + + if (options.stop_address != 0) { + /* Automatically run program and stop at specified address. */ + console_exec("0x0000", NULL); + console_show_registers(); + QuitRequest = 1; + } else { + Index = 0; + while (Title[Index] != 0) + printf("%s\n", Title[Index++]); + + Index = 0; + while (Menu[Index] != 0) + printf("%s\n", Menu[Index++]); + + console_show_registers(); + } + + while (!QuitRequest) { + int slen; + size_t len = 0; + char Command[256]; + char Args[256]; + char Parameter1[256]; + char Parameter2[256]; + + Parameter1[0] = '\0'; + Parameter2[0] = '\0'; + + printf(prompt); + (void) getline(&line, &len, stdin); + Capitalize(line); + RemoveSpaces(line); + + /* Strip trailing newline */ + slen = strlen(line); + if (line[slen - 1] == '\n') + line[slen - 1] = '\0'; + + /* Find command-arguments delimiter */ + for (Index = 0; Index < strlen(line); Index++) { + if (isblank(line[Index])) + break; + } + + /* Keep only the Command part from the input line */ + memcpy(Command, &line[0], Index); + Command[Index] = '\0'; + + /* Keep only the arguments part from the input line */ + if (Index < strlen(line)) { + slen = strlen(line) - Index; + memcpy(Args, &line[Index + 1], slen); + } else { + slen = 0; + } + Args[slen] = '\0'; + RemoveSpaces(Args); + + /* Find multi-arguments delimiter */ + for (Index = 0; Index < strlen(Args); Index++) { + if (isblank(Args[Index])) + break; + } + + memcpy(Parameter1, &Args[0], Index); + Parameter1[Index] = '\0'; + + if (Index < strlen(Args)) { + slen = strlen(Args) - Index; + memcpy(Parameter2, &Args[Index + 1], slen); + } else { + slen = 0; + } + Parameter2[slen] = '\0'; + RemoveSpaces(Parameter2); + + if (strlen(Command) == 0) { + goto syntax_error; + continue; + } + + if ((strlen(Parameter1) > 4) || (strlen(Parameter2) > 4)) { + printf("Invalid Parameter Format!\n"); + continue; + } + + switch (Command[0]) { + case 'D': + if (STREQ(Command, "DB") && + (strlen(Parameter1) == 0)) + ShowBreakpoints(); + else if (STREQ(Command, "DE")) + DumpMem(Parameter1, Parameter2, EXT_MEM_ID); + else if (STREQ(Command, "DI")) + DumpMem(Parameter1, Parameter2, INT_MEM_ID); + else if (STREQ(Command, "DP")) { + if ((strlen(Parameter1) == 0)) + strcpy(Parameter1, "PC"); + DumpMem(Parameter1, Parameter2, PGM_MEM_ID); + } else if (STREQ(Command, "DR") && + (strlen(Parameter1) == 0)) + console_show_registers(); + else + goto syntax_error; + break; + case 'E': + if (STREQ(Command, "EM")) + console_exec(Parameter1, Parameter2); + else + goto syntax_error; + break; + case 'H': + case '?': + if ((STREQ(Command, "H") || STREQ(Command, "?")) && + (strlen(Parameter1) == 0) && + (strlen(Parameter2) == 0)) { + Index = 0; + while (Menu[Index] != 0) + printf("%s\n", Menu[Index++]); + } else + goto syntax_error; + break; + case 'M': + if ((strlen(Parameter1) == 0) || + (strlen(Parameter2) == 0)) + printf("Missing Parameter!\n"); + else if (STREQ(Command, "ME")) { + unsigned int adresse = Ascii2Hex(Parameter1, 4); + unsigned char valeur = Ascii2Hex(Parameter2, 2); + memory_write8(EXT_MEM_ID, adresse, valeur); + } else if (STREQ(Command, "MI")) { + unsigned int adresse = Ascii2Hex(Parameter1, 2); + unsigned char valeur = Ascii2Hex(Parameter2, 2); + memory_write8(INT_MEM_ID, adresse, valeur); + } else if (STREQ(Command, "MP")) { + unsigned int adresse = Ascii2Hex(Parameter1, 4); + unsigned char valeur = Ascii2Hex(Parameter2, 2); + memory_write8(PGM_MEM_ID, adresse, valeur); + } else if (STREQ(Command, "MR")) + SetRegister(Parameter1, Parameter2); + else + goto syntax_error; + break; + case 'Q': + if (STREQ(Command, "Q") && (strlen(Parameter1) == 0) && + (strlen(Parameter2) == 0)) + QuitRequest = 1; + else + goto syntax_error; + break; + case 'R': + if (strlen(Parameter2) != 0) + goto TooMuchParameters; + if (STREQ(Command, "RB")) { + if (strlen(Parameter1) == 0) + ClearBreakpoint(cpu8051.pc); + else + ClearBreakpoint( + Ascii2Hex(Parameter1, 4)); + } else + goto syntax_error; + break; + case 'S': + if (strlen(Parameter2) != 0) + goto TooMuchParameters; + + if (STREQ(Command, "SB")) { + if (strlen(Parameter1) == 0) + SetBreakpoint(cpu8051.pc); + else + SetBreakpoint(Ascii2Hex(Parameter1, 4)); + } else + goto syntax_error; + break; + case 'T': + if (strlen(Parameter2) != 0) + printf("Wrong Number of Parameters!\n"); + + if (STREQ(Command, "T")) + console_trace(Parameter1); + else + goto syntax_error; + break; + case 'U': + if (STREQ(Command, "U")) + Disasm(Parameter1, Parameter2); + else + goto syntax_error; + break; + case 'Z': + if (STREQ(Command, "Z") && (strlen(Parameter1) == 0) && + (strlen(Parameter2) == 0)) + cpu8051_Reset(); + else + goto syntax_error; + break; + case '\n': + break; + default: + goto syntax_error; + } + continue; + +syntax_error: + printf("Syntax Error!\n"); + continue; +TooMuchParameters: + printf("Wrong Number of Parameters!\n"); + continue; + } + + if (line) + free(line); +} + +int +main(int argc, char **argv) +{ + parse_command_line_options(argc, argv); + + cpu8051_init(); + + if (options.filename != NULL) + LoadHexFile(options.filename); + + console_main(); + + log_info("Terminate"); + + return 0; +} diff --git a/src/cli/keyboard.c b/src/cli/keyboard.c new file mode 100644 index 0000000..654087e --- /dev/null +++ b/src/cli/keyboard.c @@ -0,0 +1,77 @@ +/* + * keyboard.c + * + * Copyright (C) 1999 Jonathan St-André + * Copyright (C) 1999 Hugo Villeneuve + * + * This program 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 of the License, or + * (at your option) any later version. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include +#include + +static struct termios orig, newtio; +static int peek = -1; + +int +kbhit(void) +{ + char ch; + int nread; + if (peek != -1) + return 1; + newtio.c_cc[VMIN] = 0; + tcsetattr(0, TCSANOW, &newtio); + nread = read(0, &ch, 1); + newtio.c_cc[VMIN] = 1; + tcsetattr(0, TCSANOW, &newtio); + if (nread == 1) { + peek = ch; + return 1; + } + return 0; +} + +int +getch(void) +{ + char ch; + if (peek != -1) { + ch = peek; + peek = -1; + return ch; + } + read(0, &ch, 1); + return ch; +} + +void +InitUnixKB(void) +{ + tcgetattr(0, &orig); + newtio = orig; + newtio.c_lflag &= ~ICANON; + newtio.c_lflag &= ~ECHO; + newtio.c_lflag &= ~ISIG; + newtio.c_cc[VMIN] = 1; + newtio.c_cc[VTIME] = 0; + tcsetattr(0, TCSANOW, &newtio); +} + +void +ResetUnixKB(void) +{ + tcsetattr(0, TCSANOW, &orig); +} diff --git a/src/cli/keyboard.h b/src/cli/keyboard.h new file mode 100644 index 0000000..8660616 --- /dev/null +++ b/src/cli/keyboard.h @@ -0,0 +1,37 @@ +/* + * keyboard.h + * + * Copyright (C) 1999 Jonathan St-André + * Copyright (C) 1999 Hugo Villeneuve + * + * This program 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 of the License, or + * (at your option) any later version. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _KEYBOARD_H_ +#define _KEYBOARD_H_ + +int +kbhit(void); + +int +getch(void); + +void +InitUnixKB(void); + +void +ResetUnixKB(void); + +#endif /* _KEYBOARD_H_ */ diff --git a/src/common.h b/src/common.h deleted file mode 100644 index 0058a01..0000000 --- a/src/common.h +++ /dev/null @@ -1,60 +0,0 @@ -/* - * common.h - * - * Copyright (C) 1999 Jonathan St-André - * Copyright (C) 1999 Hugo Villeneuve - * - * This program 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 of the License, or - * (at your option) any later version. - * - * This program 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 this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#ifndef COMMON_H -#define COMMON_H 1 - -#include -#include -#include - -#if STDC_HEADERS -# include -#elif HAVE_STRINGS_H -# include -#endif - -#include "log.h" - -#define FIXED_FONT "monospace 12" - -#define MAX_FILENAME_LENGTH 1024 - -/* Common constants. */ -#ifndef EXIT_SUCCESS -# define EXIT_SUCCESS 0 -# define EXIT_FAILURE 1 -#endif - -/* Returns TRUE if the strings 'a' and 'b' are equal. */ -#define STREQ(a, b) (strcasecmp((a), (b)) == 0) - -/* Returns TRUE if the first 'c' characters of strings 'a' and 'b' are equal. */ -#define STREQ_LEN(a, b, c) (strncasecmp((a), (b), (c)) == 0) - - -inline void -ErrorLocation(const char *file, int line); - -void * -xmalloc(size_t size, const char *filename, int line_number); - -#endif /* COMMON_H */ diff --git a/src/common/Makefile.am b/src/common/Makefile.am new file mode 100644 index 0000000..2d0df82 --- /dev/null +++ b/src/common/Makefile.am @@ -0,0 +1,38 @@ +# This file is processed by GNU automake to generate Makefile.in + +AM_CPPFLAGS = \ + -Wall \ + -I$(top_srcdir) + +noinst_LIBRARIES = libemu8051.a + +libemu8051_a_SOURCES = \ + instructions_8051.c \ + options.c options.h \ + log.c log.h \ + hexfile.c hexfile.h \ + cpu8051.c cpu8051.h \ + memory.c memory.h \ + psw.c psw.h \ + sfr.c sfr.h \ + timers.c timers.h \ + common.h \ + reg8051.h + +# These files are generated automatically by a perl script. +instructions_8051.c instructions_8051.h disasm.h : opcode2c.pl opcodes.lst + ./opcode2c.pl + +CLEANFILES = *~ + +MAINTAINERCLEANFILES = \ + Makefile.in \ + instructions_8051.c \ + instructions_8051.h \ + disasm.h + +EXTRA_DIST = \ + opcode2c.pl \ + opcodes.lst \ + instructions_8051.h \ + disasm.h diff --git a/src/common/common.h b/src/common/common.h new file mode 100644 index 0000000..0058a01 --- /dev/null +++ b/src/common/common.h @@ -0,0 +1,60 @@ +/* + * common.h + * + * Copyright (C) 1999 Jonathan St-André + * Copyright (C) 1999 Hugo Villeneuve + * + * This program 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 of the License, or + * (at your option) any later version. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef COMMON_H +#define COMMON_H 1 + +#include +#include +#include + +#if STDC_HEADERS +# include +#elif HAVE_STRINGS_H +# include +#endif + +#include "log.h" + +#define FIXED_FONT "monospace 12" + +#define MAX_FILENAME_LENGTH 1024 + +/* Common constants. */ +#ifndef EXIT_SUCCESS +# define EXIT_SUCCESS 0 +# define EXIT_FAILURE 1 +#endif + +/* Returns TRUE if the strings 'a' and 'b' are equal. */ +#define STREQ(a, b) (strcasecmp((a), (b)) == 0) + +/* Returns TRUE if the first 'c' characters of strings 'a' and 'b' are equal. */ +#define STREQ_LEN(a, b, c) (strncasecmp((a), (b), (c)) == 0) + + +inline void +ErrorLocation(const char *file, int line); + +void * +xmalloc(size_t size, const char *filename, int line_number); + +#endif /* COMMON_H */ diff --git a/src/common/cpu8051.c b/src/common/cpu8051.c new file mode 100644 index 0000000..bf7bd99 --- /dev/null +++ b/src/common/cpu8051.c @@ -0,0 +1,651 @@ +/* + * cpu8051.c + * + * Copyright (C) 1999 Jonathan St-André + * Copyright (C) 1999 Hugo Villeneuve + * + * This program 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 of the License, or + * (at your option) any later version. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/* Define only here, for not having extern scope on local variables. */ +#define CPU8051_M 1 + +#include +#include + +#include "reg8051.h" +#include "cpu8051.h" +#include "memory.h" +#include "psw.h" +#include "timers.h" +#include "disasm.h" +#include "options.h" +#include "instructions_8051.h" + +extern struct options_t options; + +/* Check if the address is a breakpoint */ +int +IsBreakpoint(unsigned int address) +{ + int k; + + for (k = 0; k < cpu8051.bp_count; k++) { + if (cpu8051.bp[k] == address) + return 1; + } + + /* The address was not found in the list of breakpoints */ + return 0; +} + +/* Check if the address is a stop point */ +int +IsStoppoint(unsigned int address) +{ + if ((options.stop_address != 0) && (options.stop_address == address)) + return 1; + else + return 0; +} + +/* Show Breakpoints list */ +void +ShowBreakpoints(void) +{ + int k; + + for (k = 0; k < cpu8051.bp_count; k++) + printf("Breakpoint at address = %.4X\n", cpu8051.bp[k]); +} + +/* Set Breakpoint at address at the end of the breakpoint list */ +void +SetBreakpoint(unsigned int address) +{ + if (IsBreakpoint(address)) + return; /* Already a breakpoint */ + + if (cpu8051.bp_count < MAXBP) + cpu8051.bp[cpu8051.bp_count++] = address; +} + +/* Clear Breakpoint at Address from list */ +void +ClearBreakpoint(unsigned int address) +{ + int k; + + for (k = 0; k < cpu8051.bp_count; k++) { + if (cpu8051.bp[k] == address) { + /* Fill removed breakpoint slot with last entry */ + cpu8051.bp[k] = cpu8051.bp[cpu8051.bp_count - 1]; + cpu8051.bp_count--; + } + } +} + +/* Toggle the breakpoint at Address. */ +void +ToggleBreakpoint(unsigned int address) +{ + if (IsBreakpoint(address)) + ClearBreakpoint(address); + else + SetBreakpoint(address); +} + +void +cpu8051_init(void) +{ + memory_init(); + + cpu8051.pc = 0; + cpu8051.clock = 0; + cpu8051.active_priority = -1; + cpu8051.bp_count = 0; +} + +/* Reset the registers and CPU state */ +void +cpu8051_Reset(void) +{ + cpu8051.pc = 0; + cpu8051.clock = 0; + cpu8051.active_priority = -1; + + /* Clear IRAM and SFR. */ + memory_clear(INT_MEM_ID); + + memory_sfr_write8(_P0_, 0xFF); + memory_sfr_write8(_P1_, 0xFF); + memory_sfr_write8(_P2_, 0xFF); + memory_sfr_write8(_P3_, 0xFF); + + /* The default value of SP (after system reset) is 07 */ + memory_sfr_write8(_SP_, 0x07); +} + +static void +cpu8051_convert_bit_address(uint8_t bit_address, uint8_t *byte_address, + uint8_t *bit_number) +{ + if (bit_address > 0x7F) { + /* SFR 80-FF */ + *byte_address = bit_address & 0xF8; + *bit_number = bit_address & 0x07; + } else { + /* 20-2F */ + *byte_address = (bit_address >> 3) + 0x20; + *bit_number = bit_address & 0x07; + } +} + +/* Write with a direct addressing mode at Address the new Value */ +void +cpu8051_WriteD(unsigned int Address, unsigned char Value) +{ + memory_write8(INT_MEM_ID, Address, Value); +} + +/* Write with an indirect addressing mode at Address the new Value */ +void +cpu8051_WriteI(unsigned int Address, unsigned char Value) +{ + if (Address > 0x7F) { + memory_write8(EXT_MEM_ID, Address, Value); + return; + } + + memory_write8(INT_MEM_ID, Address, Value); +} + +/* Write with a bit addressing mode at BitAddress the new Value */ +void +cpu8051_WriteB(uint8_t bit_address, uint8_t value) +{ + uint8_t byte_address; + uint8_t bit_number; + unsigned char ByteValue, ByteMask; + + cpu8051_convert_bit_address(bit_address, &byte_address, &bit_number); + + ByteMask = ((1 << bit_number) ^ 0xFF); + ByteValue = cpu8051_ReadD(byte_address) & ByteMask; + ByteValue += value << bit_number; + cpu8051_WriteD(byte_address, ByteValue); +} + +/* Read with a direct addressing mode at Address */ +unsigned char +cpu8051_ReadD(unsigned int Address) +{ + if (Address > 0xFF) + return memory_read8(EXT_MEM_ID, Address); + else + return memory_read8(INT_MEM_ID, Address); +} + +/* Read with a indirect addressing mode at Address */ +unsigned char +cpu8051_ReadI(unsigned int Address) +{ + if (Address > 0x7F) + return memory_read8(EXT_MEM_ID, Address); + else + return memory_read8(INT_MEM_ID, Address); +} + +/* Read with a bit addressing mode at BitAddress */ +unsigned char +cpu8051_ReadB(uint8_t bit_address) +{ + uint8_t byte_address; + uint8_t bit_number; + unsigned char BitValue; + + cpu8051_convert_bit_address(bit_address, &byte_address, &bit_number); + + BitValue = (cpu8051_ReadD(byte_address) >> bit_number); + BitValue &= 1; + return BitValue; +} + +static int +cpu8051_interrupt_fire(int interrupt_no, int priority) +{ + if (cpu8051_ReadD(_IP_) & INTERRUPT_MASK(interrupt_no)) + return priority; + else + return !priority; +} + +static int +cpu8051_interrupt_enabled(int interrupt_no) +{ + return (cpu8051_ReadD(_IE_) & INTERRUPT_MASK(interrupt_no)) ? 1 : 0; +} + +static void +cpu8051_process_interrupt(int pc, int pri) +{ + stack_push16(cpu8051.pc); + cpu8051.pc = pc; + cpu8051.active_priority = pri; +} + + +/* Check interrupts state and process them as needed */ +static void +cpu8051_CheckInterrupts(void) +{ + int i; + + if ((cpu8051_ReadD(_IE_) & 0x80) == 0) + return; + + for (i = INTERRUPT_PRIORITY_HIGH; i >= INTERRUPT_PRIORITY_LOW; i--) { + if (cpu8051.active_priority < i) { + /* Interrupt timer 0 */ + if (cpu8051_interrupt_enabled(INTERRUPT_1) && + cpu8051_interrupt_fire(INTERRUPT_1, i) && + (cpu8051_ReadD(_TCON_) & 0x20)) { + cpu8051_WriteD(_TCON_, + cpu8051_ReadD(_TCON_) & 0xDF); + cpu8051_process_interrupt(0x0B, i); + return; + } + /* Interrupt timer 1 */ + if (cpu8051_interrupt_enabled(INTERRUPT_3) && + cpu8051_interrupt_fire(INTERRUPT_3, i) && + (cpu8051_ReadD(_TCON_) & 0x80)) { + cpu8051_WriteD(_TCON_, + cpu8051_ReadD(_TCON_) & 0x7F); + cpu8051_process_interrupt(0x1B, i); + return; + } + /* Serial Interrupts */ + if (cpu8051_interrupt_enabled(INTERRUPT_4) && + cpu8051_interrupt_fire(INTERRUPT_4, i) && + (cpu8051_ReadD(_SCON_) & 0x03)) { + cpu8051_process_interrupt(0x23, i); + return; + } + /* Interrupt timer 2 */ + if (cpu8051_interrupt_enabled(INTERRUPT_5) && + cpu8051_interrupt_fire(INTERRUPT_5, i) && + (cpu8051_ReadD(_T2CON_) & 0x80)) { + cpu8051_process_interrupt(0x2B, i); + return; + } + } + } +} + +/* Execute at address cpu8051.pc from PGMMem */ +void +cpu8051_Exec(void) +{ + int i; + unsigned char opcode; + int insttiming; + + opcode = memory_read8(PGM_MEM_ID, cpu8051.pc); + cpu8051.pc++; + insttiming = (*opcode_table[opcode])(); /* Function callback. */ + + /* + * Parity bit (p): is automatically set or cleared in each machine + * cycle to establish even parity in the accumulator. + */ + psw_compute_parity_bit(); + + for (i = 0; i < insttiming; i++) { + cpu8051_CheckInterrupts(); + timers_check(); + cpu8051.clock++; + } +} + +/* + * Addressing modes defined in the order as they appear in disasm.h + * from table argstext[] + */ +#define ADDR11 0 +#define ADDR16 1 +#define DIRECT 3 +#define BITADDR 14 +#define RELADDR 15 +#define DATAIMM 16 +#define DATA16 22 +#define CBITADDR 23 + +/* + * SFR Memory map [80h - FFh] + * --------------------------------------------------------------- + * F8 | | | | | | | | | FF + * F0 | B | | | | | | | | F7 + * E8 | | | | | | | | | EF + * E0 | ACC | | | | | | | | E7 + * D8 | | | | | | | | | DF + * D0 | PSW | | | | | | | | D7 + * C8 | T2CON| |RCAP2L|RCAP2H| TL2 | TH2 | | | CF + * C0 | | | | | | | | | C7 + * B8 | IP | | | | | | | | BF + * B0 | P3 | | | | | | | | B7 + * A8 | IE | | | | | | | | AF + * A0 | P2 | | | | | | | | A7 + * 98 | SCON | SBUF | | | | | | | 9F + * 90 | P1 | | | | | | | | 97 + * 88 | TCON | TMOD | TL0 | TL1 | TH0 | TH1 | | | 8F + * 80 | P0 | SP | DPL | DPH | | | | PCON | 87 + * --------------------------------------------------------------- + */ + +/* Return as Text the name of the SFR register at Address if any */ +static int +cpu8051_SFRMemInfo(unsigned int Address, char *Text) +{ + switch (Address) { + case 0x80: return sprintf(Text, "P0"); + case 0x81: return sprintf(Text, "SP"); + case 0x82: return sprintf(Text, "DPL"); + case 0x83: return sprintf(Text, "DPH"); + case 0x87: return sprintf(Text, "PCON"); + case 0x88: return sprintf(Text, "TCON"); + case 0x89: return sprintf(Text, "TMOD"); + case 0x8A: return sprintf(Text, "TL0"); + case 0x8B: return sprintf(Text, "TL1"); + case 0x8C: return sprintf(Text, "TH0"); + case 0x8D: return sprintf(Text, "TH1"); + case 0x90: return sprintf(Text, "P1"); + case 0x98: return sprintf(Text, "SCON"); + case 0x99: return sprintf(Text, "SBUF"); + case 0xA0: return sprintf(Text, "P2"); + case 0xA8: return sprintf(Text, "IE"); + case 0xB0: return sprintf(Text, "P3"); + case 0xB8: return sprintf(Text, "IP"); + case 0xC8: return sprintf(Text, "T2CON"); + case 0xCA: return sprintf(Text, "RCAP2L"); + case 0xCB: return sprintf(Text, "RCAP2H"); + case 0xCC: return sprintf(Text, "TL2"); + case 0xCD: return sprintf(Text, "TH2"); + case 0xD0: return sprintf(Text, "PSW"); + case 0xE0: return sprintf(Text, "ACC"); + case 0xF0: return sprintf(Text, "B"); + default: return sprintf(Text, "%.2XH", Address); + } +} + +/* Return as Text the decoded BitAddress */ +static void +cpu8051_IntMemBitInfo(uint8_t bit_address, char *text) +{ + uint8_t byte_address; + uint8_t bit_number; + int len; + + cpu8051_convert_bit_address(bit_address, &byte_address, &bit_number); + + len = cpu8051_SFRMemInfo(byte_address, text); + sprintf(&text[len], ".%X", bit_address); +} + +/* Get instruction size from opcode */ +int +cpu8051_get_instruction_size(unsigned char opcode) +{ + return InstSizesTbl[opcode]; +} + +/* Display instruction mnemonic. */ +void +cpu8051_disasm_mnemonic(unsigned char OpCode, char *buf) +{ + sprintf(buf, "%s", InstTextTbl[InstTypesTbl[OpCode]]); +} + +/* Disasm instruction arguments starting at address into a text string */ +void +cpu8051_disasm_args(unsigned int address, char *buf) +{ + int len = 0; + char TextTmp[20]; + unsigned char OpCode; + int ArgTblOfs; + int i; + + OpCode = memory_read8(PGM_MEM_ID, address); + ArgTblOfs = OpCode << 2; + address++; + + /* + * MOV direct, direct (OpCode 85h) is peculiar, the operands + * are inverted + */ + if (OpCode == 0x85) { + cpu8051_SFRMemInfo(memory_read8(PGM_MEM_ID, address + 1), + TextTmp); + len += sprintf(&buf[len], "%s,", TextTmp); + cpu8051_SFRMemInfo(memory_read8(PGM_MEM_ID, address), + TextTmp); + len += sprintf(&buf[len], "%s", TextTmp); + address += 2; + return; + } + + for (i = 1; i <= InstArgTbl[ArgTblOfs]; i++) { + switch (InstArgTbl[ArgTblOfs + i]) { + case ADDR11: { + len += sprintf(&buf[len], + "%.4XH", ((OpCode << 3) & 0xF00) + + (memory_read8(PGM_MEM_ID, address))); + address++; + break; + } + case ADDR16: { + len += sprintf( + &buf[len], "%.4XH", + ((memory_read8(PGM_MEM_ID, address) << 8) + + memory_read8(PGM_MEM_ID, address + 1))); + address += 2; + break; + } + case DIRECT: { + cpu8051_SFRMemInfo(memory_read8(PGM_MEM_ID, address), + TextTmp); + len += sprintf(&buf[len], "%s", TextTmp); + address++; + break; + } + case BITADDR: { + cpu8051_IntMemBitInfo( + (memory_read8(PGM_MEM_ID, address) & 0xF8), + TextTmp); + len += sprintf(&buf[len], "%s.%X" , TextTmp, + (memory_read8(PGM_MEM_ID, address) & 7)); + address++; + break; + } + case RELADDR: { + address++; + len += sprintf(&buf[len], "%.4XH", (address & 0xFF00) + + (((address & 0xFF) + + memory_read8(PGM_MEM_ID, + address - 1)) & 0xFF)); + break; + } + case DATAIMM: { + len += sprintf(&buf[len], "#%.2XH", + memory_read8(PGM_MEM_ID, address)); + address++; + break; + } + case DATA16: { + len += sprintf(&buf[len], "#%.4XH", + ((memory_read8(PGM_MEM_ID, + address) << 8) + + memory_read8(PGM_MEM_ID, address+1))); + address += 2; + break; + } + case CBITADDR: { + cpu8051_IntMemBitInfo((memory_read8(PGM_MEM_ID, + address) & 0xF8), + TextTmp); + len += sprintf(&buf[len], "/%s.%X", TextTmp, + (memory_read8(PGM_MEM_ID, address) & 7)); + address++; + break; + } + default: { + len += sprintf(&buf[len], "%s", + ArgsTextTbl[InstArgTbl[ArgTblOfs + i]]); + } + } + if (i < InstArgTbl[ArgTblOfs]) + len += sprintf(&buf[len], ","); + } +} + +/* Disasm one instruction at Address into a Text string */ +int +cpu8051_Disasm(unsigned int Address, char *Text) +{ + int len = 0; + char TextTmp[20]; + unsigned char OpCode; + int ArgTblOfs; + int InstSize; + int i; + + /* Display address. */ + len += sprintf(Text, " %.4X ", Address); + + OpCode = memory_read8(PGM_MEM_ID, Address); + InstSize = InstSizesTbl[OpCode]; + + /* Display hex bytes. */ + for (i = 0; i < InstSize; i++) + len += sprintf(&Text[len], " %.2X", + memory_read8(PGM_MEM_ID, Address + i)); + + Address++; + + /* Padd remaining area with spaces. */ + for (; len < 17;) + len += sprintf(&Text[len], " "); + + /* Display instruction mnemonic. */ + len += sprintf(&Text[len], "%s ", + InstTextTbl[InstTypesTbl[OpCode]]); + ArgTblOfs = OpCode << 2; + + /* Padd remaining area with spaces. */ + for (; len < 25;) + len += sprintf(&Text[len], " "); + + /* Display instruction arguments. */ + + /* + * MOV direct, direct (OpCode 85h) is peculiar, the operands + * are inverted + */ + if (OpCode == 0x85) { + cpu8051_SFRMemInfo(memory_read8(PGM_MEM_ID, Address + 1), + TextTmp); + len += sprintf(&Text[len], "%s,", TextTmp); + cpu8051_SFRMemInfo(memory_read8(PGM_MEM_ID, Address), + TextTmp); + len += sprintf(&Text[len], "%s", TextTmp); + Address += 2; + return InstSize; + } + + for (i = 1; i <= InstArgTbl[ArgTblOfs]; i++) { + switch (InstArgTbl[ArgTblOfs + i]) { + case ADDR11: { + len += sprintf(&Text[len], + "%.4XH", ((OpCode << 3) & 0xF00) + + (memory_read8(PGM_MEM_ID, Address))); + Address++; + break; + } + case ADDR16: { + len += sprintf( + &Text[len], "%.4XH", + ((memory_read8(PGM_MEM_ID, Address) << 8) + + memory_read8(PGM_MEM_ID, Address + 1))); + Address += 2; + break; + } + case DIRECT: { + cpu8051_SFRMemInfo(memory_read8(PGM_MEM_ID, Address), + TextTmp); + len += sprintf(&Text[len], "%s", TextTmp); + Address++; + break; + } + case BITADDR: { + cpu8051_IntMemBitInfo( + (memory_read8(PGM_MEM_ID, Address) & 0xF8), + TextTmp); + len += sprintf(&Text[len], "%s.%X" , TextTmp, + (memory_read8(PGM_MEM_ID, Address) & 7)); + Address++; + break; + } + case RELADDR: { + Address++; + len += sprintf(&Text[len], "%.4XH", (Address & 0xFF00) + + (((Address & 0xFF) + + memory_read8(PGM_MEM_ID, + Address - 1)) & 0xFF)); + break; + } + case DATAIMM: { + len += sprintf(&Text[len], "#%.2XH", + memory_read8(PGM_MEM_ID, Address)); + Address++; + break; + } + case DATA16: { + len += sprintf(&Text[len], "#%.4XH", + ((memory_read8(PGM_MEM_ID, + Address) << 8) + + memory_read8(PGM_MEM_ID, Address+1))); + Address += 2; + break; + } + case CBITADDR: { + cpu8051_IntMemBitInfo((memory_read8(PGM_MEM_ID, + Address) & 0xF8), + TextTmp); + len += sprintf(&Text[len], "/%s.%X", TextTmp, + (memory_read8(PGM_MEM_ID, Address) & 7)); + Address++; + break; + } + default: { + len += sprintf(&Text[len], "%s", + ArgsTextTbl[InstArgTbl[ArgTblOfs + i]]); + } + } + if (i < InstArgTbl[ArgTblOfs]) + len += sprintf(&Text[len], ","); + } + + return InstSize; +} diff --git a/src/common/cpu8051.h b/src/common/cpu8051.h new file mode 100644 index 0000000..adb96c8 --- /dev/null +++ b/src/common/cpu8051.h @@ -0,0 +1,116 @@ +/* + * cpu8051.h + * + * Copyright (C) 1999 Jonathan St-André + * Copyright (C) 1999 Hugo Villeneuve + * + * This program 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 of the License, or + * (at your option) any later version. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef CPU8051_H +#define CPU8051_H 1 + +#include + +/* Maximum number of BreakPoints */ +#define MAXBP 32 + +#define INTERRUPT_0 (0) +#define INTERRUPT_1 (1) +#define INTERRUPT_2 (2) +#define INTERRUPT_3 (3) +#define INTERRUPT_4 (4) +#define INTERRUPT_5 (5) +#define INTERRUPT_MASK(n) (1 << n) + +#define INTERRUPT_PRIORITY_HIGH (1) +#define INTERRUPT_PRIORITY_LOW (0) + +struct cpu8051_t { + unsigned int pc; /* Program counter */ + unsigned long clock; + int active_priority; + int bp_count; + unsigned int bp[MAXBP]; /* List of breakpoints */ +}; + +/* Exported variables */ +#undef _SCOPE_ +#ifdef CPU8051_M +# define _SCOPE_ /**/ +#else +# define _SCOPE_ extern +#endif + +_SCOPE_ struct cpu8051_t cpu8051; + +int +IsBreakpoint(unsigned int Address); + +int +IsStoppoint(unsigned int address); + +void +ShowBreakpoints(void); + +void +SetBreakpoint(unsigned int Address); + +void +ClearBreakpoint(unsigned int Address); + +void +ToggleBreakpoint(unsigned int Address); + +void +cpu8051_init(void); + +void +cpu8051_Exec(void); + +void +cpu8051_Reset(void); + +void +cpu8051_WriteD(unsigned int Address, unsigned char Value); + +void +cpu8051_WriteI(unsigned int Address, unsigned char Value); + +void +cpu8051_WriteB(uint8_t bit_address, uint8_t value); + +unsigned char +cpu8051_ReadD(unsigned int Address); + +unsigned char +cpu8051_ReadI(unsigned int Address); + +unsigned char +cpu8051_ReadB(uint8_t bit_address); + +int +cpu8051_get_instruction_size(unsigned char opcode); + +void +cpu8051_disasm_mnemonic(unsigned char OpCode, char *buf); + +void +cpu8051_disasm_args(unsigned int address, char *buf); + +int +cpu8051_Disasm(unsigned int Address, char *Text); + +#endif /* CPU8051_H */ diff --git a/src/common/hexfile.c b/src/common/hexfile.c new file mode 100644 index 0000000..6411166 --- /dev/null +++ b/src/common/hexfile.c @@ -0,0 +1,186 @@ +/* + * Functions for loading an Intel HEX file. + * + * Copyright (C) 1999 Jonathan St-André + * Copyright (C) 1999 Hugo Villeneuve + * + * This program 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 of the License, or + * (at your option) any later version. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#if HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include + +#if STDC_HEADERS +# include +#elif HAVE_STRINGS_H +# include +#endif + +#include "common.h" +#include "memory.h" + +/* Convert integer to ASCII hex string. */ +void +int2asciihex(int val, char *str, int width) +{ + if (width == 1) + sprintf(str , "%.1X", (u_int8_t) val); + else if (width == 2) + sprintf(str , "%.2X", (u_int8_t) val); + else if (width == 4) + sprintf(str , "%.4X", (u_int16_t) val); + else + sprintf(str , "Err"); +} + +/* Convert ASCII hex string to integer. */ +int +asciihex2int(char *str) +{ + int val; + + sscanf(str, "%X", &val); + + return val; +} + +/* Convert an ascii string to an hexadecimal number. */ +unsigned int +Ascii2Hex(char *istring, int length) +{ + unsigned int result = 0; + int i, ascii_code; + + if (!length || (length > (int) strlen(istring))) + length = strlen(istring); + + for (i = 0; i < length; i++) { + ascii_code = istring[i]; + if (ascii_code > 0x39) + ascii_code &= 0xDF; + + if ((ascii_code >= 0x30 && ascii_code <= 0x39) || + (ascii_code >= 0x41 && ascii_code <= 0x46)) { + ascii_code -= 0x30; + if (ascii_code > 9) + ascii_code -= 7; + + result <<= 4; + result += ascii_code; + } else { + printf("%s: In Ascii2Hex(), syntax error.\n", PACKAGE); + printf(" str=%s, length=%d\n", istring, length); + } + } + return result; +} + +void +LoadHexFile(const char *filename) +{ + int i, j, RecLength, LoadOffset, RecType, Data, Checksum; + +#define LINE_BUFFER_LEN 256 + FILE *fp; + int status; + char line[LINE_BUFFER_LEN]; + + if (filename == NULL) { + printf("%s: No file specified\n", PACKAGE); + exit(EXIT_FAILURE); + } + + /* Trying to open the file. */ + fp = fopen(filename, "r"); + if (fp == NULL) { + perror(filename); + /*ErrorLocation(__FILE__, __LINE__);*/ + exit(EXIT_FAILURE); + } + + /* Reading one line of data from the hex file. */ + /* char *fgets(char *s, int size, FILE *stream); + Reading stops after an EOF or a newline. If a newline is read, it is + stored into the buffer. A '\0' is stored after the last character + in the buffer. + */ + while (fgets(line, LINE_BUFFER_LEN, fp) != NULL) { + i = 0; + Checksum = 0; + + if (line[i++] != ':') { + printf("%s: line not beginning with \":\"\n", PACKAGE); + goto close_file; + } + + RecLength = Ascii2Hex(&line[i], 2); + i += 2; + Checksum += RecLength; + + LoadOffset = Ascii2Hex(&line[i], 4); + Checksum += LoadOffset / 256; + Checksum += LoadOffset % 256; + i += 4; + + RecType = Ascii2Hex(&line[i], 2); + i += 2; + Checksum += RecType; + + if (RecType == 1) { + Checksum += Ascii2Hex(&line[i], 2); + Checksum &= 0x000000FF; + + if (Checksum) { + /* Error. */ + printf("%s: Invalid format\n", PACKAGE); + goto close_file; + } else { + /* OK */ + goto close_file; + } + } + + for (j = 0; j < RecLength; j++) { + Data = Ascii2Hex(&line[i], 2); + memory_write8(PGM_MEM_ID, + (unsigned int)(LoadOffset + j), + (unsigned char)Data); + i += 2; + Checksum += Data; + } + + RecType = Ascii2Hex(&line[i], 2); + Checksum += RecType; + Checksum &= 0x000000FF; + + if (Checksum) { + printf("%s: Invalid format\n", PACKAGE); + goto close_file; + } + } + +close_file: + status = fclose(fp); + if (status != EXIT_SUCCESS) { + fprintf(stderr, "%s: Error closing hex file.\n", PACKAGE); + /*ErrorLocation(__FILE__, __LINE__);*/ + exit(EXIT_FAILURE); + } +} diff --git a/src/common/hexfile.h b/src/common/hexfile.h new file mode 100644 index 0000000..0f46527 --- /dev/null +++ b/src/common/hexfile.h @@ -0,0 +1,37 @@ +/* + * hexfile.h + * + * Copyright (C) 1999 Jonathan St-André + * Copyright (C) 1999 Hugo Villeneuve + * + * This program 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 of the License, or + * (at your option) any later version. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef HEXFILE_H +#define HEXFILE_H 1 + +void +int2asciihex(int val, char *str, int width); + +int +asciihex2int(char *str); + +unsigned int +Ascii2Hex(char *istring, int length); + +void +LoadHexFile(const char *filename); + +#endif /* HEXFILE_H */ diff --git a/src/common/log.c b/src/common/log.c new file mode 100644 index 0000000..b378575 --- /dev/null +++ b/src/common/log.c @@ -0,0 +1,130 @@ +/* + * log.c -- debug functions for logging. + * + * Copyright (C) 2011 Hugo Villeneuve + * + * This program 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 of the License, or + * (at your option) any later version. + */ + +#include "config.h" + +#include +#include +#include +#include +#include + +#include "common.h" +#include "options.h" + +#define PREFIX_PACKAGE_NAME 1 +#define ADD_LINEFEED 1 + +extern struct options_t options; + +static void +log_prefix_package_name(FILE *stream, const char *severity) +{ +#if PREFIX_PACKAGE_NAME + /* Printing the name of the program first if desired. */ + fprintf(stream, "%s %s: ", PACKAGE_NAME, severity); +#endif /* PREFIX_PACKAGE_NAME */ +} + +static void +log_suffix_newline(FILE *stream) +{ +#if ADD_LINEFEED + fprintf(stream, "\n"); +#endif /* ADD_LINEFEED */ +} + +void +log_debug(const char *format, ...) +{ + FILE *stream = stdout; + + if (options.log >= LOG_LEVEL_DEBUG) { + va_list ap; + + log_prefix_package_name(stream, "debug"); + + va_start(ap, format); + vfprintf(stream, format, ap); + va_end(ap); + + log_suffix_newline(stream); + } +} + +void +log_info(const char *format, ...) +{ + FILE *stream = stdout; + + if (options.log >= LOG_LEVEL_INFO) { + va_list ap; + + log_prefix_package_name(stream, "info"); + + va_start(ap, format); + vfprintf(stream, format, ap); + va_end(ap); + + log_suffix_newline(stream); + } +} + +void +log_warn(const char *format, ...) +{ + FILE *stream = stderr; + + if (options.log >= LOG_LEVEL_WARN) { + va_list ap; + + log_prefix_package_name(stream, "warn"); + + va_start(ap, format); + vfprintf(stream, format, ap); + va_end(ap); + + log_suffix_newline(stream); + } +} + +void +log_err(const char *format, ...) +{ + FILE *stream = stderr; + va_list ap; + + log_prefix_package_name(stream, "error"); + + va_start(ap, format); + vfprintf(stream, format, ap); + va_end(ap); + + log_suffix_newline(stream); +} + +/* Log error message and exits with error code. */ +void +log_fail(const char *format, ...) +{ + FILE *stream = stderr; + va_list ap; + + log_prefix_package_name(stream, "error"); + + va_start(ap, format); + vfprintf(stream, format, ap); + va_end(ap); + + log_suffix_newline(stream); + + exit(EXIT_FAILURE); +} diff --git a/src/common/log.h b/src/common/log.h new file mode 100644 index 0000000..6b3e2e9 --- /dev/null +++ b/src/common/log.h @@ -0,0 +1,46 @@ +/* + * log.h + * + * Copyright (C) 2011 Hugo Villeneuve + * + * This program 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 of the License, or + * (at your option) any later version. + */ + +#ifndef LOG_H +#define LOG_H 1 + +#include +#include +#include +#include +#include + +#include "common.h" + +enum LOG_LEVEL { + LOG_LEVEL_ERR = 0, /* Display only errors */ + LOG_LEVEL_WARN, /* Display warnings */ + LOG_LEVEL_INFO, /* Display information messages */ + LOG_LEVEL_DEBUG, /* Display all messages */ +}; + +void +log_debug(const char *format, ...); + +void +log_info(const char *format, ...); + +void +log_warn(const char *format, ...); + +void +log_err(const char *format, ...); + +/* Log error message and exits with error code. */ +void +log_fail(const char *format, ...); + +#endif /* LOG_H */ diff --git a/src/common/memory.c b/src/common/memory.c new file mode 100644 index 0000000..c5b2acf --- /dev/null +++ b/src/common/memory.c @@ -0,0 +1,245 @@ +/* + * memory.c + * + * Copyright (C) 1999 Jonathan St-André + * Copyright (C) 1999 Hugo Villeneuve + * + * This program 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 of the License, or + * (at your option) any later version. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include +#include + +#include "common.h" +#include "cpu8051.h" +#include "reg8051.h" +#include "hexfile.h" +#include "memory.h" +#include "options.h" + +struct mem_infos_t { + int size; + int max_size; + u_int8_t *buf; +}; + +struct mem_infos_t mem_infos[MEM_ID_COUNT]; + +extern struct options_t options; + +/* Init each 8051 memory sections. */ +void +memory_init(void) +{ + int k; + struct mem_infos_t *m; + + /* Set desired and maximum allowable sizes for each memory type. */ + mem_infos[PGM_MEM_ID].size = options.pram_size; + mem_infos[PGM_MEM_ID].max_size = PGM_MEM_MAX_SIZE; + + mem_infos[INT_MEM_ID].size = options.iram_size; + mem_infos[INT_MEM_ID].max_size = INT_MEM_MAX_SIZE; + + mem_infos[EXT_MEM_ID].size = options.xram_size; + mem_infos[EXT_MEM_ID].max_size = EXT_MEM_MAX_SIZE; + + /* Verify if desired sizes are valid, and if so allocate memory. */ + for (k = 0; k < MEM_ID_COUNT; k++) { + m = &mem_infos[k]; + + if (m->size > m->max_size) { + log_err("Memory size invalid (max = %d)", m->max_size); + exit(1); + } + + m->buf = malloc(m->size); + if (m->buf == NULL) { + log_err("%s", strerror(errno)); + exit(1); + } + + memset(m->buf, 0x00, m->size); + } +} + +void +memory_clear(enum mem_id_t id) +{ + memset(mem_infos[id].buf, 0, mem_infos[id].size); +} + +void +memory_write8(enum mem_id_t id, unsigned long address, u_int8_t value) +{ + if (address >= mem_infos[id].max_size) { + printf("Error writing to memory ID: %d\n", id); + printf(" Address (%lu) greater than maximum memory size\n", + address); + return; + } else + mem_infos[id].buf[address] = value; +} + +void +memory_sfr_write8(unsigned long address, u_int8_t value) +{ + /* SFR registers are from addresses $80 to $FF. */ + memory_write8(INT_MEM_ID, address, value); +} + +void +memory_sfr_write_dptr(u_int16_t value) +{ + memory_write8(INT_MEM_ID, _DPTRHIGH_, value >> 8); + memory_write8(INT_MEM_ID, _DPTRLOW_, (uint8_t) value); +} + +u_int8_t +memory_read8(enum mem_id_t id, unsigned long address) +{ + if (address >= mem_infos[id].max_size) { + printf("Error reading from memory ID: %d\n", id); + printf(" Address (%lu) greater than maximum memory size\n", + address); + return 0; + } else + return mem_infos[id].buf[address]; +} + +u_int8_t +memory_sfr_read8(unsigned long address) +{ + /* SFR registers are from addresses $80 to $FF. */ + return memory_read8(INT_MEM_ID, address); +} + +u_int16_t +memory_sfr_read_dptr(void) +{ + return (memory_read8(INT_MEM_ID, _DPTRHIGH_) << 8) + + memory_read8(INT_MEM_ID, _DPTRLOW_); +} + +void +stack_push8(uint8_t value) +{ + uint8_t sp; + + sp = memory_read8(INT_MEM_ID, _SP_); + + memory_write8(INT_MEM_ID, ++sp, value); + memory_write8(INT_MEM_ID, _SP_, sp); /* Save new stack pointer */ +} + +void +stack_push16(uint16_t value) +{ + uint8_t sp; + + sp = memory_read8(INT_MEM_ID, _SP_); + + memory_write8(INT_MEM_ID, ++sp, (uint8_t) value); /* Write LSB */ + memory_write8(INT_MEM_ID, ++sp, value >> 8); /* Write MSB */ + memory_write8(INT_MEM_ID, _SP_, sp); /* Save new stack pointer */ +} + +uint8_t +stack_pop8(void) +{ + uint8_t sp; + uint8_t value; + + sp = memory_read8(INT_MEM_ID, _SP_); + + value = memory_read8(INT_MEM_ID, sp--); + memory_write8(INT_MEM_ID, _SP_, sp); /* Save new stack pointer */ + + return value; +} + +uint16_t +stack_pop16(void) +{ + uint8_t sp; + uint16_t value; + + sp = memory_read8(INT_MEM_ID, _SP_); + + value = memory_read8(INT_MEM_ID, sp--) << 8; /* Read MSB */ + value |= memory_read8(INT_MEM_ID, sp--); /* Read LSB */ + memory_write8(INT_MEM_ID, _SP_, sp); /* Save new stack pointer */ + + return value; +} + +/* Read a 16-bit address from PGM memory, starting at offset */ +uint16_t +pgm_read_addr16(uint16_t base) +{ + uint16_t addr; + + addr = memory_read8(PGM_MEM_ID, base) << 8; /* MSB */ + addr |= memory_read8(PGM_MEM_ID, base + 1); /* LSB */ + + return addr; +} + +/* Dump memory */ +void +DumpMem(char *Address, char *Asize, int memory_id) +{ + unsigned int MemAddress; + int size; + int Offset, Column; + + if (strlen(Address) != 0) { + if (STREQ(Address, "PC")) + MemAddress = cpu8051.pc; + else + MemAddress = Ascii2Hex(Address, strlen(Address)); + } else { + MemAddress = 0; + } + + if (strlen(Asize) != 0) { + size = Ascii2Hex(Asize, strlen(Asize)); + } else { + size = 256; /* Default size if not specified. */ + } + + for (Offset = 0; Offset < size; Offset += 16) { + unsigned char data[16]; + + printf("%.4X ", MemAddress + Offset); + + for (Column = 0; Column < 16; Column++) { + data[Column] = memory_read8(memory_id, MemAddress + + Offset + Column); + printf(" %.2X", (int) data[Column]); + } + printf(" "); + + /* Display any ASCII characters */ + for (Column = 0; Column < 16; Column++) { + if ((int) data[Column] >= 32 && + (int) data[Column] <= 126) { + printf("%c", data[Column]); + } else + printf("."); + } + printf("\n"); + } +} diff --git a/src/common/memory.h b/src/common/memory.h new file mode 100644 index 0000000..fee41a6 --- /dev/null +++ b/src/common/memory.h @@ -0,0 +1,88 @@ +/* + * memory.h + * + * Copyright (C) 1999 Jonathan St-André + * Copyright (C) 1999 Hugo Villeneuve + * + * This program 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 of the License, or + * (at your option) any later version. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef MEMORY_H +#define MEMORY_H 1 + +#include + +#define PGM_MEM_MAX_SIZE 65536 +/* + * Direct addressing $00 to $7F = IRAM (8051) + * Direct addressing $80 to $FF = SFR (8051) + * Indirect addressing $80 to $FF = IRAM (8052) + */ +#define INT_MEM_MAX_SIZE 256 +#define EXT_MEM_MAX_SIZE 65536 + +#define PGM_MEM_DEFAULT_SIZE 8192 +#define EXT_MEM_DEFAULT_SIZE 1024 + +enum mem_id_t { + PGM_MEM_ID, + INT_MEM_ID, + EXT_MEM_ID, + MEM_ID_COUNT +}; + +void +memory_init(void); + +void +memory_clear(enum mem_id_t id); + +void +memory_write8(enum mem_id_t id, unsigned long address, u_int8_t value); + +void +memory_sfr_write8(unsigned long address, u_int8_t value); + +void +memory_sfr_write_dptr(u_int16_t value); + +u_int8_t +memory_read8(enum mem_id_t id, unsigned long address); + +u_int8_t +memory_sfr_read8(unsigned long address); + +u_int16_t +memory_sfr_read_dptr(void); + +void +stack_push8(uint8_t value); + +void +stack_push16(uint16_t value); + +uint8_t +stack_pop8(void); + +uint16_t +stack_pop16(void); + +uint16_t +pgm_read_addr16(uint16_t base); + +void +DumpMem(char *Address, char *Asize, int memory_id); + +#endif /* MEMORY_H */ diff --git a/src/common/opcode2c.pl b/src/common/opcode2c.pl new file mode 100755 index 0000000..035c718 --- /dev/null +++ b/src/common/opcode2c.pl @@ -0,0 +1,851 @@ +#!/usr/bin/perl +# +# Copyright (C) 1999 Jonathan St-André +# Copyright (C) 1999 Hugo Villeneuve +# +# This program 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 of the License, or +# (at your option) any later version. +# +# This program 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 this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. + +open INST_DEF, ">instructions_8051.h" or die "Error creating : $!\n"; +open INST_IMP, ">instructions_8051.c" or die "Error creating : $!\n"; +open OPCODELST, "opcodes.lst" or die "Error opening : $!\n"; +open DISASM_H, ">disasm.h" or die "Error creating : $!\n"; + +# Write GPL license +# Argument 0 is file descriptor +sub write_header +{ + my $fd = $_[0]; + + print $fd " *\n"; + print $fd " * Do not modify this file directly, as it was created by opcode2c.pl\n"; + print $fd " * Any modifications made directly to this file will be lost.\n"; + print $fd " *\n"; + print $fd " * Copyright (C) 1999 Jonathan St-André\n"; + print $fd " * Copyright (C) 1999 Hugo Villeneuve \n"; + print $fd " *\n"; + print $fd " * This program is free software; you can redistribute it and/or modify\n"; + print $fd " * it under the terms of the GNU General Public License as published by\n"; + print $fd " * the Free Software Foundation; either version 2 of the License, or\n"; + print $fd " * (at your option) any later version.\n"; + print $fd " *\n"; + print $fd " * This program is distributed in the hope that it will be useful,\n"; + print $fd " * but WITHOUT ANY WARRANTY; without even the implied warranty of\n"; + print $fd " * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"; + print $fd " * GNU General Public License for more details.\n"; + print $fd " *\n"; + print $fd " * You should have received a copy of the GNU General Public License\n"; + print $fd " * along with this program; if not, write to the Free Software\n"; + print $fd " * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.\n"; + print $fd " */\n\n"; +} + +# Write C function source code line to INST_IMP file. +# Prefix each line with a tab (indentation) and add newline character at the end. +sub cfw +{ + print INST_IMP "\t",$_[0],"\n"; +} + +# Header for instructions_8051.c +print INST_IMP "/*\n"; +print INST_IMP " * instructions_8051.c\n"; +write_header(INST_IMP); +print INST_IMP "/* Define only here, for not having extern scope on local variables. */\n"; +print INST_IMP "#define INSTRUCTIONS_8051_M 1\n\n\n"; +print INST_IMP "#include \"reg8051.h\"\n"; +print INST_IMP "#include \"cpu8051.h\"\n"; +print INST_IMP "#include \"memory.h\"\n"; +print INST_IMP "#include \"psw.h\"\n"; +print INST_IMP "#include \"instructions_8051.h\"\n\n\n"; + +# Header for disasm.h +print DISASM_H "/*\n"; +print DISASM_H " * disasm.h\n"; +write_header(DISASM_H); +print DISASM_H "#ifndef DISASM_H\n"; +print DISASM_H "#define DISASM_H 1\n\n"; + +$nbinst=0; +$nbaddr=0; +$nbargs=0; +$instnumb=0; + +$ligne=; +$ligne=; +while($ligne=) { + chop $ligne; + if (length $ligne < 2) {next;} + @wordlist=split ' ',$ligne; + $nbword=@wordlist; + $instruction=$wordlist[2]; + for($i=3;$i<($nbword-2);$i++) {$instruction="$instruction $wordlist[$i]";} + + $a_instruction[$instnumb]=$instruction; + $a_bytes[$instnumb]=$wordlist[$nbword-2]; + $a_cycles[$instnumb]=$wordlist[$nbword-1]; + $a_opcodehex[$instnumb]=$wordlist[1]; + $a_opcodebin[$instnumb]=$wordlist[0]; + + $instfunction[$instnumb]="CPU8051::OP_$wordlist[1]"; + + $instargs[$instnumb << 2]=$instargs[($instnumb << 2) + 1]=$instargs[($instnumb << 2) + 2]=$instargs[($instnumb << 2) + 3]=0; + if ($nbword > 5) { + @argslist=split /\,/,$wordlist[3]; + $argslistsize=@argslist; + $instargs[$instnumb << 2]=$argslistsize; + for ($i=0;$i<$argslistsize;$i++) { + if (not exists $argstypes{$argslist[$i]}) { + $argstypes[$nbargs]=$argslist[$i]; + $argstypes{$argslist[$i]}=$nbargs++; + } + $instargs[($instnumb << 2) + $i + 1]=$argstypes{$argslist[$i]}; + } + } + + if (not exists $insttext{$wordlist[2]}) { + $insttext[$nbinst]=$wordlist[2]; + $insttext{$wordlist[2]}=$nbinst++; + } + + $insttype[$instnumb]=$insttext{$wordlist[2]}; + + if ( not exists $addrmode{$wordlist[3]}) { + $addrmode[$nbaddr]=$wordlist[3]; + $addrmode{$wordlist[3]}=$nbaddr++; + } + + $nbbytes[$instnumb]=$wordlist[$nbword-2]; + + $instaddr[$instnumb]=$addrmode{$wordlist[3]}; + + $instnumb++; +} +# ------------------------------------------------------------------------------ +print DISASM_H "/*\n"; +print DISASM_H " * For all 256 opcodes, the value in this table gives the instruction type\n"; +print DISASM_H " * ex.: MOV, INC, CLR, CPL,...\n"; +print DISASM_H " * To know what is the instruction type, use\n"; +print DISASM_H " * the number as an offset in the InstTextTbl[]\n"; +print DISASM_H " */\n"; +print DISASM_H "static int InstTypesTbl[] = {\n"; +for($i=0;$i<256;$i++) { + print DISASM_H " $insttype[$i]"; + ($i != 255) and print DISASM_H ","; + if (($i+1) % 16 == 0) { print DISASM_H "\n"; } +} +print DISASM_H "};\n"; +print DISASM_H "\n"; +# ------------------------------------------------------------------------------ +print DISASM_H "/* Size(in bytes) of each instruction (offset in table is instruction opcode) */\n"; +print DISASM_H "static int InstSizesTbl[] = {\n"; +for($i=0;$i<256;$i++) { + print DISASM_H " $nbbytes[$i]"; + ($i != 255) and print DISASM_H ","; + if (($i+1) % 16 == 0) { print DISASM_H "\n"; } +} +print DISASM_H "};\n"; +print DISASM_H "\n"; +# ------------------------------------------------------------------------------ +print DISASM_H "/* List of instructions types referenced by InstTypesTbl[] */\n"; +$nbelement=@insttext; +print DISASM_H "\#define InstTextTblLength $nbelement\n"; +$elementnb=0; +print DISASM_H "static char *InstTextTbl[] = {\n"; +foreach $instruc (@insttext) { + print DISASM_H " \"$instruc\""; + ($elementnb++ < $nbelement-1) and print DISASM_H ","; + print DISASM_H "\n"; +} +print DISASM_H "};\n"; +print DISASM_H "\n"; +# ------------------------------------------------------------------------------ +print DISASM_H "/*\n"; +print DISASM_H " * Table describing all arguments types of an instruction\n"; +print DISASM_H " * The table is indexed InstArgTbl[ opcode * 4]\n"; +print DISASM_H " * InstArgTbl[opcode*4 + 1] gives the number of arguments the instruction has\n"; +print DISASM_H " * InstArgTbl[opcode*4 + i] for i=1,2 and 3 give the type of each argument\n"; +print DISASM_H " * for most instructions, the 3rd argument isn't used\n"; +print DISASM_H " * the argument type is referecing to ArgsTextTbl[]\n"; +print DISASM_H " */\n"; +print DISASM_H "\#define InstArgTblLength 256\n"; +print DISASM_H "static int InstArgTbl[] = {\n"; +for($i=0;$i<1024;$i++) { + print DISASM_H " $instargs[$i]"; + ($i != 1023) and print DISASM_H ","; + if (($i+1) % 16 == 0) { print DISASM_H "\n"; } +} +print DISASM_H "};\n"; +print DISASM_H "\n"; +# ------------------------------------------------------------------------------ +print DISASM_H "/*\n"; +print DISASM_H " * List all types of arguments available to instructions\n"; +print DISASM_H " * Referenced by InstArgsTbl[]\n"; +print DISASM_H " */\n"; +$nbelement=@argstypes; +print DISASM_H "\#define ArgsTextTblLength $nbelement\n"; +$elementnb=0; +print DISASM_H "static char *ArgsTextTbl[] = {\n"; +foreach $args (@argstypes) { + print DISASM_H " \"$args\""; + ($elementnb++ < $nbelement-1) and print DISASM_H ","; + print DISASM_H "\n"; +} +print DISASM_H "};\n"; +print DISASM_H "\n"; + +# ------------------------------------------------------------------------------ +for ($i=0 ; $i< 256; $i++) { + print INST_IMP "/*","*"x76,"\n"; + print INST_IMP " * Instruction \"$a_instruction[$i]\" takes $a_cycles[$i] cycle(s) and $a_bytes[$i] byte(s).\n"; + print INST_IMP " ","*"x76,"/\n"; + print INST_IMP "int\n"; + print INST_IMP "cpu8051_OP_$a_opcodehex[$i](void)\n"; + print INST_IMP "{\n"; + + if( $i == 0x85 ) { + # Cas particulier pour MOV direct,direct -> src et dest sont inverses dans la memoire + print INST_IMP " unsigned char srcaddr = memory_read8( PGM_MEM_ID, cpu8051.pc++ );\n"; + print INST_IMP " unsigned char source = cpu8051_ReadD( srcaddr );\n"; + print INST_IMP " unsigned char destaddr = memory_read8( PGM_MEM_ID, cpu8051.pc++ );\n"; + print INST_IMP " unsigned char destination = cpu8051_ReadD( destaddr );\n"; + print INST_IMP " destination = source;\n"; + print INST_IMP " cpu8051_WriteD( destaddr, destination );\n"; + } + else { + if ($instargs[$i*4] > 0) { + $op_destination=$instargs[$i*4+1]; + if ($op_destination == 0) { # addr11 + cfw("unsigned int addr11 = ( ( memory_read8( PGM_MEM_ID, cpu8051.pc - 1 ) << 3 ) & 0xF00 ) + memory_read8( PGM_MEM_ID, cpu8051.pc );"); + cfw("cpu8051.pc++;"); + } + if ($op_destination == 1) { # addr16 + cfw("uint16_t addr16 = pgm_read_addr16(cpu8051.pc);"); + cfw("cpu8051.pc += 2;"); + } + if ($op_destination == 2) { # A + cfw("unsigned char destination = cpu8051_ReadD( _ACC_ );"); + } + if ($op_destination == 3) { # direct + cfw("unsigned char destaddr = memory_read8( PGM_MEM_ID, cpu8051.pc++ );"); + cfw("unsigned char destination = cpu8051_ReadD( destaddr );"); + } + if ($op_destination == 4) { # @R0 + cfw("unsigned char destination = cpu8051_ReadI ( cpu8051_ReadD( BANKPSW + _R0_ ) );"); + } + if ($op_destination == 5) { # @R1 + cfw("unsigned char destination = cpu8051_ReadI ( cpu8051_ReadD( BANKPSW + _R1_ ) );"); + } + if ($op_destination == 6) { # R0 + cfw("unsigned char destination = cpu8051_ReadD( BANKPSW + _R0_ );"); + } + if ($op_destination == 7) { # R1 + cfw("unsigned char destination = cpu8051_ReadD( BANKPSW + _R1_ );"); + } + if ($op_destination == 8) { # R2 + cfw("unsigned char destination = cpu8051_ReadD( BANKPSW + _R2_ );"); + } + if ($op_destination == 9) { # R3 + cfw("unsigned char destination = cpu8051_ReadD( BANKPSW + _R3_ );"); + } + if ($op_destination == 10) { # R4 + cfw("unsigned char destination = cpu8051_ReadD( BANKPSW + _R4_ );"); + } + if ($op_destination == 11) { # R5 + cfw("unsigned char destination = cpu8051_ReadD( BANKPSW + _R5_ );"); + } + if ($op_destination == 12) { # R6 + cfw("unsigned char destination = cpu8051_ReadD( BANKPSW + _R6_ );"); + } + if ($op_destination == 13) { # R7 + cfw("unsigned char destination = cpu8051_ReadD( BANKPSW + _R7_ );"); + } + if ($op_destination == 14) { # bitaddr + cfw("unsigned char destination, dstbitaddr = memory_read8( PGM_MEM_ID, cpu8051.pc++ );"); + cfw("destination = cpu8051_ReadB( dstbitaddr );"); + } + if ($op_destination == 15) { # reladdr + cfw("cpu8051.pc++;"); + cfw("unsigned int destination = ((char) memory_read8(PGM_MEM_ID, cpu8051.pc - 1)) + cpu8051.pc;"); + } + if ($op_destination == 16) { # #data + cfw("unsigned char destination = memory_read8( PGM_MEM_ID, cpu8051.pc++ );"); + } + if ($op_destination == 17) { # C + cfw("unsigned char destination = psw_read_cy();"); + } + if ($op_destination == 18) { # @A+DPTR + cfw("unsigned int destination = cpu8051_ReadD( _ACC_ ) + memory_sfr_read_dptr();"); + } + if ($op_destination == 20) { # AB + cfw("unsigned char destination = cpu8051_ReadD( _ACC_ );"); + cfw("unsigned char source = cpu8051_ReadD( _B_ );"); + } + if ($op_destination == 21) { # DPTR + cfw("unsigned int destination = memory_sfr_read_dptr();"); + } + if ($op_destination == 23) { # /bitaddr + cfw("unsigned char destination, dstbitaddr = memory_read8( PGM_MEM_ID, (cpu8051.pc)++ );"); + cfw("destination = ( cpu8051_ReadB( dstbitaddr ) ^ 1 );"); + } + if ($op_destination == 24) { # @DPTR + cfw("unsigned char destination = cpu8051_ReadI(memory_sfr_read_dptr());"); + } + } + + if ($instargs[$i*4] > 1) { + $op_source=$instargs[$i*4+2]; + if ($op_source == 0) { # addr11 + cfw("unsigned int addr11 = ( ( memory_read8( PGM_MEM_ID, cpu8051.pc - 1 ) << 3 ) & 0xF00 ) + memory_read8( PGM_MEM_ID, (cpu8051.pc)++ );"); + } + if ($op_source == 1) { # addr16 + cfw("uint16_t addr16 = pgm_read_addr16(cpu8051.pc);"); + cfw("cpu8051.pc += 2;"); + } + if ($op_source == 2) { # A + cfw("unsigned char source = cpu8051_ReadD( _ACC_ );"); + } + if ($op_source == 3) { # direct + cfw("unsigned char srcaddr = memory_read8( PGM_MEM_ID, (cpu8051.pc)++ );"); + cfw("unsigned char source = cpu8051_ReadD( srcaddr );"); + } + if ($op_source == 4) { # @R0 + cfw("unsigned char source = cpu8051_ReadI ( cpu8051_ReadD( BANKPSW + _R0_ ) );"); + } + if ($op_source == 5) { # @R1 + cfw("unsigned char source = cpu8051_ReadI ( cpu8051_ReadD( BANKPSW + _R1_ ) );"); + } + if ($op_source == 6) { # R0 + cfw("unsigned char source = cpu8051_ReadD( BANKPSW + _R0_ );"); + } + if ($op_source == 7) { # R1 + cfw("unsigned char source = cpu8051_ReadD( BANKPSW + _R1_ );"); + } + if ($op_source == 8) { # R2 + cfw("unsigned char source = cpu8051_ReadD( BANKPSW + _R2_ );"); + } + if ($op_source == 9) { # R3 + cfw("unsigned char source = cpu8051_ReadD( BANKPSW + _R3_ );"); + } + if ($op_source == 10) { # R4 + cfw("unsigned char source = cpu8051_ReadD( BANKPSW + _R4_ );"); + } + if ($op_source == 11) { # R5 + cfw("unsigned char source = cpu8051_ReadD( BANKPSW + _R5_ );"); + } + if ($op_source == 12) { # R6 + cfw("unsigned char source = cpu8051_ReadD( BANKPSW + _R6_ );"); + } + if ($op_source == 13) { # R7 + cfw("unsigned char source = cpu8051_ReadD( BANKPSW + _R7_ );"); + } + + if ($op_source == 14) { # bitaddr + cfw("unsigned char source, srcbitaddr = memory_read8( PGM_MEM_ID, (cpu8051.pc)++ );"); + cfw("source = cpu8051_ReadB( srcbitaddr );"); + } + if ($op_source == 15) { # reladdr + cfw("(cpu8051.pc)++;"); + cfw("unsigned int source = ((char) memory_read8(PGM_MEM_ID, cpu8051.pc - 1)) + cpu8051.pc;"); + } + if ($op_source == 16) { # #data + cfw("unsigned char source = memory_read8( PGM_MEM_ID, (cpu8051.pc)++ );"); + } + if ($op_source == 17) { # C + cfw("unsigned char source = psw_read_cy();"); + } + if ($op_source == 18) { # @A+DPTR + cfw("unsigned char source = memory_read8( PGM_MEM_ID, cpu8051_ReadD( _ACC_ ) + memory_sfr_read_dptr());"); + } + if ($op_source == 19) { # @A+PC + cfw("unsigned char source = memory_read8( PGM_MEM_ID, cpu8051_ReadD( _ACC_ ) + ( ++cpu8051.pc ) );"); + } + if ($op_source == 21) { # DPTR + cfw("unsigned int source = memory_sfr_read_dptr();"); + } + if ($op_source == 22) { # #data16 + cfw("uint16_t source = pgm_read_addr16(cpu8051.pc);"); + cfw("cpu8051.pc += 2;"); + } + if ($op_source == 23) { # /bitaddr + cfw("unsigned char source, srcbitaddr = memory_read8( PGM_MEM_ID, (cpu8051.pc)++ );"); + cfw("source = ( cpu8051_ReadB( srcbitaddr ) ^ 1 );"); + } + if ($op_source == 24) { # @DPTR + cfw("unsigned char source = cpu8051_ReadI(memory_sfr_read_dptr());"); + } + } + +############################################################################## + $modifysrc=0; + + # RR + if ($insttype[$i] == 3) { + cfw("destination = ( destination >> 1 ) | ( destination << 7 );"); + } + + # INC + if ($insttype[$i] == 4) { + cfw("destination++;"); + } + + # JBC + if ($insttype[$i] == 5) { + cfw("if ( destination == 1 ) { cpu8051.pc = source; destination = 0; }"); + } + + # ACALL + if ($insttype[$i] == 6) { + cfw("stack_push16(cpu8051.pc);"); + } + + # LCALL + if ($insttype[$i] == 7) { + cfw("stack_push16(cpu8051.pc);"); + } + + # RRC + if ($insttype[$i] == 8) { + cfw("unsigned char new_cy = destination & 0x01;"); + cfw("destination = ( destination >> 1 ) | (psw_read_cy() << 7);"); + cfw("psw_write_cy(new_cy);"); + } + + # DEC + if ($insttype[$i] == 9) { + cfw("destination--;"); + } + + # JB + if ($insttype[$i] == 10) { + cfw("if ( destination == 1 ) { cpu8051.pc = source; }"); + } + + # RET + if ($insttype[$i] == 11) { + cfw("cpu8051.pc = stack_pop16();"); + } + + # RL + if ($insttype[$i] == 12) { + cfw("destination = ( destination << 1 ) | ( destination >> 7 );"); + } + + # ADD + if ($insttype[$i] == 13) { + cfw("psw_clr_cy();"); + cfw("psw_clr_ac();"); + cfw("psw_clr_ov();"); + # The Overflow (OV) bit is set if there is a carry-out of bit 6 or + # out of bit 7, but not both. In other words, if the addition of the + # Accumulator, operand and (in the case of ADDC) the Carry flag + # treated as signed values results in a value that is out of the + # range of a signed byte (-128 through +127) the Overflow flag is + # set. Otherwise, the Overflow flag is cleared. + cfw("if ( destination + source > 0xFF ) {"); + # Carry from bit 7 + cfw(" psw_set_cy();"); + # If no carry from bit 6, set OV + cfw(" if (((destination & 0x7F) + (source & 0x7F)) < 0x80)"); + cfw(" psw_set_ov();"); + # If no carry from bit 7, but caary from bit 6, set OV + cfw("} else if (((destination & 0x7F) + (source & 0x7F)) > 0x7F ) psw_set_ov();"); + cfw("if (((destination & 0x0F) + (source & 0x0F)) > 0x0F) psw_set_ac();"); + cfw("destination += source;"); + } + + # JNB + if ($insttype[$i] == 14) { + cfw("if ( destination == 0 ) { cpu8051.pc = source; }"); + } + + # RETI + if ($insttype[$i] == 15) { + cfw("cpu8051.active_priority = -1;"); + cfw("cpu8051.pc = stack_pop16();"); + } + + # RLC + if ($insttype[$i] == 16) { + cfw("unsigned char new_cy = destination & 0x80;"); + cfw("destination = ( destination << 1 ) | psw_read_cy();"); + cfw("psw_write_cy(new_cy);"); + } + + # ADDC + if ($insttype[$i] == 17) { + cfw("unsigned char carryflag = psw_read_cy();"); + cfw("psw_clr_cy();"); + cfw("psw_clr_ac();"); + cfw("psw_clr_ov();"); + cfw("if ( destination + source + carryflag > 0xFF ) {"); + cfw(" psw_set_cy();"); + cfw(" if (((destination & 0x7F) + (source & 0x7F) + carryflag) < 0x80);"); + cfw(" psw_set_ov();"); + cfw("} else if (((destination & 0x7F) + (source & 0x7F) + carryflag) > 0x7F) psw_set_ov();"); + cfw("if (((destination & 0x0F) + (source & 0x0F) + carryflag) > 0x0F) psw_set_ac();"); + cfw("destination += source;"); + } + + # JC + if ($insttype[$i] == 18) { + cfw("if (psw_read_cy()) { cpu8051.pc = destination; }"); + } + + # ORL + if ($insttype[$i] == 19) { + cfw("destination |= source;"); + } + + # JNC + if ($insttype[$i] == 20) { + cfw("if (psw_read_cy() == 0) { cpu8051.pc = destination; }"); + } + + # ANL + if ($insttype[$i] == 21) { + cfw("destination &= source;"); + } + + # JZ + if ($insttype[$i] == 22) { + cfw("if ( cpu8051_ReadD( _ACC_ ) == 0 ) { cpu8051.pc = destination; }"); + } + + # XRL + if ($insttype[$i] == 23) { + cfw("destination ^= source;"); + } + + # JNZ + if ($insttype[$i] == 24) { + cfw("if ( cpu8051_ReadD( _ACC_ ) != 0 ) { cpu8051.pc = destination; }"); + } + + # JMP + if ($insttype[$i] == 25) { + cfw("cpu8051.pc = destination;"); + } + + # MOV + if ($insttype[$i] == 26) { + cfw("destination = source;"); + } + + # SJMP + if ($insttype[$i] == 27) { + cfw("cpu8051.pc = destination;"); + } + + # MOVC + if ($insttype[$i] == 28) { + cfw("destination = source;"); + } + + # DIV + if ($insttype[$i] == 29) { + # A = destination + # B = source + cfw("psw_clr_cy();"); + # If B is zero, the OV flag will be set indicating a + # division-by-zero error + cfw("if (source != 0) {"); + cfw(" cpu8051_WriteD(_ACC_, destination/source);"); + cfw(" cpu8051_WriteD( _B_, destination%source);"); + cfw(" psw_clr_ov();"); + cfw("} else {"); + cfw(" psw_set_ov();"); + cfw("}"); + } + + # SUBB + if ($insttype[$i] == 30) { + cfw("unsigned char carryflag = psw_read_cy();"); + cfw("psw_clr_cy();"); + cfw("psw_clr_ac();"); + cfw("psw_clr_ov();"); + cfw("if ( destination < ( source + carryflag ) ) {"); + cfw(" psw_set_cy();"); + cfw(" if ((destination & 0x7F) > ((source + carryflag) & 0x7F)) psw_set_ov();"); + cfw("} else if ((destination & 0x7F) < ((source + carryflag) & 0x7F)) psw_set_ov();"); + cfw("if ((destination & 0x0F) < ((source + carryflag) & 0x0F)) psw_set_ac();"); + cfw("destination -= source + carryflag;"); + } + + # MUL + if ($insttype[$i] == 31) { + # A = destination + # B = source + cfw("psw_clr_cy();"); + cfw("cpu8051_WriteD(_ACC_, destination * source);"); + cfw("cpu8051_WriteD(_B_, (destination * source) / 0x100);"); + cfw("if (cpu8051_ReadD(_B_) > 0)"); + cfw(" psw_set_ov();"); + cfw("else"); + cfw(" psw_clr_ov();"); + } + + # CPL + if ($insttype[$i] == 33) { + if ($instargs[$i*4+1] == 2) { cfw("destination ^= 0xFF;"); } + else { cfw("destination ^= 0x01;"); } + } + + # CJNE + if ($insttype[$i] == 34) { + cfw("unsigned int reladdr = ((char) memory_read8(PGM_MEM_ID, cpu8051.pc)) + (cpu8051.pc + 1);"); + cfw("psw_clr_cy();"); + cfw("if ( destination < source ) psw_set_cy();"); + cfw("if ( destination != source ) cpu8051.pc = reladdr; else cpu8051.pc++;"); + } + + # PUSH + if ($insttype[$i] == 35) { + cfw("stack_push8(destination);"); + } + + # CLR + if ($insttype[$i] == 36) { + cfw("destination = 0;"); + } + + # SWAP + if ($insttype[$i] == 37) { + cfw("destination = ( destination << 4 ) + ( destination >> 4 );"); + } + + # XCH + if ($insttype[$i] == 38) { + cfw("unsigned char tmpval = destination;"); + cfw("destination = source; source = tmpval;"); + $modifysrc=1; + } + + # POP + if ($insttype[$i] == 39) { + cfw("destination = stack_pop8();"); + } + + # SETB + if ($insttype[$i] == 40) { + cfw("destination = 1;"); + } + + # DA + if ($insttype[$i] == 41) { + cfw("if (((destination & 0x0F) > 9) || psw_read_ac()) {"); + cfw(" if ( ( destination + 6 ) > 0xFF) psw_set_cy();"); + cfw(" destination += 6;"); + cfw("}"); + cfw("if ( psw_read_cy() || ( ( destination & 0xF0 ) > 0x90 ) ) {"); + cfw(" if ( ( destination + 0x60 ) > 0xFF ) psw_set_cy();"); + cfw(" destination += 0x60;"); + cfw("}"); + } + + # DJNZ + if ($insttype[$i] == 42) { + cfw("destination--;"); + cfw("if ( destination != 0 ) cpu8051.pc = source;"); + } + + # XCHD + if ($insttype[$i] == 43) { + cfw("unsigned char tmpval = ( destination & 0x0F );"); + cfw("destination = ( destination & 0xF0 ) + ( source & 0x0F );"); + cfw("source = ( source & 0xF0 ) + tmpval;"); + $modifysrc=1; + } + + # MOVX + if ($insttype[$i] == 44) { + cfw("destination = source;"); + } + + + +############################################################################## + + + if ($instargs[$i*4] > 0) { + $op_destination=$instargs[$i*4+1]; + if ($op_destination == 0) { # addr11 + cfw("cpu8051.pc = ( cpu8051.pc & 0xF800 ) | addr11;"); + } + if ($op_destination == 1) { # addr16 + cfw("cpu8051.pc = addr16;"); + } + if ($op_destination == 2) { # A + cfw("cpu8051_WriteD( _ACC_, destination );"); + } + if ($op_destination == 3) { # direct + cfw("cpu8051_WriteD( destaddr, destination );"); + } + if ($op_destination == 4) { # @R0 + cfw("cpu8051_WriteI( cpu8051_ReadD( BANKPSW + _R0_ ), destination );"); + } + if ($op_destination == 5) { # @R1 + cfw("cpu8051_WriteI( cpu8051_ReadD( BANKPSW + _R1_ ), destination );"); + } + if ($op_destination == 6) { # R0 + cfw("cpu8051_WriteD( BANKPSW + _R0_, destination );"); + } + if ($op_destination == 7) { # R1 + cfw("cpu8051_WriteD( BANKPSW + _R1_, destination );"); + } + if ($op_destination == 8) { # R2 + cfw("cpu8051_WriteD( BANKPSW + _R2_, destination );"); + } + if ($op_destination == 9) { # R3 + cfw("cpu8051_WriteD( BANKPSW + _R3_, destination );"); + } + if ($op_destination == 10) { # R4 + cfw("cpu8051_WriteD( BANKPSW + _R4_, destination );"); + } + if ($op_destination == 11) { # R5 + cfw("cpu8051_WriteD( BANKPSW + _R5_, destination );"); + } + if ($op_destination == 12) { # R6 + cfw("cpu8051_WriteD( BANKPSW + _R6_, destination );"); + } + if ($op_destination == 13) { # R7 + cfw("cpu8051_WriteD( BANKPSW + _R7_, destination );"); + } + + if ($op_destination == 14) { # bitaddr + cfw("cpu8051_WriteB( dstbitaddr, destination );"); + } + if ($op_destination == 17) { # C + cfw("psw_write_cy(destination);"); + } + if ($op_destination == 21) { # DPTR + cfw("memory_sfr_write_dptr(destination);"); + } + if ($op_destination == 23) { # /bitaddr + cfw("cpu8051_WriteB( dstbitaddr, destination );"); + } + if ($op_destination == 24) { # @DPTR + cfw("cpu8051_WriteI(memory_sfr_read_dptr(), destination);"); + } + } + + if ($modifysrc == 1) { + if ($instargs[$i*4] > 1) { + $op_source=$instargs[$i*4+2]; + if ($op_source == 0) { # addr11 + cfw("cpu8051.pc = ( cpu8051.pc & 0xF800 ) | addr11;"); + } + if ($op_source == 1) { # addr16 + cfw("cpu8051.pc = addr16;"); + } + if ($op_source == 2) { # A + cfw("cpu8051_WriteD( _ACC_, source );"); + } + if ($op_source == 3) { # direct + cfw("cpu8051_WriteD( srcaddr, source );"); + } + if ($op_source == 4) { # @R0 + cfw("cpu8051_WriteI( cpu8051_ReadD( BANKPSW + _R0_ ), source );"); + } + if ($op_source == 5) { # @R1 + cfw("cpu8051_WriteI( cpu8051_ReadD( BANKPSW + _R1_ ), source );"); + } + if ($op_source == 6) { # R0 + cfw("cpu8051_WriteD( BANKPSW + _R0_, source );"); + } + if ($op_source == 7) { # R1 + cfw("cpu8051_WriteD( BANKPSW + _R1_, source );"); + } + if ($op_source == 8) { # R2 + cfw("cpu8051_WriteD( BANKPSW + _R2_, source );"); + } + if ($op_source == 9) { # R3 + cfw("cpu8051_WriteD( BANKPSW + _R3_, source );"); + } + if ($op_source == 10) { # R4 + cfw("cpu8051_WriteD( BANKPSW + _R4_, source );"); + } + if ($op_source == 11) { # R5 + cfw("cpu8051_WriteD( BANKPSW + _R5_, source );"); + } + if ($op_source == 12) { # R6 + cfw("cpu8051_WriteD( BANKPSW + _R6_, source );"); + } + if ($op_source == 13) { # R7 + cfw("cpu8051_WriteD( BANKPSW + _R7_, source );"); + } + if ($op_source == 14) { # bitaddr + cfw("cpu8051_WriteB( srcbitaddr, source );"); + } + if ($op_source == 17) { # C + cfw("psw_write_cy(source);"); + } + if ($op_source == 21) { # DPTR + cfw("memory_sfr_write_dptr(source);"); + } + if ($op_source == 23) { # /bitaddr + cfw("cpu8051_WriteB( srcbitaddr, source );"); + } + if ($op_source == 24) { # @DPTR + cfw("cpu8051_WriteI(memory_sfr_read_dptr(), source);"); + } + } + } + } + cfw("return $a_cycles[$i];"); + print INST_IMP "}\n"; + print INST_IMP "\n"; +} +# ------------------------------------------------------------------------------ + + +# Header for instructions_8051.h +print INST_DEF "/*\n"; +print INST_DEF " * instructions_8051.h\n"; +write_header(INST_DEF); +print INST_DEF "#ifndef INSTRUCTIONS_8051_H\n"; +print INST_DEF "#define INSTRUCTIONS_8051_H 1\n\n\n"; +print INST_DEF "#define BANKPSW (cpu8051_ReadD(_PSW_) & 0x18)\n\n"; +print INST_DEF "typedef int (*OPCODE_FP)(void);\n\n\n"; +for( $i=0; $i<256; $i++ ) { + print INST_DEF "int\n"; + print INST_DEF "cpu8051_OP_$a_opcodehex[$i](void);\n\n"; +} +print INST_DEF "\n"; +print INST_DEF "/* Exported variables. */\n"; +print INST_DEF "#ifdef INSTRUCTIONS_8051_M\n"; +print INST_DEF "OPCODE_FP opcode_table[256] = {\n"; +for( $i=0; $i<256; $i++ ) { + $ifunc=substr($instfunction[$i], 9); + if( $i < 255 ) { + print INST_DEF " cpu8051_$ifunc,\n"; + } + else { + print INST_DEF " cpu8051_$ifunc\n"; + print INST_DEF "};\n"; + } +} + +print INST_DEF "#else\n"; +print INST_DEF "OPCODE_FP opcode_table[256];\n"; +print INST_DEF "#endif\n\n\n"; + +print INST_DEF "#endif /* INSTRUCTIONS_8051_H */\n"; + +print DISASM_H "#endif /* DISASM_H */\n"; + +close DISASM_H; +close OPCODELST; +close INST_DEF; +close INST_IMP; diff --git a/src/common/opcodes.lst b/src/common/opcodes.lst new file mode 100644 index 0000000..1494258 --- /dev/null +++ b/src/common/opcodes.lst @@ -0,0 +1,258 @@ +Opcode(bin) Opcode Instruction Bytes Cycles +-------------------------------------------------------------- +00000000 00 NOP 1 1 +00000001 01 AJMP addr11 2 2 +00000010 02 LJMP addr16 3 2 +00000011 03 RR A 1 1 +00000100 04 INC A 1 1 +00000101 05 INC direct 2 1 +00000110 06 INC @R0 1 1 +00000111 07 INC @R1 1 1 +00001000 08 INC R0 1 1 +00001001 09 INC R1 1 1 +00001010 0A INC R2 1 1 +00001011 0B INC R3 1 1 +00001100 0C INC R4 1 1 +00001101 0D INC R5 1 1 +00001110 0E INC R6 1 1 +00001111 0F INC R7 1 1 +00010000 10 JBC bitaddr,reladdr 3 2 +00010001 11 ACALL addr11 2 2 +00010010 12 LCALL addr16 3 2 +00010011 13 RRC A 1 1 +00010100 14 DEC A 1 1 +00010101 15 DEC direct 2 1 +00010110 16 DEC @R0 1 1 +00010111 17 DEC @R1 1 1 +00011000 18 DEC R0 1 1 +00011001 19 DEC R1 1 1 +00011010 1A DEC R2 1 1 +00011011 1B DEC R3 1 1 +00011100 1C DEC R4 1 1 +00011101 1D DEC R5 1 1 +00011110 1E DEC R6 1 1 +00011111 1F DEC R7 1 1 +00100000 20 JB bitaddr,reladdr 3 2 +00100001 21 AJMP addr11 2 2 +00100010 22 RET 1 2 +00100011 23 RL A 1 1 +00100100 24 ADD A,#data 2 1 +00100101 25 ADD A,direct 2 1 +00100110 26 ADD A,@R0 1 1 +00100111 27 ADD A,@R1 1 1 +00101000 28 ADD A,R0 1 1 +00101001 29 ADD A,R1 1 1 +00101010 2A ADD A,R2 1 1 +00101011 2B ADD A,R3 1 1 +00101100 2C ADD A,R4 1 1 +00101101 2D ADD A,R5 1 1 +00101110 2E ADD A,R6 1 1 +00101111 2F ADD A,R7 1 1 +00110000 30 JNB bitaddr,reladdr 3 2 +00110001 31 ACALL addr11 2 2 +00110010 32 RETI 1 2 +00110011 33 RLC A 1 1 +00110100 34 ADDC A,#data 2 1 +00110101 35 ADDC A,direct 2 1 +00110110 36 ADDC A,@R0 1 1 +00110111 37 ADDC A,@R1 1 1 +00111000 38 ADDC A,R0 1 1 +00111001 39 ADDC A,R1 1 1 +00111010 3A ADDC A,R2 1 1 +00111011 3B ADDC A,R3 1 1 +00111100 3C ADDC A,R4 1 1 +00111101 3D ADDC A,R5 1 1 +00111110 3E ADDC A,R6 1 1 +00111111 3F ADDC A,R7 1 1 +01000000 40 JC reladdr 2 2 +01000001 41 AJMP addr11 2 2 +01000010 42 ORL direct,A 2 1 +01000011 43 ORL direct,#data 3 2 +01000100 44 ORL A,#data 2 1 +01000101 45 ORL A,direct 2 1 +01000110 46 ORL A,@R0 1 1 +01000111 47 ORL A,@R1 1 1 +01001000 48 ORL A,R0 1 1 +01001001 49 ORL A,R1 1 1 +01001010 4A ORL A,R2 1 1 +01001011 4B ORL A,R3 1 1 +01001100 4C ORL A,R4 1 1 +01001101 4D ORL A,R5 1 1 +01001110 4E ORL A,R6 1 1 +01001111 4F ORL A,R7 1 1 +01010000 50 JNC reladdr 2 2 +01010001 51 ACALL addr11 2 2 +01010010 52 ANL direct,A 2 1 +01010011 53 ANL direct,#data 3 2 +01010100 54 ANL A,#data 2 1 +01010101 55 ANL A,direct 2 1 +01010110 56 ANL A,@R0 1 1 +01010111 57 ANL A,@R1 1 1 +01011000 58 ANL A,R0 1 1 +01011001 59 ANL A,R1 1 1 +01011010 5A ANL A,R2 1 1 +01011011 5B ANL A,R3 1 1 +01011100 5C ANL A,R4 1 1 +01011101 5D ANL A,R5 1 1 +01011110 5E ANL A,R6 1 1 +01011111 5F ANL A,R7 1 1 +01100000 60 JZ reladdr 2 2 +01100001 61 AJMP addr11 2 2 +01100010 62 XRL direct,A 2 1 +01100011 63 XRL direct,#data 3 2 +01100100 64 XRL A,#data 2 1 +01100101 65 XRL A,direct 2 1 +01100110 66 XRL A,@R0 1 1 +01100111 67 XRL A,@R1 1 1 +01101000 68 XRL A,R0 1 1 +01101001 69 XRL A,R1 1 1 +01101010 6A XRL A,R2 1 1 +01101011 6B XRL A,R3 1 1 +01101100 6C XRL A,R4 1 1 +01101101 6D XRL A,R5 1 1 +01101110 6E XRL A,R6 1 1 +01101111 6F XRL A,R7 1 1 +01110000 70 JNZ reladdr 2 2 +01110001 71 ACALL addr11 2 2 +01110010 72 ORL C,bitaddr 2 2 +01110011 73 JMP @A+DPTR 1 2 +01110100 74 MOV A,#data 2 1 +01110101 75 MOV direct,#data 3 2 +01110110 76 MOV @R0,#data 2 1 +01110111 77 MOV @R1,#data 2 1 +01111000 78 MOV R0,#data 2 1 +01111001 79 MOV R1,#data 2 1 +01111010 7A MOV R2,#data 2 1 +01111011 7B MOV R3,#data 2 1 +01111100 7C MOV R4,#data 2 1 +01111101 7D MOV R5,#data 2 1 +01111110 7E MOV R6,#data 2 1 +01111111 7F MOV R7,#data 2 1 +10000000 80 SJMP reladdr 2 2 +10000001 81 AJMP addr11 2 2 +10000010 82 ANL C,bitaddr 2 1 +10000011 83 MOVC A,@A+PC 1 1 +10000100 84 DIV AB 1 4 +10000101 85 MOV direct,direct 3 1 +10000110 86 MOV direct,@R0 2 2 +10000111 87 MOV direct,@R1 2 2 +10001000 88 MOV direct,R0 2 2 +10001001 89 MOV direct,R1 2 2 +10001010 8A MOV direct,R2 2 2 +10001011 8B MOV direct,R3 2 2 +10001100 8C MOV direct,R4 2 2 +10001101 8D MOV direct,R5 2 2 +10001110 8E MOV direct,R6 2 2 +10001111 8F MOV direct,R7 2 2 +10010000 90 MOV DPTR,#data16 3 2 +10010001 91 ACALL addr11 2 2 +10010010 92 MOV bitaddr,C 2 2 +10010011 93 MOVC A,@A+DPTR 1 2 +10010100 94 SUBB A,#data 2 1 +10010101 95 SUBB A,direct 2 1 +10010110 96 SUBB A,@R0 1 1 +10010111 97 SUBB A,@R1 1 1 +10011000 98 SUBB A,R0 1 1 +10011001 99 SUBB A,R1 1 1 +10011010 9A SUBB A,R2 1 1 +10011011 9B SUBB A,R3 1 1 +10011100 9C SUBB A,R4 1 1 +10011101 9D SUBB A,R5 1 1 +10011110 9E SUBB A,R6 1 1 +10011111 9F SUBB A,R7 1 1 +10100000 A0 ORL C,/bitaddr 2 1 +10100001 A1 AJMP addr11 2 2 +10100010 A2 MOV C,bitaddr 2 1 +10100011 A3 INC DPTR 1 2 +10100100 A4 MUL AB 1 4 +10100101 A5 INVALID 1 1 +10100110 A6 MOV @R0,direct 2 2 +10100111 A7 MOV @R1,direct 2 2 +10101000 A8 MOV R0,direct 2 2 +10101001 A9 MOV R1,direct 2 2 +10101010 AA MOV R2,direct 2 2 +10101011 AB MOV R3,direct 2 2 +10101100 AC MOV R4,direct 2 2 +10101101 AD MOV R5,direct 2 2 +10101110 AE MOV R6,direct 2 2 +10101111 AF MOV R7,direct 2 2 +10110000 B0 ANL C,/bitaddr 2 1 +10110001 B1 ACALL addr11 2 2 +10110010 B2 CPL bitaddr 2 1 +10110011 B3 CPL C 1 1 +10110100 B4 CJNE A,#data,reladdr 3 2 +10110101 B5 CJNE A,direct,reladdr 3 2 +10110110 B6 CJNE @R0,#data,reladdr 3 2 +10110111 B7 CJNE @R1,#data,reladdr 3 2 +10111000 B8 CJNE R0,#data,reladdr 3 2 +10111001 B9 CJNE R1,#data,reladdr 3 2 +10111010 BA CJNE R2,#data,reladdr 3 2 +10111011 BB CJNE R3,#data,reladdr 3 2 +10111100 BC CJNE R4,#data,reladdr 3 2 +10111101 BD CJNE R5,#data,reladdr 3 2 +10111110 BE CJNE R6,#data,reladdr 3 2 +10111111 BF CJNE R7,#data,reladdr 3 2 +11000000 C0 PUSH direct 2 2 +11000001 C1 AJMP addr11 2 2 +11000010 C2 CLR bitaddr 2 1 +11000011 C3 CLR C 1 1 +11000100 C4 SWAP A 1 1 +11000101 C5 XCH A,direct 2 1 +11000110 C6 XCH A,@R0 1 1 +11000111 C7 XCH A,@R1 1 1 +11001000 C8 XCH A,R0 1 1 +11001001 C9 XCH A,R1 1 1 +11001010 CA XCH A,R2 1 1 +11001011 CB XCH A,R3 1 1 +11001100 CC XCH A,R4 1 1 +11001101 CD XCH A,R5 1 1 +11001110 CE XCH A,R6 1 1 +11001111 CF XCH A,R7 1 1 +11010000 D0 POP direct 2 2 +11010001 D1 ACALL addr11 2 2 +11010010 D2 SETB bitaddr 2 1 +11010011 D3 SETB C 1 1 +11010100 D4 DA A 1 1 +11010101 D5 DJNZ direct,reladdr 3 2 +11010110 D6 XCHD A,@R0 1 1 +11010111 D7 XCHD A,@R1 1 1 +11011000 D8 DJNZ R0,reladdr 2 2 +11011001 D9 DJNZ R1,reladdr 2 2 +11011010 DA DJNZ R2,reladdr 2 2 +11011011 DB DJNZ R3,reladdr 2 2 +11011100 DC DJNZ R4,reladdr 2 2 +11011101 DD DJNZ R5,reladdr 2 2 +11011110 DE DJNZ R6,reladdr 2 2 +11011111 DF DJNZ R7,reladdr 2 2 +11100000 E0 MOVX A,@DPTR 1 2 +11100001 E1 AJMP addr11 2 2 +11100010 E2 MOVX A,@R0 1 2 +11100011 E3 MOVX A,@R1 1 2 +11100100 E4 CLR A 1 1 +11100101 E5 MOV A,direct 2 1 +11100110 E6 MOV A,@R0 1 1 +11100111 E7 MOV A,@R1 1 1 +11101000 E8 MOV A,R0 1 1 +11101001 E9 MOV A,R1 1 1 +11101010 EA MOV A,R2 1 1 +11101011 EB MOV A,R3 1 1 +11101100 EC MOV A,R4 1 1 +11101101 ED MOV A,R5 1 1 +11101110 EE MOV A,R6 1 1 +11101111 EF MOV A,R7 1 1 +11110000 F0 MOVX @DPTR,A 1 2 +11110001 F1 ACALL addr11 2 2 +11110010 F2 MOVX @R0,A 1 2 +11110011 F3 MOVX @R1,A 1 2 +11110100 F4 CPL A 1 1 +11110101 F5 MOV direct,A 2 1 +11110110 F6 MOV @R0,A 1 1 +11110111 F7 MOV @R1,A 1 1 +11111000 F8 MOV R0,A 1 1 +11111001 F9 MOV R1,A 1 1 +11111010 FA MOV R2,A 1 1 +11111011 FB MOV R3,A 1 1 +11111100 FC MOV R4,A 1 1 +11111101 FD MOV R5,A 1 1 +11111110 FE MOV R6,A 1 1 +11111111 FF MOV R7,A 1 1 diff --git a/src/common/options.c b/src/common/options.c new file mode 100644 index 0000000..420cc85 --- /dev/null +++ b/src/common/options.c @@ -0,0 +1,184 @@ +/* + * options.c -- functions for processing command-line options and arguments + * + * Copyright (C) 2011 Hugo Villeneuve + * + * This program 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 of the License, or + * (at your option) any later version. + */ + +#if HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include +#include + +#if STDC_HEADERS +# include +#elif HAVE_STRINGS_H +# include +#endif + +#include "common.h" +#include "options.h" +#include "memory.h" + +const char *argp_program_version = PACKAGE_VERSION; +const char *argp_program_bug_address = PACKAGE_BUGREPORT; + +#define PACKAGE_DOC_LENGTH 128 + +/* Program documentation. */ +static char str_doc[PACKAGE_DOC_LENGTH]; + +/* How many arguments we accept. */ +#define ARGS_COUNT 1 + +/* A description of the arguments we accept. */ +static const char args_doc[] = "[FILENAME]"; + +/* The options we understand. */ +static struct argp_option argp_options[] = { + {"debug", 'd', "level", 0, "Produce debugging output" }, + {"pram", 'p', "size", 0, "Set program memory size" }, + {"xram", 'x', "size", 0, "Set external ram size (default is 1024)" }, + {"stop", 's', "addr", 0, "Automatically run program and stop at address" }, + { 0 } +}; + +struct options_t options; + +const char * +get_package_description(void) +{ + return "Emulator for 8051 family microcontrollers"; +} + +static void +decode_debug_option(char *arg, struct argp_state *state) +{ + char *endptr; + int log_level; + + log_level = strtol(arg, &endptr, 0); + + if (*endptr != '\0') { + log_err("Invalid log level"); + argp_usage(state); + } + + if (log_level > LOG_LEVEL_DEBUG) { + log_err("Invalid log level (0 to 3)"); + argp_usage(state); + } + + options.log = log_level; +} + +static void +decode_memory_size(char *arg, struct argp_state *state, int memid) +{ + char *endptr; + int *dest; + + if (memid == PGM_MEM_ID) + dest = &options.pram_size; + else if (memid == INT_MEM_ID) + dest = &options.iram_size; + else if (memid == EXT_MEM_ID) + dest = &options.xram_size; + else + exit(1); /* Programming error. */ + + /* + * Sizes versus max memory sizes will be checked when calling + * memory_init(). + */ + *dest = strtol(arg, &endptr, 0); + + if (*endptr != '\0') { + log_err("Invalid memory size"); + argp_usage(state); + } +} + +static void +decode_address(char *arg, struct argp_state *state, uint16_t *dest) +{ + char *endptr; + + *dest = strtol(arg, &endptr, 0); + + if (*endptr != '\0') { + log_err("Invalid address"); + argp_usage(state); + } +} + +/* Parse a single option. */ +static error_t +parse_opt(int key, char *arg, struct argp_state *state) +{ + switch (key) { + case 'd': + decode_debug_option(arg, state); + break; + case 'i': + decode_memory_size(arg, state, INT_MEM_ID); + break; + case 'p': + decode_memory_size(arg, state, PGM_MEM_ID); + break; + case 's': + decode_address(arg, state, &options.stop_address); + break; + case 'x': + decode_memory_size(arg, state, EXT_MEM_ID); + break; + case ARGP_KEY_ARG: + if (state->arg_num >= ARGS_COUNT) { + /* Too many arguments. */ + argp_usage(state); + } + + options.filename = arg; + break; + case ARGP_KEY_END: + if (state->arg_num < ARGS_COUNT) { + /* Not enough arguments, but the filename is optional. + So no error. */ + } + break; + default: + return ARGP_ERR_UNKNOWN; + } + + return 0; +} + +/* Our argp parser. */ +static struct argp argp = { argp_options, parse_opt, args_doc, str_doc }; + +/* Initializes the different options passed as arguments on the command line. */ +void +parse_command_line_options(int argc, char *argv[]) +{ + snprintf(str_doc, PACKAGE_DOC_LENGTH, "%s -- %s", PACKAGE_NAME, + get_package_description()); + + /* Setting default values. */ + options.filename = NULL; + options.pram_size = PGM_MEM_DEFAULT_SIZE; + options.iram_size = INT_MEM_MAX_SIZE; + options.xram_size = EXT_MEM_DEFAULT_SIZE; + options.log = LOG_LEVEL_ERR; + options.stop_address = 0; /* 0 means stop address is disabled. */ + + /* Parse our arguments. */ + argp_parse(&argp, argc, argv, 0, 0, NULL); +} diff --git a/src/common/options.h b/src/common/options.h new file mode 100644 index 0000000..589c2d5 --- /dev/null +++ b/src/common/options.h @@ -0,0 +1,45 @@ +/* + * options.h + * + * Copyright (C) 1999 Hugo Villeneuve + * + * This program 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 of the License, or + * (at your option) any later version. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef OPTIONS_H +#define OPTIONS_H 1 + +#define COMMAND_LINE_OPTIONS \ + "Usage: " PACKAGE " [OPTION]... [FILENAME]\n" \ + "Simulator/emulator for 8051 family microcontrollers.\n\n" \ + " -h display this help and exit\n" \ + " -version display version information and exit\n" + +struct options_t { + int pram_size; /* Maximum program memory size. */ + int iram_size; /* Maximum internal ram size. */ + int xram_size; /* Maximum external ram size. */ + char *filename; + int log; + uint16_t stop_address; /* Run program up to that adress and exit. */ +} options_t; + +void +parse_command_line_options(int argc, char *argv[]); + +const char * +get_package_description(void); + +#endif /* OPTIONS_H */ diff --git a/src/common/psw.c b/src/common/psw.c new file mode 100644 index 0000000..09352ad --- /dev/null +++ b/src/common/psw.c @@ -0,0 +1,137 @@ +/* + * psw.c + * + * Copyright (C) 2013 Hugo Villeneuve + * + * This program 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 of the License, or + * (at your option) any later version. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "common.h" +#include "reg8051.h" +#include "memory.h" + +/* Returns 0 or 1 */ +int +psw_read_bit(int bit) +{ + return (memory_read8(INT_MEM_ID, _PSW_) >> bit) & 0x01; +} + +void +psw_write_bit(int bit, int val) +{ + u_int8_t psw = memory_read8(INT_MEM_ID, _PSW_); + + if (val) + psw |= (1 << bit); /* Set */ + else + psw &= ~(1 << bit); /* Clear */ + + memory_write8(INT_MEM_ID, _PSW_, psw); /* Save updated value */ +} + +/* Returns 0 or 1 */ +int +psw_read_cy(void) +{ + return psw_read_bit(PSW_BIT_CY); +} + +void +psw_write_cy(int cy) +{ + psw_write_bit(PSW_BIT_CY, cy); +} + +void +psw_set_cy(void) +{ + psw_write_bit(PSW_BIT_CY, 1); +} + +void +psw_clr_cy(void) +{ + psw_write_bit(PSW_BIT_CY, 0); +} + +/* Returns 0 or 1 */ +int +psw_read_ac(void) +{ + return psw_read_bit(PSW_BIT_AC); +} + +void +psw_write_ac(int ac) +{ + psw_write_bit(PSW_BIT_AC, ac); +} + +void +psw_set_ac(void) +{ + psw_write_bit(PSW_BIT_AC, 1); +} + +void +psw_clr_ac(void) +{ + psw_write_bit(PSW_BIT_AC, 0); +} + +/* Returns 0 or 1 */ +int +psw_read_ov(void) +{ + return psw_read_bit(PSW_BIT_OV); +} + +void +psw_write_ov(int ov) +{ + psw_write_bit(PSW_BIT_OV, ov); +} + +void +psw_set_ov(void) +{ + psw_write_bit(PSW_BIT_OV, 1); +} + +void +psw_clr_ov(void) +{ + psw_write_bit(PSW_BIT_OV, 0); +} + +/* + * Compute parity of bits in accumulator: + * parity = 0: even number of ones in accumulator + * parity = 1: odd number of ones in accumulator + */ +void +psw_compute_parity_bit(void) +{ + int parity = 0; + uint8_t acc = memory_read8(INT_MEM_ID, _ACC_); + + while (acc) { + parity = !parity; + acc = acc & (acc - 1); + } + + psw_write_bit(PSW_BIT_P, parity); +} diff --git a/src/common/psw.h b/src/common/psw.h new file mode 100644 index 0000000..f2c09ba --- /dev/null +++ b/src/common/psw.h @@ -0,0 +1,71 @@ +/* + * psw.h + * + * Copyright (C) 2013 Hugo Villeneuve + * + * This program 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 of the License, or + * (at your option) any later version. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef PSW_H +#define PSW_H 1 + +#include + +int +psw_read_bit(int bit); + +void +psw_write_bit(int bit, int val); + +int +psw_read_cy(void); + +void +psw_write_cy(int cy); + +void +psw_clr_cy(void); + +void +psw_set_cy(void); + +int +psw_read_ac(void); + +void +psw_write_ac(int ac); + +void +psw_clr_ac(void); + +void +psw_set_ac(void); + +int +psw_read_ov(void); + +void +psw_write_ov(int ov); + +void +psw_clr_ov(void); + +void +psw_set_ov(void); + +void +psw_compute_parity_bit(void); + +#endif /* PSW_H */ diff --git a/src/common/reg8051.h b/src/common/reg8051.h new file mode 100644 index 0000000..b484246 --- /dev/null +++ b/src/common/reg8051.h @@ -0,0 +1,75 @@ +/* + * reg8051.h + * + * Copyright (C) 1999 Jonathan St-André + * Copyright (C) 1999 Hugo Villeneuve + * + * This program 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 of the License, or + * (at your option) any later version. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef REG8051_H +#define REG8051_H 1 + +/* SFR Registers ( $80 - $FF ) */ +#define _ACC_ 0xE0 +#define _B_ 0xF0 +#define _PSW_ 0xD0 +#define _SP_ 0x81 +#define _DPTRLOW_ _DPL_ +#define _DPTRHIGH_ _DPH_ +#define _DPL_ 0x82 +#define _DPH_ 0x83 +#define _P0_ 0x80 +#define _P1_ 0x90 +#define _P2_ 0xA0 +#define _P3_ 0xB0 +#define _IP_ 0xB8 +#define _IE_ 0xA8 +#define _TMOD_ 0x89 +#define _TCON_ 0x88 +#define _TH0_ 0x8C +#define _TL0_ 0x8A +#define _TH1_ 0x8D +#define _TL1_ 0x8B +#define _SCON_ 0x98 +#define _SBUF_ 0x99 +#define _PCON_ 0x87 +#define _T2CON_ 0xC8 + +#define _R0_ 0x00 +#define _R1_ 0x01 +#define _R2_ 0x02 +#define _R3_ 0x03 +#define _R4_ 0x04 +#define _R5_ 0x05 +#define _R6_ 0x06 +#define _R7_ 0x07 + +#define _BANK0_ 0x00 +#define _BANK1_ 0x08 +#define _BANK2_ 0x10 +#define _BANK3_ 0x18 + +#define PSW_BIT_CY 7 +#define PSW_BIT_AC 6 +#define PSW_BIT_OV 2 +#define PSW_BIT_P 0 + +#define PSW_FLAG_CY (1 << PSW_BIT_CY) +#define PSW_FLAG_AC (1 << PSW_BIT_AC) +#define PSW_FLAG_OV (1 << PSW_BIT_OV) +#define PSW_FLAG_P (1 << PSW_BIT_P) + +#endif /* REG8051_H */ diff --git a/src/common/sfr.c b/src/common/sfr.c new file mode 100644 index 0000000..1bbeb8e --- /dev/null +++ b/src/common/sfr.c @@ -0,0 +1,345 @@ +/* + * sfr.c + * + * Copyright (C) 2013 Hugo Villeneuve + * + * This program 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 of the License, or + * (at your option) any later version. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#if HAVE_CONFIG_H +# include "config.h" +#endif + +#include + +#include "common.h" +#include "reg8051.h" +#include "cpu8051.h" +#include "sfr.h" +#include "memory.h" +#include "instructions_8051.h" + +#define HEX_DIGITS_2 2 +#define HEX_DIGITS_4 4 + +/* Specific read/write functions for special registers. */ + +static unsigned int +regwin_read_pc(int dummy) +{ + return cpu8051.pc; +} + +static void +regwin_write_pc(int param, int val) +{ + cpu8051.pc = (u_int16_t) val; +} + +static unsigned int +regwin_read_timer(int timer_low_addr) +{ + return (memory_sfr_read8(timer_low_addr + 2) << 8) | + memory_sfr_read8(timer_low_addr); +} + +static void +regwin_write_timer(int timer_low_addr, int val) +{ + memory_sfr_write8(timer_low_addr + 2, (u_int8_t) ((val & 0x0000FFFF) >> 8)); + memory_sfr_write8(timer_low_addr, (u_int8_t) val); +} + +static u_int8_t +regwin_read_bank_offset(void) +{ + return memory_sfr_read8(_PSW_) & 0x18; +} + +static unsigned int +regwin_read_bank(int dummy) +{ + return regwin_read_bank_offset() >> 3; +} + +static void +regwin_write_bank(int param, int bank_number) +{ + u_int8_t psw = memory_sfr_read8(_PSW_); + + if ((bank_number < 0) || (bank_number > 3)) { + log_info("Error: invalid bank number: %d", bank_number); + bank_number = 0; + } + + memory_sfr_write8(_PSW_, (psw & ~0x18) | (bank_number << 3)); +} + +/* Indirect read of R0 - R7 in current bank from internal memory. */ +static unsigned int +regwin_read_rx(int offset) +{ + return memory_read8(INT_MEM_ID, regwin_read_bank_offset() + offset); +} + +/* Indirect write to R0 - R7 in current bank to internal memory. */ +static void +regwin_write_rx(int offset, int val) +{ + memory_write8(INT_MEM_ID, regwin_read_bank_offset() + offset, (u_int8_t) val); +} + +/* This array defines how to read value for each register. */ +static struct regwin_infos_t regwin_infos[SFR_REGS] = { + { + "PC", + HEX_DIGITS_4, + regwin_read_pc, regwin_write_pc, + 0, /* Dummy */ + }, + { + "SP", + HEX_DIGITS_2, + NULL, NULL, + _SP_, + }, + { + "PSW", + HEX_DIGITS_2, + NULL, NULL, + _PSW_, + }, + { + "A", + HEX_DIGITS_2, + NULL, NULL, + _ACC_, + }, + { + "B", + HEX_DIGITS_2, + NULL, NULL, + _B_, + }, + { + "DPTR", + HEX_DIGITS_4, + NULL, NULL, + _DPL_, + }, + { + "P0", + HEX_DIGITS_2, + NULL, NULL, + _P0_, + }, + { + "P1", + HEX_DIGITS_2, + NULL, NULL, + _P1_, + }, + { + "P2", + HEX_DIGITS_2, + NULL, NULL, + _P2_, + }, + { + "P3", + HEX_DIGITS_2, + NULL, NULL, + _P3_, + }, + { + "TCON", + HEX_DIGITS_2, + NULL, NULL, + _TCON_, + }, + { + "TMOD", + HEX_DIGITS_2, + NULL, NULL, + _TMOD_, + }, + { + "TIMER0", + HEX_DIGITS_4, + regwin_read_timer, regwin_write_timer, + _TL0_, + }, + { + "TIMER1", + HEX_DIGITS_4, + regwin_read_timer, regwin_write_timer, + _TL1_, + }, + { + "SCON", + HEX_DIGITS_2, + NULL, NULL, + _SCON_, + }, + { + "IE", + HEX_DIGITS_2, + NULL, NULL, + _IE_, + }, + { + "IP", + HEX_DIGITS_2, + NULL, NULL, + _IP_, + }, + { + "BANK", + HEX_DIGITS_2, + regwin_read_bank, regwin_write_bank, + 0, /* Dummy */ + }, + /* R0-R7 Registers in current Bank */ + { + "R0", + HEX_DIGITS_2, + regwin_read_rx, regwin_write_rx, + _R0_, + }, + { + "R1", + HEX_DIGITS_2, + regwin_read_rx, regwin_write_rx, + _R1_, + }, + { + "R2", + HEX_DIGITS_2, + regwin_read_rx, regwin_write_rx, + _R2_, + }, + { + "R3", + HEX_DIGITS_2, + regwin_read_rx, regwin_write_rx, + _R3_, + }, + { + "R4", + HEX_DIGITS_2, + regwin_read_rx, regwin_write_rx, + _R4_, + }, + { + "R5", + HEX_DIGITS_2, + regwin_read_rx, regwin_write_rx, + _R5_, + }, + { + "R6", + HEX_DIGITS_2, + regwin_read_rx, regwin_write_rx, + _R6_, + }, + { + "R7", + HEX_DIGITS_2, + regwin_read_rx, regwin_write_rx, + _R7_, + }, +}; + +/* Generic read/write functions */ +static unsigned int +regwin_read_generic(int addr, int width) +{ + if (width == 2) + return memory_sfr_read8(addr); + else if (width == 4) { + /* Address is low address. */ + return (memory_sfr_read8(addr + 1) << 8) | + memory_sfr_read8(addr); + } else + return 0xFFFFFFFF; +} + +static void +regwin_write_generic(int addr, int val, int width) +{ + if (width == 2) + memory_sfr_write8(addr, (u_int8_t) val); + else if (width == 4) { + /* Address is low address. */ + memory_sfr_write8(addr + 1, (u_int8_t) ((val & 0x0000FFFF) >> 8)); + memory_sfr_write8(addr, (u_int8_t) val); + } +}; + +int +regwin_read(int row) +{ + int val; + + if (regwin_infos[row].read_func == NULL) { + /* + * Read register value using generic 8 or 16 bits read + * function, depending on width. + */ + val = regwin_read_generic(regwin_infos[row].param, + regwin_infos[row].w); + } else { + /* Read register value using custom function pointer. */ + val = regwin_infos[row].read_func( + regwin_infos[row].param); + } + + return val; +} + +void +regwin_write(struct regwin_infos_t *p, int new) +{ + if (p->write_func == NULL) { + /* + * Write register value using generic 8 or 16 bits write + * function, depending on width. + */ + regwin_write_generic(p->param, new, p->w); + } else { + /* Write register value using custom function pointer. */ + p->write_func(p->param, new); + } +} + +struct regwin_infos_t * +sfr_get_infos(const char *regname) +{ + int row; + + for (row = 0; row < SFR_REGS; row++) { + if (strcmp(regwin_infos[row].name, regname) == 0) + return ®win_infos[row]; + } + + return NULL; /* Programming error. */ +} + +struct regwin_infos_t * +sfr_get_infos_from_row(int row) +{ + return ®win_infos[row]; +} + diff --git a/src/common/sfr.h b/src/common/sfr.h new file mode 100644 index 0000000..fe552dd --- /dev/null +++ b/src/common/sfr.h @@ -0,0 +1,46 @@ +/* + * sfr.h + * + * Copyright (C) 2013 Hugo Villeneuve + * + * This program 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 of the License, or + * (at your option) any later version. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef SFR_H +#define SFR_H 1 + +#define SFR_REGS 26 + +struct regwin_infos_t { + char *name; /* Register name */ + int w; /* Number of hex digits to display */ + unsigned int (*read_func)(int addr); /* Function to read value */ + void (*write_func)(int param, int val); /* Function to write value */ + int param; /* Optional parameter to pass to read function. */ +}; + +int +regwin_read(int row); + +void +regwin_write(struct regwin_infos_t *p, int new); + +struct regwin_infos_t * +sfr_get_infos(const char *regname); + +struct regwin_infos_t * +sfr_get_infos_from_row(int row); + +#endif /* SFR_H */ diff --git a/src/common/timers.c b/src/common/timers.c new file mode 100644 index 0000000..68a92bc --- /dev/null +++ b/src/common/timers.c @@ -0,0 +1,144 @@ +/* + * timers.c + * + * Copyright (C) 1999 Jonathan St-André + * Copyright (C) 1999 Hugo Villeneuve + * + * This program 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 of the License, or + * (at your option) any later version. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include +#include +#include +#include "config.h" + +#include "common.h" +#include "reg8051.h" +#include "cpu8051.h" +#include "memory.h" +#include "psw.h" +#include "options.h" +#include "instructions_8051.h" + +extern struct options_t options; + +static void +timer_increment_check_overflow(uint8_t counter_address, uint8_t tf_mask) +{ + unsigned int tmp; + + tmp = cpu8051_ReadD(counter_address); + tmp++; + tmp &= 0xFF; + if (tmp == 0) { + /* If overflow set TFx */ + cpu8051_WriteD(_TCON_, cpu8051_ReadD(_TCON_) | tf_mask); + } + + cpu8051_WriteD(counter_address, tmp); /* Save new value. */ +} + +static void +timer_with_prescaler(uint8_t tl, uint8_t th, uint8_t tf_mask, int prescaler_width) +{ + unsigned int prescaler; + + prescaler = cpu8051_ReadD(tl); + prescaler++; + + prescaler &= (1 << prescaler_width) - 1; /* Keep only required bits */ + cpu8051_WriteD(tl, prescaler); + + if (prescaler == 0) + timer_increment_check_overflow(th, tf_mask); +} + +static void +process_timer(uint8_t tl, uint8_t th, uint8_t tf_mask, uint8_t TR, uint8_t mode, + uint8_t GATE, uint32_t TimerCounter) +{ + unsigned int tmp; + + switch (mode) { + case 0: + /* Mode 0, 8-bit timer "TH" with "TL" as 5-bit prescaler. */ + timer_with_prescaler(tl, th, tf_mask, 5); + break; + case 1: + /* Mode 1, 16-bits counter */ + timer_with_prescaler(tl, th, tf_mask, 8); + break; + case 2: + /* Mode 2, 8-bits counter with Auto-Reload */ + tmp = cpu8051_ReadD(tl); + tmp++; + tmp &= 0xFF; + if (tmp == 0) { + /* If overflow -> reload and set TF0 */ + cpu8051_WriteD(_TCON_, cpu8051_ReadD(_TCON_) | tf_mask); + cpu8051_WriteD(tl, cpu8051_ReadD(th)); + } else + cpu8051_WriteD(tl, tmp); + break; + case 3: + /* + * Mode 3: + * inactive mode for timer 1 + * 2 independents 8-bits timers for timer 0. + */ + + if (tl == _TL1_) + break; + + if (TR && !GATE && !TimerCounter) + timer_increment_check_overflow(tl, tf_mask); + + /* TH0 uses TR1 et TF1. */ + TR = cpu8051_ReadD(_TCON_) & 0x40; + + if (TR) + timer_increment_check_overflow(th, 0x80); + + break; + } +} + +/* Run timers */ +void +timers_check(void) +{ + unsigned int TR; + unsigned int MODE; + unsigned int GATE; + unsigned int TimerCounter; + + /* Timer 0 */ + TR = cpu8051_ReadD(_TCON_) & 0x10; + MODE = cpu8051_ReadD(_TMOD_) & 0x03; + GATE = cpu8051_ReadD(_TMOD_) & 0x08; + TimerCounter = cpu8051_ReadD(_TMOD_) & 0x04; + + if ((TR && !GATE && !TimerCounter) || (MODE == 3)) + process_timer(_TL0_, _TH0_, 0x20, TR, MODE, GATE, TimerCounter); + + /* Timer 1 */ + TR = cpu8051_ReadD(_TCON_) & 0x40; + MODE = (cpu8051_ReadD(_TMOD_) & 0x30) >> 4 ; + GATE = cpu8051_ReadD(_TMOD_) & 0x80; + TimerCounter = cpu8051_ReadD(_TMOD_) & 0x40; + + if (TR && !GATE && !TimerCounter) + process_timer(_TL1_, _TH1_, 0x80, TR, MODE, GATE, TimerCounter); +} diff --git a/src/common/timers.h b/src/common/timers.h new file mode 100644 index 0000000..932ace4 --- /dev/null +++ b/src/common/timers.h @@ -0,0 +1,29 @@ +/* + * timers.h + * + * Copyright (C) 2013 Hugo Villeneuve + * + * This program 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 of the License, or + * (at your option) any later version. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef TIMERS_H +#define TIMERS_H 1 + +#include + +int +timers_check(void); + +#endif /* TIMERS_H */ diff --git a/src/cpu8051.c b/src/cpu8051.c deleted file mode 100644 index bf7bd99..0000000 --- a/src/cpu8051.c +++ /dev/null @@ -1,651 +0,0 @@ -/* - * cpu8051.c - * - * Copyright (C) 1999 Jonathan St-André - * Copyright (C) 1999 Hugo Villeneuve - * - * This program 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 of the License, or - * (at your option) any later version. - * - * This program 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 this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -/* Define only here, for not having extern scope on local variables. */ -#define CPU8051_M 1 - -#include -#include - -#include "reg8051.h" -#include "cpu8051.h" -#include "memory.h" -#include "psw.h" -#include "timers.h" -#include "disasm.h" -#include "options.h" -#include "instructions_8051.h" - -extern struct options_t options; - -/* Check if the address is a breakpoint */ -int -IsBreakpoint(unsigned int address) -{ - int k; - - for (k = 0; k < cpu8051.bp_count; k++) { - if (cpu8051.bp[k] == address) - return 1; - } - - /* The address was not found in the list of breakpoints */ - return 0; -} - -/* Check if the address is a stop point */ -int -IsStoppoint(unsigned int address) -{ - if ((options.stop_address != 0) && (options.stop_address == address)) - return 1; - else - return 0; -} - -/* Show Breakpoints list */ -void -ShowBreakpoints(void) -{ - int k; - - for (k = 0; k < cpu8051.bp_count; k++) - printf("Breakpoint at address = %.4X\n", cpu8051.bp[k]); -} - -/* Set Breakpoint at address at the end of the breakpoint list */ -void -SetBreakpoint(unsigned int address) -{ - if (IsBreakpoint(address)) - return; /* Already a breakpoint */ - - if (cpu8051.bp_count < MAXBP) - cpu8051.bp[cpu8051.bp_count++] = address; -} - -/* Clear Breakpoint at Address from list */ -void -ClearBreakpoint(unsigned int address) -{ - int k; - - for (k = 0; k < cpu8051.bp_count; k++) { - if (cpu8051.bp[k] == address) { - /* Fill removed breakpoint slot with last entry */ - cpu8051.bp[k] = cpu8051.bp[cpu8051.bp_count - 1]; - cpu8051.bp_count--; - } - } -} - -/* Toggle the breakpoint at Address. */ -void -ToggleBreakpoint(unsigned int address) -{ - if (IsBreakpoint(address)) - ClearBreakpoint(address); - else - SetBreakpoint(address); -} - -void -cpu8051_init(void) -{ - memory_init(); - - cpu8051.pc = 0; - cpu8051.clock = 0; - cpu8051.active_priority = -1; - cpu8051.bp_count = 0; -} - -/* Reset the registers and CPU state */ -void -cpu8051_Reset(void) -{ - cpu8051.pc = 0; - cpu8051.clock = 0; - cpu8051.active_priority = -1; - - /* Clear IRAM and SFR. */ - memory_clear(INT_MEM_ID); - - memory_sfr_write8(_P0_, 0xFF); - memory_sfr_write8(_P1_, 0xFF); - memory_sfr_write8(_P2_, 0xFF); - memory_sfr_write8(_P3_, 0xFF); - - /* The default value of SP (after system reset) is 07 */ - memory_sfr_write8(_SP_, 0x07); -} - -static void -cpu8051_convert_bit_address(uint8_t bit_address, uint8_t *byte_address, - uint8_t *bit_number) -{ - if (bit_address > 0x7F) { - /* SFR 80-FF */ - *byte_address = bit_address & 0xF8; - *bit_number = bit_address & 0x07; - } else { - /* 20-2F */ - *byte_address = (bit_address >> 3) + 0x20; - *bit_number = bit_address & 0x07; - } -} - -/* Write with a direct addressing mode at Address the new Value */ -void -cpu8051_WriteD(unsigned int Address, unsigned char Value) -{ - memory_write8(INT_MEM_ID, Address, Value); -} - -/* Write with an indirect addressing mode at Address the new Value */ -void -cpu8051_WriteI(unsigned int Address, unsigned char Value) -{ - if (Address > 0x7F) { - memory_write8(EXT_MEM_ID, Address, Value); - return; - } - - memory_write8(INT_MEM_ID, Address, Value); -} - -/* Write with a bit addressing mode at BitAddress the new Value */ -void -cpu8051_WriteB(uint8_t bit_address, uint8_t value) -{ - uint8_t byte_address; - uint8_t bit_number; - unsigned char ByteValue, ByteMask; - - cpu8051_convert_bit_address(bit_address, &byte_address, &bit_number); - - ByteMask = ((1 << bit_number) ^ 0xFF); - ByteValue = cpu8051_ReadD(byte_address) & ByteMask; - ByteValue += value << bit_number; - cpu8051_WriteD(byte_address, ByteValue); -} - -/* Read with a direct addressing mode at Address */ -unsigned char -cpu8051_ReadD(unsigned int Address) -{ - if (Address > 0xFF) - return memory_read8(EXT_MEM_ID, Address); - else - return memory_read8(INT_MEM_ID, Address); -} - -/* Read with a indirect addressing mode at Address */ -unsigned char -cpu8051_ReadI(unsigned int Address) -{ - if (Address > 0x7F) - return memory_read8(EXT_MEM_ID, Address); - else - return memory_read8(INT_MEM_ID, Address); -} - -/* Read with a bit addressing mode at BitAddress */ -unsigned char -cpu8051_ReadB(uint8_t bit_address) -{ - uint8_t byte_address; - uint8_t bit_number; - unsigned char BitValue; - - cpu8051_convert_bit_address(bit_address, &byte_address, &bit_number); - - BitValue = (cpu8051_ReadD(byte_address) >> bit_number); - BitValue &= 1; - return BitValue; -} - -static int -cpu8051_interrupt_fire(int interrupt_no, int priority) -{ - if (cpu8051_ReadD(_IP_) & INTERRUPT_MASK(interrupt_no)) - return priority; - else - return !priority; -} - -static int -cpu8051_interrupt_enabled(int interrupt_no) -{ - return (cpu8051_ReadD(_IE_) & INTERRUPT_MASK(interrupt_no)) ? 1 : 0; -} - -static void -cpu8051_process_interrupt(int pc, int pri) -{ - stack_push16(cpu8051.pc); - cpu8051.pc = pc; - cpu8051.active_priority = pri; -} - - -/* Check interrupts state and process them as needed */ -static void -cpu8051_CheckInterrupts(void) -{ - int i; - - if ((cpu8051_ReadD(_IE_) & 0x80) == 0) - return; - - for (i = INTERRUPT_PRIORITY_HIGH; i >= INTERRUPT_PRIORITY_LOW; i--) { - if (cpu8051.active_priority < i) { - /* Interrupt timer 0 */ - if (cpu8051_interrupt_enabled(INTERRUPT_1) && - cpu8051_interrupt_fire(INTERRUPT_1, i) && - (cpu8051_ReadD(_TCON_) & 0x20)) { - cpu8051_WriteD(_TCON_, - cpu8051_ReadD(_TCON_) & 0xDF); - cpu8051_process_interrupt(0x0B, i); - return; - } - /* Interrupt timer 1 */ - if (cpu8051_interrupt_enabled(INTERRUPT_3) && - cpu8051_interrupt_fire(INTERRUPT_3, i) && - (cpu8051_ReadD(_TCON_) & 0x80)) { - cpu8051_WriteD(_TCON_, - cpu8051_ReadD(_TCON_) & 0x7F); - cpu8051_process_interrupt(0x1B, i); - return; - } - /* Serial Interrupts */ - if (cpu8051_interrupt_enabled(INTERRUPT_4) && - cpu8051_interrupt_fire(INTERRUPT_4, i) && - (cpu8051_ReadD(_SCON_) & 0x03)) { - cpu8051_process_interrupt(0x23, i); - return; - } - /* Interrupt timer 2 */ - if (cpu8051_interrupt_enabled(INTERRUPT_5) && - cpu8051_interrupt_fire(INTERRUPT_5, i) && - (cpu8051_ReadD(_T2CON_) & 0x80)) { - cpu8051_process_interrupt(0x2B, i); - return; - } - } - } -} - -/* Execute at address cpu8051.pc from PGMMem */ -void -cpu8051_Exec(void) -{ - int i; - unsigned char opcode; - int insttiming; - - opcode = memory_read8(PGM_MEM_ID, cpu8051.pc); - cpu8051.pc++; - insttiming = (*opcode_table[opcode])(); /* Function callback. */ - - /* - * Parity bit (p): is automatically set or cleared in each machine - * cycle to establish even parity in the accumulator. - */ - psw_compute_parity_bit(); - - for (i = 0; i < insttiming; i++) { - cpu8051_CheckInterrupts(); - timers_check(); - cpu8051.clock++; - } -} - -/* - * Addressing modes defined in the order as they appear in disasm.h - * from table argstext[] - */ -#define ADDR11 0 -#define ADDR16 1 -#define DIRECT 3 -#define BITADDR 14 -#define RELADDR 15 -#define DATAIMM 16 -#define DATA16 22 -#define CBITADDR 23 - -/* - * SFR Memory map [80h - FFh] - * --------------------------------------------------------------- - * F8 | | | | | | | | | FF - * F0 | B | | | | | | | | F7 - * E8 | | | | | | | | | EF - * E0 | ACC | | | | | | | | E7 - * D8 | | | | | | | | | DF - * D0 | PSW | | | | | | | | D7 - * C8 | T2CON| |RCAP2L|RCAP2H| TL2 | TH2 | | | CF - * C0 | | | | | | | | | C7 - * B8 | IP | | | | | | | | BF - * B0 | P3 | | | | | | | | B7 - * A8 | IE | | | | | | | | AF - * A0 | P2 | | | | | | | | A7 - * 98 | SCON | SBUF | | | | | | | 9F - * 90 | P1 | | | | | | | | 97 - * 88 | TCON | TMOD | TL0 | TL1 | TH0 | TH1 | | | 8F - * 80 | P0 | SP | DPL | DPH | | | | PCON | 87 - * --------------------------------------------------------------- - */ - -/* Return as Text the name of the SFR register at Address if any */ -static int -cpu8051_SFRMemInfo(unsigned int Address, char *Text) -{ - switch (Address) { - case 0x80: return sprintf(Text, "P0"); - case 0x81: return sprintf(Text, "SP"); - case 0x82: return sprintf(Text, "DPL"); - case 0x83: return sprintf(Text, "DPH"); - case 0x87: return sprintf(Text, "PCON"); - case 0x88: return sprintf(Text, "TCON"); - case 0x89: return sprintf(Text, "TMOD"); - case 0x8A: return sprintf(Text, "TL0"); - case 0x8B: return sprintf(Text, "TL1"); - case 0x8C: return sprintf(Text, "TH0"); - case 0x8D: return sprintf(Text, "TH1"); - case 0x90: return sprintf(Text, "P1"); - case 0x98: return sprintf(Text, "SCON"); - case 0x99: return sprintf(Text, "SBUF"); - case 0xA0: return sprintf(Text, "P2"); - case 0xA8: return sprintf(Text, "IE"); - case 0xB0: return sprintf(Text, "P3"); - case 0xB8: return sprintf(Text, "IP"); - case 0xC8: return sprintf(Text, "T2CON"); - case 0xCA: return sprintf(Text, "RCAP2L"); - case 0xCB: return sprintf(Text, "RCAP2H"); - case 0xCC: return sprintf(Text, "TL2"); - case 0xCD: return sprintf(Text, "TH2"); - case 0xD0: return sprintf(Text, "PSW"); - case 0xE0: return sprintf(Text, "ACC"); - case 0xF0: return sprintf(Text, "B"); - default: return sprintf(Text, "%.2XH", Address); - } -} - -/* Return as Text the decoded BitAddress */ -static void -cpu8051_IntMemBitInfo(uint8_t bit_address, char *text) -{ - uint8_t byte_address; - uint8_t bit_number; - int len; - - cpu8051_convert_bit_address(bit_address, &byte_address, &bit_number); - - len = cpu8051_SFRMemInfo(byte_address, text); - sprintf(&text[len], ".%X", bit_address); -} - -/* Get instruction size from opcode */ -int -cpu8051_get_instruction_size(unsigned char opcode) -{ - return InstSizesTbl[opcode]; -} - -/* Display instruction mnemonic. */ -void -cpu8051_disasm_mnemonic(unsigned char OpCode, char *buf) -{ - sprintf(buf, "%s", InstTextTbl[InstTypesTbl[OpCode]]); -} - -/* Disasm instruction arguments starting at address into a text string */ -void -cpu8051_disasm_args(unsigned int address, char *buf) -{ - int len = 0; - char TextTmp[20]; - unsigned char OpCode; - int ArgTblOfs; - int i; - - OpCode = memory_read8(PGM_MEM_ID, address); - ArgTblOfs = OpCode << 2; - address++; - - /* - * MOV direct, direct (OpCode 85h) is peculiar, the operands - * are inverted - */ - if (OpCode == 0x85) { - cpu8051_SFRMemInfo(memory_read8(PGM_MEM_ID, address + 1), - TextTmp); - len += sprintf(&buf[len], "%s,", TextTmp); - cpu8051_SFRMemInfo(memory_read8(PGM_MEM_ID, address), - TextTmp); - len += sprintf(&buf[len], "%s", TextTmp); - address += 2; - return; - } - - for (i = 1; i <= InstArgTbl[ArgTblOfs]; i++) { - switch (InstArgTbl[ArgTblOfs + i]) { - case ADDR11: { - len += sprintf(&buf[len], - "%.4XH", ((OpCode << 3) & 0xF00) + - (memory_read8(PGM_MEM_ID, address))); - address++; - break; - } - case ADDR16: { - len += sprintf( - &buf[len], "%.4XH", - ((memory_read8(PGM_MEM_ID, address) << 8) + - memory_read8(PGM_MEM_ID, address + 1))); - address += 2; - break; - } - case DIRECT: { - cpu8051_SFRMemInfo(memory_read8(PGM_MEM_ID, address), - TextTmp); - len += sprintf(&buf[len], "%s", TextTmp); - address++; - break; - } - case BITADDR: { - cpu8051_IntMemBitInfo( - (memory_read8(PGM_MEM_ID, address) & 0xF8), - TextTmp); - len += sprintf(&buf[len], "%s.%X" , TextTmp, - (memory_read8(PGM_MEM_ID, address) & 7)); - address++; - break; - } - case RELADDR: { - address++; - len += sprintf(&buf[len], "%.4XH", (address & 0xFF00) + - (((address & 0xFF) + - memory_read8(PGM_MEM_ID, - address - 1)) & 0xFF)); - break; - } - case DATAIMM: { - len += sprintf(&buf[len], "#%.2XH", - memory_read8(PGM_MEM_ID, address)); - address++; - break; - } - case DATA16: { - len += sprintf(&buf[len], "#%.4XH", - ((memory_read8(PGM_MEM_ID, - address) << 8) + - memory_read8(PGM_MEM_ID, address+1))); - address += 2; - break; - } - case CBITADDR: { - cpu8051_IntMemBitInfo((memory_read8(PGM_MEM_ID, - address) & 0xF8), - TextTmp); - len += sprintf(&buf[len], "/%s.%X", TextTmp, - (memory_read8(PGM_MEM_ID, address) & 7)); - address++; - break; - } - default: { - len += sprintf(&buf[len], "%s", - ArgsTextTbl[InstArgTbl[ArgTblOfs + i]]); - } - } - if (i < InstArgTbl[ArgTblOfs]) - len += sprintf(&buf[len], ","); - } -} - -/* Disasm one instruction at Address into a Text string */ -int -cpu8051_Disasm(unsigned int Address, char *Text) -{ - int len = 0; - char TextTmp[20]; - unsigned char OpCode; - int ArgTblOfs; - int InstSize; - int i; - - /* Display address. */ - len += sprintf(Text, " %.4X ", Address); - - OpCode = memory_read8(PGM_MEM_ID, Address); - InstSize = InstSizesTbl[OpCode]; - - /* Display hex bytes. */ - for (i = 0; i < InstSize; i++) - len += sprintf(&Text[len], " %.2X", - memory_read8(PGM_MEM_ID, Address + i)); - - Address++; - - /* Padd remaining area with spaces. */ - for (; len < 17;) - len += sprintf(&Text[len], " "); - - /* Display instruction mnemonic. */ - len += sprintf(&Text[len], "%s ", - InstTextTbl[InstTypesTbl[OpCode]]); - ArgTblOfs = OpCode << 2; - - /* Padd remaining area with spaces. */ - for (; len < 25;) - len += sprintf(&Text[len], " "); - - /* Display instruction arguments. */ - - /* - * MOV direct, direct (OpCode 85h) is peculiar, the operands - * are inverted - */ - if (OpCode == 0x85) { - cpu8051_SFRMemInfo(memory_read8(PGM_MEM_ID, Address + 1), - TextTmp); - len += sprintf(&Text[len], "%s,", TextTmp); - cpu8051_SFRMemInfo(memory_read8(PGM_MEM_ID, Address), - TextTmp); - len += sprintf(&Text[len], "%s", TextTmp); - Address += 2; - return InstSize; - } - - for (i = 1; i <= InstArgTbl[ArgTblOfs]; i++) { - switch (InstArgTbl[ArgTblOfs + i]) { - case ADDR11: { - len += sprintf(&Text[len], - "%.4XH", ((OpCode << 3) & 0xF00) + - (memory_read8(PGM_MEM_ID, Address))); - Address++; - break; - } - case ADDR16: { - len += sprintf( - &Text[len], "%.4XH", - ((memory_read8(PGM_MEM_ID, Address) << 8) + - memory_read8(PGM_MEM_ID, Address + 1))); - Address += 2; - break; - } - case DIRECT: { - cpu8051_SFRMemInfo(memory_read8(PGM_MEM_ID, Address), - TextTmp); - len += sprintf(&Text[len], "%s", TextTmp); - Address++; - break; - } - case BITADDR: { - cpu8051_IntMemBitInfo( - (memory_read8(PGM_MEM_ID, Address) & 0xF8), - TextTmp); - len += sprintf(&Text[len], "%s.%X" , TextTmp, - (memory_read8(PGM_MEM_ID, Address) & 7)); - Address++; - break; - } - case RELADDR: { - Address++; - len += sprintf(&Text[len], "%.4XH", (Address & 0xFF00) + - (((Address & 0xFF) + - memory_read8(PGM_MEM_ID, - Address - 1)) & 0xFF)); - break; - } - case DATAIMM: { - len += sprintf(&Text[len], "#%.2XH", - memory_read8(PGM_MEM_ID, Address)); - Address++; - break; - } - case DATA16: { - len += sprintf(&Text[len], "#%.4XH", - ((memory_read8(PGM_MEM_ID, - Address) << 8) + - memory_read8(PGM_MEM_ID, Address+1))); - Address += 2; - break; - } - case CBITADDR: { - cpu8051_IntMemBitInfo((memory_read8(PGM_MEM_ID, - Address) & 0xF8), - TextTmp); - len += sprintf(&Text[len], "/%s.%X", TextTmp, - (memory_read8(PGM_MEM_ID, Address) & 7)); - Address++; - break; - } - default: { - len += sprintf(&Text[len], "%s", - ArgsTextTbl[InstArgTbl[ArgTblOfs + i]]); - } - } - if (i < InstArgTbl[ArgTblOfs]) - len += sprintf(&Text[len], ","); - } - - return InstSize; -} diff --git a/src/cpu8051.h b/src/cpu8051.h deleted file mode 100644 index adb96c8..0000000 --- a/src/cpu8051.h +++ /dev/null @@ -1,116 +0,0 @@ -/* - * cpu8051.h - * - * Copyright (C) 1999 Jonathan St-André - * Copyright (C) 1999 Hugo Villeneuve - * - * This program 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 of the License, or - * (at your option) any later version. - * - * This program 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 this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#ifndef CPU8051_H -#define CPU8051_H 1 - -#include - -/* Maximum number of BreakPoints */ -#define MAXBP 32 - -#define INTERRUPT_0 (0) -#define INTERRUPT_1 (1) -#define INTERRUPT_2 (2) -#define INTERRUPT_3 (3) -#define INTERRUPT_4 (4) -#define INTERRUPT_5 (5) -#define INTERRUPT_MASK(n) (1 << n) - -#define INTERRUPT_PRIORITY_HIGH (1) -#define INTERRUPT_PRIORITY_LOW (0) - -struct cpu8051_t { - unsigned int pc; /* Program counter */ - unsigned long clock; - int active_priority; - int bp_count; - unsigned int bp[MAXBP]; /* List of breakpoints */ -}; - -/* Exported variables */ -#undef _SCOPE_ -#ifdef CPU8051_M -# define _SCOPE_ /**/ -#else -# define _SCOPE_ extern -#endif - -_SCOPE_ struct cpu8051_t cpu8051; - -int -IsBreakpoint(unsigned int Address); - -int -IsStoppoint(unsigned int address); - -void -ShowBreakpoints(void); - -void -SetBreakpoint(unsigned int Address); - -void -ClearBreakpoint(unsigned int Address); - -void -ToggleBreakpoint(unsigned int Address); - -void -cpu8051_init(void); - -void -cpu8051_Exec(void); - -void -cpu8051_Reset(void); - -void -cpu8051_WriteD(unsigned int Address, unsigned char Value); - -void -cpu8051_WriteI(unsigned int Address, unsigned char Value); - -void -cpu8051_WriteB(uint8_t bit_address, uint8_t value); - -unsigned char -cpu8051_ReadD(unsigned int Address); - -unsigned char -cpu8051_ReadI(unsigned int Address); - -unsigned char -cpu8051_ReadB(uint8_t bit_address); - -int -cpu8051_get_instruction_size(unsigned char opcode); - -void -cpu8051_disasm_mnemonic(unsigned char OpCode, char *buf); - -void -cpu8051_disasm_args(unsigned int address, char *buf); - -int -cpu8051_Disasm(unsigned int Address, char *Text); - -#endif /* CPU8051_H */ diff --git a/src/emuconsole.c b/src/emuconsole.c deleted file mode 100644 index f29146d..0000000 --- a/src/emuconsole.c +++ /dev/null @@ -1,518 +0,0 @@ -/* - * emuconsole.c - * - * Copyright (C) 1999 Jonathan St-André - * Copyright (C) 1999 Hugo Villeneuve - * - * This program 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 of the License, or - * (at your option) any later version. - * - * This program 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 this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#define _GNU_SOURCE /* For getline() */ -#include -#include -#include /* For isblank, toupper() */ -#include "config.h" - -#include "common.h" -#include "cpu8051.h" -#include "reg8051.h" -#include "sfr.h" -#include "memory.h" -#include "options.h" -#include "hexfile.h" -#include "keyboard.h" - -extern struct options_t options; - -/* Capitalize all letters in buffer */ -static void -Capitalize(char *buffer) -{ - int k; - - for (k = 0; k < strlen(buffer); k++) - buffer[k] = toupper(buffer[k]); -} - -/* Remove leading spaces from string in buffer */ -static void -RemoveSpaces(char *buffer) -{ - int k = 0; - - while ((k < strlen(buffer)) && isblank(buffer[k])) - k++; - - if (k != 0) - strcpy(buffer, &buffer[k]); -} - -/* CPU exec and Console UI update */ -static void -console_exec(char *Address, char *NumberInst) -{ - int NbInst = -1; /* -1 is infinity */ - if (strlen(Address) == 0) { - log_err("Invalid address"); - return; - } - - if (!STREQ(Address, "PC")) - cpu8051.pc = Ascii2Hex(Address, strlen(Address)); - - if (NumberInst) - if (strlen(NumberInst) != 0) - NbInst = Ascii2Hex(NumberInst, strlen(NumberInst)); - - InitUnixKB(); - - log_info("Program executing..."); - - do { - cpu8051_Exec(); - if (NbInst > 0) - NbInst--; - } while (!IsBreakpoint(cpu8051.pc) && !IsStoppoint(cpu8051.pc) && - (NbInst != 0) && !kbhit()); - if (kbhit()) { - (void) getch(); /* Flush key */ - log_info("Caught break signal!"); - } - if (NbInst == 0) - log_info("Number of instructions reached! Stopping!"); - if (IsBreakpoint(cpu8051.pc)) - log_info("Breakpoint hit at %.4X! Stopping!", cpu8051.pc); - if (IsStoppoint(cpu8051.pc)) - log_info("Stoppoint hit at %.4X! Stopping!", cpu8051.pc); - - ResetUnixKB(); -} - -/* Disassemble NumberInst instructions at Address */ -static void -DisasmN(unsigned int Address, int NumberInst) -{ - char TextTmp[255]; - int Row; - - for (Row = 0; Row < NumberInst ; Row++) { - Address += cpu8051_Disasm(Address, TextTmp); - printf("%s\n", TextTmp); - - if (Address > 0xFFFF) - return; - } -} - -/* Disassemble 16 instructions at Address */ -static void -Disasm(char *Address, char *NumberInst) -{ - unsigned int MemAddress, NbInst; - - if ((strlen(Address) == 0) || (STREQ(Address, "PC"))) - MemAddress = cpu8051.pc; - else - MemAddress = Ascii2Hex(Address, strlen(Address)); - - if (strlen(NumberInst) == 0) - NumberInst = "10"; - NbInst = Ascii2Hex(NumberInst, strlen(NumberInst)); - DisasmN(MemAddress, NbInst); -} - -/* Set NewValue to Register */ -static void -SetRegister(char *Register, char *NewValue) -{ - if (STREQ(Register, "PC")) - cpu8051.pc = Ascii2Hex(NewValue, 4); - else if (STREQ(Register, "A")) - cpu8051_WriteD(_ACC_, Ascii2Hex(NewValue, 2)); - else if (STREQ(Register, "B")) - cpu8051_WriteD(_B_, Ascii2Hex(NewValue, 2)); - else if (STREQ(Register, "SP")) - cpu8051_WriteD(_SP_, Ascii2Hex(NewValue, 2)); - else { - printf("\nInvalid register name!\n"); - printf("Valid registers are A, B, PC and SP.\n"); - } -} - -/* Show CPU registers, one per line */ -static void -console_dump_sfr_registers_detailed(void) -{ - int k; - - for (k = 0; k < SFR_REGS; k++) { - struct regwin_infos_t *regwin_infos; - int val; - - regwin_infos = sfr_get_infos_from_row(k); - - printf("%s = ", regwin_infos->name); - - val = regwin_read(k); - if (regwin_infos->w == 2) - printf("$%02X", val); - else if (regwin_infos->w == 4) - printf("$%04X", val); - - printf("\n"); - } -} - -/* Show CPU registers, compact format */ -static void -console_dump_sfr_registers_compact(void) -{ - unsigned char PSW = cpu8051_ReadD(_PSW_); - int BankSelect = (PSW & 0x18); - - printf("---------------------------------------------------------------" - "-------\n"); - printf("| PC | SP | DPTR | ACC | B | PSW: CY AC F0 RS1 RS0 OV" - " - P |\n"); - printf("| %.4X | %.2X | %.4X | %.2X | %.2X |", cpu8051.pc, - cpu8051_ReadD(_SP_), - memory_sfr_read_dptr(), - cpu8051_ReadD(_ACC_), cpu8051_ReadD(_B_)); - printf(" %d %d %d %d %d %d %d %d |", - (PSW >> 7) & 1, (PSW >> 6) & 1, (PSW >> 5) & 1, (PSW >> 4) & 1, - (PSW >> 3) & 1, (PSW >> 2) & 1, (PSW >> 1) & 1, PSW & 1); - printf("\n"); - printf("---------------------------------------------------------------" - "-------\n"); - - printf("| TCON | TMOD | IE | IP | R0 | R1 | R2 | R3 | R4 | R5 | R6 | R7" - " | |\n"); - printf("| %.2X | %.2X | %.2X | %.2X ", cpu8051_ReadD(_TCON_), - cpu8051_ReadD(_TMOD_), cpu8051_ReadD(_IE_), cpu8051_ReadD(_IP_)); - printf("| %.2X | %.2X | %.2X | %.2X ", - cpu8051_ReadD(BankSelect + _R0_), - cpu8051_ReadD(BankSelect + _R1_), - cpu8051_ReadD(BankSelect + _R2_), - cpu8051_ReadD(BankSelect + _R3_)); - printf("| %.2X | %.2X | %.2X | %.2X ", - cpu8051_ReadD(BankSelect + _R4_), - cpu8051_ReadD(BankSelect + _R5_), - cpu8051_ReadD(BankSelect + _R6_), - cpu8051_ReadD(BankSelect + _R7_)); - printf("| |\n"); - printf("---------------------------------------------------------------" - "-------\n"); -} - -/* Show CPU registers */ -static void -console_show_registers(void) -{ - if (options.stop_address != 0) - console_dump_sfr_registers_detailed(); - else - console_dump_sfr_registers_compact(); -} - -/* CPU reset and Console UI update */ -static void -console_reset(void) -{ - log_info("Resetting..."); - cpu8051_Reset(); - log_info("Done"); -} - -/* CPU trace and Console UI update */ -static void -console_trace(char *Address) -{ - if (strlen(Address) != 0) - cpu8051.pc = Ascii2Hex(Address, strlen(Address)); - cpu8051_Exec(); - console_show_registers(); - DisasmN(cpu8051.pc, 1); -} - -/* EmuConsole main loop */ -static void -console_main(void) -{ - unsigned int Index; - char *line = NULL; - int QuitRequest = 0; - char prompt[] = "-> "; - - char *Title[] = { " *******************", - " * 8051 Emulator *", - " *******************", - "", 0 }; - - char *Menu[] = { - " Available commands, [ ] = options", - "", - " Set Breakpoint.............. SB [address]", - " Remove Breakpoint........... RB [address]", - " Display Breakpoint(s)....... DB", - " Dump External Data Memory... DE [address] [size]", - " Dump Internal Data Memory... DI [address] [size]", - " Dump Program Memory......... DP [address] [size]", - " Display Registers content... DR", - " Execute..................... EM [address" - " [number of instructions]]", - " Help........................ H or ?", - " Modify External Data Memory. ME address value", - " Modify Internal Data Memory. MI address value", - " Modify Program Memory....... MP address value", - " Modify Register............. MR register value", - " Quit Emulator............... Q", - " Trace mode.................. T [address]", - " Unassemble.................. U [address]" - " [number of instructions]", - " Reset processor............. Z", 0 }; - - console_reset(); - - if (options.stop_address != 0) { - /* Automatically run program and stop at specified address. */ - console_exec("0x0000", NULL); - console_show_registers(); - QuitRequest = 1; - } else { - Index = 0; - while (Title[Index] != 0) - printf("%s\n", Title[Index++]); - - Index = 0; - while (Menu[Index] != 0) - printf("%s\n", Menu[Index++]); - - console_show_registers(); - } - - while (!QuitRequest) { - int slen; - size_t len = 0; - char Command[256]; - char Args[256]; - char Parameter1[256]; - char Parameter2[256]; - - Parameter1[0] = '\0'; - Parameter2[0] = '\0'; - - printf(prompt); - (void) getline(&line, &len, stdin); - Capitalize(line); - RemoveSpaces(line); - - /* Strip trailing newline */ - slen = strlen(line); - if (line[slen - 1] == '\n') - line[slen - 1] = '\0'; - - /* Find command-arguments delimiter */ - for (Index = 0; Index < strlen(line); Index++) { - if (isblank(line[Index])) - break; - } - - /* Keep only the Command part from the input line */ - memcpy(Command, &line[0], Index); - Command[Index] = '\0'; - - /* Keep only the arguments part from the input line */ - if (Index < strlen(line)) { - slen = strlen(line) - Index; - memcpy(Args, &line[Index + 1], slen); - } else { - slen = 0; - } - Args[slen] = '\0'; - RemoveSpaces(Args); - - /* Find multi-arguments delimiter */ - for (Index = 0; Index < strlen(Args); Index++) { - if (isblank(Args[Index])) - break; - } - - memcpy(Parameter1, &Args[0], Index); - Parameter1[Index] = '\0'; - - if (Index < strlen(Args)) { - slen = strlen(Args) - Index; - memcpy(Parameter2, &Args[Index + 1], slen); - } else { - slen = 0; - } - Parameter2[slen] = '\0'; - RemoveSpaces(Parameter2); - - if (strlen(Command) == 0) { - goto syntax_error; - continue; - } - - if ((strlen(Parameter1) > 4) || (strlen(Parameter2) > 4)) { - printf("Invalid Parameter Format!\n"); - continue; - } - - switch (Command[0]) { - case 'D': - if (STREQ(Command, "DB") && - (strlen(Parameter1) == 0)) - ShowBreakpoints(); - else if (STREQ(Command, "DE")) - DumpMem(Parameter1, Parameter2, EXT_MEM_ID); - else if (STREQ(Command, "DI")) - DumpMem(Parameter1, Parameter2, INT_MEM_ID); - else if (STREQ(Command, "DP")) { - if ((strlen(Parameter1) == 0)) - strcpy(Parameter1, "PC"); - DumpMem(Parameter1, Parameter2, PGM_MEM_ID); - } else if (STREQ(Command, "DR") && - (strlen(Parameter1) == 0)) - console_show_registers(); - else - goto syntax_error; - break; - case 'E': - if (STREQ(Command, "EM")) - console_exec(Parameter1, Parameter2); - else - goto syntax_error; - break; - case 'H': - case '?': - if ((STREQ(Command, "H") || STREQ(Command, "?")) && - (strlen(Parameter1) == 0) && - (strlen(Parameter2) == 0)) { - Index = 0; - while (Menu[Index] != 0) - printf("%s\n", Menu[Index++]); - } else - goto syntax_error; - break; - case 'M': - if ((strlen(Parameter1) == 0) || - (strlen(Parameter2) == 0)) - printf("Missing Parameter!\n"); - else if (STREQ(Command, "ME")) { - unsigned int adresse = Ascii2Hex(Parameter1, 4); - unsigned char valeur = Ascii2Hex(Parameter2, 2); - memory_write8(EXT_MEM_ID, adresse, valeur); - } else if (STREQ(Command, "MI")) { - unsigned int adresse = Ascii2Hex(Parameter1, 2); - unsigned char valeur = Ascii2Hex(Parameter2, 2); - memory_write8(INT_MEM_ID, adresse, valeur); - } else if (STREQ(Command, "MP")) { - unsigned int adresse = Ascii2Hex(Parameter1, 4); - unsigned char valeur = Ascii2Hex(Parameter2, 2); - memory_write8(PGM_MEM_ID, adresse, valeur); - } else if (STREQ(Command, "MR")) - SetRegister(Parameter1, Parameter2); - else - goto syntax_error; - break; - case 'Q': - if (STREQ(Command, "Q") && (strlen(Parameter1) == 0) && - (strlen(Parameter2) == 0)) - QuitRequest = 1; - else - goto syntax_error; - break; - case 'R': - if (strlen(Parameter2) != 0) - goto TooMuchParameters; - if (STREQ(Command, "RB")) { - if (strlen(Parameter1) == 0) - ClearBreakpoint(cpu8051.pc); - else - ClearBreakpoint( - Ascii2Hex(Parameter1, 4)); - } else - goto syntax_error; - break; - case 'S': - if (strlen(Parameter2) != 0) - goto TooMuchParameters; - - if (STREQ(Command, "SB")) { - if (strlen(Parameter1) == 0) - SetBreakpoint(cpu8051.pc); - else - SetBreakpoint(Ascii2Hex(Parameter1, 4)); - } else - goto syntax_error; - break; - case 'T': - if (strlen(Parameter2) != 0) - printf("Wrong Number of Parameters!\n"); - - if (STREQ(Command, "T")) - console_trace(Parameter1); - else - goto syntax_error; - break; - case 'U': - if (STREQ(Command, "U")) - Disasm(Parameter1, Parameter2); - else - goto syntax_error; - break; - case 'Z': - if (STREQ(Command, "Z") && (strlen(Parameter1) == 0) && - (strlen(Parameter2) == 0)) - cpu8051_Reset(); - else - goto syntax_error; - break; - case '\n': - break; - default: - goto syntax_error; - } - continue; - -syntax_error: - printf("Syntax Error!\n"); - continue; -TooMuchParameters: - printf("Wrong Number of Parameters!\n"); - continue; - } - - if (line) - free(line); -} - -int -main(int argc, char **argv) -{ - parse_command_line_options(argc, argv); - - cpu8051_init(); - - if (options.filename != NULL) - LoadHexFile(options.filename); - - console_main(); - - log_info("Terminate"); - - return 0; -} diff --git a/src/emugtk.c b/src/emugtk.c deleted file mode 100644 index b5ef13f..0000000 --- a/src/emugtk.c +++ /dev/null @@ -1,528 +0,0 @@ -/* - * emugtk.c - * - * Copyright (C) 1999 Jonathan St-André - * Copyright (C) 1999 Hugo Villeneuve - * - * This program 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 of the License, or - * (at your option) any later version. - * - * This program 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 this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#include -#include "config.h" - -#include -#include - -#include - -#include "common.h" -#include "cpu8051.h" -#include "memory.h" -#include "options.h" -#include "hexfile.h" - -#include "emugtk.h" -#include "reset.xpm" -#include "run.xpm" -#include "stop.xpm" -#include "step.xpm" -#include "filemenu.h" -#include "viewmenu.h" -#include "helpmenu.h" -#include "regwin.h" -#include "pgmwin.h" -#include "memwin.h" -#include "pswwin.h" -#include "app-config.h" - -#define BUTTONS_BORDER 2 - -static int running; -static int running_function_tag; -static int restart_gui = true; - -GtkWidget *mainwin; - -extern struct app_config_t *cfg; -extern struct options_t options; - -void -emugtk_UpdateDisplay(void) -{ - log_debug("UpdateDisplay()"); - regwin_refresh(); - pgmwin_refresh(); - pswwin_refresh(); - - if (cfg->view_int_memory) - memwin_refresh(INT_MEM_ID); - - if (cfg->view_ext_memory) - memwin_refresh(EXT_MEM_ID); -} - -/* Step out of running state */ -static void -emugtk_stop_running() -{ - if (running) { - log_info("StopRunning()"); - g_source_remove(running_function_tag); - running = 0; - emugtk_UpdateDisplay(); - } -} - -/* Running function called when idle from gtk_main */ -static gboolean -emugtk_running(gpointer data) -{ - cpu8051_Exec(); - if (IsBreakpoint(cpu8051.pc)) { - log_info("Breakpoint Hit"); - emugtk_stop_running(); - } - - return TRUE; -} - -/* Get in the running state */ -static void -emugtk_start_running(void) -{ - if (!running) { - log_info("StartRunning()"); - running_function_tag = g_idle_add(emugtk_running, 0); - running = 1; - } -} - -/* Taken from the Gxine source code. */ -static GtkWidget * -button_add_pix(GtkWidget *box, char **xpm) -{ - GtkWidget *button, *icon; - - button = gtk_button_new(); - gtk_button_set_relief(GTK_BUTTON(button), GTK_RELIEF_NORMAL); - - icon = gtk_image_new_from_pixbuf( - gdk_pixbuf_new_from_xpm_data((const char **) xpm)); - gtk_container_add(GTK_CONTAINER(button), icon); - - gtk_box_pack_start(GTK_BOX(box), button, FALSE, FALSE, BUTTONS_BORDER); - - return button; -} - -/* CPU reset and Gtk UI update */ -static void -emugtk_Reset(void) -{ - cpu8051_Reset(); - emugtk_UpdateDisplay(); -} - -/* Signal ResetEvent (ResetButton) */ -static void -emugtk_ResetEvent(GtkWidget *widget, GdkEvent *event, gpointer data) -{ - log_info("ResetEvent()"); - emugtk_stop_running(); - emugtk_Reset(); -} - -/* CPU Step and Gtk UI update */ -static void -emugtk_Step(void) -{ - cpu8051_Exec(); - emugtk_UpdateDisplay(); -} - -/* Signal RunEvent (RunButton) */ -static void -emugtk_RunEvent(GtkWidget *widget, GdkEvent *event, gpointer data) -{ - log_info("RunEvent()"); - - if (running) - emugtk_stop_running(); - else - emugtk_start_running(); -} - -/* Signal StopEvent (StopButton) */ -static void -emugtk_StopEvent(GtkWidget *widget, GdkEvent *event, gpointer data) -{ - log_info("StopEvent()"); - emugtk_stop_running(); -} - -/* Signal StepEvent (StepButton) */ -static void -emugtk_StepEvent(GtkWidget *widget, GdkEvent *event, gpointer data) -{ - log_info("StepEvent()"); - emugtk_stop_running(); - emugtk_Step(); -} - -/* Creates the Reset, Run, Stop and Step buttons. */ -static GtkWidget * -AddButtons(void) -{ - GtkWidget *button_hbox; - GtkWidget *button; - - /* The buttons of the hbox are NOT given equal space in the box. */ - button_hbox = gtk_hbox_new(FALSE, 0); - - /* Creating the RESET button. */ - button = button_add_pix(button_hbox, reset_xpm); - g_signal_connect(button, "clicked", - G_CALLBACK(emugtk_ResetEvent), - NULL); - - /* Creating the RUN button. */ - button = button_add_pix(button_hbox, run_xpm); - g_signal_connect(button, "clicked", - G_CALLBACK(emugtk_RunEvent), - NULL); - - /* Creating STOP button. */ - button = button_add_pix(button_hbox, stop_xpm); - g_signal_connect(GTK_OBJECT(button), "clicked", - G_CALLBACK(emugtk_StopEvent), - NULL); - - /* Creating STEP button. */ - button = button_add_pix(button_hbox, step_xpm); - g_signal_connect(GTK_OBJECT(button), "clicked", - G_CALLBACK(emugtk_StepEvent), - NULL); - - return button_hbox; -} - -static GtkWidget * -AddMenu(void) -{ - GtkWidget *menu_bar; - - /* Creating menu item. */ - menu_bar = gtk_menu_bar_new(); - - /* Adding the 'File' submenu */ - FileAddMenu(menu_bar); - - /* Adding the 'View' submenu */ - ViewAddMenu(menu_bar); - - /* Adding the 'Help' submenu */ - HelpAddMenu(menu_bar); - - return menu_bar; -} - -static int -mainwin_configure_event(GtkWindow *window, GdkEvent *event, gpointer data) -{ - cfg->win_width = event->configure.width; - cfg->win_height = event->configure.height; - - /* - * Important: - * Returning false allows event to propagate to children. If not, they - * will not be resized when we resize the main window. - */ - return FALSE; -} - -static void -hpaned_notify_event(GtkWindow *window, GdkEvent *event, gpointer data) -{ - GtkWidget *paned = data; - - cfg->hpane_pos = gtk_paned_get_position(GTK_PANED(paned)); -} - -static void -vpaned_notify_event(GtkWindow *window, GdkEvent *event, gpointer data) -{ - GtkWidget *paned = data; - - cfg->vpane_pos = gtk_paned_get_position(GTK_PANED(paned)); -} - -static void -main_paned_notify_event(GtkWindow *window, GdkEvent *event, gpointer data) -{ - GtkWidget *paned = data; - - cfg->main_pane_pos = gtk_paned_get_position(GTK_PANED(paned)); -} - -void -emugtk_restart_gui(void) -{ - emugtk_stop_running(); - - gtk_widget_destroy(mainwin); - - restart_gui = true; -} - -void -emugtk_quit_gui(void) -{ - gtk_main_quit(); - - restart_gui = false; -} - -static GtkWidget * -emugtk_create_memory_paned(void) -{ - GtkWidget *vpaned; - GtkWidget *scrollwin; - - /* Create vpaned (memory windows) only if necessary. */ - if (cfg->view_int_memory || cfg->view_ext_memory) { - vpaned = gtk_vpaned_new(); - gtk_paned_set_position(GTK_PANED(vpaned), cfg->vpane_pos); - g_signal_connect(G_OBJECT(vpaned), "notify::position", - G_CALLBACK(vpaned_notify_event), vpaned); - - /* Internal memory dump frame. */ - if (cfg->view_int_memory) { - scrollwin = memwin_init("Internal memory (IRAM)", - INT_MEM_ID); - gtk_paned_pack1(GTK_PANED(vpaned), scrollwin, - FALSE, FALSE); - } - - /* External memory dump frame. */ - if (cfg->view_ext_memory) { - scrollwin = memwin_init("External memory (XRAM)", - EXT_MEM_ID); - gtk_paned_pack2(GTK_PANED(vpaned), scrollwin, - TRUE, FALSE); - } - - return vpaned; - } else - return NULL; -} - -/* - * mainwin - * +---------------------------------------------------------------------+ - * | | - * | vbox | - * | +---------------------------------------------------------------+ | - * | | | | - * | | menu_bar | | - * | | +----------------------+ | | - * | | | File View Help | | | - * | | +----------------------+ | | - * | | | | - * | |---------------------------------------------------------------| | - * | | | | - * | | buttons_bar | | - * | | +-----------------------+ | | - * | | | RST RUN STOP STEP | | | - * | | +-----------------------+ | | - * | | | | - * | |---------------------------------------------------------------| | - * | | | | - * | | main_paned | | - * | | +---------------------------------------------------------+ | | - * | | | | | | - * | | | hpaned | | | - * | | | +---------------------------------------------------+ | | | - * | | | | | | | | | - * | | | | scrollwin | scrollwin | | | | - * | | | | +------------------+ * +--------------------+ | | | | - * | | | | | REGISTERS window | * | Disassembly window | | | | | - * | | | | +------------------+ | +--------------------+ | | | | - * | | | | | | | | | - * | | | +---------------------------------------------------+ | | | - * | | | | | | - * | | |--------------------------***----------------------------- | | - * | | | | | | - * | | | vpaned | | | - * | | | +---------------------------------------------------+ | | | - * | | | | | | | | - * | | | | scrollwin | | | | - * | | | | +---------------------------------------------+ | | | | - * | | | | | Internal memory window | | | | | - * | | | | +---------------------------------------------+ | | | | - * | | | | | | | | - * | | | +-----------------------***-------------------------| | | | - * | | | | | | | | - * | | | | scrollwin | | | | - * | | | | +---------------------------------------------+ | | | | - * | | | | | External memory window | | | | | - * | | | | +---------------------------------------------+ | | | | - * | | | | | | | | - * | | | +---------------------------------------------------+ | | | - * | | | | | | - * | | +---------------------------------------------------------+ | | - * | | | | - * | | | | - * | +---------------------------------------------------------------+ | - * | | - * | | - * +---------------------------------------------------------------------+ - */ -static void -emugtk_window_init(void) -{ - GtkWidget *vbox; - GtkWidget *menu_bar; - GtkWidget *buttons_bar; - GtkWidget *scrollwin; - GtkWidget *hpaned; - GtkWidget *vpaned; - GtkWidget *main_paned; - - mainwin = gtk_window_new(GTK_WINDOW_TOPLEVEL); - gtk_window_set_title(GTK_WINDOW(mainwin), PACKAGE); - gtk_window_set_default_size(GTK_WINDOW(mainwin), - cfg->win_width, cfg->win_height); - gtk_container_set_border_width(GTK_CONTAINER(mainwin), 0); - - /* Window DESTROY event. */ - g_signal_connect(mainwin, "destroy", - G_CALLBACK(gtk_main_quit), NULL); - - g_signal_connect(G_OBJECT(mainwin), "configure-event", - G_CALLBACK(mainwin_configure_event), NULL); - - /* Creating the menu bar. */ - menu_bar = AddMenu(); - - /* Creating the buttons bar. */ - buttons_bar = AddButtons(); - - scrollwin = pswwin_init(); - gtk_box_pack_start(GTK_BOX(buttons_bar), scrollwin, FALSE, FALSE, 100); - - /* hpaned will contain registers and disassembly windows. */ - hpaned = gtk_hpaned_new(); - gtk_paned_set_position(GTK_PANED(hpaned), cfg->hpane_pos); - g_signal_connect(G_OBJECT(hpaned), "notify::position", - G_CALLBACK(hpaned_notify_event), hpaned); - - /* 8051 registers frame. */ - scrollwin = regwin_init(); - gtk_paned_pack1(GTK_PANED(hpaned), scrollwin, FALSE, FALSE); - - /* Program disassembly frame. */ - scrollwin = pgmwin_init(); - gtk_paned_pack2(GTK_PANED(hpaned), scrollwin, TRUE, FALSE); - - /* - * main_paned will contain two groups: - * group1: registers and disassembly windows. - * group2: memory windows - */ - if (cfg->layout == UI_LAYOUT1) - main_paned = gtk_vpaned_new(); - else - main_paned = gtk_hpaned_new(); - - gtk_paned_set_position(GTK_PANED(main_paned), cfg->main_pane_pos); - g_signal_connect(G_OBJECT(main_paned), "notify::position", - G_CALLBACK(main_paned_notify_event), main_paned); - gtk_paned_pack1(GTK_PANED(main_paned), hpaned, FALSE, FALSE); - - vpaned = emugtk_create_memory_paned(); - if (vpaned != NULL) - gtk_paned_pack2(GTK_PANED(main_paned), vpaned, - TRUE, FALSE); - - /* - * vbox contains the menu bar and body_vbox (for all remaining - * items). - */ - vbox = gtk_vbox_new(FALSE, 1); - gtk_box_pack_start(GTK_BOX(vbox), menu_bar, FALSE, FALSE, 1); - gtk_box_pack_start(GTK_BOX(vbox), buttons_bar, FALSE, FALSE, 1); - gtk_box_pack_start(GTK_BOX(vbox), main_paned, true, true, 1); - - /* Adding the vbox to the main window. */ - gtk_container_add(GTK_CONTAINER(mainwin), vbox); - - g_signal_connect(mainwin, "destroy", G_CALLBACK(emugtk_quit_gui), NULL); - - gtk_widget_show_all(mainwin); -} - -void -AddMenuSeparator(GtkWidget *menu) -{ - GtkWidget *item; - - item = gtk_menu_item_new(); - gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); -} - -void -emugtk_new_file(char *file) -{ - emugtk_stop_running(); - - LoadHexFile(file); - - if (cfg->clear_ram_on_file_load) - emugtk_Reset(); - - emugtk_UpdateDisplay(); -} - -int -main(int argc, char **argv) -{ - parse_command_line_options(argc, argv); - app_config_load(); - - cpu8051_init(); - - running = 0; - - gtk_init(&argc, &argv); - - if (options.filename != NULL) - LoadHexFile(options.filename); - - cpu8051_Reset(); - - while (restart_gui == true) { - log_info("Init GUI"); - - emugtk_window_init(); - emugtk_UpdateDisplay(); - gtk_main(); - } - - log_info("Terminate"); - - app_config_save(); - - return EXIT_SUCCESS; -} diff --git a/src/emugtk.h b/src/emugtk.h deleted file mode 100644 index 8e47427..0000000 --- a/src/emugtk.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * emugtk.h - * - * Copyright (C) 1999 Jonathan St-André - * Copyright (C) 1999 Hugo Villeneuve - * - * This program 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 of the License, or - * (at your option) any later version. - * - * This program 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 this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#ifndef EMUGTK_H -#define EMUGTK_H 1 - -#include - -void -AddMenuSeparator(GtkWidget *menu); - -void -emugtk_new_file(char *file); - -void -emugtk_UpdateDisplay(void); - -void -emugtk_restart_gui(void); - -void -emugtk_quit_gui(void); - -#endif /* EMUGTK_H */ diff --git a/src/filemenu.c b/src/filemenu.c deleted file mode 100644 index d2dae9c..0000000 --- a/src/filemenu.c +++ /dev/null @@ -1,139 +0,0 @@ -/* - * filemenu.c - * - * Copyright (C) 1999 Jonathan St-André - * Copyright (C) 1999 Hugo Villeneuve - * - * This program 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 of the License, or - * (at your option) any later version. - * - * This program 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 this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#if HAVE_CONFIG_H -# include "config.h" -#endif - -#include /* UNIX standard function definitions */ -#include -#include - -#include "common.h" -#include "emugtk.h" -#include "messagebox.h" -#include "filemenu.h" - -#define FILENAME_DESCRIPTION "Open Intel Hex file" - -static char previous_folder[MAX_FILENAME_LENGTH + 1]; - -static void -remember_current_folder(GtkFileChooser *chooser) -{ - char *folder; - - folder = gtk_file_chooser_get_current_folder(chooser); - - if (folder != NULL) { - if (strlen(folder) >= MAX_FILENAME_LENGTH) { - /* Non-critical error */ - log_warn("current folder name too long for buffer"); - } else { - log_info("current folder = %s", folder); - strncpy(previous_folder, folder, MAX_FILENAME_LENGTH); - } - - g_free(folder); - } -} - -void -FileOpenEvent(GtkObject *object, gpointer data) -{ - GtkWidget *file_dialog; - char *dir; - char *cwd = NULL; - - log_info("FileOpenEvent()"); - - /* Create a new file selection widget. */ - file_dialog = gtk_file_chooser_dialog_new( - FILENAME_DESCRIPTION, NULL, GTK_FILE_CHOOSER_ACTION_OPEN, - GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, - GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, NULL); - - if (strlen(previous_folder) == 0) { - /* Opening file chooser to current working directory. */ - cwd = g_get_current_dir(); - dir = cwd; - } else { - /* Opening file chooser to previous opened directory. */ - dir = previous_folder; - } - - gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(file_dialog), dir); - - if (cwd) - g_free(cwd); - - if (gtk_dialog_run(GTK_DIALOG(file_dialog)) == GTK_RESPONSE_ACCEPT) { - char *selected_file; - - selected_file = gtk_file_chooser_get_filename( - GTK_FILE_CHOOSER(file_dialog)); - - if (selected_file != NULL) { - log_info("emugtk_File = %s", selected_file); - - remember_current_folder(GTK_FILE_CHOOSER(file_dialog)); - - emugtk_new_file(selected_file); - g_free(selected_file); - } - } - - gtk_widget_destroy(file_dialog); -} - -static void -FileQuitEvent(gchar *string) -{ - emugtk_quit_gui(); -} - -void -FileAddMenu(GtkWidget *menu_bar) -{ - GtkWidget *item; - GtkWidget *menu; - - menu = gtk_menu_new(); - - /* Create the 'open' item. */ - item = gtk_menu_item_new_with_label(FILENAME_DESCRIPTION); - gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); - /* Attach the callback functions to the activate signal. */ - g_signal_connect(item, "activate", G_CALLBACK(FileOpenEvent), NULL); - - AddMenuSeparator(menu); - - item = gtk_menu_item_new_with_label("Exit"); - gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); - /* We can attach the Quit menu item to our exit function */ - g_signal_connect(item, "activate", G_CALLBACK(FileQuitEvent), - (gpointer) "file.quit"); - - /* Adding submenu title. */ - item = gtk_menu_item_new_with_label("File"); - gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), menu); - gtk_menu_shell_append((GtkMenuShell *) menu_bar, item); -} diff --git a/src/filemenu.h b/src/filemenu.h deleted file mode 100644 index fe9688a..0000000 --- a/src/filemenu.h +++ /dev/null @@ -1,36 +0,0 @@ -/* - * filemenu.h - * - * Copyright (C) 1999 Jonathan St-André - * Copyright (C) 1999 Hugo Villeneuve - * - * This program 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 of the License, or - * (at your option) any later version. - * - * This program 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 this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#ifndef FILEMENU_H -#define FILEMENU_H 1 - -#include - -void -FileOpenEvent(GtkObject *object, gpointer data); - -void -FileResetEvent(GtkObject *object, gpointer data); - -void -FileAddMenu(GtkWidget *menu_bar); - -#endif /* FILEMENU_H */ diff --git a/src/gtk/Makefile.am b/src/gtk/Makefile.am new file mode 100644 index 0000000..22bb895 --- /dev/null +++ b/src/gtk/Makefile.am @@ -0,0 +1,38 @@ +# This file is processed by GNU automake to generate Makefile.in + +AM_CPPFLAGS = \ + -Wall \ + -I@top_srcdir@ \ + -I@top_srcdir@/src/common \ + -I$(top_srcdir)/pixmaps \ + @GTK_CFLAGS@ \ + @GLIB_CFLAGS@ \ + -DDATADIR=\"$(datadir)\" \ + -DGDK_PIXBUF_DISABLE_DEPRECATED \ + -DGDK_DISABLE_DEPRECATED \ + -DGTK_DISABLE_DEPRECATED + +LDADD = \ + $(top_builddir)/src/common/libemu8051.a \ + @GTK_LIBS@ \ + @GLIB_LIBS@ + +bin_PROGRAMS = emu8051-gtk + +emu8051_gtk_SOURCES = \ + emugtk.c emugtk.h \ + app-config.c app-config.h \ + memwin.c memwin.h \ + pgmwin.c pgmwin.h \ + regwin.c regwin.h \ + pswwin.c pswwin.h \ + filemenu.c filemenu.h \ + viewmenu.c viewmenu.h \ + helpmenu.c helpmenu.h \ + messagebox.c messagebox.h + +EXTRA_DIST = + +CLEANFILES = *~ + +MAINTAINERCLEANFILES = Makefile.in diff --git a/src/gtk/app-config.c b/src/gtk/app-config.c new file mode 100644 index 0000000..90022f2 --- /dev/null +++ b/src/gtk/app-config.c @@ -0,0 +1,218 @@ +/* + * Handle loading and saving of application configuration settings + * + * Copyright (C) 2013 Hugo Villeneuve + * + * This program 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 of the License, or + * (at your option) any later version. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#if HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include +#include +#include + +#if STDC_HEADERS +# include +#elif HAVE_STRINGS_H +# include +#endif + +#include + +#include "common.h" +#include "app-config.h" + +static const char profile_name[] = "default"; +static struct app_config_t app_config; + +struct app_config_t *cfg = &app_config; + +static void +app_config_init(void) +{ + /* Emulation options */ + cfg->clear_ram_on_file_load = false; + + /* UI settings */ + cfg->win_width = 640; + cfg->win_height = 480; + cfg->hpane_pos = 100; + cfg->vpane_pos = 200; + cfg->main_pane_pos = 200; + + /* View menu options */ + cfg->layout = UI_LAYOUT1; + cfg->view_int_memory = 1; + cfg->view_sfr_memory = 1; + cfg->view_ext_memory = 1; + cfg->bits_per_row = 16; /* 8 or 16 */ +} + +static int +app_config_key_file_get_int(GKeyFile *kf, const char *grp, const char *key, int *value) +{ + char *str = g_key_file_get_value(kf, grp, key, NULL); + + log_debug("key: %s", key); + + if (G_LIKELY(str)) { + *value = atoi(str); + log_debug(" value = %d", *value); + g_free(str); + } + + return str != NULL; +} + +static void +app_config_load_from_key_file(GKeyFile *kf) +{ + /* Emulation options */ + app_config_key_file_get_int(kf, "emulation", "clear_ram_on_file_load", + &cfg->clear_ram_on_file_load); + + /* ui */ + app_config_key_file_get_int(kf, "ui", "win_width", &cfg->win_width); + app_config_key_file_get_int(kf, "ui", "win_height", &cfg->win_height); + app_config_key_file_get_int(kf, "ui", "hpane_pos", &cfg->hpane_pos); + app_config_key_file_get_int(kf, "ui", "vpane_pos", &cfg->vpane_pos); + app_config_key_file_get_int(kf, "ui", "main_pane_pos", + &cfg->main_pane_pos); + + /* View */ + app_config_key_file_get_int(kf, "view", "layout", &cfg->layout); + if ((cfg->layout != UI_LAYOUT1) && (cfg->layout != UI_LAYOUT2)) { + log_err("Invalid layout, defaulting to layout 1"); + cfg->layout = UI_LAYOUT1; + } + app_config_key_file_get_int(kf, "view", "int_memory", + &cfg->view_int_memory); + app_config_key_file_get_int(kf, "view", "sfr_memory", + &cfg->view_sfr_memory); + app_config_key_file_get_int(kf, "view", "ext_memory", + &cfg->view_ext_memory); + app_config_key_file_get_int(kf, "view", "bits_per_row", + &cfg->bits_per_row); +} + +static char * +app_config_get_dir_path(void) +{ + char *dir_path; + + dir_path = g_build_filename(g_get_user_config_dir(), PACKAGE, + profile_name, NULL); + + return dir_path; +} + +static char * +app_config_get_file_path(void) +{ + char *file_path; + char *dir_path; + char file[MAX_FILENAME_LENGTH]; + + sprintf(file, "%s.conf", PACKAGE); + + dir_path = app_config_get_dir_path(); + + file_path = g_build_filename(dir_path, file, NULL); + + log_info("app. config file = %s", file_path); + + g_free(dir_path); + + return file_path; +} + +int +app_config_load(void) +{ + char *file_path; + GKeyFile *kf; + + /* Load default values before config file */ + app_config_init(); + + kf = g_key_file_new(); + + file_path = app_config_get_file_path(); + + if (g_key_file_load_from_file(kf, file_path, 0, NULL)) + app_config_load_from_key_file(kf); + + g_free(file_path); + + g_key_file_free(kf); + + /* ??? */ + return 0; +} + +int +app_config_save(void) +{ + char *dir_path; + + dir_path = app_config_get_dir_path(); + + if (g_mkdir_with_parents(dir_path, 0700) != -1) + { + char *file_path; + GString* buf = g_string_sized_new(1024); + + g_string_append(buf, "\n[emulation]\n"); + + g_string_append_printf(buf, "clear_ram_on_file_load=%d\n", + cfg->clear_ram_on_file_load); + + g_string_append(buf, "\n[ui]\n"); + + g_string_append_printf(buf, "win_width=%d\n", cfg->win_width); + g_string_append_printf(buf, "win_height=%d\n", cfg->win_height); + g_string_append_printf(buf, "hpane_pos=%d\n", cfg->hpane_pos); + g_string_append_printf(buf, "vpane_pos=%d\n", cfg->vpane_pos); + g_string_append_printf(buf, "main_pane_pos=%d\n", + cfg->main_pane_pos); + + g_string_append(buf, "\n[view]\n"); + g_string_append_printf(buf, "layout=%d\n", cfg->layout); + g_string_append_printf(buf, "int_memory=%d\n", + cfg->view_int_memory); + g_string_append_printf(buf, "sfr_memory=%d\n", + cfg->view_sfr_memory); + g_string_append_printf(buf, "ext_memory=%d\n", + cfg->view_ext_memory); + g_string_append_printf(buf, "bits_per_row=%d\n", + cfg->bits_per_row); + + file_path = app_config_get_file_path(); + + g_file_set_contents(file_path, buf->str, buf->len, NULL); + g_string_free(buf, TRUE); + g_free(file_path); + } + + g_free(dir_path); + + /* ??? */ + return 0; +} diff --git a/src/gtk/app-config.h b/src/gtk/app-config.h new file mode 100644 index 0000000..1c418b5 --- /dev/null +++ b/src/gtk/app-config.h @@ -0,0 +1,64 @@ +/* + * app_config.h + * + * Copyright (C) 1999 Hugo Villeneuve + * + * This program 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 of the License, or + * (at your option) any later version. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef APP_CONFIG_H +#define APP_CONFIG_H 1 + +/* + * Layout1: Layout2: + * + * REGS | PROGRAM | | IRAM + * -------------- REGS | PROGRAM | ---- + * IRAM | | XRAM + * -------------- + * XRAM + */ +enum layout_t { + UI_LAYOUT1 = 1, + UI_LAYOUT2, +}; + +struct app_config_t +{ + /* Emulation options */ + int clear_ram_on_file_load; + + /* UI settings */ + int win_width; + int win_height; + int hpane_pos; /* For registers and program windows. */ + int vpane_pos; /* For internal and external memory windows. */ + int main_pane_pos; /* Between hpane and vpane. */ + + /* View menu options */ + int layout; /* UI Layout 1 or 2 */ + int view_int_memory; + int view_sfr_memory; + int view_ext_memory; + int bits_per_row; /* 8 or 16 */ +}; + +int +app_config_load(void); + +int +app_config_save(void); + +#endif /* APP_CONFIG_H */ diff --git a/src/gtk/emugtk.c b/src/gtk/emugtk.c new file mode 100644 index 0000000..b5ef13f --- /dev/null +++ b/src/gtk/emugtk.c @@ -0,0 +1,528 @@ +/* + * emugtk.c + * + * Copyright (C) 1999 Jonathan St-André + * Copyright (C) 1999 Hugo Villeneuve + * + * This program 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 of the License, or + * (at your option) any later version. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include +#include "config.h" + +#include +#include + +#include + +#include "common.h" +#include "cpu8051.h" +#include "memory.h" +#include "options.h" +#include "hexfile.h" + +#include "emugtk.h" +#include "reset.xpm" +#include "run.xpm" +#include "stop.xpm" +#include "step.xpm" +#include "filemenu.h" +#include "viewmenu.h" +#include "helpmenu.h" +#include "regwin.h" +#include "pgmwin.h" +#include "memwin.h" +#include "pswwin.h" +#include "app-config.h" + +#define BUTTONS_BORDER 2 + +static int running; +static int running_function_tag; +static int restart_gui = true; + +GtkWidget *mainwin; + +extern struct app_config_t *cfg; +extern struct options_t options; + +void +emugtk_UpdateDisplay(void) +{ + log_debug("UpdateDisplay()"); + regwin_refresh(); + pgmwin_refresh(); + pswwin_refresh(); + + if (cfg->view_int_memory) + memwin_refresh(INT_MEM_ID); + + if (cfg->view_ext_memory) + memwin_refresh(EXT_MEM_ID); +} + +/* Step out of running state */ +static void +emugtk_stop_running() +{ + if (running) { + log_info("StopRunning()"); + g_source_remove(running_function_tag); + running = 0; + emugtk_UpdateDisplay(); + } +} + +/* Running function called when idle from gtk_main */ +static gboolean +emugtk_running(gpointer data) +{ + cpu8051_Exec(); + if (IsBreakpoint(cpu8051.pc)) { + log_info("Breakpoint Hit"); + emugtk_stop_running(); + } + + return TRUE; +} + +/* Get in the running state */ +static void +emugtk_start_running(void) +{ + if (!running) { + log_info("StartRunning()"); + running_function_tag = g_idle_add(emugtk_running, 0); + running = 1; + } +} + +/* Taken from the Gxine source code. */ +static GtkWidget * +button_add_pix(GtkWidget *box, char **xpm) +{ + GtkWidget *button, *icon; + + button = gtk_button_new(); + gtk_button_set_relief(GTK_BUTTON(button), GTK_RELIEF_NORMAL); + + icon = gtk_image_new_from_pixbuf( + gdk_pixbuf_new_from_xpm_data((const char **) xpm)); + gtk_container_add(GTK_CONTAINER(button), icon); + + gtk_box_pack_start(GTK_BOX(box), button, FALSE, FALSE, BUTTONS_BORDER); + + return button; +} + +/* CPU reset and Gtk UI update */ +static void +emugtk_Reset(void) +{ + cpu8051_Reset(); + emugtk_UpdateDisplay(); +} + +/* Signal ResetEvent (ResetButton) */ +static void +emugtk_ResetEvent(GtkWidget *widget, GdkEvent *event, gpointer data) +{ + log_info("ResetEvent()"); + emugtk_stop_running(); + emugtk_Reset(); +} + +/* CPU Step and Gtk UI update */ +static void +emugtk_Step(void) +{ + cpu8051_Exec(); + emugtk_UpdateDisplay(); +} + +/* Signal RunEvent (RunButton) */ +static void +emugtk_RunEvent(GtkWidget *widget, GdkEvent *event, gpointer data) +{ + log_info("RunEvent()"); + + if (running) + emugtk_stop_running(); + else + emugtk_start_running(); +} + +/* Signal StopEvent (StopButton) */ +static void +emugtk_StopEvent(GtkWidget *widget, GdkEvent *event, gpointer data) +{ + log_info("StopEvent()"); + emugtk_stop_running(); +} + +/* Signal StepEvent (StepButton) */ +static void +emugtk_StepEvent(GtkWidget *widget, GdkEvent *event, gpointer data) +{ + log_info("StepEvent()"); + emugtk_stop_running(); + emugtk_Step(); +} + +/* Creates the Reset, Run, Stop and Step buttons. */ +static GtkWidget * +AddButtons(void) +{ + GtkWidget *button_hbox; + GtkWidget *button; + + /* The buttons of the hbox are NOT given equal space in the box. */ + button_hbox = gtk_hbox_new(FALSE, 0); + + /* Creating the RESET button. */ + button = button_add_pix(button_hbox, reset_xpm); + g_signal_connect(button, "clicked", + G_CALLBACK(emugtk_ResetEvent), + NULL); + + /* Creating the RUN button. */ + button = button_add_pix(button_hbox, run_xpm); + g_signal_connect(button, "clicked", + G_CALLBACK(emugtk_RunEvent), + NULL); + + /* Creating STOP button. */ + button = button_add_pix(button_hbox, stop_xpm); + g_signal_connect(GTK_OBJECT(button), "clicked", + G_CALLBACK(emugtk_StopEvent), + NULL); + + /* Creating STEP button. */ + button = button_add_pix(button_hbox, step_xpm); + g_signal_connect(GTK_OBJECT(button), "clicked", + G_CALLBACK(emugtk_StepEvent), + NULL); + + return button_hbox; +} + +static GtkWidget * +AddMenu(void) +{ + GtkWidget *menu_bar; + + /* Creating menu item. */ + menu_bar = gtk_menu_bar_new(); + + /* Adding the 'File' submenu */ + FileAddMenu(menu_bar); + + /* Adding the 'View' submenu */ + ViewAddMenu(menu_bar); + + /* Adding the 'Help' submenu */ + HelpAddMenu(menu_bar); + + return menu_bar; +} + +static int +mainwin_configure_event(GtkWindow *window, GdkEvent *event, gpointer data) +{ + cfg->win_width = event->configure.width; + cfg->win_height = event->configure.height; + + /* + * Important: + * Returning false allows event to propagate to children. If not, they + * will not be resized when we resize the main window. + */ + return FALSE; +} + +static void +hpaned_notify_event(GtkWindow *window, GdkEvent *event, gpointer data) +{ + GtkWidget *paned = data; + + cfg->hpane_pos = gtk_paned_get_position(GTK_PANED(paned)); +} + +static void +vpaned_notify_event(GtkWindow *window, GdkEvent *event, gpointer data) +{ + GtkWidget *paned = data; + + cfg->vpane_pos = gtk_paned_get_position(GTK_PANED(paned)); +} + +static void +main_paned_notify_event(GtkWindow *window, GdkEvent *event, gpointer data) +{ + GtkWidget *paned = data; + + cfg->main_pane_pos = gtk_paned_get_position(GTK_PANED(paned)); +} + +void +emugtk_restart_gui(void) +{ + emugtk_stop_running(); + + gtk_widget_destroy(mainwin); + + restart_gui = true; +} + +void +emugtk_quit_gui(void) +{ + gtk_main_quit(); + + restart_gui = false; +} + +static GtkWidget * +emugtk_create_memory_paned(void) +{ + GtkWidget *vpaned; + GtkWidget *scrollwin; + + /* Create vpaned (memory windows) only if necessary. */ + if (cfg->view_int_memory || cfg->view_ext_memory) { + vpaned = gtk_vpaned_new(); + gtk_paned_set_position(GTK_PANED(vpaned), cfg->vpane_pos); + g_signal_connect(G_OBJECT(vpaned), "notify::position", + G_CALLBACK(vpaned_notify_event), vpaned); + + /* Internal memory dump frame. */ + if (cfg->view_int_memory) { + scrollwin = memwin_init("Internal memory (IRAM)", + INT_MEM_ID); + gtk_paned_pack1(GTK_PANED(vpaned), scrollwin, + FALSE, FALSE); + } + + /* External memory dump frame. */ + if (cfg->view_ext_memory) { + scrollwin = memwin_init("External memory (XRAM)", + EXT_MEM_ID); + gtk_paned_pack2(GTK_PANED(vpaned), scrollwin, + TRUE, FALSE); + } + + return vpaned; + } else + return NULL; +} + +/* + * mainwin + * +---------------------------------------------------------------------+ + * | | + * | vbox | + * | +---------------------------------------------------------------+ | + * | | | | + * | | menu_bar | | + * | | +----------------------+ | | + * | | | File View Help | | | + * | | +----------------------+ | | + * | | | | + * | |---------------------------------------------------------------| | + * | | | | + * | | buttons_bar | | + * | | +-----------------------+ | | + * | | | RST RUN STOP STEP | | | + * | | +-----------------------+ | | + * | | | | + * | |---------------------------------------------------------------| | + * | | | | + * | | main_paned | | + * | | +---------------------------------------------------------+ | | + * | | | | | | + * | | | hpaned | | | + * | | | +---------------------------------------------------+ | | | + * | | | | | | | | | + * | | | | scrollwin | scrollwin | | | | + * | | | | +------------------+ * +--------------------+ | | | | + * | | | | | REGISTERS window | * | Disassembly window | | | | | + * | | | | +------------------+ | +--------------------+ | | | | + * | | | | | | | | | + * | | | +---------------------------------------------------+ | | | + * | | | | | | + * | | |--------------------------***----------------------------- | | + * | | | | | | + * | | | vpaned | | | + * | | | +---------------------------------------------------+ | | | + * | | | | | | | | + * | | | | scrollwin | | | | + * | | | | +---------------------------------------------+ | | | | + * | | | | | Internal memory window | | | | | + * | | | | +---------------------------------------------+ | | | | + * | | | | | | | | + * | | | +-----------------------***-------------------------| | | | + * | | | | | | | | + * | | | | scrollwin | | | | + * | | | | +---------------------------------------------+ | | | | + * | | | | | External memory window | | | | | + * | | | | +---------------------------------------------+ | | | | + * | | | | | | | | + * | | | +---------------------------------------------------+ | | | + * | | | | | | + * | | +---------------------------------------------------------+ | | + * | | | | + * | | | | + * | +---------------------------------------------------------------+ | + * | | + * | | + * +---------------------------------------------------------------------+ + */ +static void +emugtk_window_init(void) +{ + GtkWidget *vbox; + GtkWidget *menu_bar; + GtkWidget *buttons_bar; + GtkWidget *scrollwin; + GtkWidget *hpaned; + GtkWidget *vpaned; + GtkWidget *main_paned; + + mainwin = gtk_window_new(GTK_WINDOW_TOPLEVEL); + gtk_window_set_title(GTK_WINDOW(mainwin), PACKAGE); + gtk_window_set_default_size(GTK_WINDOW(mainwin), + cfg->win_width, cfg->win_height); + gtk_container_set_border_width(GTK_CONTAINER(mainwin), 0); + + /* Window DESTROY event. */ + g_signal_connect(mainwin, "destroy", + G_CALLBACK(gtk_main_quit), NULL); + + g_signal_connect(G_OBJECT(mainwin), "configure-event", + G_CALLBACK(mainwin_configure_event), NULL); + + /* Creating the menu bar. */ + menu_bar = AddMenu(); + + /* Creating the buttons bar. */ + buttons_bar = AddButtons(); + + scrollwin = pswwin_init(); + gtk_box_pack_start(GTK_BOX(buttons_bar), scrollwin, FALSE, FALSE, 100); + + /* hpaned will contain registers and disassembly windows. */ + hpaned = gtk_hpaned_new(); + gtk_paned_set_position(GTK_PANED(hpaned), cfg->hpane_pos); + g_signal_connect(G_OBJECT(hpaned), "notify::position", + G_CALLBACK(hpaned_notify_event), hpaned); + + /* 8051 registers frame. */ + scrollwin = regwin_init(); + gtk_paned_pack1(GTK_PANED(hpaned), scrollwin, FALSE, FALSE); + + /* Program disassembly frame. */ + scrollwin = pgmwin_init(); + gtk_paned_pack2(GTK_PANED(hpaned), scrollwin, TRUE, FALSE); + + /* + * main_paned will contain two groups: + * group1: registers and disassembly windows. + * group2: memory windows + */ + if (cfg->layout == UI_LAYOUT1) + main_paned = gtk_vpaned_new(); + else + main_paned = gtk_hpaned_new(); + + gtk_paned_set_position(GTK_PANED(main_paned), cfg->main_pane_pos); + g_signal_connect(G_OBJECT(main_paned), "notify::position", + G_CALLBACK(main_paned_notify_event), main_paned); + gtk_paned_pack1(GTK_PANED(main_paned), hpaned, FALSE, FALSE); + + vpaned = emugtk_create_memory_paned(); + if (vpaned != NULL) + gtk_paned_pack2(GTK_PANED(main_paned), vpaned, + TRUE, FALSE); + + /* + * vbox contains the menu bar and body_vbox (for all remaining + * items). + */ + vbox = gtk_vbox_new(FALSE, 1); + gtk_box_pack_start(GTK_BOX(vbox), menu_bar, FALSE, FALSE, 1); + gtk_box_pack_start(GTK_BOX(vbox), buttons_bar, FALSE, FALSE, 1); + gtk_box_pack_start(GTK_BOX(vbox), main_paned, true, true, 1); + + /* Adding the vbox to the main window. */ + gtk_container_add(GTK_CONTAINER(mainwin), vbox); + + g_signal_connect(mainwin, "destroy", G_CALLBACK(emugtk_quit_gui), NULL); + + gtk_widget_show_all(mainwin); +} + +void +AddMenuSeparator(GtkWidget *menu) +{ + GtkWidget *item; + + item = gtk_menu_item_new(); + gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); +} + +void +emugtk_new_file(char *file) +{ + emugtk_stop_running(); + + LoadHexFile(file); + + if (cfg->clear_ram_on_file_load) + emugtk_Reset(); + + emugtk_UpdateDisplay(); +} + +int +main(int argc, char **argv) +{ + parse_command_line_options(argc, argv); + app_config_load(); + + cpu8051_init(); + + running = 0; + + gtk_init(&argc, &argv); + + if (options.filename != NULL) + LoadHexFile(options.filename); + + cpu8051_Reset(); + + while (restart_gui == true) { + log_info("Init GUI"); + + emugtk_window_init(); + emugtk_UpdateDisplay(); + gtk_main(); + } + + log_info("Terminate"); + + app_config_save(); + + return EXIT_SUCCESS; +} diff --git a/src/gtk/emugtk.h b/src/gtk/emugtk.h new file mode 100644 index 0000000..8e47427 --- /dev/null +++ b/src/gtk/emugtk.h @@ -0,0 +1,42 @@ +/* + * emugtk.h + * + * Copyright (C) 1999 Jonathan St-André + * Copyright (C) 1999 Hugo Villeneuve + * + * This program 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 of the License, or + * (at your option) any later version. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef EMUGTK_H +#define EMUGTK_H 1 + +#include + +void +AddMenuSeparator(GtkWidget *menu); + +void +emugtk_new_file(char *file); + +void +emugtk_UpdateDisplay(void); + +void +emugtk_restart_gui(void); + +void +emugtk_quit_gui(void); + +#endif /* EMUGTK_H */ diff --git a/src/gtk/filemenu.c b/src/gtk/filemenu.c new file mode 100644 index 0000000..d2dae9c --- /dev/null +++ b/src/gtk/filemenu.c @@ -0,0 +1,139 @@ +/* + * filemenu.c + * + * Copyright (C) 1999 Jonathan St-André + * Copyright (C) 1999 Hugo Villeneuve + * + * This program 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 of the License, or + * (at your option) any later version. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#if HAVE_CONFIG_H +# include "config.h" +#endif + +#include /* UNIX standard function definitions */ +#include +#include + +#include "common.h" +#include "emugtk.h" +#include "messagebox.h" +#include "filemenu.h" + +#define FILENAME_DESCRIPTION "Open Intel Hex file" + +static char previous_folder[MAX_FILENAME_LENGTH + 1]; + +static void +remember_current_folder(GtkFileChooser *chooser) +{ + char *folder; + + folder = gtk_file_chooser_get_current_folder(chooser); + + if (folder != NULL) { + if (strlen(folder) >= MAX_FILENAME_LENGTH) { + /* Non-critical error */ + log_warn("current folder name too long for buffer"); + } else { + log_info("current folder = %s", folder); + strncpy(previous_folder, folder, MAX_FILENAME_LENGTH); + } + + g_free(folder); + } +} + +void +FileOpenEvent(GtkObject *object, gpointer data) +{ + GtkWidget *file_dialog; + char *dir; + char *cwd = NULL; + + log_info("FileOpenEvent()"); + + /* Create a new file selection widget. */ + file_dialog = gtk_file_chooser_dialog_new( + FILENAME_DESCRIPTION, NULL, GTK_FILE_CHOOSER_ACTION_OPEN, + GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, + GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, NULL); + + if (strlen(previous_folder) == 0) { + /* Opening file chooser to current working directory. */ + cwd = g_get_current_dir(); + dir = cwd; + } else { + /* Opening file chooser to previous opened directory. */ + dir = previous_folder; + } + + gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(file_dialog), dir); + + if (cwd) + g_free(cwd); + + if (gtk_dialog_run(GTK_DIALOG(file_dialog)) == GTK_RESPONSE_ACCEPT) { + char *selected_file; + + selected_file = gtk_file_chooser_get_filename( + GTK_FILE_CHOOSER(file_dialog)); + + if (selected_file != NULL) { + log_info("emugtk_File = %s", selected_file); + + remember_current_folder(GTK_FILE_CHOOSER(file_dialog)); + + emugtk_new_file(selected_file); + g_free(selected_file); + } + } + + gtk_widget_destroy(file_dialog); +} + +static void +FileQuitEvent(gchar *string) +{ + emugtk_quit_gui(); +} + +void +FileAddMenu(GtkWidget *menu_bar) +{ + GtkWidget *item; + GtkWidget *menu; + + menu = gtk_menu_new(); + + /* Create the 'open' item. */ + item = gtk_menu_item_new_with_label(FILENAME_DESCRIPTION); + gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); + /* Attach the callback functions to the activate signal. */ + g_signal_connect(item, "activate", G_CALLBACK(FileOpenEvent), NULL); + + AddMenuSeparator(menu); + + item = gtk_menu_item_new_with_label("Exit"); + gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); + /* We can attach the Quit menu item to our exit function */ + g_signal_connect(item, "activate", G_CALLBACK(FileQuitEvent), + (gpointer) "file.quit"); + + /* Adding submenu title. */ + item = gtk_menu_item_new_with_label("File"); + gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), menu); + gtk_menu_shell_append((GtkMenuShell *) menu_bar, item); +} diff --git a/src/gtk/filemenu.h b/src/gtk/filemenu.h new file mode 100644 index 0000000..fe9688a --- /dev/null +++ b/src/gtk/filemenu.h @@ -0,0 +1,36 @@ +/* + * filemenu.h + * + * Copyright (C) 1999 Jonathan St-André + * Copyright (C) 1999 Hugo Villeneuve + * + * This program 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 of the License, or + * (at your option) any later version. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef FILEMENU_H +#define FILEMENU_H 1 + +#include + +void +FileOpenEvent(GtkObject *object, gpointer data); + +void +FileResetEvent(GtkObject *object, gpointer data); + +void +FileAddMenu(GtkWidget *menu_bar); + +#endif /* FILEMENU_H */ diff --git a/src/gtk/helpmenu.c b/src/gtk/helpmenu.c new file mode 100644 index 0000000..4a8d9dc --- /dev/null +++ b/src/gtk/helpmenu.c @@ -0,0 +1,119 @@ +/* + * helpmenu.c + * + * Copyright (C) 1999 Jonathan St-André + * Copyright (C) 1999 Hugo Villeneuve + * + * This program 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 of the License, or + * (at your option) any later version. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#if HAVE_CONFIG_H +# include "config.h" +#endif + +#include + +#if STDC_HEADERS +# include +#elif HAVE_STRINGS_H +# include +#endif + +#include + +#include "common.h" +#include "options.h" +#include "emugtk.h" +#include "messagebox.h" +#include "helpmenu.h" + +#define PACKAGE_COPYRIGHT "(c) Hugo Villeneuve" + +static void +HelpCommandsEvent(gchar *string) +{ + ShowMessage("Command Line Options", COMMAND_LINE_OPTIONS, + GTK_JUSTIFY_LEFT, MESSAGE_DIALOG_FIXED_FONT); +} + +static void +HelpAboutEvent(GtkWidget *widget, gpointer data) +{ + const char *authors[] = { + "Hugo Villeneuve ", + "Jonathan St-André", + "Pascal Fecteau", + "Jimmy Ringuette", + NULL, + }; + + const char *license = + "This program 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 of the License, or (at your option) any later" + " version.\n\n" + "This program 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.\n\n" + "You should have received a copy of the GNU General Public" + " License along with this program. If not, see\n" + " "; + + gtk_show_about_dialog( + NULL, + "name", PACKAGE_NAME, + "title", "About Dialog", + "version", PACKAGE_VERSION, + "logo-icon-name", PACKAGE_TARNAME, + "comments", get_package_description(), + "authors", authors, + "website", PACKAGE_URL, + "copyright", PACKAGE_COPYRIGHT, + "license", license, + "wrap-license", true, + NULL); +} + +void +HelpAddMenu(GtkWidget *menu_bar) +{ + GtkWidget *item; + GtkWidget *menu; + + menu = gtk_menu_new(); + + /* Create the 'Help Command Line Options' item. */ + item = gtk_menu_item_new_with_label("Command Line Options"); + gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); + /* Attach the callback functions to the activate signal. */ + g_signal_connect(item, "activate", G_CALLBACK(HelpCommandsEvent), NULL); + + AddMenuSeparator(menu); + + /* Create the 'Help About' item. */ + item = gtk_menu_item_new_with_label("About " PACKAGE); + gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); + /* Attach the callback functions to the activate signal. */ + g_signal_connect(item, "activate", G_CALLBACK(HelpAboutEvent), NULL); + + /* Adding submenu title. */ + item = gtk_menu_item_new_with_label("Help"); + gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), menu); + gtk_menu_shell_append((GtkMenuShell *) menu_bar, item); +} diff --git a/src/gtk/helpmenu.h b/src/gtk/helpmenu.h new file mode 100644 index 0000000..63908dd --- /dev/null +++ b/src/gtk/helpmenu.h @@ -0,0 +1,30 @@ +/* + * helpmenu.h + * + * Copyright (C) 1999 Jonathan St-André + * Copyright (C) 1999 Hugo Villeneuve + * + * This program 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 of the License, or + * (at your option) any later version. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef HELPMENU_H +#define HELPMENU_H 1 + +#include + +void +HelpAddMenu(GtkWidget *menu_bar); + +#endif /* HELPMENU_H */ diff --git a/src/gtk/memwin.c b/src/gtk/memwin.c new file mode 100644 index 0000000..58ce1d2 --- /dev/null +++ b/src/gtk/memwin.c @@ -0,0 +1,346 @@ +/* + * memwin.c + * + * Copyright (C) 1999 Jonathan St-André + * Copyright (C) 1999 Hugo Villeneuve + * + * This program 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 of the License, or + * (at your option) any later version. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#if HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include /* For isprint */ + +#include "common.h" +#include "memory.h" +#include "hexfile.h" +#include "cpu8051.h" +#include "regwin.h" +#include "memwin.h" +#include "emugtk.h" +#include "options.h" +#include "app-config.h" + +extern struct app_config_t *cfg; +extern struct options_t options; + +static int COL_ASCII; +static int N_COLUMNS; + +enum +{ + COL_ADDRESS = 0, + COL_DATA0, +}; + +static GtkWidget *memlist_internal; +static GtkWidget *memlist_external; + +/* Creating a model */ +static GtkListStore * +memwin_init_store(int data_rows) +{ + GtkTreeIter iter; + int row; + int col; + GtkListStore *store; + GType col_types[N_COLUMNS]; + + /* No need for static array, all our columns are of the same type. */ + for (col = 0; col < N_COLUMNS; col++) + col_types[col] = G_TYPE_STRING; + + store = gtk_list_store_newv(N_COLUMNS, col_types); + + /* Add rows. */ + for (row = 0; row < data_rows; row++) + gtk_list_store_append(store, &iter); + + return store; +} + +static void +memwin_cell_edited(GtkCellRendererText *cell, gchar *path_string, + gchar *new_str, gpointer model) +{ + guint column; + guint memory_id; + gpointer columnptr; + gpointer memory_id_ptr; + GtkTreeIter iter; + int address; + u_int8_t old; + int new; + char *str; + + if (!model) { + g_error("Unable to get model from cell renderer"); + } + + /* Column number is passed as renderer object data */ + columnptr = g_object_get_data(G_OBJECT(cell), "column"); + column = GPOINTER_TO_UINT(columnptr); + + /* Memory ID is passed as renderer object data */ + memory_id_ptr = g_object_get_data(G_OBJECT(cell), "memory_id"); + memory_id = GPOINTER_TO_UINT(memory_id_ptr); + + /* Get the iterator */ + gtk_tree_model_get_iter_from_string(model, &iter, path_string); + + /* Get base address. */ + gtk_tree_model_get(model, &iter, COL_ADDRESS, &str, -1); + address = asciihex2int(str); + + /* Convert column number (1, 2, 3...) to index (0, 1, 2...) */ + address += (column - COL_DATA0); + old = memory_read8(memory_id, address); + + log_info("Address: $%02X", address); + log_info(" old value: $%02X", old); + + /* Convert new value (asciihex) to integer. */ + new = asciihex2int(new_str); + if ((new < 0) || (new > 255)) { + log_info(" new value: out of range"); + new = old; /* Put back old value... */ + } else { + log_info(" new value: $%02X", new); + } + + /* Store new value in emulator memory. */ + memory_write8(memory_id, address, new); + + /* Convert to text. */ + int2asciihex(new, str, 2); + + /* Store new value in gtk model. */ + gtk_list_store_set(GTK_LIST_STORE(model), &iter, column, str, -1); + + /* + * Make sure to update all registers and memory. + * For example, BANKed registers depends on internal memory. + */ + emugtk_UpdateDisplay(); +}; + +static void +memwin_init_columns(GtkWidget *listview, int memory_id) +{ + int i; + GtkCellRenderer *renderer; + GtkTreeViewColumn *column; + + /* Columns and cell renderers */ + renderer = gtk_cell_renderer_text_new(); + + /* Add address column */ + column = gtk_tree_view_column_new_with_attributes( + "Address", renderer, "text", COL_ADDRESS, NULL); + gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_AUTOSIZE); + gtk_tree_view_append_column(GTK_TREE_VIEW(listview), column); + + for (i = COL_DATA0; i < (COL_DATA0 + cfg->bits_per_row); i++) { + char col_name[8]; + + /* Create new renderer for each editable cell. */ + renderer = gtk_cell_renderer_text_new(); + + /* Allow edition, align to left side. */ + g_object_set(renderer, "editable", TRUE, "xalign", 0, NULL); + + g_signal_connect(renderer, "edited", + G_CALLBACK(memwin_cell_edited), + gtk_tree_view_get_model( + GTK_TREE_VIEW(listview))); + + /* Add column index and memory_id, used when editing the cell. */ + g_object_set_data(G_OBJECT(renderer), "column", + GUINT_TO_POINTER(i)); + g_object_set_data(G_OBJECT(renderer), "memory_id", + GUINT_TO_POINTER(memory_id)); + + /* Use two digits only if DATA_ROWS > 10 */ + if (cfg->bits_per_row < 10) + sprintf(col_name, "B%1d", i - COL_DATA0); + else + sprintf(col_name, "B%02d", i - COL_DATA0); + + column = gtk_tree_view_column_new_with_attributes( + col_name, renderer, "text", i, NULL); + gtk_tree_view_column_set_sizing(column, + GTK_TREE_VIEW_COLUMN_AUTOSIZE); + gtk_tree_view_append_column(GTK_TREE_VIEW(listview), column); + } + + /* Add ASCII column, using fixed-font. */ + renderer = gtk_cell_renderer_text_new(); + g_object_set(renderer, "family", "Monospace", NULL); + column = gtk_tree_view_column_new_with_attributes( + "ASCII", renderer, "text", COL_ASCII, NULL); + gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_AUTOSIZE); + gtk_tree_view_append_column(GTK_TREE_VIEW(listview), column); +} + +static int +compute_data_rows(int memory_id) +{ + int data_rows; + + if (memory_id == INT_MEM_ID) { + data_rows = options.iram_size / cfg->bits_per_row; + } else if (memory_id == EXT_MEM_ID) { + data_rows = options.xram_size / cfg->bits_per_row; + } else { + log_fail("Invalid memory type"); + exit(1); + } + + return data_rows; +} + +GtkWidget * +memwin_init(char *title, int memory_id) +{ + GtkWidget *frame; + GtkWidget *scrollwin; + GtkListStore *store; + GtkWidget *memlist; + int data_rows; + + COL_ASCII = cfg->bits_per_row + 1; + N_COLUMNS = COL_ASCII + 1; + + frame = gtk_frame_new(title); + + scrollwin = gtk_scrolled_window_new(NULL, NULL); + gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrollwin), + GTK_SHADOW_ETCHED_OUT); + + /* Automatically add scrollbars when necessary. */ + gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrollwin), + GTK_POLICY_AUTOMATIC, + GTK_POLICY_AUTOMATIC); + + gtk_container_add(GTK_CONTAINER(frame), scrollwin); + + data_rows = compute_data_rows(memory_id); + + /* Creating a model */ + store = memwin_init_store(data_rows); + + /* Creating the view component */ + memlist = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store)); + gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(memlist), TRUE); + gtk_container_add(GTK_CONTAINER(scrollwin), memlist); + + if (memory_id == INT_MEM_ID) { + memlist_internal = memlist; + } else if (memory_id == EXT_MEM_ID) { + memlist_external = memlist; + } else { + log_fail("Invalid memory type"); + exit(1); + } + + memwin_init_columns(memlist, memory_id); + + /* + * The tree view has acquired its own reference to the model, so we can + * drop ours. That way the model will be freed automatically when the + * tree view is destroyed. + */ + g_object_unref(store); + + return frame; +} + +/* Dump internal or external memory. */ +void +memwin_refresh(int memory_id) +{ + int row; + unsigned int Address; + GtkListStore *store; + GtkWidget *memlist; + int data_rows; + + Address = 0; + + data_rows = compute_data_rows(memory_id); + + if (memory_id == INT_MEM_ID) { + memlist = memlist_internal; + } else if (memory_id == EXT_MEM_ID) { + memlist = memlist_external; + } else { + log_fail("Invalid memory type"); + exit(1); + } + + store = GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(memlist))); + + for (row = 0; row < data_rows; row++) { + int valid; + GtkTreeIter iter; + char str[4+1]; /* Maximum str len is for address column (4 digits) */ + char ascii_str[16+1]; /* Maximum 16 data columns. */ + int col; + + if (row == 0) { + /* Get first row in list store */ + valid = gtk_tree_model_get_iter_first( + GTK_TREE_MODEL(store), &iter); + } else { + /* Get next row in list store */ + valid = gtk_tree_model_iter_next( + GTK_TREE_MODEL(store), &iter); + } + + if (!valid) { + printf("Invalid iter...\n"); + return; + } + + /* Display base address. */ + int2asciihex(Address, str, 4); + + gtk_list_store_set(store, &iter, COL_ADDRESS, str, -1); + + for (col = 0; col < cfg->bits_per_row; col++) { + u_int8_t data; + + data = memory_read8(memory_id, Address + col); + + /* Display hex data */ + int2asciihex(data, str, 2); + + gtk_list_store_set(store, &iter, col + 1, str, -1); + + /* Append to ASCII string (if applicable). */ + if (!isprint(data)) + data = '.'; + sprintf(&ascii_str[col], "%c", data); + } + + /* Display ASCII characters. */ + gtk_list_store_set(store, &iter, COL_ASCII, ascii_str, -1); + + Address += cfg->bits_per_row; + } +} diff --git a/src/gtk/memwin.h b/src/gtk/memwin.h new file mode 100644 index 0000000..ccb528d --- /dev/null +++ b/src/gtk/memwin.h @@ -0,0 +1,33 @@ +/* + * memwin.h + * + * Copyright (C) 1999 Jonathan St-André + * Copyright (C) 1999 Hugo Villeneuve + * + * This program 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 of the License, or + * (at your option) any later version. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef MEMWIN_H +#define MEMWIN_H 1 + +#include + +GtkWidget * +memwin_init(char *title, int memory_id); + +void +memwin_refresh(int memory_id); + +#endif /* MEMWIN_H */ diff --git a/src/gtk/messagebox.c b/src/gtk/messagebox.c new file mode 100644 index 0000000..c4d3723 --- /dev/null +++ b/src/gtk/messagebox.c @@ -0,0 +1,98 @@ +/* + * messagebox.c + * + * Copyright (C) 1999 Jonathan St-André + * Copyright (C) 1999 Hugo Villeneuve + * + * This program 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 of the License, or + * (at your option) any later version. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#if HAVE_CONFIG_H +# include "config.h" +#endif + +#include + +#include "common.h" +#include "messagebox.h" + +#define MESSAGE_DIALOG_BORDER 25 + +#define BUTTON_TEXT_BORDER 3 + +extern GtkWidget *mainwin; + +void +ShowMessage(gchar *title, gchar *message, int justification, int font_style) +{ + GtkWidget *dialog; + GtkWidget *label; + GtkWidget *label_window; + + /* Keep the dialog on top of the main window, and centered. */ + dialog = gtk_dialog_new_with_buttons( + title, GTK_WINDOW(mainwin), + GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT, GTK_STOCK_OK, + GTK_RESPONSE_NONE, NULL); + + /* + * The GtkLabel widget is one of a few GTK+ widgets that don't create + * their own window to render themselves into. Instead, they draw + * themselves directly onto their parents window. This means that in + * order to set a property for a GtkLabel widget, you need to change the + * property of its parent, i.e. the object that you pack it into. + * Another solution (short term workaround) is to put the label widget + * inside another widget that does get its own window, like the + * 'ViewPort' or 'EventBox' widget. + */ + + /* + * Using workaround described above to set the border width of 'label' + * widget. + */ + label_window = gtk_event_box_new(); + + /* Creating our label. */ + label = gtk_label_new(message); + gtk_label_set_justify(GTK_LABEL(label), justification); + + if (font_style == MESSAGE_DIALOG_FIXED_FONT) { + PangoFontDescription *pango_font; + + pango_font = pango_font_description_from_string(FIXED_FONT); + gtk_widget_modify_font(label, pango_font); + } + + /* Adding label widget to label_window widget. */ + gtk_container_add(GTK_CONTAINER(label_window), label); + + /* + * Changing border width of the label widget by way of label_window + * widget. + */ + gtk_container_set_border_width(GTK_CONTAINER(label_window), + MESSAGE_DIALOG_BORDER); + + /* Ensure that the dialog box is destroyed when the user responds */ + g_signal_connect_swapped(dialog, "response", + G_CALLBACK(gtk_widget_destroy), dialog); + + /* Add the label_window to the dialog window. */ + gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), + label_window); + + /* Show everything we've added to the dialog. */ + gtk_widget_show_all(dialog); +} diff --git a/src/gtk/messagebox.h b/src/gtk/messagebox.h new file mode 100644 index 0000000..991e758 --- /dev/null +++ b/src/gtk/messagebox.h @@ -0,0 +1,33 @@ +/* + * messagebox.h + * + * Copyright (C) 1999 Jonathan St-André + * Copyright (C) 1999 Hugo Villeneuve + * + * This program 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 of the License, or + * (at your option) any later version. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef MESSAGEBOX_H +#define MESSAGEBOX_H 1 + +#include + +#define MESSAGE_DIALOG_NORMAL_FONT 0 +#define MESSAGE_DIALOG_FIXED_FONT 1 + +void +ShowMessage(gchar *title, gchar *message, int justification, int font_style); + +#endif /* MESSAGEBOX_H */ diff --git a/src/gtk/pgmwin.c b/src/gtk/pgmwin.c new file mode 100644 index 0000000..0e8961b --- /dev/null +++ b/src/gtk/pgmwin.c @@ -0,0 +1,299 @@ +/* + * pgmwin.c + * + * Copyright (C) 1999 Jonathan St-André + * Copyright (C) 1999 Hugo Villeneuve + * + * This program 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 of the License, or + * (at your option) any later version. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#if HAVE_CONFIG_H +# include "config.h" +#endif + +#include + +#include "common.h" +#include "memory.h" +#include "cpu8051.h" +#include "pgmwin.h" +#include "hexfile.h" + +static GtkWidget *pgmlist; + +#define LIST_VIEW_NAME "Program" +#define DATA_ROWS 100 + +enum +{ + COL_BREAKPT = 0, + COL_ADDR, + COL_B0, + COL_B1, + COL_B2, + COL_INST, + COL_ARGS, + COL_COLOR, + N_COLUMNS, +}; + +static char *col_names[N_COLUMNS] = { + "BPT", + "Address", + "B0", + "B1", + "B2", + "Mnemonic", + "Arguments", + "COLOR", /* Not displayed, used to set foreground color of cell. */ +}; + +/* Creating a model */ +static GtkListStore * +pgmwin_init_store(void) +{ + GtkTreeIter iter; + int row; + int col; + GtkListStore *store; + GType col_types[N_COLUMNS]; + + /* No need for static array, all our columns are of the same type. */ + for (col = 0; col < N_COLUMNS; col++) + col_types[col] = G_TYPE_STRING; + + store = gtk_list_store_newv(N_COLUMNS, col_types); + + /* Add rows. */ + for (row = 0; row < DATA_ROWS; row++) { + gtk_list_store_append(store, &iter); + + /* Color first row in red (current instruction). */ + if (row == 0) + gtk_list_store_set(store, &iter, COL_COLOR, "red", -1); + else + gtk_list_store_set(store, &iter, COL_COLOR, "black", -1); + } + + return store; +} + +static void +pgmwin_init_columns(void) +{ + int k; + GtkCellRenderer *renderer; + + /* Create renderer */ + renderer = gtk_cell_renderer_text_new(); + + /* Add columns, except for last one (COL_COLOR). */ + for (k = 0; k < COL_COLOR; k++) { + GtkTreeViewColumn *col; + + /* Create tree view column */ + col = gtk_tree_view_column_new(); + gtk_tree_view_column_set_title(col, col_names[k]); + gtk_tree_view_column_set_sizing(col, + GTK_TREE_VIEW_COLUMN_AUTOSIZE); + gtk_tree_view_append_column(GTK_TREE_VIEW(pgmlist), col); + + /* Pack cell renderer into column */ + gtk_tree_view_column_pack_start(col, renderer, TRUE); + + /* Establish connection between cell renderer and data store. */ + gtk_tree_view_column_set_attributes(col, renderer, "text", k, + "foreground", COL_COLOR, + NULL); + } +} + +/* Mouse button pressed in the window. */ +static gint +pgmwin_sel_changed_event(GtkWidget *widget, GdkEvent *event, gpointer data) +{ + GtkTreeSelection *selection; + GtkTreeModel *model; + GtkTreeIter iter; + + log_debug("pgmwin_sel_changed_event()"); + + /* This will only work in single or browse selection mode! */ + selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(pgmlist)); + + if (gtk_tree_selection_get_selected(selection, &model, &iter)) { + char *str_addr; + int val; + + gtk_tree_model_get(model, &iter, COL_ADDR, &str_addr, -1); + + /* Convert hex address in ASCII to integer. */ + val = asciihex2int(str_addr); + + log_debug(" row address is: $%04X", val); + + ToggleBreakpoint(val); + pgmwin_refresh(); + + g_free(str_addr); + } else { + log_debug(" no row selected"); + } + + return FALSE; +} + +GtkWidget * +pgmwin_init(void) +{ + GtkWidget *frame; + GtkWidget *scrollwin; + GtkListStore *store; + GtkTreeSelection *selection; + + frame = gtk_frame_new(LIST_VIEW_NAME); + + scrollwin = gtk_scrolled_window_new(NULL, NULL); + gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrollwin), + GTK_SHADOW_ETCHED_OUT); + + /* Automatically add scrollbars when necessary. */ + gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrollwin), + GTK_POLICY_AUTOMATIC, + GTK_POLICY_AUTOMATIC); + + gtk_container_add(GTK_CONTAINER(frame), scrollwin); + + /* Creating a model */ + store = pgmwin_init_store(); + + /* Creating the view component */ + pgmlist = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store)); + gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(pgmlist), TRUE); + gtk_container_add(GTK_CONTAINER(scrollwin), pgmlist); + + selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(pgmlist)); + + /* Only one row can be selected at a time. */ + gtk_tree_selection_set_mode(selection, GTK_SELECTION_BROWSE); + + g_signal_connect(selection, "changed", + G_CALLBACK(pgmwin_sel_changed_event), NULL); + + pgmwin_init_columns(); + + /* + * The tree view has acquired its own reference to the model, so we can + * drop ours. That way the model will be freed automatically when the + * tree view is destroyed. + */ + g_object_unref(store); + + return frame; +} + +/* Show disassembled program. */ +void +pgmwin_refresh(void) +{ + int row; + GtkListStore *store; + unsigned int Address; + + Address = cpu8051.pc; + + store = GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(pgmlist))); + + for (row = 0; row < DATA_ROWS; row++) { + int valid; + GtkTreeIter iter; + char str[128]; + int k; + int col_id; + int InstSize; + unsigned char OpCode; + + if (row == 0) { + /* Get first row in list store */ + valid = gtk_tree_model_get_iter_first( + GTK_TREE_MODEL(store), &iter); + } else { + /* Get next row in list store */ + valid = gtk_tree_model_iter_next( + GTK_TREE_MODEL(store), &iter); + } + + if (!valid) { + printf("Invalid iter...\n"); + return; + } + + if (Address > 0xFFFF) { + /* + * Not the most elegant solution, but it works to not + * display instructions past last address, 0xFFFF. + */ + gtk_list_store_set(store, &iter, + COL_BREAKPT, NULL, + COL_ADDR, NULL, + COL_B0, NULL, + COL_B1, NULL, + COL_B2, NULL, + COL_INST, NULL, + COL_ARGS, NULL, + COL_COLOR, NULL, + -1); + } else { + /* Display breakpoints. */ + if (IsBreakpoint(Address)) + sprintf(str, "*"); + else + str[0] = '\0'; + + gtk_list_store_set(store, &iter, COL_BREAKPT, str, -1); + + /* Display base address. */ + int2asciihex(Address, str, 4); + + gtk_list_store_set(store, &iter, COL_ADDR, str, -1); + + OpCode = memory_read8(PGM_MEM_ID, Address); + InstSize = cpu8051_get_instruction_size(OpCode); + + /* Display instruction hex bytes. */ + for (k = 0, col_id = COL_B0; k < 3; k++, col_id++) { + if (k < InstSize) + int2asciihex(memory_read8(PGM_MEM_ID, + Address + k), + str, 2); + else + str[0] = '\0'; + + gtk_list_store_set(store, &iter, col_id, str, -1); + } + + /* Display instruction menmonic. */ + cpu8051_disasm_mnemonic(OpCode, str); + gtk_list_store_set(store, &iter, COL_INST, str, -1); + + /* Display instruction arguments (if applicable). */ + str[0] = '\0'; + cpu8051_disasm_args(Address, str); + gtk_list_store_set(store, &iter, COL_ARGS, str, -1); + + Address += InstSize; + } + } +} diff --git a/src/gtk/pgmwin.h b/src/gtk/pgmwin.h new file mode 100644 index 0000000..952d931 --- /dev/null +++ b/src/gtk/pgmwin.h @@ -0,0 +1,36 @@ +/* + * pgmwin.h + * + * Copyright (C) 1999 Jonathan St-André + * Copyright (C) 1999 Hugo Villeneuve + * + * This program 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 of the License, or + * (at your option) any later version. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef PGMWIN_H +#define PGMWIN_H 1 + +#include + +GtkWidget * +pgmwin_init(void); + +void +pgmwin_refresh(void); + +int +pgmwin_IsBreakpoint(unsigned int address); + +#endif /* PGMWIN_H */ diff --git a/src/gtk/pswwin.c b/src/gtk/pswwin.c new file mode 100644 index 0000000..94f733c --- /dev/null +++ b/src/gtk/pswwin.c @@ -0,0 +1,247 @@ +/* + * pswwin.c + * + * Copyright (C) 1999 Jonathan St-André + * Copyright (C) 1999 Hugo Villeneuve + * + * This program 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 of the License, or + * (at your option) any later version. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#if HAVE_CONFIG_H +# include "config.h" +#endif + +#include + +#include "common.h" +#include "reg8051.h" +#include "cpu8051.h" +#include "memory.h" +#include "pswwin.h" +#include "memwin.h" +#include "pgmwin.h" +#include "psw.h" +#include "instructions_8051.h" +#include "hexfile.h" +#include "emugtk.h" + +static GtkWidget *pswlist; + +#define DATA_ROWS 1 +#define LIST_VIEW_NAME "PSW" +enum +{ + COL_CY = 0, + COL_AC, + COL_F0, + COL_RS1, + COL_RS0, + COL_OV, + COL_RESERVED, + COL_P, + N_COLUMNS, +}; + +static char *col_names[N_COLUMNS] = { + "CY", + "AC", + "F0", + "RS1", + "RS0", + "OV", + "-", + "P", +}; + +/* Creating a model */ +static GtkListStore * +pswwin_init_store(void) +{ + GtkTreeIter iter; + int row; + int col; + GtkListStore *store; + GType col_types[N_COLUMNS]; + + /* No need for static array, all our columns are of the same type. */ + for (col = 0; col < N_COLUMNS; col++) + col_types[col] = G_TYPE_STRING; + + store = gtk_list_store_newv(N_COLUMNS, col_types); + + /* Add rows. */ + for (row = 0; row < DATA_ROWS; row++) + gtk_list_store_append(store, &iter); + + return store; +} + +static void +pswwin_cell_edited(GtkCellRendererText *cell, gchar *path_string, + gchar *new_str, gpointer model) +{ + guint column; + gpointer columnptr; + GtkTreeIter iter; + u_int8_t old; + int new; + char str[10]; + int bit_index; + + if (!model) { + g_error("Unable to get model from cell renderer"); + } + + /* Column number is passed as renderer object data */ + columnptr = g_object_get_data(G_OBJECT(cell), "column"); + column = GPOINTER_TO_UINT(columnptr); + + log_info("column = $%02X", column); + + /* Get the iterator */ + gtk_tree_model_get_iter_from_string(model, &iter, path_string); + + bit_index = 7 - column; + + old = psw_read_bit(bit_index); + + log_info(" old value: %d", old); + + /* Convert new value (asciihex) to integer. */ + new = asciihex2int(new_str); + + if ((new != 0) && (new != 1)) { + log_info(" new value: out of range"); + new = old; /* Put back old value... */ + } else { + log_info(" new value: %d", new); + } + + /* Store new value in emulator memory. */ + psw_write_bit(bit_index, new); + + /* Convert to text. */ + int2asciihex(new, str, 1); + + /* Store new value in gtk model. */ + gtk_list_store_set(GTK_LIST_STORE(model), &iter, column, str, -1); + + /* + * Make sure to update all registers and memory. + * For example, BANKed registers depends on internal memory. + */ + emugtk_UpdateDisplay(); +}; + +static void +pswwin_init_columns(void) +{ + int k; + + /* Add column for each bit in PSW. */ + for (k = 0; k < N_COLUMNS; k++) { + GtkCellRenderer *renderer; + GtkTreeViewColumn *column; + + /* Create new renderer for value column (editable). */ + renderer = gtk_cell_renderer_text_new(); + + /* Allow edition, align to center. */ + g_object_set(renderer, "editable", TRUE, "xalign", 0.5, NULL); + + g_signal_connect(renderer, "edited", + G_CALLBACK(pswwin_cell_edited), + gtk_tree_view_get_model(GTK_TREE_VIEW(pswlist))); + + /* Add column index, used when editing the cell. */ + g_object_set_data(G_OBJECT(renderer), "column", + GUINT_TO_POINTER(k)); + + column = gtk_tree_view_column_new_with_attributes( + col_names[k], renderer, "text", k, NULL); + + /* Center column name */ + g_object_set(column, "alignment", 0.5, NULL); + + /* Hardcoded width... */ + gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_FIXED); + gtk_tree_view_column_set_fixed_width(column, 35); + + gtk_tree_view_append_column(GTK_TREE_VIEW(pswlist), column); + } +} + +GtkWidget * +pswwin_init(void) +{ + GtkWidget *frame; + GtkListStore *store; + + frame = gtk_frame_new(LIST_VIEW_NAME); + + /* Creating a model */ + store = pswwin_init_store(); + + /* Creating the view component */ + pswlist = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store)); + + gtk_tree_view_set_grid_lines(GTK_TREE_VIEW(pswlist), GTK_TREE_VIEW_GRID_LINES_BOTH); + + gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(pswlist), TRUE); + gtk_container_add(GTK_CONTAINER(frame), pswlist); + + pswwin_init_columns(); + + /* + * The tree view has acquired its own reference to the model, so we can + * drop ours. That way the model will be freed automatically when the + * tree view is destroyed. + */ + g_object_unref(store); + + return frame; +} + +/* Show registers. */ +void +pswwin_refresh(void) +{ + GtkListStore *store; + int valid; + GtkTreeIter iter; + int k; + + store = GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(pswlist))); + + /* Get first row in list store */ + valid = gtk_tree_model_get_iter_first( + GTK_TREE_MODEL(store), &iter); + + if (!valid) { + printf("Invalid iter...\n"); + return; + } + + /* Display bit values. */ + for (k = 0; k < N_COLUMNS; k++) { + char str[4]; + int bit_index; + + bit_index = 7 - k; + + int2asciihex(psw_read_bit(bit_index), str, 1); + gtk_list_store_set(store, &iter, k, str, -1); + } +} diff --git a/src/gtk/pswwin.h b/src/gtk/pswwin.h new file mode 100644 index 0000000..84d34dd --- /dev/null +++ b/src/gtk/pswwin.h @@ -0,0 +1,33 @@ +/* + * pswwin.h + * + * Copyright (C) 1999 Jonathan St-André + * Copyright (C) 1999 Hugo Villeneuve + * + * This program 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 of the License, or + * (at your option) any later version. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef PSWWIN_H +#define PSWWIN_H 1 + +#include + +GtkWidget * +pswwin_init(void); + +void +pswwin_refresh(void); + +#endif /* PSWWIN_H */ diff --git a/src/gtk/regwin.c b/src/gtk/regwin.c new file mode 100644 index 0000000..8c4cd4d --- /dev/null +++ b/src/gtk/regwin.c @@ -0,0 +1,256 @@ +/* + * regwin.c + * + * Copyright (C) 1999 Jonathan St-André + * Copyright (C) 1999 Hugo Villeneuve + * + * This program 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 of the License, or + * (at your option) any later version. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#if HAVE_CONFIG_H +# include "config.h" +#endif + +#include + +#include "common.h" +#include "reg8051.h" +#include "cpu8051.h" +#include "sfr.h" +#include "memory.h" +#include "regwin.h" +#include "memwin.h" +#include "pgmwin.h" +#include "instructions_8051.h" +#include "hexfile.h" +#include "emugtk.h" + +static GtkWidget *reglist; + +#define LIST_VIEW_NAME "Registers" +#define DATA_ROWS SFR_REGS + +enum +{ + COL_NAME = 0, + COL_VAL, + N_COLUMNS, +}; + +/* Creating a model */ +static GtkListStore * +regwin_init_store(void) +{ + GtkTreeIter iter; + int row; + int col; + GtkListStore *store; + GType col_types[N_COLUMNS]; + + /* No need for static array, all our columns are of the same type. */ + for (col = 0; col < N_COLUMNS; col++) + col_types[col] = G_TYPE_STRING; + + store = gtk_list_store_newv(N_COLUMNS, col_types); + + /* Add rows. */ + for (row = 0; row < DATA_ROWS; row++) + gtk_list_store_append(store, &iter); + + return store; +} + +static void +regwin_cell_edited(GtkCellRendererText *cell, gchar *path_string, + gchar *new_str, gpointer model) +{ + GtkTreeIter iter; + int old; + int new; + char *str; + struct regwin_infos_t *regwin_infos; + + if (!model) { + g_error("Unable to get model from cell renderer"); + } + + /* Get the iterator */ + gtk_tree_model_get_iter_from_string(model, &iter, path_string); + + /* Get register name. */ + gtk_tree_model_get(model, &iter, COL_NAME, &str, -1); + + log_info("Register: %s", str); + regwin_infos = sfr_get_infos(str); + + /* Read current (old) value. */ + gtk_tree_model_get(model, &iter, COL_VAL, &str, -1); + + old = asciihex2int(str); + + if (regwin_infos->w == 2) + log_info(" old value: $%02X", old); + else if (regwin_infos->w == 4) + log_info(" old value: $%04X", old); + + new = asciihex2int(new_str); + + if (regwin_infos->w == 2) { + if ((new < 0) || (new > 0xFF)) { + log_info(" new value: out of range"); + new = old; /* Put back old value... */ + } else { + log_info(" new value: $%02X", new); + } + } else if (regwin_infos->w == 4) { + if ((new < 0) || (new > 0xFFFF)) { + log_info(" new value: out of range"); + new = old; /* Put back old value... */ + } else { + log_info(" new value: $%04X", new); + } + } + + /* Store new value in emulator register. */ + regwin_write(regwin_infos, new); + + /* Store new value in gtk model. */ + int2asciihex(new, str, regwin_infos->w); + gtk_list_store_set(GTK_LIST_STORE(model), &iter, COL_VAL, str, -1); + + /* + * Make sure to update all windows. + * For example, R0-R7 values depends on internal memory values. + */ + emugtk_UpdateDisplay(); +}; + +static void +regwin_init_columns(void) +{ + GtkCellRenderer *renderer; + GtkTreeViewColumn *column; + + /* Columns and cell renderers */ + renderer = gtk_cell_renderer_text_new(); + + /* Add Register column */ + column = gtk_tree_view_column_new_with_attributes( + "Name", renderer, "text", COL_NAME, NULL); + gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_AUTOSIZE); + gtk_tree_view_append_column(GTK_TREE_VIEW(reglist), column); + + /* Add Value column */ + + /* Create new renderer for value column (editable). */ + renderer = gtk_cell_renderer_text_new(); + + /* Allow edition, align to right side. */ + g_object_set(renderer, "editable", TRUE, "xalign", 1.0, NULL); + + g_signal_connect(renderer, "edited", + G_CALLBACK(regwin_cell_edited), + gtk_tree_view_get_model(GTK_TREE_VIEW(reglist))); + + column = gtk_tree_view_column_new_with_attributes( + "Value", renderer, "text", COL_VAL, NULL); + gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_AUTOSIZE); + gtk_tree_view_append_column(GTK_TREE_VIEW(reglist), column); +} + +GtkWidget * +regwin_init(void) +{ + GtkWidget *frame; + GtkWidget *scrollwin; + GtkListStore *store; + + frame = gtk_frame_new(LIST_VIEW_NAME); + + scrollwin = gtk_scrolled_window_new(NULL, NULL); + gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrollwin), + GTK_SHADOW_ETCHED_OUT); + + /* Automatically add scrollbars when necessary. */ + gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrollwin), + GTK_POLICY_AUTOMATIC, + GTK_POLICY_AUTOMATIC); + + gtk_container_add(GTK_CONTAINER(frame), scrollwin); + + /* Creating a model */ + store = regwin_init_store(); + + /* Creating the view component */ + reglist = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store)); + gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(reglist), TRUE); + gtk_container_add(GTK_CONTAINER(scrollwin), reglist); + + regwin_init_columns(); + + /* + * The tree view has acquired its own reference to the model, so we can + * drop ours. That way the model will be freed automatically when the + * tree view is destroyed. + */ + g_object_unref(store); + + return frame; +} + +/* Show registers. */ +void +regwin_refresh(void) +{ + int row; + GtkListStore *store; + + store = GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(reglist))); + + for (row = 0; row < DATA_ROWS; row++) { + int valid; + GtkTreeIter iter; + int val; + char str[8]; + struct regwin_infos_t *regwin_infos; + + if (row == 0) { + /* Get first row in list store */ + valid = gtk_tree_model_get_iter_first( + GTK_TREE_MODEL(store), &iter); + } else { + /* Get next row in list store */ + valid = gtk_tree_model_iter_next( + GTK_TREE_MODEL(store), &iter); + } + + if (!valid) { + printf("Invalid iter...\n"); + return; + } + + regwin_infos = sfr_get_infos_from_row(row); + + val = regwin_read(row); + + /* Convert to specified number of hex digits. */ + int2asciihex(val, str, regwin_infos->w); + + gtk_list_store_set(store, &iter, + COL_NAME, regwin_infos->name, + COL_VAL, str, + -1); + } +} diff --git a/src/gtk/regwin.h b/src/gtk/regwin.h new file mode 100644 index 0000000..a526f6f --- /dev/null +++ b/src/gtk/regwin.h @@ -0,0 +1,33 @@ +/* + * regwin.h + * + * Copyright (C) 1999 Jonathan St-André + * Copyright (C) 1999 Hugo Villeneuve + * + * This program 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 of the License, or + * (at your option) any later version. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef REGWIN_H +#define REGWIN_H 1 + +#include + +GtkWidget * +regwin_init(void); + +void +regwin_refresh(void); + +#endif /* REGWIN_H */ diff --git a/src/gtk/viewmenu.c b/src/gtk/viewmenu.c new file mode 100644 index 0000000..3377329 --- /dev/null +++ b/src/gtk/viewmenu.c @@ -0,0 +1,208 @@ +/* + * viewmenu.c + * + * Copyright (C) 1999 Jonathan St-André + * Copyright (C) 1999 Hugo Villeneuve + * + * This program 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 of the License, or + * (at your option) any later version. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#if HAVE_CONFIG_H +# include "config.h" +#endif + +#include + +#include "common.h" +#include "emugtk.h" /* For AddMenuSeparator() function. */ +#include "messagebox.h" +#include "viewmenu.h" +#include "app-config.h" + +extern struct app_config_t *cfg; + +void toggle_layout(GtkWidget *widget, gpointer data) +{ + int id; + + id = GPOINTER_TO_UINT(data); + + if (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(widget))) { + log_info(" Switching to layout %d", id); + cfg->layout = id; + emugtk_restart_gui(); + } +} + +void toggle_bits_per_row(GtkWidget *widget, gpointer data) +{ + int bits_per_row; + + bits_per_row = GPOINTER_TO_UINT(data); + + if (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(widget))) { + log_info(" Bits per row = %d", bits_per_row); + cfg->bits_per_row = bits_per_row; + emugtk_restart_gui(); + } +} + +void toggle_int_memory(GtkWidget *widget, gpointer data) +{ + if (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(widget))) { + log_info(" View internal memory"); + cfg->view_int_memory = 1; + } else { + cfg->view_int_memory = 0; + } + + emugtk_restart_gui(); +} + +void toggle_sfr_memory(GtkWidget *widget, gpointer data) +{ + if (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(widget))) { + log_info(" View SFR memory"); + cfg->view_sfr_memory = 1; + } else { + cfg->view_sfr_memory = 0; + } + + emugtk_restart_gui(); +} + +void toggle_ext_memory(GtkWidget *widget, gpointer data) +{ + if (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(widget))) { + log_info(" View external memory"); + cfg->view_ext_memory = 1; + } else { + cfg->view_ext_memory = 0; + } + + emugtk_restart_gui(); +} + +void +view_add_layout_submenu(GtkWidget *parent) +{ + GtkWidget *submenu; + GtkWidget *layout; + GtkWidget *layout1; + GtkWidget *layout2; + GSList *group = NULL; + + submenu = gtk_menu_new(); + + layout = gtk_menu_item_new_with_label("Layout"); + + layout1 = gtk_radio_menu_item_new_with_label(group, "Layout1"); + group = gtk_radio_menu_item_get_group(GTK_RADIO_MENU_ITEM(layout1)); + layout2 = gtk_radio_menu_item_new_with_label(group, "Layout2"); + + if (cfg->layout == UI_LAYOUT1) + gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(layout1), TRUE); + else + gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(layout2), TRUE); + + g_signal_connect(G_OBJECT(layout1), "activate", + G_CALLBACK(toggle_layout), (gpointer) UI_LAYOUT1); + g_signal_connect(G_OBJECT(layout2), "activate", + G_CALLBACK(toggle_layout), (gpointer) UI_LAYOUT2); + + gtk_menu_item_set_submenu(GTK_MENU_ITEM(layout), submenu); + gtk_menu_shell_append(GTK_MENU_SHELL(submenu), layout1); + gtk_menu_shell_append(GTK_MENU_SHELL(submenu), layout2); + gtk_menu_shell_append(GTK_MENU_SHELL(parent), layout); +} + +void +view_add_bits_per_row_submenu(GtkWidget *parent) +{ + GtkWidget *submenu; + GtkWidget *item; + GtkWidget *item1; + GtkWidget *item2; + GSList *group = NULL; + + submenu = gtk_menu_new(); + + item = gtk_menu_item_new_with_label("Bits per row"); + + item1 = gtk_radio_menu_item_new_with_label(group, "8"); + group = gtk_radio_menu_item_get_group(GTK_RADIO_MENU_ITEM(item1)); + item2 = gtk_radio_menu_item_new_with_label(group, "16"); + + if (cfg->bits_per_row == 8) + gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(item1), TRUE); + else + gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(item2), TRUE); + + g_signal_connect(G_OBJECT(item1), "activate", + G_CALLBACK(toggle_bits_per_row), (gpointer) 8); + g_signal_connect(G_OBJECT(item2), "activate", + G_CALLBACK(toggle_bits_per_row), (gpointer) 16); + + gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), submenu); + gtk_menu_shell_append(GTK_MENU_SHELL(submenu), item1); + gtk_menu_shell_append(GTK_MENU_SHELL(submenu), item2); + gtk_menu_shell_append(GTK_MENU_SHELL(parent), item); +} + +void +ViewAddMenu(GtkWidget *menu_bar) +{ + GtkWidget *item; + GtkWidget *menu; + GtkWidget *view; + + menu = gtk_menu_new(); + + view = gtk_menu_item_new_with_label("View"); + + item = gtk_check_menu_item_new_with_label("Internal Memory"); + gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); + gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(item), + cfg->view_int_memory); + g_signal_connect(G_OBJECT(item), "activate", + G_CALLBACK(toggle_int_memory), NULL); + + item = gtk_check_menu_item_new_with_label("SFR Memory"); + gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); + gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(item), + cfg->view_sfr_memory); + g_signal_connect(G_OBJECT(item), "activate", + G_CALLBACK(toggle_sfr_memory), NULL); + + item = gtk_check_menu_item_new_with_label("External Memory"); + gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); + gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(item), + cfg->view_ext_memory); + g_signal_connect(G_OBJECT(item), "activate", + G_CALLBACK(toggle_ext_memory), NULL); + + AddMenuSeparator(menu); + + /* Add layout submenu */ + view_add_layout_submenu(menu); + + AddMenuSeparator(menu); + + /* Add bits per row submenu */ + view_add_bits_per_row_submenu(menu); + + gtk_menu_item_set_submenu(GTK_MENU_ITEM(view), menu); + gtk_menu_shell_append(GTK_MENU_SHELL(menu_bar), view); +} diff --git a/src/gtk/viewmenu.h b/src/gtk/viewmenu.h new file mode 100644 index 0000000..bf78564 --- /dev/null +++ b/src/gtk/viewmenu.h @@ -0,0 +1,30 @@ +/* + * viewmenu.h + * + * Copyright (C) 1999 Jonathan St-André + * Copyright (C) 1999 Hugo Villeneuve + * + * This program 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 of the License, or + * (at your option) any later version. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef VIEWMENU_H +#define VIEWMENU_H 1 + +#include + +void +ViewAddMenu(GtkWidget *menu_bar); + +#endif /* VIEWMENU_H */ diff --git a/src/helpmenu.c b/src/helpmenu.c deleted file mode 100644 index 4a8d9dc..0000000 --- a/src/helpmenu.c +++ /dev/null @@ -1,119 +0,0 @@ -/* - * helpmenu.c - * - * Copyright (C) 1999 Jonathan St-André - * Copyright (C) 1999 Hugo Villeneuve - * - * This program 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 of the License, or - * (at your option) any later version. - * - * This program 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 this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#if HAVE_CONFIG_H -# include "config.h" -#endif - -#include - -#if STDC_HEADERS -# include -#elif HAVE_STRINGS_H -# include -#endif - -#include - -#include "common.h" -#include "options.h" -#include "emugtk.h" -#include "messagebox.h" -#include "helpmenu.h" - -#define PACKAGE_COPYRIGHT "(c) Hugo Villeneuve" - -static void -HelpCommandsEvent(gchar *string) -{ - ShowMessage("Command Line Options", COMMAND_LINE_OPTIONS, - GTK_JUSTIFY_LEFT, MESSAGE_DIALOG_FIXED_FONT); -} - -static void -HelpAboutEvent(GtkWidget *widget, gpointer data) -{ - const char *authors[] = { - "Hugo Villeneuve ", - "Jonathan St-André", - "Pascal Fecteau", - "Jimmy Ringuette", - NULL, - }; - - const char *license = - "This program 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 of the License, or (at your option) any later" - " version.\n\n" - "This program 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.\n\n" - "You should have received a copy of the GNU General Public" - " License along with this program. If not, see\n" - " "; - - gtk_show_about_dialog( - NULL, - "name", PACKAGE_NAME, - "title", "About Dialog", - "version", PACKAGE_VERSION, - "logo-icon-name", PACKAGE_TARNAME, - "comments", get_package_description(), - "authors", authors, - "website", PACKAGE_URL, - "copyright", PACKAGE_COPYRIGHT, - "license", license, - "wrap-license", true, - NULL); -} - -void -HelpAddMenu(GtkWidget *menu_bar) -{ - GtkWidget *item; - GtkWidget *menu; - - menu = gtk_menu_new(); - - /* Create the 'Help Command Line Options' item. */ - item = gtk_menu_item_new_with_label("Command Line Options"); - gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); - /* Attach the callback functions to the activate signal. */ - g_signal_connect(item, "activate", G_CALLBACK(HelpCommandsEvent), NULL); - - AddMenuSeparator(menu); - - /* Create the 'Help About' item. */ - item = gtk_menu_item_new_with_label("About " PACKAGE); - gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); - /* Attach the callback functions to the activate signal. */ - g_signal_connect(item, "activate", G_CALLBACK(HelpAboutEvent), NULL); - - /* Adding submenu title. */ - item = gtk_menu_item_new_with_label("Help"); - gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), menu); - gtk_menu_shell_append((GtkMenuShell *) menu_bar, item); -} diff --git a/src/helpmenu.h b/src/helpmenu.h deleted file mode 100644 index 63908dd..0000000 --- a/src/helpmenu.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - * helpmenu.h - * - * Copyright (C) 1999 Jonathan St-André - * Copyright (C) 1999 Hugo Villeneuve - * - * This program 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 of the License, or - * (at your option) any later version. - * - * This program 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 this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#ifndef HELPMENU_H -#define HELPMENU_H 1 - -#include - -void -HelpAddMenu(GtkWidget *menu_bar); - -#endif /* HELPMENU_H */ diff --git a/src/hexfile.c b/src/hexfile.c deleted file mode 100644 index 6411166..0000000 --- a/src/hexfile.c +++ /dev/null @@ -1,186 +0,0 @@ -/* - * Functions for loading an Intel HEX file. - * - * Copyright (C) 1999 Jonathan St-André - * Copyright (C) 1999 Hugo Villeneuve - * - * This program 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 of the License, or - * (at your option) any later version. - * - * This program 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 this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#if HAVE_CONFIG_H -# include "config.h" -#endif - -#include -#include -#include - -#if STDC_HEADERS -# include -#elif HAVE_STRINGS_H -# include -#endif - -#include "common.h" -#include "memory.h" - -/* Convert integer to ASCII hex string. */ -void -int2asciihex(int val, char *str, int width) -{ - if (width == 1) - sprintf(str , "%.1X", (u_int8_t) val); - else if (width == 2) - sprintf(str , "%.2X", (u_int8_t) val); - else if (width == 4) - sprintf(str , "%.4X", (u_int16_t) val); - else - sprintf(str , "Err"); -} - -/* Convert ASCII hex string to integer. */ -int -asciihex2int(char *str) -{ - int val; - - sscanf(str, "%X", &val); - - return val; -} - -/* Convert an ascii string to an hexadecimal number. */ -unsigned int -Ascii2Hex(char *istring, int length) -{ - unsigned int result = 0; - int i, ascii_code; - - if (!length || (length > (int) strlen(istring))) - length = strlen(istring); - - for (i = 0; i < length; i++) { - ascii_code = istring[i]; - if (ascii_code > 0x39) - ascii_code &= 0xDF; - - if ((ascii_code >= 0x30 && ascii_code <= 0x39) || - (ascii_code >= 0x41 && ascii_code <= 0x46)) { - ascii_code -= 0x30; - if (ascii_code > 9) - ascii_code -= 7; - - result <<= 4; - result += ascii_code; - } else { - printf("%s: In Ascii2Hex(), syntax error.\n", PACKAGE); - printf(" str=%s, length=%d\n", istring, length); - } - } - return result; -} - -void -LoadHexFile(const char *filename) -{ - int i, j, RecLength, LoadOffset, RecType, Data, Checksum; - -#define LINE_BUFFER_LEN 256 - FILE *fp; - int status; - char line[LINE_BUFFER_LEN]; - - if (filename == NULL) { - printf("%s: No file specified\n", PACKAGE); - exit(EXIT_FAILURE); - } - - /* Trying to open the file. */ - fp = fopen(filename, "r"); - if (fp == NULL) { - perror(filename); - /*ErrorLocation(__FILE__, __LINE__);*/ - exit(EXIT_FAILURE); - } - - /* Reading one line of data from the hex file. */ - /* char *fgets(char *s, int size, FILE *stream); - Reading stops after an EOF or a newline. If a newline is read, it is - stored into the buffer. A '\0' is stored after the last character - in the buffer. - */ - while (fgets(line, LINE_BUFFER_LEN, fp) != NULL) { - i = 0; - Checksum = 0; - - if (line[i++] != ':') { - printf("%s: line not beginning with \":\"\n", PACKAGE); - goto close_file; - } - - RecLength = Ascii2Hex(&line[i], 2); - i += 2; - Checksum += RecLength; - - LoadOffset = Ascii2Hex(&line[i], 4); - Checksum += LoadOffset / 256; - Checksum += LoadOffset % 256; - i += 4; - - RecType = Ascii2Hex(&line[i], 2); - i += 2; - Checksum += RecType; - - if (RecType == 1) { - Checksum += Ascii2Hex(&line[i], 2); - Checksum &= 0x000000FF; - - if (Checksum) { - /* Error. */ - printf("%s: Invalid format\n", PACKAGE); - goto close_file; - } else { - /* OK */ - goto close_file; - } - } - - for (j = 0; j < RecLength; j++) { - Data = Ascii2Hex(&line[i], 2); - memory_write8(PGM_MEM_ID, - (unsigned int)(LoadOffset + j), - (unsigned char)Data); - i += 2; - Checksum += Data; - } - - RecType = Ascii2Hex(&line[i], 2); - Checksum += RecType; - Checksum &= 0x000000FF; - - if (Checksum) { - printf("%s: Invalid format\n", PACKAGE); - goto close_file; - } - } - -close_file: - status = fclose(fp); - if (status != EXIT_SUCCESS) { - fprintf(stderr, "%s: Error closing hex file.\n", PACKAGE); - /*ErrorLocation(__FILE__, __LINE__);*/ - exit(EXIT_FAILURE); - } -} diff --git a/src/hexfile.h b/src/hexfile.h deleted file mode 100644 index 0f46527..0000000 --- a/src/hexfile.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - * hexfile.h - * - * Copyright (C) 1999 Jonathan St-André - * Copyright (C) 1999 Hugo Villeneuve - * - * This program 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 of the License, or - * (at your option) any later version. - * - * This program 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 this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#ifndef HEXFILE_H -#define HEXFILE_H 1 - -void -int2asciihex(int val, char *str, int width); - -int -asciihex2int(char *str); - -unsigned int -Ascii2Hex(char *istring, int length); - -void -LoadHexFile(const char *filename); - -#endif /* HEXFILE_H */ diff --git a/src/keyboard.c b/src/keyboard.c deleted file mode 100644 index 654087e..0000000 --- a/src/keyboard.c +++ /dev/null @@ -1,77 +0,0 @@ -/* - * keyboard.c - * - * Copyright (C) 1999 Jonathan St-André - * Copyright (C) 1999 Hugo Villeneuve - * - * This program 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 of the License, or - * (at your option) any later version. - * - * This program 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 this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#include -#include - -static struct termios orig, newtio; -static int peek = -1; - -int -kbhit(void) -{ - char ch; - int nread; - if (peek != -1) - return 1; - newtio.c_cc[VMIN] = 0; - tcsetattr(0, TCSANOW, &newtio); - nread = read(0, &ch, 1); - newtio.c_cc[VMIN] = 1; - tcsetattr(0, TCSANOW, &newtio); - if (nread == 1) { - peek = ch; - return 1; - } - return 0; -} - -int -getch(void) -{ - char ch; - if (peek != -1) { - ch = peek; - peek = -1; - return ch; - } - read(0, &ch, 1); - return ch; -} - -void -InitUnixKB(void) -{ - tcgetattr(0, &orig); - newtio = orig; - newtio.c_lflag &= ~ICANON; - newtio.c_lflag &= ~ECHO; - newtio.c_lflag &= ~ISIG; - newtio.c_cc[VMIN] = 1; - newtio.c_cc[VTIME] = 0; - tcsetattr(0, TCSANOW, &newtio); -} - -void -ResetUnixKB(void) -{ - tcsetattr(0, TCSANOW, &orig); -} diff --git a/src/keyboard.h b/src/keyboard.h deleted file mode 100644 index 8660616..0000000 --- a/src/keyboard.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - * keyboard.h - * - * Copyright (C) 1999 Jonathan St-André - * Copyright (C) 1999 Hugo Villeneuve - * - * This program 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 of the License, or - * (at your option) any later version. - * - * This program 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 this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#ifndef _KEYBOARD_H_ -#define _KEYBOARD_H_ - -int -kbhit(void); - -int -getch(void); - -void -InitUnixKB(void); - -void -ResetUnixKB(void); - -#endif /* _KEYBOARD_H_ */ diff --git a/src/log.c b/src/log.c deleted file mode 100644 index b378575..0000000 --- a/src/log.c +++ /dev/null @@ -1,130 +0,0 @@ -/* - * log.c -- debug functions for logging. - * - * Copyright (C) 2011 Hugo Villeneuve - * - * This program 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 of the License, or - * (at your option) any later version. - */ - -#include "config.h" - -#include -#include -#include -#include -#include - -#include "common.h" -#include "options.h" - -#define PREFIX_PACKAGE_NAME 1 -#define ADD_LINEFEED 1 - -extern struct options_t options; - -static void -log_prefix_package_name(FILE *stream, const char *severity) -{ -#if PREFIX_PACKAGE_NAME - /* Printing the name of the program first if desired. */ - fprintf(stream, "%s %s: ", PACKAGE_NAME, severity); -#endif /* PREFIX_PACKAGE_NAME */ -} - -static void -log_suffix_newline(FILE *stream) -{ -#if ADD_LINEFEED - fprintf(stream, "\n"); -#endif /* ADD_LINEFEED */ -} - -void -log_debug(const char *format, ...) -{ - FILE *stream = stdout; - - if (options.log >= LOG_LEVEL_DEBUG) { - va_list ap; - - log_prefix_package_name(stream, "debug"); - - va_start(ap, format); - vfprintf(stream, format, ap); - va_end(ap); - - log_suffix_newline(stream); - } -} - -void -log_info(const char *format, ...) -{ - FILE *stream = stdout; - - if (options.log >= LOG_LEVEL_INFO) { - va_list ap; - - log_prefix_package_name(stream, "info"); - - va_start(ap, format); - vfprintf(stream, format, ap); - va_end(ap); - - log_suffix_newline(stream); - } -} - -void -log_warn(const char *format, ...) -{ - FILE *stream = stderr; - - if (options.log >= LOG_LEVEL_WARN) { - va_list ap; - - log_prefix_package_name(stream, "warn"); - - va_start(ap, format); - vfprintf(stream, format, ap); - va_end(ap); - - log_suffix_newline(stream); - } -} - -void -log_err(const char *format, ...) -{ - FILE *stream = stderr; - va_list ap; - - log_prefix_package_name(stream, "error"); - - va_start(ap, format); - vfprintf(stream, format, ap); - va_end(ap); - - log_suffix_newline(stream); -} - -/* Log error message and exits with error code. */ -void -log_fail(const char *format, ...) -{ - FILE *stream = stderr; - va_list ap; - - log_prefix_package_name(stream, "error"); - - va_start(ap, format); - vfprintf(stream, format, ap); - va_end(ap); - - log_suffix_newline(stream); - - exit(EXIT_FAILURE); -} diff --git a/src/log.h b/src/log.h deleted file mode 100644 index 6b3e2e9..0000000 --- a/src/log.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - * log.h - * - * Copyright (C) 2011 Hugo Villeneuve - * - * This program 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 of the License, or - * (at your option) any later version. - */ - -#ifndef LOG_H -#define LOG_H 1 - -#include -#include -#include -#include -#include - -#include "common.h" - -enum LOG_LEVEL { - LOG_LEVEL_ERR = 0, /* Display only errors */ - LOG_LEVEL_WARN, /* Display warnings */ - LOG_LEVEL_INFO, /* Display information messages */ - LOG_LEVEL_DEBUG, /* Display all messages */ -}; - -void -log_debug(const char *format, ...); - -void -log_info(const char *format, ...); - -void -log_warn(const char *format, ...); - -void -log_err(const char *format, ...); - -/* Log error message and exits with error code. */ -void -log_fail(const char *format, ...); - -#endif /* LOG_H */ diff --git a/src/memory.c b/src/memory.c deleted file mode 100644 index c5b2acf..0000000 --- a/src/memory.c +++ /dev/null @@ -1,245 +0,0 @@ -/* - * memory.c - * - * Copyright (C) 1999 Jonathan St-André - * Copyright (C) 1999 Hugo Villeneuve - * - * This program 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 of the License, or - * (at your option) any later version. - * - * This program 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 this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#include -#include - -#include "common.h" -#include "cpu8051.h" -#include "reg8051.h" -#include "hexfile.h" -#include "memory.h" -#include "options.h" - -struct mem_infos_t { - int size; - int max_size; - u_int8_t *buf; -}; - -struct mem_infos_t mem_infos[MEM_ID_COUNT]; - -extern struct options_t options; - -/* Init each 8051 memory sections. */ -void -memory_init(void) -{ - int k; - struct mem_infos_t *m; - - /* Set desired and maximum allowable sizes for each memory type. */ - mem_infos[PGM_MEM_ID].size = options.pram_size; - mem_infos[PGM_MEM_ID].max_size = PGM_MEM_MAX_SIZE; - - mem_infos[INT_MEM_ID].size = options.iram_size; - mem_infos[INT_MEM_ID].max_size = INT_MEM_MAX_SIZE; - - mem_infos[EXT_MEM_ID].size = options.xram_size; - mem_infos[EXT_MEM_ID].max_size = EXT_MEM_MAX_SIZE; - - /* Verify if desired sizes are valid, and if so allocate memory. */ - for (k = 0; k < MEM_ID_COUNT; k++) { - m = &mem_infos[k]; - - if (m->size > m->max_size) { - log_err("Memory size invalid (max = %d)", m->max_size); - exit(1); - } - - m->buf = malloc(m->size); - if (m->buf == NULL) { - log_err("%s", strerror(errno)); - exit(1); - } - - memset(m->buf, 0x00, m->size); - } -} - -void -memory_clear(enum mem_id_t id) -{ - memset(mem_infos[id].buf, 0, mem_infos[id].size); -} - -void -memory_write8(enum mem_id_t id, unsigned long address, u_int8_t value) -{ - if (address >= mem_infos[id].max_size) { - printf("Error writing to memory ID: %d\n", id); - printf(" Address (%lu) greater than maximum memory size\n", - address); - return; - } else - mem_infos[id].buf[address] = value; -} - -void -memory_sfr_write8(unsigned long address, u_int8_t value) -{ - /* SFR registers are from addresses $80 to $FF. */ - memory_write8(INT_MEM_ID, address, value); -} - -void -memory_sfr_write_dptr(u_int16_t value) -{ - memory_write8(INT_MEM_ID, _DPTRHIGH_, value >> 8); - memory_write8(INT_MEM_ID, _DPTRLOW_, (uint8_t) value); -} - -u_int8_t -memory_read8(enum mem_id_t id, unsigned long address) -{ - if (address >= mem_infos[id].max_size) { - printf("Error reading from memory ID: %d\n", id); - printf(" Address (%lu) greater than maximum memory size\n", - address); - return 0; - } else - return mem_infos[id].buf[address]; -} - -u_int8_t -memory_sfr_read8(unsigned long address) -{ - /* SFR registers are from addresses $80 to $FF. */ - return memory_read8(INT_MEM_ID, address); -} - -u_int16_t -memory_sfr_read_dptr(void) -{ - return (memory_read8(INT_MEM_ID, _DPTRHIGH_) << 8) + - memory_read8(INT_MEM_ID, _DPTRLOW_); -} - -void -stack_push8(uint8_t value) -{ - uint8_t sp; - - sp = memory_read8(INT_MEM_ID, _SP_); - - memory_write8(INT_MEM_ID, ++sp, value); - memory_write8(INT_MEM_ID, _SP_, sp); /* Save new stack pointer */ -} - -void -stack_push16(uint16_t value) -{ - uint8_t sp; - - sp = memory_read8(INT_MEM_ID, _SP_); - - memory_write8(INT_MEM_ID, ++sp, (uint8_t) value); /* Write LSB */ - memory_write8(INT_MEM_ID, ++sp, value >> 8); /* Write MSB */ - memory_write8(INT_MEM_ID, _SP_, sp); /* Save new stack pointer */ -} - -uint8_t -stack_pop8(void) -{ - uint8_t sp; - uint8_t value; - - sp = memory_read8(INT_MEM_ID, _SP_); - - value = memory_read8(INT_MEM_ID, sp--); - memory_write8(INT_MEM_ID, _SP_, sp); /* Save new stack pointer */ - - return value; -} - -uint16_t -stack_pop16(void) -{ - uint8_t sp; - uint16_t value; - - sp = memory_read8(INT_MEM_ID, _SP_); - - value = memory_read8(INT_MEM_ID, sp--) << 8; /* Read MSB */ - value |= memory_read8(INT_MEM_ID, sp--); /* Read LSB */ - memory_write8(INT_MEM_ID, _SP_, sp); /* Save new stack pointer */ - - return value; -} - -/* Read a 16-bit address from PGM memory, starting at offset */ -uint16_t -pgm_read_addr16(uint16_t base) -{ - uint16_t addr; - - addr = memory_read8(PGM_MEM_ID, base) << 8; /* MSB */ - addr |= memory_read8(PGM_MEM_ID, base + 1); /* LSB */ - - return addr; -} - -/* Dump memory */ -void -DumpMem(char *Address, char *Asize, int memory_id) -{ - unsigned int MemAddress; - int size; - int Offset, Column; - - if (strlen(Address) != 0) { - if (STREQ(Address, "PC")) - MemAddress = cpu8051.pc; - else - MemAddress = Ascii2Hex(Address, strlen(Address)); - } else { - MemAddress = 0; - } - - if (strlen(Asize) != 0) { - size = Ascii2Hex(Asize, strlen(Asize)); - } else { - size = 256; /* Default size if not specified. */ - } - - for (Offset = 0; Offset < size; Offset += 16) { - unsigned char data[16]; - - printf("%.4X ", MemAddress + Offset); - - for (Column = 0; Column < 16; Column++) { - data[Column] = memory_read8(memory_id, MemAddress + - Offset + Column); - printf(" %.2X", (int) data[Column]); - } - printf(" "); - - /* Display any ASCII characters */ - for (Column = 0; Column < 16; Column++) { - if ((int) data[Column] >= 32 && - (int) data[Column] <= 126) { - printf("%c", data[Column]); - } else - printf("."); - } - printf("\n"); - } -} diff --git a/src/memory.h b/src/memory.h deleted file mode 100644 index fee41a6..0000000 --- a/src/memory.h +++ /dev/null @@ -1,88 +0,0 @@ -/* - * memory.h - * - * Copyright (C) 1999 Jonathan St-André - * Copyright (C) 1999 Hugo Villeneuve - * - * This program 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 of the License, or - * (at your option) any later version. - * - * This program 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 this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#ifndef MEMORY_H -#define MEMORY_H 1 - -#include - -#define PGM_MEM_MAX_SIZE 65536 -/* - * Direct addressing $00 to $7F = IRAM (8051) - * Direct addressing $80 to $FF = SFR (8051) - * Indirect addressing $80 to $FF = IRAM (8052) - */ -#define INT_MEM_MAX_SIZE 256 -#define EXT_MEM_MAX_SIZE 65536 - -#define PGM_MEM_DEFAULT_SIZE 8192 -#define EXT_MEM_DEFAULT_SIZE 1024 - -enum mem_id_t { - PGM_MEM_ID, - INT_MEM_ID, - EXT_MEM_ID, - MEM_ID_COUNT -}; - -void -memory_init(void); - -void -memory_clear(enum mem_id_t id); - -void -memory_write8(enum mem_id_t id, unsigned long address, u_int8_t value); - -void -memory_sfr_write8(unsigned long address, u_int8_t value); - -void -memory_sfr_write_dptr(u_int16_t value); - -u_int8_t -memory_read8(enum mem_id_t id, unsigned long address); - -u_int8_t -memory_sfr_read8(unsigned long address); - -u_int16_t -memory_sfr_read_dptr(void); - -void -stack_push8(uint8_t value); - -void -stack_push16(uint16_t value); - -uint8_t -stack_pop8(void); - -uint16_t -stack_pop16(void); - -uint16_t -pgm_read_addr16(uint16_t base); - -void -DumpMem(char *Address, char *Asize, int memory_id); - -#endif /* MEMORY_H */ diff --git a/src/memwin.c b/src/memwin.c deleted file mode 100644 index 58ce1d2..0000000 --- a/src/memwin.c +++ /dev/null @@ -1,346 +0,0 @@ -/* - * memwin.c - * - * Copyright (C) 1999 Jonathan St-André - * Copyright (C) 1999 Hugo Villeneuve - * - * This program 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 of the License, or - * (at your option) any later version. - * - * This program 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 this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#if HAVE_CONFIG_H -# include "config.h" -#endif - -#include -#include /* For isprint */ - -#include "common.h" -#include "memory.h" -#include "hexfile.h" -#include "cpu8051.h" -#include "regwin.h" -#include "memwin.h" -#include "emugtk.h" -#include "options.h" -#include "app-config.h" - -extern struct app_config_t *cfg; -extern struct options_t options; - -static int COL_ASCII; -static int N_COLUMNS; - -enum -{ - COL_ADDRESS = 0, - COL_DATA0, -}; - -static GtkWidget *memlist_internal; -static GtkWidget *memlist_external; - -/* Creating a model */ -static GtkListStore * -memwin_init_store(int data_rows) -{ - GtkTreeIter iter; - int row; - int col; - GtkListStore *store; - GType col_types[N_COLUMNS]; - - /* No need for static array, all our columns are of the same type. */ - for (col = 0; col < N_COLUMNS; col++) - col_types[col] = G_TYPE_STRING; - - store = gtk_list_store_newv(N_COLUMNS, col_types); - - /* Add rows. */ - for (row = 0; row < data_rows; row++) - gtk_list_store_append(store, &iter); - - return store; -} - -static void -memwin_cell_edited(GtkCellRendererText *cell, gchar *path_string, - gchar *new_str, gpointer model) -{ - guint column; - guint memory_id; - gpointer columnptr; - gpointer memory_id_ptr; - GtkTreeIter iter; - int address; - u_int8_t old; - int new; - char *str; - - if (!model) { - g_error("Unable to get model from cell renderer"); - } - - /* Column number is passed as renderer object data */ - columnptr = g_object_get_data(G_OBJECT(cell), "column"); - column = GPOINTER_TO_UINT(columnptr); - - /* Memory ID is passed as renderer object data */ - memory_id_ptr = g_object_get_data(G_OBJECT(cell), "memory_id"); - memory_id = GPOINTER_TO_UINT(memory_id_ptr); - - /* Get the iterator */ - gtk_tree_model_get_iter_from_string(model, &iter, path_string); - - /* Get base address. */ - gtk_tree_model_get(model, &iter, COL_ADDRESS, &str, -1); - address = asciihex2int(str); - - /* Convert column number (1, 2, 3...) to index (0, 1, 2...) */ - address += (column - COL_DATA0); - old = memory_read8(memory_id, address); - - log_info("Address: $%02X", address); - log_info(" old value: $%02X", old); - - /* Convert new value (asciihex) to integer. */ - new = asciihex2int(new_str); - if ((new < 0) || (new > 255)) { - log_info(" new value: out of range"); - new = old; /* Put back old value... */ - } else { - log_info(" new value: $%02X", new); - } - - /* Store new value in emulator memory. */ - memory_write8(memory_id, address, new); - - /* Convert to text. */ - int2asciihex(new, str, 2); - - /* Store new value in gtk model. */ - gtk_list_store_set(GTK_LIST_STORE(model), &iter, column, str, -1); - - /* - * Make sure to update all registers and memory. - * For example, BANKed registers depends on internal memory. - */ - emugtk_UpdateDisplay(); -}; - -static void -memwin_init_columns(GtkWidget *listview, int memory_id) -{ - int i; - GtkCellRenderer *renderer; - GtkTreeViewColumn *column; - - /* Columns and cell renderers */ - renderer = gtk_cell_renderer_text_new(); - - /* Add address column */ - column = gtk_tree_view_column_new_with_attributes( - "Address", renderer, "text", COL_ADDRESS, NULL); - gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_AUTOSIZE); - gtk_tree_view_append_column(GTK_TREE_VIEW(listview), column); - - for (i = COL_DATA0; i < (COL_DATA0 + cfg->bits_per_row); i++) { - char col_name[8]; - - /* Create new renderer for each editable cell. */ - renderer = gtk_cell_renderer_text_new(); - - /* Allow edition, align to left side. */ - g_object_set(renderer, "editable", TRUE, "xalign", 0, NULL); - - g_signal_connect(renderer, "edited", - G_CALLBACK(memwin_cell_edited), - gtk_tree_view_get_model( - GTK_TREE_VIEW(listview))); - - /* Add column index and memory_id, used when editing the cell. */ - g_object_set_data(G_OBJECT(renderer), "column", - GUINT_TO_POINTER(i)); - g_object_set_data(G_OBJECT(renderer), "memory_id", - GUINT_TO_POINTER(memory_id)); - - /* Use two digits only if DATA_ROWS > 10 */ - if (cfg->bits_per_row < 10) - sprintf(col_name, "B%1d", i - COL_DATA0); - else - sprintf(col_name, "B%02d", i - COL_DATA0); - - column = gtk_tree_view_column_new_with_attributes( - col_name, renderer, "text", i, NULL); - gtk_tree_view_column_set_sizing(column, - GTK_TREE_VIEW_COLUMN_AUTOSIZE); - gtk_tree_view_append_column(GTK_TREE_VIEW(listview), column); - } - - /* Add ASCII column, using fixed-font. */ - renderer = gtk_cell_renderer_text_new(); - g_object_set(renderer, "family", "Monospace", NULL); - column = gtk_tree_view_column_new_with_attributes( - "ASCII", renderer, "text", COL_ASCII, NULL); - gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_AUTOSIZE); - gtk_tree_view_append_column(GTK_TREE_VIEW(listview), column); -} - -static int -compute_data_rows(int memory_id) -{ - int data_rows; - - if (memory_id == INT_MEM_ID) { - data_rows = options.iram_size / cfg->bits_per_row; - } else if (memory_id == EXT_MEM_ID) { - data_rows = options.xram_size / cfg->bits_per_row; - } else { - log_fail("Invalid memory type"); - exit(1); - } - - return data_rows; -} - -GtkWidget * -memwin_init(char *title, int memory_id) -{ - GtkWidget *frame; - GtkWidget *scrollwin; - GtkListStore *store; - GtkWidget *memlist; - int data_rows; - - COL_ASCII = cfg->bits_per_row + 1; - N_COLUMNS = COL_ASCII + 1; - - frame = gtk_frame_new(title); - - scrollwin = gtk_scrolled_window_new(NULL, NULL); - gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrollwin), - GTK_SHADOW_ETCHED_OUT); - - /* Automatically add scrollbars when necessary. */ - gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrollwin), - GTK_POLICY_AUTOMATIC, - GTK_POLICY_AUTOMATIC); - - gtk_container_add(GTK_CONTAINER(frame), scrollwin); - - data_rows = compute_data_rows(memory_id); - - /* Creating a model */ - store = memwin_init_store(data_rows); - - /* Creating the view component */ - memlist = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store)); - gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(memlist), TRUE); - gtk_container_add(GTK_CONTAINER(scrollwin), memlist); - - if (memory_id == INT_MEM_ID) { - memlist_internal = memlist; - } else if (memory_id == EXT_MEM_ID) { - memlist_external = memlist; - } else { - log_fail("Invalid memory type"); - exit(1); - } - - memwin_init_columns(memlist, memory_id); - - /* - * The tree view has acquired its own reference to the model, so we can - * drop ours. That way the model will be freed automatically when the - * tree view is destroyed. - */ - g_object_unref(store); - - return frame; -} - -/* Dump internal or external memory. */ -void -memwin_refresh(int memory_id) -{ - int row; - unsigned int Address; - GtkListStore *store; - GtkWidget *memlist; - int data_rows; - - Address = 0; - - data_rows = compute_data_rows(memory_id); - - if (memory_id == INT_MEM_ID) { - memlist = memlist_internal; - } else if (memory_id == EXT_MEM_ID) { - memlist = memlist_external; - } else { - log_fail("Invalid memory type"); - exit(1); - } - - store = GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(memlist))); - - for (row = 0; row < data_rows; row++) { - int valid; - GtkTreeIter iter; - char str[4+1]; /* Maximum str len is for address column (4 digits) */ - char ascii_str[16+1]; /* Maximum 16 data columns. */ - int col; - - if (row == 0) { - /* Get first row in list store */ - valid = gtk_tree_model_get_iter_first( - GTK_TREE_MODEL(store), &iter); - } else { - /* Get next row in list store */ - valid = gtk_tree_model_iter_next( - GTK_TREE_MODEL(store), &iter); - } - - if (!valid) { - printf("Invalid iter...\n"); - return; - } - - /* Display base address. */ - int2asciihex(Address, str, 4); - - gtk_list_store_set(store, &iter, COL_ADDRESS, str, -1); - - for (col = 0; col < cfg->bits_per_row; col++) { - u_int8_t data; - - data = memory_read8(memory_id, Address + col); - - /* Display hex data */ - int2asciihex(data, str, 2); - - gtk_list_store_set(store, &iter, col + 1, str, -1); - - /* Append to ASCII string (if applicable). */ - if (!isprint(data)) - data = '.'; - sprintf(&ascii_str[col], "%c", data); - } - - /* Display ASCII characters. */ - gtk_list_store_set(store, &iter, COL_ASCII, ascii_str, -1); - - Address += cfg->bits_per_row; - } -} diff --git a/src/memwin.h b/src/memwin.h deleted file mode 100644 index ccb528d..0000000 --- a/src/memwin.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * memwin.h - * - * Copyright (C) 1999 Jonathan St-André - * Copyright (C) 1999 Hugo Villeneuve - * - * This program 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 of the License, or - * (at your option) any later version. - * - * This program 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 this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#ifndef MEMWIN_H -#define MEMWIN_H 1 - -#include - -GtkWidget * -memwin_init(char *title, int memory_id); - -void -memwin_refresh(int memory_id); - -#endif /* MEMWIN_H */ diff --git a/src/messagebox.c b/src/messagebox.c deleted file mode 100644 index c4d3723..0000000 --- a/src/messagebox.c +++ /dev/null @@ -1,98 +0,0 @@ -/* - * messagebox.c - * - * Copyright (C) 1999 Jonathan St-André - * Copyright (C) 1999 Hugo Villeneuve - * - * This program 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 of the License, or - * (at your option) any later version. - * - * This program 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 this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#if HAVE_CONFIG_H -# include "config.h" -#endif - -#include - -#include "common.h" -#include "messagebox.h" - -#define MESSAGE_DIALOG_BORDER 25 - -#define BUTTON_TEXT_BORDER 3 - -extern GtkWidget *mainwin; - -void -ShowMessage(gchar *title, gchar *message, int justification, int font_style) -{ - GtkWidget *dialog; - GtkWidget *label; - GtkWidget *label_window; - - /* Keep the dialog on top of the main window, and centered. */ - dialog = gtk_dialog_new_with_buttons( - title, GTK_WINDOW(mainwin), - GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT, GTK_STOCK_OK, - GTK_RESPONSE_NONE, NULL); - - /* - * The GtkLabel widget is one of a few GTK+ widgets that don't create - * their own window to render themselves into. Instead, they draw - * themselves directly onto their parents window. This means that in - * order to set a property for a GtkLabel widget, you need to change the - * property of its parent, i.e. the object that you pack it into. - * Another solution (short term workaround) is to put the label widget - * inside another widget that does get its own window, like the - * 'ViewPort' or 'EventBox' widget. - */ - - /* - * Using workaround described above to set the border width of 'label' - * widget. - */ - label_window = gtk_event_box_new(); - - /* Creating our label. */ - label = gtk_label_new(message); - gtk_label_set_justify(GTK_LABEL(label), justification); - - if (font_style == MESSAGE_DIALOG_FIXED_FONT) { - PangoFontDescription *pango_font; - - pango_font = pango_font_description_from_string(FIXED_FONT); - gtk_widget_modify_font(label, pango_font); - } - - /* Adding label widget to label_window widget. */ - gtk_container_add(GTK_CONTAINER(label_window), label); - - /* - * Changing border width of the label widget by way of label_window - * widget. - */ - gtk_container_set_border_width(GTK_CONTAINER(label_window), - MESSAGE_DIALOG_BORDER); - - /* Ensure that the dialog box is destroyed when the user responds */ - g_signal_connect_swapped(dialog, "response", - G_CALLBACK(gtk_widget_destroy), dialog); - - /* Add the label_window to the dialog window. */ - gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), - label_window); - - /* Show everything we've added to the dialog. */ - gtk_widget_show_all(dialog); -} diff --git a/src/messagebox.h b/src/messagebox.h deleted file mode 100644 index 991e758..0000000 --- a/src/messagebox.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * messagebox.h - * - * Copyright (C) 1999 Jonathan St-André - * Copyright (C) 1999 Hugo Villeneuve - * - * This program 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 of the License, or - * (at your option) any later version. - * - * This program 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 this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#ifndef MESSAGEBOX_H -#define MESSAGEBOX_H 1 - -#include - -#define MESSAGE_DIALOG_NORMAL_FONT 0 -#define MESSAGE_DIALOG_FIXED_FONT 1 - -void -ShowMessage(gchar *title, gchar *message, int justification, int font_style); - -#endif /* MESSAGEBOX_H */ diff --git a/src/opcode2c.pl b/src/opcode2c.pl deleted file mode 100755 index 035c718..0000000 --- a/src/opcode2c.pl +++ /dev/null @@ -1,851 +0,0 @@ -#!/usr/bin/perl -# -# Copyright (C) 1999 Jonathan St-André -# Copyright (C) 1999 Hugo Villeneuve -# -# This program 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 of the License, or -# (at your option) any later version. -# -# This program 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 this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. - -open INST_DEF, ">instructions_8051.h" or die "Error creating : $!\n"; -open INST_IMP, ">instructions_8051.c" or die "Error creating : $!\n"; -open OPCODELST, "opcodes.lst" or die "Error opening : $!\n"; -open DISASM_H, ">disasm.h" or die "Error creating : $!\n"; - -# Write GPL license -# Argument 0 is file descriptor -sub write_header -{ - my $fd = $_[0]; - - print $fd " *\n"; - print $fd " * Do not modify this file directly, as it was created by opcode2c.pl\n"; - print $fd " * Any modifications made directly to this file will be lost.\n"; - print $fd " *\n"; - print $fd " * Copyright (C) 1999 Jonathan St-André\n"; - print $fd " * Copyright (C) 1999 Hugo Villeneuve \n"; - print $fd " *\n"; - print $fd " * This program is free software; you can redistribute it and/or modify\n"; - print $fd " * it under the terms of the GNU General Public License as published by\n"; - print $fd " * the Free Software Foundation; either version 2 of the License, or\n"; - print $fd " * (at your option) any later version.\n"; - print $fd " *\n"; - print $fd " * This program is distributed in the hope that it will be useful,\n"; - print $fd " * but WITHOUT ANY WARRANTY; without even the implied warranty of\n"; - print $fd " * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"; - print $fd " * GNU General Public License for more details.\n"; - print $fd " *\n"; - print $fd " * You should have received a copy of the GNU General Public License\n"; - print $fd " * along with this program; if not, write to the Free Software\n"; - print $fd " * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.\n"; - print $fd " */\n\n"; -} - -# Write C function source code line to INST_IMP file. -# Prefix each line with a tab (indentation) and add newline character at the end. -sub cfw -{ - print INST_IMP "\t",$_[0],"\n"; -} - -# Header for instructions_8051.c -print INST_IMP "/*\n"; -print INST_IMP " * instructions_8051.c\n"; -write_header(INST_IMP); -print INST_IMP "/* Define only here, for not having extern scope on local variables. */\n"; -print INST_IMP "#define INSTRUCTIONS_8051_M 1\n\n\n"; -print INST_IMP "#include \"reg8051.h\"\n"; -print INST_IMP "#include \"cpu8051.h\"\n"; -print INST_IMP "#include \"memory.h\"\n"; -print INST_IMP "#include \"psw.h\"\n"; -print INST_IMP "#include \"instructions_8051.h\"\n\n\n"; - -# Header for disasm.h -print DISASM_H "/*\n"; -print DISASM_H " * disasm.h\n"; -write_header(DISASM_H); -print DISASM_H "#ifndef DISASM_H\n"; -print DISASM_H "#define DISASM_H 1\n\n"; - -$nbinst=0; -$nbaddr=0; -$nbargs=0; -$instnumb=0; - -$ligne=; -$ligne=; -while($ligne=) { - chop $ligne; - if (length $ligne < 2) {next;} - @wordlist=split ' ',$ligne; - $nbword=@wordlist; - $instruction=$wordlist[2]; - for($i=3;$i<($nbword-2);$i++) {$instruction="$instruction $wordlist[$i]";} - - $a_instruction[$instnumb]=$instruction; - $a_bytes[$instnumb]=$wordlist[$nbword-2]; - $a_cycles[$instnumb]=$wordlist[$nbword-1]; - $a_opcodehex[$instnumb]=$wordlist[1]; - $a_opcodebin[$instnumb]=$wordlist[0]; - - $instfunction[$instnumb]="CPU8051::OP_$wordlist[1]"; - - $instargs[$instnumb << 2]=$instargs[($instnumb << 2) + 1]=$instargs[($instnumb << 2) + 2]=$instargs[($instnumb << 2) + 3]=0; - if ($nbword > 5) { - @argslist=split /\,/,$wordlist[3]; - $argslistsize=@argslist; - $instargs[$instnumb << 2]=$argslistsize; - for ($i=0;$i<$argslistsize;$i++) { - if (not exists $argstypes{$argslist[$i]}) { - $argstypes[$nbargs]=$argslist[$i]; - $argstypes{$argslist[$i]}=$nbargs++; - } - $instargs[($instnumb << 2) + $i + 1]=$argstypes{$argslist[$i]}; - } - } - - if (not exists $insttext{$wordlist[2]}) { - $insttext[$nbinst]=$wordlist[2]; - $insttext{$wordlist[2]}=$nbinst++; - } - - $insttype[$instnumb]=$insttext{$wordlist[2]}; - - if ( not exists $addrmode{$wordlist[3]}) { - $addrmode[$nbaddr]=$wordlist[3]; - $addrmode{$wordlist[3]}=$nbaddr++; - } - - $nbbytes[$instnumb]=$wordlist[$nbword-2]; - - $instaddr[$instnumb]=$addrmode{$wordlist[3]}; - - $instnumb++; -} -# ------------------------------------------------------------------------------ -print DISASM_H "/*\n"; -print DISASM_H " * For all 256 opcodes, the value in this table gives the instruction type\n"; -print DISASM_H " * ex.: MOV, INC, CLR, CPL,...\n"; -print DISASM_H " * To know what is the instruction type, use\n"; -print DISASM_H " * the number as an offset in the InstTextTbl[]\n"; -print DISASM_H " */\n"; -print DISASM_H "static int InstTypesTbl[] = {\n"; -for($i=0;$i<256;$i++) { - print DISASM_H " $insttype[$i]"; - ($i != 255) and print DISASM_H ","; - if (($i+1) % 16 == 0) { print DISASM_H "\n"; } -} -print DISASM_H "};\n"; -print DISASM_H "\n"; -# ------------------------------------------------------------------------------ -print DISASM_H "/* Size(in bytes) of each instruction (offset in table is instruction opcode) */\n"; -print DISASM_H "static int InstSizesTbl[] = {\n"; -for($i=0;$i<256;$i++) { - print DISASM_H " $nbbytes[$i]"; - ($i != 255) and print DISASM_H ","; - if (($i+1) % 16 == 0) { print DISASM_H "\n"; } -} -print DISASM_H "};\n"; -print DISASM_H "\n"; -# ------------------------------------------------------------------------------ -print DISASM_H "/* List of instructions types referenced by InstTypesTbl[] */\n"; -$nbelement=@insttext; -print DISASM_H "\#define InstTextTblLength $nbelement\n"; -$elementnb=0; -print DISASM_H "static char *InstTextTbl[] = {\n"; -foreach $instruc (@insttext) { - print DISASM_H " \"$instruc\""; - ($elementnb++ < $nbelement-1) and print DISASM_H ","; - print DISASM_H "\n"; -} -print DISASM_H "};\n"; -print DISASM_H "\n"; -# ------------------------------------------------------------------------------ -print DISASM_H "/*\n"; -print DISASM_H " * Table describing all arguments types of an instruction\n"; -print DISASM_H " * The table is indexed InstArgTbl[ opcode * 4]\n"; -print DISASM_H " * InstArgTbl[opcode*4 + 1] gives the number of arguments the instruction has\n"; -print DISASM_H " * InstArgTbl[opcode*4 + i] for i=1,2 and 3 give the type of each argument\n"; -print DISASM_H " * for most instructions, the 3rd argument isn't used\n"; -print DISASM_H " * the argument type is referecing to ArgsTextTbl[]\n"; -print DISASM_H " */\n"; -print DISASM_H "\#define InstArgTblLength 256\n"; -print DISASM_H "static int InstArgTbl[] = {\n"; -for($i=0;$i<1024;$i++) { - print DISASM_H " $instargs[$i]"; - ($i != 1023) and print DISASM_H ","; - if (($i+1) % 16 == 0) { print DISASM_H "\n"; } -} -print DISASM_H "};\n"; -print DISASM_H "\n"; -# ------------------------------------------------------------------------------ -print DISASM_H "/*\n"; -print DISASM_H " * List all types of arguments available to instructions\n"; -print DISASM_H " * Referenced by InstArgsTbl[]\n"; -print DISASM_H " */\n"; -$nbelement=@argstypes; -print DISASM_H "\#define ArgsTextTblLength $nbelement\n"; -$elementnb=0; -print DISASM_H "static char *ArgsTextTbl[] = {\n"; -foreach $args (@argstypes) { - print DISASM_H " \"$args\""; - ($elementnb++ < $nbelement-1) and print DISASM_H ","; - print DISASM_H "\n"; -} -print DISASM_H "};\n"; -print DISASM_H "\n"; - -# ------------------------------------------------------------------------------ -for ($i=0 ; $i< 256; $i++) { - print INST_IMP "/*","*"x76,"\n"; - print INST_IMP " * Instruction \"$a_instruction[$i]\" takes $a_cycles[$i] cycle(s) and $a_bytes[$i] byte(s).\n"; - print INST_IMP " ","*"x76,"/\n"; - print INST_IMP "int\n"; - print INST_IMP "cpu8051_OP_$a_opcodehex[$i](void)\n"; - print INST_IMP "{\n"; - - if( $i == 0x85 ) { - # Cas particulier pour MOV direct,direct -> src et dest sont inverses dans la memoire - print INST_IMP " unsigned char srcaddr = memory_read8( PGM_MEM_ID, cpu8051.pc++ );\n"; - print INST_IMP " unsigned char source = cpu8051_ReadD( srcaddr );\n"; - print INST_IMP " unsigned char destaddr = memory_read8( PGM_MEM_ID, cpu8051.pc++ );\n"; - print INST_IMP " unsigned char destination = cpu8051_ReadD( destaddr );\n"; - print INST_IMP " destination = source;\n"; - print INST_IMP " cpu8051_WriteD( destaddr, destination );\n"; - } - else { - if ($instargs[$i*4] > 0) { - $op_destination=$instargs[$i*4+1]; - if ($op_destination == 0) { # addr11 - cfw("unsigned int addr11 = ( ( memory_read8( PGM_MEM_ID, cpu8051.pc - 1 ) << 3 ) & 0xF00 ) + memory_read8( PGM_MEM_ID, cpu8051.pc );"); - cfw("cpu8051.pc++;"); - } - if ($op_destination == 1) { # addr16 - cfw("uint16_t addr16 = pgm_read_addr16(cpu8051.pc);"); - cfw("cpu8051.pc += 2;"); - } - if ($op_destination == 2) { # A - cfw("unsigned char destination = cpu8051_ReadD( _ACC_ );"); - } - if ($op_destination == 3) { # direct - cfw("unsigned char destaddr = memory_read8( PGM_MEM_ID, cpu8051.pc++ );"); - cfw("unsigned char destination = cpu8051_ReadD( destaddr );"); - } - if ($op_destination == 4) { # @R0 - cfw("unsigned char destination = cpu8051_ReadI ( cpu8051_ReadD( BANKPSW + _R0_ ) );"); - } - if ($op_destination == 5) { # @R1 - cfw("unsigned char destination = cpu8051_ReadI ( cpu8051_ReadD( BANKPSW + _R1_ ) );"); - } - if ($op_destination == 6) { # R0 - cfw("unsigned char destination = cpu8051_ReadD( BANKPSW + _R0_ );"); - } - if ($op_destination == 7) { # R1 - cfw("unsigned char destination = cpu8051_ReadD( BANKPSW + _R1_ );"); - } - if ($op_destination == 8) { # R2 - cfw("unsigned char destination = cpu8051_ReadD( BANKPSW + _R2_ );"); - } - if ($op_destination == 9) { # R3 - cfw("unsigned char destination = cpu8051_ReadD( BANKPSW + _R3_ );"); - } - if ($op_destination == 10) { # R4 - cfw("unsigned char destination = cpu8051_ReadD( BANKPSW + _R4_ );"); - } - if ($op_destination == 11) { # R5 - cfw("unsigned char destination = cpu8051_ReadD( BANKPSW + _R5_ );"); - } - if ($op_destination == 12) { # R6 - cfw("unsigned char destination = cpu8051_ReadD( BANKPSW + _R6_ );"); - } - if ($op_destination == 13) { # R7 - cfw("unsigned char destination = cpu8051_ReadD( BANKPSW + _R7_ );"); - } - if ($op_destination == 14) { # bitaddr - cfw("unsigned char destination, dstbitaddr = memory_read8( PGM_MEM_ID, cpu8051.pc++ );"); - cfw("destination = cpu8051_ReadB( dstbitaddr );"); - } - if ($op_destination == 15) { # reladdr - cfw("cpu8051.pc++;"); - cfw("unsigned int destination = ((char) memory_read8(PGM_MEM_ID, cpu8051.pc - 1)) + cpu8051.pc;"); - } - if ($op_destination == 16) { # #data - cfw("unsigned char destination = memory_read8( PGM_MEM_ID, cpu8051.pc++ );"); - } - if ($op_destination == 17) { # C - cfw("unsigned char destination = psw_read_cy();"); - } - if ($op_destination == 18) { # @A+DPTR - cfw("unsigned int destination = cpu8051_ReadD( _ACC_ ) + memory_sfr_read_dptr();"); - } - if ($op_destination == 20) { # AB - cfw("unsigned char destination = cpu8051_ReadD( _ACC_ );"); - cfw("unsigned char source = cpu8051_ReadD( _B_ );"); - } - if ($op_destination == 21) { # DPTR - cfw("unsigned int destination = memory_sfr_read_dptr();"); - } - if ($op_destination == 23) { # /bitaddr - cfw("unsigned char destination, dstbitaddr = memory_read8( PGM_MEM_ID, (cpu8051.pc)++ );"); - cfw("destination = ( cpu8051_ReadB( dstbitaddr ) ^ 1 );"); - } - if ($op_destination == 24) { # @DPTR - cfw("unsigned char destination = cpu8051_ReadI(memory_sfr_read_dptr());"); - } - } - - if ($instargs[$i*4] > 1) { - $op_source=$instargs[$i*4+2]; - if ($op_source == 0) { # addr11 - cfw("unsigned int addr11 = ( ( memory_read8( PGM_MEM_ID, cpu8051.pc - 1 ) << 3 ) & 0xF00 ) + memory_read8( PGM_MEM_ID, (cpu8051.pc)++ );"); - } - if ($op_source == 1) { # addr16 - cfw("uint16_t addr16 = pgm_read_addr16(cpu8051.pc);"); - cfw("cpu8051.pc += 2;"); - } - if ($op_source == 2) { # A - cfw("unsigned char source = cpu8051_ReadD( _ACC_ );"); - } - if ($op_source == 3) { # direct - cfw("unsigned char srcaddr = memory_read8( PGM_MEM_ID, (cpu8051.pc)++ );"); - cfw("unsigned char source = cpu8051_ReadD( srcaddr );"); - } - if ($op_source == 4) { # @R0 - cfw("unsigned char source = cpu8051_ReadI ( cpu8051_ReadD( BANKPSW + _R0_ ) );"); - } - if ($op_source == 5) { # @R1 - cfw("unsigned char source = cpu8051_ReadI ( cpu8051_ReadD( BANKPSW + _R1_ ) );"); - } - if ($op_source == 6) { # R0 - cfw("unsigned char source = cpu8051_ReadD( BANKPSW + _R0_ );"); - } - if ($op_source == 7) { # R1 - cfw("unsigned char source = cpu8051_ReadD( BANKPSW + _R1_ );"); - } - if ($op_source == 8) { # R2 - cfw("unsigned char source = cpu8051_ReadD( BANKPSW + _R2_ );"); - } - if ($op_source == 9) { # R3 - cfw("unsigned char source = cpu8051_ReadD( BANKPSW + _R3_ );"); - } - if ($op_source == 10) { # R4 - cfw("unsigned char source = cpu8051_ReadD( BANKPSW + _R4_ );"); - } - if ($op_source == 11) { # R5 - cfw("unsigned char source = cpu8051_ReadD( BANKPSW + _R5_ );"); - } - if ($op_source == 12) { # R6 - cfw("unsigned char source = cpu8051_ReadD( BANKPSW + _R6_ );"); - } - if ($op_source == 13) { # R7 - cfw("unsigned char source = cpu8051_ReadD( BANKPSW + _R7_ );"); - } - - if ($op_source == 14) { # bitaddr - cfw("unsigned char source, srcbitaddr = memory_read8( PGM_MEM_ID, (cpu8051.pc)++ );"); - cfw("source = cpu8051_ReadB( srcbitaddr );"); - } - if ($op_source == 15) { # reladdr - cfw("(cpu8051.pc)++;"); - cfw("unsigned int source = ((char) memory_read8(PGM_MEM_ID, cpu8051.pc - 1)) + cpu8051.pc;"); - } - if ($op_source == 16) { # #data - cfw("unsigned char source = memory_read8( PGM_MEM_ID, (cpu8051.pc)++ );"); - } - if ($op_source == 17) { # C - cfw("unsigned char source = psw_read_cy();"); - } - if ($op_source == 18) { # @A+DPTR - cfw("unsigned char source = memory_read8( PGM_MEM_ID, cpu8051_ReadD( _ACC_ ) + memory_sfr_read_dptr());"); - } - if ($op_source == 19) { # @A+PC - cfw("unsigned char source = memory_read8( PGM_MEM_ID, cpu8051_ReadD( _ACC_ ) + ( ++cpu8051.pc ) );"); - } - if ($op_source == 21) { # DPTR - cfw("unsigned int source = memory_sfr_read_dptr();"); - } - if ($op_source == 22) { # #data16 - cfw("uint16_t source = pgm_read_addr16(cpu8051.pc);"); - cfw("cpu8051.pc += 2;"); - } - if ($op_source == 23) { # /bitaddr - cfw("unsigned char source, srcbitaddr = memory_read8( PGM_MEM_ID, (cpu8051.pc)++ );"); - cfw("source = ( cpu8051_ReadB( srcbitaddr ) ^ 1 );"); - } - if ($op_source == 24) { # @DPTR - cfw("unsigned char source = cpu8051_ReadI(memory_sfr_read_dptr());"); - } - } - -############################################################################## - $modifysrc=0; - - # RR - if ($insttype[$i] == 3) { - cfw("destination = ( destination >> 1 ) | ( destination << 7 );"); - } - - # INC - if ($insttype[$i] == 4) { - cfw("destination++;"); - } - - # JBC - if ($insttype[$i] == 5) { - cfw("if ( destination == 1 ) { cpu8051.pc = source; destination = 0; }"); - } - - # ACALL - if ($insttype[$i] == 6) { - cfw("stack_push16(cpu8051.pc);"); - } - - # LCALL - if ($insttype[$i] == 7) { - cfw("stack_push16(cpu8051.pc);"); - } - - # RRC - if ($insttype[$i] == 8) { - cfw("unsigned char new_cy = destination & 0x01;"); - cfw("destination = ( destination >> 1 ) | (psw_read_cy() << 7);"); - cfw("psw_write_cy(new_cy);"); - } - - # DEC - if ($insttype[$i] == 9) { - cfw("destination--;"); - } - - # JB - if ($insttype[$i] == 10) { - cfw("if ( destination == 1 ) { cpu8051.pc = source; }"); - } - - # RET - if ($insttype[$i] == 11) { - cfw("cpu8051.pc = stack_pop16();"); - } - - # RL - if ($insttype[$i] == 12) { - cfw("destination = ( destination << 1 ) | ( destination >> 7 );"); - } - - # ADD - if ($insttype[$i] == 13) { - cfw("psw_clr_cy();"); - cfw("psw_clr_ac();"); - cfw("psw_clr_ov();"); - # The Overflow (OV) bit is set if there is a carry-out of bit 6 or - # out of bit 7, but not both. In other words, if the addition of the - # Accumulator, operand and (in the case of ADDC) the Carry flag - # treated as signed values results in a value that is out of the - # range of a signed byte (-128 through +127) the Overflow flag is - # set. Otherwise, the Overflow flag is cleared. - cfw("if ( destination + source > 0xFF ) {"); - # Carry from bit 7 - cfw(" psw_set_cy();"); - # If no carry from bit 6, set OV - cfw(" if (((destination & 0x7F) + (source & 0x7F)) < 0x80)"); - cfw(" psw_set_ov();"); - # If no carry from bit 7, but caary from bit 6, set OV - cfw("} else if (((destination & 0x7F) + (source & 0x7F)) > 0x7F ) psw_set_ov();"); - cfw("if (((destination & 0x0F) + (source & 0x0F)) > 0x0F) psw_set_ac();"); - cfw("destination += source;"); - } - - # JNB - if ($insttype[$i] == 14) { - cfw("if ( destination == 0 ) { cpu8051.pc = source; }"); - } - - # RETI - if ($insttype[$i] == 15) { - cfw("cpu8051.active_priority = -1;"); - cfw("cpu8051.pc = stack_pop16();"); - } - - # RLC - if ($insttype[$i] == 16) { - cfw("unsigned char new_cy = destination & 0x80;"); - cfw("destination = ( destination << 1 ) | psw_read_cy();"); - cfw("psw_write_cy(new_cy);"); - } - - # ADDC - if ($insttype[$i] == 17) { - cfw("unsigned char carryflag = psw_read_cy();"); - cfw("psw_clr_cy();"); - cfw("psw_clr_ac();"); - cfw("psw_clr_ov();"); - cfw("if ( destination + source + carryflag > 0xFF ) {"); - cfw(" psw_set_cy();"); - cfw(" if (((destination & 0x7F) + (source & 0x7F) + carryflag) < 0x80);"); - cfw(" psw_set_ov();"); - cfw("} else if (((destination & 0x7F) + (source & 0x7F) + carryflag) > 0x7F) psw_set_ov();"); - cfw("if (((destination & 0x0F) + (source & 0x0F) + carryflag) > 0x0F) psw_set_ac();"); - cfw("destination += source;"); - } - - # JC - if ($insttype[$i] == 18) { - cfw("if (psw_read_cy()) { cpu8051.pc = destination; }"); - } - - # ORL - if ($insttype[$i] == 19) { - cfw("destination |= source;"); - } - - # JNC - if ($insttype[$i] == 20) { - cfw("if (psw_read_cy() == 0) { cpu8051.pc = destination; }"); - } - - # ANL - if ($insttype[$i] == 21) { - cfw("destination &= source;"); - } - - # JZ - if ($insttype[$i] == 22) { - cfw("if ( cpu8051_ReadD( _ACC_ ) == 0 ) { cpu8051.pc = destination; }"); - } - - # XRL - if ($insttype[$i] == 23) { - cfw("destination ^= source;"); - } - - # JNZ - if ($insttype[$i] == 24) { - cfw("if ( cpu8051_ReadD( _ACC_ ) != 0 ) { cpu8051.pc = destination; }"); - } - - # JMP - if ($insttype[$i] == 25) { - cfw("cpu8051.pc = destination;"); - } - - # MOV - if ($insttype[$i] == 26) { - cfw("destination = source;"); - } - - # SJMP - if ($insttype[$i] == 27) { - cfw("cpu8051.pc = destination;"); - } - - # MOVC - if ($insttype[$i] == 28) { - cfw("destination = source;"); - } - - # DIV - if ($insttype[$i] == 29) { - # A = destination - # B = source - cfw("psw_clr_cy();"); - # If B is zero, the OV flag will be set indicating a - # division-by-zero error - cfw("if (source != 0) {"); - cfw(" cpu8051_WriteD(_ACC_, destination/source);"); - cfw(" cpu8051_WriteD( _B_, destination%source);"); - cfw(" psw_clr_ov();"); - cfw("} else {"); - cfw(" psw_set_ov();"); - cfw("}"); - } - - # SUBB - if ($insttype[$i] == 30) { - cfw("unsigned char carryflag = psw_read_cy();"); - cfw("psw_clr_cy();"); - cfw("psw_clr_ac();"); - cfw("psw_clr_ov();"); - cfw("if ( destination < ( source + carryflag ) ) {"); - cfw(" psw_set_cy();"); - cfw(" if ((destination & 0x7F) > ((source + carryflag) & 0x7F)) psw_set_ov();"); - cfw("} else if ((destination & 0x7F) < ((source + carryflag) & 0x7F)) psw_set_ov();"); - cfw("if ((destination & 0x0F) < ((source + carryflag) & 0x0F)) psw_set_ac();"); - cfw("destination -= source + carryflag;"); - } - - # MUL - if ($insttype[$i] == 31) { - # A = destination - # B = source - cfw("psw_clr_cy();"); - cfw("cpu8051_WriteD(_ACC_, destination * source);"); - cfw("cpu8051_WriteD(_B_, (destination * source) / 0x100);"); - cfw("if (cpu8051_ReadD(_B_) > 0)"); - cfw(" psw_set_ov();"); - cfw("else"); - cfw(" psw_clr_ov();"); - } - - # CPL - if ($insttype[$i] == 33) { - if ($instargs[$i*4+1] == 2) { cfw("destination ^= 0xFF;"); } - else { cfw("destination ^= 0x01;"); } - } - - # CJNE - if ($insttype[$i] == 34) { - cfw("unsigned int reladdr = ((char) memory_read8(PGM_MEM_ID, cpu8051.pc)) + (cpu8051.pc + 1);"); - cfw("psw_clr_cy();"); - cfw("if ( destination < source ) psw_set_cy();"); - cfw("if ( destination != source ) cpu8051.pc = reladdr; else cpu8051.pc++;"); - } - - # PUSH - if ($insttype[$i] == 35) { - cfw("stack_push8(destination);"); - } - - # CLR - if ($insttype[$i] == 36) { - cfw("destination = 0;"); - } - - # SWAP - if ($insttype[$i] == 37) { - cfw("destination = ( destination << 4 ) + ( destination >> 4 );"); - } - - # XCH - if ($insttype[$i] == 38) { - cfw("unsigned char tmpval = destination;"); - cfw("destination = source; source = tmpval;"); - $modifysrc=1; - } - - # POP - if ($insttype[$i] == 39) { - cfw("destination = stack_pop8();"); - } - - # SETB - if ($insttype[$i] == 40) { - cfw("destination = 1;"); - } - - # DA - if ($insttype[$i] == 41) { - cfw("if (((destination & 0x0F) > 9) || psw_read_ac()) {"); - cfw(" if ( ( destination + 6 ) > 0xFF) psw_set_cy();"); - cfw(" destination += 6;"); - cfw("}"); - cfw("if ( psw_read_cy() || ( ( destination & 0xF0 ) > 0x90 ) ) {"); - cfw(" if ( ( destination + 0x60 ) > 0xFF ) psw_set_cy();"); - cfw(" destination += 0x60;"); - cfw("}"); - } - - # DJNZ - if ($insttype[$i] == 42) { - cfw("destination--;"); - cfw("if ( destination != 0 ) cpu8051.pc = source;"); - } - - # XCHD - if ($insttype[$i] == 43) { - cfw("unsigned char tmpval = ( destination & 0x0F );"); - cfw("destination = ( destination & 0xF0 ) + ( source & 0x0F );"); - cfw("source = ( source & 0xF0 ) + tmpval;"); - $modifysrc=1; - } - - # MOVX - if ($insttype[$i] == 44) { - cfw("destination = source;"); - } - - - -############################################################################## - - - if ($instargs[$i*4] > 0) { - $op_destination=$instargs[$i*4+1]; - if ($op_destination == 0) { # addr11 - cfw("cpu8051.pc = ( cpu8051.pc & 0xF800 ) | addr11;"); - } - if ($op_destination == 1) { # addr16 - cfw("cpu8051.pc = addr16;"); - } - if ($op_destination == 2) { # A - cfw("cpu8051_WriteD( _ACC_, destination );"); - } - if ($op_destination == 3) { # direct - cfw("cpu8051_WriteD( destaddr, destination );"); - } - if ($op_destination == 4) { # @R0 - cfw("cpu8051_WriteI( cpu8051_ReadD( BANKPSW + _R0_ ), destination );"); - } - if ($op_destination == 5) { # @R1 - cfw("cpu8051_WriteI( cpu8051_ReadD( BANKPSW + _R1_ ), destination );"); - } - if ($op_destination == 6) { # R0 - cfw("cpu8051_WriteD( BANKPSW + _R0_, destination );"); - } - if ($op_destination == 7) { # R1 - cfw("cpu8051_WriteD( BANKPSW + _R1_, destination );"); - } - if ($op_destination == 8) { # R2 - cfw("cpu8051_WriteD( BANKPSW + _R2_, destination );"); - } - if ($op_destination == 9) { # R3 - cfw("cpu8051_WriteD( BANKPSW + _R3_, destination );"); - } - if ($op_destination == 10) { # R4 - cfw("cpu8051_WriteD( BANKPSW + _R4_, destination );"); - } - if ($op_destination == 11) { # R5 - cfw("cpu8051_WriteD( BANKPSW + _R5_, destination );"); - } - if ($op_destination == 12) { # R6 - cfw("cpu8051_WriteD( BANKPSW + _R6_, destination );"); - } - if ($op_destination == 13) { # R7 - cfw("cpu8051_WriteD( BANKPSW + _R7_, destination );"); - } - - if ($op_destination == 14) { # bitaddr - cfw("cpu8051_WriteB( dstbitaddr, destination );"); - } - if ($op_destination == 17) { # C - cfw("psw_write_cy(destination);"); - } - if ($op_destination == 21) { # DPTR - cfw("memory_sfr_write_dptr(destination);"); - } - if ($op_destination == 23) { # /bitaddr - cfw("cpu8051_WriteB( dstbitaddr, destination );"); - } - if ($op_destination == 24) { # @DPTR - cfw("cpu8051_WriteI(memory_sfr_read_dptr(), destination);"); - } - } - - if ($modifysrc == 1) { - if ($instargs[$i*4] > 1) { - $op_source=$instargs[$i*4+2]; - if ($op_source == 0) { # addr11 - cfw("cpu8051.pc = ( cpu8051.pc & 0xF800 ) | addr11;"); - } - if ($op_source == 1) { # addr16 - cfw("cpu8051.pc = addr16;"); - } - if ($op_source == 2) { # A - cfw("cpu8051_WriteD( _ACC_, source );"); - } - if ($op_source == 3) { # direct - cfw("cpu8051_WriteD( srcaddr, source );"); - } - if ($op_source == 4) { # @R0 - cfw("cpu8051_WriteI( cpu8051_ReadD( BANKPSW + _R0_ ), source );"); - } - if ($op_source == 5) { # @R1 - cfw("cpu8051_WriteI( cpu8051_ReadD( BANKPSW + _R1_ ), source );"); - } - if ($op_source == 6) { # R0 - cfw("cpu8051_WriteD( BANKPSW + _R0_, source );"); - } - if ($op_source == 7) { # R1 - cfw("cpu8051_WriteD( BANKPSW + _R1_, source );"); - } - if ($op_source == 8) { # R2 - cfw("cpu8051_WriteD( BANKPSW + _R2_, source );"); - } - if ($op_source == 9) { # R3 - cfw("cpu8051_WriteD( BANKPSW + _R3_, source );"); - } - if ($op_source == 10) { # R4 - cfw("cpu8051_WriteD( BANKPSW + _R4_, source );"); - } - if ($op_source == 11) { # R5 - cfw("cpu8051_WriteD( BANKPSW + _R5_, source );"); - } - if ($op_source == 12) { # R6 - cfw("cpu8051_WriteD( BANKPSW + _R6_, source );"); - } - if ($op_source == 13) { # R7 - cfw("cpu8051_WriteD( BANKPSW + _R7_, source );"); - } - if ($op_source == 14) { # bitaddr - cfw("cpu8051_WriteB( srcbitaddr, source );"); - } - if ($op_source == 17) { # C - cfw("psw_write_cy(source);"); - } - if ($op_source == 21) { # DPTR - cfw("memory_sfr_write_dptr(source);"); - } - if ($op_source == 23) { # /bitaddr - cfw("cpu8051_WriteB( srcbitaddr, source );"); - } - if ($op_source == 24) { # @DPTR - cfw("cpu8051_WriteI(memory_sfr_read_dptr(), source);"); - } - } - } - } - cfw("return $a_cycles[$i];"); - print INST_IMP "}\n"; - print INST_IMP "\n"; -} -# ------------------------------------------------------------------------------ - - -# Header for instructions_8051.h -print INST_DEF "/*\n"; -print INST_DEF " * instructions_8051.h\n"; -write_header(INST_DEF); -print INST_DEF "#ifndef INSTRUCTIONS_8051_H\n"; -print INST_DEF "#define INSTRUCTIONS_8051_H 1\n\n\n"; -print INST_DEF "#define BANKPSW (cpu8051_ReadD(_PSW_) & 0x18)\n\n"; -print INST_DEF "typedef int (*OPCODE_FP)(void);\n\n\n"; -for( $i=0; $i<256; $i++ ) { - print INST_DEF "int\n"; - print INST_DEF "cpu8051_OP_$a_opcodehex[$i](void);\n\n"; -} -print INST_DEF "\n"; -print INST_DEF "/* Exported variables. */\n"; -print INST_DEF "#ifdef INSTRUCTIONS_8051_M\n"; -print INST_DEF "OPCODE_FP opcode_table[256] = {\n"; -for( $i=0; $i<256; $i++ ) { - $ifunc=substr($instfunction[$i], 9); - if( $i < 255 ) { - print INST_DEF " cpu8051_$ifunc,\n"; - } - else { - print INST_DEF " cpu8051_$ifunc\n"; - print INST_DEF "};\n"; - } -} - -print INST_DEF "#else\n"; -print INST_DEF "OPCODE_FP opcode_table[256];\n"; -print INST_DEF "#endif\n\n\n"; - -print INST_DEF "#endif /* INSTRUCTIONS_8051_H */\n"; - -print DISASM_H "#endif /* DISASM_H */\n"; - -close DISASM_H; -close OPCODELST; -close INST_DEF; -close INST_IMP; diff --git a/src/opcodes.lst b/src/opcodes.lst deleted file mode 100644 index 1494258..0000000 --- a/src/opcodes.lst +++ /dev/null @@ -1,258 +0,0 @@ -Opcode(bin) Opcode Instruction Bytes Cycles --------------------------------------------------------------- -00000000 00 NOP 1 1 -00000001 01 AJMP addr11 2 2 -00000010 02 LJMP addr16 3 2 -00000011 03 RR A 1 1 -00000100 04 INC A 1 1 -00000101 05 INC direct 2 1 -00000110 06 INC @R0 1 1 -00000111 07 INC @R1 1 1 -00001000 08 INC R0 1 1 -00001001 09 INC R1 1 1 -00001010 0A INC R2 1 1 -00001011 0B INC R3 1 1 -00001100 0C INC R4 1 1 -00001101 0D INC R5 1 1 -00001110 0E INC R6 1 1 -00001111 0F INC R7 1 1 -00010000 10 JBC bitaddr,reladdr 3 2 -00010001 11 ACALL addr11 2 2 -00010010 12 LCALL addr16 3 2 -00010011 13 RRC A 1 1 -00010100 14 DEC A 1 1 -00010101 15 DEC direct 2 1 -00010110 16 DEC @R0 1 1 -00010111 17 DEC @R1 1 1 -00011000 18 DEC R0 1 1 -00011001 19 DEC R1 1 1 -00011010 1A DEC R2 1 1 -00011011 1B DEC R3 1 1 -00011100 1C DEC R4 1 1 -00011101 1D DEC R5 1 1 -00011110 1E DEC R6 1 1 -00011111 1F DEC R7 1 1 -00100000 20 JB bitaddr,reladdr 3 2 -00100001 21 AJMP addr11 2 2 -00100010 22 RET 1 2 -00100011 23 RL A 1 1 -00100100 24 ADD A,#data 2 1 -00100101 25 ADD A,direct 2 1 -00100110 26 ADD A,@R0 1 1 -00100111 27 ADD A,@R1 1 1 -00101000 28 ADD A,R0 1 1 -00101001 29 ADD A,R1 1 1 -00101010 2A ADD A,R2 1 1 -00101011 2B ADD A,R3 1 1 -00101100 2C ADD A,R4 1 1 -00101101 2D ADD A,R5 1 1 -00101110 2E ADD A,R6 1 1 -00101111 2F ADD A,R7 1 1 -00110000 30 JNB bitaddr,reladdr 3 2 -00110001 31 ACALL addr11 2 2 -00110010 32 RETI 1 2 -00110011 33 RLC A 1 1 -00110100 34 ADDC A,#data 2 1 -00110101 35 ADDC A,direct 2 1 -00110110 36 ADDC A,@R0 1 1 -00110111 37 ADDC A,@R1 1 1 -00111000 38 ADDC A,R0 1 1 -00111001 39 ADDC A,R1 1 1 -00111010 3A ADDC A,R2 1 1 -00111011 3B ADDC A,R3 1 1 -00111100 3C ADDC A,R4 1 1 -00111101 3D ADDC A,R5 1 1 -00111110 3E ADDC A,R6 1 1 -00111111 3F ADDC A,R7 1 1 -01000000 40 JC reladdr 2 2 -01000001 41 AJMP addr11 2 2 -01000010 42 ORL direct,A 2 1 -01000011 43 ORL direct,#data 3 2 -01000100 44 ORL A,#data 2 1 -01000101 45 ORL A,direct 2 1 -01000110 46 ORL A,@R0 1 1 -01000111 47 ORL A,@R1 1 1 -01001000 48 ORL A,R0 1 1 -01001001 49 ORL A,R1 1 1 -01001010 4A ORL A,R2 1 1 -01001011 4B ORL A,R3 1 1 -01001100 4C ORL A,R4 1 1 -01001101 4D ORL A,R5 1 1 -01001110 4E ORL A,R6 1 1 -01001111 4F ORL A,R7 1 1 -01010000 50 JNC reladdr 2 2 -01010001 51 ACALL addr11 2 2 -01010010 52 ANL direct,A 2 1 -01010011 53 ANL direct,#data 3 2 -01010100 54 ANL A,#data 2 1 -01010101 55 ANL A,direct 2 1 -01010110 56 ANL A,@R0 1 1 -01010111 57 ANL A,@R1 1 1 -01011000 58 ANL A,R0 1 1 -01011001 59 ANL A,R1 1 1 -01011010 5A ANL A,R2 1 1 -01011011 5B ANL A,R3 1 1 -01011100 5C ANL A,R4 1 1 -01011101 5D ANL A,R5 1 1 -01011110 5E ANL A,R6 1 1 -01011111 5F ANL A,R7 1 1 -01100000 60 JZ reladdr 2 2 -01100001 61 AJMP addr11 2 2 -01100010 62 XRL direct,A 2 1 -01100011 63 XRL direct,#data 3 2 -01100100 64 XRL A,#data 2 1 -01100101 65 XRL A,direct 2 1 -01100110 66 XRL A,@R0 1 1 -01100111 67 XRL A,@R1 1 1 -01101000 68 XRL A,R0 1 1 -01101001 69 XRL A,R1 1 1 -01101010 6A XRL A,R2 1 1 -01101011 6B XRL A,R3 1 1 -01101100 6C XRL A,R4 1 1 -01101101 6D XRL A,R5 1 1 -01101110 6E XRL A,R6 1 1 -01101111 6F XRL A,R7 1 1 -01110000 70 JNZ reladdr 2 2 -01110001 71 ACALL addr11 2 2 -01110010 72 ORL C,bitaddr 2 2 -01110011 73 JMP @A+DPTR 1 2 -01110100 74 MOV A,#data 2 1 -01110101 75 MOV direct,#data 3 2 -01110110 76 MOV @R0,#data 2 1 -01110111 77 MOV @R1,#data 2 1 -01111000 78 MOV R0,#data 2 1 -01111001 79 MOV R1,#data 2 1 -01111010 7A MOV R2,#data 2 1 -01111011 7B MOV R3,#data 2 1 -01111100 7C MOV R4,#data 2 1 -01111101 7D MOV R5,#data 2 1 -01111110 7E MOV R6,#data 2 1 -01111111 7F MOV R7,#data 2 1 -10000000 80 SJMP reladdr 2 2 -10000001 81 AJMP addr11 2 2 -10000010 82 ANL C,bitaddr 2 1 -10000011 83 MOVC A,@A+PC 1 1 -10000100 84 DIV AB 1 4 -10000101 85 MOV direct,direct 3 1 -10000110 86 MOV direct,@R0 2 2 -10000111 87 MOV direct,@R1 2 2 -10001000 88 MOV direct,R0 2 2 -10001001 89 MOV direct,R1 2 2 -10001010 8A MOV direct,R2 2 2 -10001011 8B MOV direct,R3 2 2 -10001100 8C MOV direct,R4 2 2 -10001101 8D MOV direct,R5 2 2 -10001110 8E MOV direct,R6 2 2 -10001111 8F MOV direct,R7 2 2 -10010000 90 MOV DPTR,#data16 3 2 -10010001 91 ACALL addr11 2 2 -10010010 92 MOV bitaddr,C 2 2 -10010011 93 MOVC A,@A+DPTR 1 2 -10010100 94 SUBB A,#data 2 1 -10010101 95 SUBB A,direct 2 1 -10010110 96 SUBB A,@R0 1 1 -10010111 97 SUBB A,@R1 1 1 -10011000 98 SUBB A,R0 1 1 -10011001 99 SUBB A,R1 1 1 -10011010 9A SUBB A,R2 1 1 -10011011 9B SUBB A,R3 1 1 -10011100 9C SUBB A,R4 1 1 -10011101 9D SUBB A,R5 1 1 -10011110 9E SUBB A,R6 1 1 -10011111 9F SUBB A,R7 1 1 -10100000 A0 ORL C,/bitaddr 2 1 -10100001 A1 AJMP addr11 2 2 -10100010 A2 MOV C,bitaddr 2 1 -10100011 A3 INC DPTR 1 2 -10100100 A4 MUL AB 1 4 -10100101 A5 INVALID 1 1 -10100110 A6 MOV @R0,direct 2 2 -10100111 A7 MOV @R1,direct 2 2 -10101000 A8 MOV R0,direct 2 2 -10101001 A9 MOV R1,direct 2 2 -10101010 AA MOV R2,direct 2 2 -10101011 AB MOV R3,direct 2 2 -10101100 AC MOV R4,direct 2 2 -10101101 AD MOV R5,direct 2 2 -10101110 AE MOV R6,direct 2 2 -10101111 AF MOV R7,direct 2 2 -10110000 B0 ANL C,/bitaddr 2 1 -10110001 B1 ACALL addr11 2 2 -10110010 B2 CPL bitaddr 2 1 -10110011 B3 CPL C 1 1 -10110100 B4 CJNE A,#data,reladdr 3 2 -10110101 B5 CJNE A,direct,reladdr 3 2 -10110110 B6 CJNE @R0,#data,reladdr 3 2 -10110111 B7 CJNE @R1,#data,reladdr 3 2 -10111000 B8 CJNE R0,#data,reladdr 3 2 -10111001 B9 CJNE R1,#data,reladdr 3 2 -10111010 BA CJNE R2,#data,reladdr 3 2 -10111011 BB CJNE R3,#data,reladdr 3 2 -10111100 BC CJNE R4,#data,reladdr 3 2 -10111101 BD CJNE R5,#data,reladdr 3 2 -10111110 BE CJNE R6,#data,reladdr 3 2 -10111111 BF CJNE R7,#data,reladdr 3 2 -11000000 C0 PUSH direct 2 2 -11000001 C1 AJMP addr11 2 2 -11000010 C2 CLR bitaddr 2 1 -11000011 C3 CLR C 1 1 -11000100 C4 SWAP A 1 1 -11000101 C5 XCH A,direct 2 1 -11000110 C6 XCH A,@R0 1 1 -11000111 C7 XCH A,@R1 1 1 -11001000 C8 XCH A,R0 1 1 -11001001 C9 XCH A,R1 1 1 -11001010 CA XCH A,R2 1 1 -11001011 CB XCH A,R3 1 1 -11001100 CC XCH A,R4 1 1 -11001101 CD XCH A,R5 1 1 -11001110 CE XCH A,R6 1 1 -11001111 CF XCH A,R7 1 1 -11010000 D0 POP direct 2 2 -11010001 D1 ACALL addr11 2 2 -11010010 D2 SETB bitaddr 2 1 -11010011 D3 SETB C 1 1 -11010100 D4 DA A 1 1 -11010101 D5 DJNZ direct,reladdr 3 2 -11010110 D6 XCHD A,@R0 1 1 -11010111 D7 XCHD A,@R1 1 1 -11011000 D8 DJNZ R0,reladdr 2 2 -11011001 D9 DJNZ R1,reladdr 2 2 -11011010 DA DJNZ R2,reladdr 2 2 -11011011 DB DJNZ R3,reladdr 2 2 -11011100 DC DJNZ R4,reladdr 2 2 -11011101 DD DJNZ R5,reladdr 2 2 -11011110 DE DJNZ R6,reladdr 2 2 -11011111 DF DJNZ R7,reladdr 2 2 -11100000 E0 MOVX A,@DPTR 1 2 -11100001 E1 AJMP addr11 2 2 -11100010 E2 MOVX A,@R0 1 2 -11100011 E3 MOVX A,@R1 1 2 -11100100 E4 CLR A 1 1 -11100101 E5 MOV A,direct 2 1 -11100110 E6 MOV A,@R0 1 1 -11100111 E7 MOV A,@R1 1 1 -11101000 E8 MOV A,R0 1 1 -11101001 E9 MOV A,R1 1 1 -11101010 EA MOV A,R2 1 1 -11101011 EB MOV A,R3 1 1 -11101100 EC MOV A,R4 1 1 -11101101 ED MOV A,R5 1 1 -11101110 EE MOV A,R6 1 1 -11101111 EF MOV A,R7 1 1 -11110000 F0 MOVX @DPTR,A 1 2 -11110001 F1 ACALL addr11 2 2 -11110010 F2 MOVX @R0,A 1 2 -11110011 F3 MOVX @R1,A 1 2 -11110100 F4 CPL A 1 1 -11110101 F5 MOV direct,A 2 1 -11110110 F6 MOV @R0,A 1 1 -11110111 F7 MOV @R1,A 1 1 -11111000 F8 MOV R0,A 1 1 -11111001 F9 MOV R1,A 1 1 -11111010 FA MOV R2,A 1 1 -11111011 FB MOV R3,A 1 1 -11111100 FC MOV R4,A 1 1 -11111101 FD MOV R5,A 1 1 -11111110 FE MOV R6,A 1 1 -11111111 FF MOV R7,A 1 1 diff --git a/src/options.c b/src/options.c deleted file mode 100644 index 420cc85..0000000 --- a/src/options.c +++ /dev/null @@ -1,184 +0,0 @@ -/* - * options.c -- functions for processing command-line options and arguments - * - * Copyright (C) 2011 Hugo Villeneuve - * - * This program 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 of the License, or - * (at your option) any later version. - */ - -#if HAVE_CONFIG_H -# include "config.h" -#endif - -#include -#include -#include -#include - -#if STDC_HEADERS -# include -#elif HAVE_STRINGS_H -# include -#endif - -#include "common.h" -#include "options.h" -#include "memory.h" - -const char *argp_program_version = PACKAGE_VERSION; -const char *argp_program_bug_address = PACKAGE_BUGREPORT; - -#define PACKAGE_DOC_LENGTH 128 - -/* Program documentation. */ -static char str_doc[PACKAGE_DOC_LENGTH]; - -/* How many arguments we accept. */ -#define ARGS_COUNT 1 - -/* A description of the arguments we accept. */ -static const char args_doc[] = "[FILENAME]"; - -/* The options we understand. */ -static struct argp_option argp_options[] = { - {"debug", 'd', "level", 0, "Produce debugging output" }, - {"pram", 'p', "size", 0, "Set program memory size" }, - {"xram", 'x', "size", 0, "Set external ram size (default is 1024)" }, - {"stop", 's', "addr", 0, "Automatically run program and stop at address" }, - { 0 } -}; - -struct options_t options; - -const char * -get_package_description(void) -{ - return "Emulator for 8051 family microcontrollers"; -} - -static void -decode_debug_option(char *arg, struct argp_state *state) -{ - char *endptr; - int log_level; - - log_level = strtol(arg, &endptr, 0); - - if (*endptr != '\0') { - log_err("Invalid log level"); - argp_usage(state); - } - - if (log_level > LOG_LEVEL_DEBUG) { - log_err("Invalid log level (0 to 3)"); - argp_usage(state); - } - - options.log = log_level; -} - -static void -decode_memory_size(char *arg, struct argp_state *state, int memid) -{ - char *endptr; - int *dest; - - if (memid == PGM_MEM_ID) - dest = &options.pram_size; - else if (memid == INT_MEM_ID) - dest = &options.iram_size; - else if (memid == EXT_MEM_ID) - dest = &options.xram_size; - else - exit(1); /* Programming error. */ - - /* - * Sizes versus max memory sizes will be checked when calling - * memory_init(). - */ - *dest = strtol(arg, &endptr, 0); - - if (*endptr != '\0') { - log_err("Invalid memory size"); - argp_usage(state); - } -} - -static void -decode_address(char *arg, struct argp_state *state, uint16_t *dest) -{ - char *endptr; - - *dest = strtol(arg, &endptr, 0); - - if (*endptr != '\0') { - log_err("Invalid address"); - argp_usage(state); - } -} - -/* Parse a single option. */ -static error_t -parse_opt(int key, char *arg, struct argp_state *state) -{ - switch (key) { - case 'd': - decode_debug_option(arg, state); - break; - case 'i': - decode_memory_size(arg, state, INT_MEM_ID); - break; - case 'p': - decode_memory_size(arg, state, PGM_MEM_ID); - break; - case 's': - decode_address(arg, state, &options.stop_address); - break; - case 'x': - decode_memory_size(arg, state, EXT_MEM_ID); - break; - case ARGP_KEY_ARG: - if (state->arg_num >= ARGS_COUNT) { - /* Too many arguments. */ - argp_usage(state); - } - - options.filename = arg; - break; - case ARGP_KEY_END: - if (state->arg_num < ARGS_COUNT) { - /* Not enough arguments, but the filename is optional. - So no error. */ - } - break; - default: - return ARGP_ERR_UNKNOWN; - } - - return 0; -} - -/* Our argp parser. */ -static struct argp argp = { argp_options, parse_opt, args_doc, str_doc }; - -/* Initializes the different options passed as arguments on the command line. */ -void -parse_command_line_options(int argc, char *argv[]) -{ - snprintf(str_doc, PACKAGE_DOC_LENGTH, "%s -- %s", PACKAGE_NAME, - get_package_description()); - - /* Setting default values. */ - options.filename = NULL; - options.pram_size = PGM_MEM_DEFAULT_SIZE; - options.iram_size = INT_MEM_MAX_SIZE; - options.xram_size = EXT_MEM_DEFAULT_SIZE; - options.log = LOG_LEVEL_ERR; - options.stop_address = 0; /* 0 means stop address is disabled. */ - - /* Parse our arguments. */ - argp_parse(&argp, argc, argv, 0, 0, NULL); -} diff --git a/src/options.h b/src/options.h deleted file mode 100644 index 589c2d5..0000000 --- a/src/options.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * options.h - * - * Copyright (C) 1999 Hugo Villeneuve - * - * This program 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 of the License, or - * (at your option) any later version. - * - * This program 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 this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#ifndef OPTIONS_H -#define OPTIONS_H 1 - -#define COMMAND_LINE_OPTIONS \ - "Usage: " PACKAGE " [OPTION]... [FILENAME]\n" \ - "Simulator/emulator for 8051 family microcontrollers.\n\n" \ - " -h display this help and exit\n" \ - " -version display version information and exit\n" - -struct options_t { - int pram_size; /* Maximum program memory size. */ - int iram_size; /* Maximum internal ram size. */ - int xram_size; /* Maximum external ram size. */ - char *filename; - int log; - uint16_t stop_address; /* Run program up to that adress and exit. */ -} options_t; - -void -parse_command_line_options(int argc, char *argv[]); - -const char * -get_package_description(void); - -#endif /* OPTIONS_H */ diff --git a/src/pgmwin.c b/src/pgmwin.c deleted file mode 100644 index 0e8961b..0000000 --- a/src/pgmwin.c +++ /dev/null @@ -1,299 +0,0 @@ -/* - * pgmwin.c - * - * Copyright (C) 1999 Jonathan St-André - * Copyright (C) 1999 Hugo Villeneuve - * - * This program 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 of the License, or - * (at your option) any later version. - * - * This program 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 this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#if HAVE_CONFIG_H -# include "config.h" -#endif - -#include - -#include "common.h" -#include "memory.h" -#include "cpu8051.h" -#include "pgmwin.h" -#include "hexfile.h" - -static GtkWidget *pgmlist; - -#define LIST_VIEW_NAME "Program" -#define DATA_ROWS 100 - -enum -{ - COL_BREAKPT = 0, - COL_ADDR, - COL_B0, - COL_B1, - COL_B2, - COL_INST, - COL_ARGS, - COL_COLOR, - N_COLUMNS, -}; - -static char *col_names[N_COLUMNS] = { - "BPT", - "Address", - "B0", - "B1", - "B2", - "Mnemonic", - "Arguments", - "COLOR", /* Not displayed, used to set foreground color of cell. */ -}; - -/* Creating a model */ -static GtkListStore * -pgmwin_init_store(void) -{ - GtkTreeIter iter; - int row; - int col; - GtkListStore *store; - GType col_types[N_COLUMNS]; - - /* No need for static array, all our columns are of the same type. */ - for (col = 0; col < N_COLUMNS; col++) - col_types[col] = G_TYPE_STRING; - - store = gtk_list_store_newv(N_COLUMNS, col_types); - - /* Add rows. */ - for (row = 0; row < DATA_ROWS; row++) { - gtk_list_store_append(store, &iter); - - /* Color first row in red (current instruction). */ - if (row == 0) - gtk_list_store_set(store, &iter, COL_COLOR, "red", -1); - else - gtk_list_store_set(store, &iter, COL_COLOR, "black", -1); - } - - return store; -} - -static void -pgmwin_init_columns(void) -{ - int k; - GtkCellRenderer *renderer; - - /* Create renderer */ - renderer = gtk_cell_renderer_text_new(); - - /* Add columns, except for last one (COL_COLOR). */ - for (k = 0; k < COL_COLOR; k++) { - GtkTreeViewColumn *col; - - /* Create tree view column */ - col = gtk_tree_view_column_new(); - gtk_tree_view_column_set_title(col, col_names[k]); - gtk_tree_view_column_set_sizing(col, - GTK_TREE_VIEW_COLUMN_AUTOSIZE); - gtk_tree_view_append_column(GTK_TREE_VIEW(pgmlist), col); - - /* Pack cell renderer into column */ - gtk_tree_view_column_pack_start(col, renderer, TRUE); - - /* Establish connection between cell renderer and data store. */ - gtk_tree_view_column_set_attributes(col, renderer, "text", k, - "foreground", COL_COLOR, - NULL); - } -} - -/* Mouse button pressed in the window. */ -static gint -pgmwin_sel_changed_event(GtkWidget *widget, GdkEvent *event, gpointer data) -{ - GtkTreeSelection *selection; - GtkTreeModel *model; - GtkTreeIter iter; - - log_debug("pgmwin_sel_changed_event()"); - - /* This will only work in single or browse selection mode! */ - selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(pgmlist)); - - if (gtk_tree_selection_get_selected(selection, &model, &iter)) { - char *str_addr; - int val; - - gtk_tree_model_get(model, &iter, COL_ADDR, &str_addr, -1); - - /* Convert hex address in ASCII to integer. */ - val = asciihex2int(str_addr); - - log_debug(" row address is: $%04X", val); - - ToggleBreakpoint(val); - pgmwin_refresh(); - - g_free(str_addr); - } else { - log_debug(" no row selected"); - } - - return FALSE; -} - -GtkWidget * -pgmwin_init(void) -{ - GtkWidget *frame; - GtkWidget *scrollwin; - GtkListStore *store; - GtkTreeSelection *selection; - - frame = gtk_frame_new(LIST_VIEW_NAME); - - scrollwin = gtk_scrolled_window_new(NULL, NULL); - gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrollwin), - GTK_SHADOW_ETCHED_OUT); - - /* Automatically add scrollbars when necessary. */ - gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrollwin), - GTK_POLICY_AUTOMATIC, - GTK_POLICY_AUTOMATIC); - - gtk_container_add(GTK_CONTAINER(frame), scrollwin); - - /* Creating a model */ - store = pgmwin_init_store(); - - /* Creating the view component */ - pgmlist = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store)); - gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(pgmlist), TRUE); - gtk_container_add(GTK_CONTAINER(scrollwin), pgmlist); - - selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(pgmlist)); - - /* Only one row can be selected at a time. */ - gtk_tree_selection_set_mode(selection, GTK_SELECTION_BROWSE); - - g_signal_connect(selection, "changed", - G_CALLBACK(pgmwin_sel_changed_event), NULL); - - pgmwin_init_columns(); - - /* - * The tree view has acquired its own reference to the model, so we can - * drop ours. That way the model will be freed automatically when the - * tree view is destroyed. - */ - g_object_unref(store); - - return frame; -} - -/* Show disassembled program. */ -void -pgmwin_refresh(void) -{ - int row; - GtkListStore *store; - unsigned int Address; - - Address = cpu8051.pc; - - store = GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(pgmlist))); - - for (row = 0; row < DATA_ROWS; row++) { - int valid; - GtkTreeIter iter; - char str[128]; - int k; - int col_id; - int InstSize; - unsigned char OpCode; - - if (row == 0) { - /* Get first row in list store */ - valid = gtk_tree_model_get_iter_first( - GTK_TREE_MODEL(store), &iter); - } else { - /* Get next row in list store */ - valid = gtk_tree_model_iter_next( - GTK_TREE_MODEL(store), &iter); - } - - if (!valid) { - printf("Invalid iter...\n"); - return; - } - - if (Address > 0xFFFF) { - /* - * Not the most elegant solution, but it works to not - * display instructions past last address, 0xFFFF. - */ - gtk_list_store_set(store, &iter, - COL_BREAKPT, NULL, - COL_ADDR, NULL, - COL_B0, NULL, - COL_B1, NULL, - COL_B2, NULL, - COL_INST, NULL, - COL_ARGS, NULL, - COL_COLOR, NULL, - -1); - } else { - /* Display breakpoints. */ - if (IsBreakpoint(Address)) - sprintf(str, "*"); - else - str[0] = '\0'; - - gtk_list_store_set(store, &iter, COL_BREAKPT, str, -1); - - /* Display base address. */ - int2asciihex(Address, str, 4); - - gtk_list_store_set(store, &iter, COL_ADDR, str, -1); - - OpCode = memory_read8(PGM_MEM_ID, Address); - InstSize = cpu8051_get_instruction_size(OpCode); - - /* Display instruction hex bytes. */ - for (k = 0, col_id = COL_B0; k < 3; k++, col_id++) { - if (k < InstSize) - int2asciihex(memory_read8(PGM_MEM_ID, - Address + k), - str, 2); - else - str[0] = '\0'; - - gtk_list_store_set(store, &iter, col_id, str, -1); - } - - /* Display instruction menmonic. */ - cpu8051_disasm_mnemonic(OpCode, str); - gtk_list_store_set(store, &iter, COL_INST, str, -1); - - /* Display instruction arguments (if applicable). */ - str[0] = '\0'; - cpu8051_disasm_args(Address, str); - gtk_list_store_set(store, &iter, COL_ARGS, str, -1); - - Address += InstSize; - } - } -} diff --git a/src/pgmwin.h b/src/pgmwin.h deleted file mode 100644 index 952d931..0000000 --- a/src/pgmwin.h +++ /dev/null @@ -1,36 +0,0 @@ -/* - * pgmwin.h - * - * Copyright (C) 1999 Jonathan St-André - * Copyright (C) 1999 Hugo Villeneuve - * - * This program 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 of the License, or - * (at your option) any later version. - * - * This program 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 this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#ifndef PGMWIN_H -#define PGMWIN_H 1 - -#include - -GtkWidget * -pgmwin_init(void); - -void -pgmwin_refresh(void); - -int -pgmwin_IsBreakpoint(unsigned int address); - -#endif /* PGMWIN_H */ diff --git a/src/psw.c b/src/psw.c deleted file mode 100644 index 09352ad..0000000 --- a/src/psw.c +++ /dev/null @@ -1,137 +0,0 @@ -/* - * psw.c - * - * Copyright (C) 2013 Hugo Villeneuve - * - * This program 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 of the License, or - * (at your option) any later version. - * - * This program 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 this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#include "common.h" -#include "reg8051.h" -#include "memory.h" - -/* Returns 0 or 1 */ -int -psw_read_bit(int bit) -{ - return (memory_read8(INT_MEM_ID, _PSW_) >> bit) & 0x01; -} - -void -psw_write_bit(int bit, int val) -{ - u_int8_t psw = memory_read8(INT_MEM_ID, _PSW_); - - if (val) - psw |= (1 << bit); /* Set */ - else - psw &= ~(1 << bit); /* Clear */ - - memory_write8(INT_MEM_ID, _PSW_, psw); /* Save updated value */ -} - -/* Returns 0 or 1 */ -int -psw_read_cy(void) -{ - return psw_read_bit(PSW_BIT_CY); -} - -void -psw_write_cy(int cy) -{ - psw_write_bit(PSW_BIT_CY, cy); -} - -void -psw_set_cy(void) -{ - psw_write_bit(PSW_BIT_CY, 1); -} - -void -psw_clr_cy(void) -{ - psw_write_bit(PSW_BIT_CY, 0); -} - -/* Returns 0 or 1 */ -int -psw_read_ac(void) -{ - return psw_read_bit(PSW_BIT_AC); -} - -void -psw_write_ac(int ac) -{ - psw_write_bit(PSW_BIT_AC, ac); -} - -void -psw_set_ac(void) -{ - psw_write_bit(PSW_BIT_AC, 1); -} - -void -psw_clr_ac(void) -{ - psw_write_bit(PSW_BIT_AC, 0); -} - -/* Returns 0 or 1 */ -int -psw_read_ov(void) -{ - return psw_read_bit(PSW_BIT_OV); -} - -void -psw_write_ov(int ov) -{ - psw_write_bit(PSW_BIT_OV, ov); -} - -void -psw_set_ov(void) -{ - psw_write_bit(PSW_BIT_OV, 1); -} - -void -psw_clr_ov(void) -{ - psw_write_bit(PSW_BIT_OV, 0); -} - -/* - * Compute parity of bits in accumulator: - * parity = 0: even number of ones in accumulator - * parity = 1: odd number of ones in accumulator - */ -void -psw_compute_parity_bit(void) -{ - int parity = 0; - uint8_t acc = memory_read8(INT_MEM_ID, _ACC_); - - while (acc) { - parity = !parity; - acc = acc & (acc - 1); - } - - psw_write_bit(PSW_BIT_P, parity); -} diff --git a/src/psw.h b/src/psw.h deleted file mode 100644 index f2c09ba..0000000 --- a/src/psw.h +++ /dev/null @@ -1,71 +0,0 @@ -/* - * psw.h - * - * Copyright (C) 2013 Hugo Villeneuve - * - * This program 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 of the License, or - * (at your option) any later version. - * - * This program 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 this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#ifndef PSW_H -#define PSW_H 1 - -#include - -int -psw_read_bit(int bit); - -void -psw_write_bit(int bit, int val); - -int -psw_read_cy(void); - -void -psw_write_cy(int cy); - -void -psw_clr_cy(void); - -void -psw_set_cy(void); - -int -psw_read_ac(void); - -void -psw_write_ac(int ac); - -void -psw_clr_ac(void); - -void -psw_set_ac(void); - -int -psw_read_ov(void); - -void -psw_write_ov(int ov); - -void -psw_clr_ov(void); - -void -psw_set_ov(void); - -void -psw_compute_parity_bit(void); - -#endif /* PSW_H */ diff --git a/src/pswwin.c b/src/pswwin.c deleted file mode 100644 index 94f733c..0000000 --- a/src/pswwin.c +++ /dev/null @@ -1,247 +0,0 @@ -/* - * pswwin.c - * - * Copyright (C) 1999 Jonathan St-André - * Copyright (C) 1999 Hugo Villeneuve - * - * This program 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 of the License, or - * (at your option) any later version. - * - * This program 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 this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#if HAVE_CONFIG_H -# include "config.h" -#endif - -#include - -#include "common.h" -#include "reg8051.h" -#include "cpu8051.h" -#include "memory.h" -#include "pswwin.h" -#include "memwin.h" -#include "pgmwin.h" -#include "psw.h" -#include "instructions_8051.h" -#include "hexfile.h" -#include "emugtk.h" - -static GtkWidget *pswlist; - -#define DATA_ROWS 1 -#define LIST_VIEW_NAME "PSW" -enum -{ - COL_CY = 0, - COL_AC, - COL_F0, - COL_RS1, - COL_RS0, - COL_OV, - COL_RESERVED, - COL_P, - N_COLUMNS, -}; - -static char *col_names[N_COLUMNS] = { - "CY", - "AC", - "F0", - "RS1", - "RS0", - "OV", - "-", - "P", -}; - -/* Creating a model */ -static GtkListStore * -pswwin_init_store(void) -{ - GtkTreeIter iter; - int row; - int col; - GtkListStore *store; - GType col_types[N_COLUMNS]; - - /* No need for static array, all our columns are of the same type. */ - for (col = 0; col < N_COLUMNS; col++) - col_types[col] = G_TYPE_STRING; - - store = gtk_list_store_newv(N_COLUMNS, col_types); - - /* Add rows. */ - for (row = 0; row < DATA_ROWS; row++) - gtk_list_store_append(store, &iter); - - return store; -} - -static void -pswwin_cell_edited(GtkCellRendererText *cell, gchar *path_string, - gchar *new_str, gpointer model) -{ - guint column; - gpointer columnptr; - GtkTreeIter iter; - u_int8_t old; - int new; - char str[10]; - int bit_index; - - if (!model) { - g_error("Unable to get model from cell renderer"); - } - - /* Column number is passed as renderer object data */ - columnptr = g_object_get_data(G_OBJECT(cell), "column"); - column = GPOINTER_TO_UINT(columnptr); - - log_info("column = $%02X", column); - - /* Get the iterator */ - gtk_tree_model_get_iter_from_string(model, &iter, path_string); - - bit_index = 7 - column; - - old = psw_read_bit(bit_index); - - log_info(" old value: %d", old); - - /* Convert new value (asciihex) to integer. */ - new = asciihex2int(new_str); - - if ((new != 0) && (new != 1)) { - log_info(" new value: out of range"); - new = old; /* Put back old value... */ - } else { - log_info(" new value: %d", new); - } - - /* Store new value in emulator memory. */ - psw_write_bit(bit_index, new); - - /* Convert to text. */ - int2asciihex(new, str, 1); - - /* Store new value in gtk model. */ - gtk_list_store_set(GTK_LIST_STORE(model), &iter, column, str, -1); - - /* - * Make sure to update all registers and memory. - * For example, BANKed registers depends on internal memory. - */ - emugtk_UpdateDisplay(); -}; - -static void -pswwin_init_columns(void) -{ - int k; - - /* Add column for each bit in PSW. */ - for (k = 0; k < N_COLUMNS; k++) { - GtkCellRenderer *renderer; - GtkTreeViewColumn *column; - - /* Create new renderer for value column (editable). */ - renderer = gtk_cell_renderer_text_new(); - - /* Allow edition, align to center. */ - g_object_set(renderer, "editable", TRUE, "xalign", 0.5, NULL); - - g_signal_connect(renderer, "edited", - G_CALLBACK(pswwin_cell_edited), - gtk_tree_view_get_model(GTK_TREE_VIEW(pswlist))); - - /* Add column index, used when editing the cell. */ - g_object_set_data(G_OBJECT(renderer), "column", - GUINT_TO_POINTER(k)); - - column = gtk_tree_view_column_new_with_attributes( - col_names[k], renderer, "text", k, NULL); - - /* Center column name */ - g_object_set(column, "alignment", 0.5, NULL); - - /* Hardcoded width... */ - gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_FIXED); - gtk_tree_view_column_set_fixed_width(column, 35); - - gtk_tree_view_append_column(GTK_TREE_VIEW(pswlist), column); - } -} - -GtkWidget * -pswwin_init(void) -{ - GtkWidget *frame; - GtkListStore *store; - - frame = gtk_frame_new(LIST_VIEW_NAME); - - /* Creating a model */ - store = pswwin_init_store(); - - /* Creating the view component */ - pswlist = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store)); - - gtk_tree_view_set_grid_lines(GTK_TREE_VIEW(pswlist), GTK_TREE_VIEW_GRID_LINES_BOTH); - - gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(pswlist), TRUE); - gtk_container_add(GTK_CONTAINER(frame), pswlist); - - pswwin_init_columns(); - - /* - * The tree view has acquired its own reference to the model, so we can - * drop ours. That way the model will be freed automatically when the - * tree view is destroyed. - */ - g_object_unref(store); - - return frame; -} - -/* Show registers. */ -void -pswwin_refresh(void) -{ - GtkListStore *store; - int valid; - GtkTreeIter iter; - int k; - - store = GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(pswlist))); - - /* Get first row in list store */ - valid = gtk_tree_model_get_iter_first( - GTK_TREE_MODEL(store), &iter); - - if (!valid) { - printf("Invalid iter...\n"); - return; - } - - /* Display bit values. */ - for (k = 0; k < N_COLUMNS; k++) { - char str[4]; - int bit_index; - - bit_index = 7 - k; - - int2asciihex(psw_read_bit(bit_index), str, 1); - gtk_list_store_set(store, &iter, k, str, -1); - } -} diff --git a/src/pswwin.h b/src/pswwin.h deleted file mode 100644 index 84d34dd..0000000 --- a/src/pswwin.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * pswwin.h - * - * Copyright (C) 1999 Jonathan St-André - * Copyright (C) 1999 Hugo Villeneuve - * - * This program 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 of the License, or - * (at your option) any later version. - * - * This program 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 this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#ifndef PSWWIN_H -#define PSWWIN_H 1 - -#include - -GtkWidget * -pswwin_init(void); - -void -pswwin_refresh(void); - -#endif /* PSWWIN_H */ diff --git a/src/reg8051.h b/src/reg8051.h deleted file mode 100644 index b484246..0000000 --- a/src/reg8051.h +++ /dev/null @@ -1,75 +0,0 @@ -/* - * reg8051.h - * - * Copyright (C) 1999 Jonathan St-André - * Copyright (C) 1999 Hugo Villeneuve - * - * This program 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 of the License, or - * (at your option) any later version. - * - * This program 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 this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#ifndef REG8051_H -#define REG8051_H 1 - -/* SFR Registers ( $80 - $FF ) */ -#define _ACC_ 0xE0 -#define _B_ 0xF0 -#define _PSW_ 0xD0 -#define _SP_ 0x81 -#define _DPTRLOW_ _DPL_ -#define _DPTRHIGH_ _DPH_ -#define _DPL_ 0x82 -#define _DPH_ 0x83 -#define _P0_ 0x80 -#define _P1_ 0x90 -#define _P2_ 0xA0 -#define _P3_ 0xB0 -#define _IP_ 0xB8 -#define _IE_ 0xA8 -#define _TMOD_ 0x89 -#define _TCON_ 0x88 -#define _TH0_ 0x8C -#define _TL0_ 0x8A -#define _TH1_ 0x8D -#define _TL1_ 0x8B -#define _SCON_ 0x98 -#define _SBUF_ 0x99 -#define _PCON_ 0x87 -#define _T2CON_ 0xC8 - -#define _R0_ 0x00 -#define _R1_ 0x01 -#define _R2_ 0x02 -#define _R3_ 0x03 -#define _R4_ 0x04 -#define _R5_ 0x05 -#define _R6_ 0x06 -#define _R7_ 0x07 - -#define _BANK0_ 0x00 -#define _BANK1_ 0x08 -#define _BANK2_ 0x10 -#define _BANK3_ 0x18 - -#define PSW_BIT_CY 7 -#define PSW_BIT_AC 6 -#define PSW_BIT_OV 2 -#define PSW_BIT_P 0 - -#define PSW_FLAG_CY (1 << PSW_BIT_CY) -#define PSW_FLAG_AC (1 << PSW_BIT_AC) -#define PSW_FLAG_OV (1 << PSW_BIT_OV) -#define PSW_FLAG_P (1 << PSW_BIT_P) - -#endif /* REG8051_H */ diff --git a/src/regwin.c b/src/regwin.c deleted file mode 100644 index 8c4cd4d..0000000 --- a/src/regwin.c +++ /dev/null @@ -1,256 +0,0 @@ -/* - * regwin.c - * - * Copyright (C) 1999 Jonathan St-André - * Copyright (C) 1999 Hugo Villeneuve - * - * This program 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 of the License, or - * (at your option) any later version. - * - * This program 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 this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#if HAVE_CONFIG_H -# include "config.h" -#endif - -#include - -#include "common.h" -#include "reg8051.h" -#include "cpu8051.h" -#include "sfr.h" -#include "memory.h" -#include "regwin.h" -#include "memwin.h" -#include "pgmwin.h" -#include "instructions_8051.h" -#include "hexfile.h" -#include "emugtk.h" - -static GtkWidget *reglist; - -#define LIST_VIEW_NAME "Registers" -#define DATA_ROWS SFR_REGS - -enum -{ - COL_NAME = 0, - COL_VAL, - N_COLUMNS, -}; - -/* Creating a model */ -static GtkListStore * -regwin_init_store(void) -{ - GtkTreeIter iter; - int row; - int col; - GtkListStore *store; - GType col_types[N_COLUMNS]; - - /* No need for static array, all our columns are of the same type. */ - for (col = 0; col < N_COLUMNS; col++) - col_types[col] = G_TYPE_STRING; - - store = gtk_list_store_newv(N_COLUMNS, col_types); - - /* Add rows. */ - for (row = 0; row < DATA_ROWS; row++) - gtk_list_store_append(store, &iter); - - return store; -} - -static void -regwin_cell_edited(GtkCellRendererText *cell, gchar *path_string, - gchar *new_str, gpointer model) -{ - GtkTreeIter iter; - int old; - int new; - char *str; - struct regwin_infos_t *regwin_infos; - - if (!model) { - g_error("Unable to get model from cell renderer"); - } - - /* Get the iterator */ - gtk_tree_model_get_iter_from_string(model, &iter, path_string); - - /* Get register name. */ - gtk_tree_model_get(model, &iter, COL_NAME, &str, -1); - - log_info("Register: %s", str); - regwin_infos = sfr_get_infos(str); - - /* Read current (old) value. */ - gtk_tree_model_get(model, &iter, COL_VAL, &str, -1); - - old = asciihex2int(str); - - if (regwin_infos->w == 2) - log_info(" old value: $%02X", old); - else if (regwin_infos->w == 4) - log_info(" old value: $%04X", old); - - new = asciihex2int(new_str); - - if (regwin_infos->w == 2) { - if ((new < 0) || (new > 0xFF)) { - log_info(" new value: out of range"); - new = old; /* Put back old value... */ - } else { - log_info(" new value: $%02X", new); - } - } else if (regwin_infos->w == 4) { - if ((new < 0) || (new > 0xFFFF)) { - log_info(" new value: out of range"); - new = old; /* Put back old value... */ - } else { - log_info(" new value: $%04X", new); - } - } - - /* Store new value in emulator register. */ - regwin_write(regwin_infos, new); - - /* Store new value in gtk model. */ - int2asciihex(new, str, regwin_infos->w); - gtk_list_store_set(GTK_LIST_STORE(model), &iter, COL_VAL, str, -1); - - /* - * Make sure to update all windows. - * For example, R0-R7 values depends on internal memory values. - */ - emugtk_UpdateDisplay(); -}; - -static void -regwin_init_columns(void) -{ - GtkCellRenderer *renderer; - GtkTreeViewColumn *column; - - /* Columns and cell renderers */ - renderer = gtk_cell_renderer_text_new(); - - /* Add Register column */ - column = gtk_tree_view_column_new_with_attributes( - "Name", renderer, "text", COL_NAME, NULL); - gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_AUTOSIZE); - gtk_tree_view_append_column(GTK_TREE_VIEW(reglist), column); - - /* Add Value column */ - - /* Create new renderer for value column (editable). */ - renderer = gtk_cell_renderer_text_new(); - - /* Allow edition, align to right side. */ - g_object_set(renderer, "editable", TRUE, "xalign", 1.0, NULL); - - g_signal_connect(renderer, "edited", - G_CALLBACK(regwin_cell_edited), - gtk_tree_view_get_model(GTK_TREE_VIEW(reglist))); - - column = gtk_tree_view_column_new_with_attributes( - "Value", renderer, "text", COL_VAL, NULL); - gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_AUTOSIZE); - gtk_tree_view_append_column(GTK_TREE_VIEW(reglist), column); -} - -GtkWidget * -regwin_init(void) -{ - GtkWidget *frame; - GtkWidget *scrollwin; - GtkListStore *store; - - frame = gtk_frame_new(LIST_VIEW_NAME); - - scrollwin = gtk_scrolled_window_new(NULL, NULL); - gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrollwin), - GTK_SHADOW_ETCHED_OUT); - - /* Automatically add scrollbars when necessary. */ - gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrollwin), - GTK_POLICY_AUTOMATIC, - GTK_POLICY_AUTOMATIC); - - gtk_container_add(GTK_CONTAINER(frame), scrollwin); - - /* Creating a model */ - store = regwin_init_store(); - - /* Creating the view component */ - reglist = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store)); - gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(reglist), TRUE); - gtk_container_add(GTK_CONTAINER(scrollwin), reglist); - - regwin_init_columns(); - - /* - * The tree view has acquired its own reference to the model, so we can - * drop ours. That way the model will be freed automatically when the - * tree view is destroyed. - */ - g_object_unref(store); - - return frame; -} - -/* Show registers. */ -void -regwin_refresh(void) -{ - int row; - GtkListStore *store; - - store = GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(reglist))); - - for (row = 0; row < DATA_ROWS; row++) { - int valid; - GtkTreeIter iter; - int val; - char str[8]; - struct regwin_infos_t *regwin_infos; - - if (row == 0) { - /* Get first row in list store */ - valid = gtk_tree_model_get_iter_first( - GTK_TREE_MODEL(store), &iter); - } else { - /* Get next row in list store */ - valid = gtk_tree_model_iter_next( - GTK_TREE_MODEL(store), &iter); - } - - if (!valid) { - printf("Invalid iter...\n"); - return; - } - - regwin_infos = sfr_get_infos_from_row(row); - - val = regwin_read(row); - - /* Convert to specified number of hex digits. */ - int2asciihex(val, str, regwin_infos->w); - - gtk_list_store_set(store, &iter, - COL_NAME, regwin_infos->name, - COL_VAL, str, - -1); - } -} diff --git a/src/regwin.h b/src/regwin.h deleted file mode 100644 index a526f6f..0000000 --- a/src/regwin.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * regwin.h - * - * Copyright (C) 1999 Jonathan St-André - * Copyright (C) 1999 Hugo Villeneuve - * - * This program 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 of the License, or - * (at your option) any later version. - * - * This program 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 this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#ifndef REGWIN_H -#define REGWIN_H 1 - -#include - -GtkWidget * -regwin_init(void); - -void -regwin_refresh(void); - -#endif /* REGWIN_H */ diff --git a/src/sfr.c b/src/sfr.c deleted file mode 100644 index 1bbeb8e..0000000 --- a/src/sfr.c +++ /dev/null @@ -1,345 +0,0 @@ -/* - * sfr.c - * - * Copyright (C) 2013 Hugo Villeneuve - * - * This program 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 of the License, or - * (at your option) any later version. - * - * This program 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 this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#if HAVE_CONFIG_H -# include "config.h" -#endif - -#include - -#include "common.h" -#include "reg8051.h" -#include "cpu8051.h" -#include "sfr.h" -#include "memory.h" -#include "instructions_8051.h" - -#define HEX_DIGITS_2 2 -#define HEX_DIGITS_4 4 - -/* Specific read/write functions for special registers. */ - -static unsigned int -regwin_read_pc(int dummy) -{ - return cpu8051.pc; -} - -static void -regwin_write_pc(int param, int val) -{ - cpu8051.pc = (u_int16_t) val; -} - -static unsigned int -regwin_read_timer(int timer_low_addr) -{ - return (memory_sfr_read8(timer_low_addr + 2) << 8) | - memory_sfr_read8(timer_low_addr); -} - -static void -regwin_write_timer(int timer_low_addr, int val) -{ - memory_sfr_write8(timer_low_addr + 2, (u_int8_t) ((val & 0x0000FFFF) >> 8)); - memory_sfr_write8(timer_low_addr, (u_int8_t) val); -} - -static u_int8_t -regwin_read_bank_offset(void) -{ - return memory_sfr_read8(_PSW_) & 0x18; -} - -static unsigned int -regwin_read_bank(int dummy) -{ - return regwin_read_bank_offset() >> 3; -} - -static void -regwin_write_bank(int param, int bank_number) -{ - u_int8_t psw = memory_sfr_read8(_PSW_); - - if ((bank_number < 0) || (bank_number > 3)) { - log_info("Error: invalid bank number: %d", bank_number); - bank_number = 0; - } - - memory_sfr_write8(_PSW_, (psw & ~0x18) | (bank_number << 3)); -} - -/* Indirect read of R0 - R7 in current bank from internal memory. */ -static unsigned int -regwin_read_rx(int offset) -{ - return memory_read8(INT_MEM_ID, regwin_read_bank_offset() + offset); -} - -/* Indirect write to R0 - R7 in current bank to internal memory. */ -static void -regwin_write_rx(int offset, int val) -{ - memory_write8(INT_MEM_ID, regwin_read_bank_offset() + offset, (u_int8_t) val); -} - -/* This array defines how to read value for each register. */ -static struct regwin_infos_t regwin_infos[SFR_REGS] = { - { - "PC", - HEX_DIGITS_4, - regwin_read_pc, regwin_write_pc, - 0, /* Dummy */ - }, - { - "SP", - HEX_DIGITS_2, - NULL, NULL, - _SP_, - }, - { - "PSW", - HEX_DIGITS_2, - NULL, NULL, - _PSW_, - }, - { - "A", - HEX_DIGITS_2, - NULL, NULL, - _ACC_, - }, - { - "B", - HEX_DIGITS_2, - NULL, NULL, - _B_, - }, - { - "DPTR", - HEX_DIGITS_4, - NULL, NULL, - _DPL_, - }, - { - "P0", - HEX_DIGITS_2, - NULL, NULL, - _P0_, - }, - { - "P1", - HEX_DIGITS_2, - NULL, NULL, - _P1_, - }, - { - "P2", - HEX_DIGITS_2, - NULL, NULL, - _P2_, - }, - { - "P3", - HEX_DIGITS_2, - NULL, NULL, - _P3_, - }, - { - "TCON", - HEX_DIGITS_2, - NULL, NULL, - _TCON_, - }, - { - "TMOD", - HEX_DIGITS_2, - NULL, NULL, - _TMOD_, - }, - { - "TIMER0", - HEX_DIGITS_4, - regwin_read_timer, regwin_write_timer, - _TL0_, - }, - { - "TIMER1", - HEX_DIGITS_4, - regwin_read_timer, regwin_write_timer, - _TL1_, - }, - { - "SCON", - HEX_DIGITS_2, - NULL, NULL, - _SCON_, - }, - { - "IE", - HEX_DIGITS_2, - NULL, NULL, - _IE_, - }, - { - "IP", - HEX_DIGITS_2, - NULL, NULL, - _IP_, - }, - { - "BANK", - HEX_DIGITS_2, - regwin_read_bank, regwin_write_bank, - 0, /* Dummy */ - }, - /* R0-R7 Registers in current Bank */ - { - "R0", - HEX_DIGITS_2, - regwin_read_rx, regwin_write_rx, - _R0_, - }, - { - "R1", - HEX_DIGITS_2, - regwin_read_rx, regwin_write_rx, - _R1_, - }, - { - "R2", - HEX_DIGITS_2, - regwin_read_rx, regwin_write_rx, - _R2_, - }, - { - "R3", - HEX_DIGITS_2, - regwin_read_rx, regwin_write_rx, - _R3_, - }, - { - "R4", - HEX_DIGITS_2, - regwin_read_rx, regwin_write_rx, - _R4_, - }, - { - "R5", - HEX_DIGITS_2, - regwin_read_rx, regwin_write_rx, - _R5_, - }, - { - "R6", - HEX_DIGITS_2, - regwin_read_rx, regwin_write_rx, - _R6_, - }, - { - "R7", - HEX_DIGITS_2, - regwin_read_rx, regwin_write_rx, - _R7_, - }, -}; - -/* Generic read/write functions */ -static unsigned int -regwin_read_generic(int addr, int width) -{ - if (width == 2) - return memory_sfr_read8(addr); - else if (width == 4) { - /* Address is low address. */ - return (memory_sfr_read8(addr + 1) << 8) | - memory_sfr_read8(addr); - } else - return 0xFFFFFFFF; -} - -static void -regwin_write_generic(int addr, int val, int width) -{ - if (width == 2) - memory_sfr_write8(addr, (u_int8_t) val); - else if (width == 4) { - /* Address is low address. */ - memory_sfr_write8(addr + 1, (u_int8_t) ((val & 0x0000FFFF) >> 8)); - memory_sfr_write8(addr, (u_int8_t) val); - } -}; - -int -regwin_read(int row) -{ - int val; - - if (regwin_infos[row].read_func == NULL) { - /* - * Read register value using generic 8 or 16 bits read - * function, depending on width. - */ - val = regwin_read_generic(regwin_infos[row].param, - regwin_infos[row].w); - } else { - /* Read register value using custom function pointer. */ - val = regwin_infos[row].read_func( - regwin_infos[row].param); - } - - return val; -} - -void -regwin_write(struct regwin_infos_t *p, int new) -{ - if (p->write_func == NULL) { - /* - * Write register value using generic 8 or 16 bits write - * function, depending on width. - */ - regwin_write_generic(p->param, new, p->w); - } else { - /* Write register value using custom function pointer. */ - p->write_func(p->param, new); - } -} - -struct regwin_infos_t * -sfr_get_infos(const char *regname) -{ - int row; - - for (row = 0; row < SFR_REGS; row++) { - if (strcmp(regwin_infos[row].name, regname) == 0) - return ®win_infos[row]; - } - - return NULL; /* Programming error. */ -} - -struct regwin_infos_t * -sfr_get_infos_from_row(int row) -{ - return ®win_infos[row]; -} - diff --git a/src/sfr.h b/src/sfr.h deleted file mode 100644 index fe552dd..0000000 --- a/src/sfr.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - * sfr.h - * - * Copyright (C) 2013 Hugo Villeneuve - * - * This program 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 of the License, or - * (at your option) any later version. - * - * This program 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 this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#ifndef SFR_H -#define SFR_H 1 - -#define SFR_REGS 26 - -struct regwin_infos_t { - char *name; /* Register name */ - int w; /* Number of hex digits to display */ - unsigned int (*read_func)(int addr); /* Function to read value */ - void (*write_func)(int param, int val); /* Function to write value */ - int param; /* Optional parameter to pass to read function. */ -}; - -int -regwin_read(int row); - -void -regwin_write(struct regwin_infos_t *p, int new); - -struct regwin_infos_t * -sfr_get_infos(const char *regname); - -struct regwin_infos_t * -sfr_get_infos_from_row(int row); - -#endif /* SFR_H */ diff --git a/src/timers.c b/src/timers.c deleted file mode 100644 index 68a92bc..0000000 --- a/src/timers.c +++ /dev/null @@ -1,144 +0,0 @@ -/* - * timers.c - * - * Copyright (C) 1999 Jonathan St-André - * Copyright (C) 1999 Hugo Villeneuve - * - * This program 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 of the License, or - * (at your option) any later version. - * - * This program 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 this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#include -#include -#include -#include "config.h" - -#include "common.h" -#include "reg8051.h" -#include "cpu8051.h" -#include "memory.h" -#include "psw.h" -#include "options.h" -#include "instructions_8051.h" - -extern struct options_t options; - -static void -timer_increment_check_overflow(uint8_t counter_address, uint8_t tf_mask) -{ - unsigned int tmp; - - tmp = cpu8051_ReadD(counter_address); - tmp++; - tmp &= 0xFF; - if (tmp == 0) { - /* If overflow set TFx */ - cpu8051_WriteD(_TCON_, cpu8051_ReadD(_TCON_) | tf_mask); - } - - cpu8051_WriteD(counter_address, tmp); /* Save new value. */ -} - -static void -timer_with_prescaler(uint8_t tl, uint8_t th, uint8_t tf_mask, int prescaler_width) -{ - unsigned int prescaler; - - prescaler = cpu8051_ReadD(tl); - prescaler++; - - prescaler &= (1 << prescaler_width) - 1; /* Keep only required bits */ - cpu8051_WriteD(tl, prescaler); - - if (prescaler == 0) - timer_increment_check_overflow(th, tf_mask); -} - -static void -process_timer(uint8_t tl, uint8_t th, uint8_t tf_mask, uint8_t TR, uint8_t mode, - uint8_t GATE, uint32_t TimerCounter) -{ - unsigned int tmp; - - switch (mode) { - case 0: - /* Mode 0, 8-bit timer "TH" with "TL" as 5-bit prescaler. */ - timer_with_prescaler(tl, th, tf_mask, 5); - break; - case 1: - /* Mode 1, 16-bits counter */ - timer_with_prescaler(tl, th, tf_mask, 8); - break; - case 2: - /* Mode 2, 8-bits counter with Auto-Reload */ - tmp = cpu8051_ReadD(tl); - tmp++; - tmp &= 0xFF; - if (tmp == 0) { - /* If overflow -> reload and set TF0 */ - cpu8051_WriteD(_TCON_, cpu8051_ReadD(_TCON_) | tf_mask); - cpu8051_WriteD(tl, cpu8051_ReadD(th)); - } else - cpu8051_WriteD(tl, tmp); - break; - case 3: - /* - * Mode 3: - * inactive mode for timer 1 - * 2 independents 8-bits timers for timer 0. - */ - - if (tl == _TL1_) - break; - - if (TR && !GATE && !TimerCounter) - timer_increment_check_overflow(tl, tf_mask); - - /* TH0 uses TR1 et TF1. */ - TR = cpu8051_ReadD(_TCON_) & 0x40; - - if (TR) - timer_increment_check_overflow(th, 0x80); - - break; - } -} - -/* Run timers */ -void -timers_check(void) -{ - unsigned int TR; - unsigned int MODE; - unsigned int GATE; - unsigned int TimerCounter; - - /* Timer 0 */ - TR = cpu8051_ReadD(_TCON_) & 0x10; - MODE = cpu8051_ReadD(_TMOD_) & 0x03; - GATE = cpu8051_ReadD(_TMOD_) & 0x08; - TimerCounter = cpu8051_ReadD(_TMOD_) & 0x04; - - if ((TR && !GATE && !TimerCounter) || (MODE == 3)) - process_timer(_TL0_, _TH0_, 0x20, TR, MODE, GATE, TimerCounter); - - /* Timer 1 */ - TR = cpu8051_ReadD(_TCON_) & 0x40; - MODE = (cpu8051_ReadD(_TMOD_) & 0x30) >> 4 ; - GATE = cpu8051_ReadD(_TMOD_) & 0x80; - TimerCounter = cpu8051_ReadD(_TMOD_) & 0x40; - - if (TR && !GATE && !TimerCounter) - process_timer(_TL1_, _TH1_, 0x80, TR, MODE, GATE, TimerCounter); -} diff --git a/src/timers.h b/src/timers.h deleted file mode 100644 index 932ace4..0000000 --- a/src/timers.h +++ /dev/null @@ -1,29 +0,0 @@ -/* - * timers.h - * - * Copyright (C) 2013 Hugo Villeneuve - * - * This program 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 of the License, or - * (at your option) any later version. - * - * This program 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 this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#ifndef TIMERS_H -#define TIMERS_H 1 - -#include - -int -timers_check(void); - -#endif /* TIMERS_H */ diff --git a/src/viewmenu.c b/src/viewmenu.c deleted file mode 100644 index 3377329..0000000 --- a/src/viewmenu.c +++ /dev/null @@ -1,208 +0,0 @@ -/* - * viewmenu.c - * - * Copyright (C) 1999 Jonathan St-André - * Copyright (C) 1999 Hugo Villeneuve - * - * This program 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 of the License, or - * (at your option) any later version. - * - * This program 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 this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#if HAVE_CONFIG_H -# include "config.h" -#endif - -#include - -#include "common.h" -#include "emugtk.h" /* For AddMenuSeparator() function. */ -#include "messagebox.h" -#include "viewmenu.h" -#include "app-config.h" - -extern struct app_config_t *cfg; - -void toggle_layout(GtkWidget *widget, gpointer data) -{ - int id; - - id = GPOINTER_TO_UINT(data); - - if (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(widget))) { - log_info(" Switching to layout %d", id); - cfg->layout = id; - emugtk_restart_gui(); - } -} - -void toggle_bits_per_row(GtkWidget *widget, gpointer data) -{ - int bits_per_row; - - bits_per_row = GPOINTER_TO_UINT(data); - - if (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(widget))) { - log_info(" Bits per row = %d", bits_per_row); - cfg->bits_per_row = bits_per_row; - emugtk_restart_gui(); - } -} - -void toggle_int_memory(GtkWidget *widget, gpointer data) -{ - if (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(widget))) { - log_info(" View internal memory"); - cfg->view_int_memory = 1; - } else { - cfg->view_int_memory = 0; - } - - emugtk_restart_gui(); -} - -void toggle_sfr_memory(GtkWidget *widget, gpointer data) -{ - if (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(widget))) { - log_info(" View SFR memory"); - cfg->view_sfr_memory = 1; - } else { - cfg->view_sfr_memory = 0; - } - - emugtk_restart_gui(); -} - -void toggle_ext_memory(GtkWidget *widget, gpointer data) -{ - if (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(widget))) { - log_info(" View external memory"); - cfg->view_ext_memory = 1; - } else { - cfg->view_ext_memory = 0; - } - - emugtk_restart_gui(); -} - -void -view_add_layout_submenu(GtkWidget *parent) -{ - GtkWidget *submenu; - GtkWidget *layout; - GtkWidget *layout1; - GtkWidget *layout2; - GSList *group = NULL; - - submenu = gtk_menu_new(); - - layout = gtk_menu_item_new_with_label("Layout"); - - layout1 = gtk_radio_menu_item_new_with_label(group, "Layout1"); - group = gtk_radio_menu_item_get_group(GTK_RADIO_MENU_ITEM(layout1)); - layout2 = gtk_radio_menu_item_new_with_label(group, "Layout2"); - - if (cfg->layout == UI_LAYOUT1) - gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(layout1), TRUE); - else - gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(layout2), TRUE); - - g_signal_connect(G_OBJECT(layout1), "activate", - G_CALLBACK(toggle_layout), (gpointer) UI_LAYOUT1); - g_signal_connect(G_OBJECT(layout2), "activate", - G_CALLBACK(toggle_layout), (gpointer) UI_LAYOUT2); - - gtk_menu_item_set_submenu(GTK_MENU_ITEM(layout), submenu); - gtk_menu_shell_append(GTK_MENU_SHELL(submenu), layout1); - gtk_menu_shell_append(GTK_MENU_SHELL(submenu), layout2); - gtk_menu_shell_append(GTK_MENU_SHELL(parent), layout); -} - -void -view_add_bits_per_row_submenu(GtkWidget *parent) -{ - GtkWidget *submenu; - GtkWidget *item; - GtkWidget *item1; - GtkWidget *item2; - GSList *group = NULL; - - submenu = gtk_menu_new(); - - item = gtk_menu_item_new_with_label("Bits per row"); - - item1 = gtk_radio_menu_item_new_with_label(group, "8"); - group = gtk_radio_menu_item_get_group(GTK_RADIO_MENU_ITEM(item1)); - item2 = gtk_radio_menu_item_new_with_label(group, "16"); - - if (cfg->bits_per_row == 8) - gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(item1), TRUE); - else - gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(item2), TRUE); - - g_signal_connect(G_OBJECT(item1), "activate", - G_CALLBACK(toggle_bits_per_row), (gpointer) 8); - g_signal_connect(G_OBJECT(item2), "activate", - G_CALLBACK(toggle_bits_per_row), (gpointer) 16); - - gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), submenu); - gtk_menu_shell_append(GTK_MENU_SHELL(submenu), item1); - gtk_menu_shell_append(GTK_MENU_SHELL(submenu), item2); - gtk_menu_shell_append(GTK_MENU_SHELL(parent), item); -} - -void -ViewAddMenu(GtkWidget *menu_bar) -{ - GtkWidget *item; - GtkWidget *menu; - GtkWidget *view; - - menu = gtk_menu_new(); - - view = gtk_menu_item_new_with_label("View"); - - item = gtk_check_menu_item_new_with_label("Internal Memory"); - gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); - gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(item), - cfg->view_int_memory); - g_signal_connect(G_OBJECT(item), "activate", - G_CALLBACK(toggle_int_memory), NULL); - - item = gtk_check_menu_item_new_with_label("SFR Memory"); - gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); - gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(item), - cfg->view_sfr_memory); - g_signal_connect(G_OBJECT(item), "activate", - G_CALLBACK(toggle_sfr_memory), NULL); - - item = gtk_check_menu_item_new_with_label("External Memory"); - gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); - gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(item), - cfg->view_ext_memory); - g_signal_connect(G_OBJECT(item), "activate", - G_CALLBACK(toggle_ext_memory), NULL); - - AddMenuSeparator(menu); - - /* Add layout submenu */ - view_add_layout_submenu(menu); - - AddMenuSeparator(menu); - - /* Add bits per row submenu */ - view_add_bits_per_row_submenu(menu); - - gtk_menu_item_set_submenu(GTK_MENU_ITEM(view), menu); - gtk_menu_shell_append(GTK_MENU_SHELL(menu_bar), view); -} diff --git a/src/viewmenu.h b/src/viewmenu.h deleted file mode 100644 index bf78564..0000000 --- a/src/viewmenu.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - * viewmenu.h - * - * Copyright (C) 1999 Jonathan St-André - * Copyright (C) 1999 Hugo Villeneuve - * - * This program 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 of the License, or - * (at your option) any later version. - * - * This program 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 this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#ifndef VIEWMENU_H -#define VIEWMENU_H 1 - -#include - -void -ViewAddMenu(GtkWidget *menu_bar); - -#endif /* VIEWMENU_H */ diff --git a/tests/opcodes.sh b/tests/opcodes.sh index f6ff764..3ae17fd 100755 --- a/tests/opcodes.sh +++ b/tests/opcodes.sh @@ -12,7 +12,7 @@ name=$(basename ${test_name} .sh) hexfile=${name}.hex echo "Testing ${name}.hex" > ${lf} -../src/emu8051-cli -d 2 --xram=${XRAM_SIZE} -s ${STOP_ADDRESS} ${hexfile} >> ${lf} +../src/cli/emu8051-cli -d 2 --xram=${XRAM_SIZE} -s ${STOP_ADDRESS} ${hexfile} >> ${lf} if test $? -ne 0 ; then return 1 fi