Skip to content

Commit

Permalink
Optimize branches and common ops when interacting with $zero
Browse files Browse the repository at this point in the history
  • Loading branch information
wargio committed Feb 17, 2025
1 parent 38a9649 commit c223f9f
Show file tree
Hide file tree
Showing 3 changed files with 78 additions and 17 deletions.
67 changes: 64 additions & 3 deletions librz/arch/isa/mips/il/common.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@
#define BITN(x, n) SHIFTR0(LOGAND(x, UN(gprlen, (ut64)1 << (n - 1))), UN(gprlen, n - 1))
#define CHECK_OVERFLOW(r, sz) EQ(BITN(r, sz), BITN(r, sz - 1))
#define MIPS_REG(idx) mips_get_reg(handle, insn, idx, gprlen)
#define MIPS_IMM(idx) UN(gprlen, IMM(idx));
#define MIPS_ZERO() UN(gprlen, 0);
#define MIPS_IMM(idx) UN(gprlen, IMM(idx))
#define MIPS_ZERO() UN(gprlen, 0)
#define MIPS_LINK() SETG(MIPS_REG_RA, UN(gprlen, insn->address + 8)) // link register $ra

// This macro checks for any writes to the $zero
Expand Down Expand Up @@ -141,9 +141,13 @@ static RzILOpEffect *mips_il_bal(const csh *handle, const cs_insn *insn, const u
}

static RzILOpEffect *mips_il_beqz(const csh *handle, const cs_insn *insn, const ut32 gprlen) {
RzILOpPure *rs = MIPS_REG(0);
RzILOpPure *target = MIPS_IMM(1);
if (IS_ZERO_REG(0)) {
// always taken
return JMP(target);
}

RzILOpPure *rs = MIPS_REG(0);
return BRANCH(IS_ZERO(rs), JMP(target), NOP());
}

Expand Down Expand Up @@ -187,6 +191,11 @@ static RzILOpEffect *mips_il_bgezal(const csh *handle, const cs_insn *insn, cons
}

