summaryrefslogtreecommitdiff
path: root/src/lem_interp/0.11/interp_lib.lem
diff options
context:
space:
mode:
Diffstat (limited to 'src/lem_interp/0.11/interp_lib.lem')
-rw-r--r--src/lem_interp/0.11/interp_lib.lem1111
1 files changed, 1111 insertions, 0 deletions
diff --git a/src/lem_interp/0.11/interp_lib.lem b/src/lem_interp/0.11/interp_lib.lem
new file mode 100644
index 00000000..e55fc175
--- /dev/null
+++ b/src/lem_interp/0.11/interp_lib.lem
@@ -0,0 +1,1111 @@
+(*========================================================================*)
+(* Sail *)
+(* *)
+(* Copyright (c) 2013-2017 *)
+(* Kathyrn Gray *)
+(* Shaked Flur *)
+(* Stephen Kell *)
+(* Gabriel Kerneis *)
+(* Robert Norton-Wright *)
+(* Christopher Pulte *)
+(* Peter Sewell *)
+(* Alasdair Armstrong *)
+(* Brian Campbell *)
+(* Thomas Bauereiss *)
+(* Anthony Fox *)
+(* Jon French *)
+(* Dominic Mulligan *)
+(* Stephen Kell *)
+(* Mark Wassell *)
+(* *)
+(* All rights reserved. *)
+(* *)
+(* This software was developed by the University of Cambridge Computer *)
+(* Laboratory as part of the Rigorous Engineering of Mainstream Systems *)
+(* (REMS) project, funded by EPSRC grant EP/K008528/1. *)
+(* *)
+(* Redistribution and use in source and binary forms, with or without *)
+(* modification, are permitted provided that the following conditions *)
+(* are met: *)
+(* 1. Redistributions of source code must retain the above copyright *)
+(* notice, this list of conditions and the following disclaimer. *)
+(* 2. Redistributions in binary form must reproduce the above copyright *)
+(* notice, this list of conditions and the following disclaimer in *)
+(* the documentation and/or other materials provided with the *)
+(* distribution. *)
+(* *)
+(* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' *)
+(* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *)
+(* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *)
+(* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR *)
+(* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, *)
+(* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT *)
+(* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF *)
+(* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND *)
+(* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, *)
+(* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT *)
+(* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF *)
+(* SUCH DAMAGE. *)
+(*========================================================================*)
+
+open import Pervasives
+open import Interp_utilities
+open import Interp
+open import Interp_ast
+(* For failwith for error reporting while debugging; and for fromJust when we know it's not Nothing *)
+import Assert_extra Maybe_extra
+open import Num
+import Num_extra
+open import List
+open import Word
+open import Bool
+
+type signed = Unsigned | Signed
+
+val debug_print : string -> unit
+declare ocaml target_rep function debug_print s = `Printf.eprintf` "%s" s
+
+let print s = let _ = debug_print (string_of_value s) in V_lit(L_aux L_unit Unknown)
+
+let hardware_mod (a: integer) (b:integer) : integer =
+ if a < 0 && b < 0
+ then (abs a) mod (abs b)
+ else if (a < 0 && b >= 0)
+ then (a mod b) - b
+ else a mod b
+
+(* There are different possible answers for integer divide regarding
+rounding behaviour on negative operands. Positive operands always
+round down so derive the one we want (trucation towards zero) from
+that *)
+let hardware_quot (a:integer) (b:integer) : integer =
+ let q = (abs a) / (abs b) in
+ if ((a<0) = (b<0)) then
+ q (* same sign -- result positive *)
+ else
+ ~q (* different sign -- result negative *)
+
+let (max_64u : integer) = integerFromNat ((natPow 2 64) - 1)
+let (max_64 : integer) = integerFromNat ((natPow 2 63) - 1)
+let (min_64 : integer) = integerNegate (integerFromNat (natPow 2 63))
+let (max_32u : integer) = integerFromNat (natPow 2 32) (*4294967295*)
+let (max_32 : integer) = integerFromNat ((natPow 2 31) - 1) (*2147483647*)
+let (min_32 : integer) = integerNegate (integerFromNat (natPow 2 31)) (*2147483648*)
+let (max_8 : integer) = (integerFromNat 127)
+let (min_8 : integer) = (integerFromNat 0) - (integerFromNat 128)
+let (max_5 : integer) = (integerFromNat 31)
+
+val get_max_representable_in : signed -> nat -> integer
+let get_max_representable_in sign n =
+ match (sign, n) with
+ | (Signed, 64) -> max_64
+ | (Unsigned, 64) -> max_64u
+ | (Signed, 32) -> max_32
+ | (Unsigned, 32) -> max_32u
+ | (Signed, 8) -> max_8
+ | (Unsigned, 5) -> max_5
+ | (Signed, _) -> 2**(n -1) - 1
+ | (Unsigned, _) -> 2**n - 1
+ end
+
+val get_min_representable_in : signed -> nat -> integer
+let get_min_representable_in sign n =
+ match (sign, n) with
+ | (Unsigned, _) -> 0
+ | (Signed, 64) -> min_64
+ | (Signed, 32) -> min_32
+ | (Signed, 8) -> min_8
+ | (Signed, _) -> 0-(2**(n-1))
+ end
+
+let ignore_sail x = V_lit (L_aux L_unit Unknown) ;;
+
+let compose f g x = f (V_tuple [g x]) ;;
+
+let zeroi = integerFromNat 0
+let onei = integerFromNat 1
+let twoi = integerFromNat 2
+
+let is_unknown v = match detaint v with
+ | V_unknown -> true
+ | _ -> false
+end
+
+let is_undef v = match detaint v with
+ | V_lit (L_aux L_undef _) -> true
+ | _ -> false
+end
+
+let has_unknown v = match detaint v with
+ | V_vector _ _ vs -> List.any is_unknown vs
+ | V_unknown -> true
+ | _ -> false
+end
+
+let has_undef v = match detaint v with
+ | V_vector _ _ vs -> List.any is_undef vs
+ | _ -> Assert_extra.failwith ("has_undef given non-vector " ^ (string_of_value v))
+end
+
+let rec sparse_walker update ni processed_length length ls df =
+ if processed_length = length
+ then []
+ else match ls with
+ | [] -> replicate (length - processed_length) df
+ | (i,v)::ls ->
+ if ni = i
+ then v::(sparse_walker update (update ni) (processed_length + 1) length ls df)
+ else df::(sparse_walker update (update ni) (processed_length + 1) length ((i,v)::ls) df)
+end
+
+let fill_in_sparse v =
+ retaint v (match detaint v with
+ | V_vector_sparse first length dir ls df ->
+ V_vector first dir
+ (sparse_walker
+ (if is_inc(dir) then (fun (x: nat) -> x + 1) else (fun (x: nat) -> x - 1)) first 0 length ls df)
+ | V_unknown -> V_unknown
+ | _ -> Assert_extra.failwith ("fill_in_sparse given non-vector " ^ (string_of_value v))
+ end)
+
+let is_one v =
+ retaint v
+ match detaint v with
+ | V_lit (L_aux (L_num n) lb) -> V_lit (L_aux (if n=1 then L_one else L_zero) lb)
+ | V_lit (L_aux b lb) -> V_lit (L_aux (if b = L_one then L_one else L_zero) lb)
+ | V_unknown -> v
+ | _ -> Assert_extra.failwith ("is_one given non-vector " ^ (string_of_value v))
+end ;;
+
+let rec most_significant v =
+ retaint v
+ match detaint v with
+ | V_vector _ _ (v::vs) -> v
+ | V_vector_sparse _ _ _ _ _ -> most_significant (fill_in_sparse v)
+ | V_lit (L_aux L_one _) -> v
+ | V_lit (L_aux L_zero _) -> v
+ | V_lit (L_aux (L_num n) lt) ->
+ if n = 1
+ then V_lit (L_aux L_one lt)
+ else if n = 0
+ then V_lit (L_aux L_zero lt)
+ else Assert_extra.failwith ("most_significant given non-vector " ^ (string_of_value v))
+ | V_lit (L_aux L_undef _) -> v
+ | V_unknown -> V_unknown
+ | _ -> Assert_extra.failwith ("most_significant given non-vector " ^ (string_of_value v))
+end;;
+
+let lt_range v =
+ let lr_helper v1 v2 = match (v1,v2) with
+ | (V_lit (L_aux (L_num l1) lr),V_lit (L_aux (L_num l2) ll)) ->
+ if l1 < l2
+ then V_lit (L_aux L_one Unknown)
+ else V_lit (L_aux L_zero Unknown)
+ | (V_unknown,_) -> V_unknown
+ | (_,V_unknown) -> V_unknown
+ | _ ->
+ Assert_extra.failwith ("lt_range given non-lit (" ^ (string_of_value v1) ^ ", " ^ (string_of_value v2) ^ ")")
+ end in
+ match v with
+ | (V_tuple[v1;v2]) ->
+ binary_taint lr_helper v1 v2
+ | _ -> Assert_extra.failwith ("lt_range not given tuple of length two " ^ (string_of_value v))
+end
+
+let bit_to_bool b = match detaint b with
+ | V_lit (L_aux L_zero _) -> false
+ | V_lit (L_aux L_false _) -> false
+ | V_lit (L_aux L_one _) -> true
+ | V_lit (L_aux L_true _) -> true
+ | _ -> Assert_extra.failwith ("bit_to_bool given unexpected " ^ (string_of_value b))
+ end ;;
+let bool_to_bit b = match b with
+ false -> V_lit (L_aux L_zero Unknown)
+ | true -> V_lit (L_aux L_one Unknown)
+ end ;;
+
+let bitwise_not_bit v =
+ let lit_not (L_aux l loc) = match l with
+ | L_zero -> (V_lit (L_aux L_one loc))
+ | L_false -> (V_lit (L_aux L_one loc))
+ | L_one -> (V_lit (L_aux L_zero loc))
+ | L_true -> (V_lit (L_aux L_zero loc))
+ | L_undef -> (V_lit (L_aux L_undef loc))
+ | _ -> Assert_extra.failwith ("bitwise_not_bit given unexpected " ^ (string_of_value v)) end in
+ retaint v (match detaint v with
+ | V_lit lit -> lit_not lit
+ | V_unknown -> V_unknown
+ | _ -> Assert_extra.failwith ("bitwise_not_bit given unexpected " ^ (string_of_value v))
+ end)
+
+let rec bitwise_not v =
+ retaint v (match detaint v with
+ | V_vector idx inc v ->
+ V_vector idx inc (List.map bitwise_not_bit v)
+ | V_unknown -> V_unknown
+ | _ -> Assert_extra.failwith ("bitwise_not given unexpected " ^ (string_of_value v))
+ end)
+
+let rec bitwise_binop_bit op op_s v =
+ let b_b_b_help x y = match (x,y) with
+ | (V_vector _ _ [b],y) -> bitwise_binop_bit op op_s (V_tuple [b; y])
+ | (_,V_vector _ _ [b]) -> bitwise_binop_bit op op_s (V_tuple [x; b])
+ | (V_unknown,_) -> V_unknown
+ | (_,V_unknown) -> V_unknown
+ | (V_lit (L_aux L_undef li), v) ->
+ (match op_s with | "|" -> y | "&" -> x | "^" -> y | _ -> x end)
+ | (v,V_lit (L_aux L_undef li)) ->
+ (match op_s with | "|" -> x | "&" -> y | "^" -> y | _ -> y end)
+ | _ -> bool_to_bit (op (bit_to_bool x) (bit_to_bool y)) end in
+ match v with
+ | (V_tuple [x; y]) -> binary_taint b_b_b_help x y
+ | _ -> Assert_extra.failwith ("bitwise_binop_bit not given tuple of length 2 " ^ (string_of_value v))
+end
+
+let rec bitwise_binop op op_s v =
+ let b_b_help v1 v2 =
+ match (v1,v2) with
+ | (V_vector idx inc v, V_vector idx' inc' v') ->
+ (* typechecker ensures inc = inc' and length v = length v' *)
+ V_vector idx inc (List.map (fun (x,y) -> (bitwise_binop_bit op op_s (V_tuple[x; y]))) (List.zip v v'))
+ | (V_unknown,_) -> V_unknown
+ | (_,V_unknown) -> V_unknown
+ | _ -> Assert_extra.failwith ("bitwise_binop given unexpected " ^ (string_of_value v)) end in
+ match v with
+ | (V_tuple [v1;v2]) -> binary_taint b_b_help v1 v2
+ | _ -> Assert_extra.failwith ("bitwise_binop not given tuple of length 2 " ^ (string_of_value v))
+end
+
+(* BitSeq expects LSB first.
+ * By convention, MSB is on the left, so increasing = Big-Endian (MSB0),
+ * hence MSB first.
+ * http://en.wikipedia.org/wiki/Bit_numbering *)
+let to_num signed v =
+ retaint v
+ (match detaint v with
+ | (V_vector idx inc l) ->
+ if has_unknown v then V_unknown else if l=[] then V_unknown
+ else if has_undef v then V_lit (L_aux L_undef Unknown)
+ else
+ (* Word library in Lem expects bitseq with LSB first *)
+ let l = reverse l in
+ (* Make sure the last bit is a zero to force unsigned numbers *)
+ let l = (match signed with | Signed -> l | Unsigned -> l ++ [V_lit (L_aux L_zero Unknown)] end) in
+ V_lit(L_aux (L_num(integerFromBitSeq (Maybe_extra.fromJust (bitSeqFromBoolList (map bit_to_bool l))))) Unknown)
+ | V_unknown -> V_unknown
+ | V_lit (L_aux L_undef _) -> v
+ | V_lit (L_aux L_zero l) -> V_lit (L_aux (L_num 0) l)
+ | V_lit (L_aux L_one l) -> V_lit (L_aux (L_num 1) l)
+ | _ -> Assert_extra.failwith ("to_num given unexpected " ^ (string_of_value v))
+ end)
+
+let to_vec_inc v =
+ let fail () = Assert_extra.failwith ("to_vec_inc given unexpected " ^ (string_of_value v)) in
+ let tv_help v1 v2 =
+ match (v1,v2) with
+ | (V_lit(L_aux (L_num len) _), (V_lit(L_aux (L_num n) ln))) ->
+ let l = if len < 0 then []
+ else boolListFrombitSeq (natFromInteger len) (bitSeqFromInteger Nothing n) in
+ V_vector 0 IInc (map bool_to_bit (reverse l))
+ | ((V_lit(L_aux (L_num n) ln)),V_unknown) ->
+ V_vector 0 IInc (List.replicate (if n < 0 then 0 else (natFromInteger n)) V_unknown)
+ | ((V_lit(L_aux (L_num n) ln)),(V_lit (L_aux L_undef _))) ->
+ V_vector 0 IInc (List.replicate (natFromInteger n) v2)
+ | (_,V_unknown) -> V_unknown
+ | (V_unknown,_) -> V_unknown
+ | _ -> fail ()
+ end in
+ match v with
+ | (V_tuple[v1;v2]) -> binary_taint tv_help v1 v2
+ | _ -> fail ()
+end
+
+let to_vec_dec v =
+ let fail () = Assert_extra.failwith ("to_vec_dec parameters were " ^ (string_of_value v)) in
+ let tv_fun v1 v2 =
+ match (v1,v2) with
+ | (V_lit(L_aux (L_num len) _), (V_lit(L_aux (L_num n) ln))) ->
+ let len = if len < 0 then 0 else natFromInteger len in
+ let l = boolListFrombitSeq len (bitSeqFromInteger Nothing n) in
+ V_vector (len - 1) IDec (map bool_to_bit (reverse l))
+ | ((V_lit(L_aux (L_num n) ln)),V_unknown) ->
+ let n = if n < 0 then 0 else natFromInteger n in
+ V_vector (if n=0 then 0 else (n-1)) IDec (List.replicate n V_unknown)
+ | ((V_lit(L_aux (L_num n) ln)),(V_lit (L_aux L_undef _))) ->
+ let n = if n < 0 then 0 else natFromInteger n in
+ V_vector (if n = 0 then 0 else (n-1)) IDec (List.replicate n v2)
+ | (_,V_unknown) -> V_unknown
+ | (V_unknown,_) -> V_unknown
+ | _ -> fail ()
+ end in
+ match v with
+ | V_tuple([v1;v2]) -> binary_taint tv_fun v1 v2
+ | _ -> fail()
+end
+
+
+let rec to_vec_inc_undef v1 =
+ retaint v1
+ match detaint v1 with
+ | V_lit(L_aux (L_num len) _) ->
+ let len = if len < 0 then 0 else natFromInteger len in
+ V_vector 0 IInc (List.replicate len (V_lit (L_aux L_undef Unknown)))
+ | _ -> V_unknown
+end
+
+let rec to_vec_dec_undef v1 =
+ retaint v1
+ match detaint v1 with
+ | V_lit(L_aux (L_num len) _) ->
+ let len = if len < 0 then 0 else natFromInteger len in
+ V_vector (len - 1) IDec (List.replicate len (V_lit (L_aux L_undef Unknown)))
+ | _ -> V_unknown
+end
+
+let to_vec ord len n =
+ if is_inc(ord)
+ then to_vec_inc (V_tuple ([V_lit(L_aux (L_num len) Interp_ast.Unknown); n]))
+ else to_vec_dec (V_tuple ([V_lit(L_aux (L_num len) Interp_ast.Unknown); n]))
+;;
+
+let exts direction v =
+ let exts_help v1 v = match (v1,v) with
+ | (V_lit(L_aux (L_num len) _), V_vector _ inc _)-> to_vec inc len (to_num Signed v)
+ | (V_lit(L_aux (L_num len) _), V_unknown) -> to_vec direction len V_unknown
+ | (V_unknown,_) -> V_unknown
+ | _ -> Assert_extra.failwith ("exts given unexpected " ^ (string_of_value v))
+ end in
+ match v with
+ | (V_tuple[v1;v]) -> binary_taint exts_help v1 v
+ | _ -> Assert_extra.failwith ("exts not given tuple of length 2 " ^ (string_of_value v))
+end
+
+let extz direction v =
+ let extz_help v1 v = match (v1,v) with
+ | (V_lit(L_aux (L_num len) _), V_vector _ inc _)-> to_vec inc len (to_num Unsigned v)
+ | (V_lit(L_aux (L_num len) _), V_unknown) -> to_vec direction len V_unknown
+ | (V_unknown,_) -> V_unknown
+ | _ -> Assert_extra.failwith ("extx given unexpected " ^ (string_of_value v))
+ end in
+ match v with
+ | (V_tuple[v1;v]) -> binary_taint extz_help v1 v
+ | _ -> Assert_extra.failwith ("extz not given tuple of length 2 " ^ (string_of_value v))
+end
+
+let eq v = match v with
+ | (V_tuple [x; y]) ->
+ let combo = binary_taint (fun v _ -> v) x y in
+ retaint combo
+ (if has_unknown x || has_unknown y
+ then V_unknown
+ else (V_lit (L_aux (if ((detaint x) = (detaint y)) then L_one else L_zero) Unknown)))
+ | _ -> Assert_extra.failwith ("eq not given tuple of length 2 " ^ (string_of_value v))
+end
+
+let eq_vec v =
+ let eq_vec_help v1 v2 = match (v1,v2) with
+ | ((V_vector _ _ c1s),(V_vector _ _ c2s)) ->
+ if (List.length c1s = List.length c2s) &&
+ List.listEqualBy
+ (fun v1 v2 -> match eq (V_tuple [v1; v2]) with V_lit (L_aux L_one _) -> true | _ -> false end) c1s c2s then
+ V_lit (L_aux L_one Unknown)
+ else if has_unknown v1 || has_unknown v2
+ then V_unknown
+ else V_lit (L_aux L_zero Unknown)
+ | (V_unknown, _) -> V_unknown
+ | (_, V_unknown) -> V_unknown
+ | (V_vector _ _ [c1], _) -> eq (V_tuple [c1; v2])
+ | (_, V_vector _ _ [c2]) -> eq (V_tuple [v1; c2])
+ | (V_lit _, V_lit _) -> eq (V_tuple [v1;v2]) (*Vectors of one bit return one bit; we need coercion to match*)
+ | _ -> Assert_extra.failwith ("eq_vec not given two vectors, given instead " ^ (string_of_value v)) end in
+ match v with
+ | (V_tuple [v1; v2]) -> binary_taint eq_vec_help v1 v2
+ | _ -> Assert_extra.failwith ("eq_vec not given tuple of length 2 " ^ (string_of_value v))
+end
+
+let eq_vec_range v = match v with
+ | (V_tuple [v; r]) -> eq (V_tuple [to_num Unsigned v; r])
+ | _ -> Assert_extra.failwith ("eq_vec_range not given tuple of length 2 " ^ (string_of_value v))
+end
+let eq_range_vec v = match v with
+ | (V_tuple [r; v]) -> eq (V_tuple [r; to_num Unsigned v])
+ | _ -> Assert_extra.failwith ("eq_range_vec not given tuple of length 2 " ^ (string_of_value v))
+end
+(*let eq_vec_vec v = match v with
+ | (V_tuple [v;v2]) -> eq (V_tuple [to_num Signed v; to_num Signed v2])
+ | _ -> Assert_extra.failwith ("eq_vec_vec not given tuple of length 2 " ^ (string_of_value v))
+end*)
+
+let rec neg v = retaint v (match detaint v with
+ | V_lit (L_aux arg la) ->
+ V_lit (L_aux (match arg with
+ | L_one -> L_zero
+ | L_zero -> L_one
+ | _ -> Assert_extra.failwith ("neg given unexpected " ^ (string_of_value v)) end) la)
+ | V_unknown -> V_unknown
+ | V_tuple [v] -> neg v
+ | _ -> Assert_extra.failwith ("neg given unexpected " ^ (string_of_value v))
+end)
+
+let neq = compose neg eq ;;
+
+let neq_vec = compose neg eq_vec
+let neq_vec_range = compose neg eq_vec_range
+let neq_range_vec = compose neg eq_range_vec
+
+let rec v_abs v = retaint v (match detaint v with
+ | V_lit (L_aux arg la) ->
+ V_lit (L_aux (match arg with
+ | L_num n -> if n < 0 then L_num (n * (0 - 1)) else L_num n
+ | _ -> Assert_extra.failwith ("abs given unexpected " ^ (string_of_value v)) end) la)
+ | V_unknown -> V_unknown
+ | V_tuple [v] -> v_abs v
+ | _ -> Assert_extra.failwith ("abs given unexpected " ^ (string_of_value v)) end)
+
+let arith_op op v =
+ let fail () = Assert_extra.failwith ("arith_op given unexpected " ^ (string_of_value v)) in
+ let arith_op_help vl vr =
+ match (vl,vr) with
+ | (V_lit(L_aux (L_num x) lx), V_lit(L_aux (L_num y) ly)) -> V_lit(L_aux (L_num (op x y)) lx)
+ | (V_unknown,_) -> V_unknown
+ | (_,V_unknown) -> V_unknown
+ | (V_lit (L_aux L_undef lx),_) -> vl
+ | (_, (V_lit (L_aux L_undef ly))) -> vr
+ | _ -> fail ()
+ end in
+ match v with
+ | (V_tuple [vl;vr]) -> binary_taint arith_op_help vl vr
+ | _ -> fail ()
+end
+let arith_op_vec op sign size v =
+ let fail () = Assert_extra.failwith ("arith_op_vec given unexpected " ^ (string_of_value v)) in
+ let arith_op_help vl vr =
+ match (vl,vr) with
+ | ((V_vector b ord cs as l1),(V_vector _ _ _ as l2)) ->
+ let (l1',l2') = (to_num sign l1,to_num sign l2) in
+ let n = arith_op op (V_tuple [l1';l2']) in
+ to_vec ord (integerFromNat ((List.length cs) * size)) n
+ | (V_unknown,_) -> V_unknown
+ | (_,V_unknown) -> V_unknown
+ | _ -> fail ()
+ end in
+ match v with
+ | (V_tuple [vl;vr]) -> binary_taint arith_op_help vl vr
+ | _ -> fail ()
+end
+let arith_op_vec_vec_range op sign v =
+ let fail () = Assert_extra.failwith ("arith_op_vec_vec_range given unexpected " ^ (string_of_value v)) in
+ let arith_op_help vl vr =
+ match (vl,vr) with
+ | (V_vector _ _ _,V_vector _ _ _ ) ->
+ let (l1,l2) = (to_num sign vl,to_num sign vr) in
+ arith_op op (V_tuple [l1;l2])
+ | (V_unknown,_) -> V_unknown
+ | (_,V_unknown) -> V_unknown
+ | _ -> fail ()
+ end in
+ match v with
+ | (V_tuple [vl;vr]) -> binary_taint arith_op_help vl vr
+ | _ -> fail ()
+end
+let arith_op_overflow_vec op over_typ sign size v =
+ let fail () = Assert_extra.failwith ("arith_op_overflow_vec given unexpected " ^ (string_of_value v)) in
+ let overflow_help vl vr =
+ match (vl,vr) with
+ | (V_vector b ord cs1,V_vector _ _ cs2) ->
+ let len = List.length cs1 in
+ let act_size = len * size in
+ let (is_l1_unknown,is_l2_unknown) = ((has_unknown vl), (has_unknown vr)) in
+ if is_l1_unknown || is_l2_unknown
+ then (V_tuple [ (to_vec ord (integerFromNat act_size) V_unknown);V_unknown;V_unknown])
+ else
+ let (l1_sign,l2_sign) = (to_num sign vl,to_num sign vr) in
+ let (l1_unsign,l2_unsign) = (to_num Unsigned vl,to_num Unsigned vr) in
+ let n = arith_op op (V_tuple [l1_sign;l2_sign]) in
+ let n_unsign = arith_op op (V_tuple[l1_unsign;l2_unsign]) in
+ let correct_size_num = to_vec ord (integerFromNat act_size) n in
+ let one_more_size_u = to_vec ord (integerFromNat (act_size +1)) n_unsign in
+ let overflow = (match n with
+ | V_lit (L_aux (L_num n') ln) ->
+ if (n' <= (get_max_representable_in sign len)) &&
+ (n' >= (get_min_representable_in sign len))
+ then V_lit (L_aux L_zero ln)
+ else V_lit (L_aux L_one ln)
+ | _ -> Assert_extra.failwith ("overflow arith_op returned " ^ (string_of_value v)) end) in
+ let out_num = to_num sign correct_size_num in
+ let c_out =
+ match detaint one_more_size_u with
+ | V_vector _ _ (b::bits) -> b
+ | v -> Assert_extra.failwith ("to_vec returned " ^ (string_of_value v)) end in
+ V_tuple [correct_size_num;overflow;c_out]
+ | (V_unknown,_) -> V_tuple [V_unknown;V_unknown;V_unknown]
+ | (_,V_unknown) -> V_tuple [V_unknown;V_unknown;V_unknown]
+ | _ -> fail ()
+ end in
+ match v with
+ | (V_tuple [vl;vr]) -> binary_taint overflow_help vl vr
+ | _ -> fail ()
+end
+let arith_op_overflow_vec_bit op sign size v =
+ let fail () = Assert_extra.failwith ("arith_op_overflow_vec_bit given unexpected " ^ (string_of_value v)) in
+ let arith_help vl vr =
+ match (vl,vr) with
+ | (V_vector b ord cs, V_lit (L_aux bit li)) ->
+ let act_size = (List.length cs) * size in
+ let is_v_unknown = has_unknown vl in
+ if is_v_unknown
+ then V_tuple [(to_vec ord (integerFromNat act_size) V_unknown);V_unknown;V_unknown]
+ else
+ let l1' = to_num sign vl in
+ let l1_u = to_num Unsigned vl in
+ let (n,nu,changed) = match bit with
+ | L_one -> (arith_op op (V_tuple [l1';(V_lit (L_aux (L_num 1) li))]),
+ arith_op op (V_tuple [l1_u;(V_lit (L_aux (L_num 1) li))]), true)
+ | L_zero -> (l1',l1_u,false)
+ | _ -> Assert_extra.failwith "arith_op_overflow_vec bit given non bit" end in
+ let correct_size_num = to_vec ord (integerFromNat act_size) n in
+ let one_larger = to_vec ord (integerFromNat (act_size +1)) nu in
+ let overflow = if changed
+ then retaint n (match detaint n with
+ | V_lit (L_aux (L_num n') ln) ->
+ if (n' <= (get_max_representable_in sign act_size)) &&
+ (n' >= (get_min_representable_in sign act_size))
+ then V_lit (L_aux L_zero ln)
+ else V_lit (L_aux L_one ln)
+ | _ -> Assert_extra.failwith "to_num returned non num" end)
+ else V_lit (L_aux L_zero Unknown) in
+ let carry_out = (match detaint one_larger with
+ | V_vector _ _ (c::rst) -> c
+ | _ -> Assert_extra.failwith "one_larger vector returned non vector" end) in
+ V_tuple [correct_size_num;overflow;carry_out]
+ | (V_unknown,_) -> V_tuple [V_unknown;V_unknown;V_unknown]
+ | (_,V_unknown) -> V_tuple [V_unknown;V_unknown;V_unknown]
+ | _ -> fail ()
+ end in
+ match v with
+ | (V_tuple [vl;vr]) -> binary_taint arith_help vl vr
+ | _ -> fail ()
+end
+
+let arith_op_range_vec op sign size v =
+ let fail () = Assert_extra.failwith ("arith_op_range_vec given unexpected " ^ (string_of_value v)) in
+ let arith_help vl vr = match (vl,vr) with
+ | (V_unknown,_) -> V_unknown
+ | (_,V_unknown) -> V_unknown
+ | (n, V_vector _ ord cs) ->
+ arith_op_vec op sign size (V_tuple [(to_vec ord (integerFromNat (List.length cs)) n);vr])
+ | _ -> fail ()
+ end in
+ match v with
+ | (V_tuple [vl;vr]) -> binary_taint arith_help vl vr
+ | _ -> fail ()
+end
+
+let arith_op_vec_range op sign size v =
+ let fail () = Assert_extra.failwith ("arith_op_vec_range given unexpected " ^ (string_of_value v)) in
+ let arith_help vl vr = match (vl,vr) with
+ | (V_unknown,_) -> V_unknown
+ | (_,V_unknown) -> V_unknown
+ | (V_vector _ ord cs,n) ->
+ arith_op_vec op sign size (V_tuple [vl;(to_vec ord (integerFromNat (List.length cs)) n)])
+ | _ -> fail ()
+ end in
+ match v with
+ | (V_tuple [vl;vr]) -> binary_taint arith_help vl vr
+ | _ -> fail ()
+end
+
+let arith_op_range_vec_range op sign v =
+ let fail () = Assert_extra.failwith ("arith_op_range_vec_range given unexpected " ^ (string_of_value v)) in
+ let arith_help vl vr = match (vl,vr) with
+ | (V_unknown,_) -> V_unknown
+ | (_,V_unknown) -> V_unknown
+ | (n,V_vector _ ord _) ->
+ arith_op op (V_tuple [n;(to_num Unsigned vr)])
+ | _ -> fail ()
+ end in
+ match v with
+ | (V_tuple [vl;vr]) -> binary_taint arith_help vl vr
+ | _ -> fail ()
+end
+
+let arith_op_vec_range_range op sign v =
+ let fail () = Assert_extra.failwith ("arith_op_vec_range_range given unexpected " ^ (string_of_value v)) in
+ let arith_help vl vr = match (vl,vr) with
+ | (V_unknown,_) -> V_unknown
+ | (_,V_unknown) -> V_unknown
+ | (V_vector _ ord _ ,n) ->
+ arith_op op (V_tuple [(to_num sign vl);n])
+ | _ -> fail ()
+ end in
+ match v with
+ | (V_tuple [vl;vr]) -> binary_taint arith_help vl vr
+ | _ -> fail ()
+end
+
+let arith_op_vec_bit op sign size v =
+ let fail () = Assert_extra.failwith ("arith_op_vec_bit given unexpected " ^ (string_of_value v)) in
+ let arith_help vl vr =
+ match (vl,vr) with
+ | (V_unknown,_) -> V_unknown
+ | (_,V_unknown) -> V_unknown
+ | (V_vector _ ord cs,V_lit (L_aux bit _)) ->
+ let l1' = to_num sign vl in
+ let n = arith_op op (V_tuple
+ [l1';
+ V_lit
+ (L_aux (L_num (match bit with | L_one -> 1 | _ -> 0 end)) Unknown)])
+ in
+ to_vec ord (integerFromNat ((List.length cs) * size)) n
+ | _ -> fail ()
+ end in
+ match v with
+ | (V_tuple [vl;vr]) -> binary_taint arith_help vl vr
+ | _ -> fail ()
+end
+
+let arith_op_no0 op v =
+ let fail () = Assert_extra.failwith ("arith_op_no0 given unexpected " ^ (string_of_value v)) in
+ let arith_help vl vr =
+ match (vl,vr) with
+ | (V_lit(L_aux (L_num x) lx), V_lit(L_aux (L_num y) ly)) ->
+ if y = 0
+ then V_lit (L_aux L_undef ly)
+ else V_lit(L_aux (L_num (op x y)) lx)
+ | (V_lit (L_aux L_undef lx),_) -> vl
+ | (_, (V_lit (L_aux L_undef ly))) -> vr
+ | (V_unknown,_) -> V_unknown
+ | (_,V_unknown) -> V_unknown
+ | _ -> fail ()
+ end in
+ match v with
+ | (V_tuple [vl;vr]) -> binary_taint arith_help vl vr
+ | _ -> fail ()
+end
+
+let arith_op_vec_no0 op op_s sign size v =
+ let fail () = Assert_extra.failwith ("arith_op_vec_no0 given unexpected " ^ (string_of_value v)) in
+ let arith_help vl vr =
+ match (vl,vr) with
+ | (V_vector b ord cs, V_vector _ _ _) ->
+ let act_size = (List.length cs) * size in
+ let (is_l1_unknown,is_l2_unknown) = ((has_unknown vl), (has_unknown vr)) in
+ let (l1',l2') = (if is_l1_unknown then V_unknown else (to_num sign vl),
+ if is_l2_unknown then V_unknown else (to_num sign vr)) in
+ let n = if is_l1_unknown || is_l2_unknown then V_unknown else arith_op op (V_tuple [l1';l2']) in
+ let representable =
+ match detaint n with
+ | V_lit (L_aux (L_num n') ln) ->
+ ((n' <= (get_max_representable_in sign act_size)) && (n' >= (get_min_representable_in sign act_size)))
+ | _ -> true end in
+ if representable
+ then to_vec ord (integerFromNat act_size) n
+ else to_vec ord (integerFromNat act_size) (V_lit (L_aux L_undef Unknown))
+ | (V_unknown,_) -> V_unknown
+ | (_,V_unknown) -> V_unknown
+ | _ -> fail ()
+ end in
+ match v with
+ | (V_tuple [vl;vr]) -> binary_taint arith_help vl vr
+ | _ -> fail ()
+end
+
+let arith_op_overflow_vec_no0 op op_s sign size v =
+ let fail () = Assert_extra.failwith ("arith_op_overflow_vec_no0 given unexpected " ^ (string_of_value v)) in
+ let arith_help vl vr =
+ match (vl,vr) with
+ | (V_vector b ord cs, V_vector _ _ cs2) ->
+ let rep_size = (List.length cs2) * size in
+ let act_size = (List.length cs) * size in
+ let (is_l1_unknown,is_l2_unknown) = ((has_unknown vl), (has_unknown vr)) in
+ if is_l1_unknown || is_l2_unknown
+ then V_tuple [to_vec ord (integerFromNat act_size) V_unknown;V_unknown;V_unknown]
+ else
+ let (l1',l2') = ((to_num sign vl),(to_num sign vr)) in
+ let (l1_u,l2_u) = (to_num Unsigned vl,to_num Unsigned vr) in
+ let n = arith_op op (V_tuple [l1';l2']) in
+ let n_u = arith_op op (V_tuple [l1_u;l2_u]) in
+ let representable =
+ match detaint n with
+ | V_lit (L_aux (L_num n') ln) ->
+ ((n' <= (get_max_representable_in sign rep_size)) && (n' >= (get_min_representable_in sign rep_size)))
+ | _ -> true end in
+ let (correct_size_num,one_more) =
+ if representable then (to_vec ord (integerFromNat act_size) n,to_vec ord (integerFromNat (act_size+1)) n_u)
+ else let udef = V_lit (L_aux L_undef Unknown) in
+ (to_vec ord (integerFromNat act_size) udef, to_vec ord (integerFromNat (act_size +1)) udef) in
+ let overflow = if representable then V_lit (L_aux L_zero Unknown) else V_lit (L_aux L_one Unknown) in
+ let carry = match one_more with
+ | V_vector _ _ (b::bits) -> b
+ | _ -> Assert_extra.failwith "one_more returned non-vector" end in
+ V_tuple [correct_size_num;overflow;carry]
+ | (V_unknown,_) -> V_tuple [V_unknown;V_unknown;V_unknown]
+ | (_,V_unknown) -> V_tuple [V_unknown;V_unknown;V_unknown]
+ | _ -> fail ()
+ end in
+ match v with
+ | (V_tuple [vl;vr]) -> binary_taint arith_help vl vr
+ | _ -> fail()
+end
+
+let arith_op_vec_range_no0 op op_s sign size v =
+ let fail () = Assert_extra.failwith ("arith_op_vec_range_no0 given unexpected " ^ (string_of_value v)) in
+ let arith_help vl vr =
+ match (vl,vr) with
+ | (V_unknown,_) -> V_unknown
+ | (_,V_unknown) -> V_unknown
+ | (V_vector _ ord cs,n) ->
+ arith_op_vec_no0 op op_s sign size (V_tuple [vl;(to_vec ord (integerFromNat (List.length cs)) n)])
+ | _ -> fail ()
+ end in
+ match v with
+ | (V_tuple [vl;vr]) -> binary_taint arith_help vl vr
+ | _ -> fail ()
+end
+
+let rec shift_op_vec op v =
+ let fail () = Assert_extra.failwith ("shift_op_vec given unexpected " ^ (string_of_value v)) in
+ let arith_op_help vl vr =
+ match (vl,vr) with
+ | (V_vector b ord cs,V_lit (L_aux (L_num n) _)) ->
+ let n = natFromInteger n in
+ (match op with
+ | "<<" ->
+ V_vector b ord
+ ((from_n_to_n n ((length cs) - 1) cs) ++(List.replicate n (V_lit (L_aux L_zero Unknown))))
+ | ">>" ->
+ V_vector b ord
+ ((List.replicate n (V_lit (L_aux L_zero Unknown))) ++ (from_n_to_n 0 (((length cs) -1) - n) cs))
+ | "<<<" ->
+ V_vector b ord
+ ((from_n_to_n n ((length cs) -1) cs) ++ (from_n_to_n 0 (n-1) cs))
+ | _ -> Assert_extra.failwith "shift_op_vec given non-recognized op" end)
+ | (V_unknown,_) -> V_unknown
+ | (_,V_unknown) -> V_unknown
+ | (V_lit (L_aux L_undef lx), _) -> V_lit (L_aux L_undef lx)
+ | (_, V_lit (L_aux L_undef ly)) -> V_lit (L_aux L_undef ly)
+ | _ -> fail ()
+ end in
+ match v with
+ | (V_tuple [vl;vr]) -> binary_taint arith_op_help vl vr
+ | _ -> fail ()
+end
+
+let compare_op op v =
+ let fail () = Assert_extra.failwith ("compare_op given unexpected " ^ (string_of_value v)) in
+ let comp_help vl vr = match (vl,vr) with
+ | (V_unknown,_) -> V_unknown
+ | (_,V_unknown) -> V_unknown
+ | (V_lit (L_aux L_undef lx), _) -> V_lit (L_aux L_undef lx)
+ | (_, V_lit (L_aux L_undef ly)) -> V_lit (L_aux L_undef ly)
+ | (V_lit(L_aux (L_num x) lx), V_lit(L_aux (L_num y) ly)) ->
+ if (op x y)
+ then V_lit(L_aux L_one lx)
+ else V_lit(L_aux L_zero lx)
+ | _ -> fail ()
+ end in
+ match v with
+ | (V_tuple [vl;vr]) -> binary_taint comp_help vl vr
+ | _ -> fail ()
+end
+
+let compare_op_vec op sign v =
+ let fail () = Assert_extra.failwith ("compare_op_vec given unexpected " ^ (string_of_value v)) in
+ let comp_help vl vr = match (vl,vr) with
+ | (V_unknown,_) -> V_unknown
+ | (_,V_unknown) -> V_unknown
+ | (V_vector _ _ _,V_vector _ _ _) ->
+ let (l1',l2') = (to_num sign vl, to_num sign vr) in
+ compare_op op (V_tuple[l1';l2'])
+ | _ -> fail ()
+ end in
+ match v with
+ | (V_tuple [vl;vr]) -> binary_taint comp_help vl vr
+ | _ -> fail ()
+end
+
+let compare_op_vec_range op sign v =
+ let fail () = Assert_extra.failwith ("compare_op_vec_range given unexpected " ^ (string_of_value v)) in
+ let comp_help vl vr = match (vl,vr) with
+ | (V_unknown,_) -> V_unknown
+ | (_,V_unknown) -> V_unknown
+ | _ -> compare_op op (V_tuple[(to_num sign vl);vr])
+ end in
+ match v with
+ | (V_tuple [vl;vr]) -> binary_taint comp_help vl vr
+ | _ -> fail ()
+end
+
+let compare_op_range_vec op sign v =
+ let fail () = Assert_extra.failwith ("compare_op_range_vec given unexpected " ^ (string_of_value v)) in
+ let comp_help vl vr = match (vl,vr) with
+ | (V_unknown,_) -> V_unknown
+ | (_,V_unknown) -> V_unknown
+ | _ -> compare_op op (V_tuple[vl;(to_num sign vr)])
+ end in
+ match v with
+ | (V_tuple [vl;vr]) -> binary_taint comp_help vl vr
+ | _ -> fail ()
+end
+
+let compare_op_vec_unsigned op v =
+ let fail () = Assert_extra.failwith ("compare_op_vec_unsigned given unexpected " ^ (string_of_value v)) in
+ let comp_help vl vr = match (vl,vr) with
+ | (V_unknown,_) -> V_unknown
+ | (_,V_unknown) -> V_unknown
+ | (V_vector _ _ _,V_vector _ _ _) ->
+ let (l1',l2') = (to_num Unsigned vl, to_num Unsigned vr) in
+ compare_op op (V_tuple[l1';l2'])
+ | _ -> fail ()
+ end in
+ match v with
+ | (V_tuple [vl;vr]) -> binary_taint comp_help vl vr
+ | _ -> fail ()
+end
+
+let duplicate direction v =
+ let fail () = Assert_extra.failwith ("duplicate given unexpected " ^ (string_of_value v)) in
+ let dup_help vl vr =
+ match (vl,vr) with
+ | ((V_lit _ as v),(V_lit (L_aux (L_num n) _))) ->
+ V_vector 0 direction (List.replicate (natFromInteger n) v)
+ | (V_unknown,(V_lit (L_aux (L_num n) _))) ->
+ V_vector 0 direction (List.replicate (natFromInteger n) V_unknown)
+ | (V_unknown,_) -> V_unknown
+ | (_, V_unknown) -> V_unknown
+ | _ -> fail ()
+ end in
+ match v with
+ | (V_tuple [vl;vr]) -> binary_taint dup_help vl vr
+ | _ -> fail ()
+end
+
+let rec repeat_block_helper (n: integer) bits =
+ if n <= 0
+ then []
+ else bits ++ (repeat_block_helper (n-1) bits)
+
+let duplicate_bits v =
+ let fail () = Assert_extra.failwith ("duplicate_bits given unexpected " ^ (string_of_value v)) in
+ let dup_help vl vr =
+ match (vl,vr) with
+ | (V_vector start direction bits, (V_lit (L_aux (L_num n) _))) ->
+ let start : nat = if direction = IInc then 0 else ((natFromInteger n) * (List.length bits)) - 1 in
+ (V_vector start direction (repeat_block_helper n bits))
+ | (_,V_unknown) -> V_unknown
+ | _ -> fail ()
+ end in
+ match v with
+ | (V_tuple [vl;vr]) -> binary_taint dup_help vl vr
+ | _ -> fail ()
+end
+
+
+let rec vec_concat v =
+ let fail () = Assert_extra.failwith ("vec_concat given unexpected " ^ (string_of_value v)) in
+ let concat_help vl vr =
+ match (vl,vr) with
+ | (V_vector n d l, V_vector n' d' l') ->
+ (* XXX d = d' ? dropping n' ? *)
+ V_vector n d (l ++ l')
+ | (V_lit l, (V_vector n d l' as x)) -> vec_concat (V_tuple [litV_to_vec l d; x])
+ | ((V_vector n d l' as x), V_lit l) -> vec_concat (V_tuple [x; litV_to_vec l d])
+ | (V_unknown,_) -> V_unknown
+ | (_,V_unknown) -> V_unknown
+ | _ -> fail ()
+ end in
+ match v with
+ | (V_tuple [vl;vr]) -> binary_taint concat_help vl vr
+ | _ -> fail ()
+end
+
+let v_length v = retaint v (match detaint v with
+ | V_vector n d l -> V_lit (L_aux (L_num (integerFromNat (List.length l))) Unknown)
+ | V_unknown -> V_unknown
+ | _ -> Assert_extra.failwith ("length given unexpected " ^ (string_of_value v)) end)
+
+let min v = retaint v (match detaint v with
+ | V_tuple [v1;v2] ->
+ (match (detaint v1,detaint v2) with
+ | (V_lit (L_aux (L_num l1) _), V_lit (L_aux (L_num l2) _)) ->
+ if l1 < l2
+ then retaint v2 v1
+ else retaint v1 v2
+ | (V_unknown,_) -> V_unknown
+ | (_,V_unknown) -> V_unknown
+ | (V_lit l1,_) -> Assert_extra.failwith ("Second argument to min not a number " ^ (string_of_value v2))
+ | (_,V_lit l2) -> Assert_extra.failwith ("First argument to min not a number " ^ (string_of_value v1))
+ | _ ->
+ Assert_extra.failwith ("min given unexpected " ^ (string_of_value v1) ^ " and " ^ (string_of_value v2)) end)
+ | _ -> Assert_extra.failwith ("min given unexpected " ^ (string_of_value v)) end)
+
+let max v = retaint v (match detaint v with
+ | (V_tuple [(V_lit (L_aux (L_num l1) _) as v1); (V_lit (L_aux (L_num l2) _) as v2)]) ->
+ if l1 > l2
+ then v1
+ else v2
+ | V_tuple [V_unknown; V_unknown] -> V_unknown
+ | _ -> Assert_extra.failwith ("max given unexpected " ^ (string_of_value v)) end)
+
+
+let mask direction v =
+ let fail () = Assert_extra.failwith ("shift_op_vec given unexpected " ^ (string_of_value v)) in
+ match v with
+ | (V_tuple [vsize;v]) ->
+ retaint v (match (detaint v,detaint vsize) with
+ | (V_vector s d l,V_lit (L_aux (L_num n) _)) ->
+ let n = natFromInteger n in
+ let current_size = List.length l in
+ V_vector (if is_inc(d) then 0 else (n-1)) d (drop (current_size - n) l)
+ | (V_unknown,V_lit (L_aux (L_num n) _)) ->
+ let nat_n = natFromInteger n in
+ let start_num = if is_inc(direction) then 0 else nat_n -1 in
+ V_vector start_num direction (List.replicate nat_n V_unknown)
+ | (_,V_unknown) -> V_unknown
+ | _ -> fail () end)
+| _ -> fail ()
+end
+
+let s_append v =
+ let fail () = Assert_extra.failwith ("append given unexpected " ^ (string_of_value v)) in
+ match v with
+ | (V_tuple [l1;l2]) ->
+ retaint v (match (detaint l1,detaint l2) with
+ | (V_list vs1, V_list vs2) -> V_list (vs1++vs2)
+ | (V_unknown, _) -> V_unknown
+ | (_,V_unknown) -> V_unknown
+ | _ -> fail () end)
+ | _ -> fail ()
+end
+
+let library_functions direction = [
+ ("ignore", ignore_sail);
+ ("append", s_append);
+ ("length", v_length);
+ ("add", arith_op (+));
+ ("add_vec", arith_op_vec (+) Unsigned 1);
+ ("add_vec_range", arith_op_vec_range (+) Unsigned 1);
+ ("add_vec_range_range", arith_op_vec_range_range (+) Unsigned);
+ ("add_range_vec", arith_op_range_vec (+) Unsigned 1);
+ ("add_range_vec_range", arith_op_range_vec_range (+) Unsigned);
+ ("add_vec_vec_range", arith_op_vec_vec_range (+) Unsigned);
+ ("add_vec_bit", arith_op_vec_bit (+) Unsigned 1);
+ ("add_overflow_vec", arith_op_overflow_vec (+) "+" Unsigned 1);
+ ("add_signed", arith_op (+));
+ ("add_vec_signed", arith_op_vec (+) Signed 1);
+ ("add_vec_range_signed", arith_op_vec_range (+) Signed 1);
+ ("add_vec_range_range_signed", arith_op_vec_range_range (+) Signed);
+ ("add_range_vec_signed", arith_op_range_vec (+) Signed 1);
+ ("add_range_vec_range_signed", arith_op_range_vec_range (+) Signed);
+ ("add_vec_vec_range_signed", arith_op_vec_vec_range (+) Signed);
+ ("add_vec_bit_signed", arith_op_vec_bit (+) Signed 1);
+ ("add_overflow_vec_signed", arith_op_overflow_vec (+) "+" Signed 1);
+ ("add_overflow_vec_bit_signed", arith_op_overflow_vec_bit (+) Signed 1);
+ ("minus", arith_op (-));
+ ("minus_vec", arith_op_vec (-) Unsigned 1);
+ ("minus_vec_range", arith_op_vec_range (-) Unsigned 1);
+ ("minus_range_vec", arith_op_range_vec (-) Unsigned 1);
+ ("minus_vec_range_range", arith_op_vec_range_range (-) Unsigned);
+ ("minus_range_vec_range", arith_op_range_vec_range (-) Unsigned);
+ ("minus_vec_bit", arith_op_vec_bit (-) Unsigned 1);
+ ("minus_overflow_vec", arith_op_overflow_vec (-) "+" Unsigned 1);
+ ("minus_overflow_vec_bit", arith_op_overflow_vec_bit (-) Unsigned 1);
+ ("minus_overflow_vec_signed", arith_op_overflow_vec (-) "+" Signed 1);
+ ("minus_overflow_vec_bit_signed", arith_op_overflow_vec_bit (-) Signed 1);
+ ("multiply", arith_op ( * ));
+ ("multiply_vec", arith_op_vec ( * ) Unsigned 2);
+ ("mult_range_vec", arith_op_range_vec ( * ) Unsigned 2);
+ ("mult_vec_range", arith_op_vec_range ( * ) Unsigned 2);
+ ("mult_overflow_vec", arith_op_overflow_vec ( * ) "*" Unsigned 2);
+ ("multiply_vec_signed", arith_op_vec ( * ) Signed 2);
+ ("mult_range_vec_signed", arith_op_range_vec ( * ) Signed 2);
+ ("mult_vec_range_signed", arith_op_vec_range ( * ) Signed 2);
+ ("mult_overflow_vec_signed", arith_op_overflow_vec ( * ) "*" Signed 2);
+ ("bitwise_leftshift", shift_op_vec "<<");
+ ("bitwise_rightshift", shift_op_vec ">>");
+ ("bitwise_rotate", shift_op_vec "<<<");
+ ("modulo", arith_op_no0 (mod));
+ ("mod_signed", arith_op_no0 hardware_mod);
+ ("mod_vec", arith_op_vec_no0 hardware_mod "mod" Unsigned 1);
+ ("mod_vec_range", arith_op_vec_range_no0 hardware_mod "mod" Unsigned 1);
+ ("mod_signed_vec", arith_op_vec_no0 hardware_mod "mod" Signed 1);
+ ("mod_signed_vec_range", arith_op_vec_range_no0 hardware_mod "mod" Signed 1);
+ ("quot", arith_op_no0 hardware_quot);
+ ("quot_signed", arith_op_no0 hardware_quot);
+ ("quot_vec", arith_op_vec_no0 hardware_quot "quot" Unsigned 1);
+ ("quot_overflow_vec", arith_op_overflow_vec_no0 hardware_quot "quot" Unsigned 1);
+ ("quot_vec_signed", arith_op_vec_no0 hardware_quot "quot" Signed 1);
+ ("quot_overflow_vec_signed", arith_op_overflow_vec_no0 hardware_quot "quot" Signed 1);
+ ("print", print);
+ ("power", arith_op power);
+ ("eq", eq);
+ ("eq_vec", eq_vec);
+ ("eq_vec_range", eq_vec_range);
+ ("eq_range_vec", eq_range_vec);
+ ("eq_bit", eq);
+ ("eq_range", eq);
+ ("neq", neq);
+ ("neq_vec", neq_vec);
+ ("neq_vec_range", neq_vec_range);
+ ("neq_range_vec", neq_range_vec);
+ ("neq_bit", neq);
+ ("neq_range", neq);
+ ("vec_concat", vec_concat);
+ ("is_one", is_one);
+ ("to_num", to_num Unsigned);
+ ("exts", exts direction);
+ ("extz", extz direction);
+ ("to_vec_inc", to_vec_inc);
+ ("to_vec_inc_undef", to_vec_inc_undef);
+ ("to_vec_dec", to_vec_dec);
+ ("to_vec_dec_undef", to_vec_dec_undef);
+ ("bitwise_not", bitwise_not);
+ ("bitwise_not_bit", bitwise_not_bit);
+ ("bitwise_and", bitwise_binop (&&) "&");
+ ("bitwise_or", bitwise_binop (||) "|");
+ ("bitwise_xor", bitwise_binop xor "^");
+ ("bitwise_and_bit", bitwise_binop_bit (&&) "&");
+ ("bitwise_or_bit", bitwise_binop_bit (||) "|");
+ ("bitwise_xor_bit", bitwise_binop_bit xor "^");
+ ("lt", compare_op (<));
+ ("lt_signed", compare_op (<));
+ ("gt", compare_op (>));
+ ("lteq", compare_op (<=));
+ ("gteq", compare_op (>=));
+ ("lt_vec", compare_op_vec (<) Signed);
+ ("gt_vec", compare_op_vec (>) Signed);
+ ("lt_vec_range", compare_op_vec_range (<) Signed);
+ ("gt_vec_range", compare_op_vec_range (>) Signed);
+ ("lt_range_vec", compare_op_range_vec (<) Signed);
+ ("gt_range_vec", compare_op_range_vec (>) Signed);
+ ("lteq_vec_range", compare_op_vec_range (<=) Signed);
+ ("gteq_vec_range", compare_op_vec_range (>=) Signed);
+ ("lteq_range_vec", compare_op_range_vec (<=) Signed);
+ ("gteq_range_vec", compare_op_range_vec (>=) Signed);
+ ("lteq_vec", compare_op_vec (<=) Signed);
+ ("gteq_vec", compare_op_vec (>=) Signed);
+ ("lt_vec_signed", compare_op_vec (<) Signed);
+ ("gt_vec_signed", compare_op_vec (>) Signed);
+ ("lteq_vec_signed", compare_op_vec (<=) Signed);
+ ("gteq_vec_signed", compare_op_vec (>=) Signed);
+ ("lt_vec_unsigned", compare_op_vec (<) Unsigned);
+ ("gt_vec_unsigned", compare_op_vec (>) Unsigned);
+ ("lteq_vec_unsigned", compare_op_vec (<=) Unsigned);
+ ("gteq_vec_unsigned", compare_op_vec (>=) Unsigned);
+ ("signed", to_num Signed);
+ ("unsigned", to_num Unsigned);
+ ("ltu", compare_op_vec_unsigned (<));
+ ("gtu", compare_op_vec_unsigned (>));
+ ("duplicate", duplicate direction);
+ ("duplicate_bits", duplicate_bits);
+ ("mask", mask direction);
+ ("most_significant", most_significant);
+ ("min", min);
+ ("max", max);
+ ("abs", v_abs);
+] ;;
+
+let eval_external name v = match List.lookup name (library_functions IInc) with
+ | Just f -> f v
+ | Nothing -> Assert_extra.failwith ("missing library function " ^ name)
+ end