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 #include <ieeefp.h> 13 14 #ifdef __riscv_flen 15 static void fssr(unsigned value)16fssr(unsigned value) 17 { 18 __asm__ volatile ("fscsr %0" :: "r"(value)); 19 } 20 21 static unsigned frsr(void)22frsr(void) 23 { 24 unsigned value; 25 __asm__ volatile ("frcsr %0" : "=r" (value)); 26 return value; 27 } 28 29 static fp_rnd frm_fp_rnd(unsigned frm)30frm_fp_rnd (unsigned frm) 31 { 32 switch (frm) 33 { 34 case 0: return FP_RN; 35 case 1: return FP_RZ; 36 case 2: return FP_RM; 37 case 3: return FP_RP; 38 /* 4 ~ 7 is invalid value, so just retun FP_RP. */ 39 default:return FP_RP; 40 } 41 } 42 43 static fp_except frm_fp_except(unsigned except)44frm_fp_except (unsigned except) 45 { 46 fp_except fp = 0; 47 if (except & (1 << 0)) 48 fp |= FP_X_IMP; 49 if (except & (1 << 1)) 50 fp |= FP_X_UFL; 51 if (except & (1 << 2)) 52 fp |= FP_X_OFL; 53 if (except & (1 << 3)) 54 fp |= FP_X_DX; 55 if (except & (1 << 4)) 56 fp |= FP_X_INV; 57 return fp; 58 } 59 60 static unsigned frm_except(fp_except fp)61frm_except(fp_except fp) 62 { 63 unsigned except = 0; 64 if (fp & FP_X_IMP) 65 except |= (1 << 0); 66 if (fp & FP_X_UFL) 67 except |= (1 << 1); 68 if (fp & FP_X_OFL) 69 except |= (1 << 2); 70 if (fp & FP_X_DX) 71 except |= (1 << 3); 72 if (fp & FP_X_INV) 73 except |= (1 << 4); 74 return except; 75 } 76 77 #endif /* __riscv_flen */ 78 79 fp_except fpgetmask(void)80fpgetmask(void) 81 { 82 return 0; 83 } 84 85 fp_rnd fpgetround(void)86fpgetround(void) 87 { 88 #ifdef __riscv_flen 89 unsigned rm = (frsr () >> 5) & 0x7; 90 return frm_fp_rnd (rm); 91 #else 92 return FP_RZ; 93 #endif /* __riscv_flen */ 94 } 95 96 fp_except fpgetsticky(void)97fpgetsticky(void) 98 { 99 #ifdef __riscv_flen 100 return frm_fp_except(frsr ()); 101 #else 102 return 0; 103 #endif /* __riscv_flen */ 104 } 105 106 fp_except fpsetmask(fp_except mask)107fpsetmask(fp_except mask) 108 { 109 (void) mask; 110 return -1; 111 } 112 113 fp_rnd fpsetround(fp_rnd rnd_dir)114fpsetround(fp_rnd rnd_dir) 115 { 116 #ifdef __riscv_flen 117 unsigned fsr = frsr (); 118 unsigned rm = (fsr >> 5) & 0x7; 119 unsigned new_rm; 120 switch (rnd_dir) 121 { 122 case FP_RN: new_rm = 0; break; 123 case FP_RZ: new_rm = 1; break; 124 case FP_RM: new_rm = 2; break; 125 case FP_RP: new_rm = 3; break; 126 default: return -1; 127 } 128 fssr (new_rm << 5 | (fsr & 0x1f)); 129 return frm_fp_rnd (rm); 130 #else 131 (void) rnd_dir; 132 return -1; 133 #endif /* __riscv_flen */ 134 } 135 136 fp_except fpsetsticky(fp_except sticky)137fpsetsticky(fp_except sticky) 138 { 139 #ifdef __riscv_flen 140 unsigned fsr = frsr (); 141 fssr (frm_except(sticky) | (fsr & ~0x1f)); 142 return frm_fp_except(fsr); 143 #else 144 (void) sticky; 145 return -1; 146 #endif /* __riscv_flen */ 147 } 148 fpgetroundtoi(void)149fp_rdi fpgetroundtoi (void) 150 { 151 return 0; 152 } 153 fpsetroundtoi(fp_rdi rdi)154fp_rdi fpsetroundtoi (fp_rdi rdi) 155 { 156 (void) rdi; 157 return -1; 158 } 159