Annotation of nono/m88xx0/gentable.php, revision 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.