Affix
view release on metacpan or search on metacpan
infix/src/arch/x64/abi_x64_emitters.c view on Meta::CPAN
* @internal
* @brief Emits `cmp r64, r64` to compare two registers.
* @details Opcode format: REX.W + 39 /r
*/
INFIX_INTERNAL void emit_cmp_reg_reg(code_buffer * buf, x64_gpr reg1, x64_gpr reg2) {
emit_rex_prefix(buf, 1, reg2 >= R8_REG, 0, reg1 >= R8_REG);
emit_byte(buf, 0x39);
emit_modrm(buf, 3, reg2 % 8, reg1 % 8);
}
/**
* @internal
* @brief Emits `test r64, r64` to test if a register is zero.
* @details Opcode format: REX.W + 85 /r
*/
INFIX_INTERNAL void emit_test_reg_reg(code_buffer * buf, x64_gpr reg1, x64_gpr reg2) {
emit_rex_prefix(buf, 1, reg2 >= R8_REG, 0, reg1 >= R8_REG);
emit_byte(buf, 0x85);
emit_modrm(buf, 3, reg2 % 8, reg1 % 8);
}
/**
* @internal
* @brief Emits `jnz rel8` for a short conditional jump if not zero.
* @details Opcode format: 75 rel8
*/
INFIX_INTERNAL void emit_jnz_short(code_buffer * buf, int8_t offset) { EMIT_BYTES(buf, 0x75, (uint8_t)offset); }
/**
* @internal
* @brief Emits `je rel8` for a short conditional jump if equal.
* @details Opcode format: 74 rel8
*/
INFIX_INTERNAL void emit_je_short(code_buffer * buf, int8_t offset) { EMIT_BYTES(buf, 0x74, (uint8_t)offset); }
/**
* @internal
* @brief Emits a `jmp r64` instruction.
* @details This instruction performs an indirect jump to the address contained in the
* specified 64-bit register. Opcode format: [REX.B] FF /4
*/
INFIX_INTERNAL void emit_jmp_reg(code_buffer * buf, x64_gpr reg) {
uint8_t rex = 0;
if (reg >= R8_REG)
rex = 0x40 | REX_B;
if (rex)
emit_byte(buf, rex);
emit_byte(buf, 0xFF);
emit_modrm(buf, 3, 4, reg % 8); // mod=11 (register), reg=/4 for JMP
}
/**
* @internal
* @brief Emits `ud2`, an undefined instruction that causes an invalid opcode exception.
* @details Opcode format: 0F 0B
*/
INFIX_INTERNAL void emit_ud2(code_buffer * buf) { EMIT_BYTES(buf, 0x0F, 0x0B); }
/**
* @internal
* @brief Emits the two-byte `syscall` instruction.
* @details Opcode: 0F 05
*/
INFIX_INTERNAL void emit_syscall(code_buffer * buf) { EMIT_BYTES(buf, 0x0F, 0x05); }
/**
* @internal
* @brief Emits the `leave` instruction to tear down a stack frame.
* @details This is equivalent to `mov rsp, rbp` followed by `pop rbp`.
* Opcode: C9
*/
INFIX_INTERNAL void emit_leave(code_buffer * buf) { emit_byte(buf, 0xC9); }
( run in 0.583 second using v1.01-cache-2.11-cpan-df04353d9ac )