|
|
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"
8: #include <setjmp.h>
9: #include <signal.h>
10: #include <stdlib.h>
11: #include <sys/siginfo.h>
12:
13: // グローバルワーク (r2 でアセンブラに渡される)
14: int global_work[2];
15:
16: // オーバーフロー例外なら 1、除算例外なら 2 をセットする。
17: // テスト前に 0 で初期化しておくこと。
18: #define exception_occurred (global_work[0])
19: // 例外を期待するなら 1 か 2、期待しないなら 0 (テスト側が書く)
20: #define exception_expected (global_work[1])
21:
22: static void
1.1.1.2 ! root 23: signal_handler(int signo, siginfo_t *si, void *ctx)
1.1 root 24: {
25: if (si->si_signo == SIGFPE) {
26: if (si->si_code == FPE_INTOVF) {
27: exception_occurred = 1;
28: return;
29: } else if (si->si_code == FPE_INTDIV) {
30: exception_occurred = 2;
31: return;
32: }
1.1.1.2 ! root 33: printf("%s: signo=SIGFPE si_code=%x\n", __func__, si->si_code);
! 34: }
! 35: if (si->si_signo == SIGILL) {
! 36: if (si->si_code == ILL_ILLOPC) {
! 37: exception_occurred = 0x1000;
! 38: return;
! 39: }
! 40: printf("%s: signo=SIGILL si_code=%x\n", __func__, si->si_code);
1.1 root 41: }
42: // XXX
43: exception_occurred = -1;
44: }
45:
46: int
47: main(int ac, char *av[])
48: {
49: char cause[64];
50: struct testentry *t;
51: func_t func;
52: const char *arg_name = "";
53: int i;
54: int j;
55: int num;
56: int res;
57:
58: if (ac >= 2) {
59: arg_name = av[1];
60: }
61:
62: struct sigaction act;
63: memset(&act, 0, sizeof(act));
1.1.1.2 ! root 64: act.sa_sigaction = signal_handler;
1.1 root 65: act.sa_flags = SA_SIGINFO;
66: sigaction(SIGFPE, &act, NULL);
1.1.1.2 ! root 67: sigaction(SIGILL, &act, NULL);
1.1 root 68:
69: for (i = j = 0; test_table[i].code != NULL; i++, j = 0) {
70: t = &test_table[i];
71:
72: if (strncasecmp(t->testname, arg_name, strlen(arg_name)) != 0) {
73: break;
74: }
75:
76: if (j == 0) {
77: // テスト数を数える
78: for (num = 0; t->testdata[num] != NULL; num++)
79: ;
80:
81: printf("%s (%d) ... ", t->testname, num);
82: fflush(stdout);
83: }
84:
85: for (; j < num; j++) {
86: exception_occurred = 0;
87:
88: res = (t->code)(global_work, t->testdata[j]);
89: // 失敗なら非 0 を返す
90: // bit3 は演算結果が期待と異なる
91: // bit0 は例外有無が期待と異なる
92: if (res != 0) {
93: cause[0] = '\0';
94: if ((res & 8)) {
95: strlcpy(cause, "incorrect result", sizeof(cause));
96: }
97: if ((res & 1)) {
98: if (cause[0]) {
99: strlcat(cause, ", ", sizeof(cause));
100: }
101: if (exception_expected) {
102: // 例外を期待したが、例外が起きなかった。
103: strlcat(cause, "exception not occurred", sizeof(cause));
104: } else {
105: // 例外が起きないことを期待したのに例外が起きた。
106: strlcat(cause, "exception occurred", sizeof(cause));
107: }
108: }
109: printf("FAILED (%s) at test_%s_%d\n",
110: cause, t->testname, j);
111: exit(1);
112: }
113: }
114:
115: printf("ok\n");
116: }
117:
118: return 0;
119: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.