Skip to content

Add support for paired-single instructions #6821

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: homegrown_powerpc
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
211 changes: 211 additions & 0 deletions arch/powerpc/decode/decode.c
Original file line number Diff line number Diff line change
Expand Up @@ -2063,6 +2063,203 @@ static InstructionId DecodeSpe0x04(uint32_t word32, uint32_t decodeFlags)
}
}

static InstructionId DecodePairedSingle0x04(uint32_t word32, uint32_t decodeFlags)
{
uint32_t a = GetA(word32);
uint32_t b = GetB(word32);
uint32_t c = GetC(word32);
uint32_t d = GetD(word32);

// see IBM Broadway RISC Microprocessor User's Manual,
// Tables A-30, A-31, and A-32
uint32_t subop = (word32 >> 1) & 0x1f;
switch (subop)
{
case 10:
return PPC_ID_PAIREDSINGLE_PS_SUM0x;

case 11:
return PPC_ID_PAIREDSINGLE_PS_SUM1x;

case 12:
if (b != 0)
return PPC_ID_INVALID;

return PPC_ID_PAIREDSINGLE_PS_MULS0x;

case 13:
if (b != 0)
return PPC_ID_INVALID;

return PPC_ID_PAIREDSINGLE_PS_MULS1x;

case 14:
return PPC_ID_PAIREDSINGLE_PS_MADDS0x;

case 15:
return PPC_ID_PAIREDSINGLE_PS_MADDS1x;

case 18:
if (c != 0)
return PPC_ID_INVALID;

return PPC_ID_PAIREDSINGLE_PS_DIVx;

case 20:
if (c != 0)
return PPC_ID_INVALID;

return PPC_ID_PAIREDSINGLE_PS_SUBx;

case 21:
if (c != 0)
return PPC_ID_INVALID;

return PPC_ID_PAIREDSINGLE_PS_ADDx;

case 23:
return PPC_ID_PAIREDSINGLE_PS_SELx;

case 24:
if ((a != 0) || (c != 0))
return PPC_ID_INVALID;

return PPC_ID_PAIREDSINGLE_PS_RESx;

case 25:
if (b != 0)
return PPC_ID_INVALID;

return PPC_ID_PAIREDSINGLE_PS_MULx;

case 26:
if ((a != 0) || (c != 0))
return PPC_ID_INVALID;

return PPC_ID_PAIREDSINGLE_PS_RSQRTEx;

case 28:
return PPC_ID_PAIREDSINGLE_PS_MSUBx;

case 29:
return PPC_ID_PAIREDSINGLE_PS_MADDx;

case 30:
return PPC_ID_PAIREDSINGLE_PS_NMSUBx;

case 31:
return PPC_ID_PAIREDSINGLE_PS_NMADDx;

default:
;
}

subop = (word32 >> 1) & 0x3f;
switch (subop)
{
case 6:
if ((word32 & 0x1) != 0)
return PPC_ID_INVALID;

return PPC_ID_PAIREDSINGLE_PSQ_LX;

case 7:
if ((word32 & 0x1) != 0)
return PPC_ID_INVALID;

return PPC_ID_PAIREDSINGLE_PSQ_STX;

case 38:
if ((word32 & 0x1) != 0)
return PPC_ID_INVALID;

return PPC_ID_PAIREDSINGLE_PSQ_LUX;

case 39:
if ((word32 & 0x1) != 0)
return PPC_ID_INVALID;

return PPC_ID_PAIREDSINGLE_PSQ_STUX;

default:
;
}

subop = (word32 >> 1) & 0x3ff;
switch (subop)
{
case 0:
if ((word32 & 0x00600001) != 0)
return PPC_ID_INVALID;

return PPC_ID_PAIREDSINGLE_PS_CMPU0;

case 32:
if ((word32 & 0x00600001) != 0)
return PPC_ID_INVALID;

return PPC_ID_PAIREDSINGLE_PS_CMPO0;

case 40:
if (a != 0)
return PPC_ID_INVALID;

return PPC_ID_PAIREDSINGLE_PS_NEGx;

case 64:
if ((word32 & 0x00600001) != 0)
return PPC_ID_INVALID;

return PPC_ID_PAIREDSINGLE_PS_CMPU1;

case 72:
if (a != 0)
return PPC_ID_INVALID;

return PPC_ID_PAIREDSINGLE_PS_MRx;

case 96:
if ((word32 & 0x00600001) != 0)
return PPC_ID_INVALID;

return PPC_ID_PAIREDSINGLE_PS_CMPO1;

case 136:
if (a != 0)
return PPC_ID_INVALID;

return PPC_ID_PAIREDSINGLE_PS_NABSx;

case 264:
if (a != 0)
return PPC_ID_INVALID;

return PPC_ID_PAIREDSINGLE_PS_ABSx;

case 528:
return PPC_ID_PAIREDSINGLE_PS_MERGE00x;

case 560:
return PPC_ID_PAIREDSINGLE_PS_MERGE01x;

case 592:
return PPC_ID_PAIREDSINGLE_PS_MERGE10x;

case 624:
return PPC_ID_PAIREDSINGLE_PS_MERGE11x;

case 1014:
if ((d != 0) || ((word32 & 0x1) != 0))
return PPC_ID_INVALID;

return PPC_ID_PAIREDSINGLE_DCBZ_L;

default:
return PPC_ID_INVALID;
}

}