static RzILOpEffect *mips_il_bgtz(const csh *handle, const cs_insn *insn, const ut32 gprlen) {
if (IS_ZERO_REG(0)) {
// never taken
return NOP();
}

RzILOpPure *rs = MIPS_REG(0);
RzILOpPure *zero = MIPS_ZERO();
RzILOpPure *target = MIPS_IMM(1);
Expand All @@ -207,6 +216,11 @@ static RzILOpEffect *mips_il_blez(const csh *handle, const cs_insn *insn, const
}

static RzILOpEffect *mips_il_bltz(const csh *handle, const cs_insn *insn, const ut32 gprlen) {
if (IS_ZERO_REG(0)) {
// never taken
return NOP();
}

RzILOpPure *rs = MIPS_REG(0);
RzILOpPure *zero = MIPS_ZERO();
RzILOpPure *target = MIPS_IMM(1);
Expand All @@ -228,6 +242,11 @@ static RzILOpEffect *mips_il_bltzal(const csh *handle, const cs_insn *insn, cons
}

static RzILOpEffect *mips_il_bnez(const csh *handle, const cs_insn *insn, const ut32 gprlen) {
if (IS_ZERO_REG(0)) {
// never taken
return NOP();
}

RzILOpPure *rs = MIPS_REG(0);
RzILOpPure *target = MIPS_IMM(1);

Expand Down Expand Up @@ -522,6 +541,11 @@ static RzILOpEffect *mips_il_movn(const csh *handle, const cs_insn *insn, const
MIPS_CHECK_IF_TARGET_IS_ZERO_REG_AND_NOP();

// Move Conditional on Not Zero
if (IS_ZERO_REG(2)) {
// rt is zero, thus always false
return NOP();
}

const char *rd = REG(0);
RzILOpPure *rs = MIPS_REG(1);
RzILOpPure *rt = MIPS_REG(2);
Expand All @@ -532,6 +556,12 @@ static RzILOpEffect *mips_il_movz(const csh *handle, const cs_insn *insn, const
// Move Conditional on Zero
const char *rd = REG(0);
RzILOpPure *rs = MIPS_REG(1);

if (IS_ZERO_REG(2)) {
// rt is zero, thus always true
return SETG(rd, rs);
}

RzILOpPure *rt = MIPS_REG(2);
return BRANCH(IS_ZERO(rt), SETG(rd, rs), NOP());
}
Expand Down Expand Up @@ -604,13 +634,25 @@ static RzILOpEffect *mips_il_mul(const csh *handle, const cs_insn *insn, const u
MIPS_CHECK_IF_TARGET_IS_ZERO_REG_AND_NOP();

const char *rd = REG(0);
if (IS_ZERO_REG(1) || IS_ZERO_REG(2)) {
// multiply by zero always returns zero.
SETG(rd, MIPS_ZERO());
}

RzILOpPure *rs = MIPS_REG(1);
RzILOpPure *rt = MIPS_REG(2);

return SETG(rd, MUL(rs, rt));
}

static RzILOpEffect *mips_il_mult(const csh *handle, const cs_insn *insn, const ut32 gprlen) {
if (IS_ZERO_REG(0) || IS_ZERO_REG(1)) {
// multiply by zero always returns zero.
RzILOpEffect *set_hi = SETG(MIPS_REG_HI, MIPS_ZERO());
RzILOpEffect *set_lo = SETG(MIPS_REG_LO, MIPS_ZERO());
return SEQ2(set_hi, set_lo);
}

RzILOpPure *rs = MIPS_REG(0);
RzILOpPure *rt = MIPS_REG(1);

Expand All @@ -633,6 +675,13 @@ static RzILOpEffect *mips_il_mult(const csh *handle, const cs_insn *insn, const
}

static RzILOpEffect *mips_il_multu(const csh *handle, const cs_insn *insn, const ut32 gprlen) {
if (IS_ZERO_REG(0) || IS_ZERO_REG(1)) {
// multiply by zero always returns zero.
RzILOpEffect *set_hi = SETG(MIPS_REG_HI, MIPS_ZERO());
RzILOpEffect *set_lo = SETG(MIPS_REG_LO, MIPS_ZERO());
return SEQ2(set_hi, set_lo);
}

RzILOpPure *rs = MIPS_REG(0);
RzILOpPure *rt = MIPS_REG(1);

Expand Down Expand Up @@ -765,12 +814,16 @@ static RzILOpEffect *mips_il_sd(const csh *handle, const cs_insn *insn, const ut

static RzILOpEffect *mips_il_seb(const csh *handle, const cs_insn *insn, const ut32 gprlen) {
// Sign-Extend Byte
MIPS_CHECK_IF_TARGET_IS_ZERO_REG_AND_NOP();

RzILOpPure *rt = MIPS_REG(1);
return SETG(REG(0), SIGNED(gprlen, UNSIGNED(MIPS_BYTE_SIZE, rt)));
}

static RzILOpEffect *mips_il_seh(const csh *handle, const cs_insn *insn, const ut32 gprlen) {
// Sign-Extend Halfword
MIPS_CHECK_IF_TARGET_IS_ZERO_REG_AND_NOP();

RzILOpPure *rt = MIPS_REG(1);
return SETG(REG(0), SIGNED(gprlen, UNSIGNED(MIPS_HALF_SIZE, rt)));
}
Expand Down Expand Up @@ -815,6 +868,8 @@ static RzILOpEffect *mips_il_sllv(const csh *handle, const cs_insn *insn, const
}

static RzILOpEffect *mips_il_slt(const csh *handle, const cs_insn *insn, const ut32 gprlen) {
MIPS_CHECK_IF_TARGET_IS_ZERO_REG_AND_NOP();

const char *rd = REG(0);
RzILOpPure *rs = MIPS_REG(1);
RzILOpPure *rt = MIPS_REG(1);
Expand All @@ -824,6 +879,8 @@ static RzILOpEffect *mips_il_slt(const csh *handle, const cs_insn *insn, const u
}

static RzILOpEffect *mips_il_slti(const csh *handle, const cs_insn *insn, const ut32 gprlen) {
MIPS_CHECK_IF_TARGET_IS_ZERO_REG_AND_NOP();

const char *rd = REG(0);
RzILOpPure *rs = MIPS_REG(1);
RzILOpPure *imm = MIPS_IMM(2);
Expand All @@ -833,6 +890,8 @@ static RzILOpEffect *mips_il_slti(const csh *handle, const cs_insn *insn, const
}

static RzILOpEffect *mips_il_sltiu(const csh *handle, const cs_insn *insn, const ut32 gprlen) {
MIPS_CHECK_IF_TARGET_IS_ZERO_REG_AND_NOP();

const char *rd = REG(0);
RzILOpPure *rs = MIPS_REG(1);
RzILOpPure *imm = MIPS_IMM(2);
Expand All @@ -842,6 +901,8 @@ static RzILOpEffect *mips_il_sltiu(const csh *handle, const cs_insn *insn, const
}

static RzILOpEffect *mips_il_sltu(const csh *handle, const cs_insn *insn, const ut32 gprlen) {
MIPS_CHECK_IF_TARGET_IS_ZERO_REG_AND_NOP();

const char *rd = REG(0);
RzILOpPure *rs = MIPS_REG(1);
RzILOpPure *rt = MIPS_REG(2);
Expand Down
14 changes: 7 additions & 7 deletions test/db/asm/mips_mips64v2_64
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,15 @@ d "bgez v0, 0x10" 02004104 0x4 (branch (|| (! (sle (var v0) (bv 64 0x0))) (== (v
d "bgezal s1, 0x108" 40003106 0x4 (branch (|| (! (sle (var s1) (bv 64 0x0))) (== (var s1) (bv 64 0x0))) (seq (set ra (bv 64 0xc)) (jmp (bv 64 0x108))) nop)
d "bgezall t3, 0x128" 48007305 0x4 (branch (|| (! (sle (var t3) (bv 64 0x0))) (== (var t3) (bv 64 0x0))) (seq (set ra (bv 64 0xc)) (jmp (bv 64 0x128))) nop)
d "bgezl t6, 0x128" 4800c305 0x4 (branch (|| (! (sle (var t6) (bv 64 0x0))) (== (var t6) (bv 64 0x0))) (jmp (bv 64 0x128)) nop)
d "bgtz zero, 8" 0000001c 0x4 (branch (! (sle (bv 64 0x0) (bv 64 0x0))) (jmp (bv 64 0x8)) nop)
d "bgtzl zero, 8" 0000005c 0x4 (branch (! (sle (bv 64 0x0) (bv 64 0x0))) (jmp (bv 64 0x8)) nop)
d "bgtz zero, 8" 0000001c 0x4 nop
d "bgtzl zero, 8" 0000005c 0x4 nop
d "blez zero, 8" 00000018 0x4 (jmp (bv 64 0x1a))
d "blezl zero, 8" 00000058 0x4 (jmp (bv 64 0x1a))
d "bltz zero, 8" 00000004 0x4 (branch (&& (sle (bv 64 0x0) (bv 64 0x0)) (! (== (bv 64 0x0) (bv 64 0x0)))) (jmp (bv 64 0x8)) nop)
d "bltz zero, 8" 00000004 0x4 nop
d "bltzl s6, 0x118" 4400c206 0x4 (branch (&& (sle (var s6) (bv 64 0x0)) (! (== (var s6) (bv 64 0x0)))) (jmp (bv 64 0x118)) nop)
d "bne t0, s0, 0x440c" 01111015 0x4 (branch (! (== (var t0) (var s0))) (jmp (bv 64 0x440c)) nop)
d "bnel s0, s0, -0xbff8" 00d01056 0x4 (branch (! (== (var s0) (var s0))) (jmp (bv 64 0xffffffffffff4008)) nop)
d "bnez zero, 8" 00000014 0x4 (branch (! (is_zero (bv 64 0x0))) (jmp (bv 64 0x8)) nop)
d "bnez zero, 8" 00000014 0x4 nop
d "cache 0, 0(zero)" 000000bc 0x4 nop
d "daddi zero, zero, 0" 00000060 0x4 nop
d "daddiu zero, zero, 0" 00000064 0x4 nop
Expand Down Expand Up @@ -60,14 +60,14 @@ d "sdc1 f0, 0(zero)" 000000f4 0x4
d "sdl zero, 0(zero)" 000000b0 0x4
d "sdr zero, 0(zero)" 000000b4 0x4
d "sh zero, 0(zero)" 000000a4 0x4 (storew 0 (+ (var zero) (bv 64 0x0)) (bv 16 0x0))
d "slti zero, zero, 0" 00000028 0x4 (set zero (ite (&& (sle (bv 64 0x0) (bv 64 0x0)) (! (== (bv 64 0x0) (bv 64 0x0)))) (bv 64 0x1) (bv 64 0x0)))
d "sltiu zero, zero, 0" 0000002c 0x4 (set zero (ite (&& (ule (bv 64 0x0) (bv 64 0x0)) (! (== (bv 64 0x0) (bv 64 0x0)))) (bv 64 0x1) (bv 64 0x0)))
d "slti zero, zero, 0" 00000028 0x4 nop
d "sltiu zero, zero, 0" 0000002c 0x4 nop
d "sw zero, 0(zero)" 000000ac 0x4 (storew 0 (+ (var zero) (bv 64 0x0)) (bv 32 0x0))
d "swc1 f0, 0(zero)" 000000e4 0x4
d "swl zero, 0(zero)" 000000a8 0x4
d "swr zero, 0(zero)" 000000b8 0x4
d "xori zero, zero, 0" 00000038 0x4 nop
d "beqzl zero, 8" 00000050 0x4 (branch (is_zero (bv 64 0x0)) (jmp (bv 64 0x8)) nop)
d "beqzl zero, 8" 00000050 0x4 (jmp (bv 64 0x8))
d "bnezl t0, 8" 00000055 0x4 (branch (! (is_zero (var t0))) (jmp (bv 64 0x8)) nop)
dB "c0 0x0" 00000042 0x4
dB "c1 0x1000000" 00000047 0x4
Expand Down
14 changes: 7 additions & 7 deletions test/db/asm/mips_mips64v6_64
Original file line number Diff line number Diff line change
Expand Up @@ -11,20 +11,20 @@ d "lwxc1 f0, zero(t0)" 0000004d 0x4
d "beq t0, s0, 0x444c" 11111011 0x4 (branch (== (var t0) (var s0)) (jmp (bv 64 0x444c)) nop)
d "beql sp, t8, 0x14008" 0050b853 0x4 (branch (== (var sp) (var t8)) (jmp (bv 64 0x14008)) nop)
d "beqz t0, 8" 00000011 0x4 (branch (is_zero (var t0)) (jmp (bv 64 0x8)) nop)
d "beqzl zero, 8" 00000050 0x4 (branch (is_zero (bv 64 0x0)) (jmp (bv 64 0x8)) nop)
d "beqzl zero, 8" 00000050 0x4 (jmp (bv 64 0x8))
d "bgez v0, 0x10" 02004104 0x4 (branch (|| (! (sle (var v0) (bv 64 0x0))) (== (var v0) (bv 64 0x0))) (jmp (bv 64 0x10)) nop)
d "bgezal s1, 0x108" 40003106 0x4 (branch (|| (! (sle (var s1) (bv 64 0x0))) (== (var s1) (bv 64 0x0))) (seq (set ra (bv 64 0xc)) (jmp (bv 64 0x108))) nop)
d "bgezall t3, 0x128" 48007305 0x4 (branch (|| (! (sle (var t3) (bv 64 0x0))) (== (var t3) (bv 64 0x0))) (seq (set ra (bv 64 0xc)) (jmp (bv 64 0x128))) nop)
d "bgezl t6, 0x128" 4800c305 0x4 (branch (|| (! (sle (var t6) (bv 64 0x0))) (== (var t6) (bv 64 0x0))) (jmp (bv 64 0x128)) nop)
d "bgtz zero, 8" 0000001c 0x4 (branch (! (sle (bv 64 0x0) (bv 64 0x0))) (jmp (bv 64 0x8)) nop)
d "bgtzl zero, 8" 0000005c 0x4 (branch (! (sle (bv 64 0x0) (bv 64 0x0))) (jmp (bv 64 0x8)) nop)
d "bgtz zero, 8" 0000001c 0x4 nop
d "bgtzl zero, 8" 0000005c 0x4 nop
d "blez zero, 8" 00000018 0x4 (jmp (bv 64 0x1a))
d "blezl zero, 8" 00000058 0x4 (jmp (bv 64 0x1a))
d "bltz zero, 8" 00000004 0x4 (branch (&& (sle (bv 64 0x0) (bv 64 0x0)) (! (== (bv 64 0x0) (bv 64 0x0)))) (jmp (bv 64 0x8)) nop)
d "bltz zero, 8" 00000004 0x4 nop
d "bltzl s6, 0x118" 4400c206 0x4 (branch (&& (sle (var s6) (bv 64 0x0)) (! (== (var s6) (bv 64 0x0)))) (jmp (bv 64 0x118)) nop)
d "bne t0, s0, 0x440c" 01111015 0x4 (branch (! (== (var t0) (var s0))) (jmp (bv 64 0x440c)) nop)
d "bnel s0, s0, -0xbff8" 00d01056 0x4 (branch (! (== (var s0) (var s0))) (jmp (bv 64 0xffffffffffff4008)) nop)
d "bnez zero, 8" 00000014 0x4 (branch (! (is_zero (bv 64 0x0))) (jmp (bv 64 0x8)) nop)
d "bnez zero, 8" 00000014 0x4 nop
d "bnezl t0, 8" 00000055 0x4 (branch (! (is_zero (var t0))) (jmp (bv 64 0x8)) nop)
dB "c0 0" 00000042 0x4
dB "c1 0x1000000" 00000047 0x4
Expand Down Expand Up @@ -73,8 +73,8 @@ d "sdc2 0, 0(zero)" 000000f8 0x4
d "sdl zero, 0(zero)" 000000b0 0x4
d "sdr zero, 0(zero)" 000000b4 0x4
d "sh zero, 0(zero)" 000000a4 0x4 (storew 0 (+ (var zero) (bv 64 0x0)) (bv 16 0x0))
d "slti zero, zero, 0" 00000028 0x4 (set zero (ite (&& (sle (bv 64 0x0) (bv 64 0x0)) (! (== (bv 64 0x0) (bv 64 0x0)))) (bv 64 0x1) (bv 64 0x0)))
d "sltiu zero, zero, 0" 0000002c 0x4 (set zero (ite (&& (ule (bv 64 0x0) (bv 64 0x0)) (! (== (bv 64 0x0) (bv 64 0x0)))) (bv 64 0x1) (bv 64 0x0)))
d "slti zero, zero, 0" 00000028 0x4 nop
d "sltiu zero, zero, 0" 0000002c 0x4 nop
d "sw zero, 0(zero)" 000000ac 0x4 (storew 0 (+ (var zero) (bv 64 0x0)) (bv 32 0x0))
d "swl zero, 0(zero)" 000000a8 0x4
d "swr zero, 0(zero)" 000000b8 0x4
Expand Down

0 comments on commit c223f9f

Please sign in to comment.