Add Intel call/return encodings.

This commit is contained in:
Jakob Stoklund Olesen
2017-06-30 12:21:36 -07:00
parent 3608be35a9
commit 1a24489a0e
4 changed files with 64 additions and 3 deletions

View File

@@ -8,6 +8,9 @@ isa intel
; ;
function %I32() { function %I32() {
fn0 = function %foo()
sig0 = signature()
ebb0: ebb0:
; asm: movl $1, %ecx ; asm: movl $1, %ecx
[-,%rcx] v1 = iconst.i32 1 ; bin: b9 00000001 [-,%rcx] v1 = iconst.i32 1 ; bin: b9 00000001
@@ -199,5 +202,14 @@ ebb0:
; asm: movsbl -50000(%esi), %edx ; asm: movsbl -50000(%esi), %edx
[-,%rdx] v129 = sload8.i32 v2-50000 ; bin: 0f be 96 ffff3cb0 [-,%rdx] v129 = sload8.i32 v2-50000 ; bin: 0f be 96 ffff3cb0
return ; asm: call foo
call fn0() ; bin: e8 PCRel4(fn0) 00000000
; asm: call *%ecx
call_indirect sig0, v1() ; bin: ff d1
; asm: call *%esi
call_indirect sig0, v2() ; bin: ff d6
; asm: ret
return ; bin: c3
} }

View File

@@ -64,3 +64,10 @@ I32.enc(base.uload8.i32.i32, *r.ldDisp32(0x0f, 0xb6))
I32.enc(base.sload8.i32.i32, *r.ld(0x0f, 0xbe)) I32.enc(base.sload8.i32.i32, *r.ld(0x0f, 0xbe))
I32.enc(base.sload8.i32.i32, *r.ldDisp8(0x0f, 0xbe)) I32.enc(base.sload8.i32.i32, *r.ldDisp8(0x0f, 0xbe))
I32.enc(base.sload8.i32.i32, *r.ldDisp32(0x0f, 0xbe)) I32.enc(base.sload8.i32.i32, *r.ldDisp32(0x0f, 0xbe))
#
# Call/return
#
I32.enc(base.call, *r.call_id(0xe8))
I32.enc(base.call_indirect.i32, *r.call_r(0xff, rrr=2))
I32.enc(base.x_return, *r.ret(0xc3))

View File

@@ -5,6 +5,7 @@ from __future__ import absolute_import
from cdsl.isa import EncRecipe from cdsl.isa import EncRecipe
from cdsl.predicates import IsSignedInt, IsEqual from cdsl.predicates import IsSignedInt, IsEqual
from base.formats import UnaryImm, Binary, BinaryImm, Store, Load from base.formats import UnaryImm, Binary, BinaryImm, Store, Load
from base.formats import MultiAry, Call, IndirectCall
from .registers import GPR, ABCD from .registers import GPR, ABCD
try: try:
@@ -206,3 +207,10 @@ ldDisp8 = TailRecipe(
ldDisp32 = TailRecipe( ldDisp32 = TailRecipe(
'ldDisp32', Load, size=5, ins=(GPR), outs=(GPR), 'ldDisp32', Load, size=5, ins=(GPR), outs=(GPR),
instp=IsSignedInt(Load.offset, 32)) instp=IsSignedInt(Load.offset, 32))
#
# Call/return
#
call_id = TailRecipe('call_id', Call, size=4, ins=(), outs=())
call_r = TailRecipe('call_r', IndirectCall, size=1, ins=GPR, outs=())
ret = TailRecipe('ret', MultiAry, size=0, ins=(), outs=())

View File

@@ -1,12 +1,24 @@
//! Emitting binary Intel machine code. //! Emitting binary Intel machine code.
use binemit::{CodeSink, bad_encoding}; use binemit::{CodeSink, Reloc, bad_encoding};
use ir::{Function, Inst, InstructionData}; use ir::{Function, Inst, InstructionData};
use isa::RegUnit; use isa::RegUnit;
include!(concat!(env!("OUT_DIR"), "/binemit-intel.rs")); include!(concat!(env!("OUT_DIR"), "/binemit-intel.rs"));
pub static RELOC_NAMES: [&'static str; 1] = ["Call"]; /// Intel relocations.
pub enum RelocKind {
/// A 4-byte relative function reference. Based from relocation + 4 bytes.
PCRel4,
}
pub static RELOC_NAMES: [&'static str; 1] = ["PCRel4"];
impl Into<Reloc> for RelocKind {
fn into(self) -> Reloc {
Reloc(self as u16)
}
}
// Emit single-byte opcode. // Emit single-byte opcode.
fn put_op1<CS: CodeSink + ?Sized>(bits: u16, sink: &mut CS) { fn put_op1<CS: CodeSink + ?Sized>(bits: u16, sink: &mut CS) {
@@ -310,3 +322,25 @@ fn recipe_op2lddisp32<CS: CodeSink + ?Sized>(func: &Function, inst: Inst, sink:
panic!("Expected Load format: {:?}", func.dfg[inst]); panic!("Expected Load format: {:?}", func.dfg[inst]);
} }
} }
fn recipe_op1call_id<CS: CodeSink + ?Sized>(func: &Function, inst: Inst, sink: &mut CS) {
if let InstructionData::Call { func_ref, .. } = func.dfg[inst] {
put_op1(func.encodings[inst].bits(), sink);
sink.reloc_func(RelocKind::PCRel4.into(), func_ref);
sink.put4(0);
} else {
panic!("Expected Call format: {:?}", func.dfg[inst]);
}
}
fn recipe_op1call_r<CS: CodeSink + ?Sized>(func: &Function, inst: Inst, sink: &mut CS) {
let bits = func.encodings[inst].bits();
put_op1(bits, sink);
modrm_r_bits(func.locations[func.dfg.inst_args(inst)[0]].unwrap_reg(),
bits,
sink);
}
fn recipe_op1ret<CS: CodeSink + ?Sized>(func: &Function, inst: Inst, sink: &mut CS) {
put_op1(func.encodings[inst].bits(), sink);
}