--- nono/m680x0/testacc.cpp 2026/04/29 17:04:28 1.1 +++ nono/m680x0/testacc.cpp 2026/04/29 17:05:30 1.1.1.7 @@ -1,32 +1,52 @@ // // nono -// Copyright (C) 2017 isaki@NetBSD.org +// Copyright (C) 2020 nono project +// Licensed under nono-license.txt // -#include "header.h" +#include "mpu680x0.h" +#include "m680x0acc.h" #include -#include "m68030core.h" -#include "m68030acc.h" +#include // パフォーマンステストの秒数 #define PERF_SEC (3) -void usage(); +[[noreturn]] void usage(); -m68kcpu *cpu; - -int argc; // getopt(3) 処理後の argc -const char **argv; // getopt(3) 処理後の argv -const char *testname; // 現在のテスト名 -int total_errcnt; // 総エラー数 -int errcnt; // 現在のセクションのエラー数 -char where[256]; // エラー発生箇所 -volatile int perf_signaled; // パフォーマンス測定用 -struct timeval perf_start; // パフォーマンス測定開始時刻 -uint64 perf_count; // パフォーマンス測定用。処理回数 +static int argc; // getopt(3) 処理後の argc +static char **argv; // getopt(3) 処理後の argv +static const char *testname; // 現在のテスト名 +static int total_errcnt; // 総エラー数 +static int errcnt; // 現在のセクションのエラー数 +static char where[256]; // エラー発生箇所 +static volatile int perf_signaled; // パフォーマンス測定用 +static struct timeval perf_start; // パフォーマンス測定開始時刻 +static uint64 perf_count; // パフォーマンス測定用。処理回数 + +// value を16進数で指定のビット数分の文字列にする +static std::string +hex(uint32 value, int sz) +{ + char buf[32]; + + switch (sz) { + case 8: + snprintf(buf, sizeof(buf), "%02x", value); + break; + case 16: + snprintf(buf, sizeof(buf), "%04x", value); + break; + case 32: + default: + snprintf(buf, sizeof(buf), "%08x", value); + break; + } + return std::string(buf); +} // 整数(32bitまで)を検査する -void +static void __unused xp_equal(uint32 expected, uint32 actual, const char *name) { if (expected != actual) { @@ -40,8 +60,8 @@ xp_equal(uint32 expected, uint32 actual, } // 値(32bitまで)と CCR を検査する -void -xp_equal(uint32 actValue, m68030ccr& actCCR, uint32 expValue, +static void +xp_equal(uint32 actValue, m680x0CCR& actCCR, uint32 expValue, bool expX, bool expN, bool expZ, bool expV, bool expC) { if (expValue != actValue || @@ -74,8 +94,8 @@ xp_equal(uint32 actValue, m68030ccr& act } // 値(64bit)と CCR を検査する -void -xp_equal64(uint64 actValue, m68030ccr& actCCR, uint64 expValue, +static void __unused +xp_equal64(uint64 actValue, m680x0CCR& actCCR, uint64 expValue, bool expX, bool expN, bool expZ, bool expV, bool expC) { if (expValue != actValue || @@ -112,7 +132,7 @@ xp_equal64(uint64 actValue, m68030ccr& a // このテストを実行するかどうか // 引数なしなら全部実行。 // 引数ありなら一致すれば実行。 -bool +static bool check_exec(const char *name) { if (argc == 0) { @@ -129,14 +149,13 @@ check_exec(const char *name) // サイズ部を除いて一致するか // add に対して addx が一致しないようにアンダーバーまでで調べる - char name2[strlen(name) + 1]; - strcpy(name2, name); - char *u = strchr(name2, '_'); - if (u) { - *u = '\0'; + std::string name2(name); + int u = name2.find('_'); + if (u != std::string::npos) { + name2.erase(u, name2.size() - u); } for (int i = 0; i < argc; i++) { - if (strcmp(name2, argv[i]) == 0) { + if (strcmp(name2.c_str(), argv[i]) == 0) { return true; } } @@ -149,7 +168,7 @@ check_exec(const char *name) return; \ start_test_func(__FUNCTION__) -void +static void start_test_func(const char *name) { testname = name; @@ -158,7 +177,7 @@ start_test_func(const char *name) errcnt = 0; } -void +static void end_test() { if (errcnt == 0) { @@ -177,13 +196,13 @@ end_test() #define END_PERF \ end_perf_func() -void +static void signal_alarm(int signo) { perf_signaled = 1; } -void +static void start_perf_func(const char *name) { testname = name; @@ -200,7 +219,7 @@ start_perf_func(const char *name) setitimer(ITIMER_REAL, &it, NULL); } -void +static void end_perf_func() { struct timeval end, result; @@ -213,7 +232,7 @@ end_perf_func() } // 乱数 -uint32 +static uint32 xor32() { static uint32 y = 2463534242; @@ -225,14 +244,14 @@ xor32() // sz ビット目(最下位を0とする)を立てた値を返す // sz は 0..63 -uint64 +static uint64 BIT(int sz) { return (1ULL << sz); } // 下位 sz ビットがすべて 1 の値を返す -uint32 +static uint32 MASK(int sz) { return (1ULL << sz) - 1; @@ -240,7 +259,7 @@ MASK(int sz) // value を sz ビット符号付き整数とした時、負かどうかを返す // sz は 8, 16, 32 -bool +static bool ISNEG(uint64 value, int sz) { return ((value & BIT(sz - 1)) != 0); @@ -250,7 +269,7 @@ ISNEG(uint64 value, int sz) // add,sub // -uint32 add_table[] = { +static uint32 add_table[] = { 0x00000000, 0x00000001, 0x0000007f, @@ -264,8 +283,8 @@ uint32 add_table[] = { 0xffffffff, }; -void -test_add(int sz) +static void +test_add(m680x0ACC& acc, int sz) { for (int i = 0; i < countof(add_table); i++) { for (int j = 0; j < countof(add_table); j++) { @@ -274,52 +293,52 @@ test_add(int sz) uint64 tmp = src + dst; uint64 res = tmp & MASK(sz); - sprintf(where, "%0*" PRIx64 " + %0*" PRIx64, - (sz / 4), src, (sz / 4), dst); + std::string w = hex(src, sz) + " + " + hex(dst, sz); + strlcpy(where, w.c_str(), sizeof(where)); bool C = tmp & BIT(sz); bool V = ((res ^ src) & (res ^ dst)) & BIT(sz - 1); uint32 actual; if (sz == 8) { - actual = acc_add_8(cpu, src, dst); + actual = acc.add_8(src, dst); } else if (sz == 16) { - actual = acc_add_16(cpu, src, dst); + actual = acc.add_16(src, dst); } else { - actual = acc_add_32(cpu, src, dst); + actual = acc.add_32(src, dst); } - xp_equal(actual, CCR, res, + xp_equal(actual, acc, res, C, ISNEG(res, sz), (res == 0), V, C); } } } -void -test_add_8() +static void +test_add_8(m680x0ACC& acc) { start_test(); - test_add(8); + test_add(acc, 8); end_test(); } -void -test_add_16() +static void +test_add_16(m680x0ACC& acc) { start_test(); - test_add(16); + test_add(acc, 16); end_test(); } -void -test_add_32() +static void +test_add_32(m680x0ACC& acc) { start_test(); - test_add(32); + test_add(acc, 32); end_test(); } -void -test_sub(int sz) +static void +test_sub(m680x0ACC& acc, int sz) { for (int i = 0; i < countof(add_table); i++) { for (int j = 0; j < countof(add_table); j++) { @@ -335,47 +354,47 @@ test_sub(int sz) tmp = (uint64)dst - (uint64)src; } uint64 res = tmp & MASK(sz); - sprintf(where, "%0*" PRIx64 " - %0*" PRIx64, - (sz / 4), dst, (sz / 4), src); + std::string w = hex(dst, sz) + " - " + hex(src, sz); + strlcpy(where, w.c_str(), sizeof(where)); bool C = tmp & BIT(sz); bool V = ((src ^ dst) & (res ^ dst)) & BIT(sz - 1); uint32 actual; if (sz == 8) { - actual = acc_sub_8(cpu, src, dst); + actual = acc.sub_8(src, dst); } else if (sz == 16) { - actual = acc_sub_16(cpu, src, dst); + actual = acc.sub_16(src, dst); } else { - actual = acc_sub_32(cpu, src, dst); + actual = acc.sub_32(src, dst); } - xp_equal(actual, CCR, res, + xp_equal(actual, acc, res, C, ISNEG(res, sz), (res == 0), V, C); } } } -void -test_sub_8() +static void +test_sub_8(m680x0ACC& acc) { start_test(); - test_sub(8); + test_sub(acc, 8); end_test(); } -void -test_sub_16() +static void +test_sub_16(m680x0ACC& acc) { start_test(); - test_sub(16); + test_sub(acc, 16); end_test(); } -void -test_sub_32() +static void +test_sub_32(m680x0ACC& acc) { start_test(); - test_sub(32); + test_sub(acc, 32); end_test(); } @@ -383,7 +402,7 @@ test_sub_32() // // addx // -struct { +static struct { uint32 src, dst; bool inX; uint32 res; @@ -397,8 +416,8 @@ struct { { 0x7fffffff, 0x80000000, 1, 0x00000000, 0, 1, 0, 1 }, }; -void -test_addx_32() +static void +test_addx_32(m680x0ACC& acc) { start_test(); for (int i = 0; i < countof(addx32_table); i++) { @@ -410,12 +429,12 @@ test_addx_32() bool expZ = addx32_table[i].expZ; bool expV = addx32_table[i].expV; bool expC = addx32_table[i].expC; - sprintf(where, "%08x + %08x + %d", src, dst, inX); + snprintf(where, sizeof(where), "%08x + %08x + %d", src, dst, inX); - CCR.PutX(inX); - CCR.PutZ(true); - uint32 actual = acc_addx_32(cpu, src, dst); - xp_equal(actual, CCR, res, expC, expN, expZ, expV, expC); + acc.SetX(inX); + acc.SetZ(true); + uint32 actual = acc.addx_32(src, dst); + xp_equal(actual, acc, res, expC, expN, expZ, expV, expC); } end_test(); } @@ -426,18 +445,19 @@ test_addx_32() // ローテート/シフト系のパフォーマンス測定 #define DEFINE_PERF_ROTATE(name) \ -void \ -__CONCAT(perf_,name)() \ +static void \ +__CONCAT(perf_,name)(m680x0ACC& acc) \ { \ START_PERF; \ volatile uint32 dst = 0; \ for (; perf_signaled == 0;) { \ for (int count = 0; count < 32; count++) { \ uint32 src = xor32(); \ - dst ^= __CONCAT(acc_,name)(cpu, src, count); \ + dst ^= acc.name(src, count); \ perf_count++; \ } \ } \ + (void)dst; \ END_PERF; \ } DEFINE_PERF_ROTATE(asl_32) @@ -449,14 +469,14 @@ DEFINE_PERF_ROTATE(lsr_32) DEFINE_PERF_ROTATE(roxr_32) DEFINE_PERF_ROTATE(ror_32) -void -perf_add_32() +static void +perf_add_32(m680x0ACC& acc) { START_PERF; volatile uint32 dst = 0; for (; perf_signaled == 0; ) { uint32 src = xor32(); - dst = acc_add_32(cpu, src, dst); + dst = acc.add_32(src, dst); perf_count++; } END_PERF; @@ -487,33 +507,31 @@ main(int ac, char *av[]) ac -= optind; av += optind; argc = ac; - argv = (const char **)av; + argv = av; - // 本当はコンストラクタを呼ぶべきだが、そうすると必要なオブジェクトが - // 芋づる式に増えて正しく解決するのは面倒。ここのテストではとりあえず - // 存在しててアクセスできればいい程度なのでこれで誤魔化してある。 - cpu = (m68kcpu *)calloc(sizeof(*cpu), 1); + std::unique_ptr accptr(new m680x0ACC()); + m680x0ACC& acc = *(accptr.get()); if (do_test) { - test_add_8(); - test_add_16(); - test_add_32(); - test_sub_8(); - test_sub_16(); - test_sub_32(); - test_addx_32(); + test_add_8(acc); + test_add_16(acc); + test_add_32(acc); + test_sub_8(acc); + test_sub_16(acc); + test_sub_32(acc); + test_addx_32(acc); } if (do_perf) { - perf_asl_32(); - perf_lsl_32(); - perf_roxl_32(); - perf_rol_32(); - perf_asr_32(); - perf_lsr_32(); - perf_roxr_32(); - perf_ror_32(); - perf_add_32(); + perf_asl_32(acc); + perf_lsl_32(acc); + perf_roxl_32(acc); + perf_rol_32(acc); + perf_asr_32(acc); + perf_lsr_32(acc); + perf_roxr_32(acc); + perf_ror_32(acc); + perf_add_32(acc); } return 0;