From 5289cbf5331dfd0d0c2242a7e7c8030aa4032c7e Mon Sep 17 00:00:00 2001 From: johannst Date: Sat, 7 Dec 2024 01:01:45 +0000 Subject: deploy: 9c3c3fd923d894d2351eb22129ea693eb98fa8ff --- src/juicebox_asm/asm.rs.html | 281 +++++++++++++++++++++++++++++++---- src/juicebox_asm/imm.rs.html | 9 +- src/juicebox_asm/insn.rs.html | 33 +++- src/juicebox_asm/insn/add.rs.html | 29 +++- src/juicebox_asm/insn/call.rs.html | 7 +- src/juicebox_asm/insn/cmovnz.rs.html | 7 +- src/juicebox_asm/insn/cmovz.rs.html | 7 +- src/juicebox_asm/insn/cmp.rs.html | 19 ++- src/juicebox_asm/insn/dec.rs.html | 55 ++++++- src/juicebox_asm/insn/inc.rs.html | 77 ++++++++++ src/juicebox_asm/insn/jmp.rs.html | 7 +- src/juicebox_asm/insn/jnz.rs.html | 7 +- src/juicebox_asm/insn/jz.rs.html | 7 +- src/juicebox_asm/insn/mov.rs.html | 7 +- src/juicebox_asm/insn/nop.rs.html | 7 +- src/juicebox_asm/insn/pop.rs.html | 7 +- src/juicebox_asm/insn/push.rs.html | 7 +- src/juicebox_asm/insn/ret.rs.html | 7 +- src/juicebox_asm/insn/test.rs.html | 7 +- src/juicebox_asm/insn/xor.rs.html | 17 +++ src/juicebox_asm/label.rs.html | 7 +- src/juicebox_asm/lib.rs.html | 119 ++++++++++++++- src/juicebox_asm/reg.rs.html | 11 +- src/juicebox_asm/rt.rs.html | 7 +- 24 files changed, 637 insertions(+), 111 deletions(-) create mode 100644 src/juicebox_asm/insn/inc.rs.html create mode 100644 src/juicebox_asm/insn/xor.rs.html (limited to 'src/juicebox_asm') diff --git a/src/juicebox_asm/asm.rs.html b/src/juicebox_asm/asm.rs.html index 4418397..3f24ae2 100644 --- a/src/juicebox_asm/asm.rs.html +++ b/src/juicebox_asm/asm.rs.html @@ -1,5 +1,5 @@ -asm.rs - source -
1
+asm.rs - source

juicebox_asm/
asm.rs

+1
 2
 3
 4
@@ -344,7 +344,120 @@
 343
 344
 345
-
//! The `x64` jit assembler.
+346
+347
+348
+349
+350
+351
+352
+353
+354
+355
+356
+357
+358
+359
+360
+361
+362
+363
+364
+365
+366
+367
+368
+369
+370
+371
+372
+373
+374
+375
+376
+377
+378
+379
+380
+381
+382
+383
+384
+385
+386
+387
+388
+389
+390
+391
+392
+393
+394
+395
+396
+397
+398
+399
+400
+401
+402
+403
+404
+405
+406
+407
+408
+409
+410
+411
+412
+413
+414
+415
+416
+417
+418
+419
+420
+421
+422
+423
+424
+425
+426
+427
+428
+429
+430
+431
+432
+433
+434
+435
+436
+437
+438
+439
+440
+441
+442
+443
+444
+445
+446
+447
+448
+449
+450
+451
+452
+453
+454
+455
+456
+457
+458
+459
//! The `x64` jit assembler.
 
 use crate::*;
 use imm::Imm;
@@ -364,6 +477,11 @@
     ((mod_ & 0b11) << 6) | ((reg & 0b111) << 3) | (rm & 0b111)
 }
 
+/// Encode the `SIB` byte.
+const fn sib(scale: u8, index: u8, base: u8) -> u8 {
+    ((scale & 0b11) << 6) | ((index & 0b111) << 3) | (base & 0b111)
+}
+
 /// `x64` jit assembler.
 pub struct Asm {
     buf: Vec<u8>,
@@ -495,6 +613,52 @@
         self.emit(&[opc, modrm]);
     }
 
