Skip to content

Commit

Permalink
Support MIPS64 - write correct PC register width on uc_emu_start (#2111)
Browse files Browse the repository at this point in the history
* Support mips64 - write correct pc register width on uc_emu_start

* Convert to UC_MODE_MIPS64

* Correctly select MIPS64 CPU model

* Simple 64-bit test - check it doesn't crash

* lint

* Comment

* Comment

* Add offset when indexing cpu model, makes tests work on older python

* Move test

* add PC check to test

* Fix test - add python version check

* Use RegressTest method for assert
  • Loading branch information
OBarronCS authored Feb 21, 2025
1 parent 56ba347 commit 76d97f8
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 3 deletions.
7 changes: 6 additions & 1 deletion qemu/target/mips/cpu.c
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,12 @@ MIPSCPU *cpu_mips_init(struct uc_struct *uc)
mips_cpu_initfn(uc, cs);

env = &cpu->env;
env->cpu_model = &(mips_defs[uc->cpu_model]);
if(uc->mode & UC_MODE_MIPS64){
// 64-bit CPU models are defined in the array directly after 32-bit models
env->cpu_model = &(mips_defs[uc->cpu_model + UC_CPU_MIPS32_ENDING]);
} else {
env->cpu_model = &(mips_defs[uc->cpu_model]);
}

if (env->cpu_model == NULL) {
free(cpu);
Expand Down
39 changes: 39 additions & 0 deletions tests/regress/mips64.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import sys
import unittest
import regress
from unicorn import *
from unicorn.mips_const import *


class Mips64(regress.RegressTest):

@unittest.skipIf(sys.version_info < (3, 7), reason="requires python3.7 or higher")
def runTest(self):
# Two instructions:
# daddu $gp, $gp, $ra # a 64-bit instruction. This is important - it ensures the selected CPU model is 64-bit, otherwise it would crash
# move $t1, $v0

code = b"\x03\x9f\xe0\x2d" + b"\x00\x40\x48\x25"

uc = Uc(UC_ARCH_MIPS, UC_MODE_MIPS64 + UC_MODE_BIG_ENDIAN)
# For MIPS64 to be able to reference addresses >= 0x80000000, you need to enable the virtual TLB
# See https://github.com/unicorn-engine/unicorn/pull/2111 for more details
uc.ctl_set_tlb_mode(UC_TLB_VIRTUAL)

ADDRESS = 0x0120003000

uc.reg_write(UC_MIPS_REG_PC, ADDRESS)
uc.reg_write(UC_MIPS_REG_GP, 0x123)
uc.reg_write(UC_MIPS_REG_RA, 0x456)

uc.mem_map(ADDRESS, 4 * 1024)
uc.mem_write(ADDRESS, code)

# This will raise an exception if MIPS64 fails
uc.emu_start(ADDRESS, 0, count=2)

self.assertEqual(uc.reg_read(UC_MIPS_REG_PC),0x0120003000 + 8)


if __name__ == '__main__':
regress.main()
7 changes: 5 additions & 2 deletions uc.c
Original file line number Diff line number Diff line change
Expand Up @@ -1020,8 +1020,11 @@ uc_err uc_emu_start(uc_engine *uc, uint64_t begin, uint64_t until,
#endif
#ifdef UNICORN_HAS_MIPS
case UC_ARCH_MIPS:
// TODO: MIPS32/MIPS64/BIGENDIAN etc
uc_reg_write(uc, UC_MIPS_REG_PC, &begin_pc32);
if (uc->mode & UC_MODE_MIPS64) {
uc_reg_write(uc, UC_MIPS_REG_PC, &begin);
} else {
uc_reg_write(uc, UC_MIPS_REG_PC, &begin_pc32);
}
break;
#endif
#ifdef UNICORN_HAS_SPARC
Expand Down

0 comments on commit 76d97f8

Please sign in to comment.