Skip to content

Commit 76d97f8

Browse files
authored
Support MIPS64 - write correct PC register width on uc_emu_start (#2111)
* 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
1 parent 56ba347 commit 76d97f8

File tree

3 files changed

+50
-3
lines changed

3 files changed

+50
-3
lines changed

qemu/target/mips/cpu.c

+6-1
Original file line numberDiff line numberDiff line change
@@ -194,7 +194,12 @@ MIPSCPU *cpu_mips_init(struct uc_struct *uc)
194194
mips_cpu_initfn(uc, cs);
195195

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

199204
if (env->cpu_model == NULL) {
200205
free(cpu);

tests/regress/mips64.py

+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import sys
2+
import unittest
3+
import regress
4+
from unicorn import *
5+
from unicorn.mips_const import *
6+
7+
8+
class Mips64(regress.RegressTest):
9+
10+
@unittest.skipIf(sys.version_info < (3, 7), reason="requires python3.7 or higher")
11+
def runTest(self):
12+
# Two instructions:
13+
# daddu $gp, $gp, $ra # a 64-bit instruction. This is important - it ensures the selected CPU model is 64-bit, otherwise it would crash
14+
# move $t1, $v0
15+
16+
code = b"\x03\x9f\xe0\x2d" + b"\x00\x40\x48\x25"
17+
18+
uc = Uc(UC_ARCH_MIPS, UC_MODE_MIPS64 + UC_MODE_BIG_ENDIAN)
19+
# For MIPS64 to be able to reference addresses >= 0x80000000, you need to enable the virtual TLB
20+
# See https://github.com/unicorn-engine/unicorn/pull/2111 for more details
21+
uc.ctl_set_tlb_mode(UC_TLB_VIRTUAL)
22+
23+
ADDRESS = 0x0120003000
24+
25+
uc.reg_write(UC_MIPS_REG_PC, ADDRESS)
26+
uc.reg_write(UC_MIPS_REG_GP, 0x123)
27+
uc.reg_write(UC_MIPS_REG_RA, 0x456)
28+
29+
uc.mem_map(ADDRESS, 4 * 1024)
30+
uc.mem_write(ADDRESS, code)
31+
32+
# This will raise an exception if MIPS64 fails
33+
uc.emu_start(ADDRESS, 0, count=2)
34+
35+
self.assertEqual(uc.reg_read(UC_MIPS_REG_PC),0x0120003000 + 8)
36+
37+
38+
if __name__ == '__main__':
39+
regress.main()

uc.c

+5-2
Original file line numberDiff line numberDiff line change
@@ -1020,8 +1020,11 @@ uc_err uc_emu_start(uc_engine *uc, uint64_t begin, uint64_t until,
10201020
#endif
10211021
#ifdef UNICORN_HAS_MIPS
10221022
case UC_ARCH_MIPS:
1023-
// TODO: MIPS32/MIPS64/BIGENDIAN etc
1024-
uc_reg_write(uc, UC_MIPS_REG_PC, &begin_pc32);
1023+
if (uc->mode & UC_MODE_MIPS64) {
1024+
uc_reg_write(uc, UC_MIPS_REG_PC, &begin);
1025+
} else {
1026+
uc_reg_write(uc, UC_MIPS_REG_PC, &begin_pc32);
1027+
}
10251028
break;
10261029
#endif
10271030
#ifdef UNICORN_HAS_SPARC

0 commit comments

Comments
 (0)