diff options
Diffstat (limited to 'yjit/src/asm/x86_64/tests.rs')
-rw-r--r-- | yjit/src/asm/x86_64/tests.rs | 47 |
1 files changed, 30 insertions, 17 deletions
diff --git a/yjit/src/asm/x86_64/tests.rs b/yjit/src/asm/x86_64/tests.rs index c77d30e74d..5ae983270f 100644 --- a/yjit/src/asm/x86_64/tests.rs +++ b/yjit/src/asm/x86_64/tests.rs @@ -1,18 +1,6 @@ #![cfg(test)] use crate::asm::x86_64::*; -use std::fmt; - -/// Produce hex string output from the bytes in a code block -impl<'a> fmt::LowerHex for super::CodeBlock { - fn fmt(&self, fmtr: &mut fmt::Formatter) -> fmt::Result { - for pos in 0..self.write_pos { - let byte = unsafe { self.mem_block.add(pos).read() }; - fmtr.write_fmt(format_args!("{:02x}", byte))?; - } - Ok(()) - } -} /// Check that the bytes for an instruction sequence match a hex string fn check_bytes<R>(bytes: &str, run: R) where R: FnOnce(&mut super::CodeBlock) { @@ -80,7 +68,7 @@ fn test_call_ptr() { // calling a lower address check_bytes("e8fbffffff", |cb| { let ptr = cb.get_write_ptr(); - call_ptr(cb, RAX, ptr.raw_ptr()); + call_ptr(cb, RAX, ptr.raw_ptr(cb)); }); } @@ -109,6 +97,7 @@ fn test_cmp() { check_bytes("39f9", |cb| cmp(cb, ECX, EDI)); check_bytes("493b1424", |cb| cmp(cb, RDX, mem_opnd(64, R12, 0))); check_bytes("4883f802", |cb| cmp(cb, RAX, imm_opnd(2))); + check_bytes("81f900000080", |cb| cmp(cb, ECX, uimm_opnd(0x8000_0000))); } #[test] @@ -117,6 +106,15 @@ fn test_cqo() { } #[test] +fn test_imul() { + check_bytes("480fafc3", |cb| imul(cb, RAX, RBX)); + check_bytes("480faf10", |cb| imul(cb, RDX, mem_opnd(64, RAX, 0))); + + // Operands flipped for encoding since multiplication is commutative + check_bytes("480faf10", |cb| imul(cb, mem_opnd(64, RAX, 0), RDX)); +} + +#[test] fn test_jge_label() { check_bytes("0f8dfaffffff", |cb| { let label_idx = cb.new_label("loop".to_owned()); @@ -201,6 +199,12 @@ fn test_mov() { } #[test] +fn test_movabs() { + check_bytes("49b83400000000000000", |cb| movabs(cb, R8, 0x34)); + check_bytes("49b80000008000000000", |cb| movabs(cb, R8, 0x80000000)); +} + +#[test] fn test_mov_unsigned() { // MOV AL, imm8 check_bytes("b001", |cb| mov(cb, AL, uimm_opnd(1))); @@ -345,6 +349,7 @@ fn test_sal() { check_bytes("d1e1", |cb| sal(cb, ECX, uimm_opnd(1))); check_bytes("c1e505", |cb| sal(cb, EBP, uimm_opnd(5))); check_bytes("d1642444", |cb| sal(cb, mem_opnd(32, RSP, 68), uimm_opnd(1))); + check_bytes("48d3e1", |cb| sal(cb, RCX, CL)); } #[test] @@ -364,6 +369,14 @@ fn test_sub() { } #[test] +#[should_panic] +fn test_sub_uimm_too_large() { + // This immediate becomes a different value after + // sign extension, so not safe to encode. + check_bytes("ff", |cb| sub(cb, RCX, uimm_opnd(0x8000_0000))); +} + +#[test] fn test_test() { check_bytes("84c0", |cb| test(cb, AL, AL)); check_bytes("6685c0", |cb| test(cb, AX, AX)); @@ -425,19 +438,19 @@ fn basic_capstone_usage() -> std::result::Result<(), capstone::Error> { } #[test] -#[cfg(feature = "asm_comments")] +#[cfg(feature = "disasm")] fn block_comments() { let mut cb = super::CodeBlock::new_dummy(4096); - let first_write_ptr = cb.get_write_ptr().into_usize(); + let first_write_ptr = cb.get_write_ptr().raw_addr(&cb); cb.add_comment("Beginning"); xor(&mut cb, EAX, EAX); // 2 bytes long - let second_write_ptr = cb.get_write_ptr().into_usize(); + let second_write_ptr = cb.get_write_ptr().raw_addr(&cb); cb.add_comment("Two bytes in"); cb.add_comment("Still two bytes in"); cb.add_comment("Still two bytes in"); // Duplicate, should be ignored test(&mut cb, mem_opnd(64, RSI, 64), imm_opnd(!0x08)); // 8 bytes long - let third_write_ptr = cb.get_write_ptr().into_usize(); + let third_write_ptr = cb.get_write_ptr().raw_addr(&cb); cb.add_comment("Ten bytes in"); assert_eq!(&vec!( "Beginning".to_string() ), cb.comments_at(first_write_ptr).unwrap()); |