Skip to content

Commit

Permalink
Merge pull request bytecodealliance#77 from near/nagisa/removes-riscv…
Browse files Browse the repository at this point in the history
…-flags

zkasm: clean up RISC-V feature flags
  • Loading branch information
nagisa authored Nov 9, 2023
2 parents 4ff752b + f9423f1 commit 239d749
Show file tree
Hide file tree
Showing 4 changed files with 5 additions and 288 deletions.
96 changes: 1 addition & 95 deletions cranelift/codegen/meta/src/isa/zkasm.rs
Original file line number Diff line number Diff line change
@@ -1,101 +1,7 @@
use crate::cdsl::isa::TargetIsa;
use crate::cdsl::settings::SettingGroupBuilder;

macro_rules! define_zvl_ext {
(DEF: $settings:expr, $size:expr) => {{
let name = concat!("has_zvl", $size, "b");
let desc = concat!("has extension Zvl", $size, "b?");
let comment = concat!(
"Zvl",
$size,
"b: Vector register has a minimum of ",
$size,
" bits"
);
$settings.add_bool(&name, &desc, &comment, false)
}};
($settings:expr, $size:expr $(, $implies:expr)*) => {{
let has_feature = define_zvl_ext!(DEF: $settings, $size);

let name = concat!("zvl", $size, "b");
let desc = concat!("Has a vector register size of at least ", $size, " bits");

let preset = $settings.add_preset(&name, &desc, preset!(has_feature $( && $implies )*));
(has_feature, preset)
}};
}

pub(crate) fn define() -> TargetIsa {
let mut setting = SettingGroupBuilder::new("zkasm");

let _has_m = setting.add_bool("has_m", "has extension M?", "", false);
let _has_a = setting.add_bool("has_a", "has extension A?", "", false);
let _has_f = setting.add_bool("has_f", "has extension F?", "", false);
let _has_d = setting.add_bool("has_d", "has extension D?", "", false);
let _has_v = setting.add_bool("has_v", "has extension V?", "", false);
let _has_c = setting.add_bool("has_c", "has extension C?", "", false);
let _has_zbkb = setting.add_bool(
"has_zbkb",
"has extension zbkb?",
"Zbkb: Bit-manipulation for Cryptography",
false,
);
let _has_zba = setting.add_bool(
"has_zba",
"has extension zba?",
"Zba: Address Generation",
false,
);
let _has_zbb = setting.add_bool(
"has_zbb",
"has extension zbb?",
"Zbb: Basic bit-manipulation",
false,
);
let _has_zbc = setting.add_bool(
"has_zbc",
"has extension zbc?",
"Zbc: Carry-less multiplication",
false,
);
let _has_zbs = setting.add_bool(
"has_zbs",
"has extension zbs?",
"Zbs: Single-bit instructions",
false,
);

let _has_zicsr = setting.add_bool(
"has_zicsr",
"has extension zicsr?",
"Zicsr: Control and Status Register (CSR) Instructions",
false,
);
let _has_zifencei = setting.add_bool(
"has_zifencei",
"has extension zifencei?",
"Zifencei: Instruction-Fetch Fence",
false,
);

// Zvl*: Minimum Vector Length Standard Extensions
// These extension specifiy the minimum number of bits in a vector register.
// Since it is a minimum, Zvl64b implies Zvl32b, Zvl128b implies Zvl64b, etc.
// The V extension supports a maximum of 64K bits in a single register.
//
// See: https://github.com/riscv/riscv-v-spec/blob/master/v-spec.adoc#181-zvl-minimum-vector-length-standard-extensions
let (_, zvl32b) = define_zvl_ext!(setting, 32);
let (_, zvl64b) = define_zvl_ext!(setting, 64, zvl32b);
let (_, zvl128b) = define_zvl_ext!(setting, 128, zvl64b);
let (_, zvl256b) = define_zvl_ext!(setting, 256, zvl128b);
let (_, zvl512b) = define_zvl_ext!(setting, 512, zvl256b);
let (_, zvl1024b) = define_zvl_ext!(setting, 1024, zvl512b);
let (_, zvl2048b) = define_zvl_ext!(setting, 2048, zvl1024b);
let (_, zvl4096b) = define_zvl_ext!(setting, 4096, zvl2048b);
let (_, zvl8192b) = define_zvl_ext!(setting, 8192, zvl4096b);
let (_, zvl16384b) = define_zvl_ext!(setting, 16384, zvl8192b);
let (_, zvl32768b) = define_zvl_ext!(setting, 32768, zvl16384b);
let (_, _zvl65536b) = define_zvl_ext!(setting, 65536, zvl32768b);

let setting = SettingGroupBuilder::new("zkasm");
TargetIsa::new("zkasm", setting.build())
}
112 changes: 0 additions & 112 deletions cranelift/codegen/src/isa/zkasm/inst.isle
Original file line number Diff line number Diff line change
Expand Up @@ -544,26 +544,6 @@
(decl u8_as_i32 (u8) i32)
(extern constructor u8_as_i32 u8_as_i32)

