|
|
1.1 root 1: <?php
2: //
3: // nono
1.1.1.2 root 4: // Copyright (C) 2020 nono project
5: // Licensed under nono-license.txt
1.1 root 6: //
7:
8: if ($argc < 2) {
9: usage();
10: }
11:
12: $insttable = read_instructions("instructions.txt");
13: $insttable = expand($insttable);
14: makeop12($insttable);
15: makeop12hash();
1.1.1.4 ! root 16: output_cpp();
1.1 root 17: output_switch();
18: output_header();
19: exit(0);
20: ?>
21: <?php
22: function usage()
23: {
24: global $argv;
25:
26: print "Usage: ${argv[0]}\n";
27: exit(1);
28: }
29:
30:
31: // instructions.txt を読み込んで $insttable[] 配列にする
32: function read_instructions($filename)
33: {
34: $fp = fopen($filename, "r");
35: if ($fp === false) {
36: print "fopen failed: {$filename}\n";
37: exit(1);
38: }
39:
40: $insttable = array();
41:
42: while (($line = fgets($fp))) {
43: $line = trim(preg_replace("/;.*/", "", $line));
44: if ($line == "") {
45: continue;
46: }
47:
48: // 1行はこんな感じ
49: // 000000_DDDDD_SSSSS_nnnnnn_nnnnnnnnnn ld_d_xrf ld.d(XRF)
50: // 列は1つ以上のタブで区切られている。
51: // $bits … ビットパターン
52: // $name … 関数名
53: // $text … コメント
54:
55: $column = preg_split("/\t+/", $line, -1, PREG_SPLIT_NO_EMPTY);
56: $bits = $column[0];
57: $name = $column[1];
58: $text = isset($column[2]) ? $column[2] : "";
59:
60: $name = trim($name);
61: $text = trim($text);
62:
63: // 命令ワード32ビットは 6-5-5 6-5-5 ビットに分解でき、ここでは
64: // 上位下位ハーフワードの上位6ビットずつを合わせた12ビットを使う。
65: $bits12 = preg_replace("/(......)_.........._(......)_........../",
66: "$1$2", $bits);
67: $bits12 = preg_replace("/[^10n]/", "n", $bits12);
68: $newinst = array(
69: "bits" => $bits,
70: "bits12" => $bits12,
71: "name" => $name,
72: "text" => $text,
73: );
74: // $insttable[] に追加する。
75: // ただし bits が同じものがあれば text だけ追加。
76: if (isset($insttable[$bits])) {
77: $insttable[$bits]["text"] .= ";{$text}";
78: } else {
79: $insttable[$bits] = $newinst;
80: }
81: }
82: fclose($fp);
83:
84: // デバッグ表示
85: if (0) {
86: print "read_instruction\n";
87: foreach ($insttable as $inst) {
88: printf("%s|%s|%-10s|%s\n",
89: $inst["bits"], $inst["bits12"], $inst["name"], $inst["text"]);
90: }
91: }
92:
93: return $insttable;
94: }
95:
96: // $insttable を bit12 で展開する。
97: // これで bits12 には未確定部分がなくなる。
98: function expand($insttable)
99: {
100: do {
101: $expanded = false;
102: $inst2table = array();
103: foreach ($insttable as $inst) {
104: if (preg_match("/^([01]*)n(.*)/", $inst["bits12"], $m)) {
105: // $m[1] は先頭から確定部分
106: // $m[2] が未処理部分
107:
108: $inst2table[] = array(
109: "bits" => $inst["bits"],
110: "bits12" => "{$m[1]}0{$m[2]}",
111: "name" => $inst["name"],
112: "text" => $inst["text"],
113: );
114: $inst2table[] = array(
115: "bits" => $inst["bits"],
116: "bits12" => "{$m[1]}1{$m[2]}",
117: "name" => $inst["name"],
118: "text" => $inst["text"],
119: );
120: $expanded = true;
121: } else {
122: $inst2table[] = $inst;
123: }
124: }
125:
126: // 出来上がったのを差し替える
127: $insttable = $inst2table;
128: } while ($expanded);
129:
130: // デバッグ表示
131: if (0) {
132: print "expand\n";
133: foreach ($insttable as $inst) {
134: printf("%s| %s|%s\n",
135: $inst["bits12"], $inst["bits"], $inst["name"]);
136: }
137: }
138:
139: return $insttable;
140: }
141:
142: // $insttable を12ビット(4096個)の $op12table に展開。
143: // $optable = array(
144: // 0 => &$inst0,
145: // 1 => &$inst1,
146: // :
1.1.1.2 root 147: // 命令の存在するところだけ埋められる。
1.1 root 148: // )
149: function makeop12($insttable)
150: {
151: global $op12table;
152:
153: $op12table = array();
154: foreach ($insttable as $inst) {
155: $num12 = bindec($inst["bits12"]);
156: $op12table[$num12] = $inst;
157: }
158:
159: // デバッグ表示
160: if (0) {
161: print "makeop12\n";
162: for ($i = 0; $i < 4096; $i++) {
163: $b = str_repeat("0", 11) . decbin($i);
164: $b = substr($b, -12);
165: printf("%03x|%s|", $i, $b);
166:
167: if (isset($op12table[$i])) {
168: $inst = $op12table[$i];
169: print "{$inst["bits"]}|{$inst["name"]}\n";
170: } else {
171: print "illegal\n";
172: }
173: }
174: }
175: }
176:
177: // op12table から op12hash を作成
178: // op12table は [4096] => array(inst, inst, ...)
179: // op12hash は [name] => name のハッシュで、実際に使われてる関数名一覧。
180: function makeop12hash()
181: {
182: global $op12table;
183: global $op12hash;
184:
185: $op12hash = array();
186: foreach ($op12table as $inst) {
187: $name = $inst["name"];
188: $op12hash[$name] = $name;
189: }
190: }
191:
1.1.1.4 ! root 192: // ソースの雛形を出力
! 193: function output_cpp()
1.1 root 194: {
195: global $insttable;
196: global $op12table;
197: global $op12hash;
198:
199: $cpp = "";
200:
201: foreach ($op12hash as $name) {
202: // name から $inst を引く。うーん。
203: $inst = array();
204: foreach ($insttable as $i) {
205: if ($i["name"] == $name) {
206: $inst = $i;
207: break;
208: }
209: }
210:
211: $text = "";
212: if ($inst["text"] != "") {
213: $text = "\t{$inst["text"]}";
214: }
215:
216: // ソース
217: $cpp .= <<<__EOM__
218: // {$inst["bits"]}{$text}
219: OP_DEF({$name})
220: {
221: OP_FUNC(unimpl);
222: }
223:
224:
225: __EOM__;
226: }
227:
228: // ファイルに出力
229: write_file("ops.cpp.new", $cpp);
230: }
231:
232: // disasm 用の switch-case 文を出力
233: function output_switch()
234: {
235: global $op12table;
236:
237: // func2 は [1024] => name 形式で不当命令ブロックを抜いたもの
238: $func2 = array();
239: foreach ($op12table as $i => $inst) {
240: $func2[$i] = $inst["name"];
241: }
242:
243: $out = "";
244: for ($i = 0; $i < 4096; $i++) {
245: if (!isset($func2[$i])) {
246: continue;
247: }
248: $funcname = $func2[$i];
249:
250: $cases = array();
251: // この関数名を持つブロックに属する人全員のコメント集める。
252: // このブロック自身もここで集計するため $j は $i から始める。
253: for ($j = $i; $j < 4096; $j++) {
254: if (isset($func2[$j]) && $func2[$j] == $funcname) {
255: // case
256: $cases[] = $j;
257:
258: // 今のところコメントはないのでスルー
259:
260: // 集計したら消す
261: unset($func2[$j]);
262: }
263: }
264:
265: // case 部分の出力
266: // 4個くらいまでなら case 文を羅列、
267: // それ以上連続してたら範囲で出力。
268: $cont = true;
269: for ($k = 1; $k < count($cases); $k++) {
270: if ($cases[$k] - $cases[$k - 1] != 1) {
271: $cont = false;
272: break;
273: }
274: }
275: if ($cont == true && count($cases) > 4) {
276: $c = array_shift($cases);
277: $bits12 = str_repeat("0", 11) . decbin($c);
278: $bits12 = preg_replace("/.*(......)(......)/", "$1_$2", $bits12);
279: $out .= sprintf("\t case 0x%03x", $c);
280: $out .= "\t// {$bits12}\n";
281:
282: $c = array_pop($cases);
283: $bits12 = str_repeat("0", 11) . decbin($c);
284: $bits12 = preg_replace("/.*(......)(......)/", "$1_$2", $bits12);
285: $out .= sprintf("\t ... 0x%03x:", $c);
286: $out .= "\t// {$bits12}\n";
287: } else {
288: foreach ($cases as $c) {
289: $bits12 = str_repeat("0", 11) . decbin($c);
290: $bits12 = preg_replace("/.*(......)(......)/", "$1_$2",$bits12);
291: $out .= sprintf("\t case 0x%03x:", $c);
292: $out .= "\t// {$bits12}\n";
293: }
294: }
295: // 関数
296: $out .= "\t\tOP_FUNC({$funcname});\n";
297: $out .= "\t\tbreak;\n";
298: }
299: write_file("switch.inc.new", $out);
300: }
301:
302: // ヘッダを出力
303: function output_header()
304: {
305: global $op12hash;
306:
307: $out = "";
308: foreach ($op12hash as $name) {
309: $out .= "OP_PROTO({$name});\n";
310: }
311:
312: // ファイルに出力
313: write_file("ops.h.new", $out);
314: }
1.1.1.3 root 315:
1.1 root 316: // ファイル出力
317: function write_file($filename, $str)
318: {
319: $fp = fopen($filename, "w");
320: fwrite($fp, $str);
321: fclose($fp);
322:
323: print "Output: {$filename}\n";
324: }
1.1.1.3 root 325: ?>
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.