--- nono/exp/optestm88k/optestm88k_main.c 2026/04/29 17:04:57 1.1.1.1 +++ nono/exp/optestm88k/optestm88k_main.c 2026/04/29 17:05:49 1.1.1.4 @@ -1,3 +1,4 @@ +/* vi:set ts=4: */ /* * nono * Copyright (C) 2021 nono project @@ -5,31 +6,63 @@ */ #include "optestm88k_main.h" +#include +#include #include #include +#include #include +#include #include // グローバルワーク (r2 でアセンブラに渡される) -int global_work[2]; +// define の値を code.s と揃えること +int global_work[6]; // オーバーフロー例外なら 1、除算例外なら 2 をセットする。 // テスト前に 0 で初期化しておくこと。 #define exception_occurred (global_work[0]) -// 例外を期待するなら 1 か 2、期待しないなら 0 (テスト側が書く) +// 例外を期待しないなら 0、期待するなら例外ごとのマスク値 (テスト側が書く) #define exception_expected (global_work[1]) +// 期待値と結果 (表示用) +#define expected_val (global_work[2]) +#define expected_val2 (global_work[3]) +#define actual_val (global_work[4]) +#define actual_val2 (global_work[5]) static void -sigfpe(int signo, siginfo_t *si, void *ctx) +usage() { - if (si->si_signo == SIGFPE) { + printf("usage: %s []\n", getprogname()); + exit(1); +} + +static void +signal_handler(int signo, siginfo_t *si, void *ctx) +{ + switch (si->si_signo) { + case SIGFPE: if (si->si_code == FPE_INTOVF) { - exception_occurred = 1; + exception_occurred = 0x0001; return; } else if (si->si_code == FPE_INTDIV) { - exception_occurred = 2; + exception_occurred = 0x0002; + return; + } + printf("%s: signo=SIGFPE si_code=%x\n", __func__, si->si_code); + break; + case SIGILL: + if (si->si_code == ILL_ILLOPC) { + exception_occurred = 0x1000; return; } + printf("%s: signo=SIGILL si_code=%x\n", __func__, si->si_code); + break; + + default: + printf("%s: signo=%d si_code=%x\n", __func__, + si->si_signo, si->si_code); + break; } // XXX exception_occurred = -1; @@ -38,30 +71,51 @@ sigfpe(int signo, siginfo_t *si, void *c int main(int ac, char *av[]) { - char cause[64]; + char cause[128]; struct testentry *t; func_t func; const char *arg_name = ""; + int c; int i; int j; int num; int res; - - if (ac >= 2) { - arg_name = av[1]; + int failed; + int total_failed; + fp_rnd rnd_backup; + + while ((c = getopt(ac, av, "")) != -1) { + switch (c) { + default: + usage(); + break; + } } + ac -= optind; + av += optind; + if (ac > 1) { + usage(); + } + if (ac == 1) { + arg_name = av[0]; + } + + rnd_backup = fpgetround(); struct sigaction act; memset(&act, 0, sizeof(act)); - act.sa_sigaction = sigfpe; + act.sa_sigaction = signal_handler; act.sa_flags = SA_SIGINFO; sigaction(SIGFPE, &act, NULL); + sigaction(SIGILL, &act, NULL); + total_failed = 0; for (i = j = 0; test_table[i].code != NULL; i++, j = 0) { + failed = 0; t = &test_table[i]; if (strncasecmp(t->testname, arg_name, strlen(arg_name)) != 0) { - break; + continue; } if (j == 0) { @@ -79,13 +133,23 @@ main(int ac, char *av[]) res = (t->code)(global_work, t->testdata[j]); // 失敗なら非 0 を返す // bit3 は演算結果が期待と異なる - // bit0 は例外有無が期待と異なる + // それ以外のビットが立っていれば例外有無が期待と異なる if (res != 0) { cause[0] = '\0'; if ((res & 8)) { - strlcpy(cause, "incorrect result", sizeof(cause)); +#define SNPRINTF(s, fmt...) n += snprintf((s) + n, sizeof(s) - n, fmt) + int n = 0; + SNPRINTF(cause, "0x%08x", expected_val); + if (t->quad) { + SNPRINTF(cause, "'%08x", expected_val2); + } + SNPRINTF(cause, " expected but 0x%08x", actual_val); + if (t->quad) { + SNPRINTF(cause, "'%08x", actual_val2); + } + res &= ~8; } - if ((res & 1)) { + if (res != 0) { if (cause[0]) { strlcat(cause, ", ", sizeof(cause)); } @@ -97,14 +161,25 @@ main(int ac, char *av[]) strlcat(cause, "exception occurred", sizeof(cause)); } } + if (failed == 0) { + printf("\n"); + } printf("FAILED (%s) at test_%s_%d\n", cause, t->testname, j); - exit(1); + failed++; } } - printf("ok\n"); + if (failed == 0) { + printf("ok\n"); + } + total_failed += failed; + } + + if (total_failed != 0) { + printf("%d failed!\n", total_failed); } + fpsetround(rnd_backup); return 0; }