Skip to content

Commit

Permalink
PPC LLVM 18 (#2540)
Browse files Browse the repository at this point in the history
* Update PPC module to LLVM 18.

**New**

(According to LLVM changelog)

- Added DFP instruction.
- Added the SCV instruction.

**Changes**

- Memory decoder were simplified by decoding disponent and base reg separately.
- `DFORM` -> `DFORM_BASE`
- Use inverted `MCInstDesc` table.
- Replace the many declared printer in PPCInstPrinter with `static inlines`.
- Renamed groups to upper case.
- Switched to `ARCH_add_cs_detail_X()` function names.
- Remove `PPCInstPrinter.h` because it is no longer used.

* Fix: Use correct directory name.

* Fix segfaults and add asserts for these NULL cases.

* Allow to map a single LLVM option to multiple CS options

* Add default endian option to the MCUpdater

* Fix setter for Little endian

* Add SPE option to cstool

* Fix QPX instructions.

Due to llvm/llvm-project@4b43ef3
the names of the operands were matched.
Because FRT dosn't exist in the XForm_1 class,
the generated tables didn't decoded them.

* Fix: AbsAddr should be printed as unsigned.

* Fix S12 immediate printing for PC memory operands

* Fix MCUpdater tests

* Update PPCRegisterInfo_stripRegisterPrefix

* Add support for selection of Power versions

* Run clang-format

* Fix feature check

* Allow to overwrite in multi-mode

* Add some more flags

* Fix order and map name

* Add new test files.

* Fix checks for features.

Only enables PowerX feature checks of a Power architecture is enabled
and the feature is in the list of it.

* Print byte sequence with space between comma.

This helps with copy and search of the byte string in the test files.

* Fix tests broken due to feature toggles

* Shorten generated names.

* Update bindings
  • Loading branch information
Rot127 authored Dec 5, 2024
1 parent e46838e commit 93a104c
Show file tree
Hide file tree
Showing 69 changed files with 85,479 additions and 38,336 deletions.
1 change: 0 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -323,7 +323,6 @@ if(CAPSTONE_PPC_SUPPORT)
)
set(HEADERS_PPC
arch/PowerPC/PPCInstrInfo.h
arch/PowerPC/PPCInstPrinter.h
arch/PowerPC/PPCLinkage.h
arch/PowerPC/PPCMapping.h
arch/PowerPC/PPCMCTargetDesc.h
Expand Down
5 changes: 5 additions & 0 deletions Mapping.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

#include "Mapping.h"
#include "capstone/capstone.h"
#include "cs_priv.h"
#include "utils.h"

// create a cache for fast id lookup
Expand Down Expand Up @@ -40,9 +41,13 @@ unsigned short insn_find(const insn_map *insns, unsigned int max,
// Returns the id or -1 if not found.
int name2id(const name_map *map, int max, const char *name)
{
CS_ASSERT_RET_VAL(map && name, -1);
int i;

for (i = 0; i < max; i++) {
if (!map[i].name) {
return -1;
}
if (!strcmp(map[i].name, name)) {
return map[i].id;
}
Expand Down
205 changes: 65 additions & 140 deletions arch/PowerPC/PPCDisassembler.c
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,14 @@ static DecodeStatus DecodeF8RCRegisterClass(MCInst *Inst, uint64_t RegNo,
return decodeRegisterClass(Inst, RegNo, FRegs);
}

static DecodeStatus DecodeFpRCRegisterClass(MCInst *Inst, uint64_t RegNo,
uint64_t Address, const void *Decoder)
{
if (RegNo > 30 || (RegNo & 1))
return MCDisassembler_Fail;
return decodeRegisterClass(Inst, RegNo >> 1, FpRegs);
}

static DecodeStatus DecodeVFRCRegisterClass(MCInst *Inst, uint64_t RegNo,
uint64_t Address,
const void *Decoder)
Expand Down Expand Up @@ -257,29 +265,39 @@ static DecodeStatus DecodeQFRCRegisterClass(MCInst *Inst, uint64_t RegNo,
N)(MCInst * Inst, uint64_t Imm, \
int64_t Address, const void *Decoder) \
{ \
if (!isUIntN(N, Imm)) \
return MCDisassembler_Fail; \
MCOperand_CreateImm0(Inst, (Imm)); \
return MCDisassembler_Success; \
}
DEFINE_decodeUImmOperand(5) DEFINE_decodeUImmOperand(16)
DEFINE_decodeUImmOperand(6) DEFINE_decodeUImmOperand(10)
DEFINE_decodeUImmOperand(8) DEFINE_decodeUImmOperand(7)
DEFINE_decodeUImmOperand(12)
DEFINE_decodeUImmOperand(1);
DEFINE_decodeUImmOperand(2);
DEFINE_decodeUImmOperand(3);
DEFINE_decodeUImmOperand(4);
DEFINE_decodeUImmOperand(5);
DEFINE_decodeUImmOperand(6);
DEFINE_decodeUImmOperand(7);
DEFINE_decodeUImmOperand(8);
DEFINE_decodeUImmOperand(10);
DEFINE_decodeUImmOperand(12);
DEFINE_decodeUImmOperand(16);

#define DEFINE_decodeSImmOperand(N) \
static DecodeStatus CONCAT(decodeSImmOperand, \
N)(MCInst * Inst, uint64_t Imm, \
int64_t Address, const void *Decoder) \
{ \
MCOperand_CreateImm0(Inst, (SignExtend64(Imm, N))); \
if (!isUIntN(N, Imm)) \
return MCDisassembler_Fail; \
MCOperand_CreateImm0(Inst, (SignExtend64((Imm), N))); \
return MCDisassembler_Success; \
}
DEFINE_decodeSImmOperand(16)
DEFINE_decodeSImmOperand(5)
DEFINE_decodeSImmOperand(34)
DEFINE_decodeSImmOperand(16);
DEFINE_decodeSImmOperand(5);
DEFINE_decodeSImmOperand(34);

static DecodeStatus
decodeImmZeroOperand(MCInst *Inst, uint64_t Imm, int64_t Address,
const void *Decoder)
static DecodeStatus decodeImmZeroOperand(MCInst *Inst, uint64_t Imm,
int64_t Address, const void *Decoder)
{
if (Imm != 0)
return MCDisassembler_Fail;
Expand All @@ -297,158 +315,65 @@ static DecodeStatus decodeVSRpEvenOperands(MCInst *Inst, uint64_t RegNo,
return MCDisassembler_Success;
}

static DecodeStatus decodeMemRIOperands(MCInst *Inst, uint64_t Imm,
int64_t Address, const void *Decoder)
{
// Decode the memri field (imm, reg), which has the low 16-bits as the
// displacement and the next 5 bits as the register #.

uint64_t Base = Imm >> 16;
uint64_t Disp = Imm & 0xFFFF;

switch (MCInst_getOpcode(Inst)) {
default:
break;
case PPC_LBZU:
case PPC_LHAU:
case PPC_LHZU:
case PPC_LWZU:
case PPC_LFSU:
case PPC_LFDU:
// Add the tied output operand.
MCOperand_CreateReg0(Inst, (RRegsNoR0[Base]));
break;
case PPC_STBU:
case PPC_STHU:
case PPC_STWU:
case PPC_STFSU:
case PPC_STFDU:
MCInst_insert0(Inst, 0,
MCOperand_CreateReg1(Inst, RRegsNoR0[Base]));
break;
}

MCOperand_CreateImm0(Inst, (SignExtend64(Disp, 16)));
MCOperand_CreateReg0(Inst, (RRegsNoR0[Base]));
return MCDisassembler_Success;
}

static DecodeStatus decodeMemRIXOperands(MCInst *Inst, uint64_t Imm,
int64_t Address, const void *Decoder)
static DecodeStatus decodeDispSPE8Operand(MCInst *Inst, uint64_t Imm,
int64_t Address, const void *Decoder)
{
// Decode the memrix field (imm, reg), which has the low 14-bits as the
// displacement and the next 5 bits as the register #.
// Decode the dispSPE8 field, which has 5-bits, 8-byte aligned.

uint64_t Base = Imm >> 14;
uint64_t Disp = Imm & 0x3FFF;

if (MCInst_getOpcode(Inst) == PPC_LDU)
// Add the tied output operand.
MCOperand_CreateReg0(Inst, (RRegsNoR0[Base]));
else if (MCInst_getOpcode(Inst) == PPC_STDU)
MCInst_insert0(Inst, 0,
MCOperand_CreateReg1(Inst, RRegsNoR0[Base]));

MCOperand_CreateImm0(Inst, (SignExtend64(Disp << 2, 16)));
MCOperand_CreateReg0(Inst, (RRegsNoR0[Base]));
return MCDisassembler_Success;
}

static DecodeStatus decodeMemRIHashOperands(MCInst *Inst, uint64_t Imm,
int64_t Address,
const void *Decoder)
{
// Decode the memrix field for a hash store or hash check operation.
// The field is composed of a register and an immediate value that is 6 bits
// and covers the range -8 to -512. The immediate is always negative and 2s
// complement which is why we sign extend a 7 bit value.
const uint64_t Base = Imm >> 6;
const int64_t Disp = SignExtend64((Imm & 0x3F) + 64, 7) * 8;
uint64_t Disp = Imm & 0x1F;

MCOperand_CreateImm0(Inst, (Disp));
MCOperand_CreateReg0(Inst, (RRegs[Base]));
MCOperand_CreateImm0(Inst, (Disp << 3));
return MCDisassembler_Success;
}

static DecodeStatus decodeMemRIX16Operands(MCInst *Inst, uint64_t Imm,
int64_t Address, const void *Decoder)
static DecodeStatus decodeDispSPE4Operand(MCInst *Inst, uint64_t Imm,
int64_t Address, const void *Decoder)
{
// Decode the memrix16 field (imm, reg), which has the low 12-bits as the
// displacement with 16-byte aligned, and the next 5 bits as the register #.
// Decode the dispSPE8 field, which has 5-bits, 4-byte aligned.

uint64_t Base = Imm >> 12;
uint64_t Disp = Imm & 0xFFF;
uint64_t Disp = Imm & 0x1F;

MCOperand_CreateImm0(Inst, (SignExtend64(Disp << 4, 16)));
MCOperand_CreateReg0(Inst, (RRegsNoR0[Base]));
MCOperand_CreateImm0(Inst, (Disp << 2));
return MCDisassembler_Success;
}

static DecodeStatus decodeMemRI34PCRelOperands(MCInst *Inst, uint64_t Imm,
int64_t Address,
const void *Decoder)
{
// Decode the memri34_pcrel field (imm, reg), which has the low 34-bits as
// the displacement, and the next 5 bits as an immediate 0.
uint64_t Base = Imm >> 34;
uint64_t Disp = Imm & 0x3FFFFFFFFUL;

MCOperand_CreateImm0(Inst, (SignExtend64(Disp, 34)));
return decodeImmZeroOperand(Inst, Base, Address, Decoder);
}

static DecodeStatus decodeMemRI34Operands(MCInst *Inst, uint64_t Imm,
static DecodeStatus decodeDispSPE2Operand(MCInst *Inst, uint64_t Imm,
int64_t Address, const void *Decoder)
{
// Decode the memri34 field (imm, reg), which has the low 34-bits as the
// displacement, and the next 5 bits as the register #.
uint64_t Base = Imm >> 34;
uint64_t Disp = Imm & 0x3FFFFFFFFUL;
// Decode the dispSPE8 field, which has 5-bits, 2-byte aligned.

MCOperand_CreateImm0(Inst, (SignExtend64(Disp, 34)));
MCOperand_CreateReg0(Inst, (RRegsNoR0[Base]));
uint64_t Disp = Imm & 0x1F;
MCOperand_CreateImm0(Inst, (Disp << 1));
return MCDisassembler_Success;
}

static DecodeStatus decodeSPE8Operands(MCInst *Inst, uint64_t Imm,
int64_t Address, const void *Decoder)
static DecodeStatus decodeDispRIXOperand(MCInst *Inst, uint64_t Imm,
int64_t Address, const void *Decoder)
{
// Decode the spe8disp field (imm, reg), which has the low 5-bits as the
// displacement with 8-byte aligned, and the next 5 bits as the register #.

uint64_t Base = Imm >> 5;
uint64_t Disp = Imm & 0x1F;

MCOperand_CreateImm0(Inst, (Disp << 3));
MCOperand_CreateReg0(Inst, (RRegsNoR0[Base]));
// The rix displacement is an immediate shifted by 2
MCOperand_CreateImm0(Inst, (SignExtend64((Imm << 2), 16)));
return MCDisassembler_Success;
}

static DecodeStatus decodeSPE4Operands(MCInst *Inst, uint64_t Imm,
int64_t Address, const void *Decoder)
static DecodeStatus decodeDispRIX16Operand(MCInst *Inst, uint64_t Imm,
int64_t Address, const void *Decoder)
{
// Decode the spe4disp field (imm, reg), which has the low 5-bits as the
// displacement with 4-byte aligned, and the next 5 bits as the register #.

uint64_t Base = Imm >> 5;
uint64_t Disp = Imm & 0x1F;

MCOperand_CreateImm0(Inst, (Disp << 2));
MCOperand_CreateReg0(Inst, (RRegsNoR0[Base]));
// The rix16 displacement has 12-bits which are shifted by 4.
MCOperand_CreateImm0(Inst, (SignExtend64((Imm << 4), 16)));
return MCDisassembler_Success;
}

static DecodeStatus decodeSPE2Operands(MCInst *Inst, uint64_t Imm,
int64_t Address, const void *Decoder)
static DecodeStatus decodeDispRIHashOperand(MCInst *Inst, uint64_t Imm,
int64_t Address,
const void *Decoder)
{
// Decode the spe2disp field (imm, reg), which has the low 5-bits as the
// displacement with 2-byte aligned, and the next 5 bits as the register #.

uint64_t Base = Imm >> 5;
uint64_t Disp = Imm & 0x1F;
// Decode the disp field for a hash store or hash check operation.
// The field is composed of an immediate value that is 6 bits
// and covers the range -8 to -512. The immediate is always negative and 2s
// complement which is why we sign extend a 7 bit value.
const int64_t Disp = SignExtend64(((Imm & 0x3F) + 64), 7) * 8;

MCOperand_CreateImm0(Inst, (Disp << 1));
MCOperand_CreateReg0(Inst, (RRegsNoR0[Base]));
MCOperand_CreateImm0(Inst, (Disp));
return MCDisassembler_Success;
}

Expand Down Expand Up @@ -486,7 +411,7 @@ DecodeStatus getInstruction(csh ud, const uint8_t *Bytes, size_t BytesLen,
uint32_t BaseInst = readBytes32(MI, Bytes + 4);
uint64_t Inst = BaseInst | (uint64_t)Prefix << 32;
DecodeStatus result =
decodeInstruction_4(DecoderTable64, MI, Inst, Address);
decodeInstruction_4(DecoderTable64, MI, Inst, Address, NULL);
if (result != MCDisassembler_Fail) {
*Size = 8;
return result;
Expand All @@ -505,22 +430,22 @@ DecodeStatus getInstruction(csh ud, const uint8_t *Bytes, size_t BytesLen,

if (PPC_getFeatureBits(MI->csh->mode, PPC_FeatureQPX)) {
DecodeStatus result = decodeInstruction_4(DecoderTableQPX32, MI,
Inst, Address);
Inst, Address, NULL);
if (result != MCDisassembler_Fail)
return result;
} else if (PPC_getFeatureBits(MI->csh->mode, PPC_FeatureSPE)) {
DecodeStatus result = decodeInstruction_4(DecoderTableSPE32, MI,
Inst, Address);
Inst, Address, NULL);
if (result != MCDisassembler_Fail)
return result;
} else if (PPC_getFeatureBits(MI->csh->mode, PPC_FeaturePS)) {
DecodeStatus result = decodeInstruction_4(DecoderTablePS32, MI,
Inst, Address);
Inst, Address, NULL);
if (result != MCDisassembler_Fail)
return result;
}

return decodeInstruction_4(DecoderTable32, MI, Inst, Address);
return decodeInstruction_4(DecoderTable32, MI, Inst, Address, NULL);
}

DecodeStatus PPC_LLVM_getInstruction(csh handle, const uint8_t *Bytes,
Expand Down
Loading

0 comments on commit 93a104c

Please sign in to comment.