Affix

 view release on metacpan or  search on metacpan

infix/src/arch/x64/abi_x64_emitters.c  view on Meta::CPAN

 * Opcode format: REX.W + 8B /r
 */
INFIX_INTERNAL void emit_mov_reg_mem(code_buffer * buf, x64_gpr dest, x64_gpr src_base, int32_t offset) {
    emit_rex_prefix(buf, 1, dest >= R8_REG, 0, src_base >= R8_REG);
    emit_byte(buf, 0x8B);
    uint8_t mod = (offset >= -128 && offset <= 127) ? 0x40 : 0x80;
    if (offset == 0 && (src_base % 8) != RBP_REG)
        mod = 0x00;
    emit_modrm(buf, mod >> 6, dest % 8, src_base % 8);
    if (src_base % 8 == RSP_REG)
        emit_byte(buf, 0x24);
    if (mod == 0x40)
        emit_byte(buf, (uint8_t)offset);
    else if (mod == 0x80)
        emit_int32(buf, offset);
}
/**
 * @internal
 * @brief Emits `mov r32, r/m32` to load a 32-bit value (zero-extended to 64).
 * @details Opcode format: 8B /r (without REX.W)
 */

infix/src/arch/x64/abi_x64_emitters.c  view on Meta::CPAN

    if (src_base >= R8_REG)
        rex |= REX_B;
    if (rex)
        emit_byte(buf, 0x40 | rex);
    emit_byte(buf, 0x8B);
    uint8_t mod = (offset >= -128 && offset <= 127) ? 0x40 : 0x80;
    if (offset == 0 && (src_base % 8) != RBP_REG)
        mod = 0x00;
    emit_modrm(buf, mod >> 6, dest % 8, src_base % 8);
    if (src_base % 8 == RSP_REG)
        emit_byte(buf, 0x24);
    if (mod == 0x40)
        emit_byte(buf, (uint8_t)offset);
    else if (mod == 0x80)
        emit_int32(buf, offset);
}
/**
 * @internal
 * @brief Emits `movsxd r64, r/m32` to load a 32-bit value and sign-extend to 64.
 * @details Opcode format: REX.W + 63 /r
 */
INFIX_INTERNAL void emit_movsxd_reg_mem(code_buffer * buf, x64_gpr dest, x64_gpr src_base, int32_t offset) {
    emit_rex_prefix(buf, 1, dest >= R8_REG, 0, src_base >= R8_REG);
    emit_byte(buf, 0x63);
    uint8_t mod = (offset >= -128 && offset <= 127) ? 0x40 : 0x80;
    if (offset == 0 && (src_base % 8) != RBP_REG)
        mod = 0x00;
    emit_modrm(buf, mod >> 6, dest % 8, src_base % 8);
    if (src_base % 8 == RSP_REG)
        emit_byte(buf, 0x24);
    if (mod == 0x40)
        emit_byte(buf, (uint8_t)offset);
    else if (mod == 0x80)
        emit_int32(buf, offset);
}
/**
 * @internal
 * @brief Emits `movsx r64, r/m8` to load a signed 8-bit value and sign-extend to 64.
 * @details Opcode format: REX.W + 0F BE /r
 */
INFIX_INTERNAL void emit_movsx_reg64_mem8(code_buffer * buf, x64_gpr dest, x64_gpr src_base, int32_t offset) {
    emit_rex_prefix(buf, 1, dest >= R8_REG, 0, src_base >= R8_REG);
    EMIT_BYTES(buf, 0x0F, 0xBE);
    uint8_t mod = (offset >= -128 && offset <= 127) ? 0x40 : 0x80;
    if (offset == 0 && (src_base % 8) != RBP_REG)
        mod = 0x00;
    emit_modrm(buf, mod >> 6, dest % 8, src_base % 8);
    if (src_base % 8 == RSP_REG)
        emit_byte(buf, 0x24);
    if (mod == 0x40)
        emit_byte(buf, (uint8_t)offset);
    else if (mod == 0x80)
        emit_int32(buf, offset);
}
/**
 * @internal
 * @brief Emits `movsx r64, r/m16` to load a signed 16-bit value and sign-extend to 64.
 * @details Opcode format: REX.W + 0F BF /r
 */
