--- nono/m680x0/gentable.php 2026/04/29 17:04:34 1.1.1.2 +++ nono/m680x0/gentable.php 2026/04/29 17:05:57 1.1.1.9 @@ -1,7 +1,7 @@ "t", - "0001" => "f", - "0010" => "hi", - "0011" => "ls", - "0100" => "cc", - "0101" => "cs", - "0110" => "ne", - "0111" => "eq", - "1000" => "vc", - "1001" => "vs", - "1010" => "pl", - "1011" => "mi", - "1100" => "ge", - "1101" => "lt", - "1110" => "gt", - "1111" => "le", +// $insttable の CCC (cpID) を展開する。 +// cpID 0 は MMU、1 は FSAVE/FRESTORE なので展開しない。 +// cpID 2 は表側で対応してあるのでこちらでは展開しない。 +function expandCCC($insttable) +{ + $c3 = array( + "011", + "100", + "101", + "110", + "111", ); + $inst2table = array(); foreach ($insttable as $inst) { - if (preg_match("/cccc/", $inst["bits"])) { - foreach ($cccc as $cbit => $cname) { - $uname = strtoupper($cname); + if (preg_match("/CCC/", $inst["bits"])) { + foreach ($c3 as $c) { $inst2 = $inst; - $inst2["bits"] = preg_replace("/cccc/", $cbit, $inst["bits"]); - $inst2["name"] = preg_replace("/cc/", $cname, $inst["name"]); - $inst2["text"] = preg_replace("/cc/", $uname, $inst["text"]); + $inst2["bits"] = preg_replace("/CCC/", $c, $inst["bits"]); $inst2table[] = $inst2; } } else { @@ -296,7 +277,7 @@ function expandCond($insttable) // デバッグ表示 if (0) { - print "expandCond\n"; + print "expandCCC\n"; foreach ($inst2table as $inst) { printf("%s|%s|%-14s|%s\n", $inst["bits"], $inst["addr"], $inst["name"], $inst["text"]); @@ -334,7 +315,7 @@ function makeop16($insttable) printf("%s|%-14s|%s\n", $inst["bits"], $inst["name"], $inst["text"]); } else { - printf("illegal\n"); + printf("n/a\n"); } } } @@ -410,7 +391,7 @@ function makeop10table() if (0) { print "makeop10table\n"; foreach ($op10table as $j => $arr) { - printf("0x%04x|", $j, $j * $ipb); + printf("[0x%04x] $%04x|", $j, $j * $ipb); foreach ($arr as $inst) { printf(" %s", $inst["name"]); } @@ -435,7 +416,7 @@ function makeop10func($op10table) foreach ($op10table as $i => $arr) { if (count($arr) == 0) { - $op10func[$i] = "illegal"; + $op10func[$i] = "n/a"; continue; } @@ -473,12 +454,37 @@ function makeop10hash($op10func) { $op10hash = array(); foreach ($op10func as $name) { - $op10hash[$name] = $name; + if ($name != "n/a") { + $op10hash[$name] = $name; + } } return $op10hash; } +// コメントをいい感じにソートしたい。 +// $a, $b は "%1111_000000_mmmrrr dam+-rxwpi 034 OPNAME" みたいなやつ。 +// これのビットパターン部分でソート。ただし英字は "0"/"1" より前。 +// ビットパターンが同じなら出現順を維持(ソースファイルに記載の順)。 +function cmp_comments($comm_a, $comm_b) +{ + $va = preg_split('/\s+/', $comm_a); + $vb = preg_split('/\s+/', $comm_b); + + $a = $va[0]; + $b = $vb[0]; + + // 同じなら a, b の順。 + if ($a == $b) { + return -1; + } + + // "0"/"1" を英字の後ろにして比較。 + $a = str_replace(array("0","1"), array("{","}"), $a); + $b = str_replace(array("0","1"), array("{","}"), $b); + return $a <=> $b; +} + // switch 本体とソースの元を出力 function output_switch($op10table, $op10func) { @@ -490,10 +496,10 @@ function output_switch($op10table, $op10 $func2 = $op10func; // 先に不当命令ブロックだけ抜いておく - $illegals = array(); + $not_assigned = array(); for ($i = 0; $i < 2 ** $nb; $i++) { - if (isset($func2[$i]) && $func2[$i] == "illegal") { - $illegals[$i] = $i; + if (isset($func2[$i]) && $func2[$i] == "n/a") { + $not_assigned[$i] = $i; unset($func2[$i]); } } @@ -519,8 +525,9 @@ function output_switch($op10table, $op10 // コメント // 同一 bits に別の命令が割り当てられているケースは // ここで2行のコメントに分解 - foreach (split(";", $inst["text"]) as $text) { - $comm = "{$inst["bits"]}\t{$text}"; + foreach (preg_split("/;/", $inst["text"]) as $text) { + $comm = "{$inst["bits"]} {$inst["addr"]} " + . "{$inst["mpu"]}\t{$text}"; $comments[$comm] = $comm; } } @@ -533,6 +540,7 @@ function output_switch($op10table, $op10 $out .= sprintf("\t case (0x%04x >> ${shift}):\n", $c * $ipb); } // コメント + usort($comments, "cmp_comments"); foreach ($comments as $comm) { if ($nb == 8) { // というか MMU というべきか @@ -543,8 +551,11 @@ function output_switch($op10table, $op10 preg_match("/(....)(......)(.*)/", $comm, $m); $comm1 = "%{$m[1]}_{$m[2]}_{$m[3]}"; } - $out .= "\t\t// {$comm1}\n"; $cpp .= "// {$comm1}\n"; + // ヘッダに出力するのはビットと名前だけに短縮。 + $comm2 = preg_replace('/(\S+)\s+\S+\s+\S+\s+(.*)/', "$1\t$2", + $comm1); + $out .= "\t\t// {$comm2}\n"; } // 関数 $out .= "\t\tOP_FUNC({$funcname});\n"; @@ -554,15 +565,15 @@ function output_switch($op10table, $op10 $cpp .= output_func($funcname); } - // 不当命令ブロックを出力 - foreach ($illegals as $i) { + // 不当命令のブロックを出力 + foreach ($not_assigned as $i) { $out .= sprintf("\t case (0x%04x >> ${shift}):\n", $i * $ipb); } $out .= "\t\tOP_FUNC(illegal);\n"; $out .= "\t\tbreak;\n"; - // 不当命令 (ILLEGAL 命令ではないので最終的にどうするかはある) - $cpp .= "// illegal instructions\n"; + // 不当命令 (ILLEGAL 命令と F ライン命令と不当命令の合流先…) + $cpp .= "// illegal (or not-assigned) instructions\n"; $cpp .= output_func("illegal"); // ファイルに出力 @@ -570,101 +581,6 @@ function output_switch($op10table, $op10 write_file("ops.cpp.new", $cpp); } -// computed-goto 本体とソースの元を出力 -function output_goto($op10table, $op10func) -{ - global $nb; - - $shift = 16 - $nb; - $ipb = 2 ** (16 - $nb); - - // ジャンプテーブルを作成 - $table = "\t\tstatic const void *jumptable[] = {\n"; - for ($i = 0; $i < 2 ** $nb; $i++) { - $table .= sprintf("\t\t\t/* $%04X */&&label_goto_%s,\n", - $i * $ipb, $op10func[$i]); - } - $table .= "\t\t};\n"; - - $func2 = $op10func; - - // 先に不当命令ブロックだけ抜いておく - $illegals = array(); - for ($i = 0; $i < 2 ** $nb; $i++) { - if (isset($func2[$i]) && $func2[$i] == "illegal") { - $illegals[$i] = $i; - unset($func2[$i]); - } - } - - $out = ""; - $cpp = ""; - - $out .= "\t\tJUMP;\n"; - - for ($i = 0; $i < 2 ** $nb; $i++) { - if (!isset($func2[$i])) { - // 不当命令ブロック - continue; - } - $funcname = $func2[$i]; - - $cases = array(); - $comments = array(); - - // この関数名をもつブロックに属する人全員のコメントを集める。 - // このブロック自身もここで集計するため $j は $i から始める。 - for ($j = $i; $j < 2 ** $nb; $j++) { - if (isset($func2[$j]) && $func2[$j] == $funcname) { - foreach ($op10table[$j] as $inst) { - // case - $cases[$j] = $j; - // コメント - // 同一 bits に別の命令が割り当てられているケースは - // ここで2行のコメントに分解 - foreach (split(";", $inst["text"]) as $text) { - $comm = "{$inst["bits"]}\t{$text}"; - $comments[$comm] = $comm; - } - } - // 集計したら消す - unset($func2[$j]); - } - } - // ラベル - $out .= "\t label_goto_{$funcname}:\n"; - // コメント - foreach ($comments as $comm) { - if ($nb == 8) { - // というか MMU というべきか - preg_match("/(...)(.....)(...)(.*)/", $comm, $m); - $comm1 = "%{$m[1]}_{$m[2]}_{$m[3]}_{$m[4]}"; - } else { - // 第1ワードというべきか - preg_match("/(....)(......)(.*)/", $comm, $m); - $comm1 = "%{$m[1]}_{$m[2]}_{$m[3]}"; - } - $out .= "\t\t// {$comm1}\n"; - $cpp .= "// {$comm1}\n"; - } - // 関数 - $out .= "\t\tOP_FUNC({$funcname});\n"; - $out .= "\t\tCHECK_AND_JUMP;\n"; - - // ソース - $cpp .= output_func($funcname); - } - - // 不当命令ブロックを出力 - $out .= "\t label_goto_illegal:\n"; - $out .= "\t\tOP_FUNC(illegal);\n"; - $out .= "\t\tCHECK_AND_JUMP;\n"; - - // ファイルに出力 - write_file("goto.h.new", $table . $out); - write_file("ops.cpp.new", $cpp); -} - // 関数ソースを出力 function output_func($name) { @@ -685,6 +601,7 @@ function output_header($op10hash) foreach ($op10hash as $name) { $out .= "OP_PROTO({$name});\n"; } + $out .= "OP_PROTO(illegal);\n"; // ファイルに出力 write_file("ops.h.new", $out); @@ -699,3 +616,4 @@ function write_file($filename, $str) print "Output: {$filename}\n"; } +?>