Add const_addr instruction

This new instruction calculates the effective address of a constant in the constant pool using LEA (x86).
This commit is contained in:
Andrew Brown
2020-03-20 14:15:47 -07:00
parent fa35d88878
commit 65856987cd
4 changed files with 44 additions and 0 deletions

View File

@@ -2179,6 +2179,7 @@ fn define_entity_ref(
let formats = &shared_defs.formats;
// Shorthands for instructions.
let const_addr = shared.by_name("const_addr");
let func_addr = shared.by_name("func_addr");
let stack_addr = shared.by_name("stack_addr");
let symbol_value = shared.by_name("symbol_value");
@@ -2188,6 +2189,7 @@ fn define_entity_ref(
let rec_allones_fnaddr8 = r.template("allones_fnaddr8");
let rec_fnaddr4 = r.template("fnaddr4");
let rec_fnaddr8 = r.template("fnaddr8");
let rec_const_addr = r.template("const_addr");
let rec_got_fnaddr8 = r.template("got_fnaddr8");
let rec_got_gvaddr8 = r.template("got_gvaddr8");
let rec_gvaddr4 = r.template("gvaddr4");
@@ -2285,6 +2287,10 @@ fn define_entity_ref(
// don't get legalized to stack_addr + load/store.
e.enc32(stack_addr.bind(I32), rec_spaddr4_id.opcodes(&LEA));
e.enc64(stack_addr.bind(I64), rec_spaddr8_id.opcodes(&LEA).rex().w());
// Constant addresses (PIC).
e.enc64(const_addr.bind(I64), rec_const_addr.opcodes(&LEA).rex().w());
e.enc32(const_addr.bind(I32), rec_const_addr.opcodes(&LEA));
}
/// Control flow opcodes.

View File

@@ -1463,6 +1463,21 @@ pub(crate) fn define<'shared>(
),
);
// Constant addresses.
recipes.add_template_recipe(
EncodingRecipeBuilder::new("const_addr", &formats.unary_const, 5)
.operands_out(vec![gpr])
.clobbers_flags(false)
.emit(
r#"
{{PUT_OP}}(bits, rex2(0, out_reg0), sink);
modrm_riprel(out_reg0, sink);
const_disp4(constant_handle, func, sink);
"#,
),
);
// Store recipes.
{

View File

@@ -1542,6 +1542,21 @@ pub(crate) fn define(
.operands_out(vec![a]),
);
let constant =
&Operand::new("constant", &imm.pool_constant).with_doc("A constant in the constant pool");
let address = &Operand::new("address", iAddr);
ig.push(
Inst::new(
"const_addr",
r#"
Calculate the base address of a value in the constant pool.
"#,
&formats.unary_const,
)
.operands_in(vec![constant])
.operands_out(vec![address]),
);
let mask = &Operand::new("mask", &imm.uimm128)
.with_doc("The 16 immediate bytes used for selecting the elements to shuffle");
let Tx16 = &TypeVar::new(

View File

@@ -19,3 +19,11 @@ block0:
[-, %xmm3] v1 = vconst.i32x4 const43 ; bin: 0f 10 1d 00000011 PCRelRodata4(31)
return
}
function %address_of_vconst() {
const42 = i32x4 [1 0 0 0]
block0:
[-, %rax] v0 = const_addr.i64 const42 ; bin: 48 8d 05 00000001 PCRelRodata4(8)
return
}