unicorn-engine / unicorn

Unicorn CPU emulator framework (ARM, AArch64, M68K, Mips, Sparc, PowerPC, RiscV, S390x, TriCore, X86)
http://www.unicorn-engine.org
GNU General Public License v2.0
7.68k stars 1.35k forks source link

x86 avx does not work #1879

Open shuffle2 opened 1 year ago

shuffle2 commented 1 year ago

here is some example code:

can this work somehow, or does unicorn need to be changed to support avx? I came across this problem in some project I was working on, and solved it a different way (without unicorn), since it didn't seem to work. But it would be nice to know what's going on.

#!/usr/bin/env python3
from unicorn import *
from unicorn.x86_const import *

'''
// documented as:
// __m256 _mm256_loadu_ps (float const * mem_addr)
// #include <immintrin.h>
// Instruction: vmovups ymm, m256
// CPUID Flags: AVX
vmovups ymm0, ymmword ptr [rax]
vmovups ymmword ptr [rbx], ymm0
'''
code = bytes.fromhex('C5FC1000C5FC1103')
code_cpuid = bytes.fromhex('0FA2')

uc = Uc(UC_ARCH_X86, UC_MODE_64)
# this line makes no difference
uc.ctl_set_cpu_model(UC_CPU_X86_EPYC_ROME)
uc.mem_map(0, 0x1000)
uc.mem_write(0, code)
uc.mem_write(0x100, code_cpuid)
uc.mem_map(0x10000, 0x1000)
uc.mem_write(0x10000, b'A'*0x20)

# get cpuid output
uc.reg_write(UC_X86_REG_EAX, 1)
uc.reg_write(UC_X86_REG_ECX, 0)
uc.emu_start(0x100, 0x100+len(code_cpuid))
r = [uc.reg_read(x) for x in (UC_X86_REG_EAX, UC_X86_REG_EBX, UC_X86_REG_ECX, UC_X86_REG_EDX)]
print(f'cpuid(eax=1,ecx=0): eax:{r[0]:8x} ebx:{r[1]:8x} ecx:{r[2]:8x} edx:{r[3]:8x}')
ecx = r[2]
xsave, osxsave, avx = (ecx >> 26) & 1, (ecx >> 27) & 1, (ecx >> 28) & 1
print(f'xsave:{xsave} osxsave:{osxsave} avx:{avx}')

# try the avx code
uc.reg_write(UC_X86_REG_RAX, 0x10000)
uc.reg_write(UC_X86_REG_RBX, 0x10100)
# will get UC_ERR_INSN_INVALID
uc.emu_start(0, len(code))
output = uc.mem_read(0x10100, 0x20)
print(output.hex())
assert output == b'A'*0x20

the output:

cpuid(eax=1,ecx=0): eax:  830f10 ebx:     800 ecx: 2182200 edx: 7088100
xsave:0 osxsave:0 avx:0
Traceback (most recent call last):
  File "unicorn_avx_test.py", line 35, in <module>
    uc.emu_start(0, len(code))
  File "C:\Users\username\AppData\Local\Programs\Python\Python311\Lib\site-packages\unicorn\unicorn.py", line 547, in emu_start
    raise UcError(status)
unicorn.unicorn.UcError: Invalid instruction (UC_ERR_INSN_INVALID)
wtdcode commented 1 year ago

Conclusion:

shuffle2 commented 1 year ago

Is it likely qemu would be updated? Or is that a big task?

wtdcode commented 1 year ago

Is it likely qemu would be updated? Or is that a big task?

I once worked on bumping qemu to 5.1.0. The work itself is not difficult or hard but just too tedious.

Actually probably we don't need to upgrade qemu but it's much easier to just port the avx decoding code back.