|
|
1.1 root 1: /*
2: * nono
3: * Copyright (C) 2021 nono project
4: * Licensed under nono-license.txt
5: */
6:
7: #include "optestm88k_main.h"
1.1.1.3 ! root 8: #include <ieeefp.h>
! 9: #include <getopt.h>
1.1 root 10: #include <setjmp.h>
11: #include <signal.h>
1.1.1.3 ! root 12: #include <stdio.h>
1.1 root 13: #include <stdlib.h>
14: #include <sys/siginfo.h>
15:
16: // グローバルワーク (r2 でアセンブラに渡される)
1.1.1.3 ! root 17: // define の値を code.s と揃えること
! 18: int global_work[6];
1.1 root 19:
20: // オーバーフロー例外なら 1、除算例外なら 2 をセットする。
21: // テスト前に 0 で初期化しておくこと。
22: #define exception_occurred (global_work[0])
1.1.1.3 ! root 23: // 例外を期待しないなら 0、期待するなら例外ごとのマスク値 (テスト側が書く)
1.1 root 24: #define exception_expected (global_work[1])
1.1.1.3 ! root 25: // 期待値と結果 (表示用)
! 26: #define expected_val (global_work[2])
! 27: #define expected_val2 (global_work[3])
! 28: #define actual_val (global_work[4])
! 29: #define actual_val2 (global_work[5])
! 30:
! 31: static void
! 32: usage()
! 33: {
! 34: printf("usage: %s [<testname>]\n", getprogname());
! 35: exit(1);
! 36: }
1.1 root 37:
38: static void
1.1.1.2 root 39: signal_handler(int signo, siginfo_t *si, void *ctx)
1.1 root 40: {
1.1.1.3 ! root 41: switch (si->si_signo) {
! 42: case SIGFPE:
1.1 root 43: if (si->si_code == FPE_INTOVF) {
1.1.1.3 ! root 44: exception_occurred = 0x0001;
1.1 root 45: return;
46: } else if (si->si_code == FPE_INTDIV) {
1.1.1.3 ! root 47: exception_occurred = 0x0002;
1.1 root 48: return;
49: }
1.1.1.2 root 50: printf("%s: signo=SIGFPE si_code=%x\n", __func__, si->si_code);
1.1.1.3 ! root 51: break;
! 52: case SIGILL:
1.1.1.2 root 53: if (si->si_code == ILL_ILLOPC) {
54: exception_occurred = 0x1000;
55: return;
56: }
57: printf("%s: signo=SIGILL si_code=%x\n", __func__, si->si_code);
1.1.1.3 ! root 58: break;
! 59:
! 60: default:
! 61: printf("%s: signo=%d si_code=%x\n", __func__,
! 62: si->si_signo, si->si_code);
! 63: break;
1.1 root 64: }
65: // XXX
66: exception_occurred = -1;
67: }
68:
69: int
70: main(int ac, char *av[])
71: {
1.1.1.3 ! root 72: char cause[128];
1.1 root 73: struct testentry *t;
74: func_t func;
75: const char *arg_name = "";
1.1.1.3 ! root 76: int c;
1.1 root 77: int i;
78: int j;
79: int num;
80: int res;
1.1.1.3 ! root 81: int failed;
! 82: int total_failed;
! 83: fp_rnd rnd_backup;
! 84:
! 85: while ((c = getopt(ac, av, "")) != -1) {
! 86: switch (c) {
! 87: default:
! 88: usage();
! 89: break;
! 90: }
! 91: }
! 92: ac -= optind;
! 93: av += optind;
! 94: if (ac > 1) {
! 95: usage();
1.1 root 96: }
1.1.1.3 ! root 97: if (ac == 1) {
! 98: arg_name = av[0];
! 99: }
! 100:
! 101: rnd_backup = fpgetround();
1.1 root 102:
103: struct sigaction act;
104: memset(&act, 0, sizeof(act));
1.1.1.2 root 105: act.sa_sigaction = signal_handler;
1.1 root 106: act.sa_flags = SA_SIGINFO;
107: sigaction(SIGFPE, &act, NULL);
1.1.1.2 root 108: sigaction(SIGILL, &act, NULL);
1.1 root 109:
1.1.1.3 ! root 110: total_failed = 0;
1.1 root 111: for (i = j = 0; test_table[i].code != NULL; i++, j = 0) {
1.1.1.3 ! root 112: failed = 0;
1.1 root 113: t = &test_table[i];
114:
115: if (strncasecmp(t->testname, arg_name, strlen(arg_name)) != 0) {
1.1.1.3 ! root 116: continue;
1.1 root 117: }
118:
119: if (j == 0) {
120: // テスト数を数える
121: for (num = 0; t->testdata[num] != NULL; num++)
122: ;
123:
124: printf("%s (%d) ... ", t->testname, num);
125: fflush(stdout);
126: }
127:
128: for (; j < num; j++) {
129: exception_occurred = 0;
130:
131: res = (t->code)(global_work, t->testdata[j]);
132: // 失敗なら非 0 を返す
133: // bit3 は演算結果が期待と異なる
1.1.1.3 ! root 134: // それ以外のビットが立っていれば例外有無が期待と異なる
1.1 root 135: if (res != 0) {
136: cause[0] = '\0';
137: if ((res & 8)) {
1.1.1.3 ! root 138: #define SNPRINTF(s, fmt...) n += snprintf((s) + n, sizeof(s) - n, fmt)
! 139: int n = 0;
! 140: SNPRINTF(cause, "0x%08x", expected_val);
! 141: if (t->quad) {
! 142: SNPRINTF(cause, "'%08x", expected_val2);
! 143: }
! 144: SNPRINTF(cause, " expected but 0x%08x", actual_val);
! 145: if (t->quad) {
! 146: SNPRINTF(cause, "'%08x", actual_val2);
! 147: }
! 148: res &= ~8;
1.1 root 149: }
1.1.1.3 ! root 150: if (res != 0) {
1.1 root 151: if (cause[0]) {
152: strlcat(cause, ", ", sizeof(cause));
153: }
154: if (exception_expected) {
155: // 例外を期待したが、例外が起きなかった。
156: strlcat(cause, "exception not occurred", sizeof(cause));
157: } else {
158: // 例外が起きないことを期待したのに例外が起きた。
159: strlcat(cause, "exception occurred", sizeof(cause));
160: }
161: }
1.1.1.3 ! root 162: if (failed == 0) {
! 163: printf("\n");
! 164: }
1.1 root 165: printf("FAILED (%s) at test_%s_%d\n",
166: cause, t->testname, j);
1.1.1.3 ! root 167: failed++;
1.1 root 168: }
169: }
170:
1.1.1.3 ! root 171: if (failed == 0) {
! 172: printf("ok\n");
! 173: }
! 174: total_failed += failed;
! 175: }
! 176:
! 177: if (total_failed != 0) {
! 178: printf("%d failed!\n", total_failed);
1.1 root 179: }
180:
1.1.1.3 ! root 181: fpsetround(rnd_backup);
1.1 root 182: return 0;
183: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.