disassembleコマンドを追加
[YACASL2.git] / src / disassemble.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #define _GNU_SOURCE
4 #include <getopt.h>
5 #include <assert.h>
6
7 #include "exec.h"
8 #include "cmem.h"
9 #include "cerr.h"
10 #include "package.h"
11
12 char *grstr(WORD word)
13 {
14     char *str;
15     str = (char *)malloc(4);
16     sprintf(str, "GR%d", word);
17     return str;
18 }
19
20 bool disassemble(const char *file)
21 {
22     FILE *fp;
23     bool stat = true;
24     int i = 0;
25     WORD w, cmd, r, x, r1, r2, adr;
26     CMDTYPE type = 0;
27     char *cmdname;
28
29     assert(file != NULL);
30     if((fp = fopen(file, "rb")) == NULL) {
31         perror(file);
32         return false;
33     }
34
35     create_code_cmdtype();                          /* 命令のコードとタイプがキーのハッシュ表を作成 */
36
37     fprintf(stdout, "MAIN\tSTART\n");
38     for( ; !feof(fp); ) {
39         fread(&w, sizeof(WORD), 1, fp);
40         cmd = w & 0xFF00;
41         cmdname = getcmdname(cmd);
42         if(cmd == 0xFF00 || (w != 0 && cmd == 0x0000)) {
43             fprintf(stdout, "\tDC\t%d\t\t; #%04X", w, i++);
44         } else if((type = getcmdtype(cmd)) == R_ADR_X || type == ADR_X) {
45             fread(&adr, sizeof(WORD), 1, fp);
46             fprintf(stdout, "\t%s\t", cmdname);
47             if(type == R_ADR_X) {
48                 r = (w &  0x00F0) >> 4;
49                 fprintf(stdout, "%s,", grstr(r));
50             }
51             fprintf(stdout, "#%04X", adr);
52             if((x = w &  0x000F) != 0) {
53                 fprintf(stdout, ",%s", grstr(x));
54             }
55             fprintf(stdout, "\t\t; #%04X", i);
56             i += 2;
57         } else {
58             fprintf(stdout, "\t%s", cmdname);
59             if(type == R1_R2) {
60                 r1 = (w &  0x00F0) >> 4;
61                 r2 = w &  0x000F;
62                 fprintf(stdout, "\t%s,%s", grstr(r1), grstr(r2));
63             } else if(type == R_) {
64                 r = (w & 0x00F0) >> 4;
65                 fprintf(stdout, "\t%s", grstr(r));
66             }
67             fprintf(stdout, "\t\t; #%04X", i++);
68         }
69         fprintf(stdout, "\n");
70     }
71     fprintf(stdout, "\tEND\n");
72     free_code_cmdtype();
73     return stat;
74 }
75
76 /**
77  * disassembleコマンドのオプション
78  */
79 static struct option longopts[] = {
80     {"version", no_argument, NULL, 'v' },
81     {"help", no_argument, NULL, 'h'},
82     {0, 0, 0, 0},
83 };
84
85 /**
86  * @brief disassembleコマンドのメイン
87  *
88  * @return 正常終了時は0、異常終了時は1
89  *
90  * @param argc コマンドライン引数の数
91  * @param *argv[] コマンドライン引数の配列
92  */
93 int main(int argc, char *argv[])
94 {
95     int opt, stat = 0;
96     const char *version = PACKAGE_VERSION,  *cmdversion = "disassemble of YACASL2 version %s\n";
97     const char *usage = "Usage: %s [-vh] FILE\n";
98
99     cerr_init();
100     addcerrlist_load();
101     addcerrlist_exec();
102
103     /* オプションの処理 */
104     while((opt = getopt_long(argc, argv, "vh", longopts, NULL)) != -1) {
105         switch(opt) {
106         case 'v':
107             fprintf(stdout, cmdversion, version);
108             return 0;
109         case 'h':
110             fprintf(stdout, usage, argv[0]);
111             return 0;
112         case '?':
113             fprintf(stderr, usage, argv[0]);
114             exit(1);
115         }
116     }
117     if(argv[optind] == NULL) {
118         setcerr(211, "");    /* object file not specified */
119         fprintf(stderr, "disassemble error - %d: %s\n", cerr->num, cerr->msg);
120         exit(1);
121     }
122     disassemble(argv[optind]);                /* プログラム実行 */
123     stat = (cerr->num == 0) ? 0 : 1;
124     /* エラーの解放 */
125     freecerr();
126     return stat;
127 }