From 1a24489a0e185a28b2a265590b8caa1957f84d2a Mon Sep 17 00:00:00 2001 From: Jakob Stoklund Olesen Date: Fri, 30 Jun 2017 12:21:36 -0700 Subject: [PATCH] Add Intel call/return encodings. --- filetests/isa/intel/binary32.cton | 14 ++++++++- lib/cretonne/meta/isa/intel/encodings.py | 7 +++++ lib/cretonne/meta/isa/intel/recipes.py | 8 +++++ lib/cretonne/src/isa/intel/binemit.rs | 38 ++++++++++++++++++++++-- 4 files changed, 64 insertions(+), 3 deletions(-) diff --git a/filetests/isa/intel/binary32.cton b/filetests/isa/intel/binary32.cton index 6d13844497..2e42d01fcc 100644 --- a/filetests/isa/intel/binary32.cton +++ b/filetests/isa/intel/binary32.cton @@ -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 } diff --git a/lib/cretonne/meta/isa/intel/encodings.py b/lib/cretonne/meta/isa/intel/encodings.py index 4010ffb64a..c05308177a 100644 --- a/lib/cretonne/meta/isa/intel/encodings.py +++ b/lib/cretonne/meta/isa/intel/encodings.py @@ -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)) diff --git a/lib/cretonne/meta/isa/intel/recipes.py b/lib/cretonne/meta/isa/intel/recipes.py index 70377f8756..4e41c9b990 100644 --- a/lib/cretonne/meta/isa/intel/recipes.py +++ b/lib/cretonne/meta/isa/intel/recipes.py @@ -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=()) diff --git a/lib/cretonne/src/isa/intel/binemit.rs b/lib/cretonne/src/isa/intel/binemit.rs index aded1e41e6..001a41e009 100644 --- a/lib/cretonne/src/isa/intel/binemit.rs +++ b/lib/cretonne/src/isa/intel/binemit.rs @@ -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 for RelocKind { + fn into(self) -> Reloc { + Reloc(self as u16) + } +} // Emit single-byte opcode. fn put_op1(bits: u16, sink: &mut CS) { @@ -310,3 +322,25 @@ fn recipe_op2lddisp32(func: &Function, inst: Inst, sink: panic!("Expected Load format: {:?}", func.dfg[inst]); } } + +fn recipe_op1call_id(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(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(func: &Function, inst: Inst, sink: &mut CS) { + put_op1(func.encodings[inst].bits(), sink); +}