Handle reserved values of the 'at' bits of BO fields. (#2168)

This commit is contained in:
Rot127 2023-09-22 04:55:18 +00:00 committed by GitHub
parent 4e496d77f1
commit 123beeee4a
5 changed files with 121 additions and 54 deletions

View File

@ -582,51 +582,6 @@ void PPC_set_detail_op_imm(MCInst *MI, unsigned OpNum, int64_t Imm)
PPC_inc_op_count(MI);
}
/// Returns the predicate wihtout branch hint information.
ppc_pred PPC_get_no_hint_pred(unsigned Code)
{
switch (Code) {
default:
assert(0 && "Invalid predicate code");
case PPC_PRED_LT:
case PPC_PRED_LT_MINUS:
case PPC_PRED_LT_PLUS:
return PPC_PRED_LT;
case PPC_PRED_LE:
case PPC_PRED_LE_MINUS:
case PPC_PRED_LE_PLUS:
return PPC_PRED_LE;
case PPC_PRED_EQ:
case PPC_PRED_EQ_MINUS:
case PPC_PRED_EQ_PLUS:
return PPC_PRED_EQ;
case PPC_PRED_GE:
case PPC_PRED_GE_MINUS:
case PPC_PRED_GE_PLUS:
return PPC_PRED_GE;
case PPC_PRED_GT:
case PPC_PRED_GT_MINUS:
case PPC_PRED_GT_PLUS:
return PPC_PRED_GT;
case PPC_PRED_NE:
case PPC_PRED_NE_MINUS:
case PPC_PRED_NE_PLUS:
return PPC_PRED_NE;
case PPC_PRED_UN:
case PPC_PRED_UN_MINUS:
case PPC_PRED_UN_PLUS:
return PPC_PRED_UN;
case PPC_PRED_NU:
case PPC_PRED_NU_MINUS:
case PPC_PRED_NU_PLUS:
return PPC_PRED_NU;
case PPC_PRED_BIT_SET:
case PPC_PRED_BIT_UNSET:
assert(0 && "Invalid use of bit predicate code");
}
return PPC_PRED_INVALID;
}
void PPC_set_mem_access(MCInst *MI, bool status)
{
if (!detail_is_set(MI))

View File

@ -68,7 +68,6 @@ void PPC_insert_detail_op_imm_at(MCInst *MI, unsigned index, int64_t Val,
void PPC_setup_op(cs_ppc_op *op);
ppc_pred PPC_get_no_hint_pred(unsigned Code);
void PPC_check_updates_cr0(MCInst *MI);
void PPC_set_instr_map_data(MCInst *MI, const uint8_t *Bytes, size_t BytesLen);

View File

@ -31,8 +31,18 @@ PPC_PRED_GT_PLUS = (1<<5)|15
PPC_PRED_NE_PLUS = (2<<5)|7
PPC_PRED_UN_PLUS = (3<<5)|15
PPC_PRED_NU_PLUS = (3<<5)|7
PPC_PRED_NZ_PLUS = (0<<5)|17
PPC_PRED_Z_PLUS = (0<<5)|19
PPC_PRED_NZ_PLUS = (0<<5)|25
PPC_PRED_Z_PLUS = (0<<5)|27
PPC_PRED_LT_RESERVED = (0<<5)|13
PPC_PRED_LE_RESERVED = (1<<5)|5
PPC_PRED_EQ_RESERVED = (2<<5)|13
PPC_PRED_GE_RESERVED = (0<<5)|5
PPC_PRED_GT_RESERVED = (1<<5)|13
PPC_PRED_NE_RESERVED = (2<<5)|5
PPC_PRED_UN_RESERVED = (3<<5)|13
PPC_PRED_NU_RESERVED = (3<<5)|5
PPC_PRED_NZ_RESERVED = (0<<5)|17
PPC_PRED_Z_RESERVED = (0<<5)|19
PPC_PRED_SPE = PPC_PRED_GT
PPC_PRED_BIT_SET = 1024
PPC_PRED_BIT_UNSET = 1025

View File

@ -15,42 +15,52 @@ static const char* get_pred_name(ppc_pred pred)
case PPC_PRED_LT:
case PPC_PRED_LT_MINUS:
case PPC_PRED_LT_PLUS:
case PPC_PRED_LT_RESERVED:
return ("lt");
case PPC_PRED_LE:
case PPC_PRED_LE_MINUS:
case PPC_PRED_LE_PLUS:
case PPC_PRED_LE_RESERVED:
return ("le");
case PPC_PRED_EQ:
case PPC_PRED_EQ_MINUS:
case PPC_PRED_EQ_PLUS:
case PPC_PRED_EQ_RESERVED:
return ("eq");
case PPC_PRED_GE:
case PPC_PRED_GE_MINUS:
case PPC_PRED_GE_PLUS:
case PPC_PRED_GE_RESERVED:
return ("ge");
case PPC_PRED_GT:
case PPC_PRED_GT_MINUS:
case PPC_PRED_GT_PLUS:
case PPC_PRED_GT_RESERVED:
return ("gt");
case PPC_PRED_NE:
case PPC_PRED_NE_MINUS:
case PPC_PRED_NE_PLUS:
case PPC_PRED_NE_RESERVED:
return ("ne");
case PPC_PRED_UN: // PPC_PRED_SO
case PPC_PRED_UN_MINUS:
case PPC_PRED_UN_PLUS:
case PPC_PRED_UN_RESERVED:
return ("so/un");
case PPC_PRED_NU: // PPC_PRED_NS
case PPC_PRED_NU_MINUS:
case PPC_PRED_NU_PLUS:
case PPC_PRED_NU_RESERVED:
return ("ns/nu");
case PPC_PRED_NZ:
case PPC_PRED_NZ_MINUS:
case PPC_PRED_NZ_PLUS:
case PPC_PRED_NZ_RESERVED:
return ("nz");
case PPC_PRED_Z:
case PPC_PRED_Z_MINUS:
case PPC_PRED_Z_PLUS:
case PPC_PRED_Z_RESERVED:
return ("z");
case PPC_PRED_BIT_SET:
return "bit-set";
@ -59,6 +69,21 @@ static const char* get_pred_name(ppc_pred pred)
}
}
static const char *get_pred_hint(ppc_br_hint at) {
switch (at) {
default:
return "invalid";
case PPC_BR_NOT_GIVEN:
return "not-given";
case PPC_BR_TAKEN:
return "likely-taken";
case PPC_BR_NOT_TAKEN:
return "likely-not-taken";
case PPC_BR_RESERVED:
return "reserved";
}
}
void print_insn_detail_ppc(csh handle, cs_insn *ins)
{
cs_ppc *ppc;
@ -125,7 +150,7 @@ void print_insn_detail_ppc(csh handle, cs_insn *ins)
if (ppc->bc.pred_ctr != PPC_PRED_INVALID)
printf("\t\tpred CTR: %s\n", get_pred_name(ppc->bc.pred_ctr));
if (ppc->bc.hint != PPC_BH_INVALID)
printf("\t\thint: %u\n", ppc->bc.hint);
printf("\t\thint: %s\n", get_pred_hint(ppc->bc.hint));
}
if (ppc->bc.hint != PPC_BR_NOT_GIVEN)

