Expand x86 registers to include 32 XMM registers
The EVEX encoding format (e.g. in AVX-512) allows addressing 32 registers instead of 16. The FPR register class currently defines 16 registers, `%xmm0`-`%xmm15`; that class is kept as-is with this change. A larger class, FPR32, is added as a super-class of FPR using a larger bank of registers, `%xmm0`-`%xmm31`.
This commit is contained in:
@@ -3,6 +3,11 @@ use crate::cdsl::regs::{IsaRegs, IsaRegsBuilder, RegBankBuilder, RegClassBuilder
|
|||||||
pub(crate) fn define() -> IsaRegs {
|
pub(crate) fn define() -> IsaRegs {
|
||||||
let mut regs = IsaRegsBuilder::new();
|
let mut regs = IsaRegsBuilder::new();
|
||||||
|
|
||||||
|
let builder = RegBankBuilder::new("FloatRegs", "xmm")
|
||||||
|
.units(32)
|
||||||
|
.track_pressure(true);
|
||||||
|
let float_regs = regs.add_bank(builder);
|
||||||
|
|
||||||
let builder = RegBankBuilder::new("IntRegs", "r")
|
let builder = RegBankBuilder::new("IntRegs", "r")
|
||||||
.units(16)
|
.units(16)
|
||||||
.names(vec!["rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi"])
|
.names(vec!["rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi"])
|
||||||
@@ -10,11 +15,6 @@ pub(crate) fn define() -> IsaRegs {
|
|||||||
.pinned_reg(15);
|
.pinned_reg(15);
|
||||||
let int_regs = regs.add_bank(builder);
|
let int_regs = regs.add_bank(builder);
|
||||||
|
|
||||||
let builder = RegBankBuilder::new("FloatRegs", "xmm")
|
|
||||||
.units(16)
|
|
||||||
.track_pressure(true);
|
|
||||||
let float_regs = regs.add_bank(builder);
|
|
||||||
|
|
||||||
let builder = RegBankBuilder::new("FlagRegs", "")
|
let builder = RegBankBuilder::new("FlagRegs", "")
|
||||||
.units(1)
|
.units(1)
|
||||||
.names(vec!["rflags"])
|
.names(vec!["rflags"])
|
||||||
@@ -24,7 +24,10 @@ pub(crate) fn define() -> IsaRegs {
|
|||||||
let builder = RegClassBuilder::new_toplevel("GPR", int_regs);
|
let builder = RegClassBuilder::new_toplevel("GPR", int_regs);
|
||||||
let gpr = regs.add_class(builder);
|
let gpr = regs.add_class(builder);
|
||||||
|
|
||||||
let builder = RegClassBuilder::new_toplevel("FPR", float_regs);
|
let builder = RegClassBuilder::new_toplevel("FPR32", float_regs);
|
||||||
|
let fpr32 = regs.add_class(builder);
|
||||||
|
|
||||||
|
let builder = RegClassBuilder::subclass_of("FPR", fpr32, 0, 16);
|
||||||
let fpr = regs.add_class(builder);
|
let fpr = regs.add_class(builder);
|
||||||
|
|
||||||
let builder = RegClassBuilder::new_toplevel("FLAG", flag_reg);
|
let builder = RegClassBuilder::new_toplevel("FLAG", flag_reg);
|
||||||
|
|||||||
@@ -12,40 +12,61 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn unit_encodings() {
|
fn unit_encodings() {
|
||||||
|
fn gpr(unit: usize) -> Option<u16> {
|
||||||
|
Some(GPR.unit(unit))
|
||||||
|
}
|
||||||
// The encoding of integer registers is not alphabetical.
|
// The encoding of integer registers is not alphabetical.
|
||||||
assert_eq!(INFO.parse_regunit("rax"), Some(0));
|
assert_eq!(INFO.parse_regunit("rax"), gpr(0));
|
||||||
assert_eq!(INFO.parse_regunit("rbx"), Some(3));
|
assert_eq!(INFO.parse_regunit("rbx"), gpr(3));
|
||||||
assert_eq!(INFO.parse_regunit("rcx"), Some(1));
|
assert_eq!(INFO.parse_regunit("rcx"), gpr(1));
|
||||||
assert_eq!(INFO.parse_regunit("rdx"), Some(2));
|
assert_eq!(INFO.parse_regunit("rdx"), gpr(2));
|
||||||
assert_eq!(INFO.parse_regunit("rsi"), Some(6));
|
assert_eq!(INFO.parse_regunit("rsi"), gpr(6));
|
||||||
assert_eq!(INFO.parse_regunit("rdi"), Some(7));
|
assert_eq!(INFO.parse_regunit("rdi"), gpr(7));
|
||||||
assert_eq!(INFO.parse_regunit("rbp"), Some(5));
|
assert_eq!(INFO.parse_regunit("rbp"), gpr(5));
|
||||||
assert_eq!(INFO.parse_regunit("rsp"), Some(4));
|
assert_eq!(INFO.parse_regunit("rsp"), gpr(4));
|
||||||
assert_eq!(INFO.parse_regunit("r8"), Some(8));
|
assert_eq!(INFO.parse_regunit("r8"), gpr(8));
|
||||||
assert_eq!(INFO.parse_regunit("r15"), Some(15));
|
assert_eq!(INFO.parse_regunit("r15"), gpr(15));
|
||||||
|
|
||||||
assert_eq!(INFO.parse_regunit("xmm0"), Some(16));
|
fn fpr(unit: usize) -> Option<u16> {
|
||||||
assert_eq!(INFO.parse_regunit("xmm15"), Some(31));
|
Some(FPR.unit(unit))
|
||||||
|
}
|
||||||
|
assert_eq!(INFO.parse_regunit("xmm0"), fpr(0));
|
||||||
|
assert_eq!(INFO.parse_regunit("xmm15"), fpr(15));
|
||||||
|
|
||||||
|
fn fpr32(unit: usize) -> Option<u16> {
|
||||||
|
Some(FPR32.unit(unit))
|
||||||
|
}
|
||||||
|
assert_eq!(INFO.parse_regunit("xmm0"), fpr32(0));
|
||||||
|
assert_eq!(INFO.parse_regunit("xmm31"), fpr32(31));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn unit_names() {
|
fn unit_names() {
|
||||||
fn uname(ru: RegUnit) -> String {
|
fn gpr(ru: RegUnit) -> String {
|
||||||
INFO.display_regunit(ru).to_string()
|
INFO.display_regunit(GPR.first + ru).to_string()
|
||||||
}
|
}
|
||||||
|
assert_eq!(gpr(0), "%rax");
|
||||||
|
assert_eq!(gpr(3), "%rbx");
|
||||||
|
assert_eq!(gpr(1), "%rcx");
|
||||||
|
assert_eq!(gpr(2), "%rdx");
|
||||||
|
assert_eq!(gpr(6), "%rsi");
|
||||||
|
assert_eq!(gpr(7), "%rdi");
|
||||||
|
assert_eq!(gpr(5), "%rbp");
|
||||||
|
assert_eq!(gpr(4), "%rsp");
|
||||||
|
assert_eq!(gpr(8), "%r8");
|
||||||
|
assert_eq!(gpr(15), "%r15");
|
||||||
|
|
||||||
assert_eq!(uname(0), "%rax");
|
fn fpr(ru: RegUnit) -> String {
|
||||||
assert_eq!(uname(3), "%rbx");
|
INFO.display_regunit(FPR.first + ru).to_string()
|
||||||
assert_eq!(uname(1), "%rcx");
|
}
|
||||||
assert_eq!(uname(2), "%rdx");
|
assert_eq!(fpr(0), "%xmm0");
|
||||||
assert_eq!(uname(6), "%rsi");
|
assert_eq!(fpr(15), "%xmm15");
|
||||||
assert_eq!(uname(7), "%rdi");
|
|
||||||
assert_eq!(uname(5), "%rbp");
|
fn fpr32(ru: RegUnit) -> String {
|
||||||
assert_eq!(uname(4), "%rsp");
|
INFO.display_regunit(FPR32.first + ru).to_string()
|
||||||
assert_eq!(uname(8), "%r8");
|
}
|
||||||
assert_eq!(uname(15), "%r15");
|
assert_eq!(fpr32(0), "%xmm0");
|
||||||
assert_eq!(uname(16), "%xmm0");
|
assert_eq!(fpr32(31), "%xmm31");
|
||||||
assert_eq!(uname(31), "%xmm15");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|||||||
Reference in New Issue
Block a user