arch/tms320: drop c55x+ global state, populate op->val, lift rptadd/rptsub (#6525)
Co-authored-by: Anton Kochkov <anton.kochkov@gmail.com>
This commit is contained in:
parent
36433ae7a1
commit
f205e231ef
8 changed files with 76 additions and 2302 deletions
|
|
@ -715,6 +715,21 @@ void c55_fill_analysis(const C55ArchDesc *a, const C55Insn *insn, RzAnalysisOp *
|
|||
default:
|
||||
break;
|
||||
}
|
||||
// Generic immediate-value exposure: record the first *data* immediate (one
|
||||
// that is not a branch/call target) on op->val so callers that look for the
|
||||
// constant involved in an operation (add/sub/and/or/xor/cmp/mov #k, ...)
|
||||
// can find it. A more specific case above (the swi vector, the frame
|
||||
// adjustment) may already have set op->val, in which case it is kept.
|
||||
// (op->val defaults to UT64_MAX -- the "unset" sentinel -- not 0.)
|
||||
if (op->val == UT64_MAX) {
|
||||
for (ut8 i = 0; i < insn->n_ops; i++) {
|
||||
const C55Operand *o = &insn->ops[i];
|
||||
if (o->kind == C55_OP_IMM && !o->addr && !o->reltarget) {
|
||||
op->val = o->imm;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Build the IL predicate for a register-compare branch condition (reg <relop>
|
||||
|
|
@ -1948,6 +1963,46 @@ RzILOpEffect *c55_lift(const C55ArchDesc *a, const C55Insn *insn, ut64 pc) {
|
|||
}
|
||||
return SETG(di->il_var, SUB(VARG(di->il_var), sv));
|
||||
}
|
||||
if (insn->lop == C55_LOP_RPTADD || insn->lop == C55_LOP_RPTSUB) {
|
||||
// rptadd/rptsub CSR, src: CSR = CSR +/- src. Unlike the A-unit
|
||||
// arithmetic above, the destination (CSR) is the FIRST operand and the
|
||||
// addend the second. The repeat behaviour these instructions also set
|
||||
// up (the following instruction executing CSR+1 times) is a hardware
|
||||
// loop that cannot be expressed one instruction at a time, but the
|
||||
// named CSR register write is a real architectural effect and is lifted.
|
||||
if (insn->n_ops < 2 || !a->reg_info) {
|
||||
return NULL;
|
||||
}
|
||||
const C55Operand *dst = &insn->ops[0];
|
||||
const C55Operand *src = &insn->ops[1];
|
||||
if (dst->kind != C55_OP_REG) {
|
||||
return NULL;
|
||||
}
|
||||
const C55RegInfo *di = a->reg_info(dst->reg.cls, dst->reg.num, C55_SUB_NONE);
|
||||
if (!di || !di->il_var) {
|
||||
return NULL;
|
||||
}
|
||||
RzILOpPure *sv;
|
||||
if (src->kind == C55_OP_IMM) {
|
||||
if (di->width < 64 && ((ut64)src->imm >> di->width)) {
|
||||
return NULL;
|
||||
}
|
||||
sv = UN(di->width, (ut64)src->imm);
|
||||
} else if (src->kind == C55_OP_REG) {
|
||||
const C55RegInfo *si = a->reg_info(src->reg.cls, src->reg.num, C55_SUB_NONE);
|
||||
if (!si || !si->il_var) {
|
||||
return NULL;
|
||||
}
|
||||
sv = VARG(si->il_var);
|
||||
if (si->width != di->width) {
|
||||
sv = UNSIGNED(di->width, sv);
|
||||
}
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
return SETG(di->il_var,
|
||||
insn->lop == C55_LOP_RPTADD ? ADD(VARG(di->il_var), sv) : SUB(VARG(di->il_var), sv));
|
||||
}
|
||||
// cmp / cmpand / cmpor SRC <relop> DST, [TCx,] TCz (opcode 0x12): compare two
|
||||
// registers and write the TCz status bit. cmpand/cmpor first AND/OR the
|
||||
// comparison with the input TCx bit. ops[0] is the compare COND; for cmp
|
||||
|
|
|
|||
|
|
@ -262,6 +262,8 @@ typedef enum {
|
|||
C55_LOP_ANDK, ///< dst = ACx & zero-extend(#k16): immediate and (opcode 0x7d)
|
||||
C55_LOP_ORK, ///< dst = ACx | zero-extend(#k16): immediate or (opcode 0x7e)
|
||||
C55_LOP_XORK, ///< dst = ACx ^ zero-extend(#k16): immediate xor (opcode 0x7f)
|
||||
C55_LOP_RPTADD, ///< CSR = CSR + src: single-repeat-counter add (rptadd CSR, src). The repeat loop itself (the next instruction running CSR+1 times) is a control-flow effect that one-instruction RzIL cannot express; only the named CSR write is modelled.
|
||||
C55_LOP_RPTSUB, ///< CSR = CSR - src: single-repeat-counter subtract (rptsub CSR, src). As with RPTADD, only the CSR write is modelled, not the repeat loop.
|
||||
} C55LiftOp;
|
||||
|
||||
/** A fully decoded instruction: the single hand-off from decode to the consumers. */
|
||||
|
|
|
|||
|
|
@ -1844,9 +1844,9 @@ static const C55InsnDef c55x_table[] = {
|
|||
// nibble 4/5 are decoded elsewhere. The operand register/immediate is byte1
|
||||
// bits 4-7.
|
||||
{ .mask = 0xfe0f0000, .match = 0x48000000, .id = TMS320C55_INS_RPT, .lop = C55_LOP_NOP, .len = 2, .ops = { { .fn = c55x_x_csr } } },
|
||||
{ .mask = 0xfe0f0000, .match = 0x48010000, .id = TMS320C55_INS_RPTADD, .lop = C55_LOP_NOP, .len = 2, .ops = { { .fn = c55x_x_csr }, { .lo = 4, .fn = c55x_x_gr4 } } },
|
||||
{ .mask = 0xfe0f0000, .match = 0x48020000, .id = TMS320C55_INS_RPTADD, .lop = C55_LOP_NOP, .len = 2, .ops = { { .fn = c55x_x_csr }, { .lo = 4, .width = 4, .fn = c55_x_imm } } },
|
||||
{ .mask = 0xfe0f0000, .match = 0x48030000, .id = TMS320C55_INS_RPTSUB, .lop = C55_LOP_NOP, .len = 2, .ops = { { .fn = c55x_x_csr }, { .lo = 4, .width = 4, .fn = c55_x_imm } } },
|
||||
{ .mask = 0xfe0f0000, .match = 0x48010000, .id = TMS320C55_INS_RPTADD, .lop = C55_LOP_RPTADD, .len = 2, .ops = { { .fn = c55x_x_csr }, { .lo = 4, .fn = c55x_x_gr4 } } },
|
||||
{ .mask = 0xfe0f0000, .match = 0x48020000, .id = TMS320C55_INS_RPTADD, .lop = C55_LOP_RPTADD, .len = 2, .ops = { { .fn = c55x_x_csr }, { .lo = 4, .width = 4, .fn = c55_x_imm } } },
|
||||
{ .mask = 0xfe0f0000, .match = 0x48030000, .id = TMS320C55_INS_RPTSUB, .lop = C55_LOP_RPTSUB, .len = 2, .ops = { { .fn = c55x_x_csr }, { .lo = 4, .width = 4, .fn = c55_x_imm } } },
|
||||
// rpt #k16 (opcode 0x0c, 0x0d parallel): repeat the next instruction by a
|
||||
// 16-bit immediate count (byte1 the high byte, byte2 the low byte). It has no
|
||||
// data effect of its own, so it lifts to nop like the other repeat forms.
|
||||
|
|
|
|||
|
|
@ -3436,9 +3436,9 @@ static const C55InsnDef c55plus_table[] = {
|
|||
{ .mask = 0xff808000, .match = 0xa9008000, .id = TMS320C55_INS_MANT, .lop = C55_LOP_OPAQUE, .len = 4, .mant_nexp = true, .ops = { { .fn = c55plus_x_mant_aca }, { .fn = c55plus_x_mant_acb }, { .fn = c55plus_x_mant_acc } } },
|
||||
// rpt csr / rptadd csr, #k|reg / rptsub csr, #k (opcode 0x01, 2 bytes).
|
||||
// byte1[7:6]: 00 rptsub #k, 01 rptadd #k, 10 rptadd reg, 11 rpt. All nop-lift.
|
||||
{ .mask = 0xffc00000, .match = 0x01000000, .id = TMS320C55_INS_RPTSUB, .lop = C55_LOP_NOP, .len = 2, .ops = { { .fn = c55plus_x_01_csr }, { .fn = c55plus_x_01_k4 } } },
|
||||
{ .mask = 0xffc00000, .match = 0x01400000, .id = TMS320C55_INS_RPTADD, .lop = C55_LOP_NOP, .len = 2, .ops = { { .fn = c55plus_x_01_csr }, { .fn = c55plus_x_01_k4 } } },
|
||||
{ .mask = 0xffc00000, .match = 0x01800000, .id = TMS320C55_INS_RPTADD, .lop = C55_LOP_NOP, .len = 2, .ops = { { .fn = c55plus_x_01_csr }, { .fn = c55plus_x_01_reg } } },
|
||||
{ .mask = 0xffc00000, .match = 0x01000000, .id = TMS320C55_INS_RPTSUB, .lop = C55_LOP_RPTSUB, .len = 2, .ops = { { .fn = c55plus_x_01_csr }, { .fn = c55plus_x_01_k4 } } },
|
||||
{ .mask = 0xffc00000, .match = 0x01400000, .id = TMS320C55_INS_RPTADD, .lop = C55_LOP_RPTADD, .len = 2, .ops = { { .fn = c55plus_x_01_csr }, { .fn = c55plus_x_01_k4 } } },
|
||||
{ .mask = 0xffc00000, .match = 0x01800000, .id = TMS320C55_INS_RPTADD, .lop = C55_LOP_RPTADD, .len = 2, .ops = { { .fn = c55plus_x_01_csr }, { .fn = c55plus_x_01_reg } } },
|
||||
{ .mask = 0xffc00000, .match = 0x01c00000, .id = TMS320C55_INS_RPT, .lop = C55_LOP_NOP, .len = 2, .ops = { { .fn = c55plus_x_01_csr } } },
|
||||
// rol / ror carry, ACx, carry, ACy (opcode 0xa8, 4 bytes). byte2[7] selects
|
||||
// rol (0) / ror (1); byte3[0] the carry-in flag and byte3[1] the carry-out
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -10,7 +10,4 @@
|
|||
// instruction length
|
||||
ut32 get_ins_len(ut8 opcode);
|
||||
|
||||
// gets instruction bytes from a position
|
||||
ut32 get_ins_part(ut32 pos, ut32 len);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -400,9 +400,9 @@ d "btstset #0x1d, dbl(*ar1(t1<<#1)), tc2" 91316f3d
|
|||
d "callcc #0x008cce," 9b8cceef
|
||||
d "circ" 27
|
||||
d "rpt csr" 01dd 0x0 nop
|
||||
d "rptadd csr, #0x7" 0177 0x0 nop
|
||||
d "rptsub csr, #0x6" 0106 0x0 nop
|
||||
d "rptadd csr, ar0" 0180 0x0 nop
|
||||
d "rptadd csr, #0x7" 0177 0x0 (set csr (+ (var csr) (bv 16 0x7)))
|
||||
d "rptsub csr, #0x6" 0106 0x0 (set csr (- (var csr) (bv 16 0x6)))
|
||||
d "rptadd csr, ar0" 0180 0x0 (set csr (+ (var csr) (var ar0)))
|
||||
d "cmpand ac29.h < ac25, !tc1, tc2" a4dd1989 0x0 (set st0_55 (ite (&& (&& (sle (cast 40 (msb (cast 16 false (>> (var ac29) (bv 8 0x10) false))) (cast 16 false (>> (var ac29) (bv 8 0x10) false))) (var ac25)) (! (== (cast 40 (msb (cast 16 false (>> (var ac29) (bv 8 0x10) false))) (cast 16 false (>> (var ac29) (bv 8 0x10) false))) (var ac25)))) (! (! (is_zero (& (var st0_55) (bv 16 0x2000)))))) (| (var st0_55) (bv 16 0x1000)) (& (var st0_55) (bv 16 0xefff))))
|
||||
d "cmporu ac13.l >= t0, !tc2, tc2" a4edb0af 0x0 (set st0_55 (ite (|| (! (&& (ule (cast 16 false (var ac13)) (var t0)) (! (== (cast 16 false (var ac13)) (var t0))))) (! (! (is_zero (& (var st0_55) (bv 16 0x1000)))))) (| (var st0_55) (bv 16 0x1000)) (& (var st0_55) (bv 16 0xefff))))
|
||||
d "delay @#0x1b" 601bf4
|
||||
|
|
@ -453,10 +453,10 @@ d "sat ac19, ac2" 79c2d3 0x0 (set ac2 (ite (! (sle (var ac19) (bv 40 0x7fffffff)
|
|||
d "rpt csr" 01dd 0x0 nop
|
||||
d "rpt #0x3" 6c0003 0x0 nop
|
||||
d "rpt #0xffff" 6cffff 0x0 nop
|
||||
d "rptadd csr, #0x7" 0177 0x0 nop
|
||||
d "rptadd csr, #0x7" 0177 0x0 (set csr (+ (var csr) (bv 16 0x7)))
|
||||
d "rptb #0x004976" 6f4976 0x0 nop
|
||||
d "rptcc #0xed, == #0" 6d0ded 0x0 nop
|
||||
d "rptsub csr, #0x6" 0106 0x0 nop
|
||||
d "rptsub csr, #0x6" 0106 0x0 (set csr (- (var csr) (bv 16 0x6)))
|
||||
d "sat" 2a2d
|
||||
d "sftcc ac7, tc2" a987b9b3
|
||||
d "sftsc ac27, ac17.h," a6bd9bd1
|
||||
|
|
|
|||
|
|
@ -165,11 +165,11 @@ d "rptcc 0x00, !tc1 ^ !tc2" 00ff00 0x0 nop
|
|||
d "rptb 0x0000" 0e0000 0x0 nop
|
||||
d "rptb 0xFF00" 0eff00 0x0 nop
|
||||
d "rpt csr" 4800 0x0 nop
|
||||
d "rptadd csr, ac0" 4801 0x0 nop
|
||||
d "rptadd csr, ar7" 48f1 0x0 nop
|
||||
d "rptadd csr, 0xF" 48f2 0x0 nop
|
||||
d "rptsub csr, 0x0" 4803 0x0 nop
|
||||
d "rptsub csr, 0xF" 48f3 0x0 nop
|
||||
d "rptadd csr, ac0" 4801 0x0 (set csr (+ (var csr) (cast 16 false (var ac0))))
|
||||
d "rptadd csr, ar7" 48f1 0x0 (set csr (+ (var csr) (var ar7)))
|
||||
d "rptadd csr, 0xF" 48f2 0x0 (set csr (+ (var csr) (bv 16 0xf)))
|
||||
d "rptsub csr, 0x0" 4803 0x0 (set csr (- (var csr) (bv 16 0x0)))
|
||||
d "rptsub csr, 0xF" 48f3 0x0 (set csr (- (var csr) (bv 16 0xf)))
|
||||
d "exp ac0, t0" 100800
|
||||
d "exp ac1, t0" 101800
|
||||
d "exp ac2, t1" 102810
|
||||
|
|
@ -263,9 +263,9 @@ d "bset 0x6, st2_55" 4665 0x0 (set st2_55 (| (var st2_55) (bv 16 0x40)))
|
|||
d "bclr 0x7, st3_55" 4676 0x0 (set st3_55 (& (var st3_55) (bv 16 0xff7f)))
|
||||
d "bset 0x8, st3_55" 4687 0x0 (set st3_55 (| (var st3_55) (bv 16 0x100)))
|
||||
d "rpt csr" 4800 0x0 nop
|
||||
d "rptadd csr, ac0" 4801 0x0 nop
|
||||
d "rptadd csr, 0x0" 4802 0x0 nop
|
||||
d "rptsub csr, 0x0" 4803 0x0 nop
|
||||
d "rptadd csr, ac0" 4801 0x0 (set csr (+ (var csr) (cast 16 false (var ac0))))
|
||||
d "rptadd csr, 0x0" 4802 0x0 (set csr (+ (var csr) (bv 16 0x0)))
|
||||
d "rptsub csr, 0x0" 4803 0x0 (set csr (- (var csr) (bv 16 0x0)))
|
||||
d "ret" 4804 0x0 (seq (set ret_addr (loadw 0 24 (* (cast 24 false (var sp)) (bv 24 0x2)))) (set sp (+ (var sp) (bv 16 0x2))) (jmp (var ret_addr)))
|
||||
d "|| ret" 4904 0x0 nop
|
||||
d "reti" 4805 0x0 (seq (set ret_addr (loadw 0 24 (* (cast 24 false (var sp)) (bv 24 0x2)))) (set sp (+ (var sp) (bv 16 0x2))) (jmp (var ret_addr)))
|
||||
|
|
|
|||
Loading…
Reference in a new issue