View File

@ -8,6 +8,7 @@
extern "C" {
#endif
#include <assert.h>
#include "cs_operand.h"
#include "platform.h"
@ -89,8 +90,19 @@ typedef enum ppc_pred {
PPC_PRED_NE_PLUS = (2 << 5) | 7,
PPC_PRED_UN_PLUS = (3 << 5) | 15,
PPC_PRED_NU_PLUS = (3 << 5) | 7,
PPC_PRED_NZ_PLUS = (0 << 5) | 17,
PPC_PRED_Z_PLUS = (0 << 5) | 19,
PPC_PRED_NZ_PLUS = (0 << 5) | 25,
PPC_PRED_Z_PLUS = (0 << 5) | 27,
// Reserved
PPC_PRED_LT_RESERVED = (0 << 5) | 13,
PPC_PRED_LE_RESERVED = (1 << 5) | 5,
PPC_PRED_EQ_RESERVED = (2 << 5) | 13,
PPC_PRED_GE_RESERVED = (0 << 5) | 5,
PPC_PRED_GT_RESERVED = (1 << 5) | 13,
PPC_PRED_NE_RESERVED = (2 << 5) | 5,
PPC_PRED_UN_RESERVED = (3 << 5) | 13,
PPC_PRED_NU_RESERVED = (3 << 5) | 5,
PPC_PRED_NZ_RESERVED = (0 << 5) | 17,
PPC_PRED_Z_RESERVED = (0 << 5) | 19,
// SPE scalar compare instructions always set the GT bit.
PPC_PRED_SPE = PPC_PRED_GT,
@ -141,6 +153,71 @@ typedef enum {
PPC_BH_RESERVED,
} ppc_bh;
/// Returns the predicate wihtout branch hint information.
inline static ppc_pred PPC_get_no_hint_pred(ppc_pred Code)
{
switch (Code) {
default:
return PPC_PRED_INVALID;
case PPC_PRED_LT:
case PPC_PRED_LT_MINUS:
case PPC_PRED_LT_PLUS:
case PPC_PRED_LT_RESERVED:
return PPC_PRED_LT;
case PPC_PRED_LE:
case PPC_PRED_LE_MINUS:
case PPC_PRED_LE_PLUS:
case PPC_PRED_LE_RESERVED:
return PPC_PRED_LE;
case PPC_PRED_EQ:
case PPC_PRED_EQ_MINUS:
case PPC_PRED_EQ_PLUS:
case PPC_PRED_EQ_RESERVED:
return PPC_PRED_EQ;
case PPC_PRED_GE:
case PPC_PRED_GE_MINUS:
case PPC_PRED_GE_PLUS:
case PPC_PRED_GE_RESERVED:
return PPC_PRED_GE;
case PPC_PRED_GT:
case PPC_PRED_GT_MINUS:
case PPC_PRED_GT_PLUS:
case PPC_PRED_GT_RESERVED:
return PPC_PRED_GT;
case PPC_PRED_NE:
case PPC_PRED_NE_MINUS:
case PPC_PRED_NE_PLUS:
case PPC_PRED_NE_RESERVED:
return PPC_PRED_NE;
case PPC_PRED_UN:
case PPC_PRED_UN_MINUS:
case PPC_PRED_UN_PLUS:
case PPC_PRED_UN_RESERVED:
return PPC_PRED_UN;
case PPC_PRED_NU:
case PPC_PRED_NU_MINUS:
case PPC_PRED_NU_PLUS:
case PPC_PRED_NU_RESERVED:
return PPC_PRED_NU;
case PPC_PRED_NZ:
case PPC_PRED_NZ_MINUS:
case PPC_PRED_NZ_PLUS:
case PPC_PRED_NZ_RESERVED:
return PPC_PRED_NZ;
case PPC_PRED_Z:
case PPC_PRED_Z_MINUS:
case PPC_PRED_Z_PLUS:
case PPC_PRED_Z_RESERVED:
return PPC_PRED_Z;
case PPC_PRED_BIT_SET:
return PPC_PRED_BIT_SET;
case PPC_PRED_BIT_UNSET:
return PPC_PRED_BIT_UNSET;
}
return PPC_PRED_INVALID;
}
/// Returns the hint encoded in the BO bits a and t.
static inline ppc_br_hint PPC_get_hint(uint8_t bo)
{
@ -158,6 +235,7 @@ static inline ppc_br_hint PPC_get_hint(uint8_t bo)
/// Returns the branch predicate encoded in the BO and BI field.
/// If get_cr_pred = true the CR-bit predicate is returned (LE, GE, EQ...).
/// Otherwise the CTR predicate (NZ, Z)
/// The branch hint does not include the hint of the 'at' bits.
///
/// It returns PPC_PRED_INVALID if the CR predicate is requested, but no
/// CR predicate is encoded in BI and BO. Same for the CTR predicate.
@ -176,11 +254,11 @@ static inline ppc_pred PPC_get_branch_pred(uint8_t bi, uint8_t bo,
// The CTR condition without the CR-bit condition.
unsigned ctr_bo_cond = (bo | PPC_BO_TEST_CR) & ~PPC_BO_CR_CMP;
if (get_cr_pred)
return (ppc_pred)(((bi % 4) << 5) | cr_bo_cond);
return (ppc_pred)ctr_bo_cond; // BI is ignored
return PPC_get_no_hint_pred((ppc_pred)(((bi % 4) << 5) | cr_bo_cond));
return PPC_get_no_hint_pred((ppc_pred)ctr_bo_cond); // BI is ignored
}
// BO doesn't need any separation
return (ppc_pred)(((bi % 4) << 5) | bo);
return PPC_get_no_hint_pred((ppc_pred)(((bi % 4) << 5) | bo));
}
/// Operand type for instruction's operands