X-Git-Url: http://j8takagi.net/cgi-bin/gitweb.cgi?p=YACASL2.git;a=blobdiff_plain;f=src%2Fdisassemble.c;h=dc40f1d7b94674bdc5dbc1c8879f1b78148d1faa;hp=9c2a341aa86e7c4672c64ee7b2ec92347a3bb7b1;hb=HEAD;hpb=ae04e48ee62a95f6f77794d5611db189a19e70de diff --git a/src/disassemble.c b/src/disassemble.c index 9c2a341..dc40f1d 100644 --- a/src/disassemble.c +++ b/src/disassemble.c @@ -1,29 +1,196 @@ -#include -#include -#define _GNU_SOURCE -#include -#include - -#include "exec.h" -#include "cmem.h" -#include "cerr.h" -#include "package.h" - -char *grstr(WORD word) +#include "disassemble.h" + +/** + * @brief 機械コードの出力列 + */ +int codecol = 32; + +/** + * @brief ファイルストリームから1ワードを取得する + * + * @return 取得した1ワード + * + * @param stream ファイルストリーム + */ +WORD fgetword(FILE *stream); + +/** + * @brief ファイルストリームを1ワード戻す + * + * @return なし + * + * @param stream ファイルストリーム + */ +void fungetword(FILE *stream); + +/** + * @brief ファイルストリームから、値が0の連続するWORD数を返す + * + * @return 値が0の連続するWORD数 + * + * @param stream ファイルストリーム + */ +WORD zero_data_cnt(FILE *stream); + +/** + * @brief 機械コードをコメントとして標準出力へ出力する + * + * @return なし + * + * @param ascol アセンブラの列位置 + * @param pradr 次に実行すべき命令語の先頭アドレス + * @param wordc ワード値の数 + * @param wordv ワード値の配列 + */ +void disassemble_puts_code(int ascol, WORD pradr, int wordc, WORD wordv[]); + +/** + * @brief 種類がR_ADRまたはR_ADR_Xのコマンドを逆アセンブルし、標準出力へ出力する + * + * @return なし + * + * @param cmdtype コマンドの種類 + * @param *cmdname コマンドの名前 + * @param word ワード値 + * @param adr アドレス値 + * @param pradr 次に実行すべき命令語の先頭アドレス + */ +void disassemble_cmd_adr_x(CMDTYPE cmdtype, const char *cmdname, WORD word, WORD adr, WORD pradr); + +/** + * @brief 種類がR1_R2またはR_のコマンドを逆アセンブルし、標準出力へ出力する + * + * @return なし + * + * @param cmdtype コマンドの種類 + * @param *cmdname コマンドの名前 + * @param word ワード値 + * @param pradr 次に実行すべき命令語の先頭アドレス + */ +void disassemble_cmd_r(CMDTYPE cmdtype, const char *cmdname, WORD word, WORD pradr); + +/** + * @brief DCコマンドを逆アセンブルし、標準出力へ出力する + * + * @return なし + * + * @param word ワード値 + * @param pradr 次に実行すべき命令語の先頭アドレス + */ +void disassemble_dc(WORD word, WORD pradr); + +void disassemble_puts_code(int ascol, WORD pradr, int wordc, WORD wordv[]) +{ + for(int i = 0; i < codecol-ascol; i++){ + fprintf(stdout, " "); + } + if(wordc == 1) { + fprintf(stdout, "; #%04X: #%04X", pradr, wordv[0]); + } else if(wordc == 2) { + fprintf(stdout, "; #%04X: #%04X #%04X", pradr, wordv[0], wordv[1]); + } +} +void disassemble_cmd_adr_x(CMDTYPE cmdtype, const char *cmdname, WORD word, WORD adr, WORD pradr) +{ + WORD x = 0; + char *g = NULL; + int cnt = 0; + + cnt += fprintf(stdout, " %-7s ", cmdname); + if(cmdtype == R_ADR_X) { + cnt += fprintf(stdout, "%s,", g = grstr((word & 0x00F0) >> 4)); + FREE(g); + } + cnt += fprintf(stdout, "#%04X", adr); + if((x = (word & 0x000F)) != 0) { + cnt += fprintf(stdout, ",%s", g = grstr(x)); + FREE(g); + } + disassemble_puts_code(cnt, pradr, 2, (WORD []){word, adr}); +} + +void disassemble_cmd_r(CMDTYPE cmdtype, const char *cmdname, WORD word, WORD pradr) +{ + char *g = NULL; + char *g1 = NULL; + char *g2 = NULL; + int cnt = 0; + + cnt += fprintf(stdout, " %-7s ", cmdname); + if(cmdtype == R1_R2) { + g1 = grstr((word & 0x00F0) >> 4); + g2 = grstr(word & 0x000F); + cnt += fprintf(stdout, "%s,%s", g1, g2); + FREE(g1); + FREE(g2); + } else if(cmdtype == R_) { + g = grstr((word & 0x00F0) >> 4); + cnt += fprintf(stdout, "%s", g); + FREE(g); + } + disassemble_puts_code(cnt, pradr, 1, (WORD []){word}); +} + +void disassemble_dc(WORD word, WORD pradr) +{ + int cnt = 0; + + cnt = fprintf(stdout, " DC %-5d ", word); + disassemble_puts_code(cnt, pradr, 1, (WORD []){word}); + fprintf(stdout, " ::" ); + print_dumpword(word, true); +} + +void disassemble_ds(WORD wcnt, WORD pradr) +{ + int cnt = 0; + + cnt = fprintf(stdout, " DS %-5d ", wcnt); + disassemble_puts_code(cnt, pradr, 1, (WORD []){0}); + for(int i = 0; i < wcnt - 1; i++) { + fprintf(stdout, "\n"); + disassemble_puts_code(0, pradr+1, 1, (WORD []){0}); + } +} + +WORD fgetword(FILE *stream) +{ + WORD aword; + fread(&aword, sizeof(WORD), 1, stream); + return aword; +} + +void fungetword(FILE *stream) +{ + fseek(stream, -sizeof(WORD), SEEK_CUR); +} + +WORD zero_data_cnt(FILE *stream) { - char *str; - str = (char *)malloc(4); - sprintf(str, "GR%d", word); - return str; + WORD cnt = 0; + WORD word = 0; + + while(!feof(stream) && word == 0) { + word = fgetword(stream); + cnt++; + } + if(!feof(stream)) { + fungetword(stream); + } + return cnt; } -bool disassemble(const char *file) +bool disassemble_file(const char *file) { bool stat = true; - FILE *fp; - WORD i = 0, w, cmd, r, x, r1, r2, adr; + FILE *fp = NULL; + WORD i = 0; + WORD word = 0; + WORD cmd = 0; + WORD zcnt = 0; CMDTYPE cmdtype = 0; - char *cmdname; + const char *cmdname = NULL; + bool inst = true; assert(file != NULL); if((fp = fopen(file, "rb")) == NULL) { @@ -31,102 +198,71 @@ bool disassemble(const char *file) return false; } - create_code_cmdtype(); /* 命令のコードとタイプがキーのハッシュ表を作成 */ + create_cmdtable(HASH_CODE); /* 命令のコードとタイプがキーのハッシュ表を作成 */ - fprintf(stdout, "MAIN\tSTART\n"); - for(; ;) { - fread(&w, sizeof(WORD), 1, fp); - if(feof(fp)) { - break; - } - cmd = w & 0xFF00; + fprintf(stdout, "MAIN START\n"); + for(word = fgetword(fp); !feof(fp); i++, word = fgetword(fp)) { + cmd = word & 0xFF00; cmdname = getcmdname(cmd); cmdtype = getcmdtype(cmd); - if(cmd == 0xFF00 || (w != 0 && cmd == 0x0000)) { - fprintf(stdout, "\tDC\t%d\t\t\t\t; #%04X: #%04X :: ", w, i++, w); - print_dumpword(w, true); - } else if(cmdtype == R_ADR_X || cmdtype == ADR_X) { - fread(&adr, sizeof(WORD), 1, fp); - fprintf(stdout, "\t%s\t", cmdname); - if(cmdtype == R_ADR_X) { - r = (w & 0x00F0) >> 4; - fprintf(stdout, "%s,", grstr(r)); - } - fprintf(stdout, "#%04X", adr); - if((x = w & 0x000F) != 0) { - fprintf(stdout, ",%s", grstr(x)); + if(word == 0){ + if(inst == true) { /* プログラム領域の場合 */ + disassemble_cmd_r(NONE, "nop", 0, i); + } else { /* データ領域の場合 */ + zcnt = zero_data_cnt(fp); + if(zcnt == 1) { /* 1つだけの0はDCとみなす */ + disassemble_dc(0, i); + } else { /* 連続する0はDSとみなす */ + disassemble_ds(zcnt, i); + i += zcnt - 1; + } } - fprintf(stdout, "\t\t\t\t; #%04X: #%04X #%04X", i, w, adr); - i += 2; + } else if(cmd == 0) { + disassemble_dc(word, i); } else { - fprintf(stdout, "\t%s", cmdname); - if(cmdtype == R1_R2) { - r1 = (w & 0x00F0) >> 4; - r2 = w & 0x000F; - fprintf(stdout, "\t%s,%s", grstr(r1), grstr(r2)); - } else if(cmdtype == R_) { - r = (w & 0x00F0) >> 4; - fprintf(stdout, "\t%s", grstr(r)); + if(cmdtype == R_ADR_X || cmdtype == ADR_X) { + disassemble_cmd_adr_x(cmdtype, cmdname, word, fgetword(fp), i++); + } else { + disassemble_cmd_r(cmdtype, cmdname, word, i); } - fprintf(stdout, "\t\t\t\t; #%04X: #%04X", i++, w); + inst = (cmd != 0x8100) ? true : false; } fprintf(stdout, "\n"); } - fprintf(stdout, "\tEND\n"); - free_code_cmdtype(); + fprintf(stdout, " END\n"); + free_cmdtable(HASH_CODE); fclose(fp); return stat; } -/** - * disassembleコマンドのオプション - */ -static struct option longopts[] = { - {"version", no_argument, NULL, 'v' }, - {"help", no_argument, NULL, 'h'}, - {0, 0, 0, 0}, -}; - -/** - * @brief disassembleコマンドのメイン - * - * @return 正常終了時は0、異常終了時は1 - * - * @param argc コマンドライン引数の数 - * @param *argv[] コマンドライン引数の配列 - */ -int main(int argc, char *argv[]) +void disassemble_memory(WORD start, WORD end) { - int opt, stat = 0; - const char *version = PACKAGE_VERSION, *cmdversion = "disassemble of YACASL2 version %s\n"; - const char *usage = "Usage: %s [-vh] FILE\n"; - - cerr_init(); - addcerrlist_load(); - addcerrlist_exec(); - - /* オプションの処理 */ - while((opt = getopt_long(argc, argv, "vh", longopts, NULL)) != -1) { - switch(opt) { - case 'v': - fprintf(stdout, cmdversion, version); - return 0; - case 'h': - fprintf(stdout, usage, argv[0]); - return 0; - case '?': - fprintf(stderr, usage, argv[0]); - exit(1); + WORD cmd = 0; + CMDTYPE cmdtype = 0; + const char *cmdname = NULL; + bool inst = true; + + for(int i = start; i <= end; i++) { + cmd = sys->memory[i] & 0xFF00; + cmdname = getcmdname(cmd); + cmdtype = getcmdtype(cmd); + if(sys->memory[i] == 0) { + if(inst == true) { /* プログラム領域の場合 */ + disassemble_cmd_r(NONE, "nop", 0, i); + } else { /* データ領域の場合。メモリーでは、DC 0とみなす */ + disassemble_dc(0, i); + } + } else if(cmd == 0) { + disassemble_dc(sys->memory[i], i); + } else { + if(cmdtype == R_ADR_X || cmdtype == ADR_X) { + disassemble_cmd_adr_x(cmdtype, cmdname, sys->memory[i], sys->memory[i+1], i); + i++; + } else { + disassemble_cmd_r(cmdtype, cmdname, sys->memory[i], i); + } + inst = (cmd != 0x8100) ? true : false; } + fprintf(stdout, "\n"); } - if(argv[optind] == NULL) { - setcerr(211, ""); /* object file not specified */ - fprintf(stderr, "disassemble error - %d: %s\n", cerr->num, cerr->msg); - exit(1); - } - disassemble(argv[optind]); /* プログラム実行 */ - stat = (cerr->num == 0) ? 0 : 1; - /* エラーの解放 */ - freecerr(); - return stat; }