static InstructionId Decode0x13(uint32_t word32, uint32_t decodeFlags)
{
uint32_t a = GetA(word32);
Expand Down Expand Up @@ -5537,6 +5734,8 @@ static InstructionId Decode32(uint32_t word32, uint32_t decodeFlags)
return DecodeAltivec0x04(word32, decodeFlags);
else if ((decodeFlags & DECODE_FLAGS_SPE))
return DecodeSpe0x04(word32, decodeFlags);
else if ((decodeFlags & DECODE_FLAGS_PS))
return DecodePairedSingle0x04(word32, decodeFlags);
else
return PPC_ID_INVALID;
}
Expand Down Expand Up @@ -5757,9 +5956,17 @@ static InstructionId Decode32(uint32_t word32, uint32_t decodeFlags)
case 0x37:
return PPC_ID_STFDU;

case 0x38:
if ((decodeFlags & DECODE_FLAGS_PS) != 0)
return PPC_ID_PAIREDSINGLE_PSQ_L;
else
return PPC_ID_INVALID;

case 0x39:
if ((decodeFlags & DECODE_FLAGS_VSX) != 0)
return DecodeVsx0x39(word32, decodeFlags);
else if ((decodeFlags & DECODE_FLAGS_PS) != 0)
return PPC_ID_PAIREDSINGLE_PSQ_LU;
else
return PPC_ID_INVALID;

Expand All @@ -5781,12 +5988,16 @@ static InstructionId Decode32(uint32_t word32, uint32_t decodeFlags)
case 0x3c:
if ((decodeFlags & DECODE_FLAGS_VSX) != 0)
return DecodeVsx0x3C(word32, decodeFlags);
else if ((decodeFlags & DECODE_FLAGS_PS) != 0)
return PPC_ID_PAIREDSINGLE_PSQ_ST;
else
return PPC_ID_INVALID;

case 0x3d:
if ((decodeFlags & DECODE_FLAGS_VSX) != 0)
return DecodeVsx0x3D(word32, decodeFlags);
else if ((decodeFlags & DECODE_FLAGS_PS) != 0)
return PPC_ID_PAIREDSINGLE_PSQ_STU;
else
return PPC_ID_INVALID;

