static inline bool isCall(uint32_t insn) { return ( (insn & MIPS_OPCODE_MASK) == MIPS_OPClass_Special && (insn & MIPS_OPClass_Special_MASK) == MIPS_OP_JALR && MIPS_OPND_REG_D(insn) == MIPS_REG_RA ); }
static inline bool isAfterCall(void* addr) { uint32_t* ra = (uint32_t*)addr; uint32_t insn = *(ra - 1/*delay slot*/ - 1/*potential call*/); // jalr rs [rd = 31 [RA] is implied] uint32_t op_spc = (insn & MIPS_OPClass_Special_MASK); return (op_spc == MIPS_OP_JALR && (MIPS_OPND_REG_D(insn) == MIPS_REG_RA)); }
static inline bool isMoveReg(uint32_t insn, int reg_dst, int reg_src) { // move rd, rs ==> addu rd, rs, rt=R0 uint32_t op = (insn & MIPS_OPCODE_MASK); uint32_t op_spc = (insn & MIPS_OPClass_Special_MASK); if (op == MIPS_OPClass_Special && (op_spc == MIPS_OP_DADDU || op_spc == MIPS_OP_ADDU || op_spc == MIPS_OP_OR || op_spc == MIPS_OP_DADD || op_spc == MIPS_OP_ADD)) { // The non-'U' probably never occur since they trap on overflow. return ((MIPS_OPND_REG_D(insn) == reg_dst) && (MIPS_OPND_REG_S(insn) == reg_src) && (MIPS_OPND_REG_T(insn) == MIPS_REG_0)); } return false; }
static inline bool isAdjustSPByVar(uint32_t insn) { // example: dsubu sp,sp,v0 // example: daddu sp,sp,v0 (where v0 is negative) uint32_t op = (insn & MIPS_OPCODE_MASK); uint32_t op_spc = (insn & MIPS_OPClass_Special_MASK); if (op == MIPS_OPClass_Special && ( op_spc == MIPS_OP_DSUBU || op_spc == MIPS_OP_SUBU || op_spc == MIPS_OP_DSUB || op_spc == MIPS_OP_SUB || op_spc == MIPS_OP_DADDU || op_spc == MIPS_OP_ADDU || op_spc == MIPS_OP_DADD || op_spc == MIPS_OP_ADD ) ) { // The non-'U' probably never occur since they trap on overflow. return ((MIPS_OPND_REG_D(insn) == MIPS_REG_SP) && (MIPS_OPND_REG_S(insn) == MIPS_REG_SP)); } return false; }