INFIX_INTERNAL void emit_movsx_reg64_mem16(code_buffer * buf, x64_gpr dest, x64_gpr src_base, int32_t offset) {
    emit_rex_prefix(buf, 1, dest >= R8_REG, 0, src_base >= R8_REG);
    EMIT_BYTES(buf, 0x0F, 0xBF);
    uint8_t mod = (offset >= -128 && offset <= 127) ? 0x40 : 0x80;
    if (offset == 0 && (src_base % 8) != RBP_REG)
        mod = 0x00;
    emit_modrm(buf, mod >> 6, dest % 8, src_base % 8);
    if (src_base % 8 == RSP_REG)
        emit_byte(buf, 0x24);
    if (mod == 0x40)
        emit_byte(buf, (uint8_t)offset);
    else if (mod == 0x80)
        emit_int32(buf, offset);
}
/**
 * @internal
 * @brief Emits `movzx r64, r/m8` to load an unsigned 8-bit value and zero-extend to 64.
 * @details Opcode format: REX.W + 0F B6 /r
 */
INFIX_INTERNAL void emit_movzx_reg64_mem8(code_buffer * buf, x64_gpr dest, x64_gpr src_base, int32_t offset) {
    emit_rex_prefix(buf, 1, dest >= R8_REG, 0, src_base >= R8_REG);
    EMIT_BYTES(buf, 0x0F, 0xB6);
    uint8_t mod = (offset >= -128 && offset <= 127) ? 0x40 : 0x80;
    if (offset == 0 && (src_base % 8) != RBP_REG)
        mod = 0x00;
    emit_modrm(buf, mod >> 6, dest % 8, src_base % 8);
    if (src_base % 8 == RSP_REG)
        emit_byte(buf, 0x24);
    if (mod == 0x40)
        emit_byte(buf, (uint8_t)offset);
    else if (mod == 0x80)
        emit_int32(buf, offset);
}
/**
 * @internal
 * @brief Emits `movzx r64, r/m16` to load an unsigned 16-bit value and zero-extend to 64.
 * @details Opcode format: REX.W + 0F B7 /r
 */
INFIX_INTERNAL void emit_movzx_reg64_mem16(code_buffer * buf, x64_gpr dest, x64_gpr src_base, int32_t offset) {
    emit_rex_prefix(buf, 1, dest >= R8_REG, 0, src_base >= R8_REG);
    EMIT_BYTES(buf, 0x0F, 0xB7);
    uint8_t mod = (offset >= -128 && offset <= 127) ? 0x40 : 0x80;
    if (offset == 0 && (src_base % 8) != RBP_REG)
        mod = 0x00;
    emit_modrm(buf, mod >> 6, dest % 8, src_base % 8);
    if (src_base % 8 == RSP_REG)
        emit_byte(buf, 0x24);
    if (mod == 0x40)
        emit_byte(buf, (uint8_t)offset);
    else if (mod == 0x80)
        emit_int32(buf, offset);
}
// GPR -> Memory Store Emitters
/**
 * @internal
 * @brief Emits `mov [base + offset], r64` to store a 64-bit GPR to memory.
 * @details Opcode format: REX.W + 89 /r
 */
INFIX_INTERNAL void emit_mov_mem_reg(code_buffer * buf, x64_gpr dest_base, int32_t offset, x64_gpr src) {
    emit_rex_prefix(buf, 1, src >= R8_REG, 0, dest_base >= R8_REG);
    emit_byte(buf, 0x89);
    uint8_t mod = (offset >= -128 && offset <= 127) ? 0x40 : 0x80;
    if (offset == 0 && (dest_base % 8) != RBP_REG)
        mod = 0x00;
    emit_modrm(buf, mod >> 6, src % 8, dest_base % 8);
    if (dest_base % 8 == RSP_REG)
        emit_byte(buf, 0x24);
    if (mod == 0x40)
        emit_byte(buf, (uint8_t)offset);
    else if (mod == 0x80)
        emit_int32(buf, offset);
}
/**
 * @internal
 * @brief Emits `mov [base + offset], r32` to store a 32-bit GPR to memory.
 * @details Opcode format: 89 /r (without REX.W)
 */

