mirror of
https://github.com/ioacademy-jikim/debugging
synced 2025-06-08 16:36:21 +00:00
239 lines
7.1 KiB
C
239 lines
7.1 KiB
C
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
|
|
typedef enum {
|
|
ABSS=0, ABSD,
|
|
ADDS, ADDD,
|
|
DIVS, DIVD,
|
|
MULS, MULD,
|
|
NEGS, NEGD,
|
|
SQRTS, SQRTD,
|
|
SUBS, SUBD,
|
|
RECIPS, RECIPD,
|
|
RSQRTS, RSQRTD
|
|
} flt_art_op_t;
|
|
|
|
const char *flt_art_op_names[] = {
|
|
"abs.s", "abs.d",
|
|
"add.s", "add.d",
|
|
"div.s", "div.d",
|
|
"mul.s", "mul.d",
|
|
"neg.s", "neg.d",
|
|
"sqrt.s", "sqrt.d",
|
|
"sub.s", "sub.d",
|
|
"recip.s", "recip.d",
|
|
"rsqrt.s", "rsqrt.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 double fs_d[] = {
|
|
0, 456.25, 3, -1,
|
|
1384.5, -7.25, 1000000000, -5786.5,
|
|
1752, 0.015625, 0.03125, -248562.75,
|
|
456, -45786.5, 34.03125, 45786.75,
|
|
1752065, 107, -45667.25, -7,
|
|
-347856.5, 356047.5, -1.0, 23.0625
|
|
};
|
|
|
|
const double ft_d[] = {
|
|
-456.25, -45786.5, 34.03125, 45786.75,
|
|
1752065, 107, -45667.25, -7.25,
|
|
-347856.5, 356047.5, -1.0, 23.0625,
|
|
0, 456.25, 3, -1,
|
|
1384.5, -7, 1000000000, -5786.5,
|
|
1752, 0.015625, 0.03125, -248562.75
|
|
};
|
|
|
|
const float fs_f[] = {
|
|
0, 456.25, 3, -1,
|
|
1384.5, -7.25, 1000000000, -5786.5,
|
|
1752, 0.015625, 0.03125, -248562.75,
|
|
456, -45786.5, 34.03125, 45786.75,
|
|
1752065, 107, -45667.25, -7,
|
|
-347856.5, 356047.5, -1.0, 23.0625
|
|
};
|
|
|
|
const float ft_f[] = {
|
|
-456.25, -4578.5, 34.03125, 4578.75,
|
|
175, 107, -456.25, -7.25,
|
|
-3478.5, 356.5, -1.0, 23.0625,
|
|
0, 456.25, 3, -1,
|
|
1384.5, -7, 100, -5786.5,
|
|
1752, 0.015625, 0.03125, -248562.75
|
|
};
|
|
|
|
#define UNOPdd(op) \
|
|
fd_d = 0; \
|
|
__asm__ volatile( \
|
|
op" %0, %1\n\t" \
|
|
: "=f"(fd_d) : "f"(fs_d[i]));
|
|
|
|
#define UNOPff(op) \
|
|
fd_f = 0; \
|
|
__asm__ volatile( \
|
|
op" %0, %1\n\t" \
|
|
: "=f"(fd_f) : "f"(fs_f[i]));
|
|
|
|
#define BINOPf(op) \
|
|
fd_f = 0; \
|
|
__asm__ volatile( \
|
|
op" %0, %1, %2\n\t" \
|
|
: "=f"(fd_f) : "f"(fs_f[i]) , "f"(ft_f[i]));
|
|
|
|
#define BINOPd(op) \
|
|
fd_d = 0; \
|
|
__asm__ volatile( \
|
|
op" %0, %1, %2\n\t" \
|
|
: "=f"(fd_d) : "f"(fs_d[i]) , "f"(ft_d[i]));
|
|
|
|
void set_rounding_mode(round_mode_t mode)
|
|
{
|
|
switch(mode) {
|
|
case TO_NEAREST:
|
|
__asm__ volatile("cfc1 $t0, $31\n\t"
|
|
"srl $t0, 2\n\t"
|
|
"sll $t0, 2\n\t"
|
|
"ctc1 $t0, $31\n\t");
|
|
break;
|
|
case TO_ZERO:
|
|
__asm__ volatile("cfc1 $t0, $31\n\t"
|
|
"srl $t0, 2\n\t"
|
|
"sll $t0, 2\n\t"
|
|
"addiu $t0, 1\n\t"
|
|
"ctc1 $t0, $31\n\t");
|
|
break;
|
|
case TO_PLUS_INFINITY:
|
|
__asm__ volatile("cfc1 $t0, $31\n\t"
|
|
"srl $t0, 2\n\t"
|
|
"sll $t0, 2\n\t"
|
|
"addiu $t0, 2\n\t"
|
|
"ctc1 $t0, $31\n\t");
|
|
break;
|
|
case TO_MINUS_INFINITY:
|
|
__asm__ volatile("cfc1 $t0, $31\n\t"
|
|
"srl $t0, 2\n\t"
|
|
"sll $t0, 2\n\t"
|
|
"addiu $t0, 3\n\t"
|
|
"ctc1 $t0, $31\n\t");
|
|
break;
|
|
}
|
|
}
|
|
|
|
int arithmeticOperations(flt_art_op_t op)
|
|
{
|
|
double fd_d = 0;
|
|
float fd_f = 0;
|
|
int i = 0;
|
|
round_mode_t rm;
|
|
for (rm = TO_NEAREST; rm <= TO_MINUS_INFINITY; rm ++) {
|
|
set_rounding_mode(rm);
|
|
printf("rounding mode: %s\n", round_mode_name[rm]);
|
|
for (i = 0; i < 24; i++)
|
|
{
|
|
switch(op) {
|
|
case ABSS:
|
|
UNOPff("abs.s");
|
|
printf("%s %f %f\n", flt_art_op_names[op], fd_f, fs_f[i]);
|
|
break;
|
|
case ABSD:
|
|
UNOPdd("abs.d");
|
|
printf("%s %lf %lf\n", flt_art_op_names[op], fd_d, fs_d[i]);
|
|
break;
|
|
case ADDS:
|
|
BINOPf("add.s");
|
|
printf("%s %f %f %f\n", flt_art_op_names[op], fd_f, fs_f[i], ft_f[i]);
|
|
break;
|
|
case ADDD:
|
|
BINOPd("add.d");
|
|
printf("%s %lf %lf %lf\n", flt_art_op_names[op], fd_d, fs_d[i], ft_d[i]);
|
|
break;
|
|
case DIVS:
|
|
BINOPf("div.s");
|
|
printf("%s %f %f %f\n", flt_art_op_names[op], fd_f, fs_f[i], ft_f[i]);
|
|
break;
|
|
case DIVD:
|
|
BINOPd("div.d");
|
|
printf("%s %lf %lf %lf\n", flt_art_op_names[op], fd_d, fs_d[i], ft_d[i]);
|
|
break;
|
|
case MULS:
|
|
BINOPf("mul.s");
|
|
printf("%s %f %f %f\n", flt_art_op_names[op], fd_f, fs_f[i], ft_f[i]);
|
|
break;
|
|
case MULD:
|
|
BINOPd("mul.d");
|
|
printf("%s %lf %lf %lf\n", flt_art_op_names[op], fd_d, fs_d[i], ft_d[i]);
|
|
break;
|
|
case NEGS:
|
|
UNOPff("neg.s");
|
|
printf("%s %f %f\n", flt_art_op_names[op], fd_f, fs_f[i]);
|
|
break;
|
|
case NEGD:
|
|
UNOPdd("neg.d");
|
|
printf("%s %lf %lf\n", flt_art_op_names[op], fd_d, fs_d[i]);
|
|
break;
|
|
case SQRTS:
|
|
UNOPff("sqrt.s");
|
|
printf("%s %f %f\n", flt_art_op_names[op], fd_f, fs_f[i]);
|
|
break;
|
|
case SQRTD:
|
|
UNOPdd("sqrt.d");
|
|
printf("%s %lf %lf\n", flt_art_op_names[op], fd_d, fs_d[i]);
|
|
break;
|
|
case SUBS:
|
|
BINOPf("sub.s");
|
|
printf("%s %f %f %f\n", flt_art_op_names[op], fd_f, fs_f[i], ft_f[i]);
|
|
break;
|
|
case SUBD:
|
|
BINOPd("sub.d");
|
|
printf("%s %lf %lf %lf\n", flt_art_op_names[op], fd_d, fs_d[i], ft_d[i]);
|
|
break;
|
|
case RECIPS:
|
|
#if (__mips==32) && (__mips_isa_rev>=2)
|
|
UNOPff("recip.s");
|
|
printf("%s %f %f\n", flt_art_op_names[op], fd_f, fs_f[i]);
|
|
#endif
|
|
break;
|
|
case RECIPD:
|
|
#if (__mips==32) && (__mips_isa_rev>=2)
|
|
UNOPdd("recip.d");
|
|
printf("%s %lf %lf\n", flt_art_op_names[op], fd_d, fs_d[i]);
|
|
#endif
|
|
break;
|
|
case RSQRTS:
|
|
#if (__mips==32) && (__mips_isa_rev>=2)
|
|
UNOPff("rsqrt.s");
|
|
printf("%s %f %f\n", flt_art_op_names[op], fd_f, fs_f[i]);
|
|
#endif
|
|
break;
|
|
case RSQRTD:
|
|
#if (__mips==32) && (__mips_isa_rev>=2)
|
|
UNOPdd("rsqrt.d");
|
|
printf("%s %lf %lf\n", flt_art_op_names[op], fd_d, fs_d[i]);
|
|
#endif
|
|
break;
|
|
default:
|
|
printf("error\n");
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int main()
|
|
{
|
|
flt_art_op_t op;
|
|
|
|
printf("-------------------------- %s --------------------------\n",
|
|
"test FPU Arithmetic Operations");
|
|
for (op = ABSS; op <= RECIPD; op++) {
|
|
arithmeticOperations(op);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|