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

target-mips: fix EXTPDP and setting up pos field in the DSPControl reg



This change makes sure that modifications of pos field in the DSPControl
register do not trash other bits in the register. This bug can be triggered
with the additional test case in mips32-dsp/extpdp.c in this commit.

In addition to this, this change corrects incorrect calculation of the mask
for EXTPDP.

Signed-off-by: default avatarPetar Jovanovic <petar.jovanovic@imgtec.com>
Signed-off-by: default avatarAurelien Jarno <aurelien@aurel32.net>
parent 489ed4bb
Loading
Loading
Loading
Loading
+5 −5
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@

#include "cpu.h"
#include "helper.h"
#include "qemu/bitops.h"

/* As the byte ordering doesn't matter, i.e. all columns are treated
   identically, these unions can be used directly.  */
@@ -90,10 +91,10 @@ static inline void set_DSPControl_pos(uint32_t pos, CPUMIPSState *env)
    dspc = env->active_tc.DSPControl;
#ifndef TARGET_MIPS64
    dspc = dspc & 0xFFFFFFC0;
    dspc |= pos;
    dspc |= (pos & 0x3F);
#else
    dspc = dspc & 0xFFFFFF80;
    dspc |= pos;
    dspc |= (pos & 0x7F);
#endif
    env->active_tc.DSPControl = dspc;
}
@@ -3439,10 +3440,9 @@ target_ulong helper_extpdp(target_ulong ac, target_ulong size,
    if (sub >= -1) {
        acc  = ((uint64_t)env->active_tc.HI[ac] << 32) |
               ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO);
        temp = (acc >> (start_pos - size)) &
               (((uint32_t)0x01 << (size + 1)) - 1);
        temp = extract64(acc, start_pos - size, size + 1);

        set_DSPControl_pos(start_pos - (size + 1), env);
        set_DSPControl_pos(sub, env);
        set_DSPControl_efi(0, env);
    } else {
        set_DSPControl_efi(1, env);
+18 −0
Original line number Diff line number Diff line
@@ -42,5 +42,23 @@ int main()
    efi = (dsp >> 14) & 0x01;
    assert(efi == 1);


    ach = 0;
    acl = 0;
    dsp = 0;
    result = 0;

    __asm
        ("wrdsp %1\n\t"
         "mthi %2, $ac1\n\t"
         "mtlo %3, $ac1\n\t"
         "extpdp %0, $ac1, 0x00\n\t"
         "rddsp %1\n\t"
         : "=r"(rt), "+r"(dsp)
         : "r"(ach), "r"(acl)
        );
    assert(dsp == 0x3F);
    assert(result == rt);

    return 0;
}