mirror of
https://github.com/ioacademy-jikim/debugging
synced 2025-06-11 09:56:29 +00:00
114 lines
2.9 KiB
C
114 lines
2.9 KiB
C
#include <assert.h>
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <stdint.h>
|
|
#include <inttypes.h>
|
|
#include "opcodes.h"
|
|
|
|
/* Test "convert to fixed" with "per fpc" rounding.
|
|
Covers all generally available rounding modes.
|
|
*/
|
|
|
|
void
|
|
set_rounding_mode(unsigned mode)
|
|
{
|
|
register unsigned r asm("1") = mode;
|
|
__asm__ volatile ( SFPC(1) : : "d"(r) );
|
|
}
|
|
|
|
unsigned
|
|
get_rounding_mode(void)
|
|
{
|
|
unsigned fpc;
|
|
|
|
__asm__ volatile ("stfpc %0\n\t" : "=m"(fpc));
|
|
|
|
return fpc & 0x7;
|
|
}
|
|
|
|
|
|
const char *
|
|
rtext(unsigned fpc_round)
|
|
{
|
|
switch (fpc_round) {
|
|
case 0: return "[-> near]";
|
|
case 1: return "[-> zero]";
|
|
case 2: return "[-> +inf]";
|
|
case 3: return "[-> -inf]";
|
|
}
|
|
assert(0);
|
|
}
|
|
|
|
#define convert_to_int(opcode,src_type,dst_type,dst_fmt,round,value) \
|
|
do { \
|
|
src_type src = value; \
|
|
dst_type dst; \
|
|
unsigned cc; \
|
|
\
|
|
__asm__ volatile (opcode " %[dst]," #round ",%[src]\n\t" \
|
|
"ipm %[cc]\n\t" \
|
|
"srl %[cc],28\n\t" \
|
|
: [dst] "=d"(dst), [cc] "=d"(cc) \
|
|
: [src] "f"(src) \
|
|
: "cc"); \
|
|
\
|
|
printf("%s %f\t-> %"dst_fmt"\tcc = %u\n", \
|
|
opcode, src, dst, cc); \
|
|
} while (0)
|
|
|
|
|
|
#define cfebr(value) \
|
|
convert_to_int("cfebr",float,int32_t,PRId32,0,value)
|
|
#define cfdbr(value) \
|
|
convert_to_int("cfdbr",double,int32_t,PRId32,0,value)
|
|
#define cgebr(value) \
|
|
convert_to_int("cgebr",float,int64_t,PRId64,0,value)
|
|
#define cgdbr(value) \
|
|
convert_to_int("cgdbr",double,int64_t,PRId64,0,value)
|
|
|
|
int main(void)
|
|
{
|
|
int i, j;
|
|
static const unsigned rmodes[] = { 0, 1, 2, 3 };
|
|
static const float fval[] = {
|
|
1.25f, 1.5f, 2.5f, 1.75f, -1.25f, -1.5f, -2.5f, -1.75f, 0.0f,
|
|
};
|
|
static const double dval[] = {
|
|
1.25, 1.5, 2.5, 1.75, -1.25, -1.5, -2.5, -1.75, 0.0,
|
|
};
|
|
|
|
|
|
for (i = 0; i < sizeof rmodes / sizeof rmodes[0]; ++i) {
|
|
printf("setting rounding mode to %s\n", rtext(rmodes[i]));
|
|
set_rounding_mode(rmodes[i]);
|
|
assert(get_rounding_mode() == rmodes[i]);
|
|
|
|
/* f32 -> i32 */
|
|
for (j = 0; j < sizeof fval / sizeof fval[0]; ++j) {
|
|
cfebr(fval[j]);
|
|
assert(get_rounding_mode() == rmodes[i]);
|
|
}
|
|
|
|
/* f32 -> i64 */
|
|
for (j = 0; j < sizeof fval / sizeof fval[0]; ++j) {
|
|
cgebr(fval[j]);
|
|
assert(get_rounding_mode() == rmodes[i]);
|
|
}
|
|
|
|
/* f64 -> i32 */
|
|
for (j = 0; j < sizeof dval / sizeof dval[0]; ++j) {
|
|
cfdbr(dval[j]);
|
|
assert(get_rounding_mode() == rmodes[i]);
|
|
}
|
|
|
|
/* f64 -> i64 */
|
|
for (j = 0; j < sizeof dval / sizeof dval[0]; ++j) {
|
|
cgdbr(dval[j]);
|
|
assert(get_rounding_mode() == rmodes[i]);
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
|
}
|