ソースコードの推敲
[YACASL2.git] / src / disassemble.c
1 #include "disassemble.h"
2
3 /**
4  * @brief 機械コードの出力列
5  */
6 int codecol = 32;
7
8 /**
9  * @brief ファイルストリームから1ワードを取得する
10  *
11  * @return 取得した1ワード
12  *
13  * @param stream ファイルストリーム
14  */
15 WORD fgetword(FILE *stream);
16
17 /**
18  * @brief ファイルストリームを1ワード戻す
19  *
20  * @return なし
21  *
22  * @param stream ファイルストリーム
23  */
24 void fungetword(FILE *stream);
25
26 /**
27  * @brief ファイルストリームから、値が0の連続するWORD数を返す
28  *
29  * @return 値が0の連続するWORD数
30  *
31  * @param stream ファイルストリーム
32  */
33 WORD zero_data_cnt(FILE *stream);
34
35 /**
36  * @brief 機械コードをコメントとして標準出力へ出力する
37  *
38  * @return なし
39  *
40  * @param ascol アセンブラの列位置
41  * @param pradr 次に実行すべき命令語の先頭アドレス
42  * @param wordc ワード値の数
43  * @param wordv ワード値の配列
44  */
45 void disassemble_puts_code(int ascol, WORD pradr, int wordc, WORD wordv[]);
46
47 /**
48  * @brief 種類がR_ADRまたはR_ADR_Xのコマンドを逆アセンブルし、標準出力へ出力する
49  *
50  * @return なし
51  *
52  * @param cmdtype コマンドの種類
53  * @param *cmdname コマンドの名前
54  * @param word ワード値
55  * @param adr アドレス値
56  * @param pradr 次に実行すべき命令語の先頭アドレス
57  */
58 void disassemble_cmd_adr_x(CMDTYPE cmdtype, const char *cmdname, WORD word, WORD adr, WORD pradr);
59
60 /**
61  * @brief 種類がR1_R2またはR_のコマンドを逆アセンブルし、標準出力へ出力する
62  *
63  * @return なし
64  *
65  * @param cmdtype コマンドの種類
66  * @param *cmdname コマンドの名前
67  * @param word ワード値
68  * @param pradr 次に実行すべき命令語の先頭アドレス
69  */
70 void disassemble_cmd_r(CMDTYPE cmdtype, const char *cmdname, WORD word, WORD pradr);
71
72 /**
73  * @brief DCコマンドを逆アセンブルし、標準出力へ出力する
74  *
75  * @return なし
76  *
77  * @param word ワード値
78  * @param pradr 次に実行すべき命令語の先頭アドレス
79  */
80 void disassemble_dc(WORD word, WORD pradr);
81
82 void disassemble_puts_code(int ascol, WORD pradr, int wordc, WORD wordv[])
83 {
84     int i;
85     for(i = 0; i < codecol-ascol; i++){
86         fprintf(stdout, " ");
87     }
88     if(wordc == 1) {
89         fprintf(stdout, "; #%04X: #%04X", pradr, wordv[0]);
90     } else if(wordc == 2) {
91         fprintf(stdout, "; #%04X: #%04X #%04X", pradr, wordv[0], wordv[1]);
92     }
93 }
94 void disassemble_cmd_adr_x(CMDTYPE cmdtype, const char *cmdname, WORD word, WORD adr, WORD pradr)
95 {
96     WORD x = 0;
97     char *g = NULL;
98     int cnt = 0;
99     cnt += fprintf(stdout, "        %-7s ", cmdname);
100     if(cmdtype == R_ADR_X) {
101         cnt += fprintf(stdout, "%s,", g = grstr((word & 0x00F0) >> 4));
102         FREE(g);
103     }
104     cnt += fprintf(stdout, "#%04X", adr);
105     if((x = (word & 0x000F)) != 0) {
106         cnt += fprintf(stdout, ",%s", g = grstr(x));
107         FREE(g);
108     }
109     disassemble_puts_code(cnt, pradr, 2, (WORD []){word, adr});
110 }
111
112 void disassemble_cmd_r(CMDTYPE cmdtype, const char *cmdname, WORD word, WORD pradr)
113 {
114     char *g = NULL, *g1 = NULL, *g2 = NULL;
115     int cnt = 0;
116     cnt += fprintf(stdout, "        %-7s ", cmdname);
117     if(cmdtype == R1_R2) {
118         g1 = grstr((word & 0x00F0) >> 4);
119         g2 = grstr(word & 0x000F);
120         cnt += fprintf(stdout, "%s,%s", g1, g2);
121         FREE(g1);
122         FREE(g2);
123     } else if(cmdtype == R_) {
124         g = grstr((word & 0x00F0) >> 4);
125         cnt += fprintf(stdout, "%s", g);
126         FREE(g);
127     }
128     disassemble_puts_code(cnt, pradr, 1, (WORD []){word});
129 }
130
131 void disassemble_dc(WORD word, WORD pradr)
132 {
133     int cnt = 0;
134     cnt = fprintf(stdout, "        DC      %-5d ", word);
135     disassemble_puts_code(cnt, pradr, 1, (WORD []){word});
136     fprintf(stdout, " ::" );
137     print_dumpword(word, true);
138 }
139
140 void disassemble_ds(WORD wcnt, WORD pradr)
141 {
142     int cnt = 0, i;
143     cnt = fprintf(stdout, "        DS      %-5d ", wcnt);
144     disassemble_puts_code(cnt, pradr, 1, (WORD []){0});
145     for(i = 0; i < wcnt - 1; i++) {
146         fprintf(stdout, "\n");
147         disassemble_puts_code(0, pradr+1, 1, (WORD []){0});
148     }
149 }
150
151 WORD fgetword(FILE *stream)
152 {
153     WORD aword;
154     fread(&aword, sizeof(WORD), 1, stream);
155     return aword;
156 }
157
158 void fungetword(FILE *stream)
159 {
160     fseek(stream, -sizeof(WORD), SEEK_CUR);
161 }
162
163 WORD zero_data_cnt(FILE *stream)
164 {
165     WORD cnt = 0, word = 0;
166     while(!feof(stream) && word == 0) {
167         word = fgetword(stream);
168         cnt++;
169     }
170     if(!feof(stream)) {
171         fungetword(stream);
172     }
173     return cnt;
174 }
175
176 bool disassemble_file(const char *file)
177 {
178     bool stat = true;
179     FILE *fp;
180     WORD i = 0, word, cmd, zcnt;
181     CMDTYPE cmdtype = 0;
182     char *cmdname;
183     bool inst = true;
184
185     assert(file != NULL);
186     if((fp = fopen(file, "rb")) == NULL) {
187         perror(file);
188         return false;
189     }
190
191     create_cmdtable(HASH_CODE);                   /* 命令のコードとタイプがキーのハッシュ表を作成 */
192
193     fprintf(stdout, "MAIN    START\n");
194     for(word = fgetword(fp); !feof(fp); i++, word = fgetword(fp)) {
195         cmd = word & 0xFF00;
196         cmdname = getcmdname(cmd);
197         cmdtype = getcmdtype(cmd);
198         if(word == 0){
199             if(inst == true) {  /* プログラム領域の場合  */
200                 disassemble_cmd_r(NONE, "nop", 0, i);
201             } else {            /* データ領域の場合 */
202                 zcnt = zero_data_cnt(fp);
203                 if(zcnt == 1) { /* 1つだけの0はDCとみなす */
204                     disassemble_dc(0, i);
205                 } else {        /* 連続する0はDSとみなす */
206                     disassemble_ds(zcnt, i);
207                     i += zcnt - 1;
208                 }
209             }
210         } else if(cmd == 0) {
211             disassemble_dc(word, i);
212         } else {
213             if(cmdtype == R_ADR_X || cmdtype == ADR_X) {
214                 disassemble_cmd_adr_x(cmdtype, cmdname, word, fgetword(fp), i++);
215             } else {
216                 disassemble_cmd_r(cmdtype, cmdname, word, i);
217             }
218             inst = (cmd != 0x8100) ? true : false;
219         }
220         fprintf(stdout, "\n");
221     }
222     fprintf(stdout, "        END\n");
223     free_cmdtable(HASH_CODE);
224     fclose(fp);
225     return stat;
226 }
227
228 void disassemble_memory(WORD start, WORD end)
229 {
230     WORD i, cmd;
231     CMDTYPE cmdtype = 0;
232     char *cmdname;
233     bool inst = true;
234
235     for(i = start; i <= end; i++) {
236         cmd = sys->memory[i] & 0xFF00;
237         cmdname = getcmdname(cmd);
238         cmdtype = getcmdtype(cmd);
239         if(sys->memory[i] == 0) {
240             if(inst == true) {  /* プログラム領域の場合  */
241                 disassemble_cmd_r(NONE, "nop", 0, i);
242             } else {            /* データ領域の場合。メモリーでは、DC 0とみなす */
243                 disassemble_dc(0, i);
244             }
245         } else if(cmd == 0) {
246             disassemble_dc(sys->memory[i], i);
247         } else {
248             if(cmdtype == R_ADR_X || cmdtype == ADR_X) {
249                 disassemble_cmd_adr_x(cmdtype, cmdname, sys->memory[i], sys->memory[i+1], i);
250                 i++;
251             } else {
252                 disassemble_cmd_r(cmdtype, cmdname, sys->memory[i], i);
253             }
254             inst = (cmd != 0x8100) ? true : false;
255         }
256         fprintf(stdout, "\n");
257     }
258 }