#2272·unicorn

MIPS emulation goes into “Branch in delay / forbidden slot” scenario when virtual tlb is enabled

Author: palantCreated Dec 12, 2025Updated Aug 28, 2026

The application I tried to emulate was producing Unhandled CPU exception consistently, this turned out to be unhandled interrupt 20, meaning EXCP_RI. I traced it back to this condition:

https://github.com/unicorn-engine/unicorn/blob/8028ec436f2d9376525352dd38ed9ed6b9f6be10/qemu/target/mips/translate.c#L6039-L6046

Now I am no MIPS expert but the code in question doesn’t seem to be putting a branch in a delay slot. Here is the reduced code:

python
import unicorn

uc = unicorn.Uc(
    unicorn.UC_ARCH_MIPS,
    unicorn.UC_MODE_MIPS32 | unicorn.UC_MODE_LITTLE_ENDIAN
)
uc.ctl_set_tlb_mode(unicorn.UC_TLB_VIRTUAL)

BASE = 0x1000

# b       0x1008
# lb      $v0, ($s8)
# b       0x1000
# addiu   $s0, $s0, 1
CODE = b'\x01\x00\x00\x10\x00\x00\xc2\x83\xFD\xFF\x00\x10\x01\x00\x10\x26'

uc.mem_map(BASE, 0x1000, perms=unicorn.UC_PROT_ALL)
uc.mem_write(BASE, CODE)


def hook_code(uc, addr, size, user_data):
    print(f'At address 0x{addr:x}')


uc.reg_write(unicorn.mips_const.UC_MIPS_REG_S8, BASE)
uc.hook_add(unicorn.UC_HOOK_CODE, hook_code)
uc.emu_start(BASE, BASE + len(CODE), count=20)

If I don’t enable virtual tlb this code goes into an endless loop as expected (unfortunately not an option for the real application, it has to be loaded at a high memory address). Same happens if the memory access in the delay slot of the first jump is replaced by nop or some other instruction that doesn’t access memory. But as written here the second jump triggers “reserved instruction” exception.