;; ISA Extension helpers

(decl pure has_v () bool)
(extern constructor has_v has_v)

(decl pure has_zbkb () bool)
(extern constructor has_zbkb has_zbkb)

(decl pure has_zba () bool)
(extern constructor has_zba has_zba)

(decl pure has_zbb () bool)
(extern constructor has_zbb has_zbb)

(decl pure has_zbc () bool)
(extern constructor has_zbc has_zbc)

(decl pure has_zbs () bool)
(extern constructor has_zbs has_zbs)

;;;; Instruction Helpers ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;; RV32I Base Integer Instruction Set
Expand Down Expand Up @@ -1064,27 +1044,6 @@
(let ((right XReg (value_regs_get val 0)))
right))

;; No point in trying to use `packh` here to zero extend 8 bit values
;; since we can just use `andi` instead which is part of the base ISA.

;; If we have the `zbkb` extension `packw` can be used to zero extend 16 bit values
(rule 1 (extend val (ExtendOp.Zero) $I16 (fits_in_64 _))
(if-let $true (has_zbkb))
(let ((val XReg (value_regs_get val 0)))
(rv_packw val (zero_reg))))

;; If we have the `zbkb` extension `pack` can be used to zero extend 32 bit registers
(rule 1 (extend val (ExtendOp.Zero) $I32 $I64)
(if-let $true (has_zbkb))
(let ((val XReg (value_regs_get val 0)))
(rv_pack val (zero_reg))))

;; With `zba` we have a `zext.w` instruction
(rule 2 (extend val (ExtendOp.Zero) $I32 $I64)
(if-let $true (has_zba))
(let ((val XReg (value_regs_get val 0)))
(rv_zextw val)))

