File:  [Isaki's NoNo m68k/m88k emulator] / nono / exp / optestm88k / optestm88k_main.c
Revision 1.1.1.4 (vendor branch): download - view: text, annotated - select for diffs
Wed Apr 29 17:05:49 2026 UTC (3 months ago) by root
Branches: MAIN, Isaki
CVS tags: v027, v026, v025, HEAD
nono 1.5.0

/* vi:set ts=4: */
/*
 * nono
 * Copyright (C) 2021 nono project
 * Licensed under nono-license.txt
 */

#include "optestm88k_main.h"
#include <ieeefp.h>
#include <getopt.h>
#include <setjmp.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/siginfo.h>

// グローバルワーク (r2 でアセンブラに渡される)
// define の値を code.s と揃えること
int global_work[6];

// オーバーフロー例外なら 1、除算例外なら 2 をセットする。
// テスト前に 0 で初期化しておくこと。
#define exception_occurred (global_work[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
usage()
{
	printf("usage: %s [<testname>]\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 = 0x0001;
			return;
		} else if (si->si_code == FPE_INTDIV) {
			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;
}

int
main(int ac, char *av[])
{
	char cause[128];
	struct testentry *t;
	func_t func;
	const char *arg_name = "";
	int c;
	int i;
	int j;
	int num;
	int res;
	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 = 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) {
			continue;
		}

		if (j == 0) {
			// テスト数を数える
			for (num = 0; t->testdata[num] != NULL; num++)
				;

			printf("%s (%d) ... ", t->testname, num);
			fflush(stdout);
		}

		for (; j < num; j++) {
			exception_occurred = 0;

			res = (t->code)(global_work, t->testdata[j]);
			// 失敗なら非 0 を返す
			// bit3 は演算結果が期待と異なる
			// それ以外のビットが立っていれば例外有無が期待と異なる
			if (res != 0) {
				cause[0] = '\0';
				if ((res & 8)) {
#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 != 0) {
					if (cause[0]) {
						strlcat(cause, ", ", sizeof(cause));
					}
					if (exception_expected) {
						// 例外を期待したが、例外が起きなかった。
						strlcat(cause, "exception not occurred", sizeof(cause));
					} else {
						// 例外が起きないことを期待したのに例外が起きた。
						strlcat(cause, "exception occurred", sizeof(cause));
					}
				}
				if (failed == 0) {
					printf("\n");
				}
				printf("FAILED (%s) at test_%s_%d\n",
					cause, t->testname, j);
				failed++;
			}
		}

		if (failed == 0) {
			printf("ok\n");
		}
		total_failed += failed;
	}

	if (total_failed != 0) {
		printf("%d failed!\n", total_failed);
	}

	fpsetround(rnd_backup);
	return 0;
}

unix.superglobalmegacorp.com

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