Add an enable_e setting for the RV32E instruction set.
This limited RISC-V version only has registers %x0 - %x15. Make sure the ABI lowering code doesn't use the banned registers for arguments.
This commit is contained in:
14
filetests/isa/riscv/abi-e.cton
Normal file
14
filetests/isa/riscv/abi-e.cton
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
; Test the legalization of function signatures for RV32E.
|
||||||
|
test legalizer
|
||||||
|
isa riscv enable_e
|
||||||
|
|
||||||
|
; regex: V=v\d+
|
||||||
|
|
||||||
|
function f() {
|
||||||
|
; Spilling into the stack args after %x15 since %16 and up are not
|
||||||
|
; available in RV32E.
|
||||||
|
sig0 = signature(i64, i64, i64, i64) -> i64
|
||||||
|
; check: sig0 = signature(i32 [%x10], i32 [%x11], i32 [%x12], i32 [%x13], i32 [%x14], i32 [%x15], i32 [0], i32 [4]) -> i32 [%x10], i32 [%x11]
|
||||||
|
ebb0:
|
||||||
|
return
|
||||||
|
}
|
||||||
@@ -18,6 +18,9 @@ enable_m = BoolSetting(
|
|||||||
"Enable the use of 'M' instructions if available",
|
"Enable the use of 'M' instructions if available",
|
||||||
default=True)
|
default=True)
|
||||||
|
|
||||||
|
enable_e = BoolSetting(
|
||||||
|
"Enable the 'RV32E' instruction set with only 16 registers")
|
||||||
|
|
||||||
use_m = And(supports_m, enable_m)
|
use_m = And(supports_m, enable_m)
|
||||||
use_a = And(supports_a, shared.enable_atomics)
|
use_a = And(supports_a, shared.enable_atomics)
|
||||||
use_f = And(supports_f, shared.enable_float)
|
use_f = And(supports_f, shared.enable_float)
|
||||||
|
|||||||
@@ -8,24 +8,27 @@
|
|||||||
use abi::{ArgAction, ValueConversion, ArgAssigner, legalize_args};
|
use abi::{ArgAction, ValueConversion, ArgAssigner, legalize_args};
|
||||||
use ir::{Signature, Type, ArgumentType, ArgumentLoc, ArgumentExtension, ArgumentPurpose};
|
use ir::{Signature, Type, ArgumentType, ArgumentLoc, ArgumentExtension, ArgumentPurpose};
|
||||||
use isa::RegClass;
|
use isa::RegClass;
|
||||||
use isa::riscv::registers::{GPR, FPR};
|
|
||||||
use settings as shared_settings;
|
use settings as shared_settings;
|
||||||
|
use super::registers::{GPR, FPR};
|
||||||
|
use super::settings;
|
||||||
|
|
||||||
struct Args {
|
struct Args {
|
||||||
pointer_bits: u16,
|
pointer_bits: u16,
|
||||||
pointer_bytes: u32,
|
pointer_bytes: u32,
|
||||||
pointer_type: Type,
|
pointer_type: Type,
|
||||||
regs: u32,
|
regs: u32,
|
||||||
|
reg_limit: u32,
|
||||||
offset: u32,
|
offset: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Args {
|
impl Args {
|
||||||
fn new(bits: u16) -> Args {
|
fn new(bits: u16, enable_e: bool) -> Args {
|
||||||
Args {
|
Args {
|
||||||
pointer_bits: bits,
|
pointer_bits: bits,
|
||||||
pointer_bytes: bits as u32 / 8,
|
pointer_bytes: bits as u32 / 8,
|
||||||
pointer_type: Type::int(bits).unwrap(),
|
pointer_type: Type::int(bits).unwrap(),
|
||||||
regs: 0,
|
regs: 0,
|
||||||
|
reg_limit: if enable_e { 6 } else { 8 },
|
||||||
offset: 0,
|
offset: 0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -62,7 +65,7 @@ impl ArgAssigner for Args {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.regs < 8 {
|
if self.regs < self.reg_limit {
|
||||||
// Assign to a register.
|
// Assign to a register.
|
||||||
let reg = if ty.is_float() {
|
let reg = if ty.is_float() {
|
||||||
FPR.unit(10 + self.regs as usize)
|
FPR.unit(10 + self.regs as usize)
|
||||||
@@ -81,13 +84,16 @@ impl ArgAssigner for Args {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Legalize `sig` for RISC-V.
|
/// Legalize `sig` for RISC-V.
|
||||||
pub fn legalize_signature(sig: &mut Signature, flags: &shared_settings::Flags, current: bool) {
|
pub fn legalize_signature(sig: &mut Signature,
|
||||||
|
flags: &shared_settings::Flags,
|
||||||
|
isa_flags: &settings::Flags,
|
||||||
|
current: bool) {
|
||||||
let bits = if flags.is_64bit() { 64 } else { 32 };
|
let bits = if flags.is_64bit() { 64 } else { 32 };
|
||||||
|
|
||||||
let mut args = Args::new(bits);
|
let mut args = Args::new(bits, isa_flags.enable_e());
|
||||||
legalize_args(&mut sig.argument_types, &mut args);
|
legalize_args(&mut sig.argument_types, &mut args);
|
||||||
|
|
||||||
let mut rets = Args::new(bits);
|
let mut rets = Args::new(bits, isa_flags.enable_e());
|
||||||
legalize_args(&mut sig.return_types, &mut rets);
|
legalize_args(&mut sig.return_types, &mut rets);
|
||||||
|
|
||||||
if current {
|
if current {
|
||||||
|
|||||||
@@ -79,8 +79,7 @@ impl TargetIsa for Isa {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn legalize_signature(&self, sig: &mut Signature, current: bool) {
|
fn legalize_signature(&self, sig: &mut Signature, current: bool) {
|
||||||
// We can pass in `self.isa_flags` too, if we need it.
|
abi::legalize_signature(sig, &self.shared_flags, &self.isa_flags, current)
|
||||||
abi::legalize_signature(sig, &self.shared_flags, current)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn regclass_for_abi_type(&self, ty: Type) -> RegClass {
|
fn regclass_for_abi_type(&self, ty: Type) -> RegClass {
|
||||||
|
|||||||
@@ -24,7 +24,8 @@ mod tests {
|
|||||||
supports_a = false\n\
|
supports_a = false\n\
|
||||||
supports_f = false\n\
|
supports_f = false\n\
|
||||||
supports_d = false\n\
|
supports_d = false\n\
|
||||||
enable_m = true\n");
|
enable_m = true\n\
|
||||||
|
enable_e = false\n");
|
||||||
// Predicates are not part of the Display output.
|
// Predicates are not part of the Display output.
|
||||||
assert_eq!(f.full_float(), false);
|
assert_eq!(f.full_float(), false);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user