target-mips: fix incorrect behaviour for INSV

Corner case for INSV instruction when size=32 has not been correctly
implemented. The mask for size should be one bit wider, and preparing the
filter variable should be aware of this case too.

The test for INSV has been extended to include the case that triggers the
bug.

Signed-off-by: Petar Jovanovic <petar.jovanovic@imgtec.com>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
master
Petar Jovanovic 2013-05-08 13:17:40 +02:00 committed by Aurelien Jarno
parent 639eadb9a3
commit c0f5f9ce86
2 changed files with 15 additions and 2 deletions

View File

@ -2921,7 +2921,7 @@ target_ulong helper_##name(CPUMIPSState *env, target_ulong rs, \
return rt; \
} \
\
filter = ((int32_t)0x01 << size) - 1; \
filter = ((int64_t)0x01 << size) - 1; \
filter = filter << pos; \
temprs = (rs << pos) & filter; \
temprt = rt & ~filter; \
@ -2930,7 +2930,7 @@ target_ulong helper_##name(CPUMIPSState *env, target_ulong rs, \
return (target_long)(ret_type)temp; \
}
BIT_INSV(insv, 0x1F, 0x1F, int32_t);
BIT_INSV(insv, 0x1F, 0x3F, int32_t);
#ifdef TARGET_MIPS64
BIT_INSV(dinsv, 0x7F, 0x3F, target_long);
#endif

View File

@ -19,5 +19,18 @@ int main()
);
assert(rt == result);
dsp = 0x1000;
rt = 0xF0F0F0F0;
rs = 0xA5A5A5A5;
result = 0xA5A5A5A5;
__asm
("wrdsp %2\n\t"
"insv %0, %1\n\t"
: "+r"(rt)
: "r"(rs), "r"(dsp)
);
assert(rt == result);
return 0;
}