Add Intel call/return encodings.
This commit is contained in:
@@ -8,6 +8,9 @@ isa intel
|
||||
;
|
||||
|
||||
function %I32() {
|
||||
fn0 = function %foo()
|
||||
sig0 = signature()
|
||||
|
||||
ebb0:
|
||||
; asm: movl $1, %ecx
|
||||
[-,%rcx] v1 = iconst.i32 1 ; bin: b9 00000001
|
||||
@@ -199,5 +202,14 @@ ebb0:
|
||||
; asm: movsbl -50000(%esi), %edx
|
||||
[-,%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
|
||||
}
|
||||
|
||||
@@ -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.ldDisp8(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))
|
||||
|
||||
@@ -5,6 +5,7 @@ from __future__ import absolute_import
|
||||
from cdsl.isa import EncRecipe
|
||||
from cdsl.predicates import IsSignedInt, IsEqual
|
||||
from base.formats import UnaryImm, Binary, BinaryImm, Store, Load
|
||||
from base.formats import MultiAry, Call, IndirectCall
|
||||
from .registers import GPR, ABCD
|
||||
|
||||
try:
|
||||
@@ -206,3 +207,10 @@ ldDisp8 = TailRecipe(
|
||||
ldDisp32 = TailRecipe(
|
||||
'ldDisp32', Load, size=5, ins=(GPR), outs=(GPR),
|
||||
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=())
|
||||
|
||||
@@ -1,12 +1,24 @@
|
||||
//! Emitting binary Intel machine code.
|
||||
|
||||
use binemit::{CodeSink, bad_encoding};
|
||||
use binemit::{CodeSink, Reloc, bad_encoding};
|
||||
use ir::{Function, Inst, InstructionData};
|
||||
use isa::RegUnit;
|
||||
|
||||
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.
|
||||
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]);
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user