summaryrefslogtreecommitdiff
path: root/lib/nostd/sail.c
diff options
context:
space:
mode:
authorAlasdair Armstrong2019-10-15 19:16:15 +0100
committerAlasdair Armstrong2019-10-15 19:16:15 +0100
commit478a236c020866f30fc1e42149550c0a7a17a2f7 (patch)
treede5a0ccaebdab18f802b53b582ca7fe867bbb0cc /lib/nostd/sail.c
parent5056bf80156738b3ed146ae052f751fa703fecad (diff)
More work on bare-metal Sail
Diffstat (limited to 'lib/nostd/sail.c')
-rw-r--r--lib/nostd/sail.c255
1 files changed, 255 insertions, 0 deletions
diff --git a/lib/nostd/sail.c b/lib/nostd/sail.c
new file mode 100644
index 00000000..00394e27
--- /dev/null
+++ b/lib/nostd/sail.c
@@ -0,0 +1,255 @@
+
+#ifndef SAIL_INT64
+#define SAIL_INT64
+#endif
+
+#ifndef SAIL_BITS64
+#define SAIL_BITS64
+#endif
+
+#include <sail_alloc.h>
+#include <sail_failure.h>
+#include <sail.h>
+
+/* ********************************************************************** */
+/* Sail integers */
+/* ********************************************************************** */
+
+#if defined(SAIL_INT64) || defined(SAIL_INT128)
+
+sail_int CREATE_OF(sail_int, mach_int)(const mach_int op)
+{
+ return (sail_int) op;
+}
+
+mach_int CREATE_OF(mach_int, sail_int)(const sail_int op)
+{
+ if (MACH_INT_MIN < op && op < MACH_INT_MAX) {
+ return (mach_int) op;
+ } else {
+ sail_failure("Lost precision when converting from sail integer to machine integer");
+ return -1;
+ }
+}
+
+mach_int CONVERT_OF(mach_int, sail_int)(const sail_int op)
+{
+ if (MACH_INT_MIN < op && op < MACH_INT_MAX) {
+ return (mach_int) op;
+ } else {
+ sail_failure("Lost precision when converting from sail integer to machine integer");
+ return -1;
+ }
+}
+
+sail_int CONVERT_OF(sail_int, mach_int)(const mach_int op)
+{
+ return (sail_int) op;
+}
+
+bool eq_int(const sail_int op1, const sail_int op2)
+{
+ return op1 == op2;
+}
+
+bool EQUAL(sail_int)(const sail_int op1, const sail_int op2)
+{
+ return op1 == op2;
+}
+
+bool lt(const sail_int op1, const sail_int op2)
+{
+ return op1 < op2;
+}
+
+bool gt(const sail_int op1, const sail_int op2)
+{
+ return op1 > op2;
+}
+
+bool lteq(const sail_int op1, const sail_int op2)
+{
+ return op1 <= op2;
+}
+
+bool gteq(const sail_int op1, const sail_int op2)
+{
+ return op1 >= op2;
+}
+
+// FIXME: Add overflow checks
+sail_int shl_int(const sail_int op1, const sail_int op2)
+{
+ return op1 << op2;
+}
+
+mach_int shl_mach_int(const mach_int op1, const mach_int op2)
+{
+ return op1 << op2;
+}
+
+sail_int shr_int(const sail_int op1, const sail_int op2)
+{
+ return op1 >> op2;
+}
+
+mach_int shr_mach_int(const mach_int op1, const mach_int op2)
+{
+ return op1 >> op2;
+}
+
+sail_int undefined_int(const int n)
+{
+ return (sail_int) n;
+}
+
+sail_int undefined_range(const sail_int lower, const sail_int upper)
+{
+ return lower;
+}
+
+sail_int add_int(const sail_int op1, const sail_int op2)
+{
+ if ((op2 > 0) && (op1 > SAIL_INT_MAX - op2)) {
+ sail_failure("Sail integer addition would overflow");
+ return -1;
+ } else if ((op2 < 0) && (op1 < SAIL_INT_MIN - op2)) {
+ sail_failure("Sail integer addition would underflow");
+ return -1;
+ } else {
+ return op1 + op2;
+ }
+}
+
+sail_int sub_int(const sail_int op1, const sail_int op2)
+{
+ if ((op2 < 0) && (op1 > SAIL_INT_MAX + op2)) {
+ sail_failure("Sail integer subtraction would overflow");
+ return -1;
+ } else if ((op2 > 0) && (op1 < SAIL_INT_MIN + op2)) {
+ sail_failure("Sail integer subtraction would underflow");
+ return -1;
+ } else {
+ return op1 - op2;
+ }
+}
+
+sail_int sub_nat(const sail_int op1, const sail_int op2)
+{
+ sail_int rop = sub_int(op1, op2);
+ if (rop < 0) {
+ return (sail_int) 0;
+ } else {
+ return rop;
+ }
+}
+
+sail_int mult_int(const sail_int op1, const sail_int op2)
+{
+ if (op1 > SAIL_INT_MAX / op2) {
+ sail_failure("Sail integer multiplication would overflow");
+ return -1;
+ } else if (op1 < SAIL_INT_MIN / op2) {
+ sail_failure("Sail integer multiplication would underflow");
+ return -1;
+ } else {
+ return op1 * op2;
+ }
+}
+
+// FIXME: Make all division operators do the right thing with rounding
+sail_int ediv_int(const sail_int op1, const sail_int op2)
+{
+ return op1 / op2;
+}
+
+sail_int emod_int(const sail_int op1, const sail_int op2)
+{
+ return op1 % op2;
+}
+
+sail_int tdiv_int(const sail_int op1, const sail_int op2)
+{
+ return op1 / op2;
+}
+
+sail_int tmod_int(const sail_int op1, const sail_int op2)
+{
+ return op1 % op2;
+}
+
+sail_int fdiv_int(const sail_int op1, const sail_int op2)
+{
+ return op1 / op2;
+}
+
+sail_int fmod_int(const sail_int op1, const sail_int op2)
+{
+ return op1 % op2;
+}
+
+sail_int max_int(const sail_int op1, const sail_int op2)
+{
+ if (op1 < op2) {
+ return op2;
+ } else {
+ return op1;
+ }
+}
+
+sail_int min_int(const sail_int op1, const sail_int op2)
+{
+ if (op1 > op2) {
+ return op2;
+ } else {
+ return op1;
+ }
+}
+
+sail_int neg_int(const sail_int op)
+{
+ if (op == SAIL_INT_MIN) {
+ sail_failure("Sail integer negation would overflow");
+ return -1;
+ }
+ return -op;
+}
+
+sail_int abs_int(const sail_int op)
+{
+ if (op < 0) {
+ return neg_int(op);
+ } else {
+ return op;
+ }
+}
+
+sail_int pow_int(sail_int base, sail_int exp)
+{
+ sail_int result = 1;
+ while (true)
+ {
+ if (exp & 1) {
+ result *= base;
+ }
+ exp >>= 1;
+ if (!exp) {
+ break;
+ }
+ base *= base;
+ }
+ return result;
+}
+
+sail_int pow2(const sail_int exp)
+{
+ return pow_int(2, exp);
+}
+
+#else
+
+#endif
+
+/* ********************************************************************** */
+/* Sail bitvectors */
+/* ********************************************************************** */