mirror of
https://github.com/ioacademy-jikim/debugging
synced 2025-06-08 08:26:14 +00:00
280 lines
9.0 KiB
C
280 lines
9.0 KiB
C
#include <stdio.h>
|
|
|
|
typedef enum {
|
|
CEILWS=0, CEILWD,
|
|
FLOORWS, FLOORWD,
|
|
ROUNDWS, ROUNDWD,
|
|
TRUNCWS, TRUNCWD
|
|
} flt_dir_op_t;
|
|
|
|
typedef enum {
|
|
CVTDS, CVTDW,
|
|
CVTSD, CVTSW,
|
|
CVTWS, CVTWD
|
|
} flt_round_op_t;
|
|
|
|
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 char *flt_dir_op_names[] = {
|
|
"ceil.w.s", "ceil.w.d",
|
|
"floor.w.s", "floor.w.d",
|
|
"round.w.s", "round.w.d",
|
|
"trunc.w.s", "trunc.w.d"
|
|
};
|
|
|
|
const char *flt_round_op_names[] = {
|
|
"cvt.d.s", "cvt.d.w",
|
|
"cvt.s.d", "cvt.s.w",
|
|
"cvt.w.s", "cvt.w.d"
|
|
};
|
|
|
|
const double fs_d[] = {
|
|
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 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 int fs_w[] = {
|
|
0, 456, 3, -1,
|
|
0xffffffff, 356, 1000000000, -5786,
|
|
1752, 24575, 10, -248562,
|
|
-45786, 456, 34, 45786,
|
|
1752065, 107, -45667, -7,
|
|
-347856, 0x80000000, 0xFFFFFFF, 23
|
|
};
|
|
|
|
#define BINOP(op) \
|
|
__asm__ volatile(op" %1, %2, %3" "\n\t" \
|
|
"cfc1 %0, $31" "\n\t" \
|
|
: "=r" (fcsr), "=f"(fd) \
|
|
: "f"(f) , "f"(fB));
|
|
|
|
#define UNOPdd(op) \
|
|
fd_d = 0; \
|
|
__asm__ volatile(op" %1, %2" "\n\t" \
|
|
"cfc1 %0, $31" "\n\t" \
|
|
: "=r" (fcsr), "=f"(fd_d) \
|
|
: "f"(fs_d[i]));
|
|
|
|
#define UNOPff(op) \
|
|
fd_f = 0; \
|
|
__asm__ volatile(op" %1, %2" "\n\t" \
|
|
"cfc1 %0, $31" "\n\t" \
|
|
: "=r" (fcsr), "=f"(fd_f) \
|
|
: "f"(fs_f[i]));
|
|
|
|
#define UNOPfd(op) \
|
|
fd_d = 0; \
|
|
__asm__ volatile(op" %1, %2" "\n\t" \
|
|
"cfc1 %0, $31" "\n\t" \
|
|
: "=r" (fcsr), "=f"(fd_d) \
|
|
: "f"(fs_f[i]));
|
|
|
|
#define UNOPdf(op) \
|
|
fd_f = 0; \
|
|
__asm__ volatile(op" %1, %2" "\n\t" \
|
|
"cfc1 %0, $31" "\n\t" \
|
|
: "=r" (fcsr), "=f"(fd_f) \
|
|
: "f"(fs_d[i]));
|
|
|
|
#define UNOPfw(op) \
|
|
fd_w = 0; \
|
|
__asm__ volatile(op" $f0, %2" "\n\t" \
|
|
"mfc1 %1, $f0" "\n\t" \
|
|
"cfc1 %0, $31" "\n\t" \
|
|
: "=r" (fcsr), "=r"(fd_w) \
|
|
: "f"(fs_f[i]) \
|
|
: "$f0");
|
|
|
|
#define UNOPdw(op) \
|
|
fd_w = 0; \
|
|
__asm__ volatile(op" $f0, %2" "\n\t" \
|
|
"mfc1 %1, $f0" "\n\t" \
|
|
"cfc1 %0, $31" "\n\t" \
|
|
: "=r" (fcsr), "=r"(fd_w) \
|
|
: "f"(fs_d[i]) \
|
|
: "$f0");
|
|
|
|
#define UNOPwd(op) \
|
|
fd_d = 0; \
|
|
__asm__ volatile("mtc1 %2, $f0" "\n\t" \
|
|
op" %1, $f0" "\n\t" \
|
|
"cfc1 %0, $31" "\n\t" \
|
|
: "=r" (fcsr), "=f"(fd_d) \
|
|
: "r"(fs_w[i]) \
|
|
: "$f0", "$f1");
|
|
|
|
#define UNOPwf(op) \
|
|
fd_f = 0; \
|
|
__asm__ volatile("mtc1 %2, $f0" "\n\t" \
|
|
op" %1, $f0" "\n\t" \
|
|
"cfc1 %0, $31" "\n\t" \
|
|
: "=r" (fcsr), "=f"(fd_f) \
|
|
: "r"(fs_w[i]) \
|
|
: "$f0");
|
|
|
|
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;
|
|
}
|
|
}
|
|
|
|
int directedRoundingMode(flt_dir_op_t op) {
|
|
int fd_w = 0;
|
|
int i;
|
|
int fcsr = 0;
|
|
round_mode_t rm = TO_NEAREST;
|
|
for (i = 0; i < 24; i++) {
|
|
set_rounding_mode(rm);
|
|
switch(op) {
|
|
case CEILWS:
|
|
UNOPfw("ceil.w.s");
|
|
printf("%s %d %f\n", flt_dir_op_names[op], fd_w, fs_f[i]);
|
|
printf("fcsr: 0x%x\n", fcsr);
|
|
break;
|
|
case CEILWD:
|
|
UNOPdw("ceil.w.d");
|
|
printf("%s %d %lf\n", flt_dir_op_names[op], fd_w, fs_d[i]);
|
|
printf("fcsr: 0x%x\n", fcsr);
|
|
break;
|
|
case FLOORWS:
|
|
UNOPfw("floor.w.s");
|
|
printf("%s %d %f\n", flt_dir_op_names[op], fd_w, fs_f[i]);
|
|
printf("fcsr: 0x%x\n", fcsr);
|
|
break;
|
|
case FLOORWD:
|
|
UNOPdw("floor.w.d");
|
|
printf("%s %d %lf\n", flt_dir_op_names[op], fd_w, fs_d[i]);
|
|
printf("fcsr: 0x%x\n", fcsr);
|
|
break;
|
|
case ROUNDWS:
|
|
UNOPfw("round.w.s");
|
|
printf("%s %d %f\n", flt_dir_op_names[op], fd_w, fs_f[i]);
|
|
printf("fcsr: 0x%x\n", fcsr);
|
|
break;
|
|
case ROUNDWD:
|
|
UNOPdw("round.w.d");
|
|
printf("%s %d %lf\n", flt_dir_op_names[op], fd_w, fs_d[i]);
|
|
printf("fcsr: 0x%x\n", fcsr);
|
|
break;
|
|
case TRUNCWS:
|
|
UNOPfw("trunc.w.s");
|
|
printf("%s %d %f\n", flt_dir_op_names[op], fd_w, fs_f[i]);
|
|
printf("fcsr: 0x%x\n", fcsr);
|
|
break;
|
|
case TRUNCWD:
|
|
UNOPdw("trunc.w.d");
|
|
printf("%s %d %lf\n", flt_dir_op_names[op], fd_w, fs_d[i]);
|
|
printf("fcsr: 0x%x\n", fcsr);
|
|
break;
|
|
default:
|
|
printf("error\n");
|
|
break;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int FCSRRoundingMode(flt_round_op_t op1)
|
|
{
|
|
double fd_d = 0;
|
|
float fd_f = 0;
|
|
int fd_w = 0;
|
|
int i;
|
|
int fcsr = 0;
|
|
round_mode_t rm;
|
|
for (rm = TO_NEAREST; rm <= TO_MINUS_INFINITY; rm ++) {
|
|
set_rounding_mode(rm);
|
|
printf("roundig mode: %s\n", round_mode_name[rm]);
|
|
for (i = 0; i < 24; i++) {
|
|
set_rounding_mode(rm);
|
|
switch(op1) {
|
|
case CVTDS:
|
|
UNOPfd("cvt.d.s");
|
|
printf("%s %lf %lf\n", flt_round_op_names[op1], fd_d, fs_f[i]);
|
|
printf("fcsr: 0x%x\n", fcsr);
|
|
break;
|
|
case CVTDW:
|
|
UNOPwd("cvt.d.w");
|
|
printf("%s %lf %d\n", flt_round_op_names[op1], fd_d, fs_w[i]);
|
|
printf("fcsr: 0x%x\n", fcsr);
|
|
break;
|
|
case CVTSD:
|
|
UNOPdf("cvt.s.d");
|
|
printf("%s %f %lf\n", flt_round_op_names[op1], fd_f, fs_d[i]);
|
|
printf("fcsr: 0x%x\n", fcsr);
|
|
break;
|
|
case CVTSW:
|
|
UNOPwf("cvt.s.w");
|
|
printf("%s %f %d\n", flt_round_op_names[op1], fd_f, fs_w[i]);
|
|
printf("fcsr: 0x%x\n", fcsr);
|
|
break;
|
|
case CVTWS:
|
|
UNOPfw("cvt.w.s");
|
|
printf("%s %d %f\n", flt_round_op_names[op1], fd_w, fs_f[i]);
|
|
printf("fcsr: 0x%x\n", fcsr);
|
|
break;
|
|
case CVTWD:
|
|
UNOPdw("cvt.w.d");
|
|
printf("%s %d %lf\n", flt_round_op_names[op1], fd_w, fs_d[i]);
|
|
printf("fcsr: 0x%x\n", fcsr);
|
|
break;
|
|
default:
|
|
printf("error\n");
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int main()
|
|
{
|
|
flt_dir_op_t op;
|
|
flt_round_op_t op1;
|
|
|
|
printf("-------------------------- %s --------------------------\n",
|
|
"test FPU Conversion Operations Using a Directed Rounding Mode");
|
|
for (op = CEILWS; op <= TRUNCWD; op++) {
|
|
directedRoundingMode(op);
|
|
}
|
|
|
|
printf("-------------------------- %s --------------------------\n",
|
|
"test FPU Conversion Operations Using the FCSR Rounding Mode");
|
|
for (op1 = CVTDS; op1 <= CVTWD; op1++) {
|
|
FCSRRoundingMode(op1);
|
|
}
|
|
return 0;
|
|
}
|
|
|