1 /* Copyright (c) 2017 SiFive Inc. All rights reserved. 2 3 This copyrighted material is made available to anyone wishing to use, 4 modify, copy, or redistribute it subject to the terms and conditions 5 of the FreeBSD License. This program is distributed in the hope that 6 it will be useful, but WITHOUT ANY WARRANTY expressed or implied, 7 including the implied warranties of MERCHANTABILITY or FITNESS FOR 8 A PARTICULAR PURPOSE. A copy of this license is available at 9 http://www.opensource.org/licenses. 10 */ 11 12 #define _BSD_SOURCE 13 #include <picolibc.h> 14 #include <ieeefp.h> 15 16 #if defined(__riscv_flen) || defined (__riscv_zfinx) 17 static void fssr(unsigned value)18fssr(unsigned value) 19 { 20 __asm__ volatile ("fscsr %0" :: "r"(value)); 21 } 22 23 static unsigned frsr(void)24frsr(void) 25 { 26 unsigned value; 27 __asm__ volatile ("frcsr %0" : "=r" (value)); 28 return value; 29 } 30 31 static fp_rnd frm_fp_rnd(unsigned frm)32frm_fp_rnd (unsigned frm) 33 { 34 switch (frm) 35 { 36 case 0: return FP_RN; 37 case 1: return FP_RZ; 38 case 2: return FP_RM; 39 case 3: return FP_RP; 40 /* 4 ~ 7 is invalid value, so just retun FP_RP. */ 41 default:return FP_RP; 42 } 43 } 44 45 static fp_except frm_fp_except(unsigned except)46frm_fp_except (unsigned except) 47 { 48 fp_except fp = 0; 49 if (except & (1 << 0)) 50 fp |= FP_X_IMP; 51 if (except & (1 << 1)) 52 fp |= FP_X_UFL; 53 if (except & (1 << 2)) 54 fp |= FP_X_OFL; 55 if (except & (1 << 3)) 56 fp |= FP_X_DX; 57 if (except & (1 << 4)) 58 fp |= FP_X_INV; 59 return fp; 60 } 61 62 static unsigned frm_except(fp_except fp)63frm_except(fp_except fp) 64 { 65 unsigned except = 0; 66 if (fp & FP_X_IMP) 67 except |= (1 << 0); 68 if (fp & FP_X_UFL) 69 except |= (1 << 1); 70 if (fp & FP_X_OFL) 71 except |= (1 << 2); 72 if (fp & FP_X_DX) 73 except |= (1 << 3); 74 if (fp & FP_X_INV) 75 except |= (1 << 4); 76 return except; 77 } 78 79 #endif /* __riscv_flen */ 80 81 fp_except fpgetmask(void)82fpgetmask(void) 83 { 84 return 0; 85 } 86 87 fp_rnd fpgetround(void)88fpgetround(void) 89 { 90 #if defined(__riscv_flen) || defined (__riscv_zfinx) 91 unsigned rm = (frsr () >> 5) & 0x7; 92 return frm_fp_rnd (rm); 93 #else 94 return FP_RZ; 95 #endif /* __riscv_flen */ 96 } 97 98 fp_except fpgetsticky(void)99fpgetsticky(void) 100 { 101 #if defined(__riscv_flen) || defined (__riscv_zfinx) 102 return frm_fp_except(frsr ()); 103 #else 104 return 0; 105 #endif /* __riscv_flen */ 106 } 107 108 fp_except fpsetmask(fp_except mask)109fpsetmask(fp_except mask) 110 { 111 (void) mask; 112 return -1; 113 } 114 115 fp_rnd fpsetround(fp_rnd rnd_dir)116fpsetround(fp_rnd rnd_dir) 117 { 118 #if defined(__riscv_flen) || defined (__riscv_zfinx) 119 unsigned fsr = frsr (); 120 unsigned rm = (fsr >> 5) & 0x7; 121 unsigned new_rm; 122 switch (rnd_dir) 123 { 124 case FP_RN: new_rm = 0; break; 125 case FP_RZ: new_rm = 1; break; 126 case FP_RM: new_rm = 2; break; 127 case FP_RP: new_rm = 3; break; 128 default: return -1; 129 } 130 fssr (new_rm << 5 | (fsr & 0x1f)); 131 return frm_fp_rnd (rm); 132 #else 133 (void) rnd_dir; 134 return -1; 135 #endif /* __riscv_flen */ 136 } 137 138 fp_except fpsetsticky(fp_except sticky)139fpsetsticky(fp_except sticky) 140 { 141 #if defined(__riscv_flen) || defined (__riscv_zfinx) 142 unsigned fsr = frsr (); 143 fssr (frm_except(sticky) | (fsr & ~0x1f)); 144 return frm_fp_except(fsr); 145 #else 146 (void) sticky; 147 return -1; 148 #endif /* __riscv_flen */ 149 } 150 fpgetroundtoi(void)151fp_rdi fpgetroundtoi (void) 152 { 153 return 0; 154 } 155 fpsetroundtoi(fp_rdi rdi)156fp_rdi fpsetroundtoi (fp_rdi rdi) 157 { 158 (void) rdi; 159 return -1; 160 } 161