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

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

unix.superglobalmegacorp.com

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