Annotation of nono/m680x0/gentable.php, revision 1.1.1.3

1.1       root        1: <?php
                      2: //
                      3: // nono
                      4: // Copyright (C) 2014 [email protected]
1.1.1.2   root        5: // Copyright (C) 2020 nono project
                      6: // Licensed under nono-license.txt
                      7: //
                      8: 
1.1       root        9: //
                     10: // gentable.php
                     11: // inst*.txt からディスパッチャ部分を生成
                     12: //
                     13: //     switch10    switch-case (10bit) を出力
                     14: //     switch13        switch-case (13bit) を出力
                     15: //     goto10          computed goto (10bit) を出力
                     16: //     mmu8            MMU の switch-case (8bit) を出力
                     17: //
                     18: 
                     19:        if ($argc < 2) {
                     20:                usage();
                     21:        }
                     22: 
                     23:        init_ea();
1.1.1.3 ! root       24:        // 今の所逆アセンブラの分離度が低いので、
        !            25:        // コアも逆アセンブラも両方とも 68020/030 という扱いにしておく。
        !            26:        $mputype = "[23]";
1.1       root       27:        switch ($argv[1]) {
                     28:         case "switch10":
                     29:         case "switch13":
                     30:         case "goto10":
                     31:                if (preg_match("/10$/", $argv[1])) {
                     32:                        $nb = 10;
                     33:                } else {
                     34:                        $nb = 13;
                     35:                }
                     36:                $insttable = read_instructions($mputype, "instructions.txt");
                     37:                $insttable = expandDST($insttable);
                     38:                $insttable = expandSS($insttable);
                     39:                $insttable = expandCond($insttable);
                     40:                makeop16($insttable);
                     41:                $op10table = makeop10table();
                     42:                $op10func  = makeop10func($op10table);
                     43:                $op10hash  = makeop10hash($op10func);
                     44:                if (preg_match("/switch/", $argv[1])) {
                     45:                        output_switch($op10table, $op10func);
                     46:                } else {
                     47:                        output_goto($op10table, $op10func);
                     48:                }
                     49:                output_header($op10hash);
                     50:                break;
                     51: 
                     52:         case "mmu8":
                     53:                $nb = 8;
                     54:                $insttable = read_instructions($mputype, "instmmu.txt");
                     55:                makeop16($insttable);
                     56:                $op10table = makeop10table();
                     57:                $op10func  = makeop10func($op10table);
                     58:                $op10hash  = makeop10hash($op10func);
                     59:                output_switch($op10table, $op10func);
                     60:                output_header($op10hash);
                     61:                break;
                     62:         default:
                     63:                usage();
                     64:        }
                     65:        exit(0);
                     66: ?>
                     67: <?php
                     68: function usage()
                     69: {
                     70:        global $argv;
                     71: 
                     72:        print "Usage: {$argv[0]} switch10 | switch13\n";
                     73:        print "  input:  instruction.txt\n";
                     74:        print "  output: switch.h.new, ops.cpp.new, ops.h.new\n";
                     75:        print "Usage: {$argv[0]} mmu8\n";
                     76:        print "  input:  instmmu.txt\n";
                     77:        print "  output: \n";
                     78:        print "Usage: {$argv[0]} goto10\n";
                     79:        print "  input:  instruction.txt\n";
                     80:        print "  output: goto.h.new, ops.cpp.new, ops.h.new\n";
                     81:        exit(1);
                     82: }
                     83: 
                     84: function init_ea()
                     85: {
                     86:        global $ambits;
                     87: 
                     88:        // アドレッシングモードの展開パターン
                     89:        $ambits = array(
                     90:                "d"     => "000rrr",
                     91:                "a"     => "001rrr",
                     92:                "m"     => "010rrr",
                     93:                "+"     => "011rrr",
                     94:                "-"     => "100rrr",
                     95:                "r"     => "101rrr",
                     96:                "x"     => "110rrr",
                     97:                "w"     => "11100r",
                     98:                "p"     => "11101r",
                     99:                "i"     => "111100",
                    100:        );
                    101: }
                    102: 
                    103: // instructions.txt を読み込んで $insttable[] 配列にする
                    104: function read_instructions($mputype, $filename)
                    105: {
                    106:        $fp = fopen($filename, "r");
                    107:        if ($fp === false) {
                    108:                print "fopen failed: {$filename}\n";
                    109:                exit(1);
                    110:        }
                    111: 
                    112:        $insttable = array();
                    113: 
                    114:        while (($line = fgets($fp))) {
                    115:                $line = trim(preg_replace("/;.*/", "", $line));
                    116:                if ($line == "") {
                    117:                        continue;
                    118:                }
                    119: 
                    120:                // 1行はこんな感じ
                    121:                // 00000000SSmmmrrr  d.m+-rxw..  034  ori_S  ORI.S #<imm>,<ea>
                    122:                // 列は1つ以上のタブで区切られている。
                    123:                // $bits … 1ワード目のビットパターン
                    124:                // $addr … 対応しているアドレッシングモード
                    125:                // $mpu  … MPU ごとのサポート有無
                    126:                // $name … 関数名
                    127:                // $text … コメント
                    128: 
                    129:                list ($bits, $addr, $mpu, $name, $text) =
                    130:                        preg_split("/\t+/", $line, -1, PREG_SPLIT_NO_EMPTY);
                    131:                $name = trim($name);
                    132:                $text = trim($text);
                    133: 
                    134:                // ターゲット CPU の命令のみ対象にする
                    135:                if (preg_match("/{$mputype}/", $mpu) == false) {
                    136:                        continue;
                    137:                }
                    138: 
                    139:                $newinst = array(
                    140:                        "bits" => $bits,
                    141:                        "addr" => $addr,
                    142:                        "mpu"  => $mpu,
                    143:                        "name" => $name,
                    144:                        "text" => $text,
                    145:                );
                    146:                // $insttable[] に追加する。
                    147:                // ただし bits が同じものがあれば text だけ追加。
                    148:                if (isset($insttable[$bits])) {
                    149:                        $insttable[$bits]["text"] .= ";{$text}";
                    150:                } else {
                    151:                        $insttable[$bits] = $newinst;
                    152:                }
                    153:        }
                    154:        fclose($fp);
                    155: 
                    156:        // デバッグ表示
                    157:        if (0) {
                    158:                print "read_instruction\n";
                    159:                foreach ($insttable as $inst) {
                    160:                        printf("%s|%s|%-14s|%s\n",
                    161:                                $inst["bits"], $inst["addr"], $inst["name"], $inst["text"]);
                    162:                }
                    163:        }
                    164: 
                    165:        return $insttable;
                    166: }
                    167: 
                    168: // $insttable のうち MOVE の DST を展開する
                    169: function expandDST($insttable)
                    170: {
                    171:        $dst = array(
                    172:                array("xxx000", "dn",   "Dx"),
                    173:                array("xxx010", "anin", "(Ax)"),
                    174:                array("xxx011", "anpi", "(Ax)+"),
                    175:                array("xxx100", "anpd", "-(Ax)"),
                    176:                array("xxx101", "andi", "d16(Ax)"),
                    177:                array("xxx110", "anix", "(Ax,IX)"),
                    178:                array("000111", "absw", "Abs.W"),
                    179:                array("001111", "absl", "Abs.L"),
                    180:        );
                    181:        $inst2table = array();
                    182:        foreach ($insttable as $inst) {
                    183:                if (preg_match("/RRRMMM/", $inst["bits"])) {
                    184:                        foreach ($dst as $d) {
                    185:                                $inst2 = $inst;
                    186:                                $inst2["bits"] = preg_replace("/RRRMMM/", $d[0], $inst["bits"]);
                    187:                                $inst2["name"] = preg_replace("/DD/", $d[1], $inst["name"]);
                    188:                                $inst2["text"] = preg_replace("/DD/", $d[2], $inst["text"]);
                    189: 
                    190:                                $inst2table[] = $inst2;
                    191:                        }
                    192:                } else {
                    193:                        $inst2table[] = $inst;
                    194:                }
                    195:        }
                    196: 
                    197:        // デバッグ表示
                    198:        if (0) {
                    199:                print "expandDST\n";
                    200:                foreach ($inst2table as $inst) {
                    201:                        printf("%s|%s|%-14s|%s\n",
                    202:                                $inst["bits"], $inst["addr"], $inst["name"], $inst["text"]);
                    203:                }
                    204:        }
                    205: 
                    206:        return $inst2table;
                    207: }
                    208: 
                    209: // $insttable の SS と s を展開する
                    210: // これらは必ず上位10ビット内にあるので (というか下位6ビット以内に現れる
                    211: // やつはテキストにする時点で手動で展開してあるので)、
                    212: // サイズ別の関数に展開できる。
                    213: function expandSS($insttable)
                    214: {
                    215:        $s3 = array(
                    216:                array("00", "_b",       ".B"),
                    217:                array("01", "_w",       ".W"),
                    218:                array("10", "_l",       ".L"),
                    219:        );
                    220:        $s2 = array(
                    221:                array("0",      "_w",   ".W"),
                    222:                array("1",      "_l",   ".L"),
                    223:        );
                    224: 
                    225:        $inst2table = array();
                    226:        foreach ($insttable as $inst) {
                    227:                if (preg_match("/SS/", $inst["bits"])) {
                    228:                        foreach ($s3 as $s) {
                    229:                                $inst2 = $inst;
                    230:                                $inst2["bits"] = preg_replace("/SS/", $s[0], $inst["bits"]);
                    231:                                $inst2["name"] = preg_replace("/_S/", $s[1], $inst["name"]);
                    232:                                $inst2["text"] = preg_replace("/\.S/", $s[2], $inst["text"]);
                    233: 
                    234:                                $inst2table[] = $inst2;
                    235:                        }
                    236:                } else if (preg_match("/s/", $inst["bits"])) {
                    237:                        foreach ($s2 as $s) {
                    238:                                $inst2 = $inst;
                    239:                                $inst2["bits"] = preg_replace("/s/", $s[0], $inst["bits"]);
                    240:                                $inst2["name"] = preg_replace("/_S/", $s[1], $inst["name"]);
                    241:                                $inst2["text"] = preg_replace("/\.S/", $s[2], $inst["text"]);
                    242: 
                    243:                                $inst2table[] = $inst2;
                    244:                        }
                    245:                } else {
                    246:                        $inst2table[] = $inst;
                    247:                }
                    248:        }
                    249: 
                    250:        // デバッグ表示
                    251:        if (0) {
                    252:                print "expandSS\n";
                    253:                foreach ($inst2table as $inst) {
                    254:                        printf("%s|%s|%-14s|%s\n",
                    255:                                $inst["bits"], $inst["addr"], $inst["name"], $inst["text"]);
                    256:                }
                    257:        }
                    258: 
                    259:        return $inst2table;
                    260: }
                    261: 
                    262: // $insttable の cccc を展開する。
                    263: function expandCond($insttable)
                    264: {
                    265:        $cccc = array(
                    266:                "0000" => "t",
                    267:                "0001" => "f",
                    268:                "0010" => "hi",
                    269:                "0011" => "ls",
                    270:                "0100" => "cc",
                    271:                "0101" => "cs",
                    272:                "0110" => "ne",
                    273:                "0111" => "eq",
                    274:                "1000" => "vc",
                    275:                "1001" => "vs",
                    276:                "1010" => "pl",
                    277:                "1011" => "mi",
                    278:                "1100" => "ge",
                    279:                "1101" => "lt",
                    280:                "1110" => "gt",
                    281:                "1111" => "le",
                    282:        );
                    283:        $inst2table = array();
                    284:        foreach ($insttable as $inst) {
                    285:                if (preg_match("/cccc/", $inst["bits"])) {
                    286:                        foreach ($cccc as $cbit => $cname) {
                    287:                                $uname = strtoupper($cname);
                    288:                                $inst2 = $inst;
                    289:                                $inst2["bits"] = preg_replace("/cccc/", $cbit, $inst["bits"]);
                    290:                                $inst2["name"] = preg_replace("/cc/", $cname, $inst["name"]);
                    291:                                $inst2["text"] = preg_replace("/cc/", $uname, $inst["text"]);
                    292:                                $inst2table[] = $inst2;
                    293:                        }
                    294:                } else {
                    295:                        $inst2table[] = $inst;
                    296:                }
                    297:        }
                    298: 
                    299:        // デバッグ表示
                    300:        if (0) {
                    301:                print "expandCond\n";
                    302:                foreach ($inst2table as $inst) {
                    303:                        printf("%s|%s|%-14s|%s\n",
                    304:                                $inst["bits"], $inst["addr"], $inst["name"], $inst["text"]);
                    305:                }
                    306:        }
                    307: 
                    308:        return $inst2table;
                    309: }
                    310: 
                    311: // insttable を16ビットの op16table に展開。
                    312: // $optable = array(
                    313: //     0 => &$inst0,
                    314: //     1 => &$inst1, ...
                    315: // )
                    316: function makeop16($insttable)
                    317: {
                    318:        global $op16table;
                    319: 
                    320:        $op16table = array();
                    321: 
                    322:        foreach ($insttable as $inst) {
                    323:                makeop16_sub($inst, $inst["bits"]);
                    324:        }
                    325: 
                    326:        // デバッグ表示
                    327:        if (0) {
                    328:                print "makeop16\n";
                    329:                for ($i = 0; $i < 65536; $i++) {
                    330:                        $b = str_repeat("0", 15) . decbin($i);
                    331:                        $b = substr($b, -16);
                    332:                        printf("%04x|%s|", $i, $b);
                    333: 
                    334:                        if (isset($op16table[$i])) {
                    335:                                $inst = $op16table[$i];
                    336:                                printf("%s|%-14s|%s\n",
                    337:                                        $inst["bits"], $inst["name"], $inst["text"]);
                    338:                        } else {
                    339:                                printf("illegal\n");
                    340:                        }
                    341:                }
                    342:        }
                    343: }
                    344: 
                    345: // inst を1ビットずつ展開する再帰関数
                    346: // lv は再帰レベル (デバッグ用)
                    347: function makeop16_sub($inst, $bits, $lv = 0)
                    348: {
                    349:        global $op16table;
                    350:        global $ambits;
                    351: 
                    352:        // $pos は bits の 0/1 でない最初の文字の位置
                    353:        $pos = strspn($bits, "01");
                    354:        if ($pos == 16) {
                    355:                // 0/1 しか現れていないので確定
                    356:                // $optable に代入
                    357:                $num16 = bindec($bits);
                    358:                $op16table[$num16] = $inst;
                    359:        } else if (substr($bits, 10) == "mmmrrr") {
                    360:                // アドレッシングモードによって展開 (いるかな?)
                    361:                $head = substr($bits, 0, 10);
                    362:                for ($i = 0; $i < strlen($inst["addr"]); $i++) {
                    363:                        $a = substr($inst["addr"], $i, 1);
                    364:                        if (isset($ambits[$a])) {
                    365:                                makeop16_sub($inst, "{$head}{$ambits[$a]}", $lv + 1);
                    366:                        }
                    367:                }
                    368:        } else {
                    369:                // pos 番目の文字を 0 と 1 に変えて再帰実行
                    370:                $head = substr($bits, 0, $pos);
                    371:                $tail = substr($bits, $pos + 1);
                    372:                makeop16_sub($inst, "{$head}0{$tail}", $lv + 1);
                    373:                makeop16_sub($inst, "{$head}1{$tail}", $lv + 1);
                    374:        }
                    375: }
                    376: 
                    377: // 16ビットテーブルから $nb (10 or 7) ビットテーブルを作成
                    378: function makeop10table()
                    379: {
                    380:        global $op16table;
                    381:        global $nb;
                    382: 
                    383:        // 1ブロックあたりの命令数 ($nb=10 なら 64)
                    384:        $ipb = 2 ** (16 - $nb);
                    385: 
                    386:        $op10table = array();
                    387:        for ($i = 0; $i < 2 ** $nb; $i++) {
                    388:                $op10table[$i] = array();
                    389:        }
                    390: 
                    391:        for ($i = 0; $i < 65536; $i++) {
                    392:                if (!isset($op16table[$i])) {
                    393:                        continue;
                    394:                }
                    395:                $inst = $op16table[$i];
                    396:                $j = $i / $ipb;
                    397: 
                    398:                // op10table[j][] にすでに同じエントリがなければ、追加
                    399:                $found = false;
                    400:                foreach ($op10table[$j] as $ji) {
                    401:                        if ($inst["bits"] == $ji["bits"]) {
                    402:                                $found = true;
                    403:                                break;
                    404:                        }
                    405:                }
                    406:                if (!$found) {
                    407:                        $op10table[$j][] = $inst;
                    408:                }
                    409:        }
                    410: 
                    411:        // デバッグ用
                    412:        if (0) {
                    413:                print "makeop10table\n";
                    414:                foreach ($op10table as $j => $arr) {
                    415:                        printf("0x%04x|", $j, $j * $ipb);
                    416:                        foreach ($arr as $inst) {
                    417:                                printf(" %s", $inst["name"]);
                    418:                        }
                    419:                        print "\n";
                    420:                }
                    421:        }
                    422: 
                    423:        return $op10table;
                    424: }
                    425: 
                    426: // op10table から op10func を作成
                    427: // op10table は [1024] => array(inst, inst, ...)
                    428: // op10func は [1024] => 代表name
                    429: function makeop10func($op10table)
                    430: {
                    431:        global $nb;
                    432: 
                    433:        $op10func = array();
                    434:        for ($i = 0; $i < 2 ** $nb; $i++) {
                    435:                $op10func[$i] = "";
                    436:        }
                    437: 
                    438:        foreach ($op10table as $i => $arr) {
                    439:                if (count($arr) == 0) {
                    440:                        $op10func[$i] = "illegal";
                    441:                        continue;
                    442:                }
                    443: 
                    444:                // 代表関数はこのブロックの中で最多数なもの。
                    445:                $funcname = "";
                    446:                $minbits = (16 - $nb) + 1;
                    447:                foreach ($arr as $inst) {
                    448:                        // fixed は bits の末尾(16-nb)ビットのうち "0" と "1" の合計数
                    449:                        $chs = count_chars(substr($inst["bits"], $nb), 0);
                    450:                        $fixed = $chs[0x30] + $chs[0x31];
                    451:                        // fixed が小さい = 出力した命令の総数が大きい、なので採用
                    452:                        if ($minbits > $fixed) {
                    453:                                $minbits = $fixed;
                    454:                                $funcname = $inst["name"];
                    455:                        }
                    456:                }
                    457: 
                    458:                $op10func[$i] = $funcname;
                    459:        }
                    460: 
                    461:        // デバッグ用
                    462:        if (0) {
                    463:                print "makeop10func\n";
                    464:                foreach ($op10func as $i => $name) {
                    465:                        printf("[%4d] %04x {$name}\n", $i, $i * 64);
                    466:                }
                    467:        }
                    468: 
                    469:        return $op10func;
                    470: }
                    471: 
                    472: // op10hash は [代表name] => 代表name のハッシュ
                    473: // 実際に使われてる関数名一覧になる。
                    474: function makeop10hash($op10func)
                    475: {
                    476:        $op10hash = array();
                    477:        foreach ($op10func as $name) {
                    478:                $op10hash[$name] = $name;
                    479:        }
                    480: 
                    481:        return $op10hash;
                    482: }
                    483: 
                    484: // switch 本体とソースの元を出力
                    485: function output_switch($op10table, $op10func)
                    486: {
                    487:        global $nb;
                    488: 
                    489:        $shift = 16 - $nb;
                    490:        $ipb = 2 ** (16 - $nb);
                    491: 
                    492:        $func2 = $op10func;
                    493: 
                    494:        // 先に不当命令ブロックだけ抜いておく
                    495:        $illegals = array();
                    496:        for ($i = 0; $i < 2 ** $nb; $i++) {
                    497:                if (isset($func2[$i]) && $func2[$i] == "illegal") {
                    498:                        $illegals[$i] = $i;
                    499:                        unset($func2[$i]);
                    500:                }
                    501:        }
                    502: 
                    503:        $out = "";
                    504:        $cpp = "";
                    505:        for ($i = 0; $i < 2 ** $nb; $i++) {
                    506:                if (!isset($func2[$i])) {
                    507:                        continue;
                    508:                }
                    509:                $funcname = $func2[$i];
                    510: 
                    511:                $cases = array();
                    512:                $comments = array();
                    513: 
                    514:                // この関数名をもつブロックに属する人全員のコメントを集める。
                    515:                // このブロック自身もここで集計するため $j は $i から始める。
                    516:                for ($j = $i; $j < 2 ** $nb; $j++) {
                    517:                        if (isset($func2[$j]) && $func2[$j] == $funcname) {
                    518:                                foreach ($op10table[$j] as $inst) {
                    519:                                        // case
                    520:                                        $cases[$j] = $j;
                    521:                                        // コメント
                    522:                                        // 同一 bits に別の命令が割り当てられているケースは
                    523:                                        // ここで2行のコメントに分解
                    524:                                        foreach (split(";", $inst["text"]) as $text) {
                    525:                                                $comm = "{$inst["bits"]}\t{$text}";
                    526:                                                $comments[$comm] = $comm;
                    527:                                        }
                    528:                                }
                    529:                                // 集計したら消す
                    530:                                unset($func2[$j]);
                    531:                        }
                    532:                }
                    533:                // case
                    534:                foreach ($cases as $c) {
                    535:                        $out .= sprintf("\t case (0x%04x >> ${shift}):\n", $c * $ipb);
                    536:                }
                    537:                // コメント
                    538:                foreach ($comments as $comm) {
                    539:                        if ($nb == 8) {
                    540:                                // というか MMU というべきか
                    541:                                preg_match("/(...)(.....)(...)(.*)/", $comm, $m);
                    542:                                $comm1 = "%{$m[1]}_{$m[2]}_{$m[3]}_{$m[4]}";
                    543:                        } else {
                    544:                                // 第1ワードというべきか
                    545:                                preg_match("/(....)(......)(.*)/", $comm, $m);
                    546:                                $comm1 = "%{$m[1]}_{$m[2]}_{$m[3]}";
                    547:                        }
                    548:                        $out .= "\t\t// {$comm1}\n";
                    549:                        $cpp .= "// {$comm1}\n";
                    550:                }
                    551:                // 関数
                    552:                $out .= "\t\tOP_FUNC({$funcname});\n";
                    553:                $out .= "\t\tbreak;\n";
                    554: 
                    555:                // ソース
                    556:                $cpp .= output_func($funcname);
                    557:        }
                    558: 
                    559:        // 不当命令ブロックを出力
                    560:        foreach ($illegals as $i) {
                    561:                $out .= sprintf("\t case (0x%04x >> ${shift}):\n", $i * $ipb);
                    562:        }
                    563:        $out .= "\t\tOP_FUNC(illegal);\n";
                    564:        $out .= "\t\tbreak;\n";
                    565: 
                    566:        // 不当命令 (ILLEGAL 命令ではないので最終的にどうするかはある)
                    567:        $cpp .= "// illegal instructions\n";
                    568:        $cpp .= output_func("illegal");
                    569: 
                    570:        // ファイルに出力
                    571:        write_file("switch.h.new", $out);
                    572:        write_file("ops.cpp.new", $cpp);
                    573: }
                    574: 
                    575: // computed-goto 本体とソースの元を出力
                    576: function output_goto($op10table, $op10func)
                    577: {
                    578:        global $nb;
                    579: 
                    580:        $shift = 16 - $nb;
                    581:        $ipb = 2 ** (16 - $nb);
                    582: 
                    583:        // ジャンプテーブルを作成
                    584:        $table = "\t\tstatic const void *jumptable[] = {\n";
                    585:        for ($i = 0; $i < 2 ** $nb; $i++) {
                    586:                $table .= sprintf("\t\t\t/* $%04X */&&label_goto_%s,\n",
                    587:                        $i * $ipb, $op10func[$i]);
                    588:        }
                    589:        $table .= "\t\t};\n";
                    590: 
                    591:        $func2 = $op10func;
                    592: 
                    593:        // 先に不当命令ブロックだけ抜いておく
                    594:        $illegals = array();
                    595:        for ($i = 0; $i < 2 ** $nb; $i++) {
                    596:                if (isset($func2[$i]) && $func2[$i] == "illegal") {
                    597:                        $illegals[$i] = $i;
                    598:                        unset($func2[$i]);
                    599:                }
                    600:        }
                    601: 
                    602:        $out = "";
                    603:        $cpp = "";
                    604: 
                    605:        $out .= "\t\tJUMP;\n";
                    606: 
                    607:        for ($i = 0; $i < 2 ** $nb; $i++) {
                    608:                if (!isset($func2[$i])) {
                    609:                        // 不当命令ブロック
                    610:                        continue;
                    611:                }
                    612:                $funcname = $func2[$i];
                    613: 
                    614:                $cases = array();
                    615:                $comments = array();
                    616: 
                    617:                // この関数名をもつブロックに属する人全員のコメントを集める。
                    618:                // このブロック自身もここで集計するため $j は $i から始める。
                    619:                for ($j = $i; $j < 2 ** $nb; $j++) {
                    620:                        if (isset($func2[$j]) && $func2[$j] == $funcname) {
                    621:                                foreach ($op10table[$j] as $inst) {
                    622:                                        // case
                    623:                                        $cases[$j] = $j;
                    624:                                        // コメント
                    625:                                        // 同一 bits に別の命令が割り当てられているケースは
                    626:                                        // ここで2行のコメントに分解
                    627:                                        foreach (split(";", $inst["text"]) as $text) {
                    628:                                                $comm = "{$inst["bits"]}\t{$text}";
                    629:                                                $comments[$comm] = $comm;
                    630:                                        }
                    631:                                }
                    632:                                // 集計したら消す
                    633:                                unset($func2[$j]);
                    634:                        }
                    635:                }
                    636:                // ラベル
                    637:                $out .= "\t label_goto_{$funcname}:\n";
                    638:                // コメント
                    639:                foreach ($comments as $comm) {
                    640:                        if ($nb == 8) {
                    641:                                // というか MMU というべきか
                    642:                                preg_match("/(...)(.....)(...)(.*)/", $comm, $m);
                    643:                                $comm1 = "%{$m[1]}_{$m[2]}_{$m[3]}_{$m[4]}";
                    644:                        } else {
                    645:                                // 第1ワードというべきか
                    646:                                preg_match("/(....)(......)(.*)/", $comm, $m);
                    647:                                $comm1 = "%{$m[1]}_{$m[2]}_{$m[3]}";
                    648:                        }
                    649:                        $out .= "\t\t// {$comm1}\n";
                    650:                        $cpp .= "// {$comm1}\n";
                    651:                }
                    652:                // 関数
                    653:                $out .= "\t\tOP_FUNC({$funcname});\n";
                    654:                $out .= "\t\tCHECK_AND_JUMP;\n";
                    655: 
                    656:                // ソース
                    657:                $cpp .= output_func($funcname);
                    658:        }
                    659: 
                    660:        // 不当命令ブロックを出力
                    661:        $out .= "\t label_goto_illegal:\n";
                    662:        $out .= "\t\tOP_FUNC(illegal);\n";
                    663:        $out .= "\t\tCHECK_AND_JUMP;\n";
                    664: 
                    665:        // ファイルに出力
                    666:        write_file("goto.h.new", $table . $out);
                    667:        write_file("ops.cpp.new", $cpp);
                    668: }
                    669: 
                    670: // 関数ソースを出力
                    671: function output_func($name)
                    672: {
                    673:        $cpp = "";
                    674:        $cpp .= "OP_DEF({$name})\n";
                    675:        $cpp .= "{\n";
                    676:        $cpp .= "\tOP_FUNC(unimpl);\n";
                    677:        $cpp .= "}\n";
                    678:        $cpp .= "\n";
                    679: 
                    680:        return $cpp;
                    681: }
                    682: 
                    683: // ヘッダを出力
                    684: function output_header($op10hash)
                    685: {
                    686:        $out = "";
                    687:        foreach ($op10hash as $name) {
                    688:                $out .= "OP_PROTO({$name});\n";
                    689:        }
                    690: 
                    691:        // ファイルに出力
                    692:        write_file("ops.h.new", $out);
                    693: }
                    694: 
                    695: // ファイル出力
                    696: function write_file($filename, $str)
                    697: {
                    698:        $fp = fopen($filename, "w");
                    699:        fwrite($fp, $str);
                    700:        fclose($fp);
                    701: 
                    702:        print "Output: {$filename}\n";
                    703: }

unix.superglobalmegacorp.com

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