Expand Down
48 changes: 39 additions & 9 deletions arch/powerpc/decode/decode.h
Original file line number Diff line number Diff line change
Expand Up @@ -1359,15 +1359,45 @@ extern "C" {
PPC_ID_VSX_XXSPLTW,
PPC_ID_VSX_XXSWAPD,

// Pair-stored
PPC_ID_PSQ_L,
PPC_ID_PSQ_LU,
PPC_ID_PSQ_LUX,
PPC_ID_PSQ_LX,
PPC_ID_PSQ_ST,
PPC_ID_PSQ_STU,
PPC_ID_PSQ_STUX,
PPC_ID_PSQ_STX,
// Paired-single
PPC_ID_PAIREDSINGLE_DCBZ_L,
PPC_ID_PAIREDSINGLE_PS_ABSx,
PPC_ID_PAIREDSINGLE_PS_ADDx,
PPC_ID_PAIREDSINGLE_PS_CMPO0,
PPC_ID_PAIREDSINGLE_PS_CMPO1,
PPC_ID_PAIREDSINGLE_PS_CMPU0,
PPC_ID_PAIREDSINGLE_PS_CMPU1,
PPC_ID_PAIREDSINGLE_PS_DIVx,
PPC_ID_PAIREDSINGLE_PS_MADDx,
PPC_ID_PAIREDSINGLE_PS_MADDS0x,
PPC_ID_PAIREDSINGLE_PS_MADDS1x,
PPC_ID_PAIREDSINGLE_PS_MERGE00x,
PPC_ID_PAIREDSINGLE_PS_MERGE01x,
PPC_ID_PAIREDSINGLE_PS_MERGE10x,
PPC_ID_PAIREDSINGLE_PS_MERGE11x,
PPC_ID_PAIREDSINGLE_PS_MRx,
PPC_ID_PAIREDSINGLE_PS_MSUBx,
PPC_ID_PAIREDSINGLE_PS_MULx,
PPC_ID_PAIREDSINGLE_PS_MULS0x,
PPC_ID_PAIREDSINGLE_PS_MULS1x,
PPC_ID_PAIREDSINGLE_PS_NABSx,
PPC_ID_PAIREDSINGLE_PS_NEGx,
PPC_ID_PAIREDSINGLE_PS_NMADDx,
PPC_ID_PAIREDSINGLE_PS_NMSUBx,
PPC_ID_PAIREDSINGLE_PS_RESx,
PPC_ID_PAIREDSINGLE_PS_RSQRTEx,
PPC_ID_PAIREDSINGLE_PS_SELx,
PPC_ID_PAIREDSINGLE_PS_SUBx,
PPC_ID_PAIREDSINGLE_PS_SUM0x,
PPC_ID_PAIREDSINGLE_PS_SUM1x,
PPC_ID_PAIREDSINGLE_PSQ_L,
PPC_ID_PAIREDSINGLE_PSQ_LU,
PPC_ID_PAIREDSINGLE_PSQ_LUX,
PPC_ID_PAIREDSINGLE_PSQ_LX,
PPC_ID_PAIREDSINGLE_PSQ_ST,
PPC_ID_PAIREDSINGLE_PSQ_STU,
PPC_ID_PAIREDSINGLE_PSQ_STUX,
PPC_ID_PAIREDSINGLE_PSQ_STX,

// SPE (Signal Processing Engine) instructions
PPC_ID_SPE_BRINC,
Expand Down
73 changes: 65 additions & 8 deletions arch/powerpc/decode/mnemonic.c
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,33 @@ DEFINE_SUBMNEM_ROUND2ODD(SubMnemXSSQRTQPx, "xssqrtqp");
DEFINE_SUBMNEM_ROUND2ODD(SubMnemXSSUBQPx, "xssubqp");
DEFINE_SUBMNEM_INEXACT(SubMnemXSRQPIx, "xsrqpi");

// PAIREDSINGLE MNEMONICS
DEFINE_SUBMNEM_RC(SubMnemPS_ABSx, "ps_abs");
DEFINE_SUBMNEM_RC(SubMnemPS_ADDx, "ps_add");
DEFINE_SUBMNEM_RC(SubMnemPS_DIVx, "ps_div");
DEFINE_SUBMNEM_RC(SubMnemPS_MADDx, "ps_madd");
DEFINE_SUBMNEM_RC(SubMnemPS_MADDS0x, "ps_madds0");
DEFINE_SUBMNEM_RC(SubMnemPS_MADDS1x, "ps_madds1");
DEFINE_SUBMNEM_RC(SubMnemPS_MERGE00x, "ps_merge00");
DEFINE_SUBMNEM_RC(SubMnemPS_MERGE01x, "ps_merge01");
DEFINE_SUBMNEM_RC(SubMnemPS_MERGE10x, "ps_merge10");
DEFINE_SUBMNEM_RC(SubMnemPS_MERGE11x, "ps_merge11");
DEFINE_SUBMNEM_RC(SubMnemPS_MRx, "ps_mr");
DEFINE_SUBMNEM_RC(SubMnemPS_MSUBx, "ps_msub");
DEFINE_SUBMNEM_RC(SubMnemPS_MULx, "ps_mul");
DEFINE_SUBMNEM_RC(SubMnemPS_MULS0x, "ps_muls0");
DEFINE_SUBMNEM_RC(SubMnemPS_MULS1x, "ps_muls1");
DEFINE_SUBMNEM_RC(SubMnemPS_NABSx, "ps_nabs");
DEFINE_SUBMNEM_RC(SubMnemPS_NEGx, "ps_neg");
DEFINE_SUBMNEM_RC(SubMnemPS_NMADDx, "ps_nmadd");
DEFINE_SUBMNEM_RC(SubMnemPS_NMSUBx, "ps_nmsub");
DEFINE_SUBMNEM_RC(SubMnemPS_RESx, "ps_res");
DEFINE_SUBMNEM_RC(SubMnemPS_RSQRTEx, "ps_rsqrte");
DEFINE_SUBMNEM_RC(SubMnemPS_SELx, "ps_sel");
DEFINE_SUBMNEM_RC(SubMnemPS_SUBx, "ps_sub");
DEFINE_SUBMNEM_RC(SubMnemPS_SUM0x, "ps_sum0");
DEFINE_SUBMNEM_RC(SubMnemPS_SUM1x, "ps_sum1");

static const char* RcMnemonic(const Instruction* instruction, const char* names[2])
{
return names[instruction->flags.rc];
Expand Down Expand Up @@ -1589,14 +1616,44 @@ const char* GetMnemonic(const Instruction* instruction)
case PPC_ID_VSX_XXSPLTW: return "xxspltw";
case PPC_ID_VSX_XXSWAPD: return "xxswapd";

case PPC_ID_PSQ_L: return "psq_l";
case PPC_ID_PSQ_LU: return "psq_lu";
case PPC_ID_PSQ_LUX: return "psq_lux";
case PPC_ID_PSQ_LX: return "psq_lx";
case PPC_ID_PSQ_ST: return "psq_st";
case PPC_ID_PSQ_STU: return "psq_stu";
case PPC_ID_PSQ_STUX: return "psq_stux";
case PPC_ID_PSQ_STX: return "psq_stx";
case PPC_ID_PAIREDSINGLE_DCBZ_L: return "dcbz_l";
case PPC_ID_PAIREDSINGLE_PS_ABSx: return RcMnemonic(instruction, SubMnemPS_ABSx);
case PPC_ID_PAIREDSINGLE_PS_ADDx: return RcMnemonic(instruction, SubMnemPS_ADDx);
case PPC_ID_PAIREDSINGLE_PS_CMPO0: return "ps_cmpo0";
case PPC_ID_PAIREDSINGLE_PS_CMPO1: return "ps_cmpo1";
case PPC_ID_PAIREDSINGLE_PS_CMPU0: return "ps_cmpu0";
case PPC_ID_PAIREDSINGLE_PS_CMPU1: return "ps_cmpu1";
case PPC_ID_PAIREDSINGLE_PS_DIVx: return RcMnemonic(instruction, SubMnemPS_DIVx);
case PPC_ID_PAIREDSINGLE_PS_MADDx: return RcMnemonic(instruction, SubMnemPS_MADDx);
case PPC_ID_PAIREDSINGLE_PS_MADDS0x: return RcMnemonic(instruction, SubMnemPS_MADDS0x);
case PPC_ID_PAIREDSINGLE_PS_MADDS1x: return RcMnemonic(instruction, SubMnemPS_MADDS1x);
case PPC_ID_PAIREDSINGLE_PS_MERGE00x: return RcMnemonic(instruction, SubMnemPS_MERGE00x);
case PPC_ID_PAIREDSINGLE_PS_MERGE01x: return RcMnemonic(instruction, SubMnemPS_MERGE01x);
case PPC_ID_PAIREDSINGLE_PS_MERGE10x: return RcMnemonic(instruction, SubMnemPS_MERGE10x);
case PPC_ID_PAIREDSINGLE_PS_MERGE11x: return RcMnemonic(instruction, SubMnemPS_MERGE11x);
case PPC_ID_PAIREDSINGLE_PS_MRx: return RcMnemonic(instruction, SubMnemPS_MRx);
case PPC_ID_PAIREDSINGLE_PS_MSUBx: return RcMnemonic(instruction, SubMnemPS_MSUBx);
case PPC_ID_PAIREDSINGLE_PS_MULx: return RcMnemonic(instruction, SubMnemPS_MULx);
case PPC_ID_PAIREDSINGLE_PS_MULS0x: return RcMnemonic(instruction, SubMnemPS_MULS0x);
case PPC_ID_PAIREDSINGLE_PS_MULS1x: return RcMnemonic(instruction, SubMnemPS_MULS1x);
case PPC_ID_PAIREDSINGLE_PS_NABSx: return RcMnemonic(instruction, SubMnemPS_NABSx);
case PPC_ID_PAIREDSINGLE_PS_NEGx: return RcMnemonic(instruction, SubMnemPS_NEGx);
case PPC_ID_PAIREDSINGLE_PS_NMADDx: return RcMnemonic(instruction, SubMnemPS_NMADDx);
case PPC_ID_PAIREDSINGLE_PS_NMSUBx: return RcMnemonic(instruction, SubMnemPS_NMSUBx);
case PPC_ID_PAIREDSINGLE_PS_RESx: return RcMnemonic(instruction, SubMnemPS_RESx);
case PPC_ID_PAIREDSINGLE_PS_RSQRTEx: return RcMnemonic(instruction, SubMnemPS_RSQRTEx);
case PPC_ID_PAIREDSINGLE_PS_SELx: return RcMnemonic(instruction, SubMnemPS_SELx);
case PPC_ID_PAIREDSINGLE_PS_SUBx: return RcMnemonic(instruction, SubMnemPS_SUBx);
case PPC_ID_PAIREDSINGLE_PS_SUM0x: return RcMnemonic(instruction, SubMnemPS_SUM0x);
case PPC_ID_PAIREDSINGLE_PS_SUM1x: return RcMnemonic(instruction, SubMnemPS_SUM1x);
case PPC_ID_PAIREDSINGLE_PSQ_L: return "psq_l";
case PPC_ID_PAIREDSINGLE_PSQ_LU: return "psq_lu";
case PPC_ID_PAIREDSINGLE_PSQ_LUX: return "psq_lux";
case PPC_ID_PAIREDSINGLE_PSQ_LX: return "psq_lx";
case PPC_ID_PAIREDSINGLE_PSQ_ST: return "psq_st";
case PPC_ID_PAIREDSINGLE_PSQ_STU: return "psq_stu";
case PPC_ID_PAIREDSINGLE_PSQ_STUX: return "psq_stux";
case PPC_ID_PAIREDSINGLE_PSQ_STX: return "psq_stx";

case PPC_ID_SPE_BRINC: return "brinc";
case PPC_ID_SPE_EFDABS: return "efdabs";
Expand Down
Loading