arch-x86: implement PSHUFB SSE instruction.

Change-Id: I9398f9ecb26b6aabf4015e0e285fdc2f4c2487dd
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/39495
Reviewed-by: Tong Shen <endlessroad@google.com>
Reviewed-by: Jason Lowe-Power <power.jg@gmail.com>
Maintainer: Jason Lowe-Power <power.jg@gmail.com>
Tested-by: kokoro <noreply+kokoro@google.com>
This commit is contained in:
Tong Shen
2021-01-20 16:11:01 -08:00
parent a701e1fd14
commit 3d257c2873
3 changed files with 42 additions and 5 deletions

View File

@@ -31,7 +31,7 @@
'X86ISA::ThreeByte0F38Opcode': decode LEGACY_OP {
format WarnUnimpl {
1: decode OPCODE_OP {
0x00: pshufb_Vdq_Wdq();
0x00: Inst::PSHUFB(Vo, Wo);
0x01: phaddw_Vdq_Wdq();
0x02: phaddd_Vdq_Wdq();
0x03: phaddsw_Vdq_Wdq();

View File

@@ -84,4 +84,32 @@ def macroop PSHUFLW_XMM_P_I {
ldfp ufp1, seg, riprel, "DISPLACEMENT", dataSize=8
shuffle xmml, ufp1, ufp1, size=2, ext=imm
};
'''
def macroop PSHUFB_XMM_XMM {
movfp ufp1, xmmlm, dataSize=8
movfp ufp2, xmmhm, dataSize=8
shuffle ufp1, xmml, xmmh, size=1, ext=0
shuffle ufp2, xmml, xmmh, size=1, ext=0
movfp xmml, ufp1, dataSize=8
movfp xmmh, ufp2, dataSize=8
};
def macroop PSHUFB_XMM_M {
ldfp ufp1, seg, sib, "DISPLACEMENT", dataSize=8
ldfp ufp2, seg, sib, "DISPLACEMENT + 8", dataSize=8
shuffle ufp1, xmml, xmmh, size=1, ext=0
shuffle ufp2, xmml, xmmh, size=1, ext=0
movfp xmml, ufp1, dataSize=8
movfp xmmh, ufp2, dataSize=8
};
def macroop PSHUFB_XMM_P {
rdip t7
ldfp ufp1, seg, riprel, "DISPLACEMENT", dataSize=8
ldfp ufp2, seg, riprel, "DISPLACEMENT + 8", dataSize=8
shuffle ufp1, xmml, xmmh, size=1, ext=0
shuffle ufp2, xmml, xmmh, size=1, ext=0
movfp xmml, ufp1, dataSize=8
movfp xmmh, ufp2, dataSize=8
};
'''

View File

@@ -337,23 +337,32 @@ let {{
if (size == 8) {
options = 2;
optionBits = 1;
} else if (size == 1) {
options = 16;
optionBits = 8;
} else {
options = 4;
optionBits = 2;
}
uint64_t result = 0;
uint8_t sel = ext;
// PSHUFB stores shuffle encoding in destination XMM register
// directly (instead of passed in by ext).
uint64_t sel = (size == 1) ? FpDestReg_uqw : ext;
for (int i = 0; i < items; i++) {
uint64_t resBits;
uint8_t lsel = sel & mask(optionBits);
if (lsel * size >= sizeof(double)) {
if (size == 1 && bits(lsel, 7)) {
// PSHUFB sets result byte to zero when highest bit of the
// corresponding shuffle encoding is 1.
resBits = 0;
} else if (lsel * size >= sizeof(double)) {
lsel -= options / 2;
resBits = bits(FpSrcReg2_uqw,
(lsel + 1) * sizeBits - 1,
(lsel + 0) * sizeBits);
} else {
} else {
resBits = bits(FpSrcReg1_uqw,
(lsel + 1) * sizeBits - 1,
(lsel + 0) * sizeBits);