mirror of
http://git.hugovil.com/git/emu8051.git
synced 2025-05-09 00:51:03 +08:00
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.
This commit is contained in:
parent
fd418e0f87
commit
c7d14532b0
@ -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)/config.sub $(ac_aux_dir)/ltmain.sh \
|
||||||
$(ac_aux_dir)/compile \
|
$(ac_aux_dir)/compile \
|
||||||
$(ac_aux_dir)/test-driver \
|
$(ac_aux_dir)/test-driver \
|
||||||
$(ac_aux_dir)/ar-lib
|
$(ac_aux_dir)/ar-lib \
|
||||||
|
$(ac_aux_dir)/ylwrap
|
||||||
|
|
||||||
changelog:
|
changelog:
|
||||||
@if test -d $(srcdir)/.git; then \
|
@if test -d $(srcdir)/.git; then \
|
||||||
|
@ -17,6 +17,10 @@ dnl Testing for libtool support.
|
|||||||
AC_PROG_RANLIB
|
AC_PROG_RANLIB
|
||||||
AM_PROG_AR
|
AM_PROG_AR
|
||||||
|
|
||||||
|
dnl Testing for Lex/Yacc
|
||||||
|
AC_PROG_LEX
|
||||||
|
AC_PROG_YACC
|
||||||
|
|
||||||
dnl Checking for typedefs, structures, and compiler characteristics.
|
dnl Checking for typedefs, structures, and compiler characteristics.
|
||||||
AC_C_CONST
|
AC_C_CONST
|
||||||
AC_TYPE_PID_T
|
AC_TYPE_PID_T
|
||||||
|
@ -5,18 +5,26 @@ AM_CPPFLAGS = \
|
|||||||
-I@top_srcdir@ \
|
-I@top_srcdir@ \
|
||||||
-I@top_srcdir@/src/common
|
-I@top_srcdir@/src/common
|
||||||
|
|
||||||
|
# Option -d: produce header file parser.h
|
||||||
|
AM_YFLAGS = -d
|
||||||
|
|
||||||
LDADD = \
|
LDADD = \
|
||||||
$(top_builddir)/src/common/libemu8051.a
|
$(top_builddir)/src/common/libemu8051.a
|
||||||
|
|
||||||
bin_PROGRAMS = emu8051-cli
|
bin_PROGRAMS = emu8051-cli
|
||||||
|
|
||||||
emu8051_cli_SOURCES = \
|
emu8051_cli_SOURCES = \
|
||||||
|
parser.y scanner.l \
|
||||||
emuconsole.c \
|
emuconsole.c \
|
||||||
|
menu.c menu.h \
|
||||||
keyboard.c keyboard.h
|
keyboard.c keyboard.h
|
||||||
|
|
||||||
# we want these in the dist tarball
|
# We want these in the dist tarball
|
||||||
EXTRA_DIST =
|
EXTRA_DIST = scanner.h
|
||||||
|
|
||||||
CLEANFILES = *~
|
CLEANFILES = *~
|
||||||
|
|
||||||
MAINTAINERCLEANFILES = Makefile.in
|
MAINTAINERCLEANFILES = \
|
||||||
|
Makefile.in \
|
||||||
|
scanner.h scanner.c \
|
||||||
|
parser.h parser.c
|
||||||
|
@ -19,492 +19,19 @@
|
|||||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define _GNU_SOURCE /* For getline() */
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <string.h>
|
#include <stdio.h>
|
||||||
#include <ctype.h> /* For isblank, toupper() */
|
|
||||||
#include "config.h"
|
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "cpu8051.h"
|
#include "cpu8051.h"
|
||||||
#include "reg8051.h"
|
|
||||||
#include "sfr.h"
|
|
||||||
#include "memory.h"
|
|
||||||
#include "timers.h"
|
|
||||||
#include "options.h"
|
#include "options.h"
|
||||||
#include "hexfile.h"
|
#include "hexfile.h"
|
||||||
#include "keyboard.h"
|
#include "menu.h"
|
||||||
|
#include "parser.h"
|
||||||
|
|
||||||
extern struct options_t options;
|
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
|
int
|
||||||
main(int argc, char **argv)
|
main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
@ -520,9 +47,17 @@ main(int argc, char **argv)
|
|||||||
exit(1);
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
228
src/cli/menu.c
Normal file
228
src/cli/menu.c
Normal file
@ -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();
|
||||||
|
}
|
52
src/cli/menu.h
Normal file
52
src/cli/menu.h
Normal file
@ -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_ */
|
257
src/cli/parser.y
Normal file
257
src/cli/parser.y
Normal file
@ -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);
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
|
|
32
src/cli/scanner.l
Normal file
32
src/cli/scanner.l
Normal file
@ -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];}
|
||||||
|
%%
|
@ -99,6 +99,13 @@ ClearBreakpoint(unsigned int address)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Clear all breakpoints */
|
||||||
|
void
|
||||||
|
ClearAllBreakpoints(void)
|
||||||
|
{
|
||||||
|
cpu8051.bp_count = 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* Toggle the breakpoint at Address. */
|
/* Toggle the breakpoint at Address. */
|
||||||
void
|
void
|
||||||
ToggleBreakpoint(unsigned int address)
|
ToggleBreakpoint(unsigned int address)
|
||||||
|
@ -71,6 +71,9 @@ SetBreakpoint(unsigned int Address);
|
|||||||
void
|
void
|
||||||
ClearBreakpoint(unsigned int Address);
|
ClearBreakpoint(unsigned int Address);
|
||||||
|
|
||||||
|
void
|
||||||
|
ClearAllBreakpoints(void);
|
||||||
|
|
||||||
void
|
void
|
||||||
ToggleBreakpoint(unsigned int Address);
|
ToggleBreakpoint(unsigned int Address);
|
||||||
|
|
||||||
|
@ -205,34 +205,17 @@ pgm_read_addr16(uint16_t base)
|
|||||||
|
|
||||||
/* Dump memory */
|
/* Dump memory */
|
||||||
void
|
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;
|
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) {
|
for (Offset = 0; Offset < size; Offset += 16) {
|
||||||
unsigned char data[16];
|
unsigned char data[16];
|
||||||
|
|
||||||
printf("%.4X ", MemAddress + Offset);
|
printf("%.4X ", address + Offset);
|
||||||
|
|
||||||
for (Column = 0; Column < 16; Column++) {
|
for (Column = 0; Column < 16; Column++) {
|
||||||
data[Column] = memory_read8(memory_id, MemAddress +
|
data[Column] = memory_read8(memory_id, address +
|
||||||
Offset + Column);
|
Offset + Column);
|
||||||
printf(" %.2X", (int) data[Column]);
|
printf(" %.2X", (int) data[Column]);
|
||||||
}
|
}
|
||||||
|
@ -86,6 +86,6 @@ uint16_t
|
|||||||
pgm_read_addr16(uint16_t base);
|
pgm_read_addr16(uint16_t base);
|
||||||
|
|
||||||
void
|
void
|
||||||
DumpMem(char *Address, char *Asize, int memory_id);
|
DumpMem(unsigned int address, int size, int memory_id);
|
||||||
|
|
||||||
#endif /* MEMORY_H */
|
#endif /* MEMORY_H */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user