diff --git a/cranelift/codegen/src/isa/x86/binemit.rs b/cranelift/codegen/src/isa/x86/binemit.rs index a92589e632..90ed8b7ef8 100644 --- a/cranelift/codegen/src/isa/x86/binemit.rs +++ b/cranelift/codegen/src/isa/x86/binemit.rs @@ -74,10 +74,15 @@ fn evex2(rm: RegUnit, reg: RegUnit) -> u8 { 0x00 | r_ | (b << 1) | (x << 2) | (r << 3) } -/// Determines whether a REX prefix should be emitted. +/// Determines whether a REX prefix should be emitted. A REX byte always has 0100 in bits 7:4; bits +/// 3:0 correspond to WRXB. W allows certain instructions to declare a 64-bit operand size; because +/// [needs_rex] is only used by [infer_rex] and we prevent [infer_rex] from using [w] in +/// [Template::build], we do not need to check again whether [w] forces an inferred REX prefix--it +/// always does and should be encoded like `.rex().w()`. The RXB are extension of ModR/M or SIB +/// fields; see section 2.2.1.2 in the Intel Software Development Manual. #[inline] -fn needs_rex(bits: u16, rex: u8) -> bool { - rex != BASE_REX || EncodingBits::from(bits).rex_w() == 1 +fn needs_rex(rex: u8) -> bool { + rex != BASE_REX } // Emit a REX prefix. @@ -107,7 +112,7 @@ fn put_rexop1(bits: u16, rex: u8, sink: &mut CS) { /// Emit a single-byte opcode with inferred REX prefix. fn put_dynrexop1(bits: u16, rex: u8, sink: &mut CS) { debug_assert_eq!(bits & 0x0f00, 0, "Invalid encoding bits for DynRexOp1*"); - if needs_rex(bits, rex) { + if needs_rex(rex) { rex_prefix(bits, rex, sink); } sink.put1(bits as u8); @@ -136,7 +141,7 @@ fn put_dynrexop2(bits: u16, rex: u8, sink: &mut CS) { 0x0400, "Invalid encoding bits for DynRexOp2*" ); - if needs_rex(bits, rex) { + if needs_rex(rex) { rex_prefix(bits, rex, sink); } sink.put1(0x0f); @@ -190,7 +195,7 @@ fn put_dynrexmp2(bits: u16, rex: u8, sink: &mut CS) { ); let enc = EncodingBits::from(bits); sink.put1(PREFIX[(enc.pp() - 1) as usize]); - if needs_rex(bits, rex) { + if needs_rex(rex) { rex_prefix(bits, rex, sink); } sink.put1(0x0f); @@ -228,7 +233,7 @@ fn put_dynrexmp3(bits: u16, rex: u8, sink: &mut CS) { ); let enc = EncodingBits::from(bits); sink.put1(PREFIX[(enc.pp() - 1) as usize]); - if needs_rex(bits, rex) { + if needs_rex(rex) { rex_prefix(bits, rex, sink); } sink.put1(0x0f);