4757e84ae31ffba3b13590de0e6aa7f93a213f63
[cavatools.git] / caveat / arith.h
1 /*
2 Copyright (c) 2020 Peter Hsu. All Rights Reserved. See LICENCE file for details.
3 */
4
5
6 #define F32_SIGN (0x1 << 31)
7 #define F64_SIGN (0x1L << 63)
8
9 #define sgnj32(a, b, n, x) ((FR(a).ui & ~F32_SIGN) | ((((x) ? FR(a).ui : (n) ? F32_SIGN : 0) ^ FR(b).ui) & F32_SIGN))
10 #define sgnj64(a, b, n, x) ((FR(a).ul & ~F64_SIGN) | ((((x) ? FR(a).ul : (n) ? F64_SIGN : 0) ^ FR(b).ul) & F64_SIGN))
11
12
13
14 #ifdef SOFT_FP
15
16
17 #include "internals.h"
18 #include "softfloat_types.h"
19 #include "softfloat.h"
20
21 #define RM cpu->state.fcsr.rmode
22 #define SRM(m) softfloat_roundingMode=((m)==7?RM:(m))
23 #define SET_FPX /* set_fp_exceptions() */
24
25 static inline float32_t defaultNaNF32UI() { union ui32_f32 u; u.ui= 0x7FC00000; return u.f; }
26 static inline float64_t defaultNaNF64UI() { union ui64_f64 u; u.ui=0x7FF8000000000000L; return u.f; }
27 #define f32_less(a, b) (f32_lt_quiet(a, b) || (f32_eq(a, b) && (a.v & F32_SIGN)))
28 #define f32_more(a, b) (f32_lt_quiet(b, a) || (f32_eq(b, a) && (b.v & F32_SIGN)))
29 static inline float32_t f32_min(float32_t a, float32_t b) { return (isNaNF32UI(a.v) && isNaNF32UI(b.v)) ? defaultNaNF32UI() : (f32_more(a, b) || isNaNF32UI(b.v)) ? a : b; }
30 static inline float32_t f32_max(float32_t a, float32_t b) { return (isNaNF32UI(a.v) && isNaNF32UI(b.v)) ? defaultNaNF32UI() : (f32_less(a, b) || isNaNF32UI(b.v)) ? a : b; }
31 #define f64_less(a, b) (f64_lt_quiet(a, b) || (f64_eq(a, b) && (a.v & F64_SIGN)))
32 #define f64_more(a, b) (f64_lt_quiet(b, a) || (f64_eq(b, a) && (b.v & F64_SIGN)))
33 static inline float64_t f64_min(float64_t a, float64_t b) { return (isNaNF64UI(a.v) && isNaNF64UI(b.v)) ? defaultNaNF64UI() : (f64_more(a, b) || isNaNF64UI(b.v)) ? a : b; }
34 static inline float64_t f64_max(float64_t a, float64_t b) { return (isNaNF64UI(a.v) && isNaNF64UI(b.v)) ? defaultNaNF64UI() : (f64_less(a, b) || isNaNF64UI(b.v)) ? a : b; }
35
36
37 #else
38
39
40 #include <fenv.h>
41 static long tmp_rm;
42 #define SRM(rm) if (rm!=7) { tmp_rm=fegetround(); fesetround(riscv_to_c_rm(rm)); }
43 #define RRM(rm) if(rm!=7) fesetround(tmp_rm);
44 #define SET_FPX ;/* set_fp_exceptions() */
45
46 static inline long riscv_to_c_rm(long rm)
47 {
48 switch (rm) {
49 case /* RNE */ 0x0: return FE_TONEAREST;
50 case /* RTZ */ 0x1: return FE_TOWARDZERO;
51 case /* RDN */ 0x2: return FE_DOWNWARD;
52 case /* RUP */ 0x3: return FE_UPWARD;
53 default: abort();
54 }
55 }
56
57
58 #endif
59
60
61
62 // Following copied from Spike
63
64 static inline unsigned long mulhu(unsigned long a, unsigned long b)
65 {
66 unsigned long t;
67 unsigned int y1, y2, y3;
68 unsigned long a0 = (unsigned int)a, a1 = a >> 32;
69 unsigned long b0 = (unsigned int)b, b1 = b >> 32;
70
71 t = a1*b0 + ((a0*b0) >> 32);
72 y1 = t;
73 y2 = t >> 32;
74
75 t = a0*b1 + y1;
76 y1 = t;
77
78 t = a1*b1 + y2 + (t >> 32);
79 y2 = t;
80 y3 = t >> 32;
81
82 return ((unsigned long)y3 << 32) | y2;
83 }
84
85 static inline long mulh(long a, long b)
86 {
87 int negate = (a < 0) != (b < 0);
88 unsigned long res = mulhu(a < 0 ? -a : a, b < 0 ? -b : b);
89 return negate ? ~res + (a * b == 0) : res;
90 }
91
92 static inline long mulhsu(long a, unsigned long b)
93 {
94 int negate = a < 0;
95 unsigned long res = mulhu(a < 0 ? -a : a, b);
96 return negate ? ~res + (a * b == 0) : res;
97 }