Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Relocation and analysis improvement for Renesas RX #4461

Merged
merged 7 commits into from
May 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions librz/arch/opcodes/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ sdb_opcodes_files = [
'ppc',
'propeller',
'riscv',
'rx',
'rl78',
XVilka marked this conversation as resolved.
Show resolved Hide resolved
'sh',
'sparc',
'sysz',
Expand Down
129 changes: 129 additions & 0 deletions librz/arch/opcodes/rx.sdb.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
abs=absolute value
add=byte data addition without carry
sub=subtract data
adc=addition of byte data with carry
and=logical and
bclr=clear a bit
bnot=inverts a bit
bset=set a bit
btst=test a bit to set C/Z flag
clrpsw=clear a flag in the PSW reg
cmp=compare two operands
div=divide signed
divu=divide unsigned
emul=extended multiply signed
emulu=extended multiply unsigned
fadd=float-point addition
fcmp=compare float-point
fdiv=divide float-point
fmul=multiply float-point
fsub=subtract float-point
ftoi=convert float-point to signed integer
itof=convert signed integer to float-point
machi=multiply-accumulate the upper words
maclo=multiply-accumulate the lower words
max=maximum of two signed integers
min=minimum of two signed integers
mov=move data
mov=move data unsigned
xchg=exchange data
mul=multiply data
mulhi=multiply the upper words
mullo=multiply the lower words
mvfachi=move data from upper longword([b32,b63]) of the accumulator(acc)
mvfacmi=move data from middle longword([b16, b47]) of the accumulator(acc)
mvtachi=move data to upper longword([b32,b63]) of the accumulator(acc)
mvtaclo=move data to lower longword([b0, b31]) of the accumulator(acc)
mvfc=move data from a control register
mvtc=move data to a control register
mvtipl=move data to IPL
neg=negate operand (2's complement)
not=logical not (1's complement)
or=logical or
xor=logical xor
nop=do nothing
pop=pop register from stack
popc=pop a control register from stack
popm=pop multiple registers from stack
push= push a register to stack
pushc=push a control register to stack
pushm=push multiple registers to stack
racw=round the accumulator into a word and stores result
revl=reverse endian within longword
revw=reverse endian within word
rmpa=repeat multiply-accumulate
rolc=rotate left with carry
rorc=rotate right with carry
rotl=rotate left
rotr=rotate right
round=round float-point to signed integer
rte=return from exception
rtfi=return from fast interrupt
rts=return from subroutine
rtsd=return from subroutine after deallocating stack frames
sat=saturate (generate 7FFFFFFFh if flag O and S are set to 1 else generate 80000000)
satr=saturate from rmpa
sbb=subtract with borrow
setpsw=set a flag or bit in PSW
shar=arithmetic shift right
shlr=logical shift right
shll=logical shift left
scmpu=string compare until not equal
smovb=string move backward
smovf=string move forward
smovu=string move until zero detected
sstr=string store
suntil=string search until equal
swhile=string search while equal
stnz=store(move) data on not zero
stz=store(move) on zero
tst=test logical (S = MSB(op1&op2) Z = !(op1&op2))
wait=pause and wait interrupt
int=software interrupt
jmp=unconditional
jsr=jump to a subroutine
bra=unconditional relative branch
brk=unconditional trap
bsr=relative branch to a subroutine
scgeu=store truth value of condition if C == 1 (unsigned <=)
sceq=store truth value of condition if Z == 1 (==)
scgtu=store truth value of condition if (C & ~Z) == 1 (unsigned <)
scpz=store truth value of condition if S == 0 ( >= 0)
scge=store truth value of condition if (S ^ O) == 0 (signed <=)
scgt=store truth value of condition if ((S ^ O) | Z) == 0 (signed <)
sco=store truth value of condition if O == 1 (overflow)
scltu=store truth value of condition if C == 0 (unsigned >)
scne=store truth value of condition if Z == 0 (!=)
scleu=store truth value of condition if (C & ~Z) == 0 (unsigned >=)
scn=store truth value of condition if S == 1 ( < 0 )
scle=store truth value of condition if ((S ^ O) | Z) == 1 (<)
sclt=store truth value of condition if (S ^ O) == 1 (>)
scno=store truth value of condition if O == 0
bgeu=conditional relative branch if C == 1 (unsigned <=)
beq=conditional relative branch if Z == 1 (==)
bgtu=conditional relative branch if (C & ~Z) == 1 (unsigned <)
bpz=conditional relative branch if S == 0 ( >= 0)
bge=conditional relative branch if (S ^ O) == 0 (signed <=)
bgt=conditional relative branch if ((S ^ O) | Z) == 0 (signed <)
bo=conditional relative branch if O == 1 (overflow)
bltu=conditional relative branch if C == 0 (unsigned >)
bne=conditional relative branch if Z == 0 (!=)
bleu=conditional relative branch if (C & ~Z) == 0 (unsigned >=)
bn=conditional relative branch if S == 1 ( < 0 )
ble=conditional relative branch if ((S ^ O) | Z) == 1 (<)
blt=conditional relative branch if (S ^ O) == 1 (>)
bno=conditional relative branch if O == 0
bmgeu=store truth value of condition to a bit if C == 1 (unsigned <=)
bmeq=store truth value of condition to a bit if Z == 1 (==)
bmgtu=store truth value of condition to a bit if (C & ~Z) == 1 (unsigned <)
bmpz=store truth value of condition to a bit if S == 0 ( >= 0)
bmge=store truth value of condition to a bit if (S ^ O) == 0 (signed <=)
bmgt=store truth value of condition to a bit if ((S ^ O) | Z) == 0 (signed <)
bmo=store truth value of condition to a bit if O == 1 (overflow)
bmltu=store truth value of condition to a bit if C == 0 (unsigned >)
bmne=store truth value of condition to a bit if Z == 0 (!=)
bmleu=store truth value of condition to a bit if (C & ~Z) == 0 (unsigned >=)
bmn=store truth value of condition to a bit if S == 1 ( < 0 )
bmle=store truth value of condition to a bit if ((S ^ O) | Z) == 1 (<)
bmlt=store truth value of condition to a bit if (S ^ O) == 1 (>)
bmno=store truth value of condition to a bit if O == 0
173 changes: 152 additions & 21 deletions librz/arch/p/analysis/analysis_rx.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,38 @@ static void calculate_jmp_addr(RxInst *inst, RzAnalysisOp *op) {
op->fail = op->addr + op->size;
}

static int rx_operand_cnt(RxInst *inst) {
int cnt = 0;
if (inst->v0.kind != RX_OPERAND_NULL) {
cnt++;
}
if (inst->v1.kind != RX_OPERAND_NULL) {
cnt++;
}
if (inst->v2.kind != RX_OPERAND_NULL) {
cnt++;
}
return cnt;
}

static inline RxOperand *rx_operand_get(RxInst *inst, int idx) {
if (idx >= rx_operand_cnt(inst)) {
RZ_LOG_WARN("Failed to get operand%d of ISA Renesas Rx\n", idx);
rz_warn_if_reached();
return NULL;
}
switch (idx) {
case 0:
return &inst->v0;
case 1:
return &inst->v1;
case 2:
return &inst->v2;
default:
return NULL;
}
}

static int analysis_rx_op(RzAnalysis *analysis, RzAnalysisOp *op, ut64 addr,
const ut8 *buf, int len, RzAnalysisOpMask mask) {
op->addr = addr;
Expand All @@ -46,12 +78,16 @@ static int analysis_rx_op(RzAnalysis *analysis, RzAnalysisOp *op, ut64 addr,
switch (inst.op) {
// jump related instructions
case RX_OP_RTS:
op->type = RZ_ANALYSIS_OP_TYPE_RET;
op->stackop = RZ_ANALYSIS_STACK_INC;
op->stackptr = 4;
break;
case RX_OP_RTSD:
// use register to deallocate stack frames
op->type = RZ_ANALYSIS_OP_TYPE_RET;
break;
case RX_OP_BSR_A:
case RX_OP_BSR_L:
case RX_OP_BSR_W:
case RX_OP_JSR:
op->type = RZ_ANALYSIS_OP_TYPE_CALL;
calculate_jmp_addr(&inst, op);
break;
Expand All @@ -61,25 +97,84 @@ static int analysis_rx_op(RzAnalysis *analysis, RzAnalysisOp *op, ut64 addr,
op->type = RZ_ANALYSIS_OP_TYPE_CJMP;
calculate_jmp_addr(&inst, op);
break;
case RX_OP_BRA_L:
case RX_OP_BRA_A:
case RX_OP_BRA_B:
case RX_OP_BRA_S:
case RX_OP_BRA_W:
op->type = RZ_ANALYSIS_OP_TYPE_JMP;
calculate_jmp_addr(&inst, op);
break;
case RX_OP_BRA_L:
case RX_OP_JMP:
// use register
op->type = RZ_ANALYSIS_OP_TYPE_JMP;
// use register to jump unconditionally
op->type = RZ_ANALYSIS_OP_TYPE_IRJMP;
break;
case RX_OP_BSR_L:
case RX_OP_JSR:
// use register to call unconditionally
op->type = RZ_ANALYSIS_OP_TYPE_IRCALL;
break;

// stack related operations
case RX_OP_PUSH:
case RX_OP_PUSHC:
op->type = RZ_ANALYSIS_OP_TYPE_PUSH;
op->stackop = RZ_ANALYSIS_STACK_DEC;
op->stackptr = 4;
break;
case RX_OP_PUSHM:
op->type = RZ_ANALYSIS_OP_TYPE_PUSH;
op->stackop = RZ_ANALYSIS_STACK_DEC;
op->stackptr = 4 * (inst.v1.v.reg.reg - inst.v0.v.reg.reg + 1);
break;
case RX_OP_POP:
case RX_OP_POPM:
op->type = RZ_ANALYSIS_OP_TYPE_POP;
op->stackop = RZ_ANALYSIS_STACK_INC;
op->stackptr = 4;
break;
case RX_OP_POPC:
op->type = RZ_ANALYSIS_OP_TYPE_POP;
op->stackop = RZ_ANALYSIS_STACK_INC;
op->stackptr = 4 * (inst.v1.v.reg.reg - inst.v0.v.reg.reg + 1);
break;

// normal instruction
case RX_OP_ADD:
case RX_OP_ADD_UB:
case RX_OP_ADC:
// add imm, rn, rm
op->type = RZ_ANALYSIS_OP_TYPE_ADD;
break;
case RX_OP_ADD:
op->type = RZ_ANALYSIS_OP_TYPE_ADD;
if (rx_operand_cnt(&inst) == 2) {
// add imm, sp
const RxOperand *op0 = rx_operand_get(&inst, 0);
if (op0->kind == RX_OPERAND_IMM) {
const RxOperand *op1 = rx_operand_get(&inst, 1);
if (op1->kind == RX_OPERAND_REG && op1->v.reg.reg == RX_REG_R0) {
// modify SP
op->stackop = RZ_ANALYSIS_STACK_INC;
op->stackptr = op0->v.imm.imm;
}
}
}
break;
case RX_OP_SUB:
op->type = RZ_ANALYSIS_OP_TYPE_SUB;
if (rx_operand_cnt(&inst) == 2) {
// sub imm, sp
const RxOperand *op0 = rx_operand_get(&inst, 0);
if (op0->kind == RX_OPERAND_IMM) {
const RxOperand *op1 = rx_operand_get(&inst, 1);
if (op1->kind == RX_OPERAND_REG && op1->v.reg.reg == RX_REG_R0) {
// modify SP
op->stackop = RZ_ANALYSIS_STACK_DEC;
op->stackptr = op0->v.imm.imm;
}
}
}
break;
case RX_OP_SUB_UB:
op->type = RZ_ANALYSIS_OP_TYPE_SUB;
break;
Expand Down Expand Up @@ -115,20 +210,13 @@ static int analysis_rx_op(RzAnalysis *analysis, RzAnalysisOp *op, ut64 addr,
case RX_OP_NOP:
op->type = RZ_ANALYSIS_OP_TYPE_NOP;
break;
case RX_OP_NEG:
op->type = RZ_ANALYSIS_OP_TYPE_CPL;
break;
case RX_OP_CMP:
case RX_OP_CMP_UB:
op->type = RZ_ANALYSIS_OP_TYPE_CMP;
break;
case RX_OP_PUSH:
case RX_OP_PUSHM:
case RX_OP_PUSHC:
op->type = RZ_ANALYSIS_OP_TYPE_PUSH;
break;
case RX_OP_POP:
case RX_OP_POPM:
case RX_OP_POPC:
op->type = RZ_ANALYSIS_OP_TYPE_POP;
break;
case RX_OP_ROTL:
case RX_OP_ROLC:
op->type = RZ_ANALYSIS_OP_TYPE_ROL;
Expand All @@ -154,15 +242,26 @@ static int analysis_rx_op(RzAnalysis *analysis, RzAnalysisOp *op, ut64 addr,
case RX_OP_XOR_UB:
op->type = RZ_ANALYSIS_OP_TYPE_XOR;
break;
case RX_OP_ITOF:
case RX_OP_FTOI:
case RX_OP_ITOF_UB:
op->type = RZ_ANALYSIS_OP_TYPE_CAST;
break;
case RX_OP_INT:
case RX_OP_RTE:
case RX_OP_RTFI:
op->type = RZ_ANALYSIS_OP_TYPE_SWI;
break;
case RX_OP_MOV:
op->type = RZ_ANALYSIS_OP_TYPE_MOV;
if (rx_operand_cnt(&inst) == 2) {
// mov sp, rn
const RxOperand *op0 = rx_operand_get(&inst, 0);
const RxOperand *op1 = rx_operand_get(&inst, 1);
if (op0->kind == RX_OPERAND_IMM) {
if (op1->kind == RX_OPERAND_REG && op1->v.reg.reg == RX_REG_R0) {
// modify SP
op->stackop = RZ_ANALYSIS_STACK_SET;
op->stackptr = op0->v.imm.imm;
}
}
}
break;
case RX_OP_MOVU:
case RX_OP_MVTIPL:
case RX_OP_MVTC:
Expand All @@ -173,7 +272,39 @@ static int analysis_rx_op(RzAnalysis *analysis, RzAnalysisOp *op, ut64 addr,
case RX_OP_MVFC:
op->type = RZ_ANALYSIS_OP_TYPE_MOV;
break;
case RX_OP_ABS:
op->type = RZ_ANALYSIS_OP_TYPE_ABS;
break;

// FPU
case RX_OP_FADD:
op->type = RZ_ANALYSIS_OP_TYPE_ADD;
op->family = RZ_ANALYSIS_OP_FAMILY_FPU;
break;
case RX_OP_FSUB:
op->type = RZ_ANALYSIS_OP_TYPE_SUB;
op->family = RZ_ANALYSIS_OP_FAMILY_FPU;
break;
case RX_OP_FMUL:
op->type = RZ_ANALYSIS_OP_TYPE_MUL;
op->family = RZ_ANALYSIS_OP_FAMILY_FPU;
break;
case RX_OP_FDIV:
op->type = RZ_ANALYSIS_OP_TYPE_DIV;
op->family = RZ_ANALYSIS_OP_FAMILY_FPU;
break;
case RX_OP_FCMP:
op->type = RZ_ANALYSIS_OP_TYPE_CMP;
op->family = RZ_ANALYSIS_OP_FAMILY_FPU;
break;
case RX_OP_ITOF:
case RX_OP_FTOI:
case RX_OP_ITOF_UB:
op->type = RZ_ANALYSIS_OP_TYPE_CAST;
op->family = RZ_ANALYSIS_OP_FAMILY_FPU;
break;
default:
op->type = RZ_ANALYSIS_OP_TYPE_UNK;
break;
}

Expand Down
Loading
Loading