1- //! Encodes instructions in the standard x86 encoding mode. This is called IA-32E mode in the Intel
2- //! manuals but corresponds to the addition of the REX-prefix format (hence the name of this module)
3- //! that allowed encoding instructions in both compatibility mode (32-bit instructions running on a
1+ //! Encodes instructions in the standard x86 encoding mode. This is called
2+ //! IA-32E mode in the Intel manuals but corresponds to the addition of the
3+ //! REX-prefix format (hence the name of this module) that allowed encoding
4+ //! instructions in both compatibility mode (32-bit instructions running on a
45//! 64-bit OS) and in 64-bit mode (using the full 64-bit address space).
56//!
6- //! For all of the routines that take both a memory-or-reg operand (sometimes called "E" in the
7- //! Intel documentation, see the Intel Developer's manual, vol. 2, section A.2) and a reg-only
8- //! operand ("G" in Intelese), the order is always G first, then E. The term "enc" in the following
9- //! means "hardware register encoding number".
10-
11- use crate :: machinst:: { Reg , RegClass } ;
12- use crate :: {
13- isa:: x64:: inst:: {
14- args:: { Amode , OperandSize } ,
15- regs, Inst , LabelUse ,
16- } ,
17- machinst:: MachBuffer ,
18- } ;
7+ //! For all of the routines that take both a memory-or-reg operand (sometimes
8+ //! called "E" in the Intel documentation, see the Intel Developer's manual,
9+ //! vol. 2, section A.2) and a reg-only operand ("G" in Intel-ese), the order is
10+ //! always G first, then E. The term "enc" in the following means "hardware
11+ //! register encoding number".
12+
13+ use super :: ByteSink ;
14+ use crate :: isa:: x64:: inst:: args:: { Amode , OperandSize } ;
15+ use crate :: isa:: x64:: inst:: { regs, Inst , LabelUse } ;
16+ use crate :: machinst:: { MachBuffer , Reg , RegClass } ;
1917
2018pub ( crate ) fn low8_will_sign_extend_to_64 ( x : u32 ) -> bool {
2119 let xs = ( x as i32 ) as i64 ;
@@ -81,13 +79,25 @@ impl RexFlags {
8179 Self ( 1 )
8280 }
8381
82+ /// True if 64-bit operands are used.
83+ #[ inline( always) ]
84+ pub fn must_clear_w ( & self ) -> bool {
85+ ( self . 0 & 1 ) != 0
86+ }
87+
8488 /// Require that the REX prefix is emitted.
8589 #[ inline( always) ]
8690 pub fn always_emit ( & mut self ) -> & mut Self {
8791 self . 0 = self . 0 | 2 ;
8892 self
8993 }
9094
95+ /// True if the REX prefix must always be emitted.
96+ #[ inline( always) ]
97+ pub fn must_always_emit ( & self ) -> bool {
98+ ( self . 0 & 2 ) != 0
99+ }
100+
91101 /// Emit the rex prefix if the referenced register would require it for 8-bit operations.
92102 #[ inline( always) ]
93103 pub fn always_emit_if_8bit_needed ( & mut self , reg : Reg ) -> & mut Self {
@@ -98,21 +108,9 @@ impl RexFlags {
98108 self
99109 }
100110
101- /// True if 64-bit operands are used.
102- #[ inline( always) ]
103- pub fn must_clear_w ( & self ) -> bool {
104- ( self . 0 & 1 ) != 0
105- }
106-
107- /// True if the REX prefix must always be emitted.
108- #[ inline( always) ]
109- pub fn must_always_emit ( & self ) -> bool {
110- ( self . 0 & 2 ) != 0
111- }
112-
113111 /// Emit a unary instruction.
114112 #[ inline( always) ]
115- pub fn emit_one_op ( & self , sink : & mut MachBuffer < Inst > , enc_e : u8 ) {
113+ pub fn emit_one_op < BS : ByteSink + ? Sized > ( & self , sink : & mut BS , enc_e : u8 ) {
116114 // Register Operand coded in Opcode Byte
117115 // REX.R and REX.X unused
118116 // REX.B == 1 accesses r8-r15
@@ -128,7 +126,7 @@ impl RexFlags {
128126
129127 /// Emit a binary instruction.
130128 #[ inline( always) ]
131- pub fn emit_two_op ( & self , sink : & mut MachBuffer < Inst > , enc_g : u8 , enc_e : u8 ) {
129+ pub fn emit_two_op < BS : ByteSink + ? Sized > ( & self , sink : & mut BS , enc_g : u8 , enc_e : u8 ) {
132130 let w = if self . must_clear_w ( ) { 0 } else { 1 } ;
133131 let r = ( enc_g >> 3 ) & 1 ;
134132 let x = 0 ;
@@ -141,9 +139,9 @@ impl RexFlags {
141139
142140 /// Emit a ternary instruction.
143141 #[ inline( always) ]
144- pub fn emit_three_op (
142+ pub fn emit_three_op < BS : ByteSink + ? Sized > (
145143 & self ,
146- sink : & mut MachBuffer < Inst > ,
144+ sink : & mut BS ,
147145 enc_g : u8 ,
148146 enc_index : u8 ,
149147 enc_base : u8 ,
@@ -232,7 +230,7 @@ pub enum LegacyPrefixes {
232230impl LegacyPrefixes {
233231 /// Emit the legacy prefix as bytes (e.g. in REX instructions).
234232 #[ inline( always) ]
235- pub ( crate ) fn emit ( & self , sink : & mut MachBuffer < Inst > ) {
233+ pub ( crate ) fn emit < BS : ByteSink + ? Sized > ( & self , sink : & mut BS ) {
236234 match self {
237235 Self :: _66 => sink. put1 ( 0x66 ) ,
238236 Self :: _F0 => sink. put1 ( 0xF0 ) ,
@@ -501,7 +499,7 @@ impl Imm {
501499 }
502500 }
503501
504- fn emit ( & self , sink : & mut MachBuffer < Inst > ) {
502+ fn emit < BS : ByteSink + ? Sized > ( & self , sink : & mut BS ) {
505503 match self {
506504 Imm :: None => { }
507505 Imm :: Imm8 ( n) => sink. put1 ( * n as u8 ) ,
@@ -514,8 +512,8 @@ impl Imm {
514512///
515513/// This is conceptually the same as emit_modrm_sib_enc_ge, except it is for the case where the E
516514/// operand is a register rather than memory. Hence it is much simpler.
517- pub ( crate ) fn emit_std_enc_enc (
518- sink : & mut MachBuffer < Inst > ,
515+ pub ( crate ) fn emit_std_enc_enc < BS : ByteSink + ? Sized > (
516+ sink : & mut BS ,
519517 prefixes : LegacyPrefixes ,
520518 opcodes : u32 ,
521519 mut num_opcodes : usize ,
@@ -571,8 +569,8 @@ pub(crate) fn emit_std_reg_mem(
571569 ) ;
572570}
573571
574- pub ( crate ) fn emit_std_reg_reg (
575- sink : & mut MachBuffer < Inst > ,
572+ pub ( crate ) fn emit_std_reg_reg < BS : ByteSink + ? Sized > (
573+ sink : & mut BS ,
576574 prefixes : LegacyPrefixes ,
577575 opcodes : u32 ,
578576 num_opcodes : usize ,
@@ -586,7 +584,7 @@ pub(crate) fn emit_std_reg_reg(
586584}
587585
588586/// Write a suitable number of bits from an imm64 to the sink.
589- pub ( crate ) fn emit_simm ( sink : & mut MachBuffer < Inst > , size : u8 , simm32 : u32 ) {
587+ pub ( crate ) fn emit_simm < BS : ByteSink + ? Sized > ( sink : & mut BS , size : u8 , simm32 : u32 ) {
590588 match size {
591589 8 | 4 => sink. put4 ( simm32) ,
592590 2 => sink. put2 ( simm32 as u16 ) ,
0 commit comments