Skip to content

Commit

Permalink
Add HPPA 2.0 wide support
Browse files Browse the repository at this point in the history
  • Loading branch information
R33v0LT committed Mar 4, 2024
1 parent 03e1d26 commit 6f07eca
Show file tree
Hide file tree
Showing 10 changed files with 68 additions and 30 deletions.
2 changes: 1 addition & 1 deletion MCInst.h
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ struct MCInst {
uint8_t xAcquireRelease; // X86 xacquire/xrelease
bool isAliasInstr; // Flag if this MCInst is an alias.
bool fillDetailOps; // If set, detail->operands gets filled.
hppa_ext hppa_ext; // for HPPA operand
hppa_ext hppa_ext; ///< for HPPA operand. Contains info about modifiers and their effect on the instruction
};

void MCInst_Init(MCInst *inst);
Expand Down
1 change: 1 addition & 0 deletions arch/HPPA/HPPAConstants.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

#define HPPA_OP_TYPE(byte) (byte) >> 2
#define MODE_IS_HPPA_20(mode) (((mode) & CS_MODE_HPPA_20) != 0)
#define MODE_IS_HPPA_20W(mode) (((mode) & (1 << 3)) != 0)

///> HPPA opcode types
#define HPPA_OP_TYPE_SYSOP 0x00
Expand Down
71 changes: 50 additions & 21 deletions arch/HPPA/HPPADisassembler.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
#define GET_BIT(X, WHICH) \
GET_FIELD (X, WHICH, WHICH)

#define CMPLT_IS_REG_MOD(CMPLT) (((CMPLT) & 1) == 1)
#define CMPLT_HAS_MODIFY_BIT(CMPLT) (((CMPLT) & 1) == 1)

#define HPPA_EXT_REF(MI) (&MI->hppa_ext)

Expand Down Expand Up @@ -78,10 +78,6 @@ static const char *const shift_cond_64_names[] =
{
"*", "*=", "*<", "*od", "*tr", "*<>", "*>=", "*ev"
};
static const char *const bb_cond_64_names[] =
{
"*<", "*>="
};
static const char *const index_compl_names[] = {"", "m", "s", "sm"};
static const char *const short_ldst_compl_names[] = {"", "ma", "", "mb"};
static const char *const short_bytes_compl_names[] =
Expand Down Expand Up @@ -209,17 +205,22 @@ static int extract_14(unsigned word)
return low_sign_extend(word & MASK_14, 14);
}

/* Extract a 16 bit immediate field (PA2.0 wide only). */
/* Extract a 16 bit immediate field. */

static int extract_16(unsigned word)
static int extract_16(unsigned word, bool wide)
{
int m15, m0, m1;

m0 = GET_BIT(word, 16);
m1 = GET_BIT(word, 17);
m15 = GET_BIT(word, 31);
word = (word >> 1) & 0x1fff;
word = word | (m15 << 15) | ((m15 ^ m0) << 14) | ((m15 ^ m1) << 13);
if (wide) {
word = word | (m15 << 15) | ((m15 ^ m0) << 14) | ((m15 ^ m1) << 13);
}
else {
word = word | (m15 << 15) | (m15 << 14) | (m15 << 13);
}
return sign_extend(word, 16);
}

