Commit c0f5f9ce authored by Petar Jovanovic's avatar Petar Jovanovic Committed by Aurelien Jarno
Browse files

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: default avatarPetar Jovanovic <petar.jovanovic@imgtec.com>
Signed-off-by: default avatarAurelien Jarno <aurelien@aurel32.net>
parent 639eadb9
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -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
+13 −0
Original line number Diff line number Diff line
@@ -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;
}