mirror of
https://github.com/Zenithsiz/ftmemsim-valgrind.git
synced 2026-02-05 19:13:46 +00:00
Force "hardfloat" mode for inline assembly that uses FPU instructions, but pop original mode at the end of the assembly. Unhandled FPU instructions will be handled by the signal handler (env_unsup_insn). Skip MIPS specific tests for FPU if the code gets compiled for soft- float. This should allow Valgrind to be compiled as a soft-float binary, but that executable should be used for soft-float systems only. Related VEX change - r3261. Related issue - BZ#351282. Patch by Aleksandar Rikalo. git-svn-id: svn://svn.valgrind.org/valgrind/trunk@16039
245 lines
7.1 KiB
C
245 lines
7.1 KiB
C
#if defined(__mips_hard_float)
|
|
|
|
#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;
|
|
}
|
|
#else
|
|
int main() {
|
|
return 0;
|
|
}
|
|
#endif
|