aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/lib.rs
diff options
context:
space:
mode:
authorJohannes Stoelp <johannes.stoelp@gmail.com>2023-12-05 00:56:58 +0100
committerJohannes Stoelp <johannes.stoelp@gmail.com>2023-12-05 00:56:58 +0100
commit3f47ede3d0a1aaf3a9176ab9c93b8d0e970388f2 (patch)
tree395c01d6dad25e14ee8f6879d3f040e9f57f1d2f /src/lib.rs
parent4a80838151a9945438739ab937c415939e2ccf5b (diff)
downloadjuicebox-asm-3f47ede3d0a1aaf3a9176ab9c93b8d0e970388f2.tar.gz
juicebox-asm-3f47ede3d0a1aaf3a9176ab9c93b8d0e970388f2.zip
insn: add additional insn required for the new tiny_vm example
Diffstat (limited to 'src/lib.rs')
-rw-r--r--src/lib.rs59
1 files changed, 59 insertions, 0 deletions
diff --git a/src/lib.rs b/src/lib.rs
index 0cc86fb..8348435 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -273,6 +273,42 @@ impl Asm {
self.emit(&[opc, modrm]);
}
+ /// Encode a memory-immediate instruction.
+ fn encode_mi<T: Imm>(&mut self, opc: u8, opc_ext: u8, op1: MemOp, op2: T)
+ where
+ Self: EncodeMI<T>,
+ {
+ // MI operand encoding.
+ // op1 -> modrm.rm
+ // op2 -> imm
+ let mode = match op1 {
+ MemOp::Indirect(..) => {
+ assert!(!op1.base().need_sib() && !op1.base().is_pc_rel());
+ 0b00
+ }
+ MemOp::IndirectDisp(..) => {
+ assert!(!op1.base().need_sib());
+ 0b10
+ }
+ };
+
+ let modrm = modrm(
+ mode, /* mode */
+ opc_ext, /* reg */
+ op1.base().idx(), /* rm */
+ );
+
+ let prefix = <Self as EncodeMI<T>>::legacy_prefix();
+ let rex = <Self as EncodeMI<T>>::rex(&op1);
+
+ self.emit_optional(&[prefix, rex]);
+ self.emit(&[opc, modrm]);
+ if let MemOp::IndirectDisp(_, disp) = op1 {
+ self.emit(&disp.to_ne_bytes());
+ }
+ self.emit(op2.bytes());
+ }
+
/// Encode a memory-register instruction.
fn encode_mr<T: Reg>(&mut self, opc: u8, op1: MemOp, op2: T)
where
@@ -408,3 +444,26 @@ impl EncodeMR<Reg16> for Asm {
}
impl EncodeMR<Reg32> for Asm {}
impl EncodeMR<Reg64> for Asm {}
+
+/// Encode helper for memory-immediate instructions.
+trait EncodeMI<T: Imm> {
+ fn legacy_prefix() -> Option<u8> {
+ None
+ }
+
+ fn rex(op1: &MemOp) -> Option<u8> {
+ if op1.base().is_ext() {
+ Some(rex(false, 0, 0, op1.base().idx()))
+ } else {
+ None
+ }
+ }
+}
+
+impl EncodeMI<Imm8> for Asm {}
+impl EncodeMI<Imm16> for Asm {
+ fn legacy_prefix() -> Option<u8> {
+ Some(0x66)
+ }
+}
+impl EncodeMI<Imm32> for Asm {}