+    /// Encode a memory operand instruction.
+    pub(crate) fn encode_m<T: MemOpSized>(&mut self, opc: u8, opc_ext: u8, op1: T)
+    where
+        Self: EncodeM<T>,
+    {
+        let op1 = op1.mem_op();
+
+        // M operand encoding.
+        //   op1 -> modrm.rm
+        let (mode, rm) = match op1 {
+            MemOp::Indirect(..) => {
+                assert!(!op1.base().need_sib() && !op1.base().is_pc_rel());
+                (0b00, op1.base().idx())
+            }
+            MemOp::IndirectDisp(..) => {
+                assert!(!op1.base().need_sib());
+                (0b10, op1.base().idx())
+            }
+            MemOp::IndirectBaseIndex(..) => {
+                assert!(!op1.base().is_pc_rel());
+                // Using rsp as index register is interpreted as just base w/o offset.
+                //   https://wiki.osdev.org/X86-64_Instruction_Encoding#32.2F64-bit_addressing_2
+                // Disallow this case, as guard for the user.
+                assert!(!matches!(op1.index(), Reg64::rsp));
+                (0b00, 0b100)
+            }
+        };
+
+        let modrm = modrm(
+            mode,    /* mode */
+            opc_ext, /* reg */
+            rm,      /* rm */
+        );
+
+        let prefix = <Self as EncodeM<T>>::legacy_prefix();
+        let rex = <Self as EncodeM<T>>::rex(&op1);
+
+        self.emit_optional(&[prefix, rex]);
+        self.emit(&[opc, modrm]);
+        match op1 {
+            MemOp::Indirect(..) => {}
+            MemOp::IndirectDisp(_, disp) => self.emit(&disp.to_ne_bytes()),
+            MemOp::IndirectBaseIndex(base, index) => self.emit(&[sib(0, index.idx(), base.idx())]),
+        }
+    }
+
     /// Encode a memory-immediate instruction.
     pub(crate) fn encode_mi<T: Imm>(&mut self, opc: u8, opc_ext: u8, op1: MemOp, op2: T)
     where
@@ -503,21 +667,29 @@
         // MI operand encoding.
         //   op1 -> modrm.rm
         //   op2 -> imm
-        let mode = match op1 {
+        let (mode, rm) = match op1 {
             MemOp::Indirect(..) => {
                 assert!(!op1.base().need_sib() && !op1.base().is_pc_rel());
-                0b00
-            }
+                (0b00, op1.base().idx())
+            }
             MemOp::IndirectDisp(..) => {
                 assert!(!op1.base().need_sib());
-                0b10
-            }
+                (0b10, op1.base().idx())
+            }
+            MemOp::IndirectBaseIndex(..) => {
+                assert!(!op1.base().is_pc_rel());
+                // Using rsp as index register is interpreted as just base w/o offset.
+                //   https://wiki.osdev.org/X86-64_Instruction_Encoding#32.2F64-bit_addressing_2
+                // Disallow this case, as guard for the user.
+                assert!(!matches!(op1.index(), Reg64::rsp));
+                (0b00, 0b100)
+            }
         };
 
         let modrm = modrm(
-            mode,             /* mode */
-            opc_ext,          /* reg */
-            op1.base().idx(), /* rm */
+            mode,    /* mode */
+            opc_ext, /* reg */
+            rm,      /* rm */
         );
 
         let prefix = <Self as EncodeMI<T>>::legacy_prefix();
@@ -525,8 +697,10 @@
 
         self.emit_optional(&[prefix, rex]);
         self.emit(&[opc, modrm]);
-        if let MemOp::IndirectDisp(_, disp) = op1 {
-            self.emit(&disp.to_ne_bytes());
+        match op1 {
+            MemOp::Indirect(..) => {}
+            MemOp::IndirectDisp(_, disp) => self.emit(&disp.to_ne_bytes()),
+            MemOp::IndirectBaseIndex(base, index) => self.emit(&[sib(0, index.idx(), base.idx())]),
         }
         self.emit(op2.bytes());
     }
@@ -539,29 +713,40 @@
         // MR operand encoding.
         //   op1 -> modrm.rm
         //   op2 -> modrm.reg
-        let mode = match op1 {
+        let (mode, rm) = match op1 {
             MemOp::Indirect(..) => {
                 assert!(!op1.base().need_sib() && !op1.base().is_pc_rel());
-                0b00
-            }
+                (0b00, op1.base().idx())
+            }
             MemOp::IndirectDisp(..) => {
                 assert!(!op1.base().need_sib());
-                0b10
-            }
+                (0b10, op1.base().idx())
+            }
+            MemOp::IndirectBaseIndex(..) => {
+                assert!(!op1.base().is_pc_rel());
+                // Using rsp as index register is interpreted as just base w/o offset.
+                //   https://wiki.osdev.org/X86-64_Instruction_Encoding#32.2F64-bit_addressing_2
+                // Disallow this case, as guard for the user.
+                assert!(!matches!(op1.index(), Reg64::rsp));
+                (0b00, 0b100)
+            }
         };
 
         let modrm = modrm(
-            mode,             /* mode */
-            op2.idx(),        /* reg */
-            op1.base().idx(), /* rm */
+            mode,      /* mode */
+            op2.idx(), /* reg */
+            rm,        /* rm */
         );
