mirror of
https://github.com/ioacademy-jikim/debugging
synced 2025-06-09 17:06:24 +00:00
205 lines
6.0 KiB
C
205 lines
6.0 KiB
C
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <signal.h>
|
|
#include <setjmp.h>
|
|
|
|
#define MAX_ARR 24
|
|
#define PERROR \
|
|
printf("This test is testing mips32r2 instructions in fpu64 mode.\n");
|
|
#define FLAGS_RM_MASK 0xFFFFFFFF
|
|
|
|
typedef enum {
|
|
CVTLS, CVTLD, ROUNDLS, ROUNDLD,
|
|
TRUNCLS, TRUNCLD, FLOORLS, FLOORLD,
|
|
CEILLS, CEILLD
|
|
} flt_round_op_t;
|
|
|
|
const char *flt_round_op_names[] = {
|
|
"cvt.l.s", "cvt.l.d", "round.l.s", "round.l.d",
|
|
"trunc.l.s", "trunc.l.d", "floor.l.s", "floor.l.d"
|
|
"ceil.l.s", "ceil.l.d"
|
|
};
|
|
|
|
typedef enum {
|
|
TO_NEAREST=0, TO_ZERO, TO_PLUS_INFINITY, TO_MINUS_INFINITY } round_mode_t;
|
|
char *round_mode_name[] = { "near", "zero", "+inf", "-inf" };
|
|
|
|
const float fs_f[] = {
|
|
0, 456.25, 3, -1,
|
|
1384.5, -7.25, 1000000000, -5786.25,
|
|
1752, 0.015625, 0.03125, -248562.75,
|
|
-45786.5, 456, 34.03125, 45786.75,
|
|
1752065, 107, -45667.25, -7,
|
|
-347856.5, 356047, -1.25, 23.0625
|
|
};
|
|
|
|
const double fs_d[] = {
|
|
0, 456.25, 3, -1,
|
|
1384.5, -7.25, 1000000000, -5786.25,
|
|
1752, 0.015625, 0.03125, -24856226678933.75,
|
|
-45786.5, 456, 34.03125, 45786.75,
|
|
1752065, 107, -45667.25, -7,
|
|
-347856.5, 356047, -1.25, 23.0625
|
|
};
|
|
|
|
#define UNOPsl(op) \
|
|
__asm__ __volatile__( \
|
|
op" $f0, %2" "\n\t" \
|
|
"sdc1 $f0, 0(%1)" "\n\t" \
|
|
"cfc1 %0, $31" "\n\t" \
|
|
: "=r" (fcsr) \
|
|
: "r"(&fd_l), "f"(fs_f[i]) \
|
|
: "$f0" \
|
|
);
|
|
|
|
#define UNOPdl(op) \
|
|
__asm__ __volatile__( \
|
|
op" $f0, %2" "\n\t" \
|
|
"sdc1 $f0, 0(%1)" "\n\t" \
|
|
"cfc1 %0, $31" "\n\t" \
|
|
: "=r" (fcsr) \
|
|
: "r"(&fd_l), "f"(fs_d[i]) \
|
|
: "$f0" \
|
|
);
|
|
|
|
#define TEST_FPU64 \
|
|
__asm__ __volatile__( \
|
|
"cvt.l.s $f0, $f0" "\n\t" \
|
|
: \
|
|
: \
|
|
: "$f0" \
|
|
);
|
|
|
|
#if (__mips==32) && (__mips_isa_rev>=2) && (__mips_fpr==64)
|
|
void set_rounding_mode(round_mode_t mode)
|
|
{
|
|
switch(mode) {
|
|
case TO_NEAREST:
|
|
__asm__ volatile("ctc1 $zero, $31" "\n\t");
|
|
break;
|
|
case TO_ZERO:
|
|
__asm__ volatile("li $t0, 0x1" "\n\t"
|
|
"ctc1 $t0, $31" "\n\t");
|
|
break;
|
|
case TO_PLUS_INFINITY:
|
|
__asm__ volatile("li $t0, 0x2" "\n\t"
|
|
"ctc1 $t0, $31" "\n\t");
|
|
break;
|
|
case TO_MINUS_INFINITY:
|
|
__asm__ volatile("li $t0, 0x3" "\n\t"
|
|
"ctc1 $t0, $31" "\n\t");
|
|
break;
|
|
}
|
|
}
|
|
|
|
struct test {
|
|
void (*test)(void);
|
|
int sig;
|
|
int code;
|
|
};
|
|
|
|
static void handler(int sig)
|
|
{
|
|
PERROR;
|
|
exit(0);
|
|
}
|
|
|
|
int FCSRRoundingMode(flt_round_op_t op)
|
|
{
|
|
long long int fd_l;
|
|
int i;
|
|
int fcsr = 0;
|
|
round_mode_t rm;
|
|
for (rm = TO_NEAREST; rm <= TO_MINUS_INFINITY; rm ++) {
|
|
printf("roundig mode: %s\n", round_mode_name[rm]);
|
|
for (i = 0; i < MAX_ARR; i++) {
|
|
set_rounding_mode(rm);
|
|
switch(op) {
|
|
case CVTLS:
|
|
UNOPsl("cvt.l.s");
|
|
printf("%s %lld %f\n",
|
|
flt_round_op_names[op], fd_l, fs_f[i]);
|
|
printf("fcsr: 0x%x\n", fcsr & FLAGS_RM_MASK);
|
|
break;
|
|
case CVTLD:
|
|
UNOPdl("cvt.l.d");
|
|
printf("%s %lld %lf\n",
|
|
flt_round_op_names[op], fd_l, fs_d[i]);
|
|
printf("fcsr: 0x%x\n", fcsr & FLAGS_RM_MASK);
|
|
break;
|
|
case ROUNDLS:
|
|
UNOPsl("round.l.s");
|
|
printf("%s %lld %f\n",
|
|
flt_round_op_names[op], fd_l, fs_f[i]);
|
|
printf("fcsr: 0x%x\n", fcsr & FLAGS_RM_MASK);
|
|
break;
|
|
case ROUNDLD:
|
|
UNOPdl("round.l.d");
|
|
printf("%s %lld %lf\n",
|
|
flt_round_op_names[op], fd_l, fs_d[i]);
|
|
printf("fcsr: 0x%x\n", fcsr & FLAGS_RM_MASK);
|
|
break;
|
|
case TRUNCLS:
|
|
UNOPsl("trunc.l.s");
|
|
printf("%s %lld %f\n",
|
|
flt_round_op_names[op], fd_l, fs_f[i]);
|
|
printf("fcsr: 0x%x\n", fcsr & FLAGS_RM_MASK);
|
|
break;
|
|
case TRUNCLD:
|
|
UNOPdl("trunc.l.d");
|
|
printf("%s %lld %lf\n",
|
|
flt_round_op_names[op], fd_l, fs_d[i]);
|
|
printf("fcsr: 0x%x\n", fcsr & FLAGS_RM_MASK);
|
|
break;
|
|
case FLOORLS:
|
|
UNOPsl("floor.l.s");
|
|
printf("%s %lld %f\n",
|
|
flt_round_op_names[op], fd_l, fs_f[i]);
|
|
printf("fcsr: 0x%x\n", fcsr & FLAGS_RM_MASK);
|
|
break;
|
|
case FLOORLD:
|
|
UNOPdl("floor.l.d");
|
|
printf("%s %lld %lf\n",
|
|
flt_round_op_names[op], fd_l, fs_d[i]);
|
|
printf("fcsr: 0x%x\n", fcsr & FLAGS_RM_MASK);
|
|
break;
|
|
case CEILLS:
|
|
UNOPsl("ceil.l.s");
|
|
printf("%s %lld %f\n",
|
|
flt_round_op_names[op], fd_l, fs_f[i]);
|
|
printf("fcsr: 0x%x\n", fcsr & FLAGS_RM_MASK);
|
|
break;
|
|
case CEILLD:
|
|
UNOPdl("ceil.l.d");
|
|
printf("%s %lld %lf\n",
|
|
flt_round_op_names[op], fd_l, fs_d[i]);
|
|
printf("fcsr: 0x%x\n", fcsr & FLAGS_RM_MASK);
|
|
break;
|
|
default:
|
|
printf("error\n");
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
#endif
|
|
|
|
|
|
int main()
|
|
{
|
|
#if (__mips==32) && (__mips_isa_rev>=2) && (__mips_fpr==64)
|
|
flt_round_op_t op;
|
|
signal(SIGILL, handler);
|
|
/* Test fpu64 mode. */
|
|
TEST_FPU64;
|
|
printf("-------------------------- %s --------------------------\n",
|
|
"test FPU Conversion Operations Using the FCSR Rounding Mode");
|
|
for (op = CVTLS; op <= CEILLD; op++)
|
|
FCSRRoundingMode(op);
|
|
#else
|
|
PERROR;
|
|
#endif
|
|
return 0;
|
|
}
|