Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added start in mips16 mode support, and unit test for it - on dev branch #2089

Merged
merged 1 commit into from
Jan 19, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 14 additions & 3 deletions qemu/target/mips/unicorn.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,18 @@ MIPSCPU *cpu_mips_init(struct uc_struct *uc);

static void mips_set_pc(struct uc_struct *uc, uint64_t address)
{
((CPUMIPSState *)uc->cpu->env_ptr)->active_tc.PC = address;
((CPUMIPSState *)uc->cpu->env_ptr)->active_tc.PC = address & ~(uint64_t )1ULL;
if (address & 1) {
((CPUMIPSState *)uc->cpu->env_ptr)->hflags |= MIPS_HFLAG_M16;
} else {
((CPUMIPSState *)uc->cpu->env_ptr)->hflags &= ~(MIPS_HFLAG_M16);
}
}

static uint64_t mips_get_pc(struct uc_struct *uc)
{
return ((CPUMIPSState *)uc->cpu->env_ptr)->active_tc.PC;
return ((CPUMIPSState *)uc->cpu->env_ptr)->active_tc.PC |
!!(((CPUMIPSState *)uc->cpu->env_ptr)->hflags & (MIPS_HFLAG_M16));
}

static void mips_release(void *ctx)
Expand Down Expand Up @@ -128,7 +134,12 @@ uc_err reg_write(void *_env, int mode, unsigned int regid, const void *value,
break;
case UC_MIPS_REG_PC:
CHECK_REG_TYPE(mipsreg_t);
env->active_tc.PC = *(mipsreg_t *)value;
env->active_tc.PC = *(mipsreg_t *)value & ~1ULL;
if ((*(uint32_t *)value & 1)) {
env->hflags |= MIPS_HFLAG_M16;
} else {
env->hflags &= ~(MIPS_HFLAG_M16);
}
*setpc = 1;
break;
case UC_MIPS_REG_CP0_CONFIG3:
Expand Down
31 changes: 26 additions & 5 deletions tests/unit/test_mips.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ static void test_mips_el_ori(void)
char code[] = "\x56\x34\x21\x34"; // ori $at, $at, 0x3456;
int r_r1 = 0x6789;

uc_common_setup(&uc, UC_ARCH_MIPS, UC_MODE_32 | UC_MODE_LITTLE_ENDIAN, code,
uc_common_setup(&uc, UC_ARCH_MIPS, UC_MODE_MIPS32 | UC_MODE_LITTLE_ENDIAN, code,
sizeof(code) - 1);
OK(uc_reg_write(uc, UC_MIPS_REG_1, &r_r1));

Expand All @@ -36,7 +36,7 @@ static void test_mips_eb_ori(void)
char code[] = "\x34\x21\x34\x56"; // ori $at, $at, 0x3456;
int r_r1 = 0x6789;

uc_common_setup(&uc, UC_ARCH_MIPS, UC_MODE_32 | UC_MODE_BIG_ENDIAN, code,
uc_common_setup(&uc, UC_ARCH_MIPS, UC_MODE_MIPS32 | UC_MODE_BIG_ENDIAN, code,
sizeof(code) - 1);
OK(uc_reg_write(uc, UC_MIPS_REG_1, &r_r1));

Expand All @@ -56,7 +56,7 @@ static void test_mips_stop_at_branch(void)
"\x02\x00\x00\x08\x00\x00\x00\x00\x00\x00\x00\x00"; // j 0x8; nop;
int r_pc = 0x0;

uc_common_setup(&uc, UC_ARCH_MIPS, UC_MODE_32 | UC_MODE_LITTLE_ENDIAN, code,
uc_common_setup(&uc, UC_ARCH_MIPS, UC_MODE_MIPS32 | UC_MODE_LITTLE_ENDIAN, code,
sizeof(code) - 1);

// Execute one instruction with branch delay slot.
Expand All @@ -78,7 +78,7 @@ static void test_mips_stop_at_delay_slot(void)
"\x02\x00\x00\x08\x00\x00\x00\x00\x00\x00\x00\x00"; // j 0x8; nop;
int r_pc = 0x0;

uc_common_setup(&uc, UC_ARCH_MIPS, UC_MODE_32 | UC_MODE_LITTLE_ENDIAN, code,
uc_common_setup(&uc, UC_ARCH_MIPS, UC_MODE_MIPS32 | UC_MODE_LITTLE_ENDIAN, code,
sizeof(code) - 1);

// Stop at the delay slot by design.
Expand All @@ -99,7 +99,7 @@ static void test_mips_lwx_exception_issue_1314(void)
char code[] = "\x0a\xc8\x79\x7e"; // lwx $t9, $t9($s3)
int reg;

uc_common_setup(&uc, UC_ARCH_MIPS, UC_MODE_32 | UC_MODE_LITTLE_ENDIAN, code,
uc_common_setup(&uc, UC_ARCH_MIPS, UC_MODE_MIPS32 | UC_MODE_LITTLE_ENDIAN, code,
sizeof(code) - 1);
OK(uc_mem_map(uc, 0x10000, 0x4000, UC_PROT_ALL));

Expand All @@ -126,10 +126,31 @@ static void test_mips_lwx_exception_issue_1314(void)
OK(uc_close(uc));
}

static void test_mips_mips16(void)
{
uc_engine *uc;
char code[] = "\xC4\x6B\x49\xE3"; // li $v1, 0xC4; addu $v0, $v1, $v0
int r_v0 = 0x6789;
int mips16_lowbit = 1;

uc_common_setup(&uc, UC_ARCH_MIPS, UC_MODE_MIPS32 | UC_MODE_LITTLE_ENDIAN, code,
sizeof(code) - 1);
OK(uc_reg_write(uc, UC_MIPS_REG_V0, &r_v0));

OK(uc_emu_start(uc, code_start | mips16_lowbit, code_start + sizeof(code) - 1, 0, 0));

OK(uc_reg_read(uc, UC_MIPS_REG_V0, &r_v0));

TEST_CHECK(r_v0 == 0x684D);

OK(uc_close(uc));
}

TEST_LIST = {
{"test_mips_stop_at_branch", test_mips_stop_at_branch},
{"test_mips_stop_at_delay_slot", test_mips_stop_at_delay_slot},
{"test_mips_el_ori", test_mips_el_ori},
{"test_mips_eb_ori", test_mips_eb_ori},
{"test_mips_lwx_exception_issue_1314", test_mips_lwx_exception_issue_1314},
{"test_mips_mips16", test_mips_mips16},
{NULL, NULL}};
Loading