infix/src/arch/x64/abi_x64_emitters.c  view on Meta::CPAN

    if (dest_base >= R8_REG)
        rex |= REX_B;
    if (rex)
        emit_byte(buf, 0x40 | rex);
    emit_byte(buf, 0x89);
    uint8_t mod = (offset >= -128 && offset <= 127) ? 0x40 : 0x80;
    if (offset == 0 && (dest_base % 8) != RBP_REG)
        mod = 0x00;
    emit_modrm(buf, mod >> 6, src % 8, dest_base % 8);
    if (dest_base % 8 == RSP_REG)
        emit_byte(buf, 0x24);
    if (mod == 0x40)
        emit_byte(buf, (uint8_t)offset);
    else if (mod == 0x80)
        emit_int32(buf, offset);
}
/**
 * @internal
 * @brief Emits `mov [base + offset], r16` to store a 16-bit GPR to memory.
 * @details Opcode format: 66 + 89 /r (66 is the operand-size override prefix).
 */

infix/src/arch/x64/abi_x64_emitters.c  view on Meta::CPAN

    if (dest_base >= R8_REG)
        rex |= REX_B;
    if (rex)
        emit_byte(buf, 0x40 | rex);
    emit_byte(buf, 0x89);
    uint8_t mod = (offset >= -128 && offset <= 127) ? 0x40 : 0x80;
    if (offset == 0 && (dest_base % 8) != RBP_REG)
        mod = 0x00;
    emit_modrm(buf, mod >> 6, src % 8, dest_base % 8);
    if (dest_base % 8 == RSP_REG)
        emit_byte(buf, 0x24);
    if (mod == 0x40)
        emit_byte(buf, (uint8_t)offset);
    else if (mod == 0x80)
        emit_int32(buf, offset);
}
/**
 * @internal
 * @brief Emits `mov [base + offset], r8` to store an 8-bit GPR to memory.
 * @details Opcode format: 88 /r
 */

infix/src/arch/x64/abi_x64_emitters.c  view on Meta::CPAN

    if (dest_base >= R8_REG)
        rex |= REX_B;
    if (rex)
        emit_byte(buf, rex);
    emit_byte(buf, 0x88);
    uint8_t mod = (offset >= -128 && offset <= 127) ? 0x40 : 0x80;
    if (offset == 0 && (dest_base % 8) != RBP_REG)
        mod = 0x00;
    emit_modrm(buf, mod >> 6, src % 8, dest_base % 8);
    if (dest_base % 8 == RSP_REG)
        emit_byte(buf, 0x24);
    if (mod == 0x40)
        emit_byte(buf, (uint8_t)offset);
    else if (mod == 0x80)
        emit_int32(buf, offset);
}
// Memory <-> XMM/YMM (SSE/AVX) Emitters
/**
 * @internal
 * @brief Emits `movss xmm, [base + offset]` to load a 32-bit float from memory.
 * @details Opcode format: F3 0F 10 /r

infix/src/arch/x64/abi_x64_emitters.c  view on Meta::CPAN

    if (src_base >= R8_REG)
        rex |= REX_B;
    if (rex)
        emit_byte(buf, 0x40 | rex);
    EMIT_BYTES(buf, 0x0F, 0x10);
    uint8_t mod = (offset >= -128 && offset <= 127) ? 0x40 : 0x80;
    if (offset == 0 && (src_base % 8) != RBP_REG)
        mod = 0x00;
    emit_modrm(buf, mod >> 6, dest % 8, src_base % 8);
    if (src_base % 8 == RSP_REG)
        emit_byte(buf, 0x24);
    if (mod == 0x40)
        emit_byte(buf, (uint8_t)offset);
    else if (mod == 0x80)
        emit_int32(buf, offset);
}
/**
 * @internal
 * @brief Emits `movss [base + offset], xmm` to store a 32-bit float to memory.
 * @details Opcode format: F3 0F 11 /r
 */

