Skip to content

Commit

Permalink
Handle writes to immutable and partly immutable registers.
Browse files Browse the repository at this point in the history
  • Loading branch information
Rot127 committed Nov 11, 2023
1 parent 8f3b134 commit 33a05ca
Showing 1 changed file with 35 additions and 16 deletions.
51 changes: 35 additions & 16 deletions handwritten/hexagon_il_c/functions.c
Original file line number Diff line number Diff line change
Expand Up @@ -467,11 +467,15 @@ static void log_reg_write(RZ_BORROW HexInsnPktBundle *bundle, ut8 reg_num, HexRe
pkt->il_op_stats.gpr_written |= (1 << reg_num);
break;
case HEX_REG_CLASS_CTR_REGS64:
pkt->il_op_stats.ctr_written |= (1 << (reg_num + 1));
if (hex_ctr_immut_masks[reg_num + 1] != HEX_IMMUTABLE_MASK) {
pkt->il_op_stats.ctr_written |= (1 << (reg_num + 1));
}
// fallthrough
case HEX_REG_CLASS_MOD_REGS:
case HEX_REG_CLASS_CTR_REGS:
pkt->il_op_stats.ctr_written |= (1 << reg_num);
if (hex_ctr_immut_masks[reg_num] != HEX_IMMUTABLE_MASK) {
pkt->il_op_stats.ctr_written |= (1 << reg_num);
}
break;
case HEX_REG_CLASS_PRED_REGS:
pkt->il_op_stats.pred_written |= (1 << reg_num);
Expand Down Expand Up @@ -509,6 +513,12 @@ static bool other_slot_wrote_to_pred(const HexInsnPktBundle *bundle, ut32 pred_n
return (pw != 0) && slot_w;
}

static inline RzILOpPure *get_masked_reg_val(RzILOpPure *reg_val, RzILOpPure *val, ut32 mask) {
RzILOpPure *masked_val = LOGAND(val, LOGNOT(U32(mask)));
RzILOpPure *masked_reg = LOGAND(reg_val, U32(mask));
return LOGOR(masked_reg, masked_val);
}

/**
* \brief Writes the given value to the register specified in \p op and logs the write.
* If the register is a double register, each of its sub-registers are written separately.
Expand All @@ -528,7 +538,7 @@ RZ_IPI RZ_OWN RzILOpEffect *hex_write_reg(RZ_BORROW HexInsnPktBundle *bundle, co
RzILOpPure *high_val = NULL;
RzILOpPure *low_val = NULL;
ut32 reg_num = hex_resolve_reg_enum_id(op->class, op->op.reg);
ut32 dest_width = 0;
ut32 dest_width = HEX_GPR_WIDTH;
switch (op->class) {
default:
rz_warn_if_reached();
Expand All @@ -544,17 +554,25 @@ RZ_IPI RZ_OWN RzILOpEffect *hex_write_reg(RZ_BORROW HexInsnPktBundle *bundle, co
case HEX_REG_CLASS_GENERAL_SUB_REGS:
low_name = hex_get_reg_in_class(HEX_REG_CLASS_INT_REGS, reg_num, false, true, true);
low_val = CAST(HEX_GPR_WIDTH, IL_FALSE, val);
dest_width = HEX_GPR_WIDTH;
break;
case HEX_REG_CLASS_CTR_REGS64:
high_name = hex_get_reg_in_class(HEX_REG_CLASS_CTR_REGS, reg_num + 1, false, true, true);
high_val = SHIFTR0(DUP(val), U8(HEX_GPR_WIDTH));
if (hex_ctr_immut_masks[reg_num + 1] != HEX_IMMUTABLE_MASK) {
high_name = hex_get_reg_in_class(HEX_REG_CLASS_CTR_REGS, reg_num + 1, false, true, true);
high_val = SHIFTR0(DUP(val), U8(HEX_GPR_WIDTH));
if (hex_ctr_immut_masks[reg_num + 1] != 0) {
high_val = get_masked_reg_val(VARG(high_name), CAST(HEX_GPR_WIDTH, IL_FALSE, high_val), hex_ctr_immut_masks[reg_num + 1]);
}
}
// fallthrough
case HEX_REG_CLASS_MOD_REGS:
case HEX_REG_CLASS_CTR_REGS:
low_name = hex_get_reg_in_class(HEX_REG_CLASS_CTR_REGS, reg_num, false, true, true);
low_val = CAST(HEX_GPR_WIDTH, IL_FALSE, val);
dest_width = HEX_GPR_WIDTH;
if (hex_ctr_immut_masks[reg_num] != HEX_IMMUTABLE_MASK) {
low_name = hex_get_reg_in_class(HEX_REG_CLASS_CTR_REGS, reg_num, false, true, true);
low_val = CAST(HEX_GPR_WIDTH, IL_FALSE, val);
if (hex_ctr_immut_masks[reg_num] != 0) {
low_val = get_masked_reg_val(VARG(low_name), low_val, hex_ctr_immut_masks[reg_num]);
}
}
break;
case HEX_REG_CLASS_PRED_REGS:
low_name = hex_get_reg_in_class(HEX_REG_CLASS_PRED_REGS, reg_num, false, true, true);
Expand All @@ -567,17 +585,18 @@ RZ_IPI RZ_OWN RzILOpEffect *hex_write_reg(RZ_BORROW HexInsnPktBundle *bundle, co
dest_width = HEX_PRED_WIDTH;
break;
}
if (!low_val || dest_width == 0) {
rz_warn_if_reached();
return NULL;
}
RzILOpEffect *write_high = high_val ? SETG(high_name, CAST(dest_width, IL_FALSE, high_val)) : NULL;
RzILOpEffect *write_low = SETG(low_name, CAST(dest_width, IL_FALSE, low_val));
RzILOpEffect *write_low = low_val ? SETG(low_name, CAST(dest_width, IL_FALSE, low_val)) : NULL;
log_reg_write(bundle, reg_num, op->class, false, true);
if (write_high) {

if (write_high && write_low) {
return SEQ2(write_low, write_high);
} else if (write_low) {
return write_low;
} else if (write_high) {
return write_high;
}
return write_low;
return EMPTY();
}

static inline bool read_cond_faulty(RzILOpPure *low_val, RzILOpPure *high_val, ut32 val_width) {
Expand Down

0 comments on commit 33a05ca

Please sign in to comment.