Annotation of nono/m88xx0/gentable.php, revision 1.1.1.1

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.