;;; Unsigned rules extending to I128
;; Extend the bottom register to I64 and then just zero out the top half.
(rule 3 (extend val (ExtendOp.Zero) (fits_in_64 from_ty) $I128)
Expand Down Expand Up @@ -1131,24 +1090,12 @@

(decl lower_rotl (Type XReg XReg) XReg)

(rule 1
(lower_rotl $I64 rs amount)
(if-let $true (has_zbb))
(rv_rol rs amount))

(rule
(lower_rotl $I64 rs amount)
(if-let $false (has_zbb))
(lower_rotl_shift $I64 rs amount))

(rule 1
(lower_rotl $I32 rs amount)
(if-let $true (has_zbb))
(rv_rolw rs amount))

(rule
(lower_rotl $I32 rs amount)
(if-let $false (has_zbb))
(lower_rotl_shift $I32 rs amount))

(rule -1
Expand Down Expand Up @@ -1181,23 +1128,12 @@

(decl lower_rotr (Type XReg XReg) XReg)

(rule 1
(lower_rotr $I64 rs amount)
(if-let $true (has_zbb))
(rv_ror rs amount))
(rule
(lower_rotr $I64 rs amount)
(if-let $false (has_zbb))
(lower_rotr_shift $I64 rs amount))

(rule 1
(lower_rotr $I32 rs amount)
(if-let $true (has_zbb))
(rv_rorw rs amount))

(rule
(lower_rotr $I32 rs amount)
(if-let $false (has_zbb))
(lower_rotr_shift $I32 rs amount))

(rule -1
Expand Down Expand Up @@ -1226,7 +1162,6 @@
;; bseti: Set a single bit in a register, indexed by a constant.
(decl gen_bseti (Reg u64) Reg)
(rule (gen_bseti val bit)
(if-let $false (has_zbs))
(if-let $false (u64_le bit 12))
(let ((const XReg (load_u64_constant (u64_shl 1 bit))))
(rv_or val const)))
Expand Down Expand Up @@ -1578,15 +1513,10 @@
(rule 2 (neg $I128 val)
(i128_sub (value_regs_zero) val))


;; Selects the greatest of two registers as signed values.
(decl max (Type XReg XReg) XReg)
(rule (max (fits_in_64 (ty_int ty)) x y)
(if-let $true (has_zbb))
(rv_max x y))

(rule (max (fits_in_64 (ty_int ty)) x y)
(if-let $false (has_zbb))
(gen_select_reg (IntCC.SignedGreaterThan) x y x y))


Expand Down Expand Up @@ -1637,48 +1567,6 @@
((t XReg (zk_mul n m)))
(rv_add t a)))

;;;; Helpers for bmask ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

(decl lower_bmask (Type Type ValueRegs) ValueRegs)

;; Produces -1 if the 64-bit value is non-zero, and 0 otherwise.
;; If the type is smaller than 64 bits, we need to mask off the
;; high bits.
(rule
0
(lower_bmask (fits_in_64 _) (fits_in_64 in_ty) val)
(let ((input XReg (truthy_to_reg in_ty (normalize_cmp_value in_ty val (ExtendOp.Zero))))
(non_zero XReg (rv_snez input)))
(value_reg (rv_neg non_zero))))

;; Bitwise-or the two registers that make up the 128-bit value, then recurse as
;; though it was a 64-bit value.
(rule
1
(lower_bmask (fits_in_64 ty) $I128 val)
(let ((lo XReg (value_regs_get val 0))
(hi XReg (value_regs_get val 1))
(combined XReg (rv_or lo hi)))
(lower_bmask ty $I64 (value_reg combined))))

;; Conversion of one 64-bit value to a 128-bit one. Duplicate the result of the
;; bmask of the 64-bit value into both result registers of the i128.
(rule
2
(lower_bmask $I128 (fits_in_64 in_ty) val)
(let ((res ValueRegs (lower_bmask $I64 in_ty val)))
(value_regs (value_regs_get res 0) (value_regs_get res 0))))

;; Conversion of one 64-bit value to a 128-bit one. Duplicate the result of
;; bmasking the 128-bit value to a 64-bit value into both registers of the
;; 128-bit result.
(rule
3
(lower_bmask $I128 $I128 val)
(let ((res ValueRegs (lower_bmask $I64 $I128 val)))
(value_regs (value_regs_get res 0) (value_regs_get res 0))))


;;;; Helpers for physical registers ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

(decl gen_mov_from_preg (PReg) Reg)
Expand Down
61 changes: 4 additions & 57 deletions cranelift/codegen/src/isa/zkasm/lower.isle
Original file line number Diff line number Diff line change
Expand Up @@ -144,58 +144,10 @@
(rule 0 (lower (has_type (ty_int ty) (band x y)))
(gen_and ty x y))

;; Specialized lowerings for `(band x (bnot y))` which is additionally produced
;; by Cranelift's `band_not` instruction that is legalized into the simpler
;; forms early on.

(rule 4 (lower (has_type (fits_in_64 (ty_int ty)) (band x (bnot y))))
(if-let $true (has_zbb))
(rv_andn x y))

(rule 5 (lower (has_type (fits_in_64 (ty_int ty)) (band (bnot y) x)))
(if-let $true (has_zbb))
(rv_andn x y))

(rule 6 (lower (has_type $I128 (band x (bnot y))))
(if-let $true (has_zbb))
(let ((low XReg (rv_andn (value_regs_get x 0) (value_regs_get y 0)))
(high XReg (rv_andn (value_regs_get x 1) (value_regs_get y 1))))
(value_regs low high)))

(rule 7 (lower (has_type $I128 (band (bnot y) x)))
(if-let $true (has_zbb))
(let ((low XReg (rv_andn (value_regs_get x 0) (value_regs_get y 0)))
(high XReg (rv_andn (value_regs_get x 1) (value_regs_get y 1))))
(value_regs low high)))

;;;; Rules for `or` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(rule 0 (lower (has_type (ty_int ty) (bor x y)))
(gen_or ty x y))

;; Specialized lowerings for `(bor x (bnot y))` which is additionally produced
;; by Cranelift's `bor_not` instruction that is legalized into the simpler
;; forms early on.

(rule 4 (lower (has_type (fits_in_64 (ty_int ty)) (bor x (bnot y))))
(if-let $true (has_zbb))
(rv_orn x y))

(rule 5 (lower (has_type (fits_in_64 (ty_int ty)) (bor (bnot y) x)))
(if-let $true (has_zbb))
(rv_orn x y))

(rule 6 (lower (has_type $I128 (bor x (bnot y))))
(if-let $true (has_zbb))
(let ((low XReg (rv_orn (value_regs_get x 0) (value_regs_get y 0)))
(high XReg (rv_orn (value_regs_get x 1) (value_regs_get y 1))))
(value_regs low high)))

(rule 7 (lower (has_type $I128 (bor (bnot y) x)))
(if-let $true (has_zbb))
(let ((low XReg (rv_orn (value_regs_get x 0) (value_regs_get y 0)))
(high XReg (rv_orn (value_regs_get x 1) (value_regs_get y 1))))
(value_regs low high)))

;;;; Rules for `xor` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(rule 0 (lower (has_type (fits_in_64 (ty_int ty)) (bxor x y)))
(rv_xor x y))
Expand Down Expand Up @@ -562,11 +514,6 @@
(lower (has_type out_ty (bitcast _ v @ (value_type in_ty))))
(gen_bitcast v in_ty out_ty))

