AArch64 Ruby immediates (https://github.com/Shopify/ruby/pull/400)
This commit is contained in:
parent
c022a60540
commit
be730cdae5
@ -187,16 +187,25 @@ impl Assembler
|
|||||||
let mut iterator = self.into_draining_iter();
|
let mut iterator = self.into_draining_iter();
|
||||||
|
|
||||||
while let Some((index, insn)) = iterator.next_mapped() {
|
while let Some((index, insn)) = iterator.next_mapped() {
|
||||||
let opnds = match insn.op {
|
// Here we're going to map the operands of the instruction to load
|
||||||
Op::Load => insn.opnds,
|
// any Opnd::Value operands into registers if they are heap objects
|
||||||
_ => insn.opnds.into_iter().map(|opnd| {
|
// such that only the Op::Load instruction needs to handle that
|
||||||
if let Opnd::Value(_) = opnd {
|
// case. If the values aren't heap objects then we'll treat them as
|
||||||
asm.load(opnd)
|
// if they were just unsigned integer.
|
||||||
} else {
|
let opnds: Vec<Opnd> = insn.opnds.into_iter().map(|opnd| {
|
||||||
opnd
|
match opnd {
|
||||||
}
|
Opnd::Value(value) => {
|
||||||
}).collect()
|
if value.special_const_p() {
|
||||||
};
|
Opnd::UImm(value.as_u64())
|
||||||
|
} else if insn.op == Op::Load {
|
||||||
|
opnd
|
||||||
|
} else {
|
||||||
|
asm.load(opnd)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
_ => opnd
|
||||||
|
}
|
||||||
|
}).collect();
|
||||||
|
|
||||||
match insn.op {
|
match insn.op {
|
||||||
Op::Add => {
|
Op::Add => {
|
||||||
@ -652,6 +661,11 @@ impl Assembler
|
|||||||
ldur(cb, insn.out.into(), insn.opnds[0].into());
|
ldur(cb, insn.out.into(), insn.opnds[0].into());
|
||||||
},
|
},
|
||||||
Opnd::Value(value) => {
|
Opnd::Value(value) => {
|
||||||
|
// We dont need to check if it's a special const
|
||||||
|
// here because we only allow these operands to hit
|
||||||
|
// this point if they're not a special const.
|
||||||
|
assert!(!value.special_const_p());
|
||||||
|
|
||||||
// This assumes only load instructions can contain
|
// This assumes only load instructions can contain
|
||||||
// references to GC'd Value operands. If the value
|
// references to GC'd Value operands. If the value
|
||||||
// being loaded is a heap object, we'll report that
|
// being loaded is a heap object, we'll report that
|
||||||
@ -660,10 +674,8 @@ impl Assembler
|
|||||||
b(cb, A64Opnd::new_imm(1 + (SIZEOF_VALUE as i64) / 4));
|
b(cb, A64Opnd::new_imm(1 + (SIZEOF_VALUE as i64) / 4));
|
||||||
cb.write_bytes(&value.as_u64().to_le_bytes());
|
cb.write_bytes(&value.as_u64().to_le_bytes());
|
||||||
|
|
||||||
if !value.special_const_p() {
|
let ptr_offset: u32 = (cb.get_write_pos() as u32) - (SIZEOF_VALUE as u32);
|
||||||
let ptr_offset: u32 = (cb.get_write_pos() as u32) - (SIZEOF_VALUE as u32);
|
gc_offsets.push(ptr_offset);
|
||||||
gc_offsets.push(ptr_offset);
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
Opnd::None => {
|
Opnd::None => {
|
||||||
unreachable!("Attempted to load from None operand");
|
unreachable!("Attempted to load from None operand");
|
||||||
@ -985,6 +997,32 @@ mod tests {
|
|||||||
assert_eq!(16, cb.get_write_pos());
|
assert_eq!(16, cb.get_write_pos());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_emit_load_value_immediate() {
|
||||||
|
let (mut asm, mut cb) = setup_asm();
|
||||||
|
|
||||||
|
let opnd = asm.load(Opnd::Value(Qnil));
|
||||||
|
asm.store(Opnd::mem(64, SP, 0), opnd);
|
||||||
|
asm.compile_with_num_regs(&mut cb, 1);
|
||||||
|
|
||||||
|
// Assert that only two instructions were written since the value is an
|
||||||
|
// immediate.
|
||||||
|
assert_eq!(8, cb.get_write_pos());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_emit_load_value_non_immediate() {
|
||||||
|
let (mut asm, mut cb) = setup_asm();
|
||||||
|
|
||||||
|
let opnd = asm.load(Opnd::Value(VALUE(0xCAFECAFECAFE0000)));
|
||||||
|
asm.store(Opnd::mem(64, SP, 0), opnd);
|
||||||
|
asm.compile_with_num_regs(&mut cb, 1);
|
||||||
|
|
||||||
|
// Assert that five instructions were written since the value is not an
|
||||||
|
// immediate and needs to be loaded into a register.
|
||||||
|
assert_eq!(20, cb.get_write_pos());
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_emit_or() {
|
fn test_emit_or() {
|
||||||
let (mut asm, mut cb) = setup_asm();
|
let (mut asm, mut cb) = setup_asm();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user