summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/arith.sail4
-rw-r--r--lib/rts.c54
-rw-r--r--lib/rts.h32
-rw-r--r--lib/sail.c341
-rw-r--r--lib/sail.h83
-rw-r--r--lib/smt.sail4
6 files changed, 498 insertions, 20 deletions
diff --git a/lib/arith.sail b/lib/arith.sail
index f713805a..e5d2d6ea 100644
--- a/lib/arith.sail
+++ b/lib/arith.sail
@@ -54,7 +54,7 @@ val div_int = {
smt: "div",
ocaml: "quotient",
lem: "integerDiv",
- c: "div_int",
+ c: "tdiv_int",
coq: "Z.quot"
} : (int, int) -> int
@@ -64,7 +64,7 @@ val mod_int = {
smt: "mod",
ocaml: "modulus",
lem: "integerMod",
- c: "mod_int",
+ c: "tmod_int",
coq: "Z.rem"
} : (int, int) -> int
diff --git a/lib/rts.c b/lib/rts.c
index b098ae0e..61f772cf 100644
--- a/lib/rts.c
+++ b/lib/rts.c
@@ -16,6 +16,18 @@ unit sail_assert(bool b, sail_string msg)
exit(EXIT_FAILURE);
}
+unit sail_exit(unit u)
+{
+ exit(EXIT_SUCCESS);
+ return UNIT;
+}
+
+unit sleep_request(const unit u)
+{
+ fprintf(stderr, "Sail model going to sleep\n");
+ exit(EXIT_SUCCESS);
+}
+
/* ***** Sail memory builtins ***** */
/*
@@ -151,6 +163,19 @@ void read_ram(sail_bits *data,
mpz_clear(byte);
}
+unit load_raw(mach_bits addr, const sail_string file)
+{
+ FILE *fp = fopen(file, "r");
+
+ uint64_t byte;
+ while ((byte = (uint64_t)fgetc(fp)) != EOF) {
+ write_mem(addr, byte);
+ addr++;
+ }
+
+ return UNIT;
+}
+
void load_image(char *file) {
FILE *fp = fopen(file, "r");
@@ -201,7 +226,12 @@ unit disable_tracing(const unit u)
return UNIT;
}
-void trace_uint64_t(const uint64_t x) {
+bool is_tracing(const unit u)
+{
+ return g_trace_enabled;
+}
+
+void trace_mach_bits(const mach_bits x) {
if (g_trace_enabled) fprintf(stderr, "0x%" PRIx64, x);
}
@@ -209,10 +239,18 @@ void trace_unit(const unit u) {
if (g_trace_enabled) fputs("()", stderr);
}
-void trace_mpz_t(const mpz_t op) {
+void trace_sail_string(const sail_string str) {
+ if (g_trace_enabled) fputs(str, stderr);
+}
+
+void trace_sail_int(const sail_int op) {
if (g_trace_enabled) mpz_out_str(stderr, 10, op);
}
+void trace_sail_bits(const sail_bits op) {
+ if (g_trace_enabled) fprint_bits("", op, "", stderr);
+}
+
void trace_bool(const bool b) {
if (g_trace_enabled) {
if (b) {
@@ -247,6 +285,7 @@ void trace_start(char *name)
fprintf(stderr, "%s", "| ");
}
fprintf(stderr, "%s(", name);
+ g_trace_depth++;
}
}
@@ -257,9 +296,20 @@ void trace_end(void)
for (int64_t i = 0; i < g_trace_depth; ++i) {
fprintf(stderr, "%s", "| ");
}
+ g_trace_depth--;
}
}
+/* ***** ELF functions ***** */
+
+void elf_entry(mpz_t *rop, const unit u) {
+ mpz_set_ui(*rop, g_elf_entry);
+}
+
+void elf_tohost(mpz_t *rop, const unit u) {
+ mpz_set_ui(*rop, 0x0ul);
+}
+
/* ***** Setup and cleanup functions for RTS ***** */
void setup_rts(void)
diff --git a/lib/rts.h b/lib/rts.h
index de32ef8d..f86962c4 100644
--- a/lib/rts.h
+++ b/lib/rts.h
@@ -12,12 +12,21 @@
*/
void sail_match_failure(sail_string msg);
-/*
+/*
* sail_assert implements the assert construct in Sail. If any
* assertion fails we immediately exit the model.
*/
unit sail_assert(bool b, sail_string msg);
+unit sail_exit(unit);
+
+/*
+ * ASL->Sail model has an EnterLowPowerState() function that calls a
+ * sleep request builtin. If it gets called we print a message and
+ * exit the model.
+ */
+unit sleep_request(const unit u);
+
/* ***** Memory builtins ***** */
// These memory builtins are intended to match the semantics for the
@@ -35,6 +44,8 @@ void read_ram(sail_bits *data,
const sail_bits hex_ram,
const sail_bits addr_bv);
+unit load_raw(mach_bits addr, const sail_string file);
+
void load_image(char *);
/* ***** Tracing ***** */
@@ -43,16 +54,20 @@ static int64_t g_trace_depth;
static bool g_trace_enabled;
/*
- * Bind these functions in Sail to enable and disable tracing:
+ * Bind these functions in Sail to enable and disable tracing (see
+ * lib/trace.sail):
*
* val "enable_tracing" : unit -> unit
* val "disable_tracing" : unit -> unit
+ * val "is_tracing" : unit -> bool
*
* Compile with sail -c -c_trace.
*/
unit enable_tracing(const unit);
unit disable_tracing(const unit);
+bool is_tracing(const unit);
+
/*
* Tracing is implemented by void trace_TYPE functions, each of which
* takes the Sail value to print as the first argument, and prints it
@@ -68,7 +83,11 @@ unit disable_tracing(const unit);
*/
void trace_sail_int(const sail_int);
void trace_bool(const bool);
-
+void trace_unit(const unit);
+void trace_sail_string(const sail_string);
+void trace_mach_bits(const mach_bits);
+void trace_sail_bits(const sail_bits);
+
void trace_unknown(void);
void trace_argsep(void);
void trace_argend(void);
@@ -76,8 +95,15 @@ void trace_retend(void);
void trace_start(char *);
void trace_end(void);
+/*
+ * Functions to get info from ELF files.
+ */
+
static uint64_t g_elf_entry;
+void elf_entry(sail_int *rop, const unit u);
+void elf_tohost(sail_int *rop, const unit u);
+
/*
* setup_rts and cleanup_rts are responsible for calling setup_library
* and cleanup_library in sail.h.
diff --git a/lib/sail.c b/lib/sail.c
index 5fd7a04e..13f1a0e8 100644
--- a/lib/sail.c
+++ b/lib/sail.c
@@ -27,6 +27,16 @@ void cleanup_library(void)
mpz_clear(sail_lib_tmp2);
}
+bool eq_unit(const unit a, const unit b)
+{
+ return true;
+}
+
+unit UNDEFINED(unit)(const unit u)
+{
+ return UNIT;
+}
+
/* ***** Sail bit type ***** */
bool eq_bit(const mach_bits a, const mach_bits b)
@@ -50,43 +60,60 @@ bool UNDEFINED(bool)(const unit u) {
/* ***** Sail strings ***** */
-void CREATE(sail_string)(sail_string *str) {
+void CREATE(sail_string)(sail_string *str)
+{
char *istr = (char *) malloc(1 * sizeof(char));
istr[0] = '\0';
*str = istr;
}
-void RECREATE(sail_string)(sail_string *str) {
+void RECREATE(sail_string)(sail_string *str)
+{
free(*str);
char *istr = (char *) malloc(1 * sizeof(char));
istr[0] = '\0';
*str = istr;
}
-void COPY(sail_string)(sail_string *str1, const sail_string str2) {
+void COPY(sail_string)(sail_string *str1, const sail_string str2)
+{
size_t len = strlen(str2);
*str1 = realloc(*str1, len + 1);
*str1 = strcpy(*str1, str2);
}
-void KILL(sail_string)(sail_string *str) {
+void KILL(sail_string)(sail_string *str)
+{
free(*str);
}
-void dec_str(sail_string *str, const mpz_t n) {
+void dec_str(sail_string *str, const mpz_t n)
+{
free(*str);
gmp_asprintf(str, "%Zd", n);
}
-void hex_str(sail_string *str, const mpz_t n) {
+void hex_str(sail_string *str, const mpz_t n)
+{
free(*str);
gmp_asprintf(str, "0x%Zx", n);
}
-bool eq_string(const sail_string str1, const sail_string str2) {
+bool eq_string(const sail_string str1, const sail_string str2)
+{
return strcmp(str1, str2) == 0;
}
+void undefined_string(sail_string *str, const unit u) {}
+
+void concat_str(sail_string *stro, const sail_string str1, const sail_string str2)
+{
+ *stro = realloc(*stro, strlen(str1) + strlen(str2) + 1);
+ (*stro)[0] = '\0';
+ strcat(*stro, str1);
+ strcat(*stro, str2);
+}
+
/* ***** Sail integers ***** */
#ifndef USE_INT128
@@ -392,6 +419,33 @@ void sub_bits_int(sail_bits *rop, const sail_bits op1, const mpz_t op2)
normalize_sail_bits(rop);
}
+void and_bits(sail_bits *rop, const sail_bits op1, const sail_bits op2)
+{
+ rop->len = op1.len;
+ mpz_and(*rop->bits, *op1.bits, *op2.bits);
+}
+
+void or_bits(sail_bits *rop, const sail_bits op1, const sail_bits op2)
+{
+ rop->len = op1.len;
+ mpz_ior(*rop->bits, *op1.bits, *op2.bits);
+}
+
+void xor_bits(sail_bits *rop, const sail_bits op1, const sail_bits op2)
+{
+ rop->len = op1.len;
+ mpz_xor(*rop->bits, *op1.bits, *op2.bits);
+}
+
+void not_bits(sail_bits *rop, const sail_bits op)
+{
+ rop->len = op.len;
+ mpz_set(*rop->bits, *op.bits);
+ for (mp_bitcnt_t i = 0; i < op.len; i++) {
+ mpz_combit(*rop->bits, i);
+ }
+}
+
void zeros(sail_bits *rop, const sail_int op)
{
rop->len = mpz_get_ui(op);
@@ -467,8 +521,274 @@ void sail_signed(sail_int *rop, const sail_bits op)
}
}
+void append(sail_bits *rop, const sail_bits op1, const sail_bits op2)
+{
+ rop->len = op1.len + op2.len;
+ mpz_mul_2exp(*rop->bits, *op1.bits, op2.len);
+ mpz_ior(*rop->bits, *rop->bits, *op2.bits);
+}
+
+void replicate_bits(sail_bits *rop, const sail_bits op1, const mpz_t op2)
+{
+ uint64_t op2_ui = mpz_get_ui(op2);
+ rop->len = op1.len * op2_ui;
+ mpz_set(*rop->bits, *op1.bits);
+ for (int i = 1; i < op2_ui; i++) {
+ mpz_mul_2exp(*rop->bits, *rop->bits, op1.len);
+ mpz_ior(*rop->bits, *rop->bits, *op1.bits);
+ }
+}
+
+uint64_t fast_replicate_bits(const uint64_t shift, const uint64_t v, const int64_t times)
+{
+ uint64_t r = v;
+ for (int i = 1; i < times; ++i) {
+ r |= (r << shift);
+ }
+ return r;
+}
+
+// Takes a slice of the (two's complement) binary representation of
+// integer n, starting at bit start, and of length len. With the
+// argument in the following order:
+//
+// get_slice_int(len, n, start)
+//
+// For example:
+//
+// get_slice_int(8, 1680, 4) =
+//
+// 11 0
+// V V
+// get_slice_int(8, 0b0110_1001_0000, 4) = 0b0110_1001
+// <-------^
+// (8 bit) 4
+//
+void get_slice_int(sail_bits *rop, const sail_int len_mpz, const sail_int n, const sail_int start_mpz)
+{
+ uint64_t start = mpz_get_ui(start_mpz);
+ uint64_t len = mpz_get_ui(len_mpz);
+
+ mpz_set_ui(*rop->bits, 0ul);
+ rop->len = len;
+
+ for (uint64_t i = 0; i < len; i++) {
+ if (mpz_tstbit(n, i + start)) mpz_setbit(*rop->bits, i);
+ }
+}
+
+// Set slice uses the same indexing scheme as get_slice_int, but it
+// puts a bitvector slice into an integer rather than returning it.
+void set_slice_int(sail_int *rop,
+ const sail_int len_mpz,
+ const sail_int n,
+ const sail_int start_mpz,
+ const sail_bits slice)
+{
+ uint64_t start = mpz_get_ui(start_mpz);
+
+ mpz_set(*rop, n);
+
+ for (uint64_t i = 0; i < slice.len; i++) {
+ if (mpz_tstbit(*slice.bits, i)) {
+ mpz_setbit(*rop, i + start);
+ } else {
+ mpz_clrbit(*rop, i + start);
+ }
+ }
+}
+
+void vector_update_subrange_sail_bits(sail_bits *rop,
+ const sail_bits op,
+ const sail_int n_mpz,
+ const sail_int m_mpz,
+ const sail_bits slice)
+{
+ uint64_t n = mpz_get_ui(n_mpz);
+ uint64_t m = mpz_get_ui(m_mpz);
+
+ mpz_set(*rop->bits, *op.bits);
+
+ for (uint64_t i = 0; i < n - (m - 1ul); i++) {
+ if (mpz_tstbit(*slice.bits, i)) {
+ mpz_setbit(*rop->bits, i + m);
+ } else {
+ mpz_clrbit(*rop->bits, i + m);
+ }
+ }
+}
+
+void slice(sail_bits *rop, const sail_bits op, const sail_int start_mpz, const sail_int len_mpz)
+{
+ uint64_t start = mpz_get_ui(start_mpz);
+ uint64_t len = mpz_get_ui(len_mpz);
+
+ mpz_set_ui(*rop->bits, 0ul);
+ rop->len = len;
+
+ for (uint64_t i = 0; i < len; i++) {
+ if (mpz_tstbit(*op.bits, i + start)) mpz_setbit(*rop->bits, i);
+ }
+}
+
+void set_slice(sail_bits *rop,
+ const sail_int len_mpz,
+ const sail_int slen_mpz,
+ const sail_bits op,
+ const sail_int start_mpz,
+ const sail_bits slice)
+{
+ uint64_t start = mpz_get_ui(start_mpz);
+
+ mpz_set(*rop->bits, *op.bits);
+ rop->len = op.len;
+
+ for (uint64_t i = 0; i < slice.len; i++) {
+ if (mpz_tstbit(*slice.bits, i)) {
+ mpz_setbit(*rop->bits, i + start);
+ } else {
+ mpz_clrbit(*rop->bits, i + start);
+ }
+ }
+}
+
+/* ***** Sail Reals ***** */
+
+void CREATE(real)(real *rop)
+{
+ mpf_init(*rop);
+}
+
+void RECREATE(real)(real *rop)
+{
+ mpf_set_ui(*rop, 0);
+}
+
+void KILL(real)(real *rop)
+{
+ mpf_clear(*rop);
+}
+
+void COPY(real)(real *rop, const real op)
+{
+ mpf_set(*rop, op);
+}
+
+void UNDEFINED(real)(real *rop, unit u)
+{
+ mpf_set_ui(*rop, 0ul);
+}
+
+void neg_real(real *rop, const real op)
+{
+ mpf_neg(*rop, op);
+}
+
+void mult_real(real *rop, const real op1, const real op2) {
+ mpf_mul(*rop, op1, op2);
+}
+
+void sub_real(real *rop, const real op1, const real op2)
+{
+ mpf_sub(*rop, op1, op2);
+}
+
+void add_real(real *rop, const real op1, const real op2)
+{
+ mpf_add(*rop, op1, op2);
+}
+
+void div_real(real *rop, const real op1, const real op2)
+{
+ mpf_div(*rop, op1, op2);
+}
+
+void sqrt_real(real *rop, const real op)
+{
+ mpf_sqrt(*rop, op);
+}
+
+void abs_real(real *rop, const real op)
+{
+ mpf_abs(*rop, op);
+}
+
+void round_up(sail_int *rop, const real op)
+{
+ mpf_t x;
+ mpf_init(x);
+ mpf_ceil(x, op);
+ mpz_set_ui(*rop, mpf_get_ui(x));
+ mpf_clear(x);
+}
+
+void round_down(sail_int *rop, const real op)
+{
+ mpf_t x;
+ mpf_init(x);
+ mpf_floor(x, op);
+ mpz_set_ui(*rop, mpf_get_ui(x));
+ mpf_clear(x);
+}
+
+void to_real(real *rop, const sail_int op)
+{
+ mpf_set_z(*rop, op);
+}
+
+bool eq_real(const real op1, const real op2)
+{
+ return mpf_cmp(op1, op2) == 0;
+}
+
+bool lt_real(const real op1, const real op2)
+{
+ return mpf_cmp(op1, op2) < 0;
+}
+
+bool gt_real(const real op1, const real op2)
+{
+ return mpf_cmp(op1, op2) > 0;
+}
+
+bool lteq_real(const real op1, const real op2)
+{
+ return mpf_cmp(op1, op2) <= 0;
+}
+
+bool gteq_real(const real op1, const real op2)
+{
+ return mpf_cmp(op1, op2) >= 0;
+}
+
+void real_power(real *rop, const real base, const sail_int exp)
+{
+ uint64_t exp_ui = mpz_get_ui(exp);
+ mpf_pow_ui(*rop, base, exp_ui);
+}
+
+void CREATE_OF(real, sail_string)(real *rop, const sail_string op)
+{
+ mpf_init(*rop);
+ gmp_sscanf(op, "%Ff", *rop);
+}
+
/* ***** Printing functions ***** */
+void string_of_int(sail_string *str, const sail_int i)
+{
+ gmp_asprintf(str, "%Zd", i);
+}
+
+void string_of_bits(sail_string *str, const sail_bits op)
+{
+ if ((op.len % 4) == 0) {
+ gmp_asprintf(str, "0x%*0Zx", op.len / 4, *op.bits);
+ } else {
+ gmp_asprintf(str, "0b%*0Zb", op.len, *op.bits);
+ }
+}
+
void fprint_bits(const sail_string pre,
const sail_bits op,
const sail_string post,
@@ -556,3 +876,10 @@ unit prerr_int(const sail_string str, const sail_int op)
fputs("\n", stderr);
return UNIT;
}
+
+unit sail_putchar(const sail_int op)
+{
+ char c = (char) mpz_get_ui(op);
+ putchar(c);
+ return UNIT;
+}
diff --git a/lib/sail.h b/lib/sail.h
index 1cd5d928..23ff7f52 100644
--- a/lib/sail.h
+++ b/lib/sail.h
@@ -43,7 +43,7 @@ typedef int unit;
unit UNDEFINED(unit)(const unit);
bool eq_unit(const unit, const unit);
-
+
/* ***** Sail booleans ***** */
/*
@@ -66,8 +66,12 @@ SAIL_BUILTIN_TYPE(sail_string);
void dec_str(sail_string *str, const mpz_t n);
void hex_str(sail_string *str, const mpz_t n);
+void undefined_string(sail_string *str, const unit u);
+
bool eq_string(const sail_string, const sail_string);
+void concat_str(sail_string *stro, const sail_string str1, const sail_string str2);
+
/* ***** Sail integers ***** */
typedef int64_t mach_int;
@@ -94,7 +98,7 @@ void RECREATE_OF(sail_int, sail_string)(mpz_t *, const sail_string);
mach_int CONVERT_OF(mach_int, sail_int)(const sail_int);
void CONVERT_OF(sail_int, mach_int)(sail_int *, const mach_int);
-
+
#else
typedef __int128 sail_int;
@@ -134,6 +138,7 @@ SAIL_INT_FUNCTION(undefined_range, sail_int, const sail_int, const sail_int);
*/
SAIL_INT_FUNCTION(add_int, sail_int, const sail_int, const sail_int);
SAIL_INT_FUNCTION(sub_int, sail_int, const sail_int, const sail_int);
+SAIL_INT_FUNCTION(mult_int, sail_int, const sail_int, const sail_int);
SAIL_INT_FUNCTION(tdiv_int, sail_int, const sail_int, const sail_int);
SAIL_INT_FUNCTION(tmod_int, sail_int, const sail_int, const sail_int);
SAIL_INT_FUNCTION(fdiv_int, sail_int, const sail_int, const sail_int);
@@ -175,7 +180,7 @@ mach_bits CONVERT_OF(mach_bits, sail_bits)(const sail_bits);
void UNDEFINED(sail_bits)(sail_bits *, const sail_int len, const mach_bits bit);
mach_bits UNDEFINED(mach_bits)(const unit);
-/*
+/*
* Wrapper around >> operator to avoid UB when shift amount is greater
* than or equal to 64.
*/
@@ -192,6 +197,11 @@ void sub_bits(sail_bits *rop, const sail_bits op1, const sail_bits op2);
void add_bits_int(sail_bits *rop, const sail_bits op1, const mpz_t op2);
void sub_bits_int(sail_bits *rop, const sail_bits op1, const mpz_t op2);
+void and_bits(sail_bits *rop, const sail_bits op1, const sail_bits op2);
+void or_bits(sail_bits *rop, const sail_bits op1, const sail_bits op2);
+void xor_bits(sail_bits *rop, const sail_bits op1, const sail_bits op2);
+void not_bits(sail_bits *rop, const sail_bits op);
+
void zeros(sail_bits *rop, const sail_int op);
void zero_extend(sail_bits *rop, const sail_bits op, const sail_int len);
@@ -211,11 +221,74 @@ mach_bits bitvector_access(const sail_bits op, const sail_int n_mpz);
void sail_unsigned(sail_int *rop, const sail_bits op);
void sail_signed(sail_int *rop, const sail_bits op);
+void append(sail_bits *rop, const sail_bits op1, const sail_bits op2);
+
+void replicate_bits(sail_bits *rop, const sail_bits op1, const sail_int op2);
+mach_bits fast_replicate_bits(const mach_bits shift, const mach_bits v, const mach_int times);
+
+void get_slice_int(sail_bits *rop, const sail_int len_mpz, const sail_int n, const sail_int start_mpz);
+
+void set_slice_int(sail_int *rop,
+ const sail_int len_mpz,
+ const sail_int n,
+ const sail_int start_mpz,
+ const sail_bits slice);
+
+void vector_update_subrange_sail_bits(sail_bits *rop,
+ const sail_bits op,
+ const sail_int n_mpz,
+ const sail_int m_mpz,
+ const sail_bits slice);
+
+void slice(sail_bits *rop, const sail_bits op, const sail_int start_mpz, const sail_int len_mpz);
+
+void set_slice(sail_bits *rop,
+ const sail_int len_mpz,
+ const sail_int slen_mpz,
+ const sail_bits op,
+ const sail_int start_mpz,
+ const sail_bits slice);
+
/* ***** Sail reals ***** */
+typedef mpf_t real;
+
+SAIL_BUILTIN_TYPE(real);
+
+void CREATE_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);
+
+void round_up(sail_int *rop, const real op);
+void round_down(sail_int *rop, const real op);
+
+void to_real(real *rop, const sail_int op);
+
+bool eq_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);
+
/* ***** Printing ***** */
-/*
+void string_of_int(sail_string *str, const sail_int i);
+void string_of_bits(sail_string *str, const sail_bits op);
+
+/*
* Utility function not callable from Sail!
*/
void fprint_bits(const sail_string pre,
@@ -234,3 +307,5 @@ unit prerr_endline(const sail_string str);
unit print_int(const sail_string str, const sail_int op);
unit prerr_int(const sail_string str, const sail_int op);
+
+unit sail_putchar(const sail_int op);
diff --git a/lib/smt.sail b/lib/smt.sail
index ae672947..c9312819 100644
--- a/lib/smt.sail
+++ b/lib/smt.sail
@@ -7,7 +7,7 @@ val div = {
smt: "div",
ocaml: "quotient",
lem: "integerDiv",
- c: "div_int"
+ c: "tdiv_int"
} : forall 'n 'm. (atom('n), atom('m)) -> {'o, 'o = div('n, 'm). atom('o)}
overload operator / = {div}
@@ -16,7 +16,7 @@ val mod = {
smt: "mod",
ocaml: "modulus",
lem: "integerMod",
- c: "mod_int"
+ c: "tmod_int"
} : forall 'n 'm. (atom('n), atom('m)) -> {'o, 'o = mod('n, 'm). atom('o)}
overload operator % = {mod}