summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/nostd/arch/x86/sail_spinlock.S68
-rw-r--r--lib/nostd/sail.c220
-rw-r--r--lib/nostd/sail.h159
-rw-r--r--lib/nostd/sail_arena.c4
-rw-r--r--lib/nostd/sail_failure.h7
-rw-r--r--lib/nostd/sail_spinlock.h44
-rw-r--r--lib/nostd/stubs/sail_failure.c12
7 files changed, 437 insertions, 77 deletions
diff --git a/lib/nostd/arch/x86/sail_spinlock.S b/lib/nostd/arch/x86/sail_spinlock.S
deleted file mode 100644
index 517a969d..00000000
--- a/lib/nostd/arch/x86/sail_spinlock.S
+++ /dev/null
@@ -1,68 +0,0 @@
-
-/*
- * Enabling and disabling interrupts setting is clearly not going
- * to be very useful for running on x86 in Linux userspace, but
- * mostly here just to think about what we might need for ARM
- */
-.macro enable_interrupts
-#ifdef SAIL_DISABLE_INTERRUPTS
- sti
-#endif
-.endm
-
-.macro disable_interrupts
-#ifdef SAIL_DISABLE_INTERRUPTS
- cli
-#endif
-.endm
-
-sail_spin_unlock:
- movl $1, (%rdi)
- xorl %eax, %eax
- enable_interrupts
- ret
-
- .globl sail_spin_unlock
-
-/* Attempt to aquire the lock. zero flag will be set on success, otherwise set */
-.macro acquire reg, mem
- disable_interrupts
- movl $0, \reg
- xchgl \reg, \mem
- cmpl $1, \reg
-.endm
-
-sail_spin_lock:
- /* If the value pointed to by %rdi is equal to 0 (locked), then spin */
- cmpl $0, (%rdi)
- je .spin
-.acquire:
- acquire %eax, (%rdi)
-#ifdef SAIL_DISABLE_INTERRUPTS
- jnz .failed
-#else
- jnz .spin
-#endif
- xorl %eax, %eax
- ret
-.failed:
- enable_interrupts
-.spin:
- pause
- cmpl $0, (%rdi)
- je .spin
- jmp .acquire
-
- .globl sail_spin_lock
-
-sail_spin_trylock:
- acquire %eax, (%rdi)
- jnz .failed_try
- xorl %eax, %eax
- ret
-.failed_try:
- enable_interrupts
- movl $1, %eax
- ret
-
- .globl sail_spin_trylock
diff --git a/lib/nostd/sail.c b/lib/nostd/sail.c
index fc42f620..d25f5eae 100644
--- a/lib/nostd/sail.c
+++ b/lib/nostd/sail.c
@@ -2,6 +2,7 @@
#include <sail_failure.h>
#include <sail.h>
+
/* ********************************************************************** */
/* Sail strings */
/* ********************************************************************** */
@@ -338,3 +339,222 @@ sail_int pow2(const sail_int exp)
/* ********************************************************************** */
/* Sail bitvectors */
/* ********************************************************************** */
+
+lbits CONVERT_OF(lbits, fbits)(const fbits op, const uint64_t len, const bool order)
+{
+ lbits rop;
+ rop.len = len;
+ rop.bits = op;
+ return rop;
+}
+
+fbits CONVERT_OF(fbits, lbits)(const lbits op, const bool direction)
+{
+ return op.bits;
+}
+
+sbits CONVERT_OF(sbits, lbits)(const lbits op, const bool order)
+{
+ return op;
+}
+
+lbits CONVERT_OF(lbits, sbits)(const sbits op, const bool order)
+{
+ return op;
+}
+
+lbits UNDEFINED(lbits)(const sail_int len)
+{
+ lbits rop;
+ rop.bits = 0;
+ rop.len = (uint64_t) len;
+ return rop;
+}
+
+bool eq_bits(const lbits op1, const lbits op2)
+{
+ return op1.bits == op2.bits;
+}
+
+bool EQUAL(lbits)(const lbits op1, const lbits op2)
+{
+ return op1.bits == op2.bits;
+}
+
+bool neq_bits(const lbits op1, const lbits op2)
+{
+ return op1.bits != op2.bits;
+}
+
+lbits not_bits(const lbits op)
+{
+ lbits rop;
+ rop.bits = (~op.bits) & sail_bzhi_u64(UINT64_MAX, op.len);
+ rop.len = op.len;
+ return rop;
+}
+
+lbits and_bits(const lbits op1, const lbits op2)
+{
+ lbits rop;
+ rop.bits = op1.bits & op2.bits;
+ rop.len = op1.len;
+ return rop;
+}
+
+lbits or_bits(const lbits op1, const lbits op2)
+{
+ lbits rop;
+ rop.bits = op1.bits | op2.bits;
+ rop.len = op1.len;
+ return rop;
+}
+
+lbits xor_bits(const lbits op1, const lbits op2)
+{
+ lbits rop;
+ rop.bits = op1.bits ^ op2.bits;
+ rop.len = op1.len;
+ return rop;
+}
+
+lbits add_bits(const lbits op1, const lbits op2)
+{
+ lbits rop;
+ rop.bits = (op1.bits + op2.bits) & sail_bzhi_u64(UINT64_MAX, op1.len);
+ rop.len = op1.len;
+ return rop;
+}
+
+lbits sub_bits(const lbits op1, const lbits op2)
+{
+ lbits rop;
+ rop.bits = (op1.bits - op2.bits) & sail_bzhi_u64(UINT64_MAX, op1.len);
+ rop.len = op1.len;
+ return rop;
+}
+
+lbits add_bits_int(const lbits op1, const sail_int op2)
+{
+ lbits rop;
+ rop.bits = (op1.bits + ((uint64_t) op2)) & sail_bzhi_u64(UINT64_MAX, op1.len);
+ rop.len = op1.len;
+ return rop;
+}
+
+
+lbits sub_bits_int(const lbits op1, const sail_int op2)
+{
+ lbits rop;
+ rop.bits = (op1.bits - ((uint64_t) op2)) & sail_bzhi_u64(UINT64_MAX, op1.len);
+ rop.len = op1.len;
+ return rop;
+}
+
+sail_int sail_unsigned(const lbits op)
+{
+ return (sail_int) op.bits;
+}
+
+sail_int sail_signed(const lbits op)
+{
+ return (sail_int) ((int64_t) op.bits);
+}
+
+fbits bitvector_access(const lbits bv, const sail_int n)
+{
+ return 1 & (bv.bits >> ((uint64_t) n));
+}
+
+lbits slice(const lbits op, const sail_int start, const sail_int len)
+{
+ uint64_t l = len;
+ lbits rop;
+ rop.bits = sail_bzhi_u64(op.bits >> ((uint64_t) start), l);
+ rop.len = l;
+ return rop;
+}
+
+lbits set_slice(const sail_int len,
+ const sail_int slen,
+ const lbits op,
+ const sail_int start,
+ const lbits slice)
+{
+ uint64_t s = start;
+ uint64_t mask = (1 << (uint64_t) slen) - 1;
+ lbits rop;
+ rop.len = op.len;
+ rop.bits = op.bits;
+ rop.bits &= ~(mask << s);
+ rop.bits |= slice.bits << s;
+ return rop;
+}
+
+lbits append(const lbits op1, const lbits op2)
+{
+ lbits rop;
+ rop.bits = (op1.bits << op2.len) | op2.bits;
+ rop.len = op1.len + op2.len;
+ return rop;
+}
+
+sail_int length_lbits(const lbits op)
+{
+ return (sail_int) op.len;
+}
+
+lbits zeros(const sail_int len)
+{
+ lbits rop;
+ rop.bits = 0;
+ rop.len = (uint64_t) len;
+ return rop;
+}
+
+lbits replicate_bits(const lbits op, const sail_int n)
+{
+ return op;
+}
+
+lbits get_slice_int(const sail_int len, const sail_int n, const sail_int start)
+{
+ return zeros(len);
+}
+
+sail_int set_slice_int(const sail_int len, const sail_int n, const sail_int start, const lbits slice)
+{
+ return n;
+}
+
+lbits vector_subrange_lbits(const lbits op, const sail_int n, const sail_int m)
+{
+ return op;
+}
+
+lbits vector_update_subrange_lbits(const lbits op, const sail_int n, const sail_int m, const lbits slice)
+{
+ return op;
+}
+
+/* ********************************************************************** */
+/* Sail reals */
+/* ********************************************************************** */
+
+void CREATE(real)(double *r) {}
+void KILL(real)(double *r) {}
+
+void to_real(real *rop, const sail_int op)
+{
+ *rop = (double) op;
+}
+
+void div_real(real *rop, const real op1, const real op2)
+{
+ *rop = op1 / op2;
+}
+
+sail_int round_up(const real op)
+{
+ return (sail_int) op;
+}
diff --git a/lib/nostd/sail.h b/lib/nostd/sail.h
index fbc7b235..d553e6b3 100644
--- a/lib/nostd/sail.h
+++ b/lib/nostd/sail.h
@@ -8,6 +8,19 @@
#include <stdint.h>
#include <stdbool.h>
+#ifdef SAIL_X86INTRIN
+#include <x64intrin.h>
+#endif
+
+static inline uint64_t sail_bzhi_u64(uint64_t op1, uint64_t op2)
+{
+#ifdef SAIL_X64INTRIN
+ return _bzhi_u64(op1, op2);
+#else
+ return (op1 << (64 - op2)) >> (64 - op2);
+#endif
+}
+
/*
* The Sail compiler expects functions to follow a specific naming
* convention for allocation, deallocation, and (deep)-copying. These
@@ -95,8 +108,6 @@ bool EQUAL(sail_string)(const sail_string, const sail_string);
void concat_str(sail_string *stro, const sail_string str1, const sail_string str2);
bool string_startswith(sail_string s, sail_string prefix);
-unit sail_assert(bool, sail_string);
-
/* ********************************************************************** */
/* Sail integers */
/* ********************************************************************** */
@@ -120,6 +131,7 @@ static inline bool EQUAL(mach_int)(const mach_int a, const mach_int b)
* function prototypes that work for either case.
*/
#if defined(SAIL_INT64) || defined(SAIL_INT128)
+
#ifdef SAIL_INT64
typedef int64_t sail_int;
#define SAIL_INT_MAX INT64_MAX
@@ -130,9 +142,22 @@ typedef __int128 sail_int;
#define SAIL_INT_MIN (~SAIL_INT_MAX)
#endif
#define SAIL_INT_FUNCTION(fname, ...) sail_int fname(__VA_ARGS__)
+
+static inline uint64_t sail_int_get_ui(const sail_int op)
+{
+ return (uint64_t) op;
+}
+
#else
+
typedef mpz_t sail_int;
#define SAIL_INT_FUNCTION(fname, ...) void fname(sail_int*, __VA_ARGS__)
+
+static inline uint64_t sail_int_get_ui(const sail_int op)
+{
+ return (uint64_t) mpz_get_ui(op);
+}
+
#endif
SAIL_INT_FUNCTION(CREATE_OF(sail_int, mach_int), const mach_int);
@@ -210,6 +235,20 @@ SAIL_INT_FUNCTION(pow2, const sail_int);
typedef uint64_t fbits;
+static inline bool EQUAL(fbits)(const fbits op1, const fbits op2)
+{
+ return op1 == op2;
+}
+
+static inline fbits safe_rshift(const fbits x, const fbits n)
+{
+ if (n >= 64) {
+ return 0;
+ } else {
+ return x >> n;
+ }
+}
+
/*
* For backwards compatability with older Sail C libraries
*/
@@ -220,21 +259,133 @@ typedef struct {
uint64_t bits;
} sbits;
+static inline sbits CONVERT_OF(sbits, fbits)(const fbits op, const uint64_t len, const bool order)
+{
+ sbits rop;
+ rop.len = len;
+ rop.bits = op;
+ return rop;
+}
+
+static inline fbits CONVERT_OF(fbits, sbits)(const sbits op, const bool order)
+{
+ return op.bits;
+}
+
+/*
+ * If the SAIL_BITS64 symbol is defined, we will use sbits as the
+ * lbits type.
+ */
+
#ifdef SAIL_BITS64
+
typedef sbits lbits;
#define SAIL_BITS_FUNCTION(fname, ...) lbits fname(__VA_ARGS__)
+
+static inline lbits CREATE_OF(lbits, fbits)(const fbits op, const uint64_t len, const bool order)
+{
+ lbits rop;
+ rop.bits = op;
+ rop.len = len;
+ return rop;
+}
+
+static inline lbits CREATE_OF(lbits, sbits)(const sbits op, const bool order)
+{
+ return op;
+}
+
#else
+
typedef struct {
mp_bitcnt_t len;
mpz_t *bits;
} lbits;
#define SAIL_BITS_FUNCTION(fname, ...) void fname(lbits*, __VA_ARGS__)
SAIL_BUILTIN_TYPE(lbits)
-#endif
SAIL_BITS_FUNCTION(CREATE_OF(lbits, fbits), const fbits, const uint64_t, const bool);
-SAIL_BITS_FUNCTION(RECREATE_OF(lbits, fbits), const fbits, const uint64_t, const bool);
SAIL_BITS_FUNCTION(CREATE_OF(lbits, sbits), const fbits, const bool);
+SAIL_BITS_FUNCTION(RECREATE_OF(lbits, fbits), const fbits, const uint64_t, const bool);
SAIL_BITS_FUNCTION(RECREATE_OF(lbits, sbits), const fbits, const bool);
#endif
+
+SAIL_BITS_FUNCTION(CONVERT_OF(lbits, fbits), const fbits, const uint64_t, const bool);
+fbits CONVERT_OF(fbits, lbits)(const lbits, const bool);
+SAIL_BITS_FUNCTION(CONVERT_OF(lbits, sbits), const sbits, const bool);
+sbits CONVERT_OF(sbits, lbits)(const lbits, const bool);
+
+SAIL_BITS_FUNCTION(UNDEFINED(lbits), const sail_int);
+
+bool eq_bits(const lbits, const lbits);
+bool EQUAL(lbits)(const lbits, const lbits);
+bool neq_bits(const lbits, const lbits);
+
+SAIL_BITS_FUNCTION(not_bits, const lbits);
+SAIL_BITS_FUNCTION(and_bits, const lbits, const lbits);
+SAIL_BITS_FUNCTION(or_bits, const lbits, const lbits);
+SAIL_BITS_FUNCTION(xor_bits, const lbits, const lbits);
+
+SAIL_BITS_FUNCTION(add_bits, const lbits, const lbits);
+SAIL_BITS_FUNCTION(sub_bits, const lbits, const lbits);
+SAIL_BITS_FUNCTION(add_bits_int, const lbits, const sail_int);
+SAIL_BITS_FUNCTION(sub_bits_int, const lbits, const sail_int);
+
+SAIL_INT_FUNCTION(sail_signed, const lbits op);
+SAIL_INT_FUNCTION(sail_unsigned, const lbits op);
+
+fbits bitvector_access(const lbits bv, const sail_int n);
+SAIL_BITS_FUNCTION(slice, const lbits, const sail_int, const sail_int);
+SAIL_BITS_FUNCTION(set_slice, const sail_int len, const sail_int slen, const lbits op, const sail_int start, const lbits slice);
+SAIL_BITS_FUNCTION(append, const lbits, const lbits);
+SAIL_INT_FUNCTION(length_lbits, const lbits);
+SAIL_BITS_FUNCTION(zeros, const sail_int);
+SAIL_BITS_FUNCTION(replicate_bits, const lbits op, const sail_int n);
+SAIL_BITS_FUNCTION(get_slice_int, const sail_int len, const sail_int n, const sail_int start);
+SAIL_INT_FUNCTION(set_slice_int, const sail_int len, const sail_int n, const sail_int start, const lbits slice);
+SAIL_BITS_FUNCTION(vector_subrange_lbits, const lbits op, const sail_int n, const sail_int m);
+SAIL_BITS_FUNCTION(vector_update_subrange_lbits, const lbits op, const sail_int n, const sail_int m, const lbits slice);
+
+/* ********************************************************************** */
+/* Sail reals */
+/* ********************************************************************** */
+
+#ifdef SAIL_FLOATING_REAL
+typedef double real;
+#else
+typedef mpq_t real;
+#endif
+
+SAIL_BUILTIN_TYPE(real);
+
+void CREATE_OF(real, sail_string)(real *rop, const sail_string op);
+void CONVERT_OF(real, sail_string)(real *rop, const sail_string op);
+
+void UNDEFINED(real)(real *rop, unit u);
+
+void neg_real(real *rop, const real op);
+
+void mult_real(real *rop, const real op1, const real op2);
+void sub_real(real *rop, const real op1, const real op2);
+void add_real(real *rop, const real op1, const real op2);
+void div_real(real *rop, const real op1, const real op2);
+
+void sqrt_real(real *rop, const real op);
+void abs_real(real *rop, const real op);
+
+SAIL_INT_FUNCTION(round_up, const real op);
+SAIL_INT_FUNCTION(round_down, const real op);
+
+void to_real(real *rop, const sail_int op);
+
+bool EQUAL(real)(const real op1, const real op2);
+
+bool lt_real(const real op1, const real op2);
+bool gt_real(const real op1, const real op2);
+bool lteq_real(const real op1, const real op2);
+bool gteq_real(const real op1, const real op2);
+
+void real_power(real *rop, const real base, const sail_int exp);
+
+#endif
diff --git a/lib/nostd/sail_arena.c b/lib/nostd/sail_arena.c
index f0ed5f90..d2bc17ac 100644
--- a/lib/nostd/sail_arena.c
+++ b/lib/nostd/sail_arena.c
@@ -7,14 +7,14 @@
static unsigned char *sail_arena_buffer;
static size_t sail_arena_length;
static size_t sail_arena_offset;
-static volatile int sail_arena_lock;
+static struct sail_spinlock sail_arena_lock;
void sail_arena_init(void *buffer, size_t length)
{
sail_arena_buffer = buffer;
sail_arena_length = length;
sail_arena_offset = 0;
- sail_arena_lock = 1;
+ sail_spin_init(&sail_arena_lock);
}
void sail_arena_reset(void)
diff --git a/lib/nostd/sail_failure.h b/lib/nostd/sail_failure.h
index fd339097..61ada596 100644
--- a/lib/nostd/sail_failure.h
+++ b/lib/nostd/sail_failure.h
@@ -1,6 +1,8 @@
#ifndef __SAIL_FAILURE__
#define __SAIL_FAILURE__
+#include <stdbool.h>
+
/*
* Called when some builtin hits an unexpected case, such as overflow
* when using 64- or 128-bit integers.
@@ -12,4 +14,9 @@ void sail_failure(char *message);
*/
void sail_match_failure(char *message);
+/*
+ * Implements the Sail assert construct
+ */
+int sail_assert(bool result, char *message);
+
#endif
diff --git a/lib/nostd/sail_spinlock.h b/lib/nostd/sail_spinlock.h
index 5e776b46..d69672dd 100644
--- a/lib/nostd/sail_spinlock.h
+++ b/lib/nostd/sail_spinlock.h
@@ -1,10 +1,48 @@
+/*
+ * Copyright 2018 The Hafnium Authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
#ifndef __SAIL_SPINLOCK__
#define __SAIL_SPINLOCK__
-int sail_spin_unlock(volatile int *lock);
+#include <stdatomic.h>
+
+struct sail_spinlock {
+ atomic_flag v;
+};
+
+#define SPINLOCK_INIT \
+ { \
+ .v = ATOMIC_FLAG_INIT \
+ }
+
+static inline void sail_spin_init(struct sail_spinlock *l)
+{
+ *l = (struct sail_spinlock)SPINLOCK_INIT;
+}
-int sail_spin_lock(volatile int *lock);
+static inline void sail_spin_lock(struct sail_spinlock *l)
+{
+ while (atomic_flag_test_and_set_explicit(&l->v, memory_order_acquire)) {
+ /* do nothing */
+ }
+}
-int sail_spin_trylock(volatile int *lock);
+static inline void sail_spin_unlock(struct sail_spinlock *l)
+{
+ atomic_flag_clear_explicit(&l->v, memory_order_release);
+}
#endif
diff --git a/lib/nostd/stubs/sail_failure.c b/lib/nostd/stubs/sail_failure.c
index 06d3f53d..e6120ded 100644
--- a/lib/nostd/stubs/sail_failure.c
+++ b/lib/nostd/stubs/sail_failure.c
@@ -18,3 +18,15 @@ void sail_failure(char *message)
exit(EXIT_FAILURE);
#endif
}
+
+int sail_assert(bool result, char *message)
+{
+ if (~result) {
+ fprintf(stderr, "Assert failed: %s\n", message);
+#ifndef SAIL_NO_FAILURE
+ exit(EXIT_FAILURE);
+#endif
+ return 0;
+ }
+ return 0;
+}