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

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: ?>

unix.superglobalmegacorp.com

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