changes access to rounding mode to fail explicitly instead of unintended behavior

This commit is contained in:
Eyck-Alexander Jentzsch 2024-07-31 12:20:25 +02:00
parent fd20e66f1f
commit f579ec6e48
1 changed files with 33 additions and 30 deletions

View File

@ -33,6 +33,7 @@
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
#include "fp_functions.h" #include "fp_functions.h"
#include <array>
extern "C" { extern "C" {
#include "internals.h" #include "internals.h"
@ -43,9 +44,10 @@ extern "C" {
#include <limits> #include <limits>
using this_t = uint8_t*; using this_t = uint8_t*;
const uint8_t rmm_map[] = { // this does not inlcude any reserved rm or the DYN rm, as DYN rm should be taken care of in the vm_impl
const std::array<uint8_t, 5> rmm_map = {
softfloat_round_near_even /*RNE*/, softfloat_round_minMag /*RTZ*/, softfloat_round_min /*RDN*/, softfloat_round_max /*RUP?*/, softfloat_round_near_even /*RNE*/, softfloat_round_minMag /*RTZ*/, softfloat_round_min /*RDN*/, softfloat_round_max /*RUP?*/,
softfloat_round_near_maxMag /*RMM*/, softfloat_round_max /*RTZ*/, softfloat_round_max /*RTZ*/, softfloat_round_max /*RTZ*/, softfloat_round_near_maxMag /*RMM*/
}; };
const uint32_t quiet_nan32 = 0x7fC00000; const uint32_t quiet_nan32 = 0x7fC00000;
@ -56,7 +58,7 @@ uint32_t fget_flags() { return softfloat_exceptionFlags & 0x1f; }
uint32_t fadd_s(uint32_t v1, uint32_t v2, uint8_t mode) { uint32_t fadd_s(uint32_t v1, uint32_t v2, uint8_t mode) {
float32_t v1f{v1}, v2f{v2}; float32_t v1f{v1}, v2f{v2};
softfloat_roundingMode = rmm_map[mode & 0x7]; softfloat_roundingMode = rmm_map.at(mode);
softfloat_exceptionFlags = 0; softfloat_exceptionFlags = 0;
float32_t r = f32_add(v1f, v2f); float32_t r = f32_add(v1f, v2f);
return r.v; return r.v;
@ -64,7 +66,7 @@ uint32_t fadd_s(uint32_t v1, uint32_t v2, uint8_t mode) {
uint32_t fsub_s(uint32_t v1, uint32_t v2, uint8_t mode) { uint32_t fsub_s(uint32_t v1, uint32_t v2, uint8_t mode) {
float32_t v1f{v1}, v2f{v2}; float32_t v1f{v1}, v2f{v2};
softfloat_roundingMode = rmm_map[mode & 0x7]; softfloat_roundingMode = rmm_map.at(mode);
softfloat_exceptionFlags = 0; softfloat_exceptionFlags = 0;
float32_t r = f32_sub(v1f, v2f); float32_t r = f32_sub(v1f, v2f);
return r.v; return r.v;
@ -72,7 +74,7 @@ uint32_t fsub_s(uint32_t v1, uint32_t v2, uint8_t mode) {
uint32_t fmul_s(uint32_t v1, uint32_t v2, uint8_t mode) { uint32_t fmul_s(uint32_t v1, uint32_t v2, uint8_t mode) {
float32_t v1f{v1}, v2f{v2}; float32_t v1f{v1}, v2f{v2};
softfloat_roundingMode = rmm_map[mode & 0x7]; softfloat_roundingMode = rmm_map.at(mode);
softfloat_exceptionFlags = 0; softfloat_exceptionFlags = 0;
float32_t r = f32_mul(v1f, v2f); float32_t r = f32_mul(v1f, v2f);
return r.v; return r.v;
@ -80,7 +82,7 @@ uint32_t fmul_s(uint32_t v1, uint32_t v2, uint8_t mode) {
uint32_t fdiv_s(uint32_t v1, uint32_t v2, uint8_t mode) { uint32_t fdiv_s(uint32_t v1, uint32_t v2, uint8_t mode) {
float32_t v1f{v1}, v2f{v2}; float32_t v1f{v1}, v2f{v2};
softfloat_roundingMode = rmm_map[mode & 0x7]; softfloat_roundingMode = rmm_map.at(mode);
softfloat_exceptionFlags = 0; softfloat_exceptionFlags = 0;
float32_t r = f32_div(v1f, v2f); float32_t r = f32_div(v1f, v2f);
return r.v; return r.v;
@ -88,7 +90,7 @@ uint32_t fdiv_s(uint32_t v1, uint32_t v2, uint8_t mode) {
uint32_t fsqrt_s(uint32_t v1, uint8_t mode) { uint32_t fsqrt_s(uint32_t v1, uint8_t mode) {
float32_t v1f{v1}; float32_t v1f{v1};
softfloat_roundingMode = rmm_map[mode & 0x7]; softfloat_roundingMode = rmm_map.at(mode);
softfloat_exceptionFlags = 0; softfloat_exceptionFlags = 0;
float32_t r = f32_sqrt(v1f); float32_t r = f32_sqrt(v1f);
return r.v; return r.v;
@ -126,22 +128,23 @@ uint32_t fcmp_s(uint32_t v1, uint32_t v2, uint32_t op) {
} }
uint32_t fcvt_s(uint32_t v1, uint32_t op, uint8_t mode) { uint32_t fcvt_s(uint32_t v1, uint32_t op, uint8_t mode) {
float32_t v1f{v1}; float32_t v1f{v1};
softfloat_exceptionFlags = 0; softfloat_exceptionFlags = 0;
float32_t r; float32_t r;
switch(op) { switch(op) {
case 0: { // w->s, fp to int32 case 0: { // FCVT__W__S
uint_fast32_t res = f32_to_i32(v1f, rmm_map[mode & 0x7], true); uint_fast32_t res = f32_to_i32(v1f, rmm_map.at(mode), true);
return (uint32_t)res; return (uint32_t)res;
} }
case 1: { // wu->s case 1: { // FCVT__WU__S
uint_fast32_t res = f32_to_ui32(v1f, rmm_map[mode & 0x7], true); uint_fast32_t res = f32_to_ui32(v1f, rmm_map.at(mode), true);
return (uint32_t)res; return (uint32_t)res;
} }
case 2: // s->w case 2: // FCVT__S__W
r = i32_to_f32(v1); r = i32_to_f32((int32_t)v1);
return r.v; return r.v;
case 3: // s->wu case 3: // FCVT__S__WU
r = ui32_to_f32(v1); r = ui32_to_f32(v1);
return r.v; return r.v;
} }
@ -164,7 +167,7 @@ uint32_t fmadd_s(uint32_t v1, uint32_t v2, uint32_t v3, uint32_t op, uint8_t mod
v1 ^= F32_SIGN; v1 ^= F32_SIGN;
break; break;
} }
softfloat_roundingMode = rmm_map[mode & 0x7]; softfloat_roundingMode = rmm_map.at(mode);
softfloat_exceptionFlags = 0; softfloat_exceptionFlags = 0;
float32_t res = softfloat_mulAddF32(v1, v2, v3, 0); float32_t res = softfloat_mulAddF32(v1, v2, v3, 0);
return res.v; return res.v;
@ -215,7 +218,7 @@ uint32_t fclass_s(uint32_t v1) {
} }
uint32_t fconv_d2f(uint64_t v1, uint8_t mode) { uint32_t fconv_d2f(uint64_t v1, uint8_t mode) {
softfloat_roundingMode = rmm_map[mode & 0x7]; softfloat_roundingMode = rmm_map.at(mode);
bool nan = (v1 & defaultNaNF64UI) == defaultNaNF64UI; bool nan = (v1 & defaultNaNF64UI) == defaultNaNF64UI;
if(nan) { if(nan) {
return defaultNaNF32UI; return defaultNaNF32UI;
@ -230,7 +233,7 @@ uint64_t fconv_f2d(uint32_t v1, uint8_t mode) {
if(nan) { if(nan) {
return defaultNaNF64UI; return defaultNaNF64UI;
} else { } else {
softfloat_roundingMode = rmm_map[mode & 0x7]; softfloat_roundingMode = rmm_map.at(mode);
float64_t res = f32_to_f64(float32_t{v1}); float64_t res = f32_to_f64(float32_t{v1});
return res.v; return res.v;
} }
@ -240,7 +243,7 @@ uint64_t fadd_d(uint64_t v1, uint64_t v2, uint8_t mode) {
bool nan = (v1 & defaultNaNF32UI) == quiet_nan32; bool nan = (v1 & defaultNaNF32UI) == quiet_nan32;
bool snan = softfloat_isSigNaNF32UI(v1); bool snan = softfloat_isSigNaNF32UI(v1);
float64_t v1f{v1}, v2f{v2}; float64_t v1f{v1}, v2f{v2};
softfloat_roundingMode = rmm_map[mode & 0x7]; softfloat_roundingMode = rmm_map.at(mode);
softfloat_exceptionFlags = 0; softfloat_exceptionFlags = 0;
float64_t r = f64_add(v1f, v2f); float64_t r = f64_add(v1f, v2f);
return r.v; return r.v;
@ -248,7 +251,7 @@ uint64_t fadd_d(uint64_t v1, uint64_t v2, uint8_t mode) {
uint64_t fsub_d(uint64_t v1, uint64_t v2, uint8_t mode) { uint64_t fsub_d(uint64_t v1, uint64_t v2, uint8_t mode) {
float64_t v1f{v1}, v2f{v2}; float64_t v1f{v1}, v2f{v2};
softfloat_roundingMode = rmm_map[mode & 0x7]; softfloat_roundingMode = rmm_map.at(mode);
softfloat_exceptionFlags = 0; softfloat_exceptionFlags = 0;
float64_t r = f64_sub(v1f, v2f); float64_t r = f64_sub(v1f, v2f);
return r.v; return r.v;
@ -256,7 +259,7 @@ uint64_t fsub_d(uint64_t v1, uint64_t v2, uint8_t mode) {
uint64_t fmul_d(uint64_t v1, uint64_t v2, uint8_t mode) { uint64_t fmul_d(uint64_t v1, uint64_t v2, uint8_t mode) {
float64_t v1f{v1}, v2f{v2}; float64_t v1f{v1}, v2f{v2};
softfloat_roundingMode = rmm_map[mode & 0x7]; softfloat_roundingMode = rmm_map.at(mode);
softfloat_exceptionFlags = 0; softfloat_exceptionFlags = 0;
float64_t r = f64_mul(v1f, v2f); float64_t r = f64_mul(v1f, v2f);
return r.v; return r.v;
@ -264,7 +267,7 @@ uint64_t fmul_d(uint64_t v1, uint64_t v2, uint8_t mode) {
uint64_t fdiv_d(uint64_t v1, uint64_t v2, uint8_t mode) { uint64_t fdiv_d(uint64_t v1, uint64_t v2, uint8_t mode) {
float64_t v1f{v1}, v2f{v2}; float64_t v1f{v1}, v2f{v2};
softfloat_roundingMode = rmm_map[mode & 0x7]; softfloat_roundingMode = rmm_map.at(mode);
softfloat_exceptionFlags = 0; softfloat_exceptionFlags = 0;
float64_t r = f64_div(v1f, v2f); float64_t r = f64_div(v1f, v2f);
return r.v; return r.v;
@ -272,7 +275,7 @@ uint64_t fdiv_d(uint64_t v1, uint64_t v2, uint8_t mode) {
uint64_t fsqrt_d(uint64_t v1, uint8_t mode) { uint64_t fsqrt_d(uint64_t v1, uint8_t mode) {
float64_t v1f{v1}; float64_t v1f{v1};
softfloat_roundingMode = rmm_map[mode & 0x7]; softfloat_roundingMode = rmm_map.at(mode);
softfloat_exceptionFlags = 0; softfloat_exceptionFlags = 0;
float64_t r = f64_sqrt(v1f); float64_t r = f64_sqrt(v1f);
return r.v; return r.v;
@ -315,11 +318,11 @@ uint64_t fcvt_d(uint64_t v1, uint32_t op, uint8_t mode) {
float64_t r; float64_t r;
switch(op) { switch(op) {
case 0: { // l->d, fp to int32 case 0: { // l->d, fp to int32
int64_t res = f64_to_i64(v1f, rmm_map[mode & 0x7], true); int64_t res = f64_to_i64(v1f, rmm_map.at(mode), true);
return (uint64_t)res; return (uint64_t)res;
} }
case 1: { // lu->s case 1: { // lu->s
uint64_t res = f64_to_ui64(v1f, rmm_map[mode & 0x7], true); uint64_t res = f64_to_ui64(v1f, rmm_map.at(mode), true);
return res; return res;
} }
case 2: // s->l case 2: // s->l
@ -334,7 +337,7 @@ uint64_t fcvt_d(uint64_t v1, uint32_t op, uint8_t mode) {
uint64_t fmadd_d(uint64_t v1, uint64_t v2, uint64_t v3, uint32_t op, uint8_t mode) { uint64_t fmadd_d(uint64_t v1, uint64_t v2, uint64_t v3, uint32_t op, uint8_t mode) {
// op should be {softfloat_mulAdd_subProd(2), softfloat_mulAdd_subC(1)} // op should be {softfloat_mulAdd_subProd(2), softfloat_mulAdd_subC(1)}
softfloat_roundingMode = rmm_map[mode & 0x7]; softfloat_roundingMode = rmm_map.at(mode);
softfloat_exceptionFlags = 0; softfloat_exceptionFlags = 0;
float64_t res = softfloat_mulAddF64(v1, v2, v3, op & 0x1); float64_t res = softfloat_mulAddF64(v1, v2, v3, op & 0x1);
if(op > 1) if(op > 1)
@ -393,9 +396,9 @@ uint64_t fcvt_32_64(uint32_t v1, uint32_t op, uint8_t mode) {
float64_t r; float64_t r;
switch(op) { switch(op) {
case 0: // l->s, fp to int32 case 0: // l->s, fp to int32
return f32_to_i64(v1f, rmm_map[mode & 0x7], true); return f32_to_i64(v1f, rmm_map.at(mode), true);
case 1: // wu->s case 1: // wu->s
return f32_to_ui64(v1f, rmm_map[mode & 0x7], true); return f32_to_ui64(v1f, rmm_map.at(mode), true);
case 2: // s->w case 2: // s->w
r = i32_to_f64(v1); r = i32_to_f64(v1);
return r.v; return r.v;
@ -411,11 +414,11 @@ uint32_t fcvt_64_32(uint64_t v1, uint32_t op, uint8_t mode) {
float32_t r; float32_t r;
switch(op) { switch(op) {
case 0: { // wu->s case 0: { // wu->s
int32_t r = f64_to_i32(float64_t{v1}, rmm_map[mode & 0x7], true); int32_t r = f64_to_i32(float64_t{v1}, rmm_map.at(mode), true);
return r; return r;
} }
case 1: { // wu->s case 1: { // wu->s
uint32_t r = f64_to_ui32(float64_t{v1}, rmm_map[mode & 0x7], true); uint32_t r = f64_to_ui32(float64_t{v1}, rmm_map.at(mode), true);
return r; return r;
} }
case 2: // l->s, fp to int32 case 2: // l->s, fp to int32