Skip to content
Merged
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
35 changes: 35 additions & 0 deletions arch/Sparc/SparcDisassembler.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@
#define GET_REGINFO_MC_DESC
#define GET_REGINFO_ENUM
#include "SparcGenRegisterInfo.inc"

#define GET_INSTRINFO_ENUM
#include "SparcGenInstrInfo.inc"
static const unsigned IntRegDecoderTable[] = {
SP_G0, SP_G1, SP_G2, SP_G3,
SP_G4, SP_G5, SP_G6, SP_G7,
Expand Down Expand Up @@ -203,6 +206,8 @@ static DecodeStatus DecodeSWAP(MCInst *Inst, unsigned insn, uint64_t Address,
#include "SparcGenSubtargetInfo.inc"
#include "SparcGenDisassemblerTables.inc"

static DecodeStatus decodeIntPairMem(MCInst *MI, uint32_t insn, uint64_t Address);

/// readInstruction - read four bytes and return 32 bit word.
static DecodeStatus readInstruction32(const uint8_t *code, size_t len, uint32_t *Insn)
{
Expand Down Expand Up @@ -235,6 +240,8 @@ bool Sparc_getInstruction(csh ud, const uint8_t *code, size_t code_len, MCInst *

Result = decodeInstruction_4(DecoderTableSparc32, MI, Insn, address,
(MCRegisterInfo *)info, 0);
if (Result == MCDisassembler_Fail)
Result = decodeIntPairMem(MI, Insn, address);
if (Result != MCDisassembler_Fail) {
*size = 4;
return true;
Expand Down Expand Up @@ -298,6 +305,34 @@ static DecodeStatus DecodeLoadInt(MCInst *Inst, unsigned insn, uint64_t Address,
DecodeIntRegsRegisterClass);
}

// An odd register pair is undefined; round it down like LLVM does.
static DecodeStatus DecodeIntPairRegisterClass(MCInst *Inst, unsigned RegNo,
uint64_t Address, const void *Decoder)
{
return DecodeIntRegsRegisterClass(Inst, RegNo & ~1U, Address, Decoder);
}

// The generated table predates LLVM's integer LDD and STD.
static DecodeStatus decodeIntPairMem(MCInst *MI, uint32_t insn, uint64_t Address)
{
bool isImm = fieldFromInstruction_4(insn, 13, 1);
if (fieldFromInstruction_4(insn, 30, 2) != 3)
return MCDisassembler_Fail;
if (!isImm && fieldFromInstruction_4(insn, 5, 8))
return MCDisassembler_Fail;

switch (fieldFromInstruction_4(insn, 19, 6)) {
case 0x03:
MCInst_setOpcode(MI, isImm ? SP_LDDri : SP_LDDrr);
return DecodeMem(MI, insn, Address, NULL, true, DecodeIntPairRegisterClass);
case 0x07:
MCInst_setOpcode(MI, isImm ? SP_STDri : SP_STDrr);
return DecodeMem(MI, insn, Address, NULL, false, DecodeIntPairRegisterClass);
default:
return MCDisassembler_Fail;
}
}

static DecodeStatus DecodeLoadFP(MCInst *Inst, unsigned insn, uint64_t Address,
const void *Decoder)
{
Expand Down
6 changes: 5 additions & 1 deletion arch/Sparc/SparcGenInstrInfo.inc
Original file line number Diff line number Diff line change
Expand Up @@ -508,7 +508,11 @@ enum {
SP_XORXrr = 491,
SP_XORri = 492,
SP_XORrr = 493,
SP_INSTRUCTION_LIST_END = 494
SP_LDDri = 494,
SP_LDDrr = 495,
SP_STDri = 496,
SP_STDrr = 497,
SP_INSTRUCTION_LIST_END = 498
};

#endif // GET_INSTRINFO_ENUM
15 changes: 15 additions & 0 deletions arch/Sparc/SparcInstPrinter.c
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,21 @@ static bool printSparcAliasInstr(MCInst *MI, SStream *O)
{
switch (MCInst_getOpcode(MI)) {
default: return false;
case SP_LDDri:
case SP_LDDrr:
SStream_concat0(O, "ldd\t[");
printMemOperand(MI, 1, O, NULL);
SStream_concat0(O, "], ");
printOperand(MI, 0, O);
return true;
case SP_STDri:
case SP_STDrr:
SStream_concat0(O, "std\t");
printOperand(MI, 2, O);
SStream_concat0(O, ", [");
printMemOperand(MI, 0, O, NULL);
SStream_concat0(O, "]");
return true;
case SP_JMPLrr:
case SP_JMPLri:
if (MCInst_getNumOperands(MI) != 3)
Expand Down
24 changes: 24 additions & 0 deletions arch/Sparc/SparcMappingInsn.inc
Original file line number Diff line number Diff line change
Expand Up @@ -2641,3 +2641,27 @@
{ 0 }, { 0 }, { 0 }, 0, 0
#endif
},
{
SP_LDDri, SPARC_INS_LDD,
#ifndef CAPSTONE_DIET
{ 0 }, { 0 }, { 0 }, 0, 0
#endif
},
{
SP_LDDrr, SPARC_INS_LDD,
#ifndef CAPSTONE_DIET
{ 0 }, { 0 }, { 0 }, 0, 0
#endif
},
{
SP_STDri, SPARC_INS_STD,
#ifndef CAPSTONE_DIET
{ 0 }, { 0 }, { 0 }, 0, 0
#endif
},
{
SP_STDrr, SPARC_INS_STD,
#ifndef CAPSTONE_DIET
{ 0 }, { 0 }, { 0 }, 0, 0
#endif
},
8 changes: 8 additions & 0 deletions suite/MC/Sparc/sparc-mem-instructions.s.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@
0xd4,0x06,0x00,0x16 = ld [%i0+%l6], %o2
0xd4,0x06,0x20,0x20 = ld [%i0+32], %o2
0xd4,0x00,0x60,0x00 = ld [%g1], %o2
0xd4,0x1e,0x00,0x16 = ldd [%i0+%l6], %o2
0xd4,0x1e,0x20,0x20 = ldd [%i0+32], %o2
0xd4,0x18,0x60,0x00 = ldd [%g1], %o2
0xda,0x18,0x63,0xd8 = ldd [%g1+0x3d8], %o4
0xd4,0x2e,0x00,0x16 = stb %o2, [%i0+%l6]
0xd4,0x2e,0x20,0x20 = stb %o2, [%i0+32]
0xd4,0x28,0x60,0x00 = stb %o2, [%g1]
Expand All @@ -23,3 +27,7 @@
0xd4,0x26,0x00,0x16 = st %o2, [%i0+%l6]
0xd4,0x26,0x20,0x20 = st %o2, [%i0+32]
0xd4,0x20,0x60,0x00 = st %o2, [%g1]
0xd4,0x3e,0x00,0x16 = std %o2, [%i0+%l6]
0xd4,0x3e,0x20,0x20 = std %o2, [%i0+32]
0xd4,0x38,0x60,0x00 = std %o2, [%g1]
0xd8,0x38,0x63,0xd8 = std %o4, [%g1+0x3d8]
Loading