fix(m68k): correct SR register read (#2161)
The SR register in the `CPUM68KState` struct does not contain the value of the lower 5 flags. To compute them, we must OR the CCR values with the SR register to get the true SR value.
This commit is contained in:
@@ -20,3 +20,22 @@ fn test_move_to_sr() {
|
||||
let sr = uc.reg_read(RegisterM68K::SR).unwrap();
|
||||
assert_eq!(sr, 0x2700);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_sr_contains_flags() {
|
||||
let code = [
|
||||
0x76, 0xed, // moveq #-19, %d3
|
||||
];
|
||||
|
||||
let mut uc = uc_common_setup(Arch::M68K, Mode::BIG_ENDIAN, None, &code, ());
|
||||
|
||||
uc.emu_start(CODE_START, CODE_START + code.len() as u64, 0, 0)
|
||||
.unwrap();
|
||||
|
||||
let d3 = uc.reg_read(RegisterM68K::D3).unwrap();
|
||||
assert_eq!(d3, 0xffffffed);
|
||||
|
||||
let sr = uc.reg_read(RegisterM68K::SR).unwrap();
|
||||
let is_negative = sr & 0x8 == 0x8;
|
||||
assert!(is_negative, "SR should contain negative flag");
|
||||
}
|
||||
|
||||
@@ -1372,6 +1372,7 @@
|
||||
#define helper_bitrev helper_bitrev_m68k
|
||||
#define helper_ff1 helper_ff1_m68k
|
||||
#define helper_sats helper_sats_m68k
|
||||
#define cpu_m68k_get_sr cpu_m68k_get_sr_m68k
|
||||
#define cpu_m68k_set_sr cpu_m68k_set_sr_m68k
|
||||
#define helper_set_sr helper_set_sr_m68k
|
||||
#define helper_mac_move helper_mac_move_m68k
|
||||
|
||||
@@ -183,6 +183,7 @@ int cpu_m68k_signal_handler(int host_signum, void *pinfo,
|
||||
void *puc);
|
||||
uint32_t cpu_m68k_get_ccr(CPUM68KState *env);
|
||||
void cpu_m68k_set_ccr(CPUM68KState *env, uint32_t);
|
||||
uint32_t cpu_m68k_get_sr(CPUM68KState *env);
|
||||
void cpu_m68k_set_sr(CPUM68KState *env, uint32_t);
|
||||
void cpu_m68k_set_fpcr(CPUM68KState *env, uint32_t val);
|
||||
|
||||
|
||||
@@ -591,6 +591,10 @@ uint32_t HELPER(sats)(uint32_t val, uint32_t v)
|
||||
return val;
|
||||
}
|
||||
|
||||
uint32_t cpu_m68k_get_sr(CPUM68KState *env) {
|
||||
return env->sr | cpu_m68k_get_ccr(env);
|
||||
}
|
||||
|
||||
void cpu_m68k_set_sr(CPUM68KState *env, uint32_t sr)
|
||||
{
|
||||
env->sr = sr & 0xffe0;
|
||||
|
||||
@@ -72,7 +72,8 @@ uc_err reg_read(void *_env, int mode, unsigned int regid, void *value,
|
||||
break;
|
||||
case UC_M68K_REG_SR:
|
||||
CHECK_REG_TYPE(uint32_t);
|
||||
*(uint32_t *)value = env->sr;
|
||||
env->cc_op = CC_OP_FLAGS;
|
||||
*(uint32_t *)value = cpu_m68k_get_sr(env);
|
||||
break;
|
||||
case UC_M68K_REG_CR_SFC:
|
||||
CHECK_REG_TYPE(uint32_t);
|
||||
|
||||
@@ -5749,6 +5749,7 @@ m68k_cpu_tlb_fill \
|
||||
helper_bitrev \
|
||||
helper_ff1 \
|
||||
helper_sats \
|
||||
cpu_m68k_get_sr \
|
||||
cpu_m68k_set_sr \
|
||||
helper_set_sr \
|
||||
helper_mac_move \
|
||||
|
||||
@@ -37,4 +37,29 @@ static void test_move_to_sr(void)
|
||||
OK(uc_close(uc));
|
||||
}
|
||||
|
||||
TEST_LIST = {{"test_move_to_sr", test_move_to_sr}, {NULL, NULL}};
|
||||
static void test_sr_contains_flags(void)
|
||||
{
|
||||
uc_engine *uc;
|
||||
uint8_t code[] = {
|
||||
0x76, 0xed, // moveq #-19, %d3
|
||||
};
|
||||
|
||||
uint32_t d3, sr;
|
||||
|
||||
uc_common_setup(&uc, UC_ARCH_M68K, UC_MODE_BIG_ENDIAN, code, sizeof(code),
|
||||
UC_CPU_M68K_M68000);
|
||||
|
||||
OK(uc_emu_start(uc, code_start, code_start + sizeof(code), 0, 0));
|
||||
|
||||
OK(uc_reg_read(uc, UC_M68K_REG_D3, &d3));
|
||||
OK(uc_reg_read(uc, UC_M68K_REG_SR, &sr));
|
||||
|
||||
TEST_CHECK(d3 == 0xFFFFFFED);
|
||||
TEST_CHECK((sr & 0x8) /* N flag */ == 0x8);
|
||||
|
||||
OK(uc_close(uc));
|
||||
}
|
||||
|
||||
TEST_LIST = {{"test_move_to_sr", test_move_to_sr},
|
||||
{"test_sr_contains_flags", test_sr_contains_flags},
|
||||
{NULL, NULL}};
|
||||
|
||||
Reference in New Issue
Block a user