bool dump; /**<メモリの内容をステップごとに表示する場合はtrue */
WORD dump_start; /**<メモリの内容をステップごとに表示する場合の開始アドレス */
WORD dump_end; /**<メモリの内容をステップごとに表示する場合の終了アドレス */
+ bool reverse; /**<逆アセンブルの結果をステップごとに表示する場合はtrue */
bool monitor; /**<モニターモードの場合はtrue */
bool step; /**<ステップ実行の場合はtrue */
} EXECMODE;
/**
- * @brief 実行モード: trace, logical, dump, monitor, step
+ * @brief 実行モード: trace, logical, dump, reverse, monitor, step
*/
extern EXECMODE execmode;
char *getcmdname(WORD code);
#endif
+
+/**
+ * 命令コードから、命令語長を返す\n
+ * 無効な場合は0を返す
+ */
+WORD code2cmdwordlen(WORD code);
{"tracearithmetic", no_argument, NULL, 't'},
{"tracelogical", no_argument, NULL, 'T'},
{"dump", no_argument, NULL, 'd'},
+ {"reverse", no_argument, NULL, 'r'},
{"memorysize", required_argument, NULL, 'M'},
{"clocks", required_argument, NULL, 'C'},
{"version", no_argument, NULL, 'v' },
int stat = 0;
const char *version = PACKAGE_VERSION;
const char *cmdversion = "comet2monitor: COMET II machine code monitor of YACASL2 version %s\n";
- const char *usage = "Usage: %s [-tTdvh] [-M <MEMORYSIZE>] [-C <CLOCKS>] FILE\n";
+ const char *usage = "Usage: %s [-tTdrvh] [-M <MEMORYSIZE>] [-C <CLOCKS>] FILE\n";
/* エラーの定義 */
cerr_init();
addcerrlist_exec();
addcerrlist_comet2monitor();
+ execmode.reverse = true;
/* オプションの処理 */
- while((opt = getopt_long(argc, argv, "tTdM:C:vh", longopts, NULL)) != -1) {
+ while((opt = getopt_long(argc, argv, "tTdqM:C:vh", longopts, NULL)) != -1) {
switch(opt) {
case 't':
execmode.trace = true;
case 'd':
execmode.dump = true;
break;
+ case 'q':
+ execmode.reverse = false;
+ break;
case 'M':
if((memsize = memsize_str2word(optarg)) == 0) {
goto comet2monitorfin;
#include "exec.h"
+#include "struct.h"
+#include "disassemble.h"
/* exec.hに定義された関数群 */
void dumpmemory(WORD start, WORD end)
void dsp_trace_dump()
{
- if(execptr->stop == false && (execmode.dump || execmode.trace)) { /* traceまたはdumpオプション指定時、改行を出力 */
- if(execmode.trace) { /* traceオプション指定時、レジスタを出力 */
+ if(execptr->stop == false && (execmode.dump == true || execmode.trace == true || execmode.reverse == true)) { /* traceまたはdumpオプション指定時、改行を出力 */
+ if(sys->cpu->pr == execptr->start && execmode.reverse == true) { /* reverseオプション指定時、スタート時にプログラム全体を逆アセンブル */
+ fprintf(stdout, "Disassemble::::\n");
+ disassemble_memory(execptr->start, execptr->end);
+ }
+ if(execmode.trace == true) { /* traceオプション指定時、レジスタを出力 */
fprintf(stdout, "#%04X: Register::::\n", sys->cpu->pr);
dspregister();
}
- if(execmode.dump) { /* dumpオプション指定時、メモリを出力 */
+ if(execmode.dump == true) { /* dumpオプション指定時、メモリを出力 */
fprintf(stdout, "#%04X: Memory::::\n", sys->cpu->pr);
dumpmemory(execmode.dump_start, execmode.dump_end);
}
+ if(execmode.reverse == true) { /* reverseオプション指定時、ステップごとに語長分を逆アセンブル */
+ fprintf(stdout, "#%04X: Disassemble::::\n", sys->cpu->pr);
+ disassemble_memory(sys->cpu->pr, sys->cpu->pr + code2cmdwordlen(sys->memory[sys->cpu->pr] & 0xFF00) - 1);
+ }
fprintf(stdout, "\n");
}
}
};
/**
- * @brief 実行モード: trace, logical, dump, dump_start, dump_end, monitor, step
+ * @brief 実行モード: trace, logical, dump, dump_start, dump_end, reverse, monitor, step
*/
-EXECMODE execmode = {false, false, false, 0, 0xFFFF, false, false};
+EXECMODE execmode = {false, false, false, 0, 0xFFFF, false, false, false};
CLOCK clock_str2clock(const char *str) {
long val = str2l_range(str, 1, LONG_MAX, "Clock");
fprintf(stdout, "Quit: COMET II monitor\n");
cmdtype = MONQUIT;
} else if(stracmp(cmd, 2, (char* []){"r", "reverse"})) {
- if(args->argc == 2) {
+ if(args->argc > 0 && stracmp(args->argv[0], 2, (char* []){"a", "auto"})) {
+ execmode.reverse = true;
+ } else if(args->argc > 0 && stracmp(args->argv[0], 2, (char* []){"n", "noauto"})) {
+ execmode.reverse = false;
+ } else if(args->argc == 2) {
disassemble_memory(nh2word(args->argv[0]), nh2word(args->argv[1]));
+ } else {
+ disassemble_memory(execptr->start, execptr->end);
}
} else if(stracmp(cmd, 1, (char* []){"reset"})) {
fprintf(stdout, "Reset COMET II CPU.\n");
} else if(stracmp(cmd, 1, (char* []){"resetall"})) {
fprintf(stdout, "Reset COMET II CPU and memory.\n");
comet2_resetall(); /* COMET II仮想マシンのCPUとメモリのリセット */
- } else if(stracmp(cmd, 2, (char* []){"t", "trace"})) {
- if(args->argc > 0 && stracmp(args->argv[0], 2, (char* []){"a", "auto"})) {
+ } else if(stracmp(cmd, 2, (char* []){"t", "trace", "T", "tracelogical"})) {
+ if(stracmp(cmd, 2, (char* []){"t", "trace"})) {
execmode.logical = false;
- execmode.trace = true;
- } else if(args->argc > 0 && stracmp(args->argv[0], 2, (char* []){"no", "noauto"})) {
- execmode.trace = false;
} else {
- fprintf(stdout, "#%04X: Register::::\n", sys->cpu->pr);
- dspregister();
+ execmode.logical = true;
}
- } else if(stracmp(cmd, 2, (char* []){"T", "tracelogical"})) {
if(args->argc > 0 && stracmp(args->argv[0], 2, (char* []){"a", "auto"})) {
- execmode.logical = true;
execmode.trace = true;
- } else if(args->argc > 0 && stracmp(args->argv[0], 2, (char* []){"no", "noauto"})) {
+ } else if(args->argc > 0 && stracmp(args->argv[0], 2, (char* []){"n", "noauto"})) {
execmode.trace = false;
} else {
fprintf(stdout, "#%04X: Register::::\n", sys->cpu->pr);
fprintf(stdout, "q[uit] -- Quit running your program.\n");
fprintf(stdout, "reset -- Reset COMET II CPU.\n");
fprintf(stdout, "resetall -- Reset COMET II CPU and memory.\n");
- fprintf(stdout, "r[everse] -- Disassemble memory. `r[everse] <start address> <end address>.\n");
+ fprintf(stdout, "r[everse] -- Disassemble memory. `r[everse] <start address> <end address>'. `r[everse] a[uto]/n[oauto]' set auto/noauto display.\n");
fprintf(stdout, "s[ave] -- Save object from the memory to a file. `s[ave] <filepath> [<start address1> [<end address>]]' if <start address> and <end address> is omitted, save the whole memory. if <end address> is omitted, save the memory after <start address>.\n");
fprintf(stdout, "t[race] -- Display CPU register. `t[race] a[uto]/n[oauto]' set auto/noauto display. \n");
- fprintf(stdout, "T[race] -- Display CPU register as logical value. `t[race] a[uto]/n[oauto]' set auto/noauto display. \n");
+ fprintf(stdout, "T[race] -- Display CPU register as logical value. `t[race] a[uto]/n[oauto]' set auto/noauto display.\n");
fprintf(stdout, "?/h[elp] -- Display this help.\n");
}
return cmdtype;
WORD getcmdwordlen(const char *cmd, CMDTYPE type)
{
CMDTAB *p = NULL;
- int l = 0;
+ int wl = 0;
assert(cmd != NULL);
for(p = cmdtab[HASH_CMDTYPE][hash_cmdtype(cmd, type)]; p != NULL; p = p->next) {
if(strcmp(cmd, p->cmd->name) == 0 && type == p->cmd->type) {
- l = p->cmd->wordlen;
+ wl = p->cmd->wordlen;
break;
}
}
- return l;
+ return wl;
}
/**
return cmd;
}
+/**
+ * 命令コードから、命令語長を返す\n
+ * 無効な場合は0を返す
+ */
+WORD code2cmdwordlen(WORD code)
+{
+ CMDTAB *t = NULL;
+ int wl = 0;
+
+ for(t = cmdtab[HASH_CODE][hash_code(code)]; t != NULL; t = t->next) {
+ if(code == t->cmd->code) {
+ wl = t->cmd->wordlen;
+ break;
+ }
+ }
+ return wl;
+}
+
/**
* 汎用レジスタの番号からレジスタを表す文字列を返す
*/