[codegen] Add a pinned register that's entirely under the control of the user;

This commit is contained in:
Benjamin Bouvier
2019-08-28 17:33:45 +02:00
parent d1d2e790b9
commit 660b8b28b8
15 changed files with 229 additions and 30 deletions

View File

@@ -372,6 +372,7 @@ pub(crate) fn define(
let fpromote = shared.by_name("fpromote");
let fsub = shared.by_name("fsub");
let func_addr = shared.by_name("func_addr");
let get_pinned_reg = shared.by_name("get_pinned_reg");
let iadd = shared.by_name("iadd");
let iadd_cout = shared.by_name("iadd_cout");
let iadd_cin = shared.by_name("iadd_cin");
@@ -421,6 +422,7 @@ pub(crate) fn define(
let scalar_to_vector = shared.by_name("scalar_to_vector");
let selectif = shared.by_name("selectif");
let sextend = shared.by_name("sextend");
let set_pinned_reg = shared.by_name("set_pinned_reg");
let sload16 = shared.by_name("sload16");
let sload16_complex = shared.by_name("sload16_complex");
let sload32 = shared.by_name("sload32");
@@ -516,6 +518,7 @@ pub(crate) fn define(
let rec_furm = r.template("furm");
let rec_furm_reg_to_ssa = r.template("furm_reg_to_ssa");
let rec_furmi_rnd = r.template("furmi_rnd");
let rec_get_pinned_reg = r.recipe("get_pinned_reg");
let rec_got_fnaddr8 = r.template("got_fnaddr8");
let rec_got_gvaddr8 = r.template("got_gvaddr8");
let rec_gvaddr4 = r.template("gvaddr4");
@@ -569,6 +572,7 @@ pub(crate) fn define(
let rec_safepoint = r.recipe("safepoint");
let rec_setf_abcd = r.template("setf_abcd");
let rec_seti_abcd = r.template("seti_abcd");
let rec_set_pinned_reg = r.template("set_pinned_reg");
let rec_spaddr4_id = r.template("spaddr4_id");
let rec_spaddr8_id = r.template("spaddr8_id");
let rec_spillSib32 = r.template("spillSib32");
@@ -619,6 +623,13 @@ pub(crate) fn define(
// Definitions.
let mut e = PerCpuModeEncodings::new();
// The pinned reg is fixed to a certain value entirely user-controlled, so it generates nothing!
e.enc64_rec(get_pinned_reg.bind(I64), rec_get_pinned_reg, 0);
e.enc_x86_64(
set_pinned_reg.bind(I64),
rec_set_pinned_reg.opcodes(vec![0x89]).rex().w(),
);
e.enc_i32_i64(iadd, rec_rr.opcodes(vec![0x01]));
e.enc_i32_i64(iadd_cout, rec_rr.opcodes(vec![0x01]));
e.enc_i32_i64(iadd_cin, rec_rin.opcodes(vec![0x11]));

View File

@@ -351,6 +351,7 @@ pub(crate) fn define<'shared>(
let reg_rax = Register::new(gpr, regs.regunit_by_name(gpr, "rax"));
let reg_rcx = Register::new(gpr, regs.regunit_by_name(gpr, "rcx"));
let reg_rdx = Register::new(gpr, regs.regunit_by_name(gpr, "rdx"));
let reg_r15 = Register::new(gpr, regs.regunit_by_name(gpr, "r15"));
// Stack operand with a 32-bit signed displacement from either RBP or RSP.
let stack_gpr32 = Stack::new(gpr);
@@ -428,6 +429,25 @@ pub(crate) fn define<'shared>(
.emit(""),
);
recipes.add_recipe(
EncodingRecipeBuilder::new("get_pinned_reg", f_nullary, 0)
.operands_out(vec![reg_r15])
.emit(""),
);
// umr with a fixed register output that's r15.
recipes.add_template_recipe(
EncodingRecipeBuilder::new("set_pinned_reg", f_unary, 1)
.operands_in(vec![gpr])
.clobbers_flags(false)
.emit(
r#"
let r15 = RU::r15.into();
{{PUT_OP}}(bits, rex2(r15, in_reg0), sink);
modrm_rr(r15, in_reg0, sink);
"#,
),
);
// No-op fills, created by late-stage redundant-fill removal.
recipes.add_recipe(
EncodingRecipeBuilder::new("fillnull", f_unary, 0)

View File

@@ -6,7 +6,8 @@ pub fn define() -> IsaRegs {
let builder = RegBankBuilder::new("IntRegs", "r")
.units(16)
.names(vec!["rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi"])
.track_pressure(true);
.track_pressure(true)
.pinned_reg(15);
let int_regs = regs.add_bank(builder);
let builder = RegBankBuilder::new("FloatRegs", "xmm")