/build-aux/install-sh
/build-aux/missing
/build-aux/test-driver
+/build-aux/ar-lib
/config.cache
/config.log
/config.status
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 \
$(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
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)
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
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)
+++ /dev/null
-# 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
+++ /dev/null
-/*
- * Handle loading and saving of application configuration settings
- *
- * Copyright (C) 2013 Hugo Villeneuve <hugo@hugovil.com>
- *
- * 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 <stdint.h>
-#include <stdbool.h>
-#include <unistd.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-#if STDC_HEADERS
-# include <string.h>
-#elif HAVE_STRINGS_H
-# include <strings.h>
-#endif
-
-#include <glib.h>
-
-#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;
-}
+++ /dev/null
-/*
- * app_config.h
- *
- * Copyright (C) 1999 Hugo Villeneuve <hugo@hugovil.com>
- *
- * 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 */
--- /dev/null
+# 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
--- /dev/null
+/*
+ * emuconsole.c
+ *
+ * Copyright (C) 1999 Jonathan St-André
+ * Copyright (C) 1999 Hugo Villeneuve <hugo@hugovil.com>
+ *
+ * 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 <stdio.h>
+#include <string.h>
+#include <ctype.h> /* 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;
+}
--- /dev/null
+/*
+ * keyboard.c
+ *
+ * Copyright (C) 1999 Jonathan St-André
+ * Copyright (C) 1999 Hugo Villeneuve <hugo@hugovil.com>
+ *
+ * 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 <termios.h>
+#include <unistd.h>
+
+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);
+}
--- /dev/null
+/*
+ * keyboard.h
+ *
+ * Copyright (C) 1999 Jonathan St-André
+ * Copyright (C) 1999 Hugo Villeneuve <hugo@hugovil.com>
+ *
+ * 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_ */
+++ /dev/null
-/*
- * common.h
- *
- * Copyright (C) 1999 Jonathan St-André
- * Copyright (C) 1999 Hugo Villeneuve <hugo@hugovil.com>
- *
- * 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 <stdio.h>
-#include <stdlib.h>
-#include <errno.h>
-
-#if STDC_HEADERS
-# include <string.h>
-#elif HAVE_STRINGS_H
-# include <strings.h>
-#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 */
--- /dev/null
+# 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
--- /dev/null
+/*
+ * common.h
+ *
+ * Copyright (C) 1999 Jonathan St-André
+ * Copyright (C) 1999 Hugo Villeneuve <hugo@hugovil.com>
+ *
+ * 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 <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+
+#if STDC_HEADERS
+# include <string.h>
+#elif HAVE_STRINGS_H
+# include <strings.h>
+#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 */
--- /dev/null
+/*
+ * cpu8051.c
+ *
+ * Copyright (C) 1999 Jonathan St-André
+ * Copyright (C) 1999 Hugo Villeneuve <hugo@hugovil.com>
+ *
+ * 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 <stdio.h>
+#include <stdint.h>
+
+#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;
+}
--- /dev/null
+/*
+ * cpu8051.h
+ *
+ * Copyright (C) 1999 Jonathan St-André
+ * Copyright (C) 1999 Hugo Villeneuve <hugo@hugovil.com>
+ *
+ * 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 <stdint.h>
+
+/* 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 */
--- /dev/null
+/*
+ * Functions for loading an Intel HEX file.
+ *
+ * Copyright (C) 1999 Jonathan St-André
+ * Copyright (C) 1999 Hugo Villeneuve <hugo@hugovil.com>
+ *
+ * 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 <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#if STDC_HEADERS
+# include <string.h>
+#elif HAVE_STRINGS_H
+# include <strings.h>
+#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);
+ }
+}
--- /dev/null
+/*
+ * hexfile.h
+ *
+ * Copyright (C) 1999 Jonathan St-André
+ * Copyright (C) 1999 Hugo Villeneuve <hugo@hugovil.com>
+ *
+ * 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 */
--- /dev/null
+/*
+ * log.c -- debug functions for logging.
+ *
+ * Copyright (C) 2011 Hugo Villeneuve <hugo@hugovil.com>
+ *
+ * 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 <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+
+#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);
+}
--- /dev/null
+/*
+ * log.h
+ *
+ * Copyright (C) 2011 Hugo Villeneuve <hugo@hugovil.com>
+ *
+ * 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 <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <errno.h>
+#include <string.h>
+
+#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 */
--- /dev/null
+/*
+ * memory.c
+ *
+ * Copyright (C) 1999 Jonathan St-André
+ * Copyright (C) 1999 Hugo Villeneuve <hugo@hugovil.com>
+ *
+ * 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 <stdio.h>
+#include <string.h>
+
+#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 <base> 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");
+ }
+}
--- /dev/null
+/*
+ * memory.h
+ *
+ * Copyright (C) 1999 Jonathan St-André
+ * Copyright (C) 1999 Hugo Villeneuve <hugo@hugovil.com>
+ *
+ * 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 <sys/types.h>
+
+#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 */
--- /dev/null
+#!/usr/bin/perl
+#
+# Copyright (C) 1999 Jonathan St-André
+# Copyright (C) 1999 Hugo Villeneuve <hugo@hugovil.com>
+#
+# 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 <instructions_8051.h> : $!\n";
+open INST_IMP, ">instructions_8051.c" or die "Error creating <instructions_8051.c> : $!\n";
+open OPCODELST, "opcodes.lst" or die "Error opening <opcodes.lst> : $!\n";
+open DISASM_H, ">disasm.h" or die "Error creating <disasm.h> : $!\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 <hugo@hugovil.com>\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=<OPCODELST>;
+$ligne=<OPCODELST>;
+while($ligne=<OPCODELST>) {
+ 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;
--- /dev/null
+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
--- /dev/null
+/*
+ * options.c -- functions for processing command-line options and arguments
+ *
+ * Copyright (C) 2011 Hugo Villeneuve <hugo@hugovil.com>
+ *
+ * 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 <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <argp.h>
+
+#if STDC_HEADERS
+# include <string.h>
+#elif HAVE_STRINGS_H
+# include <strings.h>
+#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);
+}
--- /dev/null
+/*
+ * options.h
+ *
+ * Copyright (C) 1999 Hugo Villeneuve <hugo@hugovil.com>
+ *
+ * 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 */
--- /dev/null
+/*
+ * psw.c
+ *
+ * Copyright (C) 2013 Hugo Villeneuve <hugo@hugovil.com>
+ *
+ * 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);
+}
--- /dev/null
+/*
+ * psw.h
+ *
+ * Copyright (C) 2013 Hugo Villeneuve <hugo@hugovil.com>
+ *
+ * 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 <sys/types.h>
+
+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 */
--- /dev/null
+/*
+ * reg8051.h
+ *
+ * Copyright (C) 1999 Jonathan St-André
+ * Copyright (C) 1999 Hugo Villeneuve <hugo@hugovil.com>
+ *
+ * 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 */
--- /dev/null
+/*
+ * sfr.c
+ *
+ * Copyright (C) 2013 Hugo Villeneuve <hugo@hugovil.com>
+ *
+ * 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 <stdio.h>
+
+#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];
+}
+
--- /dev/null
+/*
+ * sfr.h
+ *
+ * Copyright (C) 2013 Hugo Villeneuve <hugo@hugovil.com>
+ *
+ * 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 */
--- /dev/null
+/*
+ * timers.c
+ *
+ * Copyright (C) 1999 Jonathan St-André
+ * Copyright (C) 1999 Hugo Villeneuve <hugo@hugovil.com>
+ *
+ * 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 <stdio.h>
+#include <stdbool.h>
+#include <stdint.h>
+#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);
+}
--- /dev/null
+/*
+ * timers.h
+ *
+ * Copyright (C) 2013 Hugo Villeneuve <hugo@hugovil.com>
+ *
+ * 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 <stdint.h>
+
+int
+timers_check(void);
+
+#endif /* TIMERS_H */
+++ /dev/null
-/*
- * cpu8051.c
- *
- * Copyright (C) 1999 Jonathan St-André
- * Copyright (C) 1999 Hugo Villeneuve <hugo@hugovil.com>
- *
- * 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 <stdio.h>
-#include <stdint.h>
-
-#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;
-}
+++ /dev/null
-/*
- * cpu8051.h
- *
- * Copyright (C) 1999 Jonathan St-André
- * Copyright (C) 1999 Hugo Villeneuve <hugo@hugovil.com>
- *
- * 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 <stdint.h>
-
-/* 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 */
+++ /dev/null
-/*
- * emuconsole.c
- *
- * Copyright (C) 1999 Jonathan St-André
- * Copyright (C) 1999 Hugo Villeneuve <hugo@hugovil.com>
- *
- * 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 <stdio.h>
-#include <string.h>
-#include <ctype.h> /* 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;
-}
+++ /dev/null
-/*
- * emugtk.c
- *
- * Copyright (C) 1999 Jonathan St-André
- * Copyright (C) 1999 Hugo Villeneuve <hugo@hugovil.com>
- *
- * 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 <stdio.h>
-#include "config.h"
-
-#include <stdint.h>
-#include <stdbool.h>
-
-#include <gtk/gtk.h>
-
-#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;
-}
+++ /dev/null
-/*
- * emugtk.h
- *
- * Copyright (C) 1999 Jonathan St-André
- * Copyright (C) 1999 Hugo Villeneuve <hugo@hugovil.com>
- *
- * 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 <gtk/gtk.h>
-
-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 */
+++ /dev/null
-/*
- * filemenu.c
- *
- * Copyright (C) 1999 Jonathan St-André
- * Copyright (C) 1999 Hugo Villeneuve <hugo@hugovil.com>
- *
- * 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 <unistd.h> /* UNIX standard function definitions */
-#include <pwd.h>
-#include <gtk/gtk.h>
-
-#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);
-}
+++ /dev/null
-/*
- * filemenu.h
- *
- * Copyright (C) 1999 Jonathan St-André
- * Copyright (C) 1999 Hugo Villeneuve <hugo@hugovil.com>
- *
- * 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 <gtk/gtk.h>
-
-void
-FileOpenEvent(GtkObject *object, gpointer data);
-
-void
-FileResetEvent(GtkObject *object, gpointer data);
-
-void
-FileAddMenu(GtkWidget *menu_bar);
-
-#endif /* FILEMENU_H */
--- /dev/null
+# 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
--- /dev/null
+/*
+ * Handle loading and saving of application configuration settings
+ *
+ * Copyright (C) 2013 Hugo Villeneuve <hugo@hugovil.com>
+ *
+ * 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 <stdint.h>
+#include <stdbool.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#if STDC_HEADERS
+# include <string.h>
+#elif HAVE_STRINGS_H
+# include <strings.h>
+#endif
+
+#include <glib.h>
+
+#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;
+}
--- /dev/null
+/*
+ * app_config.h
+ *
+ * Copyright (C) 1999 Hugo Villeneuve <hugo@hugovil.com>
+ *
+ * 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 */
--- /dev/null
+/*
+ * emugtk.c
+ *
+ * Copyright (C) 1999 Jonathan St-André
+ * Copyright (C) 1999 Hugo Villeneuve <hugo@hugovil.com>
+ *
+ * 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 <stdio.h>
+#include "config.h"
+
+#include <stdint.h>
+#include <stdbool.h>
+
+#include <gtk/gtk.h>
+
+#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;
+}
--- /dev/null
+/*
+ * emugtk.h
+ *
+ * Copyright (C) 1999 Jonathan St-André
+ * Copyright (C) 1999 Hugo Villeneuve <hugo@hugovil.com>
+ *
+ * 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 <gtk/gtk.h>
+
+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 */
--- /dev/null
+/*
+ * filemenu.c
+ *
+ * Copyright (C) 1999 Jonathan St-André
+ * Copyright (C) 1999 Hugo Villeneuve <hugo@hugovil.com>
+ *
+ * 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 <unistd.h> /* UNIX standard function definitions */
+#include <pwd.h>
+#include <gtk/gtk.h>
+
+#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);
+}
--- /dev/null
+/*
+ * filemenu.h
+ *
+ * Copyright (C) 1999 Jonathan St-André
+ * Copyright (C) 1999 Hugo Villeneuve <hugo@hugovil.com>
+ *
+ * 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 <gtk/gtk.h>
+
+void
+FileOpenEvent(GtkObject *object, gpointer data);
+
+void
+FileResetEvent(GtkObject *object, gpointer data);
+
+void
+FileAddMenu(GtkWidget *menu_bar);
+
+#endif /* FILEMENU_H */
--- /dev/null
+/*
+ * helpmenu.c
+ *
+ * Copyright (C) 1999 Jonathan St-André
+ * Copyright (C) 1999 Hugo Villeneuve <hugo@hugovil.com>
+ *
+ * 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 <stdbool.h>
+
+#if STDC_HEADERS
+# include <string.h>
+#elif HAVE_STRINGS_H
+# include <strings.h>
+#endif
+
+#include <gtk/gtk.h>
+
+#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 <hugo@hugovil.com>",
+ "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"
+ " <http://www.gnu.org/licenses/>";
+
+ 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);
+}
--- /dev/null
+/*
+ * helpmenu.h
+ *
+ * Copyright (C) 1999 Jonathan St-André
+ * Copyright (C) 1999 Hugo Villeneuve <hugo@hugovil.com>
+ *
+ * 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 <gtk/gtk.h>
+
+void
+HelpAddMenu(GtkWidget *menu_bar);
+
+#endif /* HELPMENU_H */
--- /dev/null
+/*
+ * memwin.c
+ *
+ * Copyright (C) 1999 Jonathan St-André
+ * Copyright (C) 1999 Hugo Villeneuve <hugo@hugovil.com>
+ *
+ * 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 <stdio.h>
+#include <ctype.h> /* 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;
+ }
+}
--- /dev/null
+/*
+ * memwin.h
+ *
+ * Copyright (C) 1999 Jonathan St-André
+ * Copyright (C) 1999 Hugo Villeneuve <hugo@hugovil.com>
+ *
+ * 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 <gtk/gtk.h>
+
+GtkWidget *
+memwin_init(char *title, int memory_id);
+
+void
+memwin_refresh(int memory_id);
+
+#endif /* MEMWIN_H */
--- /dev/null
+/*
+ * messagebox.c
+ *
+ * Copyright (C) 1999 Jonathan St-André
+ * Copyright (C) 1999 Hugo Villeneuve <hugo@hugovil.com>
+ *
+ * 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 <gtk/gtk.h>
+
+#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);
+}
--- /dev/null
+/*
+ * messagebox.h
+ *
+ * Copyright (C) 1999 Jonathan St-André
+ * Copyright (C) 1999 Hugo Villeneuve <hugo@hugovil.com>
+ *
+ * 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 <gtk/gtk.h>
+
+#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 */
--- /dev/null
+/*
+ * pgmwin.c
+ *
+ * Copyright (C) 1999 Jonathan St-André
+ * Copyright (C) 1999 Hugo Villeneuve <hugo@hugovil.com>
+ *
+ * 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 <stdio.h>
+
+#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;
+ }
+ }
+}
--- /dev/null
+/*
+ * pgmwin.h
+ *
+ * Copyright (C) 1999 Jonathan St-André
+ * Copyright (C) 1999 Hugo Villeneuve <hugo@hugovil.com>
+ *
+ * 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 <gtk/gtk.h>
+
+GtkWidget *
+pgmwin_init(void);
+
+void
+pgmwin_refresh(void);
+
+int
+pgmwin_IsBreakpoint(unsigned int address);
+
+#endif /* PGMWIN_H */
--- /dev/null
+/*
+ * pswwin.c
+ *
+ * Copyright (C) 1999 Jonathan St-André
+ * Copyright (C) 1999 Hugo Villeneuve <hugo@hugovil.com>
+ *
+ * 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 <stdio.h>
+
+#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);
+ }
+}
--- /dev/null
+/*
+ * pswwin.h
+ *
+ * Copyright (C) 1999 Jonathan St-André
+ * Copyright (C) 1999 Hugo Villeneuve <hugo@hugovil.com>
+ *
+ * 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 <gtk/gtk.h>
+
+GtkWidget *
+pswwin_init(void);
+
+void
+pswwin_refresh(void);
+
+#endif /* PSWWIN_H */
--- /dev/null
+/*
+ * regwin.c
+ *
+ * Copyright (C) 1999 Jonathan St-André
+ * Copyright (C) 1999 Hugo Villeneuve <hugo@hugovil.com>
+ *
+ * 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 <stdio.h>
+
+#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);
+ }
+}
--- /dev/null
+/*
+ * regwin.h
+ *
+ * Copyright (C) 1999 Jonathan St-André
+ * Copyright (C) 1999 Hugo Villeneuve <hugo@hugovil.com>
+ *
+ * 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 <gtk/gtk.h>
+
+GtkWidget *
+regwin_init(void);
+
+void
+regwin_refresh(void);
+
+#endif /* REGWIN_H */
--- /dev/null
+/*
+ * viewmenu.c
+ *
+ * Copyright (C) 1999 Jonathan St-André
+ * Copyright (C) 1999 Hugo Villeneuve <hugo@hugovil.com>
+ *
+ * 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 <gtk/gtk.h>
+
+#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);
+}
--- /dev/null
+/*
+ * viewmenu.h
+ *
+ * Copyright (C) 1999 Jonathan St-André
+ * Copyright (C) 1999 Hugo Villeneuve <hugo@hugovil.com>
+ *
+ * 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 <gtk/gtk.h>
+
+void
+ViewAddMenu(GtkWidget *menu_bar);
+
+#endif /* VIEWMENU_H */
+++ /dev/null
-/*
- * helpmenu.c
- *
- * Copyright (C) 1999 Jonathan St-André
- * Copyright (C) 1999 Hugo Villeneuve <hugo@hugovil.com>
- *
- * 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 <stdbool.h>
-
-#if STDC_HEADERS
-# include <string.h>
-#elif HAVE_STRINGS_H
-# include <strings.h>
-#endif
-
-#include <gtk/gtk.h>
-
-#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 <hugo@hugovil.com>",
- "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"
- " <http://www.gnu.org/licenses/>";
-
- 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);
-}
+++ /dev/null
-/*
- * helpmenu.h
- *
- * Copyright (C) 1999 Jonathan St-André
- * Copyright (C) 1999 Hugo Villeneuve <hugo@hugovil.com>
- *
- * 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 <gtk/gtk.h>
-
-void
-HelpAddMenu(GtkWidget *menu_bar);
-
-#endif /* HELPMENU_H */
+++ /dev/null
-/*
- * Functions for loading an Intel HEX file.
- *
- * Copyright (C) 1999 Jonathan St-André
- * Copyright (C) 1999 Hugo Villeneuve <hugo@hugovil.com>
- *
- * 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 <unistd.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-#if STDC_HEADERS
-# include <string.h>
-#elif HAVE_STRINGS_H
-# include <strings.h>
-#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);
- }
-}
+++ /dev/null
-/*
- * hexfile.h
- *
- * Copyright (C) 1999 Jonathan St-André
- * Copyright (C) 1999 Hugo Villeneuve <hugo@hugovil.com>
- *
- * 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 */
+++ /dev/null
-/*
- * keyboard.c
- *
- * Copyright (C) 1999 Jonathan St-André
- * Copyright (C) 1999 Hugo Villeneuve <hugo@hugovil.com>
- *
- * 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 <termios.h>
-#include <unistd.h>
-
-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);
-}
+++ /dev/null
-/*
- * keyboard.h
- *
- * Copyright (C) 1999 Jonathan St-André
- * Copyright (C) 1999 Hugo Villeneuve <hugo@hugovil.com>
- *
- * 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_ */
+++ /dev/null
-/*
- * log.c -- debug functions for logging.
- *
- * Copyright (C) 2011 Hugo Villeneuve <hugo@hugovil.com>
- *
- * 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 <unistd.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdarg.h>
-#include <string.h>
-
-#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);
-}
+++ /dev/null
-/*
- * log.h
- *
- * Copyright (C) 2011 Hugo Villeneuve <hugo@hugovil.com>
- *
- * 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 <stdio.h>
-#include <stdlib.h>
-#include <stdint.h>
-#include <errno.h>
-#include <string.h>
-
-#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 */
+++ /dev/null
-/*
- * memory.c
- *
- * Copyright (C) 1999 Jonathan St-André
- * Copyright (C) 1999 Hugo Villeneuve <hugo@hugovil.com>
- *
- * 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 <stdio.h>
-#include <string.h>
-
-#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 <base> 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");
- }
-}
+++ /dev/null
-/*
- * memory.h
- *
- * Copyright (C) 1999 Jonathan St-André
- * Copyright (C) 1999 Hugo Villeneuve <hugo@hugovil.com>
- *
- * 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 <sys/types.h>
-
-#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 */
+++ /dev/null
-/*
- * memwin.c
- *
- * Copyright (C) 1999 Jonathan St-André
- * Copyright (C) 1999 Hugo Villeneuve <hugo@hugovil.com>
- *
- * 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 <stdio.h>
-#include <ctype.h> /* 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;
- }
-}
+++ /dev/null
-/*
- * memwin.h
- *
- * Copyright (C) 1999 Jonathan St-André
- * Copyright (C) 1999 Hugo Villeneuve <hugo@hugovil.com>
- *
- * 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 <gtk/gtk.h>
-
-GtkWidget *
-memwin_init(char *title, int memory_id);
-
-void
-memwin_refresh(int memory_id);
-
-#endif /* MEMWIN_H */
+++ /dev/null
-/*
- * messagebox.c
- *
- * Copyright (C) 1999 Jonathan St-André
- * Copyright (C) 1999 Hugo Villeneuve <hugo@hugovil.com>
- *
- * 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 <gtk/gtk.h>
-
-#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);
-}
+++ /dev/null
-/*
- * messagebox.h
- *
- * Copyright (C) 1999 Jonathan St-André
- * Copyright (C) 1999 Hugo Villeneuve <hugo@hugovil.com>
- *
- * 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 <gtk/gtk.h>
-
-#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 */
+++ /dev/null
-#!/usr/bin/perl
-#
-# Copyright (C) 1999 Jonathan St-André
-# Copyright (C) 1999 Hugo Villeneuve <hugo@hugovil.com>
-#
-# 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 <instructions_8051.h> : $!\n";
-open INST_IMP, ">instructions_8051.c" or die "Error creating <instructions_8051.c> : $!\n";
-open OPCODELST, "opcodes.lst" or die "Error opening <opcodes.lst> : $!\n";
-open DISASM_H, ">disasm.h" or die "Error creating <disasm.h> : $!\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 <hugo@hugovil.com>\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=<OPCODELST>;
-$ligne=<OPCODELST>;
-while($ligne=<OPCODELST>) {
- 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;
+++ /dev/null
-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
+++ /dev/null
-/*
- * options.c -- functions for processing command-line options and arguments
- *
- * Copyright (C) 2011 Hugo Villeneuve <hugo@hugovil.com>
- *
- * 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 <unistd.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <argp.h>
-
-#if STDC_HEADERS
-# include <string.h>
-#elif HAVE_STRINGS_H
-# include <strings.h>
-#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);
-}
+++ /dev/null
-/*
- * options.h
- *
- * Copyright (C) 1999 Hugo Villeneuve <hugo@hugovil.com>
- *
- * 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 */
+++ /dev/null
-/*
- * pgmwin.c
- *
- * Copyright (C) 1999 Jonathan St-André
- * Copyright (C) 1999 Hugo Villeneuve <hugo@hugovil.com>
- *
- * 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 <stdio.h>
-
-#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;
- }
- }
-}
+++ /dev/null
-/*
- * pgmwin.h
- *
- * Copyright (C) 1999 Jonathan St-André
- * Copyright (C) 1999 Hugo Villeneuve <hugo@hugovil.com>
- *
- * 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 <gtk/gtk.h>
-
-GtkWidget *
-pgmwin_init(void);
-
-void
-pgmwin_refresh(void);
-
-int
-pgmwin_IsBreakpoint(unsigned int address);
-
-#endif /* PGMWIN_H */
+++ /dev/null
-/*
- * psw.c
- *
- * Copyright (C) 2013 Hugo Villeneuve <hugo@hugovil.com>
- *
- * 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);
-}
+++ /dev/null
-/*
- * psw.h
- *
- * Copyright (C) 2013 Hugo Villeneuve <hugo@hugovil.com>
- *
- * 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 <sys/types.h>
-
-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 */
+++ /dev/null
-/*
- * pswwin.c
- *
- * Copyright (C) 1999 Jonathan St-André
- * Copyright (C) 1999 Hugo Villeneuve <hugo@hugovil.com>
- *
- * 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 <stdio.h>
-
-#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);
- }
-}
+++ /dev/null
-/*
- * pswwin.h
- *
- * Copyright (C) 1999 Jonathan St-André
- * Copyright (C) 1999 Hugo Villeneuve <hugo@hugovil.com>
- *
- * 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 <gtk/gtk.h>
-
-GtkWidget *
-pswwin_init(void);
-
-void
-pswwin_refresh(void);
-
-#endif /* PSWWIN_H */
+++ /dev/null
-/*
- * reg8051.h
- *
- * Copyright (C) 1999 Jonathan St-André
- * Copyright (C) 1999 Hugo Villeneuve <hugo@hugovil.com>
- *
- * 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 */
+++ /dev/null
-/*
- * regwin.c
- *
- * Copyright (C) 1999 Jonathan St-André
- * Copyright (C) 1999 Hugo Villeneuve <hugo@hugovil.com>
- *
- * 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 <stdio.h>
-
-#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);
- }
-}
+++ /dev/null
-/*
- * regwin.h
- *
- * Copyright (C) 1999 Jonathan St-André
- * Copyright (C) 1999 Hugo Villeneuve <hugo@hugovil.com>
- *
- * 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 <gtk/gtk.h>
-
-GtkWidget *
-regwin_init(void);
-
-void
-regwin_refresh(void);
-
-#endif /* REGWIN_H */
+++ /dev/null
-/*
- * sfr.c
- *
- * Copyright (C) 2013 Hugo Villeneuve <hugo@hugovil.com>
- *
- * 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 <stdio.h>
-
-#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];
-}
-
+++ /dev/null
-/*
- * sfr.h
- *
- * Copyright (C) 2013 Hugo Villeneuve <hugo@hugovil.com>
- *
- * 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 */
+++ /dev/null
-/*
- * timers.c
- *
- * Copyright (C) 1999 Jonathan St-André
- * Copyright (C) 1999 Hugo Villeneuve <hugo@hugovil.com>
- *
- * 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 <stdio.h>
-#include <stdbool.h>
-#include <stdint.h>
-#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);
-}
+++ /dev/null
-/*
- * timers.h
- *
- * Copyright (C) 2013 Hugo Villeneuve <hugo@hugovil.com>
- *
- * 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 <stdint.h>
-
-int
-timers_check(void);
-
-#endif /* TIMERS_H */
+++ /dev/null
-/*
- * viewmenu.c
- *
- * Copyright (C) 1999 Jonathan St-André
- * Copyright (C) 1999 Hugo Villeneuve <hugo@hugovil.com>
- *
- * 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 <gtk/gtk.h>
-
-#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);
-}
+++ /dev/null
-/*
- * viewmenu.h
- *
- * Copyright (C) 1999 Jonathan St-André
- * Copyright (C) 1999 Hugo Villeneuve <hugo@hugovil.com>
- *
- * 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 <gtk/gtk.h>
-
-void
-ViewAddMenu(GtkWidget *menu_bar);
-
-#endif /* VIEWMENU_H */
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