;;;;; Rules for `bmask`;;;;;;;;;
(rule
(lower (has_type oty (bmask x @ (value_type ity))))
(lower_bmask oty ity x))

;; N.B.: the Ret itself is generated by the ABI.
(rule (lower (return args))
(lower_return args))
Expand All @@ -589,10 +536,10 @@
;; sext.{b,h,w} a0, a0
;; neg a1, a0
;; max a0, a0, a1
(rule 0 (lower (has_type (ty_int_ref_scalar_64 ty) (iabs x)))
(let ((extended XReg (sext x ty $I64))
(negated XReg (rv_neg extended)))
(max $I64 extended negated)))
; (rule 0 (lower (has_type (ty_int_ref_scalar_64 ty) (iabs x)))
; (let ((extended XReg (sext x ty $I64))
; (negated XReg (rv_neg extended)))
; (max $I64 extended negated)))

;;;; Rules for calls ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

Expand Down
24 changes: 0 additions & 24 deletions cranelift/codegen/src/isa/zkasm/lower/isle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -323,30 +323,6 @@ impl generated_code::Context for ZkAsmIsleContext<'_, '_, MInst, ZkAsmBackend> {
todo!()
}

fn has_v(&mut self) -> bool {
self.backend.isa_flags.has_v()
}

fn has_zbkb(&mut self) -> bool {
self.backend.isa_flags.has_zbkb()
}

fn has_zba(&mut self) -> bool {
self.backend.isa_flags.has_zba()
}

fn has_zbb(&mut self) -> bool {
self.backend.isa_flags.has_zbb()
}

fn has_zbc(&mut self) -> bool {
self.backend.isa_flags.has_zbc()
}

fn has_zbs(&mut self) -> bool {
self.backend.isa_flags.has_zbs()
}

fn offset32_imm(&mut self, offset: i32) -> Offset32 {
Offset32::new(offset)
}
Expand Down

0 comments on commit 239d749

Please sign in to comment.