summaryrefslogtreecommitdiff
path: root/src/lem_interp/interp_interface.lem
diff options
context:
space:
mode:
Diffstat (limited to 'src/lem_interp/interp_interface.lem')
-rw-r--r--src/lem_interp/interp_interface.lem178
1 files changed, 107 insertions, 71 deletions
diff --git a/src/lem_interp/interp_interface.lem b/src/lem_interp/interp_interface.lem
index 213b7d51..830877e1 100644
--- a/src/lem_interp/interp_interface.lem
+++ b/src/lem_interp/interp_interface.lem
@@ -53,7 +53,14 @@ type direction =
| D_increasing
| D_decreasing
-type register_value = <| rv_bits: list bit_lifted (* MSB first, smallest index number *); rv_dir: direction; rv_start: nat |>
+type register_value = <|
+ rv_bits: list bit_lifted (* MSB first, smallest index number *);
+ rv_dir: direction;
+ rv_start: nat ;
+ rv_start_internal: nat;
+ (*when dir is increasing, rv_start = rv_start_internal.
+ Otherwise, tells interpreter how to reconstruct a proper decreasing value*)
+ |>
type byte_lifted = Byte_lifted of list bit_lifted (* of length 8 *)
@@ -61,14 +68,14 @@ type instruction_field_value = list bit
type byte = Byte of list bit (* of length 8 *) (*MSB first*)
-type address_lifted = Address_lifted of list byte_lifted (* of length 8 for 64bit machines*)
+type address_lifted = Address_lifted of list byte_lifted (* of length 8 for 64bit machines*) * maybe integer
type memory_byte = byte_lifted
type memory_value = list memory_byte (* the head of the list, most-significant first, at the lowest address, of length >=1 *)
(* not sure which of these is more handy yet *)
-type address = Address of list byte (* of length 8 *)
+type address = Address of list byte (* of length 8 *) * integer
(* type address = Address of integer *)
type opcode = Opcode of list byte (* of length 4 *)
@@ -130,40 +137,46 @@ instance (Ord address_lifted)
end
(* Registers *)
-(*Can be nat nat, but finding out where ppcmem doens't like that is maybe not worth the effort *)
-type slice = (int * int)
+type slice = (nat * nat)
type reg_name =
-| Reg of string * nat
-(*Name of the register, accessing the entire register, and the size of this register *)
+| Reg of string * nat * nat * direction
+(*Name of the register, accessing the entire register, the start and size of this register, and it's direction *)
-| Reg_slice of string * slice
+| Reg_slice of string * nat * direction * slice
(* Name of the register, accessing from the bit indexed by the first
to the bit indexed by the second integer of the slice, inclusive. For
-Power the first will be a smaller number than or equal to the second;
-for other architectures it might be the other way round. *)
+machineDef* the first is a smaller number or equal to the second, adjusted
+to reflect the correct span direction in the interpreter side. *)
-| Reg_field of string * string * slice
-(*Name of the register and name of the field of the register
+| Reg_field of string * nat * direction * string * slice
+(*Name of the register, start and direction, and name of the field of the register
accessed. The slice specifies where this field is in the register*)
-| Reg_f_slice of string * string * slice * slice
-(* The first three components are as in Reg_field; the final slice
+| Reg_f_slice of string * nat * direction * string * slice * slice
+(* The first four components are as in Reg_field; the final slice
specifies a part of the field, indexed w.r.t. the register as a whole *)
-
-(* because reg_name contains slice which currently contains Big_int.big_int, the default OCaml comparison is not sufficient and we need to define explicit type classes *)
let slice_eq (s1l,s1r) (s2l,s2r) = (s1l = s2l) && (s1r = s2r)
let reg_nameEqual r1 r2 =
match (r1,r2) with
- | (Reg s1 l1, Reg s2 l2) -> s1=s2 && l1=l2
- | (Reg_slice s1 sl1, Reg_slice s2 sl2) -> s1=s2 && (slice_eq sl1 sl2)
- | (Reg_field s1 f1 sl1, Reg_field s2 f2 sl2) -> s1=s2 && f1=f2 && (slice_eq sl1 sl2)
- | (Reg_f_slice s1 f1 sl1 sl1', Reg_f_slice s2 f2 sl2 sl2') -> s1=s2 && f1=f2 && (slice_eq sl1 sl2) && (slice_eq sl1' sl2')
+ | (Reg s1 ns1 d1 l1, Reg s2 ns2 d2 l2) -> s1=s2 && ns1 = ns2 && l1=l2 && d1=d2
+ | (Reg_slice s1 ns1 d1 sl1, Reg_slice s2 ns2 d2 sl2) -> s1=s2 && ns1=ns2 && d1=d2 && (slice_eq sl1 sl2)
+ | (Reg_field s1 ns1 d1 f1 sl1, Reg_field s2 ns2 d2 f2 sl2) -> s1=s2 && ns1=ns2 && d1=d2 && f1=f2 && (slice_eq sl1 sl2)
+ | (Reg_f_slice s1 ns1 d1 f1 sl1 sl1', Reg_f_slice s2 ns2 d2 f2 sl2 sl2') ->
+ s1=s2 && ns1=ns2 && d1=d2 && f1=f2 && (slice_eq sl1 sl2) && (slice_eq sl1' sl2')
| _ -> false
end
+instance (Ord direction)
+ let compare = defaultCompare
+ let (<) = defaultLess
+ let (<=) = defaultLessEq
+ let (>) = defaultGreater
+ let (>=) = defaultGreaterEq
+end
+
instance (Eq reg_name)
let (=) = reg_nameEqual
let (<>) x y = not (reg_nameEqual x y)
@@ -171,15 +184,15 @@ end
let reg_nameCompare r1 r2 =
match (r1,r2) with
- | (Reg s1 l1, Reg s2 l2) -> pairCompare compare compare (s1,l1) (s2,l2)
- | (Reg_slice s1 sl1, Reg_slice s2 sl2) -> pairCompare compare compare (s1,sl1) (s2,sl2)
- | (Reg_field s1 f1 sl1, Reg_field s2 f2 sl2) ->
+ | (Reg s1 _ _ l1, Reg s2 _ _ l2) -> pairCompare compare compare (s1,l1) (s2,l2)
+ | (Reg_slice s1 _ _ sl1, Reg_slice s2 _ _ sl2) -> pairCompare compare compare (s1,sl1) (s2,sl2)
+ | (Reg_field s1 _ _ f1 sl1, Reg_field s2 _ _ f2 sl2) ->
tripleCompare compare compare compare (s1,f1,sl1) (s2,f2,sl2)
- | (Reg_f_slice s1 f1 sl1 sl1', Reg_f_slice s2 f2 sl2 sl2') ->
+ | (Reg_f_slice s1 _ _ f1 sl1 sl1', Reg_f_slice s2 _ _ f2 sl2 sl2') ->
pairCompare compare (tripleCompare compare compare compare) (s1,(f1,sl1,sl1')) (s2,(f2,sl2,sl2'))
- | (Reg _ _, _) -> LT
- | (Reg_slice _ _, _) -> LT
- | (Reg_field _ _ _, _) -> LT
+ | (Reg _ _ _ _, _) -> LT
+ | (Reg_slice _ _ _ _, _) -> LT
+ | (Reg_field _ _ _ _ _, _) -> LT
| (_, _) -> GT
end
@@ -195,6 +208,20 @@ instance (Ord reg_name)
let (>=) r1 r2 = (reg_nameCompare r1 r2) <> LT
end
+let direction_of_reg_name r = match r with
+ | Reg _ _ _ d -> d
+ | Reg_slice _ _ d _ -> d
+ | Reg_field _ _ d _ _ -> d
+ | Reg_f_slice _ _ d _ _ _ -> d
+ end
+
+let start_of_reg_name r = match r with
+ | Reg _ start _ _ -> start
+ | Reg_slice _ start _ _ -> start
+ | Reg_field _ start _ _ _ -> start
+ | Reg_f_slice _ start _ _ _ _ -> start
+end
+
(* Data structures for building up instructions *)
type read_kind =
@@ -376,20 +403,9 @@ val decode_to_instruction : context -> opcode -> instruction_or_decode_error
(*Function to generate the state to run from an instruction form; is always an Instr*)
val instruction_to_istate : context -> instruction -> instruction_state (*i_state_or_error*)
-(* Augment an address by the given value *)
-(*val add_to_address : value -> integer -> value
-
-(* Coerce a Bitvector value (presumed a multiple of 8 bits long) to a Bytevector value *)
-val coerce_Bytevector_of_Bitvector : value -> value
-
-(* Coerce a Bytevector value to a Bitvector value, increasing and starting at zero *)
-val coerce_Bitvector_of_Bytevector : value -> value*)
-
(* Slice a register value into a smaller vector, starting at first number (wrt the indices of the register value, not raw positions in its list of bits) and going to second (inclusive) according to order. *)
val slice_reg_value : register_value -> nat -> nat -> register_value
-(*(*append two vectors (bit x byte -> bit) *)
-val append_value : value -> value -> value *)
(* Big step of the interpreter, to the next request for an external action *)
(* When interp_mode has eager_eval false, interpreter is (close to) small step *)
@@ -410,13 +426,31 @@ val bitls_to_word8 : list bit_lifted -> word8
val integer_of_word8_list : list word8 -> integer
val word8_list_of_integer : integer -> integer -> list word8
+val concretizable_bitl : bit_lifted -> bool
+val concretizable_bytl : byte_lifted -> bool
+val concretizable_bytls : list byte_lifted -> bool
+
+let concretizable_bitl = function
+ | Bitl_zero -> true
+ | Bitl_one -> true
+ | Bitl_undef -> false
+ | Bitl_unknown -> false
+end
+
+let concretizable_bytl (Byte_lifted bs) = List.all concretizable_bitl bs
+let concretizable_bytls = List.all concretizable_bytl
+
(* constructing values *)
val register_value : bit_lifted -> direction -> nat -> nat -> register_value
let register_value b dir width start_index =
<| rv_bits = List.replicate width b;
rv_dir = dir; (* D_increasing for Power, D_decreasing for ARM *)
- rv_start = start_index; |>
+ rv_start_internal = start_index;
+ rv_start = if dir = D_increasing
+ then start_index
+ else (start_index+1) - width; (* Smaller index, as in Power, for external interaction *)
+ |>
val register_value_zeros : direction -> nat -> nat -> register_value
let register_value_zeros dir width start_index =
@@ -429,9 +463,9 @@ let register_value_ones dir width start_index =
val byte_lifted_unknown : byte_lifted
let byte_lifted_unknown = Byte_lifted (List.replicate 8 Bitl_unknown)
-val memory_value_unknown : int (*the number of bytes*) -> memory_value
-let memory_value_unknown (width:int) : memory_value =
- List.replicate (natFromInt width) byte_lifted_unknown
+val memory_value_unknown : nat (*the number of bytes*) -> memory_value
+let memory_value_unknown (width:nat) : memory_value =
+ List.replicate width byte_lifted_unknown
(* lengths *)
@@ -539,13 +573,12 @@ let byte_list_of_integer (len:nat) (a:integer):list byte =
val integer_of_address : address -> integer
let integer_of_address (a:address):integer =
match a with
- | Address bs -> integer_of_byte_list bs
+ | Address bs i -> i
end
val address_of_integer : integer -> address
let address_of_integer (i:integer):address =
- Address (byte_list_of_integer 8 i)
-
+ Address (byte_list_of_integer 8 i) i
(* regarding a list of int as a list of bytes in memory, MSB lowest-address first, convert to an integer *)
@@ -561,28 +594,26 @@ let integer_address_of_int_list (is: list int) =
val address_of_byte_list : list byte -> address
let address_of_byte_list bs =
if List.length bs <> 8 then failwith "address_of_byte_list given list not of length 8" else
- Address bs
-
+ Address bs (integer_of_byte_list bs)
(* operations on addresses *)
-val add_address_int : address -> int -> address
-let add_address_int (a:address) (i:int) : address =
- address_of_integer ((integer_of_address a) + (integerFromInt i))
+val add_address_nat : address -> nat -> address
+let add_address_nat (a:address) (i:nat) : address =
+ address_of_integer ((integer_of_address a) + (integerFromNat i))
val clear_low_order_bits_of_address : address -> address
let clear_low_order_bits_of_address a =
match a with
- | Address [b0;b1;b2;b3;b4;b5;b6;b7] ->
+ | Address [b0;b1;b2;b3;b4;b5;b6;b7] i ->
match b7 with
| Byte [bt0;bt1;bt2;bt3;bt4;bt5;bt6;bt7] ->
let b7' = Byte [bt0;bt1;bt2;bt3;bt4;bt5;Bitc_zero;Bitc_zero] in
- Address [b0;b1;b2;b3;b4;b5;b6;b7']
+ let bytes = [b0;b1;b2;b3;b4;b5;b6;b7'] in
+ Address bytes (integer_of_byte_list bytes)
end
end
-
-
val byte_list_of_memory_value : memory_value -> maybe (list byte)
let byte_list_of_memory_value mv = maybe_all (List.map byte_of_memory_byte mv)
@@ -605,29 +636,30 @@ let integer_of_register_value (rv:register_value):maybe integer =
| Nothing -> Nothing
| Just bs -> Just (integer_of_bit_list bs)
end
-
-val register_value_of_integer : nat -> nat -> integer -> register_value
-let register_value_of_integer (len:nat) (start:nat) (i:integer):register_value =
+val register_value_of_integer : nat -> nat -> direction -> integer -> register_value
+let register_value_of_integer (len:nat) (start:nat) (dir:direction) (i:integer):register_value =
let bs = bit_list_of_integer len i in
<|
rv_bits = List.map bit_lifted_of_bit bs;
- rv_dir = D_increasing;
+ rv_dir = dir;
rv_start = start;
+ rv_start_internal = if dir = D_increasing then start else start + (List.length bs) - 1
|>
-
(* *)
val opcode_of_bytes : byte -> byte -> byte -> byte -> opcode
let opcode_of_bytes b0 b1 b2 b3 : opcode = Opcode [b0;b1;b2;b3]
-val register_value_of_address : address -> register_value
-let register_value_of_address (Address bytes) : register_value =
- <| rv_bits = List.concatMap (fun (Byte bs) -> List.map bit_lifted_of_bit bs) bytes;
- rv_dir = D_increasing;
- rv_start = 0; |>
-
+val register_value_of_address : address -> direction -> register_value
+let register_value_of_address (Address bytes _) dir : register_value =
+ let bits = List.concatMap (fun (Byte bs) -> List.map bit_lifted_of_bit bs) bytes in
+ <| rv_bits = bits;
+ rv_dir = dir;
+ rv_start = 0;
+ rv_start_internal = if dir = D_increasing then 0 else (List.length bits) - 1
+ |>
val address_lifted_of_register_value : register_value -> maybe address_lifted
@@ -636,18 +668,22 @@ allowing Bitl_undef and Bitl_unknown *)
let address_lifted_of_register_value (rv:register_value) : maybe address_lifted =
if List.length rv.rv_bits <> 64 then Nothing
else
- Just (Address_lifted (byte_lifteds_of_bit_lifteds rv.rv_bits))
-
+ Just (Address_lifted (byte_lifteds_of_bit_lifteds rv.rv_bits)
+ (if List.all concretizable_bitl rv.rv_bits
+ then let (Just(bits)) = (maybe_all (List.map bit_of_bit_lifted rv.rv_bits)) in
+ Just (integer_of_bit_list bits)
+ else Nothing))
val address_of_address_lifted : address_lifted -> maybe address
(* returning Nothing iff the address contains any Bitl_undef or Bitl_unknown *)
let address_of_address_lifted (al:address_lifted): maybe address =
match al with
- | Address_lifted bls ->
+ | Address_lifted bls (Just i)->
match maybe_all ((List.map byte_of_byte_lifted) bls) with
| Nothing -> Nothing
- | Just bs -> Just (Address bs)
+ | Just bs -> Just (Address bs i)
end
+ | _ -> Nothing
end
val address_of_register_value : register_value -> maybe address
@@ -690,13 +726,13 @@ let int_of_memory_byte (mb:memory_byte) : int =
val memory_value_of_address_lifted : address_lifted -> memory_value
let memory_value_of_address_lifted (al:address_lifted) =
match al with
- | Address_lifted bs -> bs
+ | Address_lifted bs _ -> bs
end
val byte_list_of_address : address -> list byte
let byte_list_of_address (a:address) : list byte =
match a with
- | Address bs -> bs
+ | Address bs _ -> bs
end
val byte_list_of_opcode : opcode -> list byte