summaryrefslogtreecommitdiff
path: root/yjit/src/asm/x86_64/tests.rs
diff options
context:
space:
mode:
Diffstat (limited to 'yjit/src/asm/x86_64/tests.rs')
-rw-r--r--yjit/src/asm/x86_64/tests.rs47
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 ffcc063420..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.start_ptr().raw_ptr().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());