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.54k stars 1.33k forks source link

PowerPC64 std / ld instructions triggers UC_ERR_EXCEPTION #1779

Open InvoxiPlayGames opened 1 year ago

InvoxiPlayGames commented 1 year ago

When setting up a Unicorn instance with UC_MODE_PPC64 as a uc_mode and UC_CPU_PPC64_970_V2_2 as the CPU model, the emulator starts executing instructions, however an UC_ERR_EXCEPTION is thrown whenever the program counter reaches a std (Store Double Word) or ld (Load Double Word) instruction. The 32-bit equivalents of these instructions (stw and lwz) have no problems executing.

Other 64-bit behaviours, from a quick glance, appear to be working, with uc_set_reg expecting and accepting 64-bit values. There are probably countless other instructions that aren't working, however...

wtdcode commented 1 year ago

Could you provide a reproduction script?

InvoxiPlayGames commented 1 year ago

Here's a Python script that reproduces the behaviour.

from unicorn import *
from unicorn.ppc_const import *

# code to be emulated - this will return an UC_ERR_EXECPTION
PPC64_CODE = b"\xF8\x64\x00\x00\xE8\x64\x00\x08" # std r3, 0(r4); ld r3, 8(r4);
# this code will write and read 32-bit integers, but does work 
#PPC64_CODE = b"\x90\x64\x00\x00\x80\x64\x00\x08" # stw r3, 0(r4); lwz r3, 8(r4);

# example number, 0x6913374200133769
DATA_TO_READ = b"\x69\x13\x37\x42\x00\x13\x37\x69"

CODE_ADDRESS = 0x1000000
DATA_ADDRESS = 0x2000000

print("Emulate powerpc64 code")
try:
    # Initialize emulator in PPC-64bit mode, emulating a POWER5
    mu = Uc(UC_ARCH_PPC, UC_MODE_PPC64 | UC_MODE_BIG_ENDIAN)
    mu.ctl_set_cpu_model(UC_CPU_PPC64_POWER5_V2_1) # machine i'm targeting is this

    # map 1MB memory for the code
    mu.mem_map(CODE_ADDRESS, 1024 * 1024)
    # map 1MB memory to be used as data space
    mu.mem_map(DATA_ADDRESS, 1024 * 1024)

    # write machine code to be emulated to memory
    mu.mem_write(CODE_ADDRESS, PPC64_CODE)
    # write an example number
    mu.mem_write(DATA_ADDRESS + 8, DATA_TO_READ)

    # initialize machine registers
    mu.reg_write(UC_PPC_REG_3, 0x12345678ABCDEF00)
    mu.reg_write(UC_PPC_REG_4, DATA_ADDRESS)

    # emulate code in infinite time & unlimited instructions
    mu.emu_start(CODE_ADDRESS, CODE_ADDRESS + len(PPC64_CODE))

    # now print out some registers
    print("Emulation done. Below is the CPU context")
    r3 = mu.reg_read(UC_PPC_REG_3)
    print(">>> R3 = 0x%x" %r3) # expected to be 0x6913374200133769
    # and the memory contents
    print("Memory contents")
    data = mu.mem_read(DATA_ADDRESS, 8)
    print(data) # expected to be 0x12345678ABCDEF00
except UcError as e:
    print("ERROR: %s" % e)
github-actions[bot] commented 1 year ago

This issue is stale because it has been open 60 days with no activity. Remove stale label or comment or this will be closed in 15 days.