summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHugo Villeneuve <hugo@hugovil.com>2014-01-26 19:59:34 -0500
committerHugo Villeneuve <hugo@hugovil.com>2014-02-13 00:25:17 -0500
commitc7d14532b034286e990bc28c994fa20b23aca95a (patch)
tree86c898308693e1f39a63fccd80af670c46bda76f
parentfd418e0f87d891d2cad0ce77e235a029487ab54e (diff)
downloademu8051-c7d14532b034286e990bc28c994fa20b23aca95a.tar.gz
emu8051-c7d14532b034286e990bc28c994fa20b23aca95a.tar.bz2
emu8051-c7d14532b034286e990bc28c994fa20b23aca95a.zip
Convert CLI version input parsing to Lex/Yacc
Some error checking is still missing, but all commands seem to be working correctly. Update CLI help menu.
-rw-r--r--Makefile.am3
-rw-r--r--configure.ac4
-rw-r--r--src/cli/Makefile.am14
-rw-r--r--src/cli/emuconsole.c493
-rw-r--r--src/cli/menu.c228
-rw-r--r--src/cli/menu.h52
-rw-r--r--src/cli/parser.y257
-rw-r--r--src/cli/scanner.l32
-rw-r--r--src/common/cpu8051.c7
-rw-r--r--src/common/cpu8051.h3
-rw-r--r--src/common/memory.c23
-rw-r--r--src/common/memory.h2
12 files changed, 614 insertions, 504 deletions
diff --git a/Makefile.am b/Makefile.am
index c15bf3a..12f0515 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -22,7 +22,8 @@ MAINTAINERCLEANFILES = Makefile.in aclocal.m4 configure config-h.in \
$(ac_aux_dir)/config.sub $(ac_aux_dir)/ltmain.sh \
$(ac_aux_dir)/compile \
$(ac_aux_dir)/test-driver \
- $(ac_aux_dir)/ar-lib
+ $(ac_aux_dir)/ar-lib \
+ $(ac_aux_dir)/ylwrap
changelog:
@if test -d $(srcdir)/.git; then \
diff --git a/configure.ac b/configure.ac
index 6bd5d18..1314fca 100644
--- a/configure.ac
+++ b/configure.ac
@@ -17,6 +17,10 @@ dnl Testing for libtool support.
AC_PROG_RANLIB
AM_PROG_AR
+dnl Testing for Lex/Yacc
+AC_PROG_LEX
+AC_PROG_YACC
+
dnl Checking for typedefs, structures, and compiler characteristics.
AC_C_CONST
AC_TYPE_PID_T
diff --git a/src/cli/Makefile.am b/src/cli/Makefile.am
index 63eedab..3fba226 100644
--- a/src/cli/Makefile.am
+++ b/src/cli/Makefile.am
@@ -5,18 +5,26 @@ AM_CPPFLAGS = \
-I@top_srcdir@ \
-I@top_srcdir@/src/common
+# Option -d: produce header file parser.h
+AM_YFLAGS = -d
+
LDADD = \
$(top_builddir)/src/common/libemu8051.a
bin_PROGRAMS = emu8051-cli
emu8051_cli_SOURCES = \
+ parser.y scanner.l \
emuconsole.c \
+ menu.c menu.h \
keyboard.c keyboard.h
-# we want these in the dist tarball
-EXTRA_DIST =
+# We want these in the dist tarball
+EXTRA_DIST = scanner.h
CLEANFILES = *~
-MAINTAINERCLEANFILES = Makefile.in
+MAINTAINERCLEANFILES = \
+ Makefile.in \
+ scanner.h scanner.c \
+ parser.h parser.c
diff --git a/src/cli/emuconsole.c b/src/cli/emuconsole.c
index e88ca0d..cbea820 100644
--- a/src/cli/emuconsole.c
+++ b/src/cli/emuconsole.c
@@ -19,492 +19,19 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-#define _GNU_SOURCE /* For getline() */
-#include <stdio.h>
#include <stdbool.h>
-#include <string.h>
-#include <ctype.h> /* For isblank, toupper() */
-#include "config.h"
+#include <stdio.h>
+#include "config.h"
#include "common.h"
#include "cpu8051.h"
-#include "reg8051.h"
-#include "sfr.h"
-#include "memory.h"
-#include "timers.h"
#include "options.h"
#include "hexfile.h"
-#include "keyboard.h"
+#include "menu.h"
+#include "parser.h"
extern struct options_t options;
-/* Capitalize all letters in buffer */
-static void
-Capitalize(char *buffer)
-{
- size_t 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)
-{
- size_t k = 0;
-
- while ((k < strlen(buffer)) && isblank(buffer[k]))
- k++;
-
- if (k != 0)
- strcpy(buffer, &buffer[k]);
-}
-
-/* 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");
-
- printf("| General-purpose Timer: %08d |\n", gp_timer_read());
- 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 exec and Console UI update */
-static void
-console_exec(char *NumberInst)
-{
- int NbInst = -1; /* -1 is infinity */
-
- if (NumberInst)
- if (strlen(NumberInst) != 0)
- NbInst = Ascii2Hex(NumberInst, strlen(NumberInst));
-
- InitUnixKB();
-
- log_info("Program executing...");
-
- cpu8051_run(NbInst, kbhit);
-
- if (kbhit()) {
- (void) getch(); /* Flush key */
- log_info("Caught break signal!");
- }
-
- ResetUnixKB();
- console_show_registers();
- DisasmN(cpu8051.pc, 1);
-}
-
-/* CPU trace and Console UI update */
-static void
-console_trace()
-{
- 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 (Run)............... EM [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 (step)................ T",
- " Unassemble.................. U [address]"
- " [number of instructions]",
- " Reset processor............. Z",
- " Reset general-purpose timer. ZT", 0 };
-
- console_reset();
-
- if (options.stop_address != 0) {
- /* Automatically run program and stop at specified address. */
- console_exec(NULL);
- 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;
- int rc;
- char Command[256];
- char Args[256];
- char Parameter1[256];
- char Parameter2[256];
-
- Parameter1[0] = '\0';
- Parameter2[0] = '\0';
-
- printf("%s", prompt);
- rc = getline(&line, &len, stdin);
- if (rc < 0)
- goto syntax_error;
-
- 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;
- }
-
- if (strlen(line) == 0) {
- /* Empty line, this is not an error. */
- continue;
- }
-
- /* 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") &&
- (strlen(Parameter1) == 0))
- console_exec(NULL);
- else if (STREQ(Command, "EM") &&
- (strlen(Parameter1) != 0))
- console_exec(Parameter1);
- 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(Parameter1) != 0) ||
- (strlen(Parameter2) != 0))
- printf("Wrong Number of Parameters!\n");
-
- if (STREQ(Command, "T"))
- console_trace();
- 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 if (STREQ(Command, "ZT") &&
- (strlen(Parameter1) == 0) &&
- (strlen(Parameter2) == 0))
- gp_timer_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)
{
@@ -520,9 +47,17 @@ main(int argc, char **argv)
exit(1);
}
- console_main();
+ console_reset();
- log_info("Terminate");
+ if (options.stop_address != 0) {
+ /* Automatically run program and stop at specified address. */
+ console_exec(-1);
+ } else {
+ menu_display_usage();
+ console_show_registers();
+ menu_prompt();
+ yyparse();
+ }
return 0;
}
diff --git a/src/cli/menu.c b/src/cli/menu.c
new file mode 100644
index 0000000..478fe2b
--- /dev/null
+++ b/src/cli/menu.c
@@ -0,0 +1,228 @@
+/*
+ * menu.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 <stdbool.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "common.h"
+#include "cpu8051.h"
+#include "reg8051.h"
+#include "sfr.h"
+#include "memory.h"
+#include "timers.h"
+#include "options.h"
+#include "hexfile.h"
+#include "keyboard.h"
+#include "menu.h"
+
+extern struct options_t options;
+
+void
+menu_prompt(void)
+{
+ printf("-> ");
+}
+
+void
+menu_display_usage(void)
+{
+ printf(" *******************\n"
+ " * 8051 Emulator *\n"
+ " *******************\n"
+ "\n"
+ " Available commands, [ ] = options\n"
+ "\n"
+ " Set Breakpoint.............. SB [address]\n"
+ " Remove Breakpoint........... RB [address]\n"
+ " address = all:"
+ " clear all breakpoints\n"
+ " Display Breakpoint(s)....... DB\n"
+ " Dump External Data Memory... DE [address] [size]\n"
+ " Dump Internal Data Memory... DI [address] [size]\n"
+ " Dump Program Memory......... DP [address] [size]\n"
+ " Display Registers........... DR\n"
+ " Help........................ H or ?\n"
+ " Modify External Data Memory. ME address value\n"
+ " Modify Internal Data Memory. MI address value\n"
+ " Modify Program Memory....... MP address value\n"
+ " Modify Register............. MR register value\n"
+ " Quit........................ Q\n"
+ " Run......................... R [number of instructions]\n"
+ " Step........................ S\n"
+ " Unassemble.................. U [address]"
+ " [number of instructions]\n"
+ " Reset processor............. Z\n"
+ " Reset general-purpose timer. ZT\n");
+}
+
+/* Disassemble NumberInst instructions at Address */
+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;
+ }
+}
+
+/* Set NewValue to Register */
+void
+SetRegister(char *Register, int NewValue)
+{
+ if (STREQ(Register, "PC"))
+ cpu8051.pc = NewValue;
+ else if (STREQ(Register, "A"))
+ cpu8051_WriteD(_ACC_, NewValue);
+ else if (STREQ(Register, "B"))
+ cpu8051_WriteD(_B_, NewValue);
+ else if (STREQ(Register, "SP"))
+ cpu8051_WriteD(_SP_, NewValue);
+ else {
+ printf("\nInvalid register name!\n");
+ printf("Valid registers are A, B, PC and SP.\n");
+ }
+}
+
+/* CPU reset and Console UI update */
+void
+console_reset(void)
+{
+ log_info("Resetting...");
+ cpu8051_Reset();
+ log_info("Done");
+}
+
+/*
+ * CPU exec and Console UI update
+ * NbInst = -1: run to infinity
+ */
+void
+console_exec(int NbInst)
+{
+ InitUnixKB();
+
+ log_info("Program executing...");
+
+ cpu8051_run(NbInst, kbhit);
+
+ if (kbhit()) {
+ (void) getch(); /* Flush key */
+ log_info("Caught break signal!");
+ }
+
+ ResetUnixKB();
+ console_show_registers();
+ DisasmN(cpu8051.pc, 1);
+}
+
+/* CPU trace and Console UI update */
+void
+console_trace(void)
+{
+ cpu8051_Exec();
+ console_show_registers();
+ DisasmN(cpu8051.pc, 1);
+}
+
+/* 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");
+
+ printf("| General-purpose Timer: %08d |\n", gp_timer_read());
+ printf("-----------------------------------\n");
+}
+
+/* Show CPU registers */
+void
+console_show_registers(void)
+{
+ if (options.stop_address != 0)
+ console_dump_sfr_registers_detailed();
+ else
+ console_dump_sfr_registers_compact();
+}
diff --git a/src/cli/menu.h b/src/cli/menu.h
new file mode 100644
index 0000000..9dd2919
--- /dev/null
+++ b/src/cli/menu.h
@@ -0,0 +1,52 @@
+/*
+ * menu.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 _MENU_H_
+#define _MENU_H_
+
+int
+yyparse(void);
+
+void
+menu_prompt(void);
+
+void
+menu_display_usage(void);
+
+void
+console_show_registers(void);
+
+void
+SetRegister(char *Register, int NewValue);
+
+void
+console_reset(void);
+
+void
+console_exec(int NbInst);
+
+void
+console_trace(void);
+
+void
+DisasmN(unsigned int Address, int NumberInst);
+
+#endif /* _MENU_H_ */
diff --git a/src/cli/parser.y b/src/cli/parser.y
new file mode 100644
index 0000000..00338b3
--- /dev/null
+++ b/src/cli/parser.y
@@ -0,0 +1,257 @@
+%{
+#include <stdint.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "config.h"
+#include "log.h"
+#include "menu.h"
+#include "memory.h"
+#include "timers.h"
+#include "cpu8051.h"
+
+/* int yydebug = 1; */
+
+/* To get rid of compiler warning. */
+int yylex();
+
+int yyerror(const char *str)
+{
+ fprintf(stderr,"error: %s\n", str);
+ return 0;
+}
+
+%}
+
+%token NUMBER TOK_ENTER TOK_ALL
+%token TOK_SB TOK_RB TOK_DB
+%token TOK_DE TOK_DI TOK_DP TOK_DR
+%token TOK_PC
+%token TOK_HELP
+%token TOK_RUN
+%token TOK_RST TOK_RST_TIMER
+%token TOK_STEP
+%token TOK_UNASM
+%token TOK_MOD_EXT TOK_MOD_INT TOK_MOD_PROG TOK_MOD_REG
+%token TOK_QUIT
+
+%%
+
+start : start command { menu_prompt(); }
+ | error TOK_ENTER {
+ /* In case of error, discard entire line */
+ yyerrok;
+ menu_prompt();
+ }
+ | start TOK_ENTER { menu_prompt(); }
+ |
+ ;
+
+command:
+ pc_set
+ |
+ breakpoint_clr
+ |
+ breakpoint_set
+ |
+ breakpoint_display
+ |
+ dump_ext_mem
+ |
+ dump_int_mem
+ |
+ dump_prog_mem
+ |
+ display_regs
+ |
+ help
+ |
+ modify
+ |
+ quit
+ |
+ reset
+ |
+ run
+ |
+ step
+ |
+ unasm
+ ;
+
+breakpoint_clr:
+ TOK_RB NUMBER TOK_ENTER
+ {
+ log_debug(" Remove breakpoint at $%04X", $2);
+ ClearBreakpoint($2);
+ }
+ |
+ TOK_RB TOK_ENTER
+ {
+ log_debug(" Remove breakpoint at PC");
+ ClearBreakpoint(cpu8051.pc);
+ }
+ |
+ TOK_RB TOK_ALL TOK_ENTER
+ {
+ log_debug(" Remove all breakpoints");
+ ClearAllBreakpoints();
+ }
+ ;
+
+breakpoint_set:
+ TOK_SB TOK_ENTER
+ {
+ log_debug(" Set breakpoint at current PC");
+ SetBreakpoint(cpu8051.pc);
+ }
+ |
+
+ TOK_SB NUMBER TOK_ENTER
+ {
+ log_debug(" Set breakpoint at $%04X", $2);
+ SetBreakpoint($2);
+ }
+ ;
+
+breakpoint_display:
+ TOK_DB TOK_ENTER
+ {
+ log_debug(" Display breakpoints");
+ ShowBreakpoints();
+ }
+ ;
+
+dump_ext_mem:
+ TOK_DE NUMBER NUMBER TOK_ENTER
+ {
+ log_debug(" Dump External Data Memory at $%04X, len %d", $2, $3);
+ DumpMem($2, $3, EXT_MEM_ID);
+ }
+ ;
+
+dump_int_mem:
+ TOK_DI NUMBER NUMBER TOK_ENTER
+ {
+ log_debug(" Dump Internal Data Memory at $%04X, len %d", $2, $3);
+ DumpMem($2, $3, INT_MEM_ID);
+ }
+ ;
+
+dump_prog_mem:
+ TOK_DP NUMBER NUMBER TOK_ENTER
+ {
+ log_debug(" Dump Program Memory at $%04X, len %d", $2, $3);
+ DumpMem($2, $3, PGM_MEM_ID);
+ }
+ ;
+
+display_regs:
+ TOK_DR TOK_ENTER
+ {
+ log_debug(" Display Registers");
+ console_show_registers();
+ }
+ ;
+
+modify:
+ TOK_MOD_EXT NUMBER NUMBER TOK_ENTER
+ {
+ log_debug(" Modify external memory");
+ memory_write8(EXT_MEM_ID, $2, $3);
+ }
+ |
+ TOK_MOD_INT NUMBER NUMBER TOK_ENTER
+ {
+ log_debug(" Modify internal memory");
+ memory_write8(INT_MEM_ID, $2, $3);
+ }
+ |
+ TOK_MOD_PROG NUMBER NUMBER TOK_ENTER
+ {
+ log_debug(" Modify program memory");
+ memory_write8(PGM_MEM_ID, $2, $3);
+ }
+ |
+ TOK_MOD_REG "pc" NUMBER TOK_ENTER
+ {
+ log_debug(" Modify register");
+ SetRegister("PC", $2);
+ }
+ ;
+
+quit:
+ TOK_QUIT TOK_ENTER
+ {
+ printf(" Quit");
+ YYACCEPT;
+ }
+ ;
+
+run:
+ TOK_RUN TOK_ENTER
+ {
+ log_debug(" Run");
+ console_exec(-1);
+ }
+ |
+ TOK_RUN NUMBER TOK_ENTER
+ {
+ log_debug(" Run %d instructions", $2);
+ console_exec($2);
+ }
+ ;
+
+pc_set:
+ TOK_PC NUMBER TOK_ENTER
+ {
+ cpu8051.pc = $2;
+ }
+ ;
+
+help:
+ TOK_HELP TOK_ENTER
+ {
+ menu_display_usage();
+ }
+ ;
+
+reset:
+ TOK_RST TOK_ENTER
+ {
+ cpu8051_Reset();
+ }
+ |
+ TOK_RST_TIMER TOK_ENTER
+ {
+ gp_timer_reset();
+ }
+ ;
+
+step:
+ TOK_STEP TOK_ENTER
+ {
+ console_trace();
+ }
+ ;
+
+unasm:
+ TOK_UNASM NUMBER NUMBER TOK_ENTER
+ {
+ DisasmN($2, $3);
+ }
+ |
+ TOK_UNASM NUMBER TOK_ENTER
+ {
+ DisasmN(cpu8051.pc, $2);
+ }
+ ;
+ |
+ TOK_UNASM TOK_ENTER
+ {
+ DisasmN(cpu8051.pc, 16);
+ }
+ ;
+
+
diff --git a/src/cli/scanner.l b/src/cli/scanner.l
new file mode 100644
index 0000000..757376e
--- /dev/null
+++ b/src/cli/scanner.l
@@ -0,0 +1,32 @@
+%option noyywrap
+%option noinput
+%option nounput
+%{
+ #include "parser.h"
+%}
+%%
+[0-9]+ { yylval = atoi(yytext); return NUMBER;}
+[h?] return TOK_HELP;
+sb return TOK_SB;
+rb return TOK_RB;
+db return TOK_DB;
+de return TOK_DE;
+di return TOK_DI;
+dp return TOK_DP;
+dr return TOK_DR;
+r return TOK_RUN;
+pc return TOK_PC;
+all return TOK_ALL;
+me return TOK_MOD_EXT;
+mi return TOK_MOD_INT;
+mp return TOK_MOD_PROG;
+mr return TOK_MOD_REG;
+q return TOK_QUIT;
+s return TOK_STEP;
+u return TOK_UNASM;
+z return TOK_RST;
+zt return TOK_RST_TIMER;
+[\n] return TOK_ENTER;
+[ \t]+ { /* ignore whitespace */ }
+. { return yytext[0];}
+%%
diff --git a/src/common/cpu8051.c b/src/common/cpu8051.c
index 107f2ef..fb93126 100644
--- a/src/common/cpu8051.c
+++ b/src/common/cpu8051.c
@@ -99,6 +99,13 @@ ClearBreakpoint(unsigned int address)
}
}
+/* Clear all breakpoints */
+void
+ClearAllBreakpoints(void)
+{
+ cpu8051.bp_count = 0;
+}
+
/* Toggle the breakpoint at Address. */
void
ToggleBreakpoint(unsigned int address)
diff --git a/src/common/cpu8051.h b/src/common/cpu8051.h
index 49494f0..430e00e 100644
--- a/src/common/cpu8051.h
+++ b/src/common/cpu8051.h
@@ -72,6 +72,9 @@ void
ClearBreakpoint(unsigned int Address);
void
+ClearAllBreakpoints(void);
+
+void
ToggleBreakpoint(unsigned int Address);
void
diff --git a/src/common/memory.c b/src/common/memory.c
index 2e37210..d01153a 100644
--- a/src/common/memory.c
+++ b/src/common/memory.c
@@ -205,34 +205,17 @@ pgm_read_addr16(uint16_t base)
/* Dump memory */
void
-DumpMem(char *Address, char *Asize, int memory_id)
+DumpMem(unsigned int address, int size, 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);
+ printf("%.4X ", address + Offset);
for (Column = 0; Column < 16; Column++) {
- data[Column] = memory_read8(memory_id, MemAddress +
+ data[Column] = memory_read8(memory_id, address +
Offset + Column);
printf(" %.2X", (int) data[Column]);
}
diff --git a/src/common/memory.h b/src/common/memory.h
index 7beb0e8..cbb9eb8 100644
--- a/src/common/memory.h
+++ b/src/common/memory.h
@@ -86,6 +86,6 @@ uint16_t
pgm_read_addr16(uint16_t base);
void
-DumpMem(char *Address, char *Asize, int memory_id);
+DumpMem(unsigned int address, int size, int memory_id);
#endif /* MEMORY_H */