Skip to content

Commit

Permalink
ARM: Add BFI and BFC
Browse files Browse the repository at this point in the history
  • Loading branch information
sarranz committed Nov 12, 2023
1 parent 7bc7452 commit bdb3577
Show file tree
Hide file tree
Showing 8 changed files with 134 additions and 2 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@
([PR #620](https://github.com/jasmin-lang/jasmin/pull/620);
fixes [#618](https://github.com/jasmin-lang/jasmin/issues/618)).

- Add instructions `BFC` and `BFI` to arm-m4
([PR #643](https://github.com/jasmin-lang/jasmin/pull/643)).

## Bug fixes

- Type-checking rejects wrongly casted primitive operators
Expand Down
12 changes: 12 additions & 0 deletions compiler/tests/success/arm-m4/intrinsic_bfc.jazz
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
export
fn bfc(reg u32 x) -> reg u32 {
x = #BFC(x, 0, 1);
x = #BFC(x, 31, 1);
x = #BFC(x, 0, 32);

inline bool b;
?{ "<s" = b } = #CMP(x, 5);
x = #BFCcc(x, 0, 32, b, x);

return x;
}
15 changes: 15 additions & 0 deletions compiler/tests/success/arm-m4/intrinsic_bfi.jazz
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
export
fn bfi(reg u32 x) -> reg u32 {
reg u32 y;
y = 0;
y = #BFI(y, x, 0, 1);
y = #BFI(y, x, 31, 1);
y = #BFI(y, x, 0, 32);

inline bool b;
?{ "<s" = b } = #CMP(y, 5);
y = #BFIcc(y, x, 0, 32, b, y);

y = y;
return y;
}
15 changes: 15 additions & 0 deletions eclib/JModel_m4.ec
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,21 @@ op AND x y = let (_n, _z, _c, r) = ANDS x y in r.
op ANDScc x y g n z c o = if g then ANDS x y else (n, z, c, o).
op ANDcc x y g o = if g then AND x y else o.

op BFC (x: W32.t) (lsb width: W8.t) : W32.t =
let ones = W32.of_int (2 ^ to_uint width - 1) in
let wmask = invw (ones `<<<` to_uint lsb) in
andw x wmask.
op BFCcc x lsb width g o = if g then BFC x lsb width else o.

op BFI (x y: W32.t) (lsb width: W8.t) : W32.t =
let lsbit = to_uint lsb in
let ones = W32.of_int (2 ^ to_uint width - 1) in
let mask = ones `<<<` lsbit in
let ybits = andw (y `<<<` lsbit) mask in
let xbits = andw x (invw mask) in
orw xbits ybits.
op BFIcc x y lsb width g o = if g then BFI x y lsb width else o.

op BICS (x y: W32.t) : bool * bool * bool * W32.t =
with_nzc (andw x (invw y)).
op BIC x y = let (_n, _z, _c, r) = BICS x y in r.
Expand Down
4 changes: 4 additions & 0 deletions proofs/arch/arch_utils.v
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,8 @@ Definition ak_reg_imm16 : i_args_kinds :=
[:: [:: [:: CAreg ]; [:: CAimm U16 ] ] ].
Definition ak_reg_addr : i_args_kinds :=
[:: [:: [:: CAreg ]; [:: CAmem true ] ] ].
Definition ak_reg_imm8_imm8 : i_args_kinds :=
[:: [:: [:: CAreg ]; [:: CAimm U8 ]; [:: CAimm U8 ] ] ].

Definition ak_reg_reg_reg : i_args_kinds :=
[:: [:: [:: CAreg ]; [:: CAreg ]; [:: CAreg ] ] ].
Expand All @@ -72,6 +74,8 @@ Definition ak_reg_reg_imm8 : i_args_kinds :=
[:: [:: [:: CAreg ]; [:: CAreg ]; [:: CAimm U8 ] ] ].
Definition ak_reg_reg_imm16 : i_args_kinds :=
[:: [:: [:: CAreg ]; [:: CAreg ]; [:: CAimm U16 ] ] ].
Definition ak_reg_reg_imm8_imm8 : i_args_kinds :=
[:: [:: [:: CAreg ]; [:: CAreg ]; [:: CAimm U8 ]; [:: CAimm U8 ] ] ].

Definition ak_reg_reg_reg_reg : i_args_kinds :=
[:: [:: [:: CAreg ]; [:: CAreg ]; [:: CAreg ] ; [:: CAreg ] ] ].
Expand Down
75 changes: 74 additions & 1 deletion proofs/compiler/arm_instr_decl.v
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,11 @@ Unset Strict Implicit.
Unset Printing Implicit Defensive.


Module E.
Definition no_semantics : error := ErrType.
End E.


(* -------------------------------------------------------------------- *)
(* ARM instruction options. *)

Expand Down Expand Up @@ -118,6 +123,8 @@ Variant arm_mnemonic : Type :=

(* Logical *)
| AND (* Bitwise AND *)
| BFC (* Bit Field Clear *)
| BFI (* Bit Field Insert *)
| BIC (* Bitwise AND with bitwise NOT *)
| EOR (* Bitwise XOR *)
| MVN (* Bitwise NOT *)
Expand Down Expand Up @@ -175,7 +182,7 @@ Canonical arm_mnemonic_eqType := @ceqT_eqType _ eqTC_arm_mnemonic.

Definition arm_mnemonics : seq arm_mnemonic :=
[:: ADD; ADC; MUL; MLA; MLS; SDIV; SUB; RSB; UDIV; UMULL; UMAAL; UMLAL; SMULL; SMLAL; SMMUL; SMMULR
; AND; BIC; EOR; MVN; ORR
; AND; BFC; BFI; BIC; EOR; MVN; ORR
; ASR; LSL; LSR; ROR; REV; REV16; REVSH
; ADR; MOV; MOVT; UBFX; UXTB; UXTH; SBFX
; CMP; TST
Expand Down Expand Up @@ -265,6 +272,8 @@ Definition string_of_arm_mnemonic (mn : arm_mnemonic) : string :=
| SMMUL => "SMMUL"
| SMMULR => "SMMULR"
| AND => "AND"
| BFC => "BFC"
| BFI => "BFI"
| BIC => "BIC"
| EOR => "EOR"
| MVN => "MVN"
Expand Down Expand Up @@ -1084,6 +1093,68 @@ Definition arm_AND_instr : instr_desc_t :=
then x
else drop_nzc x.

Definition arm_BFC_semi (x : wreg) (lsb width : word U8) : exec wreg :=
let lsbit := wunsigned lsb in
let nbits := wunsigned width in
Let _ := assert (lsbit <? 32)%Z E.no_semantics in
Let _ := assert (1 <=? nbits)%Z E.no_semantics in
Let _ := assert (nbits <=? 32 - lsbit)%Z E.no_semantics in
let ones := wrepr reg_size (2 ^ nbits - 1) in
let wmask := wnot (wshl ones lsbit) in
ok (wand x wmask).

Definition arm_BFC_instr : instr_desc_t :=
let mn := BFC in
{|
id_msb_flag := MSB_MERGE;
id_tin := [:: sreg; sword8; sword8 ];
id_in := [:: E 0; E 1; E 2 ];
id_tout := [:: sreg ];
id_out := [:: E 0 ];
id_semi := arm_BFC_semi;
id_nargs := 3;
id_args_kinds := ak_reg_imm8_imm8;
id_eq_size := refl_equal;
id_tin_narr := refl_equal;
id_tout_narr := refl_equal;
id_check_dest := refl_equal;
id_str_jas := pp_s (string_of_arm_mnemonic mn);
id_safe := [::];
id_pp_asm := pp_arm_op mn opts;
|}.

Definition arm_BFI_semi (x y : wreg) (lsb width : word U8) : exec wreg :=
let lsbit := wunsigned lsb in
let nbits := wunsigned width in
Let _ := assert (lsbit <? 32)%Z E.no_semantics in
Let _ := assert (1 <=? nbits)%Z E.no_semantics in
Let _ := assert (nbits <=? 32 - lsbit)%Z E.no_semantics in
let ones := wrepr reg_size (2 ^ nbits - 1) in
let mask := wshl ones lsbit in
let ybits := wand (wshl y lsbit) mask in
let xbits := wand x (wnot mask) in
ok (wor xbits ybits).

Definition arm_BFI_instr : instr_desc_t :=
let mn := BFI in
{|
id_msb_flag := MSB_MERGE;
id_tin := [:: sreg; sreg; sword8; sword8 ];
id_in := [:: E 0; E 1; E 2; E 3 ];
id_tout := [:: sreg ];
id_out := [:: E 0 ];
id_semi := arm_BFI_semi;
id_nargs := 4;
id_args_kinds := ak_reg_reg_imm8_imm8;
id_eq_size := refl_equal;
id_tin_narr := refl_equal;
id_tout_narr := refl_equal;
id_check_dest := refl_equal;
id_str_jas := pp_s (string_of_arm_mnemonic mn);
id_safe := [::];
id_pp_asm := pp_arm_op mn opts;
|}.

Definition arm_BIC_instr : instr_desc_t :=
let mn := BIC in
let x :=
Expand Down Expand Up @@ -1705,6 +1776,8 @@ Definition mn_desc (mn : arm_mnemonic) : instr_desc_t :=
| SMMUL => arm_SMMUL_instr
| SMMULR => arm_SMMULR_instr
| AND => arm_AND_instr
| BFC => arm_BFC_instr
| BFI => arm_BFI_instr
| BIC => arm_BIC_instr
| EOR => arm_EOR_instr
| MVN => arm_MVN_instr
Expand Down
11 changes: 10 additions & 1 deletion proofs/compiler/arm_instr_decl_lemmas.v
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ Proof.
all: case: mn.
all: rewrite /truncate_args /truncate_val.

(* Destruct [vprev]. *)
all:
repeat (
case: vprev => [| ? vprev ] //=;
Expand All @@ -79,6 +80,7 @@ Proof.
all: try move=> <-.
all: subst.

(* Destruct [vargs]. *)
all: rewrite /exec_sopn /=.
all: case: vargs => [| ? vargs ] //; t_xrbindP => // v.
all:
Expand All @@ -98,8 +100,15 @@ Proof.
end
).

(* Introduce and rewrite all semantic checks. *)
all: move: hsemop.
all: move=> [?]; subst v.
all: cbn.
all:
try match goal with
| [ |- ?f _ = ok _ -> _ ] => rewrite /f
end.
all: t_xrbindP=> *; subst v; t_eq_rewrites.

all: by case: b.
Qed.

Expand Down
1 change: 1 addition & 0 deletions proofs/lang/utils.v
Original file line number Diff line number Diff line change
Expand Up @@ -1780,6 +1780,7 @@ Ltac t_do_rewrites tac :=
match goal with
| [ h : ?lhs = ?rhs |- _ ] => tac h lhs rhs
| [ h : is_true (?lhs == ?rhs) |- _ ] => move: h => /eqP h; tac h lhs rhs
| [ h : is_true ?lhs |- _ ] => tac h lhs true
end.

#[local]
Expand Down

0 comments on commit bdb3577

Please sign in to comment.