summaryrefslogtreecommitdiff
path: root/riscv
diff options
context:
space:
mode:
authorJon French2018-06-11 16:38:53 +0100
committerJon French2018-06-11 16:38:53 +0100
commit6b70f78c3c9477d4c5f417ed0a5d96abc19c9fb0 (patch)
tree5d8bdfd982c5c0efde9c7eac021f6341af124e7f /riscv
parent0cc7d50e08b36d036771493920bb2e20251def64 (diff)
parent22aff19aeea53719004cca2b5c6b25d0a7ed0835 (diff)
Merge branch 'mappings' into sail2
Diffstat (limited to 'riscv')
-rw-r--r--riscv/Makefile11
-rw-r--r--riscv/main.sail1
-rw-r--r--riscv/prelude.sail75
-rw-r--r--riscv/riscv.sail477
-rw-r--r--riscv/riscv_sys.sail63
-rw-r--r--riscv/riscv_types.sail68
6 files changed, 577 insertions, 118 deletions
diff --git a/riscv/Makefile b/riscv/Makefile
index 8d9c3d6d..9e07ffa6 100644
--- a/riscv/Makefile
+++ b/riscv/Makefile
@@ -1,16 +1,17 @@
SAIL_SRCS = prelude.sail riscv_types.sail riscv_sys.sail riscv_platform.sail riscv_mem.sail riscv_vmem.sail riscv.sail riscv_step.sail
PLATFORM_OCAML_SRCS = platform.ml platform_impl.ml platform_main.ml
SAIL_DIR ?= $(realpath ..)
+SAIL ?= $(SAIL_DIR)/sail
export SAIL_DIR
all: platform Riscv.thy
check: $(SAIL_SRCS) main.sail Makefile
- $(SAIL_DIR)/sail $(SAIL_SRCS) main.sail
+ $(SAIL) $(SAIL_FLAGS) $(SAIL_SRCS) main.sail
_sbuild/riscv.ml: $(SAIL_SRCS) Makefile main.sail
- $(SAIL_DIR)/sail -ocaml -ocaml-nobuild -o riscv $(SAIL_SRCS)
+ $(SAIL) $(SAIL_FLAGS) -ocaml -ocaml-nobuild -o riscv $(SAIL_SRCS)
_sbuild/platform_main.native: _sbuild/riscv.ml _tags $(PLATFORM_OCAML_SRCS) Makefile
cp _tags $(PLATFORM_OCAML_SRCS) _sbuild
@@ -20,10 +21,10 @@ platform: _sbuild/platform_main.native
rm -f $@ && ln -s $^ $@
riscv_duopod_ocaml: prelude.sail riscv_duopod.sail
- $(SAIL_DIR)/sail -ocaml -o $@ $^
+ $(SAIL) $(SAIL_FLAGS) -ocaml -o $@ $^
riscv_duopod.lem: prelude.sail riscv_duopod.sail
- $(SAIL_DIR)/sail -lem -lem_mwords -lem_lib Riscv_extras -o riscv_duopod $^
+ $(SAIL) $(SAIL_FLAGS) -lem -lem_mwords -lem_lib Riscv_extras -o riscv_duopod $^
Riscv_duopod.thy: riscv_duopod.lem riscv_extras.lem
lem -isa -outdir . -lib ../src/lem_interp -lib ../src/gen_lib \
riscv_extras.lem \
@@ -40,7 +41,7 @@ Riscv.thy: riscv.lem riscv_extras.lem
sed -i 's/datatype ast/datatype (plugins only: size) ast/' Riscv_types.thy
riscv.lem: $(SAIL_SRCS) Makefile
- $(SAIL_DIR)/sail -lem -o riscv -lem_mwords -lem_lib Riscv_extras $(SAIL_SRCS)
+ $(SAIL) $(SAIL_FLAGS) -lem -o riscv -lem_mwords -lem_lib Riscv_extras $(SAIL_SRCS)
riscv_sequential.lem: $(SAIL_SRCS) Makefile
$(SAIL_DIR)/sail -lem -lem_sequential -o riscv_sequential -lem_mwords -lem_lib Riscv_extras_sequential $(SAIL_SRCS)
diff --git a/riscv/main.sail b/riscv/main.sail
index c923935b..b2a53b11 100644
--- a/riscv/main.sail
+++ b/riscv/main.sail
@@ -11,6 +11,7 @@ val elf_entry = {
val main : unit -> unit effect {barr, eamem, escape, exmem, rmem, rreg, wmv, wreg}
function main () = {
+
PC = __GetSlice_int(64, elf_entry(), 0);
try {
init_sys ();
diff --git a/riscv/prelude.sail b/riscv/prelude.sail
index 1bc4b4d6..d10dddc9 100644
--- a/riscv/prelude.sail
+++ b/riscv/prelude.sail
@@ -3,6 +3,67 @@ default Order dec
type bits ('n : Int) = vector('n, dec, bit)
union option ('a : Type) = {None : unit, Some : 'a}
+val spc : unit <-> string
+val opt_spc : unit <-> string
+val def_spc : unit <-> string
+
+val hex_bits : forall 'n . (atom('n), bits('n)) <-> string
+
+val hex_bits_4 : bits(4) <-> string
+val hex_bits_4_forwards = "string_of_bits" : bits(4) -> string
+val "hex_bits_4_matches_prefix" : string -> option((bits(4), nat))
+
+val hex_bits_5 : bits(5) <-> string
+val hex_bits_5_forwards = "string_of_bits" : bits(5) -> string
+val "hex_bits_5_matches_prefix" : string -> option((bits(5), nat))
+
+val hex_bits_6 : bits(6) <-> string
+val hex_bits_6_forwards = "string_of_bits" : bits(6) -> string
+val "hex_bits_6_matches_prefix" : string -> option((bits(6), nat))
+
+val hex_bits_12 : bits(12) <-> string
+val hex_bits_12_forwards = "string_of_bits" : bits(12) -> string
+val "hex_bits_12_matches_prefix" : string -> option((bits(12), nat))
+
+val hex_bits_13 : bits(13) <-> string
+val hex_bits_13_forwards = "string_of_bits" : bits(13) -> string
+val "hex_bits_13_matches_prefix" : string -> option((bits(13), nat))
+
+val hex_bits_20 : bits(20) <-> string
+val hex_bits_20_forwards = "string_of_bits" : bits(20) -> string
+val "hex_bits_20_matches_prefix" : string -> option((bits(20), nat))
+
+val hex_bits_21 : bits(21) <-> string
+val hex_bits_21_forwards = "string_of_bits" : bits(21) -> string
+val "hex_bits_21_matches_prefix" : string -> option((bits(21), nat))
+
+val hex_bits_32 : bits(32) <-> string
+val hex_bits_32_forwards = "string_of_bits" : bits(32) -> string
+val "hex_bits_32_matches_prefix" : string -> option((bits(32), nat))
+
+
+val spc_forwards : unit -> string
+function spc_forwards () = " "
+val spc_backwards : string -> unit
+function spc_backwards s = ()
+
+val spc_matches_prefix = "spc_matches_prefix" : string -> option((unit, nat))
+
+val opt_spc_forwards : unit -> string
+function opt_spc_forwards () = ""
+val opt_spc_backwards : string -> unit
+function opt_spc_backwards s = ()
+
+val opt_spc_matches_prefix = "opt_spc_matches_prefix" : string -> option((unit, nat))
+
+val def_spc_forwards : unit -> string
+function def_spc_forwards () = " "
+val def_spc_backwards : string -> unit
+function def_spc_backwards s = ()
+
+val def_spc_matches_prefix = "opt_spc_matches_prefix" : string -> option((unit, nat))
+
+
val eq_atom = {ocaml: "eq_int", lem: "eq", c: "eq_int"} : forall 'n 'm. (atom('n), atom('m)) -> bool
val lteq_atom = "lteq" : forall 'n 'm. (atom('n), atom('m)) -> bool
val gteq_atom = "gteq" : forall 'n 'm. (atom('n), atom('m)) -> bool
@@ -10,12 +71,19 @@ val lt_atom = "lt" : forall 'n 'm. (atom('n), atom('m)) -> bool
val gt_atom = "gt" : forall 'n 'm. (atom('n), atom('m)) -> bool
val eq_int = {ocaml: "eq_int", lem: "eq"} : (int, int) -> bool
-
-val "eq_bit" : (bit, bit) -> bool
+val eq_bit = {ocaml: "eq_bit", lem: "eq", interpreter: "eq_anything", c: "eq_bit"} : (bit, bit) -> bool
val eq_vec = {ocaml: "eq_list", lem: "eq_vec"} : forall 'n. (bits('n), bits('n)) -> bool
val eq_string = {ocaml: "eq_string", lem: "eq"} : (string, string) -> bool
+val string_startswith = "string_startswith" : (string, string) -> bool
+val string_drop = "string_drop" : (string, nat) -> string
+val string_length = "string_length" : string -> nat
+val string_append = "string_append" : (string, string) -> string
+val maybe_int_of_prefix = "maybe_int_of_prefix" : string -> option((int, nat))
+val maybe_nat_of_prefix = "maybe_nat_of_prefix" : string -> option((nat, nat))
+val maybe_int_of_string = "maybe_int_of_string" : string -> option(int)
+
val eq_real = {ocaml: "eq_real", lem: "eq"} : (real, real) -> bool
@@ -188,6 +256,9 @@ val sub_range = {ocaml: "sub_int", lem: "integerMinus"} : forall 'n 'm 'o 'p.
(range('n, 'm), range('o, 'p)) -> range('n - 'p, 'm - 'o)
val sub_int = {ocaml: "sub_int", lem: "integerMinus"} : (int, int) -> int
+val sub_nat = {ocaml: "(fun (x,y) -> let n = sub_int (x,y) in if Big_int.less_equal n Big_int.zero then Big_int.zero else n)",
+ lem: "integerMinus"}
+ : (nat, nat) -> nat
val "sub_vec" : forall 'n. (bits('n), bits('n)) -> bits('n)
diff --git a/riscv/riscv.sail b/riscv/riscv.sail
index fd42df21..9f4385e7 100644
--- a/riscv/riscv.sail
+++ b/riscv/riscv.sail
@@ -1,7 +1,6 @@
scattered union ast
val decode : bits(32) -> option(ast) effect pure
-scattered function decode
val decodeCompressed : bits(16) -> option(ast) effect pure
scattered function decodeCompressed
@@ -13,11 +12,21 @@ scattered function execute
val cast print_insn : ast -> string
scattered function print_insn
+val assembly : ast <-> string
+scattered mapping assembly
+
+val encdec : ast <-> bits(32)
+scattered mapping encdec
+
/* ****************************************************************** */
union clause ast = UTYPE : (bits(20), regbits, uop)
-function clause decode imm : bits(20) @ rd : regbits @ 0b0110111 = Some(UTYPE(imm, rd, RISCV_LUI))
-function clause decode imm : bits(20) @ rd : regbits @ 0b0010111 = Some(UTYPE(imm, rd, RISCV_AUIPC))
+mapping encdec_uop : uop <-> bits(7) = {
+ RISCV_LUI <-> 0b0110111,
+ RISCV_AUIPC <-> 0b0010111
+}
+
+mapping clause encdec = UTYPE(imm, rd, op) <-> imm @ rd @ encdec_uop(op)
function clause execute UTYPE(imm, rd, op) =
let off : xlenbits = EXTS(imm @ 0x000) in
@@ -35,10 +44,30 @@ function clause print_insn UTYPE(imm, rd, op) =
RISCV_AUIPC => "auipc " ^ rd ^ ", " ^ BitStr(imm)
}
+mapping utype_mnemonic : uop <-> string = {
+ RISCV_LUI <-> "lui",
+ RISCV_AUIPC <-> "auipc"
+}
+
+mapping clause assembly = UTYPE(imm, rd, op) <-> utype_mnemonic(op) ^ spc() ^ reg_name(rd) ^ sep() ^ hex_bits_20(imm)
+
/* ****************************************************************** */
union clause ast = RISCV_JAL : (bits(21), regbits)
-function clause decode imm : bits(20) @ rd : regbits @ 0b1101111 = Some (RISCV_JAL(imm[19] @ imm[7..0] @ imm[8] @ imm[18..13] @ imm[12..9] @ 0b0, rd))
+mapping clause encdec = RISCV_JAL(imm_19 @ imm_7_0 @ imm_8 @ imm_18_13 @ imm_12_9 @ 0b0, rd)
+ <-> imm_19 : bits(1) @ imm_18_13 : bits(6) @ imm_12_9 : bits(4) @ imm_8 : bits(1) @ imm_7_0 : bits(8) @ rd @ 0b1101111
+
+/*
+ideally we want some syntax like
+
+mapping clause encdec = RISCV_JAL(imm @ 0b0, rd) <-> imm[19] @ imm[9..0] @ imm[10] @ imm[18..11] @ rd @ 0b1101111
+
+match bv {
+ imm[19] @ imm[9..0] @ imm[10] @ imm[18..11] -> imm @ 0b0
+}
+
+but this is difficult
+*/
function clause execute (RISCV_JAL(imm, rd)) = {
let pc : xlenbits = PC;
@@ -51,11 +80,14 @@ function clause execute (RISCV_JAL(imm, rd)) = {
function clause print_insn (RISCV_JAL(imm, rd)) =
"jal " ^ rd ^ ", " ^ BitStr(imm)
+/* TODO: handle 2-byte-alignment in mappings */
+
+mapping clause assembly = RISCV_JAL(imm, rd) <-> "jal" ^ spc() ^ reg_name(rd) ^ sep() ^ hex_bits_21(imm)
+
/* ****************************************************************** */
union clause ast = RISCV_JALR : (bits(12), regbits, regbits)
-function clause decode imm : bits(12) @ rs1 : regbits @ 0b000 @ rd : regbits @ 0b1100111 =
- Some(RISCV_JALR(imm, rs1, rd))
+mapping clause encdec = RISCV_JALR(imm, rs1, rd) <-> imm @ rs1 @ 0b000 @ rd @ 0b1100111
function clause execute (RISCV_JALR(imm, rs1, rd)) = {
/* write rd before anything else to prevent unintended strength */
@@ -68,15 +100,22 @@ function clause execute (RISCV_JALR(imm, rs1, rd)) = {
function clause print_insn (RISCV_JALR(imm, rs1, rd)) =
"jalr " ^ rd ^ ", " ^ rs1 ^ ", " ^ BitStr(imm)
+mapping clause assembly = RISCV_JALR(imm, rs1, rd) <-> "jalr" ^ spc() ^ reg_name(rd) ^ sep() ^ reg_name(rs1) ^ sep() ^ hex_bits_12(imm)
+
/* ****************************************************************** */
union clause ast = BTYPE : (bits(13), regbits, regbits, bop)
-function clause decode imm7 : bits(7) @ rs2 : regbits @ rs1 : regbits @ 0b000 @ imm5 : bits(5) @ 0b1100011 = Some(BTYPE(imm7[6] @ imm5[0] @ imm7[5..0] @ imm5[4..1] @ 0b0, rs2, rs1, RISCV_BEQ))
-function clause decode imm7 : bits(7) @ rs2 : regbits @ rs1 : regbits @ 0b001 @ imm5 : bits(5) @ 0b1100011 = Some(BTYPE(imm7[6] @ imm5[0] @ imm7[5..0] @ imm5[4..1] @ 0b0, rs2, rs1, RISCV_BNE))
-function clause decode imm7 : bits(7) @ rs2 : regbits @ rs1 : regbits @ 0b100 @ imm5 : bits(5) @ 0b1100011 = Some(BTYPE(imm7[6] @ imm5[0] @ imm7[5..0] @ imm5[4..1] @ 0b0, rs2, rs1, RISCV_BLT))
-function clause decode imm7 : bits(7) @ rs2 : regbits @ rs1 : regbits @ 0b101 @ imm5 : bits(5) @ 0b1100011 = Some(BTYPE(imm7[6] @ imm5[0] @ imm7[5..0] @ imm5[4..1] @ 0b0, rs2, rs1, RISCV_BGE))
-function clause decode imm7 : bits(7) @ rs2 : regbits @ rs1 : regbits @ 0b110 @ imm5 : bits(5) @ 0b1100011 = Some(BTYPE(imm7[6] @ imm5[0] @ imm7[5..0] @ imm5[4..1] @ 0b0, rs2, rs1, RISCV_BLTU))
-function clause decode imm7 : bits(7) @ rs2 : regbits @ rs1 : regbits @ 0b111 @ imm5 : bits(5) @ 0b1100011 = Some(BTYPE(imm7[6] @ imm5[0] @ imm7[5..0] @ imm5[4..1] @ 0b0, rs2, rs1, RISCV_BGEU))
+mapping encdec_bop : bop <-> bits(3) = {
+ RISCV_BEQ <-> 0b000,
+ RISCV_BNE <-> 0b001,
+ RISCV_BLT <-> 0b100,
+ RISCV_BGE <-> 0b101,
+ RISCV_BLTU <-> 0b110,
+ RISCV_BGEU <-> 0b111
+}
+
+mapping clause encdec = BTYPE(imm7_6 @ imm5_0 @ imm7_5_0 @ imm5_4_1 @ 0b0, rs2, rs1, op)
+ <-> imm7_6 : bits(1) @ imm7_5_0 : bits(6) @ rs2 @ rs1 @ encdec_bop(op) @ imm5_4_1 : bits(4) @ imm5_0 : bits(1) @ 0b1100011
function clause execute (BTYPE(imm, rs2, rs1, op)) =
let rs1_val = X(rs1) in
@@ -105,15 +144,31 @@ function clause print_insn (BTYPE(imm, rs2, rs1, op)) =
} in
insn ^ rs1 ^ ", " ^ rs2 ^ ", " ^ BitStr(imm)
+mapping btype_mnemonic : bop <-> string = {
+ RISCV_BEQ <-> "beq",
+ RISCV_BNE <-> "bne",
+ RISCV_BLT <-> "blt",
+ RISCV_BGE <-> "bge",
+ RISCV_BLTU <-> "bltu",
+ RISCV_BGEU <-> "bgeu"
+}
+
+mapping clause assembly = BTYPE(imm, rs2, rs1, op) <-> btype_mnemonic(op) ^ spc() ^ reg_name(rs1) ^ sep() ^ reg_name(rs2) ^ sep() ^ hex_bits_13(imm)
+
+
/* ****************************************************************** */
union clause ast = ITYPE : (bits(12), regbits, regbits, iop)
-function clause decode imm : bits(12) @ rs1 : regbits @ 0b000 @ rd : regbits @ 0b0010011 = Some(ITYPE(imm, rs1, rd, RISCV_ADDI))
-function clause decode imm : bits(12) @ rs1 : regbits @ 0b010 @ rd : regbits @ 0b0010011 = Some(ITYPE(imm, rs1, rd, RISCV_SLTI))
-function clause decode imm : bits(12) @ rs1 : regbits @ 0b011 @ rd : regbits @ 0b0010011 = Some(ITYPE(imm, rs1, rd, RISCV_SLTIU))
-function clause decode imm : bits(12) @ rs1 : regbits @ 0b100 @ rd : regbits @ 0b0010011 = Some(ITYPE(imm, rs1, rd, RISCV_XORI))
-function clause decode imm : bits(12) @ rs1 : regbits @ 0b110 @ rd : regbits @ 0b0010011 = Some(ITYPE(imm, rs1, rd, RISCV_ORI))
-function clause decode imm : bits(12) @ rs1 : regbits @ 0b111 @ rd : regbits @ 0b0010011 = Some(ITYPE(imm, rs1, rd, RISCV_ANDI))
+mapping encdec_iop : iop <-> bits(3) = {
+ RISCV_ADDI <-> 0b000,
+ RISCV_SLTI <-> 0b010,
+ RISCV_SLTIU <-> 0b011,
+ RISCV_XORI <-> 0b100,
+ RISCV_ORI <-> 0b110,
+ RISCV_ANDI <-> 0b111
+}
+
+mapping clause encdec = ITYPE(imm, rs1, rd, op) <-> imm @ rs1 @ encdec_iop(op) @ rd @ 0b0010011
function clause execute (ITYPE (imm, rs1, rd, op)) =
let rs1_val = X(rs1) in
@@ -142,12 +197,29 @@ function clause print_insn (ITYPE(imm, rs1, rd, op)) =
} in
insn ^ rd ^ ", " ^ rs1 ^ ", " ^ BitStr(imm)
+mapping itype_mnemonic : iop <-> string = {
+ RISCV_ADDI <-> "addi",
+ RISCV_SLTI <-> "slti",
+ RISCV_SLTIU <-> "sltiu",
+ RISCV_XORI <-> "xori",
+ RISCV_ORI <-> "ori",
+ RISCV_ANDI <-> "andi"
+}
+
+mapping clause assembly = ITYPE(imm, rs1, rd, op) <-> itype_mnemonic(op) ^ spc() ^ reg_name(rd) ^ sep() ^ reg_name(rs1) ^ sep() ^ hex_bits_12(imm)
+
/* ****************************************************************** */
union clause ast = SHIFTIOP : (bits(6), regbits, regbits, sop)
-function clause decode 0b000000 @ shamt : bits(6) @ rs1 : regbits @ 0b001 @ rd : regbits @ 0b0010011 = Some(SHIFTIOP(shamt, rs1, rd, RISCV_SLLI))
-function clause decode 0b000000 @ shamt : bits(6) @ rs1 : regbits @ 0b101 @ rd : regbits @ 0b0010011 = Some(SHIFTIOP(shamt, rs1, rd, RISCV_SRLI))
-function clause decode 0b010000 @ shamt : bits(6) @ rs1 : regbits @ 0b101 @ rd : regbits @ 0b0010011 = Some(SHIFTIOP(shamt, rs1, rd, RISCV_SRAI))
+mapping encdec_sop : sop <-> bits(3) = {
+ RISCV_SLLI <-> 0b001,
+ RISCV_SRLI <-> 0b101,
+ RISCV_SRAI <-> 0b101
+}
+
+mapping clause encdec = SHIFTIOP(shamt, rs1, rd, RISCV_SLLI) <-> 0b000000 @ shamt @ rs1 @ 0b001 @ rd @ 0b0010011
+mapping clause encdec = SHIFTIOP(shamt, rs1, rd, RISCV_SRLI) <-> 0b000000 @ shamt @ rs1 @ 0b101 @ rd @ 0b0010011
+mapping clause encdec = SHIFTIOP(shamt, rs1, rd, RISCV_SRAI) <-> 0b010000 @ shamt @ rs1 @ 0b101 @ rd @ 0b0010011
function clause execute (SHIFTIOP(shamt, rs1, rd, op)) =
let rs1_val = X(rs1) in
@@ -169,19 +241,27 @@ function clause print_insn (SHIFTIOP(shamt, rs1, rd, op)) =
} in
insn ^ rd ^ ", " ^ rs1 ^ ", " ^ BitStr(shamt)
+mapping shiftiop_mnemonic : sop <-> string = {
+ RISCV_SLLI <-> "slli",
+ RISCV_SRLI <-> "srli",
+ RISCV_SRAI <-> "srai"
+}
+
+mapping clause assembly = SHIFTIOP(shamt, rs1, rd, op) <-> shiftiop_mnemonic(op) ^ spc() ^ reg_name(rd) ^ sep() ^ reg_name(rs1) ^ hex_bits_6(shamt)
+
/* ****************************************************************** */
union clause ast = RTYPE : (regbits, regbits, regbits, rop)
-function clause decode 0b0000000 @ rs2 : regbits @ rs1 : regbits @ 0b000 @ rd : regbits @ 0b0110011 = Some(RTYPE(rs2, rs1, rd, RISCV_ADD))
-function clause decode 0b0100000 @ rs2 : regbits @ rs1 : regbits @ 0b000 @ rd : regbits @ 0b0110011 = Some(RTYPE(rs2, rs1, rd, RISCV_SUB))
-function clause decode 0b0000000 @ rs2 : regbits @ rs1 : regbits @ 0b001 @ rd : regbits @ 0b0110011 = Some(RTYPE(rs2, rs1, rd, RISCV_SLL))
-function clause decode 0b0000000 @ rs2 : regbits @ rs1 : regbits @ 0b010 @ rd : regbits @ 0b0110011 = Some(RTYPE(rs2, rs1, rd, RISCV_SLT))
-function clause decode 0b0000000 @ rs2 : regbits @ rs1 : regbits @ 0b011 @ rd : regbits @ 0b0110011 = Some(RTYPE(rs2, rs1, rd, RISCV_SLTU))
-function clause decode 0b0000000 @ rs2 : regbits @ rs1 : regbits @ 0b100 @ rd : regbits @ 0b0110011 = Some(RTYPE(rs2, rs1, rd, RISCV_XOR))
-function clause decode 0b0000000 @ rs2 : regbits @ rs1 : regbits @ 0b101 @ rd : regbits @ 0b0110011 = Some(RTYPE(rs2, rs1, rd, RISCV_SRL))
-function clause decode 0b0100000 @ rs2 : regbits @ rs1 : regbits @ 0b101 @ rd : regbits @ 0b0110011 = Some(RTYPE(rs2, rs1, rd, RISCV_SRA))
-function clause decode 0b0000000 @ rs2 : regbits @ rs1 : regbits @ 0b110 @ rd : regbits @ 0b0110011 = Some(RTYPE(rs2, rs1, rd, RISCV_OR))
-function clause decode 0b0000000 @ rs2 : regbits @ rs1 : regbits @ 0b111 @ rd : regbits @ 0b0110011 = Some(RTYPE(rs2, rs1, rd, RISCV_AND))
+mapping clause encdec = RTYPE(rs2, rs1, rd, RISCV_ADD) <-> 0b0000000 @ rs2 @ rs1 @ 0b000 @ rd @ 0b0110011
+mapping clause encdec = RTYPE(rs2, rs1, rd, RISCV_SUB) <-> 0b0100000 @ rs2 @ rs1 @ 0b000 @ rd @ 0b0110011
+mapping clause encdec = RTYPE(rs2, rs1, rd, RISCV_SLL) <-> 0b0000000 @ rs2 @ rs1 @ 0b001 @ rd @ 0b0110011
+mapping clause encdec = RTYPE(rs2, rs1, rd, RISCV_SLT) <-> 0b0000000 @ rs2 @ rs1 @ 0b010 @ rd @ 0b0110011
+mapping clause encdec = RTYPE(rs2, rs1, rd, RISCV_SLTU) <-> 0b0000000 @ rs2 @ rs1 @ 0b011 @ rd @ 0b0110011
+mapping clause encdec = RTYPE(rs2, rs1, rd, RISCV_XOR) <-> 0b0000000 @ rs2 @ rs1 @ 0b100 @ rd @ 0b0110011
+mapping clause encdec = RTYPE(rs2, rs1, rd, RISCV_SRL) <-> 0b0000000 @ rs2 @ rs1 @ 0b101 @ rd @ 0b0110011
+mapping clause encdec = RTYPE(rs2, rs1, rd, RISCV_SRA) <-> 0b0100000 @ rs2 @ rs1 @ 0b101 @ rd @ 0b0110011
+mapping clause encdec = RTYPE(rs2, rs1, rd, RISCV_OR) <-> 0b0000000 @ rs2 @ rs1 @ 0b110 @ rd @ 0b0110011
+mapping clause encdec = RTYPE(rs2, rs1, rd, RISCV_AND) <-> 0b0000000 @ rs2 @ rs1 @ 0b111 @ rd @ 0b0110011
function clause execute (RTYPE(rs2, rs1, rd, op)) =
let rs1_val = X(rs1) in
@@ -218,16 +298,27 @@ function clause print_insn (RTYPE(rs2, rs1, rd, op)) =
} in
insn ^ rd ^ ", " ^ rs1 ^ ", " ^ rs2
+mapping rtype_mnemonic : rop <-> string = {
+ RISCV_ADD <-> "add",
+ RISCV_SUB <-> "sub",
+ RISCV_SLL <-> "sll",
+ RISCV_SLT <-> "slt",
+ RISCV_SLTU <-> "sltu",
+ RISCV_XOR <-> "xor",
+ RISCV_SRL <-> "srl",
+ RISCV_SRA <-> "sra",
+ RISCV_OR <-> "or",
+ RISCV_AND <-> "and"
+}
+
+mapping clause assembly = RTYPE(rs2, rs1, rd, op) <-> rtype_mnemonic(op) ^ spc() ^ reg_name(rd) ^ sep() ^ reg_name(rs1) ^ sep() ^ reg_name(rs2)
+
/* ****************************************************************** */
union clause ast = LOAD : (bits(12), regbits, regbits, bool, word_width, bool, bool)
-function clause decode imm : bits(12) @ rs1 : regbits @ 0b000 @ rd : regbits @ 0b0000011 = Some(LOAD(imm, rs1, rd, false, BYTE, false, false))
-function clause decode imm : bits(12) @ rs1 : regbits @ 0b001 @ rd : regbits @ 0b0000011 = Some(LOAD(imm, rs1, rd, false, HALF, false, false))
-function clause decode imm : bits(12) @ rs1 : regbits @ 0b010 @ rd : regbits @ 0b0000011 = Some(LOAD(imm, rs1, rd, false, WORD, false, false))
-function clause decode imm : bits(12) @ rs1 : regbits @ 0b011 @ rd : regbits @ 0b0000011 = Some(LOAD(imm, rs1, rd, false, DOUBLE, false, false))
-function clause decode imm : bits(12) @ rs1 : regbits @ 0b100 @ rd : regbits @ 0b0000011 = Some(LOAD(imm, rs1, rd, true, BYTE, false, false))
-function clause decode imm : bits(12) @ rs1 : regbits @ 0b101 @ rd : regbits @ 0b0000011 = Some(LOAD(imm, rs1, rd, true, HALF, false, false))
-function clause decode imm : bits(12) @ rs1 : regbits @ 0b110 @ rd : regbits @ 0b0000011 = Some(LOAD(imm, rs1, rd, true, WORD, false, false))
+/* I am assuming that load unsigned double wasn't meant to be missing here? */
+/* TODO: aq/rl */
+mapping clause encdec = LOAD(imm, rs1, rd, is_unsigned, size, false, false) <-> imm @ rs1 @ bool_bits(is_unsigned) @ size_bits(size) @ rd @ 0b0000011
val extend_value : forall 'n, 0 < 'n <= 8. (bool, MemoryOpResult(bits(8 * 'n))) -> MemoryOpResult(xlenbits)
function extend_value(is_unsigned, value) = match (value) {
@@ -270,13 +361,33 @@ function clause print_insn (LOAD(imm, rs1, rd, is_unsigned, width, aq, rl)) =
} in
insn ^ rd ^ ", " ^ rs1 ^ ", " ^ BitStr(imm)
+/* TODO FIXME: is this the actual aq/rl syntax? */
+val maybe_aq : bool <-> string
+mapping maybe_aq = {
+ true <-> ".aq",
+ false <-> ""
+}
+
+val maybe_rl : bool <-> string
+mapping maybe_rl = {
+ true <-> ".rl",
+ false <-> ""
+}
+
+val maybe_u : bool <-> string
+mapping maybe_u = {
+ true <-> "u",
+ false <-> ""
+}
+
+
+mapping clause assembly = LOAD(imm, rs1, rd, is_unsigned, size, aq, rl) <-> "l" ^ size_mnemonic(size) ^ maybe_u(is_unsigned) ^ maybe_aq(aq) ^ maybe_rl(rl) ^ spc() ^ reg_name(rd) ^ sep() ^ reg_name(rs1) ^ sep() ^ hex_bits_12(imm)
+
/* ****************************************************************** */
union clause ast = STORE : (bits(12), regbits, regbits, word_width, bool, bool)
-function clause decode imm7 : bits(7) @ rs2 : regbits @ rs1 : regbits @ 0b000 @ imm5 : bits(5) @ 0b0100011 = Some(STORE(imm7 @ imm5, rs2, rs1, BYTE, false, false))
-function clause decode imm7 : bits(7) @ rs2 : regbits @ rs1 : regbits @ 0b001 @ imm5 : bits(5) @ 0b0100011 = Some(STORE(imm7 @ imm5, rs2, rs1, HALF, false, false))
-function clause decode imm7 : bits(7) @ rs2 : regbits @ rs1 : regbits @ 0b010 @ imm5 : bits(5) @ 0b0100011 = Some(STORE(imm7 @ imm5, rs2, rs1, WORD, false, false))
-function clause decode imm7 : bits(7) @ rs2 : regbits @ rs1 : regbits @ 0b011 @ imm5 : bits(5) @ 0b0100011 = Some(STORE(imm7 @ imm5, rs2, rs1, DOUBLE, false, false))
+/* TODO: aq/rl */
+mapping clause encdec = STORE(imm7 @ imm5, rs2, rs1, size, false, false) <-> imm7 : bits(7) @ rs2 @ rs1 @ 0b0 @ size_bits(size) @ imm5 : bits(5) @ 0b0100011
/* NOTE: Currently, we only EA if address translation is successful.
This may need revisiting. */
@@ -320,10 +431,13 @@ function clause print_insn (STORE(imm, rs2, rs1, width, aq, rl)) =
} in
insn ^ rs2 ^ ", " ^ rs1 ^ ", " ^ BitStr(imm)
+mapping clause assembly = STORE(imm, rs1, rd, size, aq, rl) <-> "s" ^ size_mnemonic(size) ^ maybe_aq(aq) ^ maybe_rl(rl) ^ spc() ^ reg_name(rd) ^ sep() ^ reg_name(rs1) ^ sep() ^ hex_bits_12(imm)
+
+
/* ****************************************************************** */
union clause ast = ADDIW : (bits(12), regbits, regbits)
-function clause decode imm : bits(12) @ rs1 : regbits @ 0b000 @ rd : regbits @ 0b0011011 = Some(ADDIW(imm, rs1, rd))
+mapping clause encdec = ADDIW(imm, rs1, rd) <-> imm @ rs1 @ 0b000 @ rd @ 0b0011011
function clause execute (ADDIW(imm, rs1, rd)) = {
let result : xlenbits = EXTS(imm) + X(rs1);
@@ -334,12 +448,14 @@ function clause execute (ADDIW(imm, rs1, rd)) = {
function clause print_insn (ADDIW(imm, rs1, rd)) =
"addiw " ^ rd ^ ", " ^ rs1 ^ ", " ^ BitStr(imm)
+mapping clause assembly = ADDIW(imm, rs1, rd) <-> "addiw" ^ spc() ^ reg_name(rd) ^ sep() ^ reg_name(rs1) ^ sep() ^ hex_bits_12(imm)
+
/* ****************************************************************** */
union clause ast = SHIFTW : (bits(5), regbits, regbits, sop)
-function clause decode 0b0000000 @ shamt : bits(5) @ rs1 : regbits @ 0b001 @ rd : regbits @ 0b0011011 = Some(SHIFTW(shamt, rs1, rd, RISCV_SLLI))
-function clause decode 0b0000000 @ shamt : bits(5) @ rs1 : regbits @ 0b101 @ rd : regbits @ 0b0011011 = Some(SHIFTW(shamt, rs1, rd, RISCV_SRLI))
-function clause decode 0b0100000 @ shamt : bits(5) @ rs1 : regbits @ 0b101 @ rd : regbits @ 0b0011011 = Some(SHIFTW(shamt, rs1, rd, RISCV_SRAI))
+mapping clause encdec = SHIFTW(shamt, rs1, rd, RISCV_SLLI) <-> 0b0000000 @ shamt @ rs1 @ 0b001 @ rd @ 0b0011011
+mapping clause encdec = SHIFTW(shamt, rs1, rd, RISCV_SRLI) <-> 0b0000000 @ shamt @ rs1 @ 0b101 @ rd @ 0b0011011
+mapping clause encdec = SHIFTW(shamt, rs1, rd, RISCV_SRAI) <-> 0b0100000 @ shamt @ rs1 @ 0b101 @ rd @ 0b0011011
function clause execute (SHIFTW(shamt, rs1, rd, op)) =
let rs1_val = (X(rs1))[31..0] in
@@ -361,14 +477,22 @@ function clause print_insn (SHIFTW(shamt, rs1, rd, op)) =
} in
insn ^ rd ^ ", " ^ rs1 ^ ", " ^ BitStr(shamt)
+mapping shiftw_mnemonic : sop <-> string = {
+ RISCV_SLLI <-> "slli",
+ RISCV_SRLI <-> "srli",
+ RISCV_SRAI <-> "srai"
+}
+
+mapping clause assembly = SHIFTW(shamt, rs1, rd, op) <-> shiftw_mnemonic(op) ^ spc() ^ reg_name(rd) ^ sep() ^ reg_name(rs1) ^ sep() ^ hex_bits_5(shamt)
+
/* ****************************************************************** */
union clause ast = RTYPEW : (regbits, regbits, regbits, ropw)
-function clause decode 0b0000000 @ rs2 : regbits @ rs1 : regbits @ 0b000 @ rd : regbits @ 0b0111011 = Some(RTYPEW(rs2, rs1, rd, RISCV_ADDW))
-function clause decode 0b0100000 @ rs2 : regbits @ rs1 : regbits @ 0b000 @ rd : regbits @ 0b0111011 = Some(RTYPEW(rs2, rs1, rd, RISCV_SUBW))
-function clause decode 0b0000000 @ rs2 : regbits @ rs1 : regbits @ 0b001 @ rd : regbits @ 0b0111011 = Some(RTYPEW(rs2, rs1, rd, RISCV_SLLW))
-function clause decode 0b0000000 @ rs2 : regbits @ rs1 : regbits @ 0b101 @ rd : regbits @ 0b0111011 = Some(RTYPEW(rs2, rs1, rd, RISCV_SRLW))
-function clause decode 0b0100000 @ rs2 : regbits @ rs1 : regbits @ 0b101 @ rd : regbits @ 0b0111011 = Some(RTYPEW(rs2, rs1, rd, RISCV_SRAW))
+mapping clause encdec = RTYPEW(rs2, rs1, rd, RISCV_ADDW) <-> 0b0000000 @ rs2 @ rs1 @ 0b000 @ rd @ 0b0111011
+mapping clause encdec = RTYPEW(rs2, rs1, rd, RISCV_SUBW) <-> 0b0100000 @ rs2 @ rs1 @ 0b000 @ rd @ 0b0111011
+mapping clause encdec = RTYPEW(rs2, rs1, rd, RISCV_SLLW) <-> 0b0000000 @ rs2 @ rs1 @ 0b001 @ rd @ 0b0111011
+mapping clause encdec = RTYPEW(rs2, rs1, rd, RISCV_SRLW) <-> 0b0000000 @ rs2 @ rs1 @ 0b101 @ rd @ 0b0111011
+mapping clause encdec = RTYPEW(rs2, rs1, rd, RISCV_SRAW) <-> 0b0100000 @ rs2 @ rs1 @ 0b101 @ rd @ 0b0111011
function clause execute (RTYPEW(rs2, rs1, rd, op)) =
let rs1_val = (X(rs1))[31..0] in
@@ -395,14 +519,30 @@ function clause print_insn (RTYPEW(rs2, rs1, rd, op)) =
} in
insn ^ rd ^ ", " ^ rs1 ^ ", " ^ rs2
+mapping rtypew_mnemonic : ropw <-> string = {
+ RISCV_ADDW <-> "addw",
+ RISCV_SUBW <-> "subw",
+ RISCV_SLLW <-> "sllw",
+ RISCV_SRLW <-> "srlw",
+ RISCV_SRAW <-> "sraw"
+}
+
+mapping clause assembly = RTYPEW(rs2, rs1, rd, op) <-> rtypew_mnemonic(op) ^ spc() ^ reg_name(rd) ^ sep() ^ reg_name(rs1) ^ sep() ^ reg_name(rs2)
+
/* ****************************************************************** */
/* FIXME: separate these out into separate ast variants */
union clause ast = MUL : (regbits, regbits, regbits, bool, bool, bool)
-function clause decode 0b0000001 @ rs2 : regbits @ rs1 : regbits @ 0b000 @ rd : regbits @ 0b0110011 = Some(MUL(rs2, rs1, rd, false, true, true)) /* MUL */
-function clause decode 0b0000001 @ rs2 : regbits @ rs1 : regbits @ 0b001 @ rd : regbits @ 0b0110011 = Some(MUL(rs2, rs1, rd, true, true, true)) /* MULH */
-function clause decode 0b0000001 @ rs2 : regbits @ rs1 : regbits @ 0b010 @ rd : regbits @ 0b0110011 = Some(MUL(rs2, rs1, rd, true, true, false)) /* MULHSU */
-function clause decode 0b0000001 @ rs2 : regbits @ rs1 : regbits @ 0b011 @ rd : regbits @ 0b0110011 = Some(MUL(rs2, rs1, rd, true, false, false)) /* MULHU */
+mapping encdec_mul_op : (bool, bool, bool) <-> bits(3) = {
+ (false, true, true) <-> 0b000,
+ (true, true, true) <-> 0b001,
+ (true, true, false) <-> 0b010,
+ (true, false, false) <-> 0b011
+}
+
+/* for some reason the : bits(3) here is still necessary - BUG */
+mapping clause encdec = MUL(rs2, rs1, rd, high, signed1, signed2) <-> 0b0000001 @ rs2 @ rs1 @ encdec_mul_op(high, signed1, signed2) : bits(3) @ rd @ 0b0110011
+
function clause execute (MUL(rs2, rs1, rd, high, signed1, signed2)) =
let rs1_val = X(rs1) in
let rs2_val = X(rs2) in
@@ -424,10 +564,20 @@ function clause print_insn (MUL(rs2, rs1, rd, high, signed1, signed2)) =
} in
insn ^ rd ^ ", " ^ rs1 ^ ", " ^ rs2
+mapping mul_mnemonic : (bool, bool, bool) <-> string = {
+ (false, true, true) <-> "mul",
+ (true, true, true) <-> "mulh",
+ (true, true, false) <-> "mulhsu",
+ (true, false, false) <-> "mulhu"
+}
+
+mapping clause assembly = MUL(rs2, rs1, rd, high, signed1, signed2) <-> mul_mnemonic(high, signed1, signed2) ^ spc() ^ reg_name(rd) ^ sep() ^ reg_name(rs1) ^ sep() ^ reg_name(rs2)
+
/* ****************************************************************** */
union clause ast = DIV : (regbits, regbits, regbits, bool)
-function clause decode 0b0000001 @ rs2 : regbits @ rs1 : regbits @ 0b100 @ rd : regbits @ 0b0110011 = Some(DIV(rs2, rs1, rd, true)) /* DIV */
-function clause decode 0b0000001 @ rs2 : regbits @ rs1 : regbits @ 0b101 @ rd : regbits @ 0b0110011 = Some(DIV(rs2, rs1, rd, false)) /* DIVU */
+
+mapping clause encdec = DIV(rs2, rs1, rd, s) <-> 0b0000001 @ rs2 @ rs1 @ 0b10 @ bool_not_bits(s) @ rd @ 0b0110011
+
function clause execute (DIV(rs2, rs1, rd, s)) =
let rs1_val = X(rs1) in
let rs2_val = X(rs2) in
@@ -443,10 +593,18 @@ function clause print_insn (DIV(rs2, rs1, rd, s)) =
let insn : string = if s then "div " else "divu " in
insn ^ rd ^ ", " ^ rs1 ^ ", " ^ rs2
+mapping maybe_not_u : bool <-> string = {
+ false <-> "u",
+ true <-> ""
+}
+
+mapping clause assembly = DIV(rs2, rs1, rd, s) <-> "div" ^ maybe_not_u(s) ^ spc() ^ reg_name(rd) ^ sep() ^ reg_name(rs1) ^ sep() ^ reg_name(rs2)
+
/* ****************************************************************** */
union clause ast = REM : (regbits, regbits, regbits, bool)
-function clause decode 0b0000001 @ rs2 : regbits @ rs1 : regbits @ 0b110 @ rd : regbits @ 0b0110011 = Some(REM(rs2, rs1, rd, true)) /* REM */
-function clause decode 0b0000001 @ rs2 : regbits @ rs1 : regbits @ 0b111 @ rd : regbits @ 0b0110011 = Some(REM(rs2, rs1, rd, false)) /* REMU */
+
+mapping clause encdec = REM(rs2, rs1, rd, s) <-> 0b0000001 @ rs2 @ rs1 @ 0b11 @ bool_not_bits(s) @ rd @ 0b0110011
+
function clause execute (REM(rs2, rs1, rd, s)) =
let rs1_val = X(rs1) in
let rs2_val = X(rs2) in
@@ -462,9 +620,13 @@ function clause print_insn (REM(rs2, rs1, rd, s)) =
let insn : string = if s then "rem " else "remu " in
insn ^ rd ^ ", " ^ rs1 ^ ", " ^ rs2
+mapping clause assembly = REM(rs2, rs1, rd, s) <-> "rem" ^ maybe_not_u(s) ^ spc() ^ reg_name(rd) ^ sep() ^ reg_name(rs1) ^ sep() ^ reg_name(rs2)
+
/* ****************************************************************** */
union clause ast = MULW : (regbits, regbits, regbits)
-function clause decode 0b0000001 @ rs2 : regbits @ rs1 : regbits @ 0b000 @ rd : regbits @ 0b0111011 = Some(MULW(rs2, rs1, rd)) /* MULW */
+
+mapping clause encdec = MULW(rs2, rs1, rd) <-> 0b0000001 @ rs2 @ rs1 @ 0b000 @ rd @ 0b0111011
+
function clause execute (MULW(rs2, rs1, rd)) =
let rs1_val = X(rs1)[31..0] in
let rs2_val = X(rs2)[31..0] in
@@ -479,10 +641,13 @@ function clause execute (MULW(rs2, rs1, rd)) =
function clause print_insn (MULW(rs2, rs1, rd)) =
"mulw " ^ rd ^ ", " ^ rs1 ^ ", " ^ rs2
+mapping clause assembly = MULW(rs2, rs1, rd) <-> "mulw" ^ spc() ^ reg_name(rd) ^ sep() ^ reg_name(rs1) ^ sep() ^ reg_name(rs2)
+
/* ****************************************************************** */
union clause ast = DIVW : (regbits, regbits, regbits, bool)
-function clause decode 0b0000001 @ rs2 : regbits @ rs1 : regbits @ 0b100 @ rd : regbits @ 0b0111011 = Some(DIVW(rs2, rs1, rd, true)) /* DIVW */
-function clause decode 0b0000001 @ rs2 : regbits @ rs1 : regbits @ 0b101 @ rd : regbits @ 0b0111011 = Some(DIVW(rs2, rs1, rd, false)) /* DIVUW */
+
+mapping clause encdec = DIVW(rs2, rs1, rd, s) <-> 0b0000001 @ rs2 @ rs1 @ 0b10 @ bool_not_bits(s) @ rd @ 0b0111011
+
function clause execute (DIVW(rs2, rs1, rd, s)) =
let rs1_val = X(rs1)[31..0] in
let rs2_val = X(rs2)[31..0] in
@@ -498,10 +663,13 @@ function clause print_insn (DIVW(rs2, rs1, rd, s)) =
let insn : string = if s then "divw " else "divuw " in
insn ^ rd ^ ", " ^ rs1 ^ ", " ^ rs2
+mapping clause assembly = DIVW(rs2, rs1, rd, s) <-> "div" ^ maybe_not_u(s) ^ "w" ^ spc() ^ reg_name(rd) ^ sep() ^ reg_name(rs1) ^ sep() ^ reg_name(rs2)
+
/* ****************************************************************** */
union clause ast = REMW : (regbits, regbits, regbits, bool)
-function clause decode 0b0000001 @ rs2 : regbits @ rs1 : regbits @ 0b110 @ rd : regbits @ 0b0111011 = Some(REMW(rs2, rs1, rd, true)) /* REMW */
-function clause decode 0b0000001 @ rs2 : regbits @ rs1 : regbits @ 0b111 @ rd : regbits @ 0b0111011 = Some(REMW(rs2, rs1, rd, false)) /* REMUW */
+
+mapping clause encdec = REMW(rs2, rs1, rd, s) <-> 0b0000001 @ rs2 @ rs1 @ 0b11 @ bool_not_bits(s) @ rd @ 0b0111011
+
function clause execute (REMW(rs2, rs1, rd, s)) =
let rs1_val = X(rs1)[31..0] in
let rs2_val = X(rs2)[31..0] in
@@ -517,10 +685,12 @@ function clause print_insn (REMW(rs2, rs1, rd, s)) =
let insn : string = if s then "remw " else "remuw " in
insn ^ rd ^ ", " ^ rs1 ^ ", " ^ rs2
+mapping clause assembly = REMW(rs2, rs1, rd, s) <-> "rem" ^ maybe_not_u(s) ^ "w" ^ spc() ^ reg_name(rd) ^ sep() ^ reg_name(rs1) ^ sep() ^ reg_name(rs2)
+
/* ****************************************************************** */
union clause ast = FENCE : (bits(4), bits(4))
-function clause decode 0b0000 @ pred : bits(4) @ succ : bits(4) @ 0b00000 @ 0b000 @ 0b00000 @ 0b0001111 = Some(FENCE(pred, succ))
+mapping clause encdec = FENCE(pred, succ) <-> 0b0000 @ pred @ succ @ 0b00000 @ 0b000 @ 0b00000 @ 0b0001111
function clause execute (FENCE(pred, succ)) = {
match (pred, succ) {
@@ -539,20 +709,48 @@ function clause execute (FENCE(pred, succ)) = {
function clause print_insn (FENCE(pred, succ)) =
"fence"
+mapping bit_maybe_r : bits(1) <-> string = {
+ 0b1 <-> "r",
+ 0b0 <-> ""
+}
+
+mapping bit_maybe_w : bits(1) <-> string = {
+ 0b1 <-> "w",
+ 0b0 <-> ""
+}
+
+mapping bit_maybe_i : bits(1) <-> string = {
+ 0b1 <-> "i",
+ 0b0 <-> ""
+}
+
+mapping bit_maybe_o : bits(1) <-> string = {
+ 0b1 <-> "o",
+ 0b0 <-> ""
+}
+
+mapping fence_bits : bits(4) <-> string = {
+ r : bits(1) @ w : bits(1) @ i : bits(1) @ o : bits(1) <-> bit_maybe_r(r) ^ bit_maybe_w(w) ^ bit_maybe_i(i) ^ bit_maybe_o(o)
+}
+
+mapping clause assembly = FENCE(pred, succ) <-> "fence" ^ spc() ^ fence_bits(pred) ^ sep() ^ fence_bits(succ)
+
/* ****************************************************************** */
union clause ast = FENCEI : unit
-function clause decode 0b000000000000 @ 0b00000 @ 0b001 @ 0b00000 @ 0b0001111 = Some(FENCEI())
+mapping clause encdec = FENCEI() <-> 0b000000000000 @ 0b00000 @ 0b001 @ 0b00000 @ 0b0001111
function clause execute FENCEI() = { MEM_fence_i(); true }
function clause print_insn (FENCEI()) =
"fence.i"
+mapping clause assembly = FENCEI() <-> "fence.i"
+
/* ****************************************************************** */
union clause ast = ECALL : unit
-function clause decode 0b000000000000 @ 0b00000 @ 0b000 @ 0b00000 @ 0b1110011 = Some(ECALL())
+mapping clause encdec = ECALL() <-> 0b000000000000 @ 0b00000 @ 0b000 @ 0b00000 @ 0b1110011
function clause execute ECALL() =
let t : sync_exception =
@@ -569,10 +767,12 @@ function clause execute ECALL() =
function clause print_insn (ECALL()) =
"ecall"
+mapping clause assembly = ECALL() <-> "ecall"
+
/* ****************************************************************** */
union clause ast = MRET : unit
-function clause decode 0b0011000 @ 0b00010 @ 0b00000 @ 0b000 @ 0b00000 @ 0b1110011 = Some(MRET())
+mapping clause encdec = MRET() <-> 0b0011000 @ 0b00010 @ 0b00000 @ 0b000 @ 0b00000 @ 0b1110011
function clause execute MRET() = {
if cur_privilege == Machine then
@@ -585,10 +785,12 @@ function clause execute MRET() = {
function clause print_insn (MRET()) =
"mret"
+mapping clause assembly = MRET() <-> "mret"
+
/* ****************************************************************** */
union clause ast = SRET : unit
-function clause decode 0b0001000 @ 0b00010 @ 0b00000 @ 0b000 @ 0b00000 @ 0b1110011 = Some(SRET())
+mapping clause encdec = SRET() <-> 0b0001000 @ 0b00010 @ 0b00000 @ 0b000 @ 0b00000 @ 0b1110011
function clause execute SRET() = {
match cur_privilege {
@@ -604,10 +806,12 @@ function clause execute SRET() = {
function clause print_insn (SRET()) =
"sret"
+mapping clause assembly = SRET() <-> "sret"
+
/* ****************************************************************** */
union clause ast = EBREAK : unit
-function clause decode 0b000000000001 @ 0b00000 @ 0b000 @ 0b00000 @ 0b1110011 = Some(EBREAK())
+mapping clause encdec = EBREAK() <-> 0b000000000001 @ 0b00000 @ 0b000 @ 0b00000 @ 0b1110011
function clause execute EBREAK() = {
handle_mem_exception(PC, E_Breakpoint);
@@ -617,10 +821,12 @@ function clause execute EBREAK() = {
function clause print_insn (EBREAK()) =
"ebreak"
+mapping clause assembly = EBREAK() <-> "ebreak"
+
/* ****************************************************************** */
union clause ast = WFI : unit
-function clause decode 0b000100000101 @ 0b00000 @ 0b000 @ 0b00000 @ 0b1110011 = Some(WFI())
+mapping clause encdec = WFI() <-> 0b000100000101 @ 0b00000 @ 0b000 @ 0b00000 @ 0b1110011
function clause execute WFI() = {
match cur_privilege {
@@ -637,10 +843,12 @@ function clause execute WFI() = {
function clause print_insn (WFI()) =
"wfi"
+mapping clause assembly = WFI() <-> "wfi"
+
/* ****************************************************************** */
union clause ast = SFENCE_VMA : (regbits, regbits)
-function clause decode 0b0001001 @ rs2 : regbits @ rs1 : regbits @ 0b000 @ 0b00000 @ 0b1110011 = Some(SFENCE_VMA(rs1, rs2))
+mapping clause encdec = SFENCE_VMA(rs1, rs2) <-> 0b0001001 @ rs2 @ rs1 @ 0b000 @ 0b00000 @ 0b1110011
function clause execute SFENCE_VMA(rs1, rs2) = {
/* FIXME: spec leaves unspecified what happens if this is executed in M-mode.
@@ -662,11 +870,12 @@ function clause execute SFENCE_VMA(rs1, rs2) = {
function clause print_insn (SFENCE_VMA(rs1, rs2)) =
"sfence.vma " ^ rs1 ^ ", " ^ rs2
+mapping clause assembly = SFENCE_VMA(rs1, rs2) <-> "sfence.vma" ^ spc() ^ reg_name(rs1) ^ sep() ^ reg_name(rs2)
+
/* ****************************************************************** */
union clause ast = LOADRES : (bool, bool, regbits, word_width, regbits)
-function clause decode 0b00010 @ [aq] @ [rl] @ 0b00000 @ rs1 : regbits @ 0b010 @ rd : regbits @ 0b0101111 = Some(LOADRES(aq, rl, rs1, WORD, rd))
-function clause decode 0b00010 @ [aq] @ [rl] @ 0b00000 @ rs1 : regbits @ 0b011 @ rd : regbits @ 0b0101111 = Some(LOADRES(aq, rl, rs1, DOUBLE, rd))
+mapping clause encdec = LOADRES(aq, rl, rs1, size, rd) <-> 0b00010 @ bool_bits(aq) @ bool_bits(rl) @ 0b00000 @ rs1 @ 0b0 @ size_bits(size) @ rd @ 0b0101111
val process_loadres : forall 'n, 0 < 'n <= 8. (regbits, xlenbits, MemoryOpResult(bits(8 * 'n)), bool) -> unit
@@ -692,11 +901,12 @@ function clause print_insn (LOADRES(aq, rl, rs1, width, rd)) =
} in
insn ^ rd ^ ", " ^ rs1
+mapping clause assembly = LOADRES(aq, rl, rs1, size, rd) <-> "lr." ^ maybe_aq(aq) ^ maybe_rl(rl) ^ size_mnemonic(size) ^ spc() ^ reg_name(rd) ^ sep() ^ reg_name(rs1)
+
/* ****************************************************************** */
union clause ast = STORECON : (bool, bool, regbits, regbits, word_width, regbits)
-function clause decode 0b00011 @ [aq] @ [rl] @ rs2 : regbits @ rs1 : regbits @ 0b010 @ rd : regbits @ 0b0101111 = Some(STORECON(aq, rl, rs2, rs1, WORD, rd))
-function clause decode 0b00011 @ [aq] @ [rl] @ rs2 : regbits @ rs1 : regbits @ 0b011 @ rd : regbits @ 0b0101111 = Some(STORECON(aq, rl, rs2, rs1, DOUBLE, rd))
+mapping clause encdec = STORECON(aq, rl, rs2, rs1, size, rd) <-> 0b00011 @ bool_bits(aq) @ bool_bits(rl) @ rs2 @ rs1 @ 0b0 @ size_bits(size) @ rd @ 0b0101111
/* NOTE: Currently, we only EA if address translation is successful.
This may need revisiting. */
@@ -744,27 +954,24 @@ function clause print_insn (STORECON(aq, rl, rs2, rs1, width, rd)) =
} in
insn ^ rd ^ ", " ^ rs1 ^ ", " ^ rs2
+mapping clause assembly = STORECON(aq, rl, rs2, rs1, size, rd) <-> "sc." ^ maybe_aq(aq) ^ maybe_rl(rl) ^ size_mnemonic(size) ^ spc() ^ reg_name(rd) ^ sep() ^ reg_name(rs1) ^ sep() ^ reg_name(rs2)
+
/* ****************************************************************** */
union clause ast = AMO : (amoop, bool, bool, regbits, regbits, word_width, regbits)
-function clause decode 0b00001 @ [aq] @ [rl] @ rs2 : regbits @ rs1 : regbits @ 0b010 @ rd : regbits @ 0b0101111 = Some(AMO(AMOSWAP, aq, rl, rs2, rs1, WORD, rd))
-function clause decode 0b00001 @ [aq] @ [rl] @ rs2 : regbits @ rs1 : regbits @ 0b011 @ rd : regbits @ 0b0101111 = Some(AMO(AMOSWAP, aq, rl, rs2, rs1, DOUBLE, rd))
-function clause decode 0b00000 @ [aq] @ [rl] @ rs2 : regbits @ rs1 : regbits @ 0b010 @ rd : regbits @ 0b0101111 = Some(AMO(AMOADD , aq, rl, rs2, rs1, WORD, rd))
-function clause decode 0b00000 @ [aq] @ [rl] @ rs2 : regbits @ rs1 : regbits @ 0b011 @ rd : regbits @ 0b0101111 = Some(AMO(AMOADD , aq, rl, rs2, rs1, DOUBLE, rd))
-function clause decode 0b00100 @ [aq] @ [rl] @ rs2 : regbits @ rs1 : regbits @ 0b010 @ rd : regbits @ 0b0101111 = Some(AMO(AMOXOR , aq, rl, rs2, rs1, WORD, rd))
-function clause decode 0b00100 @ [aq] @ [rl] @ rs2 : regbits @ rs1 : regbits @ 0b011 @ rd : regbits @ 0b0101111 = Some(AMO(AMOXOR , aq, rl, rs2, rs1, DOUBLE, rd))
-function clause decode 0b01100 @ [aq] @ [rl] @ rs2 : regbits @ rs1 : regbits @ 0b010 @ rd : regbits @ 0b0101111 = Some(AMO(AMOAND , aq, rl, rs2, rs1, WORD, rd))
-function clause decode 0b01100 @ [aq] @ [rl] @ rs2 : regbits @ rs1 : regbits @ 0b011 @ rd : regbits @ 0b0101111 = Some(AMO(AMOAND , aq, rl, rs2, rs1, DOUBLE, rd))
-function clause decode 0b01000 @ [aq] @ [rl] @ rs2 : regbits @ rs1 : regbits @ 0b010 @ rd : regbits @ 0b0101111 = Some(AMO(AMOOR , aq, rl, rs2, rs1, WORD, rd))
-function clause decode 0b01000 @ [aq] @ [rl] @ rs2 : regbits @ rs1 : regbits @ 0b011 @ rd : regbits @ 0b0101111 = Some(AMO(AMOOR , aq, rl, rs2, rs1, DOUBLE, rd))
-function clause decode 0b10000 @ [aq] @ [rl] @ rs2 : regbits @ rs1 : regbits @ 0b010 @ rd : regbits @ 0b0101111 = Some(AMO(AMOMIN , aq, rl, rs2, rs1, WORD, rd))
-function clause decode 0b10000 @ [aq] @ [rl] @ rs2 : regbits @ rs1 : regbits @ 0b011 @ rd : regbits @ 0b0101111 = Some(AMO(AMOMIN , aq, rl, rs2, rs1, DOUBLE, rd))
-function clause decode 0b10100 @ [aq] @ [rl] @ rs2 : regbits @ rs1 : regbits @ 0b010 @ rd : regbits @ 0b0101111 = Some(AMO(AMOMAX , aq, rl, rs2, rs1, WORD, rd))
-function clause decode 0b10100 @ [aq] @ [rl] @ rs2 : regbits @ rs1 : regbits @ 0b011 @ rd : regbits @ 0b0101111 = Some(AMO(AMOMAX , aq, rl, rs2, rs1, DOUBLE, rd))
-function clause decode 0b11000 @ [aq] @ [rl] @ rs2 : regbits @ rs1 : regbits @ 0b010 @ rd : regbits @ 0b0101111 = Some(AMO(AMOMINU, aq, rl, rs2, rs1, WORD, rd))
-function clause decode 0b11000 @ [aq] @ [rl] @ rs2 : regbits @ rs1 : regbits @ 0b011 @ rd : regbits @ 0b0101111 = Some(AMO(AMOMINU, aq, rl, rs2, rs1, DOUBLE, rd))
-function clause decode 0b11100 @ [aq] @ [rl] @ rs2 : regbits @ rs1 : regbits @ 0b010 @ rd : regbits @ 0b0101111 = Some(AMO(AMOMAXU, aq, rl, rs2, rs1, WORD, rd))
-function clause decode 0b11100 @ [aq] @ [rl] @ rs2 : regbits @ rs1 : regbits @ 0b011 @ rd : regbits @ 0b0101111 = Some(AMO(AMOMAXU, aq, rl, rs2, rs1, DOUBLE, rd))
+mapping encdec_amoop : amoop <-> bits(5) = {
+ AMOSWAP <-> 0b00001,
+ AMOADD <-> 0b00000,
+ AMOXOR <-> 0b00100,
+ AMOAND <-> 0b01100,
+ AMOOR <-> 0b01000,
+ AMOMIN <-> 0b10000,
+ AMOMAX <-> 0b10100,
+ AMOMINU <-> 0b11000,
+ AMOMAXU <-> 0b11100
+}
+
+mapping clause encdec = AMO(op, aq, rl, rs2, rs1, size, rd) <-> encdec_amoop(op) @ bool_bits(aq) @ bool_bits(rl) @ rs2 @ rs1 @ 0b0 @ size_bits(size) @ rd @ 0b0101111
/* NOTE: Currently, we only EA if address translation is successful.
This may need revisiting. */
@@ -847,15 +1054,30 @@ function clause print_insn (AMO(op, aq, rl, rs2, rs1, width, rd)) =
} in
insn ^ rd ^ ", " ^ rs1 ^ ", " ^ rs2
+mapping amo_mnemonic : amoop <-> string = {
+ AMOSWAP <-> "amoswap",
+ AMOADD <-> "amoadd",
+ AMOXOR <-> "amoxor",
+ AMOAND <-> "amoand",
+ AMOOR <-> "amoor",
+ AMOMIN <-> "amomin",
+ AMOMAX <-> "amomax",
+ AMOMINU <-> "amominu",
+ AMOMAXU <-> "amomaxu"
+}
+
+mapping clause assembly = AMO(op, aq, rl, rs2, rs1, width, rd) <-> amo_mnemonic(op) ^ "." ^ size_mnemonic(width) ^ maybe_aq(aq) ^ maybe_rl(rl) ^ spc() ^ reg_name(rd) ^ sep() ^ reg_name(rs1) ^ sep() ^ reg_name(rs2)
+
/* ****************************************************************** */
union clause ast = CSR : (bits(12), regbits, regbits, bool, csrop)
-function clause decode csr : bits(12) @ rs1 : regbits @ 0b001 @ rd : regbits @ 0b1110011 = Some(CSR (csr, rs1, rd, false, CSRRW))
-function clause decode csr : bits(12) @ rs1 : regbits @ 0b010 @ rd : regbits @ 0b1110011 = Some(CSR (csr, rs1, rd, false, CSRRS))
-function clause decode csr : bits(12) @ rs1 : regbits @ 0b011 @ rd : regbits @ 0b1110011 = Some(CSR (csr, rs1, rd, false, CSRRC))
-function clause decode csr : bits(12) @ rs1 : regbits @ 0b101 @ rd : regbits @ 0b1110011 = Some(CSR (csr, rs1, rd, true, CSRRW))
-function clause decode csr : bits(12) @ rs1 : regbits @ 0b110 @ rd : regbits @ 0b1110011 = Some(CSR (csr, rs1, rd, true, CSRRS))
-function clause decode csr : bits(12) @ rs1 : regbits @ 0b111 @ rd : regbits @ 0b1110011 = Some(CSR (csr, rs1, rd, true, CSRRC))
+mapping encdec_csrop : csrop <-> bits(2) = {
+ CSRRW <-> 0b01,
+ CSRRS <-> 0b10,
+ CSRRC <-> 0b11
+}
+
+mapping clause encdec = CSR(csr, rs1, rd, is_imm, op) <-> csr @ rs1 @ bool_bits(is_imm) @ encdec_csrop(op) @ rd @ 0b1110011
function readCSR csr : csreg -> xlenbits =
match csr {
@@ -983,6 +1205,20 @@ function clause print_insn (CSR(csr, rs1, rd, is_imm, op)) =
let rs1_str : string = if is_imm then BitStr(rs1) else reg_name_abi(rs1) in
insn ^ rd ^ ", " ^ rs1_str ^ ", " ^ csr_name(csr)
+mapping maybe_i : bool <-> string = {
+ true <-> "i",
+ false <-> ""
+}
+
+mapping csr_mnemonic : csrop <-> string = {
+ CSRRW <-> "csrrw",
+ CSRRS <-> "csrrs",
+ CSRRC <-> "csrrc"
+}
+
+mapping clause assembly = CSR(csr, rs1, rd, true, op) <-> csr_mnemonic(op) ^ "i" ^ spc() ^ reg_name(rd) ^ sep() ^ hex_bits_5(rs1) ^ sep() ^ csr_name_map(csr)
+mapping clause assembly = CSR(csr, rs1, rd, false, op) <-> csr_mnemonic(op) ^ spc() ^ reg_name(rd) ^ sep() ^ reg_name(rs1) ^ sep() ^ csr_name_map(csr)
+
/* ****************************************************************** */
union clause ast = NOP : unit
@@ -997,16 +1233,7 @@ function clause print_insn (NOP()) =
"nop"
/* ****************************************************************** */
-union clause ast = ILLEGAL : unit
-
-function clause decodeCompressed (0b0000 @ 0b00000 @ 0b00000 @ 0b00) : bits(16) = Some(ILLEGAL())
-
-function clause execute ILLEGAL() = { handle_illegal(); false }
-function clause print_insn (ILLEGAL()) =
- "illegal"
-
-/* ****************************************************************** */
union clause ast = C_ADDI4SPN : (cregbits, bits(8))
function clause decodeCompressed (0b000 @ nz54 : bits(2) @ nz96 : bits(4) @ nz2 : bits(1) @ nz3 : bits(1) @ rd : cregbits @ 0b00) : bits(16) = {
@@ -1507,11 +1734,39 @@ function clause print_insn (C_ADD(rsd, rs2)) =
/* ****************************************************************** */
-function clause decode _ = None()
+union clause ast = ILLEGAL : word
+
+mapping clause encdec = ILLEGAL(s) <-> s
+
+function clause execute (ILLEGAL(s)) = { handle_illegal(); false }
+
+function clause print_insn (ILLEGAL(s)) = "illegal " ^ hex_bits_32(s)
+
+mapping clause assembly = ILLEGAL(s) <-> "illegal" ^ spc() ^ hex_bits_32(s)
+
+
+
+/* ****************************************************************** */
+
+union clause ast = C_ILLEGAL : unit
+
+function clause decodeCompressed (0b0000 @ 0b00000 @ 0b00000 @ 0b00) : bits(16) = Some(C_ILLEGAL())
+
+function clause execute C_ILLEGAL() = { handle_illegal(); false }
+
+function clause print_insn (C_ILLEGAL()) =
+ "c.illegal"
+
+/* ****************************************************************** */
+
+
function clause decodeCompressed _ = None()
end ast
-end decode
end decodeCompressed
end execute
end print_insn
+end assembly
+end encdec
+
+function decode bv = Some(encdec(bv)) \ No newline at end of file
diff --git a/riscv/riscv_sys.sail b/riscv/riscv_sys.sail
index 8af1155a..9373701c 100644
--- a/riscv/riscv_sys.sail
+++ b/riscv/riscv_sys.sail
@@ -519,6 +519,69 @@ function csr_name(csr) = {
}
}
+mapping csr_name_map : csreg <-> string = {
+ /* user trap setup */
+ 0x000 <-> "ustatus",
+ 0x004 <-> "uie",
+ 0x005 <-> "utvec",
+ /* user floating-point context */
+ 0x001 <-> "fflags",
+ 0x002 <-> "frm",
+ 0x003 <-> "fcsr",
+ /* counter/timers */
+ 0xC00 <-> "cycle",
+ 0xC01 <-> "time",
+ 0xC02 <-> "instret",
+ 0xC80 <-> "cycleh",
+ 0xC81 <-> "timeh",
+ 0xC82 <-> "instreth",
+ /* TODO: other hpm counters */
+ /* supervisor trap setup */
+ 0x100 <-> "sstatus",
+ 0x102 <-> "sedeleg",
+ 0x103 <-> "sideleg",
+ 0x104 <-> "sie",
+ 0x105 <-> "stvec",
+ 0x106 <-> "scounteren",
+ /* supervisor trap handling */
+ 0x140 <-> "sscratch",
+ 0x141 <-> "sepc",
+ 0x142 <-> "scause",
+ 0x143 <-> "stval",
+ 0x144 <-> "sip",
+ /* supervisor protection and translation */
+ 0x180 <-> "satp",
+ /* machine information registers */
+ 0xF11 <-> "mvendorid",
+ 0xF12 <-> "marchid",
+ 0xF13 <-> "mimpid",
+ 0xF14 <-> "mhartid",
+ /* machine trap setup */
+ 0x300 <-> "mstatus",
+ 0x301 <-> "misa",
+ 0x302 <-> "medeleg",
+ 0x303 <-> "mideleg",
+ 0x304 <-> "mie",
+ 0x305 <-> "mtvec",
+ 0x306 <-> "mcounteren",
+ /* machine trap handling */
+ 0x340 <-> "mscratch",
+ 0x341 <-> "mepc",
+ 0x342 <-> "mcause",
+ 0x343 <-> "mtval",
+ 0x344 <-> "mip",
+ /* TODO: machine protection and translation */
+ /* machine counters/timers */
+ 0xB00 <-> "mcycle",
+ 0xB02 <-> "minstret",
+ 0xB80 <-> "mcycleh",
+ 0xB82 <-> "minstreth",
+ /* TODO: other hpm counters and events */
+ /* trigger/debug */
+ 0x7a0 <-> "tselect"
+ }
+
+
/* csr access control */
function csrAccess(csr : csreg) -> csrRW = csr[11..10]
diff --git a/riscv/riscv_types.sail b/riscv/riscv_types.sail
index 1a79670b..42042293 100644
--- a/riscv/riscv_types.sail
+++ b/riscv/riscv_types.sail
@@ -327,3 +327,71 @@ enum ropw = {RISCV_ADDW, RISCV_SUBW, RISCV_SLLW, RISCV_SRLW, RISCV_SRAW} /* reg-
enum amoop = {AMOSWAP, AMOADD, AMOXOR, AMOAND, AMOOR, AMOMIN, AMOMAX, AMOMINU, AMOMAXU} /* AMO ops */
enum csrop = {CSRRW, CSRRS, CSRRC}
enum word_width = {BYTE, HALF, WORD, DOUBLE}
+
+/* mappings for assembly */
+
+val reg_name : bits(5) <-> string
+mapping reg_name = {
+ 0b00000 <-> "zero",
+ 0b00001 <-> "ra",
+ 0b00010 <-> "sp",
+ 0b00011 <-> "gp",
+ 0b00100 <-> "tp",
+ 0b00101 <-> "t0",
+ 0b00110 <-> "t1",
+ 0b00111 <-> "t2",
+ 0b01000 <-> "fp",
+ 0b01001 <-> "s1",
+ 0b01010 <-> "a0",
+ 0b01011 <-> "a1",
+ 0b01100 <-> "a2",
+ 0b01101 <-> "a3",
+ 0b01110 <-> "a4",
+ 0b01111 <-> "a5",
+ 0b10000 <-> "a6",
+ 0b10001 <-> "a7",
+ 0b10010 <-> "s2",
+ 0b10011 <-> "s3",
+ 0b10100 <-> "s4",
+ 0b10101 <-> "s5",
+ 0b10110 <-> "s6",
+ 0b10111 <-> "s7",
+ 0b11000 <-> "s8",
+ 0b11001 <-> "s9",
+ 0b11010 <-> "s10",
+ 0b11011 <-> "s11",
+ 0b11100 <-> "t3",
+ 0b11101 <-> "t4",
+ 0b11110 <-> "t5",
+ 0b11111 <-> "t6"
+}
+
+val sep : unit <-> string
+mapping sep = {
+ () <-> opt_spc() ^ "," ^ def_spc()
+}
+
+mapping bool_bits : bool <-> bits(1) = {
+ true <-> 0b1,
+ false <-> 0b0
+}
+
+mapping bool_not_bits : bool <-> bits(1) = {
+ true <-> 0b0,
+ false <-> 0b1
+}
+
+
+mapping size_bits : word_width <-> bits(2) = {
+ BYTE <-> 0b00,
+ HALF <-> 0b01,
+ WORD <-> 0b10,
+ DOUBLE <-> 0b11
+}
+
+mapping size_mnemonic : word_width <-> string = {
+ BYTE <-> "b",
+ HALF <-> "h",
+ WORD <-> "w",
+ DOUBLE <-> "d"
+}