infix/src/arch/x64/abi_x64_emitters.c  view on Meta::CPAN

    if (dest_base >= R8_REG)
        rex |= REX_B;
    if (rex)
        emit_byte(buf, 0x40 | rex);
    EMIT_BYTES(buf, 0x0F, 0x11);
    uint8_t mod = (offset >= -128 && offset <= 127) ? 0x40 : 0x80;
    if (offset == 0 && (dest_base % 8) != RBP_REG)
        mod = 0x00;
    emit_modrm(buf, mod >> 6, src % 8, dest_base % 8);
    if (dest_base % 8 == RSP_REG)
        emit_byte(buf, 0x24);
    if (mod == 0x40)
        emit_byte(buf, (uint8_t)offset);
    else if (mod == 0x80)
        emit_int32(buf, offset);
}
/**
 * @internal
 * @brief Emits `movsd xmm, [base + offset]` to load a 64-bit double from memory.
 * @details Opcode format: F2 0F 10 /r
 */

infix/src/arch/x64/abi_x64_emitters.c  view on Meta::CPAN

    if (src_base >= R8_REG)
        rex |= REX_B;
    if (rex)
        emit_byte(buf, 0x40 | rex);
    EMIT_BYTES(buf, 0x0F, 0x10);
    uint8_t mod = (offset >= -128 && offset <= 127) ? 0x40 : 0x80;
    if (offset == 0 && (src_base % 8) != RBP_REG)
        mod = 0x00;
    emit_modrm(buf, mod >> 6, dest % 8, src_base % 8);
    if (src_base % 8 == RSP_REG)
        emit_byte(buf, 0x24);
    if (mod == 0x40)
        emit_byte(buf, (uint8_t)offset);
    else if (mod == 0x80)
        emit_int32(buf, offset);
}
/**
 * @internal
 * @brief Emits `movsd [base + offset], xmm` to store a 64-bit double to memory.
 * @details Opcode format: F2 0F 11 /r
 */

infix/src/arch/x64/abi_x64_emitters.c  view on Meta::CPAN

    if (dest_base >= R8_REG)
        rex |= REX_B;
    if (rex)
        emit_byte(buf, 0x40 | rex);
    EMIT_BYTES(buf, 0x0F, 0x11);
    uint8_t mod = (offset >= -128 && offset <= 127) ? 0x40 : 0x80;
    if (offset == 0 && (dest_base % 8) != RBP_REG)
        mod = 0x00;
    emit_modrm(buf, mod >> 6, src % 8, dest_base % 8);
    if (dest_base % 8 == RSP_REG)
        emit_byte(buf, 0x24);
    if (mod == 0x40)
        emit_byte(buf, (uint8_t)offset);
    else if (mod == 0x80)
        emit_int32(buf, offset);
}
/**
 * @internal
 * @brief Emits `movups xmm, [base + offset]` to load a 128-bit unaligned value from memory.
 * @details Opcode format: 0F 10 /r
 */

infix/src/arch/x64/abi_x64_emitters.c  view on Meta::CPAN

    if (src_base >= R8_REG)
        rex |= REX_B;
    if (rex)
        emit_byte(buf, 0x40 | rex);
    EMIT_BYTES(buf, 0x0F, 0x10);
    uint8_t mod = (offset >= -128 && offset <= 127) ? 0x40 : 0x80;
    if (offset == 0 && (src_base % 8) != RBP_REG)
        mod = 0x00;
    emit_modrm(buf, mod >> 6, dest % 8, src_base % 8);
    if (src_base % 8 == RSP_REG)
        emit_byte(buf, 0x24);
    if (mod == 0x40)
        emit_byte(buf, (uint8_t)offset);
    else if (mod == 0x80)
        emit_int32(buf, offset);
}
/**
 * @internal
 * @brief Emits `movups [base + offset], xmm` to store a 128-bit unaligned value to memory.
 * @details Opcode format: 0F 11 /r
 */

infix/src/arch/x64/abi_x64_emitters.c  view on Meta::CPAN

    if (dest_base >= R8_REG)
        rex |= REX_B;
    if (rex)
        emit_byte(buf, 0x40 | rex);
    EMIT_BYTES(buf, 0x0F, 0x11);
    uint8_t mod = (offset >= -128 && offset <= 127) ? 0x40 : 0x80;
    if (offset == 0 && (dest_base % 8) != RBP_REG)
        mod = 0x00;
    emit_modrm(buf, mod >> 6, src % 8, dest_base % 8);
    if (dest_base % 8 == RSP_REG)
        emit_byte(buf, 0x24);
    if (mod == 0x40)
        emit_byte(buf, (uint8_t)offset);
    else if (mod == 0x80)
        emit_int32(buf, offset);
}
/**
 * @internal
 * @brief Emits a VEX prefix for an AVX instruction.
 * @details This helper centralizes the logic of choosing between 2-byte (C5) and 3-byte (C4) VEX encodings.
 */

