Skip to content

Commit

Permalink
Sync with C source.
Browse files Browse the repository at this point in the history
  • Loading branch information
Rot127 committed Feb 6, 2024
1 parent 47ce8d6 commit 5c6ec44
Show file tree
Hide file tree
Showing 5 changed files with 103 additions and 93 deletions.
22 changes: 11 additions & 11 deletions handwritten/hexagon_c/functions.c
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,8 @@ int resolve_n_register(const int reg_num, const ut32 addr, const HexPkt *p) {
hic = rz_list_get_n(p->bin, prod_i);

if (!hic || !hic->bin.insn || (hic->is_duplex && (!hic->bin.sub[0] || !hic->bin.sub[1]))) {
// This case happens if the current instruction (with the .new register)
// is yet the only one in the packet.
// This case happens if the current instruction (with the .new register)
// is yet the only one in the packet.
return UT32_MAX;
}
if (hic->identifier == HEX_INS_A4_EXT) {
Expand Down Expand Up @@ -104,13 +104,13 @@ RZ_API const HexOp hex_alias_to_op(HexRegAlias alias, bool tmp_reg) {
* \return const char * The corresponding register name. Or NULL on error.
*/
RZ_API const char *hex_alias_to_reg(HexRegAlias alias, bool tmp_reg) {
if (alias >= ARRAY_LEN(hex_alias_reg_lt_v69)) {
return NULL;
}
HexRegClass reg_class = hex_alias_reg_lt_v69[alias].cls;
int reg_enum = hex_alias_reg_lt_v69[alias].reg_enum;
if (alias == HEX_REG_ALIAS_PC) {
return "PC";
}
return hex_get_reg_in_class(reg_class, reg_enum, false, tmp_reg, true);
if (alias >= ARRAY_LEN(hex_alias_reg_lt_v69)) {
return NULL;
}
HexRegClass reg_class = hex_alias_reg_lt_v69[alias].cls;
int reg_enum = hex_alias_reg_lt_v69[alias].reg_enum;
if (alias == HEX_REG_ALIAS_PC) {
return "PC";
}
return hex_get_reg_in_class(reg_class, reg_enum, false, tmp_reg, true);
}
78 changes: 39 additions & 39 deletions handwritten/hexagon_h/typedefs.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,15 @@
// SPDX-License-Identifier: LGPL-3.0-only

typedef struct {
const char *name;
const char *alias;
const char *name_tmp;
const char *alias_tmp;
const char *name;
const char *alias;
const char *name_tmp;
const char *alias_tmp;
} HexRegNames;

typedef struct {
ut32 /* Reg class */ cls;
ut32 /* Reg Enum */ reg_enum;
ut32 /* Reg class */ cls;
ut32 /* Reg Enum */ reg_enum;
} HexRegAliasMapping;

typedef enum {
Expand All @@ -22,10 +22,10 @@ typedef enum {
* \brief Flags to mark which kind of predicates instructions use.
*/
typedef enum {
HEX_NOPRED, ///< no conditional execution
HEX_PRED_TRUE, ///< if (Pd) ...
HEX_PRED_FALSE, ///< if (!Pd) ...
HEX_PRED_NEW, ///< if (Pd.new) or if (!Pd.new)
HEX_NOPRED, ///< no conditional execution
HEX_PRED_TRUE, ///< if (Pd) ...
HEX_PRED_FALSE, ///< if (!Pd) ...
HEX_PRED_NEW, ///< if (Pd.new) or if (!Pd.new)
} HexPred;

typedef enum {
Expand Down Expand Up @@ -122,42 +122,42 @@ typedef struct {
*/
typedef struct {
ut8 parse_bits; ///< Parse bits of instruction.
bool is_duplex; ///< Does this container hold two sub-instructions?
ut32 identifier; ///< Equals instruction ID if is_duplex = false. Otherwise: (high.id << 16) | (low.id & 0xffff)
union {
HexInsn *sub[2]; ///< Pointer to sub-instructions if is_duplex = true. sub[0] = high, sub[1] = low
HexInsn *insn; ///< Pointer to instruction if is_duplex = false.
} bin;
ut32 addr; ///< Address of container. Equals address of instruction or of the high sub-instruction if this is a duplex.
ut32 bytes; ///< The instruction bytes.
HexPktInfo pkt_info; ///< Packet related information. First/last instr., prefix and postfix for text etc.
// Deprecated members will be removed on RzArch introduction.
RZ_DEPRECATE RzAsmOp asm_op; ///< Private copy of AsmOp. Currently only of interest because it holds the utf8 flag.
bool is_duplex; ///< Does this container hold two sub-instructions?
ut32 identifier; ///< Equals instruction ID if is_duplex = false. Otherwise: (high.id << 16) | (low.id & 0xffff)
union {
HexInsn *sub[2]; ///< Pointer to sub-instructions if is_duplex = true. sub[0] = high, sub[1] = low
HexInsn *insn; ///< Pointer to instruction if is_duplex = false.
} bin;
ut32 addr; ///< Address of container. Equals address of instruction or of the high sub-instruction if this is a duplex.
ut32 bytes; ///< The instruction bytes.
HexPktInfo pkt_info; ///< Packet related information. First/last instr., prefix and postfix for text etc.
// Deprecated members will be removed on RzArch introduction.
RZ_DEPRECATE RzAsmOp asm_op; ///< Private copy of AsmOp. Currently only of interest because it holds the utf8 flag.
RZ_DEPRECATE RzAnalysisOp ana_op; ///< Private copy of AnalysisOp. Analysis info is written into it.
char text[296]; ///< Textual disassembly
} HexInsnContainer;

#define HEX_LOG_SLOT_BIT_OFF 4
#define HEX_LOG_SLOT_BIT_OFF 4
#define HEX_LOG_SLOT_LOG_WIDTH 2
#define HEX_LOG_SLOT_LOG_MASK 0b11
#define HEX_LOG_SLOT_LOG_MASK 0b11

/**
* \brief Holds information about the execution of the packet.
*/
typedef struct {
ut8 slot_cancelled; ///< Flags for cancelled slots. If bit at (1 << slot i) is set, slot i is cancelled.
ut8 pred_read; ///< Predicate register (P0-P3) read, if flags set at (1 << reg_num) are set.
ut8 pred_tmp_read; ///< Tmp predicate register (P0-P3) read, if flags set at (1 << reg_num) are set.
ut32 pred_written; ///< Predicate register (P0-P3) written, if flags (3:0) are set at (1 << pred_num).
///< The bits[11:4] are used to indicate the last slot which wrote to the predicate (2bit each).
///< Details are necessary because, if instructions in different slots
///< write to the same predicate, the result is ANDed.
ut64 gpr_read; ///< GPR register (R0-R31) read, if flags set at (1 << reg_num) are set.
ut64 gpr_tmp_read; ///< Tmp GPR register (R0-R31) read, if flags set at (1 << reg_num) are set.
ut64 gpr_written; ///< GPR register (R0-R31) written, if flags set at (1 << reg_num) are set.
ut64 ctr_read; ///< Control register (C0-C31) read, if flags set at (1 << reg_num) are set.
ut64 ctr_tmp_read; ///< Tmp control register (C0-C31) read, if flags set at (1 << reg_num) are set.
ut64 ctr_written; ///< Control register (C0-C31) written, if flags set at (1 << reg_num) are set.
RzBitVector *slot_cancelled; ///< Flags for cancelled slots. If bit at (1 << slot i) is set, slot i is cancelled.
RzBitVector *pred_read; ///< Predicate register (P0-P3) read, if flags set at (1 << reg_num) are set.
RzBitVector *pred_tmp_read; ///< Tmp predicate register (P0-P3) read, if flags set at (1 << reg_num) are set.
RzBitVector *pred_written; ///< Predicate register (P0-P3) written, if flags (3:0) are set at (1 << pred_num).
///< The bits[11:4] are used to indicate the last slot which wrote to the predicate (2bit each).
///< Details are necessary because, if instructions in different slots
///< write to the same predicate, the result is ANDed.
RzBitVector *gpr_read; ///< GPR register (R0-R31) read, if flags set at (1 << reg_num) are set.
RzBitVector *gpr_tmp_read; ///< Tmp GPR register (R0-R31) read, if flags set at (1 << reg_num) are set.
RzBitVector *gpr_written; ///< GPR register (R0-R31) written, if flags set at (1 << reg_num) are set.
RzBitVector *ctr_read; ///< Control register (C0-C31) read, if flags set at (1 << reg_num) are set.
RzBitVector *ctr_tmp_read; ///< Tmp control register (C0-C31) read, if flags set at (1 << reg_num) are set.
RzBitVector *ctr_written; ///< Control register (C0-C31) written, if flags set at (1 << reg_num) are set.
} HexILExecData;

/**
Expand Down Expand Up @@ -189,7 +189,7 @@ typedef struct {
ut32 hw_loop1_addr; ///< Start address of hardware loop 1
ut32 pkt_addr; ///< Address of the packet. Equals the address of the first instruction.
ut64 last_access; ///< Last time accessed in milliseconds
RzList /*<HexInsnContainer>*/ *bin; ///< Descending by address sorted list of instruction containers.
RzList /*<HexInsnContainer *>*/ *bin; ///< Descending by address sorted list of instruction containers.
RzPVector /*<HexILOp *>*/ *il_ops; ///< Pointer to RZIL ops of the packet. If empty the il ops were not shuffled into order yet.
HexILExecData il_op_stats; ///< Meta information about the IL operations executed (register read/written etc.)
} HexPkt;
Expand All @@ -199,8 +199,8 @@ typedef struct {
* They use it for resolving register names, alias and the like.
*/
typedef struct {
const HexInsn *insn;
HexPkt *pkt;
const HexInsn *insn;
HexPkt *pkt;
} HexInsnPktBundle;

typedef struct {
Expand Down
21 changes: 4 additions & 17 deletions handwritten/hexagon_il_X_ops_c/non_insn_ops.c
Original file line number Diff line number Diff line change
Expand Up @@ -45,23 +45,11 @@ RZ_IPI RZ_OWN RzILOpEffect *hex_get_npc(const HexPkt *pkt) {
return SETL("ret_val", r);
}

static void reset_pkt_stats(HexILExecData *stats) {
rz_bits_map_init_64(&stats->ctr_written);
rz_bits_map_init_64(&stats->gpr_written);
rz_bits_map_init_32(&stats->pred_written);
rz_bits_map_init_64(&stats->ctr_read);
rz_bits_map_init_64(&stats->gpr_read);
rz_bits_map_init_32(&stats->pred_read);
rz_bits_map_init_64(&stats->ctr_tmp_read);
rz_bits_map_init_64(&stats->gpr_tmp_read);
rz_bits_map_init_32(&stats->pred_tmp_read);
}

RZ_IPI RZ_OWN RzILOpEffect *hex_commit_packet(HexInsnPktBundle *bundle) {
HexILExecData *stats = &bundle->pkt->il_op_stats;
RzILOpEffect *commit_seq = EMPTY();
for (ut8 i = 0; i <= HEX_REG_CTR_REGS_C31; ++i) {
if (!(rz_bits_map_get_64(&stats->ctr_written, i))) {
if (!(rz_bv_get(stats->ctr_written, i))) {
continue;
}
const char *dest_reg = hex_get_reg_in_class(HEX_REG_CLASS_CTR_REGS, i, false, false, false);
Expand All @@ -70,7 +58,7 @@ RZ_IPI RZ_OWN RzILOpEffect *hex_commit_packet(HexInsnPktBundle *bundle) {
}

for (ut8 i = 0; i <= HEX_REG_INT_REGS_R31; ++i) {
if (!(rz_bits_map_get_64(&stats->gpr_written, i))) {
if (!(rz_bv_get(stats->gpr_written, i))) {
continue;
}
const char *dest_reg = hex_get_reg_in_class(HEX_REG_CLASS_INT_REGS, i, false, false, false);
Expand All @@ -79,15 +67,15 @@ RZ_IPI RZ_OWN RzILOpEffect *hex_commit_packet(HexInsnPktBundle *bundle) {
}

for (ut8 i = 0; i <= HEX_REG_PRED_REGS_P3; ++i) {
if (!(rz_bits_map_get_32(&stats->pred_written, i))) {
if (!(rz_bv_get(stats->pred_written, i))) {
continue;
}
const char *dest_reg = hex_get_reg_in_class(HEX_REG_CLASS_PRED_REGS, i, false, false, false);
const char *src_reg = hex_get_reg_in_class(HEX_REG_CLASS_PRED_REGS, i, false, true, false);
commit_seq = SEQ2(commit_seq, SETG(dest_reg, VARG(src_reg)));
}

reset_pkt_stats(stats);
hex_reset_il_pkt_stats(stats);
return commit_seq;
}

Expand All @@ -110,4 +98,3 @@ RZ_IPI RZ_OWN RzILOpEffect *hex_il_op_next_pkt_jmp(HexInsnPktBundle *bundle) {
}
return EMPTY();
}

74 changes: 48 additions & 26 deletions handwritten/hexagon_il_c/functions.c
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,7 @@ static RZ_OWN RzILOpEffect *hex_pkt_to_il_seq(HexPkt *pkt) {

static bool set_pkt_il_ops(RZ_INOUT HexPkt *p) {
rz_return_val_if_fail(p, false);
hex_reset_il_pkt_stats(&p->il_op_stats);
// This function is a lot of unnecessary overhead so:
// TODO The assignment of IL instructions to their actual instructions should be done in the instruction template.
// But with the current separation between Asm and Analysis plugins this is not possible.
Expand Down Expand Up @@ -411,49 +412,49 @@ static void log_reg_read(RZ_BORROW HexPkt *pkt, ut8 reg_num, HexRegClass reg_cla
case HEX_REG_CLASS_DOUBLE_REGS:
case HEX_REG_CLASS_GENERAL_DOUBLE_LOW8_REGS:
if (tmp_reg) {
rz_bits_map_set_64(&pkt->il_op_stats.gpr_tmp_read, (reg_num + 1));
rz_bv_set(pkt->il_op_stats.gpr_tmp_read, (reg_num + 1), true);
} else {
rz_bits_map_set_64(&pkt->il_op_stats.gpr_read, (reg_num + 1));
rz_bv_set(pkt->il_op_stats.gpr_read, (reg_num + 1), true);
}
// fallthrough
case HEX_REG_CLASS_INT_REGS:
case HEX_REG_CLASS_INT_REGS_LOW8:
case HEX_REG_CLASS_GENERAL_SUB_REGS:
if (tmp_reg) {
rz_bits_map_set_64(&pkt->il_op_stats.gpr_tmp_read, reg_num);
rz_bv_set(pkt->il_op_stats.gpr_tmp_read, reg_num, true);
} else {
rz_bits_map_set_64(&pkt->il_op_stats.gpr_read, reg_num);
rz_bv_set(pkt->il_op_stats.gpr_read, reg_num, true);
}
break;
case HEX_REG_CLASS_CTR_REGS64:
if (tmp_reg) {
rz_bits_map_set_64(&pkt->il_op_stats.ctr_tmp_read, (reg_num + 1));
rz_bv_set(pkt->il_op_stats.ctr_tmp_read, (reg_num + 1), true);
} else {
rz_bits_map_set_64(&pkt->il_op_stats.ctr_read, (reg_num + 1));
rz_bv_set(pkt->il_op_stats.ctr_read, (reg_num + 1), true);
}
// fallthrough
case HEX_REG_CLASS_MOD_REGS:
case HEX_REG_CLASS_CTR_REGS:
if (tmp_reg) {
rz_bits_map_set_64(&pkt->il_op_stats.ctr_tmp_read, reg_num);
rz_bv_set(pkt->il_op_stats.ctr_tmp_read, reg_num, true);
} else {
rz_bits_map_set_64(&pkt->il_op_stats.ctr_read, reg_num);
rz_bv_set(pkt->il_op_stats.ctr_read, reg_num, true);
}
break;
case HEX_REG_CLASS_PRED_REGS:
if (tmp_reg) {
rz_bits_map_set_32(&pkt->il_op_stats.pred_tmp_read, reg_num);
rz_bv_set(pkt->il_op_stats.pred_tmp_read, reg_num, true);
} else {
rz_bits_map_set_32(&pkt->il_op_stats.pred_read, reg_num);
rz_bv_set(pkt->il_op_stats.pred_read, reg_num, true);
}
break;
}
}

static inline void log_pred_write_slot(HexInsnPktBundle *bundle, ut32 pred_num) {
ut32 pos = (pred_num * HEX_LOG_SLOT_LOG_WIDTH);
bundle->pkt->il_op_stats.pred_written &= ~(HEX_LOG_SLOT_LOG_MASK << HEX_LOG_SLOT_BIT_OFF << pos);
rz_bits_map_set_32(&bundle->pkt->il_op_stats.pred_written, bundle->insn->slot + HEX_LOG_SLOT_BIT_OFF + pos);
rz_bv_set_range(bundle->pkt->il_op_stats.pred_written, HEX_LOG_SLOT_BIT_OFF + pos, HEX_LOG_SLOT_BIT_OFF + pos + 2, false);
rz_bv_set(bundle->pkt->il_op_stats.pred_written, bundle->insn->slot + HEX_LOG_SLOT_BIT_OFF + pos, true);
}

static void log_reg_write(RZ_BORROW HexInsnPktBundle *bundle, ut8 reg_num, HexRegClass reg_class, bool read, bool tmp_reg) {
Expand All @@ -471,26 +472,26 @@ static void log_reg_write(RZ_BORROW HexInsnPktBundle *bundle, ut8 reg_num, HexRe
break;
case HEX_REG_CLASS_DOUBLE_REGS:
case HEX_REG_CLASS_GENERAL_DOUBLE_LOW8_REGS:
rz_bits_map_set_64(&pkt->il_op_stats.gpr_written, (reg_num + 1));
rz_bv_set(pkt->il_op_stats.gpr_written, (reg_num + 1), true);
// fallthrough
case HEX_REG_CLASS_INT_REGS:
case HEX_REG_CLASS_INT_REGS_LOW8:
case HEX_REG_CLASS_GENERAL_SUB_REGS:
rz_bits_map_set_64(&pkt->il_op_stats.gpr_written, reg_num);
rz_bv_set(pkt->il_op_stats.gpr_written, reg_num, true);
break;
case HEX_REG_CLASS_CTR_REGS64:
if (hex_ctr_immut_masks[reg_num + 1] != HEX_IMMUTABLE_REG) {
rz_bits_map_set_64(&pkt->il_op_stats.ctr_written, (reg_num + 1));
rz_bv_set(pkt->il_op_stats.ctr_written, (reg_num + 1), true);
}
// fallthrough
case HEX_REG_CLASS_MOD_REGS:
case HEX_REG_CLASS_CTR_REGS:
if (hex_ctr_immut_masks[reg_num] != HEX_IMMUTABLE_REG) {
rz_bits_map_set_64(&pkt->il_op_stats.ctr_written, reg_num);
rz_bv_set(pkt->il_op_stats.ctr_written, reg_num, true);
}
break;
case HEX_REG_CLASS_PRED_REGS:
rz_bits_map_set_32(&pkt->il_op_stats.pred_written, reg_num);
rz_bv_set(pkt->il_op_stats.pred_written, reg_num, true);
if (bundle->insn) {
log_pred_write_slot(bundle, reg_num);
}
Expand All @@ -500,7 +501,7 @@ static void log_reg_write(RZ_BORROW HexInsnPktBundle *bundle, ut8 reg_num, HexRe

static ut32 get_last_slot_w_to_p(const HexPkt *pkt, ut32 pred_num) {
rz_return_val_if_fail(pkt, false);
ut32 slots = (pkt->il_op_stats.pred_written >> HEX_LOG_SLOT_BIT_OFF);
ut32 slots = (rz_bv_to_ut32(pkt->il_op_stats.pred_written) >> HEX_LOG_SLOT_BIT_OFF);
return (slots >> (pred_num * HEX_LOG_SLOT_LOG_WIDTH)) & HEX_LOG_SLOT_LOG_MASK;
}

Expand All @@ -518,11 +519,11 @@ static bool other_slot_wrote_to_pred(const HexInsnPktBundle *bundle, ut32 pred_n
const HexPkt *pkt = bundle->pkt;
if (!bundle->insn) {
// Non instruction ops
return (pkt->il_op_stats.pred_written & (1 << pred_num));
return rz_bv_get(pkt->il_op_stats.pred_written, 1 << pred_num);
}
ut32 pw = (pkt->il_op_stats.pred_written & (1 << pred_num));
bool pw = rz_bv_get(pkt->il_op_stats.pred_written, 1 << pred_num);
bool slot_w = get_last_slot_w_to_p(bundle->pkt, pred_num) != bundle->insn->slot;
return (pw != 0) && slot_w;
return pw && slot_w;
}

static inline RzILOpPure *get_masked_reg_val(RzILOpPure *reg_val, RzILOpPure *val, ut32 mask) {
Expand Down Expand Up @@ -674,13 +675,13 @@ static bool x_reg_rw_overlap(const HexPkt *pkt, const HexOp *op, ut32 reg_num) {
case HEX_REG_CLASS_GENERAL_SUB_REGS:
case HEX_REG_CLASS_DOUBLE_REGS:
case HEX_REG_CLASS_GENERAL_DOUBLE_LOW8_REGS:
return (rz_bits_map_get_64(&pkt->il_op_stats.gpr_written, reg_num)) && (rz_bits_map_get_64(&pkt->il_op_stats.gpr_read, reg_num)) && op->isa_id == 'x';
return (rz_bv_get(pkt->il_op_stats.gpr_written, reg_num)) && (rz_bv_get(pkt->il_op_stats.gpr_read, reg_num)) && op->isa_id == 'x';
case HEX_REG_CLASS_MOD_REGS:
case HEX_REG_CLASS_CTR_REGS:
case HEX_REG_CLASS_CTR_REGS64:
return (rz_bits_map_get_64(&pkt->il_op_stats.ctr_written, reg_num)) && (rz_bits_map_get_64(&pkt->il_op_stats.ctr_read, reg_num)) && op->isa_id == 'x';
return (rz_bv_get(pkt->il_op_stats.ctr_written, reg_num)) && (rz_bv_get(pkt->il_op_stats.ctr_read, reg_num)) && op->isa_id == 'x';
case HEX_REG_CLASS_PRED_REGS:
return (rz_bits_map_get_32(&pkt->il_op_stats.pred_written, reg_num)) && (rz_bits_map_get_32(&pkt->il_op_stats.pred_read, reg_num)) && op->isa_id == 'x';
return (rz_bv_get(pkt->il_op_stats.pred_written, reg_num)) && (rz_bv_get(pkt->il_op_stats.pred_read, reg_num)) && op->isa_id == 'x';
}
}

Expand Down Expand Up @@ -811,7 +812,7 @@ RZ_IPI RZ_OWN RzILOpEffect *hex_cancel_slot(RZ_BORROW HexPkt *pkt, ut8 slot) {
rz_warn_if_reached();
RZ_LOG_WARN("Slot %d does not exist!", slot);
}
rz_bits_map_set_32(&pkt->il_op_stats.slot_cancelled, slot);
rz_bv_set(pkt->il_op_stats.slot_cancelled, slot, true);
return EMPTY();
}

Expand All @@ -831,4 +832,25 @@ RzILOpPure *hex_get_corresponding_cs(RZ_BORROW HexPkt *pkt, const HexOp *Mu) {
}
rz_warn_if_reached();
return NULL;
}
}

RZ_IPI void hex_reset_il_pkt_stats(HexILExecData *stats) {
rz_bv_free(stats->ctr_written);
rz_bv_free(stats->gpr_written);
rz_bv_free(stats->pred_written);
rz_bv_free(stats->ctr_read);
rz_bv_free(stats->gpr_read);
rz_bv_free(stats->pred_read);
rz_bv_free(stats->ctr_tmp_read);
rz_bv_free(stats->gpr_tmp_read);
rz_bv_free(stats->pred_tmp_read);
stats->ctr_written = rz_bv_new(64);
stats->gpr_written = rz_bv_new(64);
stats->pred_written = rz_bv_new(32);
stats->ctr_read = rz_bv_new(64);
stats->gpr_read = rz_bv_new(64);
stats->pred_read = rz_bv_new(32);
stats->ctr_tmp_read = rz_bv_new(64);
stats->gpr_tmp_read = rz_bv_new(64);
stats->pred_tmp_read = rz_bv_new(32);
}
Loading

0 comments on commit 5c6ec44

Please sign in to comment.