From 116acb8dcd2eae56bd4f928cfe41e34d9c096e1e Mon Sep 17 00:00:00 2001 From: Benjamin Bouvier Date: Wed, 7 Oct 2020 14:05:35 +0200 Subject: [PATCH] machinst x64: emit nop of variable sizes; --- cranelift/codegen/src/isa/x64/inst/emit.rs | 83 ++++++++++++++++++++-- cranelift/codegen/src/isa/x64/inst/mod.rs | 2 +- 2 files changed, 80 insertions(+), 5 deletions(-) diff --git a/cranelift/codegen/src/isa/x64/inst/emit.rs b/cranelift/codegen/src/isa/x64/inst/emit.rs index e94c100839..bd7b9d4426 100644 --- a/cranelift/codegen/src/isa/x64/inst/emit.rs +++ b/cranelift/codegen/src/isa/x64/inst/emit.rs @@ -2720,10 +2720,85 @@ pub(crate) fn emit( } Inst::Nop { len } => { - if *len == 0 { - // Nothing to emit. - } else { - unimplemented!("non-zero nop opcodes."); + // These encodings can all be found in Intel's architecture manual, at the NOP + // instruction description. + let mut len = *len; + while len != 0 { + let emitted = u8::min(len, 9); + match emitted { + 0 => {} + 1 => sink.put1(0x90), // NOP + 2 => { + // 66 NOP + sink.put1(0x66); + sink.put1(0x90); + } + 3 => { + // NOP [EAX] + sink.put1(0x0F); + sink.put1(0x1F); + sink.put1(0x00); + } + 4 => { + // NOP 0(EAX), with 0 a 1-byte immediate. + sink.put1(0x0F); + sink.put1(0x1F); + sink.put1(0x40); + sink.put1(0x00); + } + 5 => { + // NOP [EAX, EAX, 1] + sink.put1(0x0F); + sink.put1(0x1F); + sink.put1(0x44); + sink.put1(0x00); + sink.put1(0x00); + } + 6 => { + // 66 NOP [EAX, EAX, 1] + sink.put1(0x66); + sink.put1(0x0F); + sink.put1(0x1F); + sink.put1(0x44); + sink.put1(0x00); + sink.put1(0x00); + } + 7 => { + // NOP 0[EAX], but 0 is a 4 bytes immediate. + sink.put1(0x0F); + sink.put1(0x1F); + sink.put1(0x80); + sink.put1(0x00); + sink.put1(0x00); + sink.put1(0x00); + sink.put1(0x00); + } + 8 => { + // NOP 0[EAX, EAX, 1], with 0 a 4 bytes immediate. + sink.put1(0x0F); + sink.put1(0x1F); + sink.put1(0x84); + sink.put1(0x00); + sink.put1(0x00); + sink.put1(0x00); + sink.put1(0x00); + sink.put1(0x00); + } + 9 => { + // 66 NOP 0[EAX, EAX, 1], with 0 a 4 bytes immediate. + sink.put1(0x66); + sink.put1(0x0F); + sink.put1(0x1F); + sink.put1(0x84); + sink.put1(0x00); + sink.put1(0x00); + sink.put1(0x00); + sink.put1(0x00); + sink.put1(0x00); + } + _ => unreachable!(), + } + len -= emitted; } } diff --git a/cranelift/codegen/src/isa/x64/inst/mod.rs b/cranelift/codegen/src/isa/x64/inst/mod.rs index 58c2cb66cc..5d4c409fda 100644 --- a/cranelift/codegen/src/isa/x64/inst/mod.rs +++ b/cranelift/codegen/src/isa/x64/inst/mod.rs @@ -2487,7 +2487,7 @@ impl MachInst for Inst { } fn gen_nop(preferred_size: usize) -> Inst { - Inst::nop(preferred_size as u8) + Inst::nop((preferred_size % 16) as u8) } fn maybe_direct_reload(&self, _reg: VirtualReg, _slot: SpillSlot) -> Option {