+
         let prefix = <Self as EncodeMR<T>>::legacy_prefix();
         let rex = <Self as EncodeMR<T>>::rex(&op1, op2);
 
         self.emit_optional(&[prefix, rex]);
         self.emit(&[opc, modrm]);
-        if let MemOp::IndirectDisp(_, disp) = op1 {
-            self.emit(&disp.to_ne_bytes());
+        match op1 {
+            MemOp::Indirect(..) => {}
+            MemOp::IndirectDisp(_, disp) => self.emit(&disp.to_ne_bytes()),
+            MemOp::IndirectBaseIndex(base, index) => self.emit(&[sib(0, index.idx(), base.idx())]),
         }
     }
 
@@ -650,8 +835,13 @@
     }
 
     fn rex(op1: &MemOp, op2: T) -> Option<u8> {
-        if op2.need_rex() || (op1.base().is_ext()) {
-            Some(rex(op2.rexw(), op2.idx(), 0, op1.base().idx()))
+        if op2.need_rex() || op1.base().is_ext() || op1.index().is_ext() {
+            Some(rex(
+                op2.rexw(),
+                op2.idx(),
+                op1.index().idx(),
+                op1.base().idx(),
+            ))
         } else {
             None
         }
@@ -674,8 +864,8 @@
     }
 
     fn rex(op1: &MemOp) -> Option<u8> {
-        if op1.base().is_ext() {
-            Some(rex(false, 0, 0, op1.base().idx()))
+        if op1.base().is_ext() || op1.index().is_ext() {
+            Some(rex(false, 0, op1.index().idx(), op1.base().idx()))
         } else {
             None
         }
@@ -689,4 +879,41 @@
     }
 }
 impl EncodeMI<Imm32> for Asm {}
+
+/// Encode helper for memory operand instructions.
+pub(crate) trait EncodeM<T: MemOpSized> {
+    fn legacy_prefix() -> Option<u8> {
+        None
+    }
+
+    fn rex(op1: &MemOp) -> Option<u8> {
+        if op1.base().is_ext() || op1.index().is_ext() || Self::is_64bit() {
+            Some(rex(
+                Self::is_64bit(),
+                0,
+                op1.index().idx(),
+                op1.base().idx(),
+            ))
+        } else {
+            None
+        }
+    }
+
+    fn is_64bit() -> bool {
+        false
+    }
+}
+
+impl EncodeM<MemOp8> for Asm {}
+impl EncodeM<MemOp16> for Asm {
+    fn legacy_prefix() -> Option<u8> {
+        Some(0x66)
+    }
+}
+impl EncodeM<MemOp32> for Asm {}
+impl EncodeM<MemOp64> for Asm {
+    fn is_64bit() -> bool {
+        true
+    }
+}
 
\ No newline at end of file diff --git a/src/juicebox_asm/imm.rs.html b/src/juicebox_asm/imm.rs.html index 306b800..5ddf841 100644 --- a/src/juicebox_asm/imm.rs.html +++ b/src/juicebox_asm/imm.rs.html @@ -1,5 +1,5 @@ -imm.rs - source -
1
+imm.rs - source

juicebox_asm/
imm.rs

+1
 2
 3
 4
@@ -61,8 +61,7 @@
 60
 61
 62
-63
-
//! Definition of different immediate types which are used as input operands for various
+63
//! Definition of different immediate types which are used as input operands for various
 //! instructions.
 
 /// Trait to interact with immediate operands.
@@ -71,7 +70,7 @@
     fn bytes(&self) -> &[u8];
 }
 