Expand Down Expand Up @@ -371,13 +372,17 @@ static void fillSysopInsnName(MCInst *MI, uint32_t insn) {

static bool decodeSysop(cs_struct *ud, MCInst *MI, uint32_t insn) {
uint32_t ext8 = GET_FIELD(insn, 19, 26);
uint32_t ext5 = GET_FIELD(insn, 11, 15);
uint32_t r1 = GET_FIELD(insn, 6, 10);
uint32_t r2 = GET_FIELD(insn, 11, 15);
uint32_t t = GET_FIELD(insn, 27, 31);
uint32_t s = extract_3(insn);
if (MODE_IS_HPPA_20(MI->csh->mode)) {
switch (ext8) {
case 0xa5:
if (ext5 != 0) {
return false;
}
CREATE_GR_REG(MI, t);
return true;
case 0xc6:
Expand All @@ -391,6 +396,9 @@ static bool decodeSysop(cs_struct *ud, MCInst *MI, uint32_t insn) {
MCOperand_CreateImm0(MI, t);
MCOperand_CreateImm0(MI, GET_FIELD(insn, 6, 18));
case 0x20:
if (ext5 != 0x00 && ext5 != 0x10) {
return false;
}
case 0x60:
case 0x65:
return true;
Expand All @@ -412,6 +420,9 @@ static bool decodeSysop(cs_struct *ud, MCInst *MI, uint32_t insn) {
CREATE_SR_REG(MI, s);
return true;
case 0x25:
if (ext5 != 0) {
return false;
}
CREATE_SR_REG(MI, s);
CREATE_GR_REG(MI, t);
return true;
Expand All @@ -420,6 +431,9 @@ static bool decodeSysop(cs_struct *ud, MCInst *MI, uint32_t insn) {
CREATE_CR_REG(MI, r1);
return true;
case 0x45:
if (ext5 != 0) {
return false;
}
if (GET_BIT(insn, 17) == 1 && MODE_IS_HPPA_20(ud->mode) &&
r1 != 11) {
return false;
Expand Down Expand Up @@ -567,7 +581,7 @@ static void fillMemmgmtMods(uint32_t insn, hppa_ext* hppa_ext, cs_mode mode) {
return;
}
success:
if (CMPLT_IS_REG_MOD(cmplt)) {
if (CMPLT_HAS_MODIFY_BIT(cmplt)) {
hppa_ext->b_writeble = true;
}
push_str_modifier(hppa_ext, index_compl_names[cmplt]);
Expand Down Expand Up @@ -1179,7 +1193,7 @@ static void fillIdxmemMods(uint32_t insn, hppa_ext* hppa_ext, cs_mode mode, uint
uint32_t cmplt = (GET_BIT(insn, 18) << 1) | GET_BIT(insn, 26);
uint32_t cc = GET_FIELD(insn, 20, 21);
uint32_t ext = GET_FIELD(insn, 22, 25);
if (CMPLT_IS_REG_MOD(cmplt)) {
if (CMPLT_HAS_MODIFY_BIT(cmplt)) {
hppa_ext->b_writeble = true;
}
if (GET_BIT(insn, 19) == 0) {
Expand Down Expand Up @@ -1415,12 +1429,13 @@ static void fillLoadStoreDwMods(uint32_t insn, hppa_ext* hppa_ext, uint32_t im)

static bool decodeLoadStoreDw(cs_struct *ud, MCInst *MI, uint32_t insn) {
uint32_t opcode = insn >> 26;
uint32_t im = extract_16(insn);
uint32_t im = extract_16(insn, MODE_IS_HPPA_20W(ud->mode));
im &= ~7;
uint32_t ext = GET_BIT(insn, 30);
uint32_t r = GET_FIELD(insn, 11, 15);
uint32_t b = GET_FIELD(insn, 6, 10);
uint32_t s = GET_FIELD(insn, 16, 17);
if (opcode == 0x14) {
if (opcode == HPPA_OP_TYPE_LOADDW) {
MCOperand_CreateImm0(MI, im);
CREATE_SR_REG(MI, s);
CREATE_GR_REG(MI, b);
Expand Down Expand Up @@ -1476,7 +1491,8 @@ static void fillLoadStoreWMods(uint32_t insn, hppa_ext* hppa_ext, uint32_t im) {
static bool decodeLoadStoreW(cs_struct *ud, MCInst *MI, uint32_t insn) {
uint32_t opcode = insn >> 26;
uint32_t ext = GET_BIT(insn, 29);
uint32_t im = extract_16(insn);
uint32_t im = extract_16(insn, MODE_IS_HPPA_20W(ud->mode));
im &= ~3;
uint32_t r = GET_FIELD(insn, 11, 15);
uint32_t b = GET_FIELD(insn, 6, 10);
uint32_t s = GET_FIELD(insn, 16, 17);
Expand Down Expand Up @@ -2331,7 +2347,7 @@ static void fillCoprdwMods(uint32_t insn, uint32_t im, hppa_ext* hppa_ext, cs_mo
(opcode == HPPA_OP_TYPE_COPRDW && uid == 0x00))) {
push_int_modifier(hppa_ext, uid);
}
if (CMPLT_IS_REG_MOD(cmplt)) {
if (CMPLT_HAS_MODIFY_BIT(cmplt)) {
hppa_ext->b_writeble = true;
}

Expand Down Expand Up @@ -3199,11 +3215,21 @@ static void fillActionAndBranchMods(uint32_t insn, uint32_t opcode, hppa_ext* hp
break;
case HPPA_OP_TYPE_ADDBT:
case HPPA_OP_TYPE_ADDIBT:
push_str_modifier(hppa_ext, add_cond_names[cond]);
if (MODE_IS_HPPA_20W(mode)) {
push_str_modifier(hppa_ext, wide_add_cond_names[cond]);
}
else {
push_str_modifier(hppa_ext, add_cond_names[cond]);
}
break;
case HPPA_OP_TYPE_ADDBF:
case HPPA_OP_TYPE_ADDIBF:
push_str_modifier(hppa_ext, add_cond_names[cond+8]);
if (MODE_IS_HPPA_20W(mode)) {
push_str_modifier(hppa_ext, wide_add_cond_names[cond+8]);
}
else {
push_str_modifier(hppa_ext, add_cond_names[cond+8]);
}
break;
case HPPA_OP_TYPE_BBS:
case HPPA_OP_TYPE_BB:
Expand Down Expand Up @@ -3411,18 +3437,20 @@ static bool decodeBe(cs_struct *ud, MCInst *MI, uint32_t insn) {
static bool decodeFloatStLd(cs_struct *ud, MCInst *MI, uint32_t insn) {
uint32_t opcode = insn >> 26;
uint32_t a = GET_BIT(insn, 29);
uint32_t disp = extract_16(insn, MODE_IS_HPPA_20W(ud->mode));
disp &= ~3;

if (opcode == HPPA_OP_TYPE_FLDW) {
MCInst_setOpcode(MI, HPPA_INS_FLDW);
MCOperand_CreateImm0(MI, extract_16(insn));
MCOperand_CreateImm0(MI, disp);
CREATE_SR_REG(MI, GET_FIELD(insn, 16, 17));
CREATE_GR_REG(MI, GET_FIELD(insn, 6, 10));
CREATE_FPR_REG(MI, GET_FIELD(insn, 11, 15));
}
else {
MCInst_setOpcode(MI, HPPA_INS_FSTW);
CREATE_FPR_REG(MI, GET_FIELD(insn, 11, 15));
MCOperand_CreateImm0(MI, extract_16(insn));
MCOperand_CreateImm0(MI, disp);
CREATE_SR_REG(MI, GET_FIELD(insn, 16, 17));
CREATE_GR_REG(MI, GET_FIELD(insn, 6, 10));
}
Expand Down Expand Up @@ -3475,7 +3503,7 @@ static bool decodeFmpy(cs_struct *ud, MCInst *MI, uint32_t insn) {
static bool decodeLoad(cs_struct *ud, MCInst *MI, uint32_t insn) {
uint32_t opcode = insn >> 26;
if (MODE_IS_HPPA_20(ud->mode)) {
uint32_t d = extract_16(insn);
uint32_t d = extract_16(insn, MODE_IS_HPPA_20W(ud->mode));
if (opcode == HPPA_OP_TYPE_LDWM) {
if (d < 0) {
push_str_modifier(HPPA_EXT_REF(MI), "mb");
Expand All @@ -3499,7 +3527,7 @@ static bool decodeStore(cs_struct *ud, MCInst *MI, uint32_t insn) {
uint32_t opcode = insn >> 26;
CREATE_GR_REG(MI, GET_FIELD(insn, 11, 15));
if (MODE_IS_HPPA_20(ud->mode)) {
uint32_t d = extract_16(insn);
uint32_t d = extract_16(insn, MODE_IS_HPPA_20W(ud->mode));
if (opcode == HPPA_OP_TYPE_STWM) {
if (d < 0) {
push_str_modifier(HPPA_EXT_REF(MI), "mb");
Expand Down Expand Up @@ -3533,6 +3561,7 @@ static bool getInstruction(cs_struct *ud, const uint8_t *code, size_t code_len,
memset(HPPA_EXT_REF(MI), 0, sizeof(MI->hppa_ext));

uint32_t full_insn = readBytes32(MI, code);
// printf("full_insn: %x\n", full_insn);
uint8_t opcode = full_insn >> 26;

if (MODE_IS_HPPA_20(ud->mode)) {
Expand Down Expand Up @@ -3631,7 +3660,7 @@ static bool getInstruction(cs_struct *ud, const uint8_t *code, size_t code_len,
case HPPA_OP_TYPE_LDO:
MCInst_setOpcode(MI, HPPA_INS_LDO);
if (MODE_IS_HPPA_20(ud->mode)) {
MCOperand_CreateImm0(MI, extract_16(full_insn));
MCOperand_CreateImm0(MI, extract_16(full_insn, MODE_IS_HPPA_20W(ud->mode)));
}
else {
MCOperand_CreateImm0(MI, extract_14(full_insn));
Expand Down
2 changes: 1 addition & 1 deletion arch/HPPA/HPPAInstPrinter.c
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ struct pa_insn_fmt
// unsigned long int mask;
hppa_insn insn_id;
const char *format;
bool is_alternative; // true if some completer affects on instruction format
bool is_alternative; ///< true if some completer affects the instruction format
};

/* HPPA instruction formats (access)
Expand Down
2 changes: 2 additions & 0 deletions bindings/python/capstone/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@
'CS_MODE_TRICORE_162',
'CS_MODE_HPPA_11',
'CS_MODE_HPPA_20',
'CS_MODE_HPPA_20W',

'CS_OPT_SYNTAX',
'CS_OPT_SYNTAX_DEFAULT',
Expand Down Expand Up @@ -291,6 +292,7 @@
CS_MODE_TRICORE_162 = 1 << 7 # Tricore 1.6.2
CS_MODE_HPPA_11 = 1 << 1 # HPPA 1.1
CS_MODE_HPPA_20 = 1 << 2 # HPPA 2.0
CS_MODE_HPPA_20W = CS_MODE_HPPA_20 | (1 << 3) # HPPA 2.0 wide

# Capstone option type
CS_OPT_INVALID = 0 # No option specified
Expand Down
2 changes: 1 addition & 1 deletion cs.c
Original file line number Diff line number Diff line change
Expand Up @@ -315,7 +315,7 @@ static const cs_arch_config arch_configs[MAX_ARCH] = {
HPPA_global_init,
HPPA_option,
~(CS_MODE_LITTLE_ENDIAN | CS_MODE_BIG_ENDIAN | CS_MODE_HPPA_11
| CS_MODE_HPPA_20),
| CS_MODE_HPPA_20 | CS_MODE_HPPA_20W),
},
#else
{ NULL, NULL, 0 },
Expand Down
4 changes: 4 additions & 0 deletions cstool/cstool.c
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,8 @@ static struct {
{ "hppa11be", CS_ARCH_HPPA, CS_MODE_HPPA_11 | CS_MODE_BIG_ENDIAN },
{ "hppa20", CS_ARCH_HPPA, CS_MODE_HPPA_20 | CS_MODE_LITTLE_ENDIAN },
{ "hppa20be", CS_ARCH_HPPA, CS_MODE_HPPA_20 | CS_MODE_BIG_ENDIAN },
{ "hppa20w", CS_ARCH_HPPA, CS_MODE_HPPA_20W | CS_MODE_LITTLE_ENDIAN },
{ "hppa20wbe", CS_ARCH_HPPA, CS_MODE_HPPA_20W | CS_MODE_BIG_ENDIAN },
{ NULL }
};

Expand Down Expand Up @@ -224,6 +226,8 @@ static void usage(char *prog)
printf(" hppa11be hppa V1.1 + big endian\n");
printf(" hppa20 hppa V2.0 + little endian\n");
printf(" hppa20be hppa V2.0 + big endian\n");
printf(" hppa20w hppa V2.0 wide + little endian\n");
printf(" hppa20wbe hppa V2.0 wide + big endian\n");
}

if (cs_support(CS_ARCH_MIPS)) {
Expand Down
1 change: 1 addition & 0 deletions include/capstone/capstone.h
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,7 @@ typedef enum cs_mode {
CS_MODE_TRICORE_162 = 1 << 7, ///< Tricore 1.6.2
CS_MODE_HPPA_11 = 1 << 1, ///< HPPA 1.1
CS_MODE_HPPA_20 = 1 << 2, ///< HPPA 2.0
CS_MODE_HPPA_20W = CS_MODE_HPPA_20 | (1 << 3), ///< HPPA 2.0 wide
} cs_mode;

typedef void* (CAPSTONE_API *cs_malloc_t)(size_t size);
Expand Down
12 changes: 6 additions & 6 deletions suite/MC/HPPA/memory_reference20.s.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,15 @@
0x0c,0x41,0x60,0x43 = ldh,s r1(sr1,rp),r3
0x0c,0x41,0x60,0x63 = ldh,sm r1(sr1,rp),r3
0x0c,0x41,0x40,0x63 = ldh,m r1(sr1,rp),r3
0x44,0x43,0x41,0xbc = ldh 0x20de(sr1,rp),r3
0x44,0x43,0x41,0xbc = ldh 0xde(sr1,rp),r3
0x0c,0x51,0x50,0x63 = ldh,ma -8(sr1,rp),r3
0x0c,0x51,0x70,0x63 = ldh,mb -8(sr1,rp),r3
0x0c,0x50,0x58,0x43 = ldh,sl 8(sr1,rp),r3
0x0c,0x41,0x40,0x83 = ldw r1(sr1,rp),r3
0x0c,0x41,0x60,0x83 = ldw,s r1(sr1,rp),r3
0x0c,0x41,0x60,0xa3 = ldw,sm r1(sr1,rp),r3
0x0c,0x41,0x40,0xa3 = ldw,m r1(sr1,rp),r3
0x48,0x43,0x41,0xbc = ldw 0x20de(sr1,rp),r3
0x48,0x43,0x41,0xbc = ldw 0xde(sr1,rp),r3
0x0c,0x51,0x50,0xa3 = ldw,ma -8(sr1,rp),r3
0x0c,0x51,0x70,0xa3 = ldw,mb -8(sr1,rp),r3
0x0c,0x50,0x58,0x83 = ldw,sl 8(sr1,rp),r3
Expand All @@ -31,19 +31,19 @@
0x0c,0x51,0x50,0xe3 = ldd,ma -8(sr1,rp),r3
0x0c,0x51,0x70,0xe3 = ldd,mb -8(sr1,rp),r3
0x0c,0x50,0x58,0xc3 = ldd,sl 8(sr1,rp),r3
0x60,0x21,0xbf,0xb1 = stb r1,-0x4028(sr2,r1)
0x60,0x21,0xbf,0xb1 = stb r1,-0x28(sr2,r1)
0x0c,0x21,0x92,0x31 = stb,ma r1,-8(sr2,r1)
0x0c,0x21,0xb2,0x31 = stb,mb r1,-8(sr2,r1)
0x0c,0x21,0x92,0x20 = stb,o r1,0(sr2,r1)
0x64,0x21,0xbf,0xb1 = sth r1,-0x4028(sr2,r1)
0x64,0x21,0xbf,0xb1 = sth r1,-0x28(sr2,r1)
0x0c,0x21,0x92,0x71 = sth,ma r1,-8(sr2,r1)
0x0c,0x21,0xb2,0x71 = sth,mb r1,-8(sr2,r1)
0x0c,0x21,0x92,0x60 = sth,o r1,0(sr2,r1)
0x68,0x21,0xbf,0xb1 = stw r1,-0x4028(sr2,r1)
0x68,0x21,0xbf,0xb1 = stw r1,-0x28(sr2,r1)
0x0c,0x21,0x92,0xb1 = stw,ma r1,-8(sr2,r1)
0x0c,0x21,0xb2,0xb1 = stw,mb r1,-8(sr2,r1)
0x0c,0x21,0x92,0xa0 = stw,o r1,0(sr2,r1)
0x70,0x21,0xbf,0xb1 = std r1,-0x4028(sr2,r1)
0x70,0x21,0xbf,0xb1 = std r1,-0x28(sr2,r1)
0x0c,0x21,0x92,0xf1 = std,ma r1,-8(sr2,r1)
0x0c,0x21,0xb2,0xf1 = std,mb r1,-8(sr2,r1)
0x0c,0x21,0x92,0xe0 = std,o r1,0(sr2,r1)
Expand Down
1 change: 1 addition & 0 deletions suite/cstest/src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ static single_dict arches[] = {
{"CS_MODE_TRICORE_161", CS_MODE_TRICORE_161},
{"CS_MODE_TRICORE_162", CS_MODE_TRICORE_162},
{"CS_MODE_HPPA_20", CS_MODE_HPPA_20},
{"CS_MODE_HPPA_20W", CS_MODE_HPPA_20W},
{"CS_MODE_HPPA_11", CS_MODE_HPPA_11},
};

Expand Down

0 comments on commit 6f07eca

Please sign in to comment.