Hey,
I’m working on an AVX lifter and constantly run into issues with hexrays probably stumbling over my emitted microcode.
Concrete example from a small program I wrote to test AVX coverage in my lifter:
; =============== S U B R O U T I N E =======================================
; __int64 test_horizontal(void)
public test_horizontal
test_horizontal proc near ; CODE XREF: main+32↑p
; __unwind {
endbr64
vxorps xmm0, xmm0, xmm0
mov edi, 2
mov eax, 1
lea rsi, aHorizontalTest ; "Horizontal test: %f\n"
vcvtss2sd xmm0, xmm0, dword ptr cs:ymmword_2260
jmp ___printf_chk
; } // starts at 1280
test_horizontal endp
The following code of the lifter is responsible for vcvtss2sd instructions:
merror_t lift_conversion(codegen_t &cdg)
{
TRACE_FUNC;
// Case: vcvtsi2ss xmm1, xmm2, r/m32 OR r/m64
// ...
// Case: vcvtss2sd xmm1, xmm2, xmm3/m32
if (cdg.insn.itype == NN_vcvtss2sd)
{
mreg_t src_vec1 = load_operand_safe(cdg, 1, SZ_XMM); // Op2 (xmm2) - Pass through
mreg_t src_vec2 = load_operand_safe(cdg, 2, SZ_XMM); // Op3 (xmm3/mem) - Converted
mreg_t dst = reg2mreg(cdg.insn.Op1.reg);
if (src_vec1 == mr_none || src_vec2 == mr_none || dst == mr_none) return MERR_INSN;
tinfo_t vec_type_s = get_vector_type(SZ_XMM, false, false); // __m128
tinfo_t vec_type_d = get_vector_type(SZ_XMM, false, true); // __m128d
IntrinsicBuilder ib(cdg, "_mm_cvtss_sd");
ib.add_arg_reg(src_vec1, vec_type_d); // First arg is __m128d (pass-through upper)
ib.add_arg_reg(src_vec2, vec_type_s); // Second arg is __m128 (source scalar)
ib.set_return_type(vec_type_d);
if (ib.emit(dst) == mr_none) return MERR_INSN;
return MERR_OK;
}
return MERR_INSN;
}
Annoyingly, even with lots of debugging I keep stumbling over the same error:
[AVX] Match found for itype 1114 at 1284
[AVX] >> Enter apply (EA: 1284)
[AVX] >> Enter lift_logic (EA: 1284)
[AVX] >> Enter load_operand_safe (EA: 1284)
[AVX] [TRC] 1284: Loading Op 1: Type=1, Dtype=8
[AVX] [TRC] 1284: -> Register 64 mapped to mreg 480
[AVX] << Exit load_operand_safe (EA: 1284)
[AVX] >> Enter load_operand_safe (EA: 1284)
[AVX] [TRC] 1284: Loading Op 2: Type=1, Dtype=8
[AVX] [TRC] 1284: -> Register 64 mapped to mreg 480
[AVX] << Exit load_operand_safe (EA: 1284)
[AVX] Resolving type: __m128
[AVX] Found named type: __m128 (Size: 16)
[AVX] [TRC] 1284: IntrinsicBuilder ctor: _mm_xor_ps
[AVX] [TRC] 1284: Adding arg reg: 480
[AVX] [TYPE] Arg Type: __m128 (Size: 16, Empty: 0)
[AVX] [TRC] 1284: Adding arg reg: 480
[AVX] [TYPE] Arg Type: __m128 (Size: 16, Empty: 0)
[AVX] [TYPE] Return Type: __m128 (Size: 16, Empty: 0)
[AVX] >> Enter emit (EA: 1284)
[AVX] [TRC] 1284: Constructing m_call instruction...
[AVX] [TRC] 1284: Constructing m_mov instruction to dst 480 (size 16)...
[AVX] [TRC] 1284: Inserting into block @ 0x5f6e7b05cc60
[AVX] [INF] 1284: Emitted intrinsic _mm_xor_ps -> mreg 480
[AVX] << Exit emit (EA: 1284)
[AVX] [TRC] 1284: IntrinsicBuilder dtor: Ownership transferred for _mm_xor_ps
[AVX] << Exit lift_logic (EA: 1284)
[AVX] << Exit apply (EA: 1284)
[AVX] Match found for itype 810 at 1299
[AVX] >> Enter apply (EA: 1299)
[AVX] >> Enter lift_conversion (EA: 1299)
[AVX] >> Enter load_operand_safe (EA: 1299)
[AVX] [TRC] 1299: Loading Op 1: Type=1, Dtype=8
[AVX] [TRC] 1299: -> Register 64 mapped to mreg 480
[AVX] << Exit load_operand_safe (EA: 1299)
[AVX] >> Enter load_operand_safe (EA: 1299)
[AVX] [TRC] 1299: Loading Op 2: Type=2, Dtype=2
[AVX] [TRC] 1299: -> Memory operand loaded to mreg 176
[AVX] << Exit load_operand_safe (EA: 1299)
[AVX] Resolving type: __m128
[AVX] Found named type: __m128 (Size: 16)
[AVX] Resolving type: __m128d
[AVX] Found named type: __m128d (Size: 16)
[AVX] [TRC] 1299: IntrinsicBuilder ctor: _mm_cvtss_sd
[AVX] [TRC] 1299: Adding arg reg: 480
[AVX] [TYPE] Arg Type: __m128d (Size: 16, Empty: 0)
[AVX] [TRC] 1299: Adding arg reg: 176
[AVX] [TYPE] Arg Type: __m128 (Size: 16, Empty: 0)
[AVX] [TYPE] Return Type: __m128d (Size: 16, Empty: 0)
[AVX] >> Enter emit (EA: 1299)
[AVX] [TRC] 1299: Constructing m_call instruction...
[AVX] [TRC] 1299: Constructing m_mov instruction to dst 480 (size 16)...
[AVX] [TRC] 1299: Inserting into block @ 0x5f6e7b05cc60
[AVX] [INF] 1299: Emitted intrinsic _mm_cvtss_sd -> mreg 480
[AVX] << Exit emit (EA: 1299)
[AVX] [TRC] 1299: IntrinsicBuilder dtor: Ownership transferred for _mm_cvtss_sd
[AVX] << Exit lift_conversion (EA: 1299)
[AVX] << Exit apply (EA: 1299)
1280: INTERR 50836
I also stumbled over another INTERR which I can’t replicate right now.
For one:
- What does 50836 mean exactly? From reverse engineering my understanding is that this represents an invalid instruction?
- For the love of god, please document all of these error codes because it’s making my life an absolute agony.
Thanks!