infix/src/arch/x64/abi_x64_emitters.c  view on Meta::CPAN

    // VEX prefix fields for vmovupd ymm, m256:
    // L=1 (256-bit), p=1 (from 66 prefix), m-mmmm=01 (from 0F map).
    // The vvvv field is not used for a memory source and should be 0.
    emit_vex_prefix(buf, dest >= XMM8_REG, 0, src_base >= R8_REG, 1, false, 0, true, 1);
    emit_byte(buf, 0x10);  // Opcode for MOVUPD
    uint8_t mod = (offset >= -128 && offset <= 127) ? 0x40 : 0x80;
    if (offset == 0 && (src_base % 8) != RBP_REG)
        mod = 0x00;
    emit_modrm(buf, mod >> 6, dest % 8, src_base % 8);
    if (src_base % 8 == RSP_REG)
        emit_byte(buf, 0x24);
    if (mod == 0x40)
        emit_byte(buf, (uint8_t)offset);
    else if (mod == 0x80)
        emit_int32(buf, offset);
}
/**
 * @internal
 * @brief Emits `vmovupd [base + offset], ymm` to store a 256-bit unaligned value (AVX).
 * @details Instruction format: VEX.256.66.0F.WIG 11 /r
 */
INFIX_INTERNAL void emit_vmovupd_mem_ymm(code_buffer * buf, x64_gpr dest_base, int32_t offset, x64_xmm src) {
    // For a store, the VEX.vvvv field is not used and should be 0.
    emit_vex_prefix(buf, src >= XMM8_REG, 0, dest_base >= R8_REG, 1, false, 0, true, 1);
    emit_byte(buf, 0x11);  // Opcode for MOVUPD (store)
    uint8_t mod = (offset >= -128 && offset <= 127) ? 0x40 : 0x80;
    if (offset == 0 && (dest_base % 8) != RBP_REG)
        mod = 0x00;
    emit_modrm(buf, mod >> 6, src % 8, dest_base % 8);
    if (dest_base % 8 == RSP_REG)
        emit_byte(buf, 0x24);
    if (mod == 0x40)
        emit_byte(buf, (uint8_t)offset);
    else if (mod == 0x80)
        emit_int32(buf, offset);
}
/**
 * @internal
 * @brief Emits `vmovupd zmm, [base + offset]` to load a 512-bit unaligned value (AVX-512).
 * @details Instruction format: EVEX.512.66.0F.W0 10 /r
 */

infix/src/arch/x64/abi_x64_emitters.c  view on Meta::CPAN

                     true,   // L'=1 for 512-bit
                     false,
                     false,
                     0);
    emit_byte(buf, 0x10);  // Opcode for MOVUPD
    uint8_t mod = (offset >= -128 && offset <= 127) ? 0x40 : 0x80;
    if (offset == 0 && (src_base % 8) != RBP_REG)
        mod = 0x00;
    emit_modrm(buf, mod >> 6, dest % 8, src_base % 8);
    if (src_base % 8 == RSP_REG)
        emit_byte(buf, 0x24);
    if (mod == 0x40)
        emit_byte(buf, (uint8_t)offset);
    else if (mod == 0x80)
        emit_int32(buf, offset);
}
/**
 * @internal
 * @brief Emits `vmovupd [base + offset], zmm` to store a 512-bit unaligned value (AVX-512).
 * @details Instruction format: EVEX.512.66.0F.W0 11 /r
 */

infix/src/arch/x64/abi_x64_emitters.c  view on Meta::CPAN

                     true,   // L'=1 for 512-bit
                     false,  // z=0
                     false,  // b=0
                     0);     // aaa=0
    emit_byte(buf, 0x11);    // Opcode for MOVUPD (store)
    uint8_t mod = (offset >= -128 && offset <= 127) ? 0x40 : 0x80;
    if (offset == 0 && (dest_base % 8) != RBP_REG)
        mod = 0x00;
    emit_modrm(buf, mod >> 6, src % 8, dest_base % 8);
    if (dest_base % 8 == RSP_REG)
        emit_byte(buf, 0x24);
    if (mod == 0x40)
        emit_byte(buf, (uint8_t)offset);
    else if (mod == 0x80)
        emit_int32(buf, offset);
}
/**
 * @internal
 * @brief Emits `vzeroupper` to clear the upper bits of all YMM/ZMM registers.
 * @details Opcode format: VEX.128.0F.77
 */