-macro_rules! impl_imm {
+macro_rules! impl_imm {
     (#[$doc:meta] $name:ident, $size:expr, from: { $( $from:ty ),* $(,)? }) => {
         #[$doc]
         pub struct $name([u8; $size]);
diff --git a/src/juicebox_asm/insn.rs.html b/src/juicebox_asm/insn.rs.html
index 029258c..b82f83d 100644
--- a/src/juicebox_asm/insn.rs.html
+++ b/src/juicebox_asm/insn.rs.html
@@ -1,5 +1,5 @@
-insn.rs - source
-    
1
+insn.rs - source

juicebox_asm/
insn.rs

+1
 2
 3
 4
@@ -102,7 +102,20 @@
 101
 102
 103
-
//! Trait definitions of various instructions.
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
//! Trait definitions of various instructions.
 
 mod add;
 mod call;
@@ -110,6 +123,7 @@
 mod cmovz;
 mod cmp;
 mod dec;
+mod inc;
 mod jmp;
 mod jnz;
 mod jz;
@@ -119,6 +133,7 @@
 mod push;
 mod ret;
 mod test;
+mod xor;
 
 /// Trait for [`add`](https://www.felixcloutier.com/x86/add) instruction kinds.
 pub trait Add<T, U> {
@@ -161,6 +176,12 @@
     fn dec(&mut self, op1: T);
 }
 
+/// Trait for [`inc`](https://www.felixcloutier.com/x86/inc) instruction kinds.
+pub trait Inc<T> {
+    /// Emit a increment instruction.
+    fn inc(&mut self, op1: T);
+}
+
 /// Trait for [`jmp`](https://www.felixcloutier.com/x86/jmp) instruction kinds.
 pub trait Jmp<T> {
     /// Emit an unconditional jump instruction.
@@ -205,4 +226,10 @@
     /// `SF`, `ZF`, and `PF` status flags, the result is discarded.
     fn test(&mut self, op1: T, op2: U);
 }
+
+/// Trait for [`xor`](https://www.felixcloutier.com/x86/xor) instruction kinds.
+pub trait Xor<T, U> {
+    /// Emit a xor instruction.
+    fn xor(&mut self, op1: T, op2: U);
+}
 
\ No newline at end of file diff --git a/src/juicebox_asm/insn/add.rs.html b/src/juicebox_asm/insn/add.rs.html index 6146498..e62bc4a 100644 --- a/src/juicebox_asm/insn/add.rs.html +++ b/src/juicebox_asm/insn/add.rs.html @@ -1,5 +1,5 @@ -add.rs - source -
1
+add.rs - source

juicebox_asm/insn/
add.rs

+1
 2
 3
 4
@@ -25,7 +25,18 @@
 24
 25
 26
-
use super::Add;
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
use super::Add;
 use crate::{Asm, Imm16, MemOp, Reg16, Reg32, Reg64};
 
 impl Add<Reg64, Reg64> for Asm {
@@ -40,6 +51,12 @@
     }
 }
 
+impl Add<MemOp, Reg64> for Asm {
+    fn add(&mut self, op1: MemOp, op2: Reg64) {
+        self.encode_mr(0x01, op1, op2);
+    }
+}
+
 impl Add<MemOp, Reg16> for Asm {
     fn add(&mut self, op1: MemOp, op2: Reg16) {
         self.encode_mr(0x01, op1, op2);
@@ -51,4 +68,10 @@
         self.encode_mi(0x81, 0, op1, op2);
     }
 }
+
+impl Add<Reg64, MemOp> for Asm {
+    fn add(&mut self, op1: Reg64, op2: MemOp) {
+        self.encode_rm(0x03, op1, op2);
+    }
+}
 
\ No newline at end of file diff --git a/src/juicebox_asm/insn/call.rs.html b/src/juicebox_asm/insn/call.rs.html index 3a70194..5f8ed48 100644 --- a/src/juicebox_asm/insn/call.rs.html +++ b/src/juicebox_asm/insn/call.rs.html @@ -1,13 +1,12 @@ -call.rs - source -
1
+call.rs - source

juicebox_asm/insn/
call.rs

+1
 2
 3
 4
 5
 6
 7
-8
-
use super::Call;
+8
use super::Call;
 use crate::{Asm, Reg64};
 
 impl Call<Reg64> for Asm {
diff --git a/src/juicebox_asm/insn/cmovnz.rs.html b/src/juicebox_asm/insn/cmovnz.rs.html
index 29bfb58..4e23126 100644
--- a/src/juicebox_asm/insn/cmovnz.rs.html
+++ b/src/juicebox_asm/insn/cmovnz.rs.html
@@ -1,13 +1,12 @@
-cmovnz.rs - source
-    
1
+cmovnz.rs - source

juicebox_asm/insn/
cmovnz.rs

+1
 2
 3
 4
 5
 6
 7
-8
-
use super::Cmovnz;
+8
use super::Cmovnz;
 use crate::{Asm, Reg64};
 
 impl Cmovnz<Reg64, Reg64> for Asm {
diff --git a/src/juicebox_asm/insn/cmovz.rs.html b/src/juicebox_asm/insn/cmovz.rs.html
index ecb62f1..a51f237 100644
--- a/src/juicebox_asm/insn/cmovz.rs.html
+++ b/src/juicebox_asm/insn/cmovz.rs.html
@@ -1,13 +1,12 @@
-cmovz.rs - source
-    
1
+cmovz.rs - source

juicebox_asm/insn/
cmovz.rs

+1
 2
 3
 4
 5
 6
 7
-8
-
use super::Cmovz;
+8
use super::Cmovz;
 use crate::{Asm, Reg64};
 
 impl Cmovz<Reg64, Reg64> for Asm {
diff --git a/src/juicebox_asm/insn/cmp.rs.html b/src/juicebox_asm/insn/cmp.rs.html
index c8bcee2..a4e5447 100644
--- a/src/juicebox_asm/insn/cmp.rs.html
+++ b/src/juicebox_asm/insn/cmp.rs.html
@@ -1,5 +1,5 @@
-cmp.rs - source
-    
1
+cmp.rs - source

juicebox_asm/insn/
cmp.rs

+1
 2
 3
 4
@@ -7,8 +7,19 @@
 6
 7
 8
-
use super::Cmp;
-use crate::{Asm, Imm16, MemOp};
+9
+10
+11
+12
+13
+14
use super::Cmp;
+use crate::{Asm, Imm16, Imm8, MemOp};
+
+impl Cmp<MemOp, Imm8> for Asm {
+    fn cmp(&mut self, op1: MemOp, op2: Imm8) {
+        self.encode_mi(0x80, 0x7, op1, op2);
+    }
+}
 
 impl Cmp<MemOp, Imm16> for Asm {
     fn cmp(&mut self, op1: MemOp, op2: Imm16) {
diff --git a/src/juicebox_asm/insn/dec.rs.html b/src/juicebox_asm/insn/dec.rs.html
index 1eed3b2..7a05154 100644
--- a/src/juicebox_asm/insn/dec.rs.html
+++ b/src/juicebox_asm/insn/dec.rs.html
@@ -1,5 +1,5 @@
-dec.rs - source
-    
1
+dec.rs - source

juicebox_asm/insn/
dec.rs

+1
 2
 3
 4
@@ -13,8 +13,31 @@
 12
 13
 14
-
use super::Dec;
-use crate::{Asm, Reg32, Reg64};
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
use super::Dec;
+use crate::{Asm, MemOp16, MemOp32, MemOp64, MemOp8, Reg32, Reg64};
 
 impl Dec<Reg64> for Asm {
     fn dec(&mut self, op1: Reg64) {
@@ -27,4 +50,28 @@
         self.encode_r(0xff, 1, op1);
     }
 }
+
+impl Dec<MemOp8> for Asm {
+    fn dec(&mut self, op1: MemOp8) {
+        self.encode_m(0xfe, 1, op1);
+    }
+}
+
+impl Dec<MemOp16> for Asm {
+    fn dec(&mut self, op1: MemOp16) {
+        self.encode_m(0xff, 1, op1);
+    }
+}
+
+impl Dec<MemOp32> for Asm {
+    fn dec(&mut self, op1: MemOp32) {
+        self.encode_m(0xff, 1, op1);
+    }
+}
+
+impl Dec<MemOp64> for Asm {
+    fn dec(&mut self, op1: MemOp64) {
+        self.encode_m(0xff, 1, op1);
+    }
+}
 
\ No newline at end of file diff --git a/src/juicebox_asm/insn/inc.rs.html b/src/juicebox_asm/insn/inc.rs.html new file mode 100644 index 0000000..05ce6bb --- /dev/null +++ b/src/juicebox_asm/insn/inc.rs.html @@ -0,0 +1,77 @@ +inc.rs - source

juicebox_asm/insn/
inc.rs

+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
use super::Inc;
+use crate::{Asm, MemOp16, MemOp32, MemOp64, MemOp8, Reg32, Reg64};
+
+impl Inc<Reg64> for Asm {
+    fn inc(&mut self, op1: Reg64) {
+        self.encode_r(0xff, 0, op1);
+    }
+}
+
+impl Inc<Reg32> for Asm {
+    fn inc(&mut self, op1: Reg32) {
+        self.encode_r(0xff, 0, op1);
+    }
+}
+
+impl Inc<MemOp8> for Asm {
+    fn inc(&mut self, op1: MemOp8) {
+        self.encode_m(0xfe, 0, op1);
+    }
+}
+
+impl Inc<MemOp16> for Asm {
+    fn inc(&mut self, op1: MemOp16) {
+        self.encode_m(0xff, 0, op1);
+    }
+}
+
+impl Inc<MemOp32> for Asm {
+    fn inc(&mut self, op1: MemOp32) {
+        self.encode_m(0xff, 0, op1);
+    }
+}
+
+impl Inc<MemOp64> for Asm {
+    fn inc(&mut self, op1: MemOp64) {
+        self.encode_m(0xff, 0, op1);
+    }
+}
+
\ No newline at end of file diff --git a/src/juicebox_asm/insn/jmp.rs.html b/src/juicebox_asm/insn/jmp.rs.html index 88f3066..75b3912 100644 --- a/src/juicebox_asm/insn/jmp.rs.html +++ b/src/juicebox_asm/insn/jmp.rs.html @@ -1,13 +1,12 @@ -jmp.rs - source -
1
+jmp.rs - source

juicebox_asm/insn/
jmp.rs

+1
 2
 3
 4
 5
 6
 7
-8
-
use super::Jmp;
+8
use super::Jmp;
 use crate::{Asm, Label};
 
 impl Jmp<&mut Label> for Asm {
diff --git a/src/juicebox_asm/insn/jnz.rs.html b/src/juicebox_asm/insn/jnz.rs.html
index 40ae96c..14391d7 100644
--- a/src/juicebox_asm/insn/jnz.rs.html
+++ b/src/juicebox_asm/insn/jnz.rs.html
@@ -1,13 +1,12 @@
-jnz.rs - source
-    
1
+jnz.rs - source

juicebox_asm/insn/
jnz.rs

+1
 2
 3
 4
 5
 6
 7
-8
-
use super::Jnz;
+8
use super::Jnz;
 use crate::{Asm, Label};
 
 impl Jnz<&mut Label> for Asm {
diff --git a/src/juicebox_asm/insn/jz.rs.html b/src/juicebox_asm/insn/jz.rs.html
index 9a44a21..074c065 100644
--- a/src/juicebox_asm/insn/jz.rs.html
+++ b/src/juicebox_asm/insn/jz.rs.html
@@ -1,13 +1,12 @@
-jz.rs - source
-    
1
+jz.rs - source

juicebox_asm/insn/
jz.rs

+1
 2
 3
 4
 5
 6
 7
-8
-
use super::Jz;
+8
use super::Jz;
 use crate::{Asm, Label};
 
 impl Jz<&mut Label> for Asm {
diff --git a/src/juicebox_asm/insn/mov.rs.html b/src/juicebox_asm/insn/mov.rs.html
index 8f10e31..5bd4111 100644
--- a/src/juicebox_asm/insn/mov.rs.html
+++ b/src/juicebox_asm/insn/mov.rs.html
@@ -1,5 +1,5 @@
-mov.rs - source
-    
1
+mov.rs - source

juicebox_asm/insn/
mov.rs

+1
 2
 3
 4
@@ -112,8 +112,7 @@
 111
 112
 113
-114
-
use super::Mov;
+114
use super::Mov;
 use crate::{Asm, Imm16, Imm32, Imm64, Imm8, MemOp, Reg16, Reg32, Reg64, Reg8};
 
 // -- MOV : reg reg
diff --git a/src/juicebox_asm/insn/nop.rs.html b/src/juicebox_asm/insn/nop.rs.html
index 34afd35..ec71515 100644
--- a/src/juicebox_asm/insn/nop.rs.html
+++ b/src/juicebox_asm/insn/nop.rs.html
@@ -1,13 +1,12 @@
-nop.rs - source
-    
1
+nop.rs - source

juicebox_asm/insn/
nop.rs

+1
 2
 3
 4
 5
 6
 7
-8
-
use crate::Asm;
+8
use crate::Asm;
 
 impl Asm {
     /// Emit a [`nop`](https://www.felixcloutier.com/x86/nop) instruction.
diff --git a/src/juicebox_asm/insn/pop.rs.html b/src/juicebox_asm/insn/pop.rs.html
index 0852511..5b06e59 100644
--- a/src/juicebox_asm/insn/pop.rs.html
+++ b/src/juicebox_asm/insn/pop.rs.html
@@ -1,5 +1,5 @@
-pop.rs - source
-    
1
+pop.rs - source

juicebox_asm/insn/
pop.rs

+1
 2
 3
 4
@@ -12,8 +12,7 @@
 11
 12
 13
-14
-
use super::Pop;
+14
use super::Pop;
 use crate::{Asm, Reg16, Reg64};
 
 impl Pop<Reg64> for Asm {
diff --git a/src/juicebox_asm/insn/push.rs.html b/src/juicebox_asm/insn/push.rs.html
index e947e8b..636c6f6 100644
--- a/src/juicebox_asm/insn/push.rs.html
+++ b/src/juicebox_asm/insn/push.rs.html
@@ -1,5 +1,5 @@
-push.rs - source
-    
1
+push.rs - source

juicebox_asm/insn/
push.rs

+1
 2
 3
 4
@@ -12,8 +12,7 @@
 11
 12
 13
-14
-
use super::Push;
+14
use super::Push;
 use crate::{Asm, Reg16, Reg64};
 
 impl Push<Reg64> for Asm {
diff --git a/src/juicebox_asm/insn/ret.rs.html b/src/juicebox_asm/insn/ret.rs.html
index bc88856..b26e883 100644
--- a/src/juicebox_asm/insn/ret.rs.html
+++ b/src/juicebox_asm/insn/ret.rs.html
@@ -1,13 +1,12 @@
-ret.rs - source
-    
1
+ret.rs - source

juicebox_asm/insn/
ret.rs

+1
 2
 3
 4
 5
 6
 7
-8
-
use crate::Asm;
+8
use crate::Asm;
 
 impl Asm {
     /// Emit a [`ret`](https://www.felixcloutier.com/x86/ret) instruction.
diff --git a/src/juicebox_asm/insn/test.rs.html b/src/juicebox_asm/insn/test.rs.html
index 53a4e39..4c9bd7d 100644
--- a/src/juicebox_asm/insn/test.rs.html
+++ b/src/juicebox_asm/insn/test.rs.html
@@ -1,5 +1,5 @@
-test.rs - source
-    
1
+test.rs - source

juicebox_asm/insn/
test.rs

+1
 2
 3
 4
@@ -18,8 +18,7 @@
 17
 18
 19
-20
-
use super::Test;
+20
use super::Test;
 use crate::{Asm, Imm16, MemOp, Reg32, Reg64};
 
 impl Test<Reg64, Reg64> for Asm {
diff --git a/src/juicebox_asm/insn/xor.rs.html b/src/juicebox_asm/insn/xor.rs.html
new file mode 100644
index 0000000..2bd3dc8
--- /dev/null
+++ b/src/juicebox_asm/insn/xor.rs.html
@@ -0,0 +1,17 @@
+xor.rs - source

juicebox_asm/insn/
xor.rs

+1
+2
+3
+4
+5
+6
+7
+8
use super::Xor;
+use crate::{Asm, Reg64};
+
+impl Xor<Reg64, Reg64> for Asm {
+    fn xor(&mut self, op1: Reg64, op2: Reg64) {
+        self.encode_rr(&[0x31], op1, op2);
+    }
+}
+
\ No newline at end of file diff --git a/src/juicebox_asm/label.rs.html b/src/juicebox_asm/label.rs.html index d986d64..d46d49a 100644 --- a/src/juicebox_asm/label.rs.html +++ b/src/juicebox_asm/label.rs.html @@ -1,5 +1,5 @@ -label.rs - source -
1
+label.rs - source

juicebox_asm/
label.rs

+1
 2
 3
 4
@@ -81,8 +81,7 @@
 80
 81
 82
-83
-
//! Definition of the lable type which can be used as jump target and can be bound to a location in
+83
//! Definition of the lable type which can be used as jump target and can be bound to a location in
 //! the emitted code.
 
 use std::collections::HashSet;
diff --git a/src/juicebox_asm/lib.rs.html b/src/juicebox_asm/lib.rs.html
index d7d33f1..2b9ed8a 100644
--- a/src/juicebox_asm/lib.rs.html
+++ b/src/juicebox_asm/lib.rs.html
@@ -1,5 +1,5 @@
-lib.rs - source
-    
1
+lib.rs - source

juicebox_asm/
lib.rs

+1
 2
 3
 4
@@ -106,7 +106,63 @@
 105
 106
 107
-
//! A simple `x64` jit assembler with a minimal runtime to execute emitted code for fun.
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
//! A simple `x64` jit assembler with a minimal runtime to execute emitted code for fun.
 //!
 //! The following is an fibonacci example implementation.
 //! ```rust
@@ -196,12 +252,16 @@
 pub use rt::Runtime;
 
 /// Type representing a memory operand.
+#[derive(Clone, Copy)]
 pub enum MemOp {
     /// An indirect memory operand, eg `mov [rax], rcx`.
     Indirect(Reg64),
 
     /// An indirect memory operand with additional displacement, eg `mov [rax + 0x10], rcx`.
     IndirectDisp(Reg64, i32),
+
+    /// An indirect memory operand in the form base + index, eg `mov [rax + rcx], rdx`.
+    IndirectBaseIndex(Reg64, Reg64),
 }
 
 impl MemOp {
@@ -210,7 +270,60 @@
         match self {
             MemOp::Indirect(base) => *base,
             MemOp::IndirectDisp(base, ..) => *base,
+            MemOp::IndirectBaseIndex(base, ..) => *base,
+        }
+    }
+
+    /// Get the index register of the memory operand.
+    fn index(&self) -> Reg64 {
+        // Return zero index register for memory operands w/o index register.
+        let zero_index = Reg64::rax;
+        use reg::Reg;
+        assert_eq!(zero_index.idx(), 0);
+
+        match self {
+            MemOp::Indirect(..) => zero_index,
+            MemOp::IndirectDisp(..) => zero_index,
+            MemOp::IndirectBaseIndex(.., index) => *index,
         }
     }
 }
+
+/// Trait to give size hints for memory operands.
+trait MemOpSized {
+    fn mem_op(&self) -> MemOp;
+}
+
+macro_rules! impl_memop_sized {
+    ($(#[$doc:meta] $name:ident)+) => {
+        $(
+        #[$doc]
+        pub struct $name(MemOp);
+
+        impl $name {
+            /// Create a memory with size hint from a raw memory operand.
+            pub fn from(op: MemOp) -> Self {
+                Self(op)
+            }
+        }
+
+        impl MemOpSized for $name {
+            fn mem_op(&self) -> MemOp {
+                self.0
+            }
+        }
+        )+
+    };
+}
+
+impl_memop_sized!(
+    /// A memory operand with a word (8 bit) size hint.
+    MemOp8
+    /// A memory operand with a word (16 bit) size hint.
+    MemOp16
+    /// A memory operand with a dword (32 bit) size hint.
+    MemOp32
+    /// A memory operand with a qword (64 bit) size hint.
+    MemOp64
+);
 
\ No newline at end of file diff --git a/src/juicebox_asm/reg.rs.html b/src/juicebox_asm/reg.rs.html index f0612f6..edbf390 100644 --- a/src/juicebox_asm/reg.rs.html +++ b/src/juicebox_asm/reg.rs.html @@ -1,5 +1,5 @@ -reg.rs - source -
1
+reg.rs - source

juicebox_asm/
reg.rs

+1
 2
 3
 4
@@ -302,8 +302,7 @@
 301
 302
 303
-304
-
//! Definition of registers which are used as input operands for various instructions.
+304
//! Definition of registers which are used as input operands for various instructions.
 
 /// Trait to interact with register operands.
 pub(crate) trait Reg {
@@ -342,7 +341,7 @@
     }
 }
 
-macro_rules! enum_reg {
+macro_rules! enum_reg {
     (#[$doc:meta]  $name:ident, { $($reg:ident),+ $(,)? }) => {
         #[$doc]
         #[allow(non_camel_case_types)]
@@ -362,7 +361,7 @@
     };
 }
 
-macro_rules! impl_reg {
+macro_rules! impl_reg {
     (#[$doc:meta] $name:ident, $rexw:expr, { $($reg:ident),+ $(,)? }) => {
         enum_reg!(#[$doc] $name, { $( $reg, )+ });
 
diff --git a/src/juicebox_asm/rt.rs.html b/src/juicebox_asm/rt.rs.html
index eecdd6f..039fa77 100644
--- a/src/juicebox_asm/rt.rs.html
+++ b/src/juicebox_asm/rt.rs.html
@@ -1,5 +1,5 @@
-rt.rs - source
-    
1
+rt.rs - source

juicebox_asm/
rt.rs

+1
 2
 3
 4
@@ -267,8 +267,7 @@
 266
 267
 268
-269
-
//! Simple `mmap`ed runtime.
+269
//! Simple `mmap`ed runtime.
 //!
 //! This runtime supports adding code to executable pages and turn the added code into user
 //! specified function pointer.
-- 
cgit v1.2.3