Petar Jovanovic ed74dc8a27 mips: allow Valgrind to be compiled for soft-float
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
2016-10-12 15:13:27 +00:00

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