|
@@ -87,45 +87,45 @@ macro_rules! emit_bytes {
|
|
|
}
|
|
|
|
|
|
#[inline]
|
|
|
-fn emit1 (jit: &mut JitMemory, data: u8) {
|
|
|
+fn emit1(jit: &mut JitMemory, data: u8) {
|
|
|
emit_bytes!(jit, data, u8);
|
|
|
}
|
|
|
|
|
|
#[inline]
|
|
|
-fn emit2 (jit: &mut JitMemory, data: u16) {
|
|
|
+fn emit2(jit: &mut JitMemory, data: u16) {
|
|
|
emit_bytes!(jit, data, u16);
|
|
|
}
|
|
|
|
|
|
#[inline]
|
|
|
-fn emit4 (jit: &mut JitMemory, data: u32) {
|
|
|
+fn emit4(jit: &mut JitMemory, data: u32) {
|
|
|
emit_bytes!(jit, data, u32);
|
|
|
}
|
|
|
|
|
|
#[inline]
|
|
|
-fn emit8 (jit: &mut JitMemory, data: u64) {
|
|
|
+fn emit8(jit: &mut JitMemory, data: u64) {
|
|
|
emit_bytes!(jit, data, u64);
|
|
|
}
|
|
|
|
|
|
#[inline]
|
|
|
-fn emit_jump_offset (jit: &mut JitMemory, target_pc: isize) {
|
|
|
+fn emit_jump_offset(jit: &mut JitMemory, target_pc: isize) {
|
|
|
let jump = Jump { offset_loc: jit.offset, target_pc: target_pc };
|
|
|
jit.jumps.push(jump);
|
|
|
emit4(jit, 0);
|
|
|
}
|
|
|
|
|
|
#[inline]
|
|
|
-fn emit_modrm (jit: &mut JitMemory, modrm: u8, r: u8, m: u8) {
|
|
|
+fn emit_modrm(jit: &mut JitMemory, modrm: u8, r: u8, m: u8) {
|
|
|
assert!((modrm | 0xc0) == 0xc0);
|
|
|
emit1(jit, (modrm & 0xc0) | ((r & 0b111) << 3) | (m & 0b111));
|
|
|
}
|
|
|
|
|
|
#[inline]
|
|
|
-fn emit_modrm_reg2reg (jit: &mut JitMemory, r: u8, m: u8) {
|
|
|
+fn emit_modrm_reg2reg(jit: &mut JitMemory, r: u8, m: u8) {
|
|
|
emit_modrm(jit, 0xc0, r, m);
|
|
|
}
|
|
|
|
|
|
#[inline]
|
|
|
-fn emit_modrm_and_displacement (jit: &mut JitMemory, r: u8, m: u8, d: i32) {
|
|
|
+fn emit_modrm_and_displacement(jit: &mut JitMemory, r: u8, m: u8, d: i32) {
|
|
|
if d == 0 && (m & 0b111) != RBP {
|
|
|
emit_modrm(jit, 0x00, r, m);
|
|
|
} else if d >= -128 && d <= 127 {
|
|
@@ -138,7 +138,7 @@ fn emit_modrm_and_displacement (jit: &mut JitMemory, r: u8, m: u8, d: i32) {
|
|
|
}
|
|
|
|
|
|
#[inline]
|
|
|
-fn emit_rex (jit: &mut JitMemory, w: u8, r: u8, x: u8, b: u8) {
|
|
|
+fn emit_rex(jit: &mut JitMemory, w: u8, r: u8, x: u8, b: u8) {
|
|
|
assert!((w | 1) == 1);
|
|
|
assert!((r | 1) == 1);
|
|
|
assert!((x | 1) == 1);
|
|
@@ -149,7 +149,7 @@ fn emit_rex (jit: &mut JitMemory, w: u8, r: u8, x: u8, b: u8) {
|
|
|
// Emits a REX prefix with the top bit of src and dst.
|
|
|
// Skipped if no bits would be set.
|
|
|
#[inline]
|
|
|
-fn emit_basic_rex (jit: &mut JitMemory, w: u8, src: u8, dst: u8) {
|
|
|
+fn emit_basic_rex(jit: &mut JitMemory, w: u8, src: u8, dst: u8) {
|
|
|
if w != 0 || (src & 0b1000) != 0 || (dst & 0b1000) != 0 {
|
|
|
let is_masked = | val, mask | { match val & mask {
|
|
|
0 => 0,
|
|
@@ -160,13 +160,13 @@ fn emit_basic_rex (jit: &mut JitMemory, w: u8, src: u8, dst: u8) {
|
|
|
}
|
|
|
|
|
|
#[inline]
|
|
|
-fn emit_push (jit: &mut JitMemory, r: u8) {
|
|
|
+fn emit_push(jit: &mut JitMemory, r: u8) {
|
|
|
emit_basic_rex(jit, 0, 0, r);
|
|
|
emit1(jit, 0x50 | (r & 0b111));
|
|
|
}
|
|
|
|
|
|
#[inline]
|
|
|
-fn emit_pop (jit: &mut JitMemory, r: u8) {
|
|
|
+fn emit_pop(jit: &mut JitMemory, r: u8) {
|
|
|
emit_basic_rex(jit, 0, 0, r);
|
|
|
emit1(jit, 0x58 | (r & 0b111));
|
|
|
}
|
|
@@ -175,7 +175,7 @@ fn emit_pop (jit: &mut JitMemory, r: u8) {
|
|
|
// We use the MR encoding when there is a choice
|
|
|
// 'src' is often used as an opcode extension
|
|
|
#[inline]
|
|
|
-fn emit_alu32 (jit: &mut JitMemory, op: u8, src: u8, dst: u8) {
|
|
|
+fn emit_alu32(jit: &mut JitMemory, op: u8, src: u8, dst: u8) {
|
|
|
emit_basic_rex(jit, 0, src, dst);
|
|
|
emit1(jit, op);
|
|
|
emit_modrm_reg2reg(jit, src, dst);
|
|
@@ -183,14 +183,14 @@ fn emit_alu32 (jit: &mut JitMemory, op: u8, src: u8, dst: u8) {
|
|
|
|
|
|
// REX prefix, ModRM byte, and 32-bit immediate
|
|
|
#[inline]
|
|
|
-fn emit_alu32_imm32 (jit: &mut JitMemory, op: u8, src: u8, dst: u8, imm: i32) {
|
|
|
+fn emit_alu32_imm32(jit: &mut JitMemory, op: u8, src: u8, dst: u8, imm: i32) {
|
|
|
emit_alu32(jit, op, src, dst);
|
|
|
emit4(jit, imm as u32);
|
|
|
}
|
|
|
|
|
|
// REX prefix, ModRM byte, and 8-bit immediate
|
|
|
#[inline]
|
|
|
-fn emit_alu32_imm8 (jit: &mut JitMemory, op: u8, src: u8, dst: u8, imm: i8) {
|
|
|
+fn emit_alu32_imm8(jit: &mut JitMemory, op: u8, src: u8, dst: u8, imm: i8) {
|
|
|
emit_alu32(jit, op, src, dst);
|
|
|
emit1(jit, imm as u8);
|
|
|
}
|
|
@@ -199,7 +199,7 @@ fn emit_alu32_imm8 (jit: &mut JitMemory, op: u8, src: u8, dst: u8, imm: i8) {
|
|
|
// We use the MR encoding when there is a choice
|
|
|
// 'src' is often used as an opcode extension
|
|
|
#[inline]
|
|
|
-fn emit_alu64 (jit: &mut JitMemory, op: u8, src: u8, dst: u8) {
|
|
|
+fn emit_alu64(jit: &mut JitMemory, op: u8, src: u8, dst: u8) {
|
|
|
emit_basic_rex(jit, 1, src, dst);
|
|
|
emit1(jit, op);
|
|
|
emit_modrm_reg2reg(jit, src, dst);
|
|
@@ -207,43 +207,43 @@ fn emit_alu64 (jit: &mut JitMemory, op: u8, src: u8, dst: u8) {
|
|
|
|
|
|
// REX.W prefix, ModRM byte, and 32-bit immediate
|
|
|
#[inline]
|
|
|
-fn emit_alu64_imm32 (jit: &mut JitMemory, op: u8, src: u8, dst: u8, imm: i32) {
|
|
|
+fn emit_alu64_imm32(jit: &mut JitMemory, op: u8, src: u8, dst: u8, imm: i32) {
|
|
|
emit_alu64(jit, op, src, dst);
|
|
|
emit4(jit, imm as u32);
|
|
|
}
|
|
|
|
|
|
// REX.W prefix, ModRM byte, and 8-bit immediate
|
|
|
#[inline]
|
|
|
-fn emit_alu64_imm8 (jit: &mut JitMemory, op: u8, src: u8, dst: u8, imm: i8) {
|
|
|
+fn emit_alu64_imm8(jit: &mut JitMemory, op: u8, src: u8, dst: u8, imm: i8) {
|
|
|
emit_alu64(jit, op, src, dst);
|
|
|
emit1(jit, imm as u8);
|
|
|
}
|
|
|
|
|
|
// Register to register mov
|
|
|
#[inline]
|
|
|
-fn emit_mov (jit: &mut JitMemory, src: u8, dst: u8) {
|
|
|
+fn emit_mov(jit: &mut JitMemory, src: u8, dst: u8) {
|
|
|
emit_alu64(jit, 0x89, src, dst);
|
|
|
}
|
|
|
|
|
|
#[inline]
|
|
|
-fn emit_cmp_imm32 (jit: &mut JitMemory, dst: u8, imm: i32) {
|
|
|
+fn emit_cmp_imm32(jit: &mut JitMemory, dst: u8, imm: i32) {
|
|
|
emit_alu64_imm32(jit, 0x81, 7, dst, imm);
|
|
|
}
|
|
|
|
|
|
#[inline]
|
|
|
-fn emit_cmp (jit: &mut JitMemory, src: u8, dst: u8) {
|
|
|
+fn emit_cmp(jit: &mut JitMemory, src: u8, dst: u8) {
|
|
|
emit_alu64(jit, 0x39, src, dst);
|
|
|
}
|
|
|
|
|
|
#[inline]
|
|
|
-fn emit_jcc (jit: &mut JitMemory, code: u8, target_pc: isize) {
|
|
|
+fn emit_jcc(jit: &mut JitMemory, code: u8, target_pc: isize) {
|
|
|
emit1(jit, 0x0f);
|
|
|
emit1(jit, code);
|
|
|
emit_jump_offset(jit, target_pc);
|
|
|
}
|
|
|
|
|
|
#[inline]
|
|
|
-fn emit_jmp (jit: &mut JitMemory, target_pc: isize) {
|
|
|
+fn emit_jmp(jit: &mut JitMemory, target_pc: isize) {
|
|
|
emit1(jit, 0xe9);
|
|
|
emit_jump_offset(jit, target_pc);
|
|
|
}
|
|
@@ -255,7 +255,7 @@ fn set_anchor(jit: &mut JitMemory, target: isize) {
|
|
|
|
|
|
// Load [src + offset] into dst
|
|
|
#[inline]
|
|
|
-fn emit_load (jit: &mut JitMemory, size: OperandSize, src: u8, dst: u8, offset: i32) {
|
|
|
+fn emit_load(jit: &mut JitMemory, size: OperandSize, src: u8, dst: u8, offset: i32) {
|
|
|
let data = match size {
|
|
|
OperandSize::S64 => 1,
|
|
|
_ => 0
|
|
@@ -284,7 +284,7 @@ fn emit_load (jit: &mut JitMemory, size: OperandSize, src: u8, dst: u8, offset:
|
|
|
|
|
|
// Load sign-extended immediate into register
|
|
|
#[inline]
|
|
|
-fn emit_load_imm (jit: &mut JitMemory, dst: u8, imm: i64) {
|
|
|
+fn emit_load_imm(jit: &mut JitMemory, dst: u8, imm: i64) {
|
|
|
if imm >= std::i32::MIN as i64 && imm <= std::i32::MAX as i64 {
|
|
|
emit_alu64_imm32(jit, 0xc7, 0, dst, imm as i32);
|
|
|
} else {
|
|
@@ -297,7 +297,7 @@ fn emit_load_imm (jit: &mut JitMemory, dst: u8, imm: i64) {
|
|
|
|
|
|
// Store register src to [dst + offset]
|
|
|
#[inline]
|
|
|
-fn emit_store (jit: &mut JitMemory, size: OperandSize, src: u8, dst: u8, offset: i32) {
|
|
|
+fn emit_store(jit: &mut JitMemory, size: OperandSize, src: u8, dst: u8, offset: i32) {
|
|
|
match size {
|
|
|
OperandSize::S16 => emit1(jit, 0x66), // 16-bit override
|
|
|
_ => {},
|
|
@@ -325,7 +325,7 @@ fn emit_store (jit: &mut JitMemory, size: OperandSize, src: u8, dst: u8, offset:
|
|
|
|
|
|
// Store immediate to [dst + offset]
|
|
|
#[inline]
|
|
|
-fn emit_store_imm32 (jit: &mut JitMemory, size: OperandSize, dst: u8, offset: i32, imm: i32) {
|
|
|
+fn emit_store_imm32(jit: &mut JitMemory, size: OperandSize, dst: u8, offset: i32, imm: i32) {
|
|
|
match size {
|
|
|
OperandSize::S16 => emit1(jit, 0x66), // 16-bit override
|
|
|
_ => {},
|
|
@@ -347,7 +347,7 @@ fn emit_store_imm32 (jit: &mut JitMemory, size: OperandSize, dst: u8, offset: i3
|
|
|
}
|
|
|
|
|
|
#[inline]
|
|
|
-fn emit_call (jit: &mut JitMemory, target: i64) {
|
|
|
+fn emit_call(jit: &mut JitMemory, target: i64) {
|
|
|
// TODO use direct call when possible
|
|
|
emit_load_imm(jit, RAX, target);
|
|
|
// callq *%rax
|
|
@@ -781,7 +781,7 @@ impl<'a> JitMemory<'a> {
|
|
|
|
|
|
// Division by zero handler
|
|
|
set_anchor(self, TARGET_PC_DIV_BY_ZERO);
|
|
|
- fn log (pc: u64) -> i64 {
|
|
|
+ fn log(pc: u64) -> i64 {
|
|
|
// Write error message on stderr.
|
|
|
// We would like to panic!() instead (but does not work here), or maybe return an
|
|
|
// error, that is, if we also turn all other panics into errors someday.
|