File:  [Isaki's NoNo m68k/m88k emulator] / nono / m680x0 / gencycles.php
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs
Wed Apr 29 17:05:40 2026 UTC (2 months, 3 weeks ago) by root
Branches: MAIN, Isaki
CVS tags: v027, v026, v025, v024, v023, HEAD
nono 1.3.0

<?php
//
// nono
// Copyright (C) 2025 nono project
// Licensed under nono-license.txt
//

// gencycles.php
//	cycles.txt から m680x0cycle.h を生成する。

	// 種類。
	$names = array(
		"030cc",
		"030ncc",
		"040",
	);
	define("ITEMS", count($names));

	// cycle_map = array(
	//	"andi_dn"	=> (2, 2, 1),
	//  :
	// );
	// alias_map = array(
	//  "ori_dn" => "andi_dn",
	// );
	$cycle_map = array();
	$alias_map = array();

	$infile = "cycles.txt";
	$fp = fopen($infile, "r");
	$lineno = 0;
	while (($line = fgets($fp)) !== false) {
		$lineno++;
		$line = preg_replace('/;.*$/', "", $line);
		$line = trim($line);
		if ($line == "") {
			continue;
		}

		$params = preg_split('/\s+/', $line, -1, PREG_SPLIT_NO_EMPTY);
		if (count($params) != 4) {
			print "{$infile}:{$lineno}: Syntax error: columns not 3\n";
			exit(1);
		}

		$new_symbol = $params[0];
		$cylist = array();
		$prev = 0;
		for ($i = 0; $i < ITEMS; $i++) {
			$val = $params[$i + 1];
			switch ($val) {
			 case "=":	// 左と同じ値 (主に 030 CC/NCC で使う)
			 case "?":	// 不明 (とりあえず適当に代入)
				$val = $prev;
				break;
			 case ".":	// 該当なし
				break;
			 default:
				if (is_int($val)) {
					print "{$infile}:{$lineno}: Syntax error\n";
					exit(1);
				}
				if ($val < -128 || $val > 127) {
					print "{$infile}:{$lineno}: " +
						  "Out of range: {$val} ({$new_symbol})\n";
					exit(1);
				}
				break;
			}
			$cylist[] = $val;
			$prev = $val;
		}

		$symbol = find_symbol($cylist);
		if ($symbol == "") {
			// 新規
			$cycle_map[$new_symbol] = $cylist;
		} else {
			// すでに同じサイクルを持つエントリがある
			$alias_map[$new_symbol] = $symbol;
		}
	}

	// なんとなく昇順にソート。
	uasort($cycle_map, function($a, $b) {
		if ($a[0] != $b[0]) {
			return $a[0] <=> $b[0];
		}
		if ($a[1] != $b[1]) {
			return $a[1] <=> $b[1];
		}
		return $a[2] <=> $b[2];
	});

	if (0) {
		var_dump($cycle_map);
		var_dump($alias_map);
	}

	// $cycle_map[idx] => array(type, type2, ...) を
	// $cycle_table[type][idx] にする。
	$cycle_table = array();
	foreach ($cycle_map as $symbol => $cylist) {
		for ($i = 0; $i < ITEMS; $i++) {
			$cycle_table[$i][] = $cylist[$i];
		}
	}
	if (0) {
		var_dump($cycle_table);
	}

	// ヘッダ出力
	$fhdr = fopen("m680x0cycle.h", "w");
	fprintf($fhdr, "// generated by {$argv[0]}\n");
	// ここは pragma once が使えない(使わないほうがいい)。
	fprintf($fhdr, "#ifndef M680X0_CYCLE_HEADER\n");
	fprintf($fhdr, "#define M680X0_CYCLE_HEADER\n");

	$i = 0;
	foreach ($cycle_map as $symbol => $cylist) {
		fprintf($fhdr,
			"static constexpr int cycidx_{$symbol} = {$i};\n");
		$i++;
	}
	fprintf($fhdr, "\n");
	foreach ($alias_map as $from => $to) {
		fprintf($fhdr,
			"static constexpr int cycidx_{$from} = cycidx_{$to};\n");
	}

	fprintf($fhdr, "#endif\n");
	fprintf($fhdr, "\n");
	fprintf($fhdr, "#if defined(M680X0_CYCLE_TABLE)\n");

	// ソース出力
	for ($i = 0; $i < ITEMS; $i++) {
		fprintf($fhdr, "/*static*/ const int8\n");
		fprintf($fhdr, "MPU680x0Device::cycle_table_{$names[$i]}[] = {\n");
		$cyarray = $cycle_table[$i];
		$j = 0;
		foreach ($cyarray as $cycle) {
			if (($j % 8) == 0) {
				fprintf($fhdr, "\t");
			}
			fprintf($fhdr, "%3d,", $cycle);
			if (($j % 8) == 7) {
				fprintf($fhdr, "\n");
			}
			$j++;
		}
		if (($j % 8) != 0) {
			fprintf($fhdr, "\n");
		}
		fprintf($fhdr, "};\n");
	};
	fprintf($fhdr, "#endif\n");
	fclose($fhdr);
?>
<?php
// cycle_map から $keylist を持つエントリを探す。
// 見付かればシンボルを返す。見付からなければ "" を返す。
function find_symbol($keylist)
{
	global $cycle_map;

	$n = count($keylist);
	foreach ($cycle_map as $symbol => $list) {
		$i = 0;
		for (; $i < $n; $i++) {
			if ($keylist[$i] != ".") {
				if ($keylist[$i] != $list[$i]) {
					break;
				}
			}
		}
		if ($i == $n) {
			return $symbol;
		}
	}
	return "";
}

function array_cmp($list1, $list2)
{
	if (count($list1) != count($list2)) {
		return false;
	}
	for ($i = 0; $i < count($list1); $i++) {
		if ($list1[$i] != $list2[$i]) {
			return false;
		}
	}
	return true;
}
?>

unix.superglobalmegacorp.com

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