infix/src/arch/x64/abi_x64_emitters.c  view on Meta::CPAN


    EMIT_BYTES(buf, 0x0F, 0x5A);  // Opcode for CVTSD2SS

    uint8_t mod = (offset >= -128 && offset <= 127) ? 0x40 : 0x80;
    if (offset == 0 && (src_base % 8) != RBP_REG)
        mod = 0x00;

    emit_modrm(buf, mod >> 6, dest % 8, src_base % 8);

    if (src_base % 8 == RSP_REG)
        emit_byte(buf, 0x24);  // SIB byte for RSP base

    if (mod == 0x40)
        emit_byte(buf, (uint8_t)offset);
    else if (mod == 0x80)
        emit_int32(buf, offset);
}

/**
 * @internal
 * @brief Emits `movaps xmm1, xmm2/m128` to move 128 bits between XMM registers.

infix/src/arch/x64/abi_x64_emitters.c  view on Meta::CPAN

    if (base >= R8_REG)
        rex |= REX_B;
    if (rex)
        emit_byte(buf, 0x40 | rex);
    emit_byte(buf, 0xDB);
    uint8_t mod = (offset >= -128 && offset <= 127) ? 0x40 : 0x80;
    if (offset == 0 && (base % 8) != RBP_REG)
        mod = 0x00;
    emit_modrm(buf, mod >> 6, 5, base % 8);  // reg field is 5 for this instruction
    if (base % 8 == RSP_REG)
        emit_byte(buf, 0x24);
    if (mod == 0x40)
        emit_byte(buf, (uint8_t)offset);
    else if (mod == 0x80)
        emit_int32(buf, offset);
}
/**
 * @internal
 * @brief Emits `fstpt [base + offset]` to store and pop an 80-bit `long double`.
 * @details Opcode format: DB /7
 */

infix/src/arch/x64/abi_x64_emitters.c  view on Meta::CPAN

    if (base >= R8_REG)
        rex |= REX_B;
    if (rex)
        emit_byte(buf, 0x40 | rex);
    emit_byte(buf, 0xDB);
    uint8_t mod = (offset >= -128 && offset <= 127) ? 0x40 : 0x80;
    if (offset == 0 && (base % 8) != RBP_REG)
        mod = 0x00;
    emit_modrm(buf, mod >> 6, 7, base % 8);  // reg field is 7 for this instruction
    if (base % 8 == RSP_REG)
        emit_byte(buf, 0x24);
    if (mod == 0x40)
        emit_byte(buf, (uint8_t)offset);
    else if (mod == 0x80)
        emit_int32(buf, offset);
}
// Arithmetic & Logic Emitters
/**
 * @internal
 * @brief Emits `lea r64, [base + offset]` to load an effective address.
 * @details Opcode format: REX.W + 8D /r
 */
INFIX_INTERNAL void emit_lea_reg_mem(code_buffer * buf, x64_gpr dest, x64_gpr src_base, int32_t offset) {
    emit_rex_prefix(buf, 1, dest >= R8_REG, 0, src_base >= R8_REG);
    emit_byte(buf, 0x8D);
    uint8_t mod = (offset >= -128 && offset <= 127) ? 0x40 : 0x80;
    if (offset == 0 && (src_base % 8) != RBP_REG)
        mod = 0x00;
    emit_modrm(buf, mod >> 6, dest % 8, src_base % 8);
    if (src_base % 8 == RSP_REG)
        emit_byte(buf, 0x24);
    if (mod == 0x40)
        emit_byte(buf, (uint8_t)offset);
    else if (mod == 0x80)
        emit_int32(buf, offset);
}
/**
 * @internal
 * @brief Emits `add r64, imm32` to add a 32-bit immediate to a GPR.
 * @details Opcode format: REX.W + 81 /0 id
 */



( run in 2.130 seconds using v1.01-cache-2.11-cpan-5a3173703d6 )