Compare commits

...
144 Commits
Author SHA1 Message Date
pancake 73960d34df Fix MN103 installation and VC4 tests in CI 2026-11-09 13:53:48 +01:00
dependabot[bot] 2afaceab6a build(deps): bump iced-x86 from 1.21.0 to 1.22.0 in /x86iced
Bumps [iced-x86](https://github.com/icedland/iced) from 1.21.0 to 1.22.0.
- [Release notes](https://github.com/icedland/iced/releases)
- [Commits](https://github.com/icedland/iced/compare/v1.21.0...v1.22.0)

---
updated-dependencies:
- dependency-name: iced-x86
  dependency-version: 1.22.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <[email protected]>
2026-11-09 13:23:27 +01:00
n0p a29ce917c1 mn103: r2r test databases in the extras tree
test/db/extras/asm/mn103 (55 disassembly vectors) and test/db/extras/mn103
(disassembly, analysis, pseudo syntax, cpu levels and ESIL emulation),
run by the CI like the microblaze and ppcdisasm databases; the radare2
test target is no longer needed.
2026-11-08 15:31:12 +01:00
n0p 8c738204dd mn103: build and test the plugin in CI
Add mn103 to LOCAL_BUILDS (installed through the r2pm package) and to
TESTS (the r2r database test/db/extras/asm/mn103 of radare2). The
Makefile honours R2PM_PLUGDIR as the r2pm package expects.
2026-11-08 15:31:12 +01:00
n0p 031b077f2c mn103: tests, sweep tool and docs
Unit checks of the decoder, analysis, ESIL and the length rule of every
table row; r2 integration tests (disassembly, pseudo syntax, cpu levels,
aoj metadata, function analysis, emulation of multiply/divide, flags,
call/ret and movm frames, memory bit operations, loops); the mn103-dis
linear sweep tool; README, doc/mn103.md and CHANGELOG.
2026-11-08 15:31:12 +01:00
n0p 2a44edead6 mn103: MN10300/AM33 architecture plugin from the binutils opcode table
The GNU binutils MN10300 opcode table (opcodes/m10300-opc.c, 1129 rows)
as generated C arrays, a C port of the length rule, first-match lookup
and operand extraction of opcodes/m10300-dis.c, and the RArchPlugin:
analysis types for every row, control flow (branches, setlb/lXX loops,
jumps and calls, returns), loads/stores with size and addressing mode,
stack deltas for add/sub sp, movm and the call/ret register-list frames,
a register profile with the PSW flags and the AM33/FPU registers, and
ESIL for the integer core. asm.cpu selects the machine level
(mn10300 < am30 < am33 < am33-2); the udf placeholder rows are looked up
after the named rows of the same encoding (mulq, mulqu, swap, ...).
A pseudo-syntax parse plugin covers the common forms.
2026-11-08 15:31:12 +01:00
pancake ee031a7021 vc4: upstream cgen tables, assembler, ESIL emulation and analysis
- Update the cgen generated sources to puppeh/binutils-vc4 (branch vc4),
  which decodes the vector unit and fixes sized ld/st, scaled immediates
  and the signed 12 bit offsets
- Decode 80 bit vector insns (16 byte buffer, 10 byte max op size)
- Decode what the tables miss or get wrong: tbb/tbh, 48 bit b/bl pc+o32,
  the missing 48 bit alu ops, and the shift of 32 bit addscale immediates
- Treat the 16 bit sp offset of lea/add sp as signed, print float6
  immediates as values so they assemble back
- Add an assembler on top of the cgen one, pc relative operands, relaxed
  wider forms, 48 bit fallbacks, and a check that rejects encodings cgen
  silently truncates
- Replace the analysis with a text driven one that emits ESIL for all
  scalar insns: flags in sr, conditions, compare and branch, ldm/stm,
  table branches, floats and conversions; vector insns are typed only
- Rewrite the pseudo plugin for the upstream syntax
- Drop libvc4 from the builds, the plugin never used it
2026-11-04 20:19:45 +01:00
pancake 0a0327aa45 vc4: pseudo compare-and-branch forms and meson include path fix
- Translate addcmpb<cond> and 3 operand b<cond> into compare and goto
- Render the never-taken f condition as false and fix 'x -N' spacing
- Resolve ../../include with realpath since p/vc4 is usually a symlink
- Document the separate arch.vc4 and asm.vc4 XPS plugins
2026-11-04 18:41:02 +01:00
pancake 9870775224 Add r2plugin xps interface and pseudo for vc4 2026-11-04 18:31:28 +01:00
pancake d5e7a28186 Ignore vc4 plugin build artifacts and editor caches 2026-11-04 11:33:25 +01:00
pancake c9571534b9 Add standalone Makefile to build the vc4 asm/anal plugin
Allows building arch_vc4 from libr/asm/arch/vc4 directly instead of
going through the whole r2 build. Mirrors libr/asm/p/vc4.mk but
resolves the sources locally, links libr/libvc4 objects and the
libr/asm/p/arch_vc4.c glue, and adds an install target.
2026-11-04 11:33:09 +01:00
pancake 5fff0016a3 Support bits:// packed and be16 unpacked roms for r2tama 2026-11-03 18:30:00 +01:00
pancake f2199032a7 Add Tamagotchi P1/P2 ESIL emulator 2026-11-03 18:10:09 +01:00
n0p 5d28dc6de4 md32: tests and docs for the scq16 table update and the public test vectors
test/test_scq16.py (267 checks) and test/test_md32.c cover the new forms, the open marker, the broadcast ports, the confidence levels and ctz(0). test/scq16_vectors.json carries 195 public bytes-only vectors with the expected result in the big-endian regime of the harness and in the little-endian regime of the core data memory; test/test_scq16_vectors.py runs both and the Makefile adds it to make test. doc/scq16.md, README and CHANGELOG describe the hypothesis file, the confidence levels and the open question on ctz(0).
2026-11-03 10:17:01 +01:00
n0p 645f4154ff md32: scq16 table update (229 forms), the open-reading marker, the broadcast ports and the confidence levels
jr rn (6f ec) reads a 5-bit register field (r0-r31); btst rd, rd, #pos (67 f8-fb) has a 5-bit position; ctz is its own form without the hypothetical flag and sqr? belongs to the op41 placeholder; and rd, rs, #0x1|#0x3|#0xf (2 bytes), add rd, rs, #-1 (2 bytes) and the 4-byte sb are high, the 4-byte btst rd, rs, #pos is medium (settled by execution results).

The exporter marks an open reading (a family placeholder or a provisional name) with SCQ16_FL_OPEN and gives an open alternative without a template the uniform ESIL marker REF,ALT,open; export --hyp applies the declared plugin hypotheses of isa/scq16_hyp.json, which is empty: the packing ESIL of op41.fld rd, rs, rt, #pos is carried by the ISA source, still flagged hypothetical.

The scalar ports v0-v31 are the broadcast ports of the vector register file: a write by vbcast / vbcast.i reaches the 64 lanes of vr_k; the custom op open has no effect; aoj reports open, reading, hypothetical and confidence per unit. ctz of a zero operand gives -1 under the table ESIL; whether the hardware returns 32 is an open question. asm: the pseudo rule of op41.fld.
2026-11-03 10:17:01 +01:00
n0p 899e3344ff md32: document the three encodings the plugin serves and its scope
The README introduction states what MS15E30, uSIP and SCQ16 are and how they relate: two MD32 encodings and one distinct byte-granular encoding that shares the MD32 scalar programming model, which is why it is a cpu mode of this plugin; the remaining DSP cores of the same modem use an unrelated SIMD ISA and are out of scope. doc/scq16.md carries the same note.
2026-11-03 08:31:29 +01:00
n0p 6493987c72 md32: tests and docs for the scq16 table update and the vector unit model
test/test_scq16.py: bytes-only checks of ctz (established) next to the
provisional sqr?, sra? rd, rd, #pos, vrd? rd, vb1[x], op41.fld with three
registers, the provisional and? masks, lw.post of 2 bytes with a 4-bit
destination, the signed post-increment of the 6e page, vector ops with
non-zero fields, a vector head and B slots with the new forms; analysis
(ctz named, sqr? / sra? / vrd? provisional, op41.fld with rt, the lw.post
destination r11); the ESIL of ctz / sqr? / sra? / vrd?, the .post
templates writing rd last (rd == rb), the signed post-increments and the
vector unit model (vset.a / vmem.set, v.mem.ld with a count and with the
whole register, v.mem.ld + v.mem.st through the VU, v.move.mv back and
forth, F2 >= 4 without effect, a bundle with a vector load, unmodelled
vector ops stepped over).  test/test_md32.c: ctz, lw.post r11, sra?,
v.mem.ld with its fields.  doc/scq16.md: the new forms, the .post
convention, the VU model and its limits, the register profile with vr*,
the calling convention (r16-r31 callee-saved, r0-r15 caller-saved, lr
saved by the functions that call); README "SCQ16 mode": the VU model,
the provisional sqr? / sra?, the calling convention; CHANGELOG entry.
2026-11-03 08:31:29 +01:00
n0p ba096f3546 md32: scq16 table update (402 bit alternatives), the .post convention and the vector unit model
isa/scq16_isa.json is re-exported by the `export` command of
tools/gen_scq16_tables.py: 228 forms / 402 bit alternatives.  ctz rd, rs
(41 f3 0x22) is an established operation with the ESIL rd = 31 - clz(rs
& -rs); new provisional readings: sqr? rd, rs (41 f3 0x23, rd = rs * rs),
sra? rd, rd, #pos (67 fc-fd), vrd? rd, vb1[x] (1a xy, a 32-bit read of
the VU scalar bank with rd = w[3:0] + 1), and? #0xf000? (67 98-9b and the
2-byte 00/01 with k = 6) and and? #0xc000? (67 b4-b7); op41.fld rd, rs,
rt, #pos reads its third field as a register; lw.post rd, [rb] += 4 (21)
has a 4-bit destination (r1-r16); the 3-bit post-increment of the 6e
.post family (sh.post, lw.post, lhu.post?, lbu.post) is signed (x = 4..7
is -4..-1 units); sra rd, rd, #imm (09) is established; the load
templates with a post-increment write rd last, so with rd == rb the
loaded value wins (a declared convention: the public MD32 documents rd
written first).

scq16_vu.inc.c (new, included by scq16_arch.inc.c): the vector unit
model of the ESIL.  The register profile gains the vector register file
vr0-vr31 (128 bytes each, exposed as the four 256-bit quarters
vrK_0..vrK_3; lane 16q is the low 16 bits of quarter q); vp0-vp7 (written
by vmem.set and the hypothetical vcfg4c? #0xc) and va0-va7 (written by
vset.a) are the existing scalar ports.  The custom ESIL op vop models the
three established vector operations and nothing else: v.mem.ld copies n
halves from DM[p] into vr[F1 >> 2] and v.mem.st copies n halves from vr0
to DM[p], with p = vp[2 * F2 + F3[4]] when F2 < 4 and n = va[A] when
1..64 (otherwise the whole register), post-incrementing the pointer by
the bytes accessed; v.move.mv copies vr[F3] into vr[F1].  A memory op
with F2 >= 4, the pair mode B = 2 of v.move.mv and every other op9 pop
their operands and have no effect.  The data memory is read and written
through the ESIL memory callbacks; the vector registers are kept in the
register arena.

asm_md32.c: pseudo rule of sqr (rd = (rs * rs)).  Makefile: the new
include file among the dependencies of the arch plugin.
2026-11-03 08:31:29 +01:00
n0p bfab794507 md32: tests and docs for the scq16 table update
test/test_scq16.py: bytes-only checks of the page 42 (cmov.ge, cmov.eq
with a register, the provisional cmov.*?, the remaining sel? codes), the
67 page (mv, bset/btst rd, rd, #pos, and #0x3fff), lbu.post with 5-bit
registers and the 23 page with a signed post-increment, the 6-byte and
#imm16, ctz?/clb?, vcfg4c? #0xc, ld46?, the established vector names
(v.move.mv, v.mem.ld, v.mem.st) next to the provisional ones, addsp 14 8x,
halt, sys41, lbu? off(sp), the 4-byte beq of 5c 40-6f, j.d1 decided by its
target (also in a B slot), the ESIL of the new forms, negative frame
offsets, halt/sys41 without effect and ret.d2 / jr.d2 across two aes
steps (a packet in the first slot).  test/test_md32.c: cmov.ge, mv 67 c8,
j.d1 by target, lbu.post of the 23 page, v.mem.ld.  doc/scq16.md: the
j.d1 length by target, the vector names (established / provisional), the
page 42, 46, 4c, 41 f3, 22/23, 67, 6e and 74 families, the ESIL
conventions (.d2 across two aes steps, 32-bit addresses, no-effect units,
the memory order inside a packet), the hypothetical alternatives of the
table, the limits (rd == rb post-increment, the vector unit), the
data-space bases; README "SCQ16 mode" updates; CHANGELOG entry;
tools/scq16_flags.r2 (DM, I/O window and DM2 bases as flags).
2026-11-02 16:26:48 +01:00
n0p 619f60a7df md32: scq16 table update (228 forms), decoder rules and generator features
isa/scq16_isa.json is re-exported by the `export` command of
tools/gen_scq16_tables.py: 228 forms / 400 bit alternatives.  The ESIL
templates, the delayed transfers (SETJT/SETD) and the hypothetical flag
come from the form-description module itself (its HYP table), so the
exporter applies no overlay of its own.  The vector names carry the ? of
a provisional name in the table string and none when the operation is
established (v.move.mv, v.mem.ld, v.mem.st: vector.firm_op9).  New or
renamed forms: cmov.ge rd, rs, #imm, ra; cmov.eq rd, rs, rx, ra (register
form); the provisional cmov.leu? / cmov.ltu? / cmov.lt? / cmov.le?; mv rd,
rs (67 c8); bset / btst rd, rd, #pos (3 bytes); lbu.post rd, [rb] += inc
with 5-bit registers (6e q2) and the 23 page as lbu.post rd, [rb] += simm3
(-4..-1); and rd, rs, #0x3fff (67 a4-a7); the 6-byte and rd, rs, #imm16
(74 sub 1); the provisional ctz? / clb? (41 f3); vcfg4c? #0xc with the
hypothetical p_k <- rs; ld46? as a hypothetical byte load with a
post-increment; lbu? rd, off(sp) (ex lb?); addsp sp, #imm (14 8x-fx); fxts
without the ?; halt and sys41 with the empty ESIL; the length leaves make
5c 40-6f a 4-byte beq rA, rB.

scq16_decode.c: a first byte 56 with the top two bits of the second byte
clear is the 4-byte j.d1 when its 22-bit target (from the packet start in
a B slot) is a plausible code address, else a formless 2-byte unit
(without a function table the plugin cannot decide by membership).  Every
ESIL memory access cuts its address to 32 bits: the ESIL machine computes
in 64 bits and aes does not mask addresses, so a negative frame offset
over sp wrapped above 4 GB.  The ? of a vector name now comes with the
table string (scq16_vname_firm).  scq16_arch.inc.c: a unit whose ESIL is
the empty string (nop, halt, ieon/ieoff, loopend, vwait?, sys41) no
longer blocks the ESIL of its packet; the override hook counts as the
unit ESIL; opex named / provisional of a vector op follow the table name.

asm_md32.c: pseudo rules of cmov.ge / cmov.leu / cmov.le (the ? of a
provisional name is stripped before the lookup), sys41, ctz / clb.
2026-11-02 16:26:48 +01:00
n0p f4f11b90c3 md32: tests and docs for the uSIP table update 2026-11-02 06:43:08 +01:00
n0p f58de93399 md32: uSIP table update (760 forms), decoder rules and generator features 2026-11-02 06:43:08 +01:00
n0p 58a5ac18e6 md32: English output text for the scq16 loop, jump and trap forms 2026-11-01 20:21:45 +01:00
n0p 9b0adabca8 md32: tests and docs for the scq16 mode
test/test_scq16.py exercises cpu=scq16 inside r2 with loose bytes only
(disassembly of units, packets, vector operations and bundles; analysis;
ESIL; the pseudo parser) and runs from make test; test/test_md32.c gets
three decode checks.  README section "SCQ16 mode", doc/scq16.md and the
CHANGELOG entry.
2026-11-01 20:21:45 +01:00
n0p 219b1f7c07 md32: scq16 cpu mode (table, decoder, arch and asm)
Add cpu=scq16, the SCQ16 variant of the MD32 family with a byte-granular
packet encoding, as a third cpu of the plugin.

isa/scq16_isa.json is the ISA table (218 forms, 389 bit alternatives, the
length-rule leaves of stand-alone units and packet heads, the vector op9
classes and provisional names, the register names) and
tools/gen_scq16_tables.py generates scq16_opcodes.h from it (the VU scalar
ports as ESIL registers, vector operations as the custom op vop, delayed
transfers as SETJT/SETD, the no-effect system forms and the hypothetical
readings flagged).

scq16_decode.c implements the length and packet rule by first-byte leaves
(stand-alone units, packet heads read shifted by one bit with the borrowed
bit of the B slot, masked orphans, 4-byte vector operations, vector heads,
8-byte bundles), the form match over the transformed unit, the operand
text and the ESIL expansion with the parallel-packet register remap and
the VU scalar-port registers.

scq16_arch.inc.c carries the analysis of the SCQ16 decode (types,
jump/fail with the delay slots counted in instructions, do as a loop
reference, loads/stores, stack ops, opex with the unit/packet/bundle
structure), the ESIL (the scalar forms; a packet as A then B with the
registers B reads and A writes copied to temporaries first; delayed
transfers through SETJT/SETD; the VU ports as registers; vector operations
as the custom op vop, a no-op) and the register profile (sp/lr as
csr14/csr15, a0, the loop registers, the VU ports).  arch_md32.c
dispatches decode, info and regs on cpu=scq16 and registers vop through
esilcb; asm_md32.c gets the SCQ16 pseudo-syntax (packets as
parallel { a; b; }, memory, stack, bit-field and transfer rules).
2026-11-01 20:21:45 +01:00
n0p a1b8861f9d md32: tests and docs for the uSIP table update
Plugin vectors for the loop count, the F' = 0 / h = 1 / m = 1 loops
(validated and unverified), the 4- and 3-unit bz.s (validated and unknown),
beq9sp, the bgt rA, #-1 cell, the W6 h = 1 cells and the loop guard, op2z?,
the h = 1 shifts, the 16-bit lea, the splits (R-slot4n, R-op4imm in 2 and
more units, S0-slot, S3), op72?, saturate?, sat40 H H T T, R-waw with the
P2W prefix, R-b111pre, R-b111ctl, R-bsnext, the omitted weak cell of
R-brHHTT, sub r14, st.w [sp], st.abs hi F' = 0, addq / cell E by value,
mtcsr of the accumulator CSRs, R-1eX0F0, R-movi6d; the lea, loop#, mtcsr,
movi #-32768 / #-32767, ld.h / ld.hu of R-1eX0 / R-ldF0 / R-hhttF0 / R-F0d,
op2z? and two R-waw vectors updated to the new readings; pseudo vectors for
the new rules; README, doc/usip.md (the loop cells, the post-layout splits
and the fusion, the explicit candidates, score rules and layout
constraints, the cells added with the table, the unverified fallback and
the order of the packet-level passes) and CHANGELOG.
2026-11-01 18:45:09 +01:00
n0p 85f40b5d6c md32: uSIP table update (726 forms), decoder rules and generator features
Regenerate isa/usip_isa.json and usip_opcodes.h (52 forms added, 13 retired,
14 modified): the loop #N count is the collected head field (bits 13:5, no
+1), loop #N with the F' = 0 tail exactly at +2, with h = 1 (N >= 128) and
with m = 1 (N >= 256, printed loop #N?), bz.s in 4- and 3-unit packets, the
split entries of the slot family stslot / stslot? / ldslot? (F-slot0,
S0-slot, the S3 cells ldslot/stslot #48-63), the fusion entry
op72? rA, #k, asr#b, op2z? rA, lsl/asr r8-r15, #B, the W6 cells
ld.h/st.h rB, [r8+rrr] and [rA]+ with h = 1, sub r14, #f12/2 with any F/F'
(spfix_sub_sp retired), st.w [sp], #imm14, st.abs with the hi F' = 0,
add rB, rB, #imm27 / st.h? [rB], #sat selected by the immediate value (also
the cell-E triples), add? rB, r15, #rot12 and ld.h? / ld.hu? rB, [r15+off]
with the F' = 0 tail, saturate? rd, rs1, movi #simm6 in the delay slot of a
validated branch, mtcsr #0x30-0x3e, ld.h / ld.hu / lea / movi #-32768 /
#-32767 / ld.hu [rA+rB] without the ?; the constraints of beq_imm8_d (the
op 9 beq.d with base sp and the adjacent tail is not a branch) and of the
seven op a *_s0f1 / *_imm8_F0 entries (the bgt rA, #-1 head class takes
only the adjacent S = 1 tail); the ABI passes eight arguments in r0-r7.

The generator emits the flags FUSE, SPLIT / SPLITBARE (with a USIP_FORM_*
index for every split and fusion entry), the constraint op instr_index,
any with up to four alternatives that may be a context condition or an
instruction position and six new context conditions; the loopn operand
type is the collected field.

The decoder keeps the score in twentieths (al1 = 0.3), adds the explicit
candidates loopcand / R-brHHTT / R-b111pre / R-b111ctl with the b111_layout
context extended to them, the bz.s rules of 4- and 3-unit packets (the rest
re-parsed as the delay slot, the 3-unit one with the target beyond the
packet and no write of rA), the S3 renames and the split pass of the slot
family with the split-tail reading and the nowaw guardian, the fusion after
the renames, R-movi6d, the R-w6h1 loop guard evaluated with the packet being
parsed, the R-loopA adjacency (.word at any distance but +2), rf0dmidwaw,
the score rules R-waw / al1 / R-bsnext / P2W-P2H prefix / sat40 H H T T /
rf0dpen and the instruction position of the renames. The loop entries with
the F' = 0 tail at +2 and the h = 1 heads with the S = 1 tail (and the
adjacent F = 0 tail) are accepted unverified; the m = 1 (loop #N?) and the
other h = 1 entries are not.

The arch plugin reports the stores of an immediate ([rB] / [sp], #imm) with
the value in val and [sp] as a stack access; the new mnemonics keep their
kinds (op2z? / op72? / saturate? are unknown operations). Pseudo syntax for
the stores of an immediate (also to [sp]), the absolute st.abs / ld.abs and
the ? of a count (loop#? #256?).
2026-11-01 18:45:09 +01:00
n0p a8d4a6a520 md32: tests and docs for the uSIP table update
Plugin vectors for the F = S = 0 and R-br0 cells (validated by the session,
rejected with fall-through, unknown backward, unverified forward), ret.s.d,
movi #-1 with F = 0, the op 2 shifts, the open b.s rejected and unverified,
bz.s P5, the m = 1 slots, loop.b1? and the ?ss=N loops, movi? #-32767, the
asr16 clamp, the bit-field pair and the BF_SEL cells, ld.bu/st.b with the
byte displacement, ld.b/st.h with F != S at +2 and the undo at +1, the
ld.h?/ld.hu? of R-hhttF0 / R-F0d, the sp adjustment pair, the ld.w?/st.w?
word classes, .stimm16? and mtcsr? with a named tail; the loop, open b.s,
mtcsr, movhi and save vectors updated; pseudo vectors; README, doc/usip.md
and CHANGELOG (the target validation filter, the address views, the F = 0
branch cells, the split and context groups, the new tie-breaks and what the
plugin can see of the guards).
2026-11-01 18:45:09 +01:00
n0p e108f90f79 md32: uSIP table update (687 forms), decoder rules and generator features
Regenerate isa/usip_isa.json and usip_opcodes.h (56 forms added, 3 retired,
71 modified): the b<cond>.d cells with head F = 0 (bne.d, ble.d, bgeu.d,
bge.d, bne.u8.d, beq.u8.d, bleu.d, read only in the (B class, tail distance)
cells of usip_br0_cells; the five weak cells of usip_br0_cells_weak are never
taken), bgt.d of the F = S = 0 cell back in the table, ret.s.d, loop.b1? and
the ?ss=N loops, bz.s with bit 3 = 0, the ld/st type 111 ld.bu / st.b with
the byte displacement (st.b? retired), ld.b / st.h with F != S of op 1
exactly at +2, ld.h? / ld.hu? with the F' = 0 tail as the second head of
H H T T and by the deferred tail of a head with base sp, the bit-field pair
in H H T T and the BF_SEL cells renamed from .bf?, the 16-bit op 2 shifts
lsl/lsl?/asr/asr? (addi4 retired), ldslot/stslot with m = 1, .stimm16?,
ld.w?/st.w? for the f12 = 1 / 3 mod 4 word classes, add r14 / sub r14,
movi? #-32767, movi rA, #-1 with F = 0, mtcsr? of the accumulator CSRs with
a named 16-bit tail; the known target as a validation filter on the
F = S = 0 cells, bne.d #-1, the loops with the F' = 1 tail, the open b.s and
the near b, with fall-through on failure (USIP_F_GUARDFT); the operand
conventions of six families revised. Thirty-one entries are post-layout
renames.

The generator emits the operand type offb, the flags GUARDFT / B111 / F0CTX
(flags is ut32), the constraint ops br0_cells / br0_cells_live, bf_valid,
the guards tail_named16 and target_packet_start_any_or_function_start, the
any sub-operations packet_len, guard, range and br0_cells, the large value
sets (usip_value_sets), the new context conditions and the tables
usip_br0_cells, usip_br0_cells_weak and usip_c48sym_table; form names are
sanitised into C identifiers.

The decoder implements the fall-through guards, the fifth guard kind with
the optional packet_start_any callback, the R-br0 cells by B class and tail
distance, the b111 group in the 2-unit packet and in H H T T (which now
takes tt = 11 tails), the context conditions b111_layout, hhtt_second_head,
f0d_triple, bfpair, bf_dst_not_written and rest_named_no_q, the f0ctx pass
on the .word pairs and the re-read of the R-F0d middle unit, R-op1fs, the
bz_s_P5 context rule, the m = 1 R7 slots, P2H, R-lr16, R-align48 and
R-c48sym in the score, the b.s guard admitting a function start and the
loop F' = 0 rule by field; immediates glued to a letter or '=' print in
decimal. The forms whose guard is a validation filter keep their reading
unverified when the target is unknown (conditional branches only forward);
a definite "not a packet start" rejects them.

The arch plugin initialises UsipGuardCtx by field, separates "not a packet
start" from "unknown" for backward targets with the lowest packet start
decoded in the session, reports offb as a disp operand in opex and sets the
stack deltas of addsp and the add r14, r14, #imm / sub r14, #imm pairs.
Pseudo syntax for the 2-operand lsl / asr.
2026-11-01 18:45:09 +01:00
n0p 5b9a32f8c4 md32: tests and docs for the uSIP table update
Plugin vectors for the 14-bit word displacement, nop.ctl, the bit-field
family, mtacc?, movi? #-32768, sgt #-1, the register bset/bext, the S0F1
branches (unverified, validated by the session, not validated), the r15-based
loads, .ldF0?, the F' = 0 ld.h?, the 48-bit value table, .3eX0?, the
lsl/sext16/zext16 renames, cop with addi, .hi, movhi with the tt = 10 tail
and .op4t0; the op8 slot split vector updated; pseudo vectors; README,
doc/usip.md and CHANGELOG (the post-layout renames, the K-tie cascade and
what the plugin can see of it, the extended target-guard fallback).
2026-11-01 18:45:09 +01:00
n0p 71ab77c46b md32: uSIP table update (634 forms), decoder rules and generator features
Regenerate isa/usip_isa.json and usip_opcodes.h (52 forms added, 12
retired, 103 modified): the 14-bit word displacement of the two-unit
ld.w/st.w, nop.ctl, the bit-field family fxtu/fxts/fup, movi? #-32768, the
register bset/bext, mtacc?, sgt #-1 with F = S = 1, addi #32 next to cop,
the 16-bit lsl/sext16/zext16 variants, the r15-based loads, .ldF0? and the
F' = 0 ld.h?/ld.hu?, .3eX0?, the b<cond>.d cells with the [0][1][tt] tail at
+2, movhi with the tt = 10 tail, the 48-bit constants admitted by value, the
double-class split; the .hi/.hilo pair entries and every not_hi1010
constraint are gone. Twenty entries are post-layout renames.

The generator emits the rename_from lists, the constraint ops tail_adjacent,
ieee_short and the 48-bit value table membership, the tail_adjacent
sub-operation of any, the context conditions cop_rA_in_packet and
not_c48_lo_follows, USIP_MAXVALS 12 and the tables usip_never_tail,
usip_never_head_with_tail and usip_c48_table; the rename entries are exempt
from the 16-bit position-class checks.

The decoder implements W14, the never-tail and never-head-with-tail units
from the tables, H1 (the forced hi(1010) decode is gone; .hi/.lo only after
a 48-bit-family head in the packet), the 48-bit value table in the partial
admission, P2W (no alignment penalty for the 2 mod 4 word offsets in the
H H T T layout), callin through a new guard callback, the post-layout
renames and the K-tie cascade: dedup and nowaw on the tied readings of the
packet, du2 over the neighbouring packets the caller supplies (packet_at /
branch_target callbacks, first-pass readings with USIP_GUARD_NO_CASCADE).
UsipPacket reports how a tie was decided; a failed guard of the op C
compare-and-branch cell prints the pair as .dsp. The unverified fallback
accepts the S0F1 cells whose unverified readings are right in nearly every
case and loop rX with the F' = 0 tail when the head has F = 1 and the S = 1
tail sits at +2.

The arch plugin answers the cascade callbacks with the packets decoded
earlier in the session, the first-pass readings of the packets inside the
bytes at hand and the branch targets seen so far, reports the tie-break in
opex, sets ireg for the r15-based loads and types fxtu/fxts as cast and fup
as or. Pseudo syntax for fxtu/fxts/fup, mtacc, the 2-operand addi,
sext16/zext16 and asr16; nop.ctl reads nop.
2026-11-01 18:45:09 +01:00
n0p b6da363492 md32: tests and docs for the uSIP table update
Plugin vectors for loop# (validated at +1 and +2, unverified), b<cond>.l
(validated, unverified, not taken, 64-bit), the signed 64-bit pairs, the
negative offsets, seq/sle/sgt, movhi, the 16-bit first-slot st.h, the
deferred st.h and its undo by a validated b.s, H H T T, the op8 split, the
0e10 trio, cop with F = S = 0, xor, movi rA!, bset rd!, osl and the
cmulr16/cmuli16 names; the jr, ld.d, movhi and bank-bit vectors updated;
pseudo vectors; README, doc/usip.md and CHANGELOG.
2026-11-01 18:45:09 +01:00
n0p 4932f31af9 md32: cmulr16/cmuli16 names follow the little-endian data memory
The names of 0xDA00 (cmulr16, a*c - b*d) and 0xDC00 (cmuli16, a*d + b*c)
follow the little-endian layout of the data memory: the high half of a 32-bit
complex word is at +2 and holds the real part. The earlier assignment assumed
a big-endian data memory.
2026-11-01 18:45:09 +01:00
n0p cdd0753019 md32: new uSIP mnemonics and conditions in the arch and asm plugins
Conditions bequ/bneu of the 48-bit forms, types for sle (cmp) and osl (shl),
val = N for loop #N, the signed offsets as disp operands in opex; pseudo
syntax for loop#, sle, bequ/bneu, the 2-operand xor, mfacc, the bset family
and osl; the ? marker is stripped repeatedly and ld.d/ld.w are not
sign-extended.
2026-11-01 18:45:09 +01:00
n0p 8b98f544d7 md32: uSIP table update (594 forms) and prior-free packet layout
The uSIP table grows to 594 forms (137 added, 18 retired, 76 modified): the
48/64-bit b<cond>.l prefix forms with the complete condition table, loop #N,
the op 6 set-on-compare family, movhi by its 20-bit value, the 48-bit
constants by one formula, the signed ld.d/st.d, the closed negative
half-word and word offsets, the deferred st.h tail, the position cells and
the slot split.

The generator gains the operand types offh/offw/loopn and the redefined
movhi, the flags ADJDEF/PREFIX/RENAME/HHTT, 8 ranges per field, 64-bit
entries, the constraints gt/odd/packet_len_ge/head_index/head_pos_ge/ctx and
the b.s guard, any with up to three alternatives, the bcc48 condition table
and save w=4.

The decoder matches the prefix forms before the layout, ranks the readings
with the prior-free total order (s0, I, Fv, -A, K) instead of the enumeration
order and the group count, and implements the grammar rules (5e0d never a
tail, the deferred st.h tail with its undo and the validated-b.s guard, the
.d SP-negative rejection, the 3-unit and H H T T candidates with the forced
decode of hi(1010) heads, the 0e10 trio, the loop #N adjacency, the op8
split), the new penalties, the deferred constraints with fall-through, the
late guard evaluation, three tails for the 64-bit forms and the unverified
fallback for the prefix forms and loop #N.
2026-11-01 18:45:09 +01:00
n0p 4ad1a62408 md32: docs for the uSIP table update
README uSIP mode: the F' = 0 control tails, the target guards and what the
plugin can check, the new mnemonics and analysis types.  doc/usip.md: the
packet-model rules R0/R7, the table additions (movhi, base/offset, scale, the
new constraints, kinds io/jr), confidence census, ABI without a classic CSR
bank, and a section on the target-guard knowledge and the fallbacks.
CHANGELOG entry.
2026-11-01 18:45:09 +01:00
n0p 39458c3b5b md32: tests for the uSIP table update
test_plugin.py: vectors for ior/iow, nop32, the 32-bit ret of the sys shape,
jr?, addsp, ld.d?, the first-slot ldslot/lea? forms, movhi? and the guarded
3-unit control packets (loop with the tail at +2 and the end at the next
packet, beqz.d validated by a forward packet start and read as data when the
target is not one, call with the F' = 0 tail read unverified); the mov32 and
ld.b vectors show the bank bit on the register it applies to (r15!).
test_parse.c: the new pseudo rules.
2026-11-01 18:45:09 +01:00
n0p b07fcf44b1 md32: new uSIP mnemonics in the arch and asm plugins
arch_md32.c: operation types for the forms of the updated table: io for
ior/iow (ireg = the port register), rjmp for jr? rB (register jump with the
delay slot of a return), ret for rti, trap for trap?, nop for nop32, add for
addsp, lea for lea?, cmp for sne/scmp?, cast for extu, refptr 8 for the
ld.d?/st.d? pairs; the mnemonic test ignores the trailing ? of the medium
forms; extended CSR names in opex.

asm_md32.c: pseudo syntax for ior/iow, mfcsr/mtcsr, addsp (sp += / sp -=),
ldslot/stslot, jr, nop32, sne, scmp, movhi, extu, cop, rti, ieon/ieoff, idle,
isync, lpexit, trap and the 64-bit loads/stores; the trailing ? marker of
lea?/jr?/call? is ignored.
2026-11-01 18:45:09 +01:00
n0p 58536ef4e9 md32: uSIP table update (475 forms), generator features and decoder rules
isa/usip_isa.json goes from 386 to 475 forms (110 added, 24 retired, 140
modified): port I/O ior/iow instead of mfcr/mtcr, mtcsr and mfcsr with F' = 0,
the sys shape split by its tail field (cop, rti, lpexit?, isync?, ieon, ieoff,
trap?, sys?, ret, ret?, jr?, call rB), nop32, cmov r15, add rB, rA, #rot12 for
the whole op 0 cell, sne, scmp?, movhi?, extu, movi #-1, addsp, lea?, the
stack-slot closers (ldslot/stslot, .slot?, lsl #1/#2, movi #simm6, .bit4?,
.ext8?), ld.d?/st.d? (64-bit pairs), st.b?, ld.hu for type 110, unsigned
12-bit ld/st offsets, ld.bu in the class-E cells, per-operand bank bits
(rB! by x, rA! by m, rs1! by ss), save w=2 = four words; the 48-bit call with
the far tail is retired (those packets are call/b with the F' = 0 tail at +2).

tools/gen_usip_tables.py: the movhi operand type, base as a constant added to
register/immediate fields, scale on immediates, the ge and any constraints,
membership masks for the large CSR sets, the target guards as constraint
records, flag USIP_F_ADJ2, kinds io/jr, the sys name table, extended CSR names
and kind names.  The header stays byte-identical on regeneration.

usip_decode.c: packet guards, adjacency rule and tie-breaks.  F' = 0 control
tails exactly at +2 (otherwise data), target guards evaluated after the mask
match (32-bit forms: a failure is .word, no fall-through; the 16-bit call.s
falls through), packet_len constraints with the real packet length so that
the stand-alone closers never count as named 16-bit ops, closers matched with
bit 15, rules R0 (the final closer may be its own group) and R7 (first-slot
ldslot/stslot/lea? when the rest of the packet is named), the 1dX6 + named
tail and validated-guard tie-breaks; the enumeration order is unchanged.

The decoder asks the caller about branch targets through UsipGuardCtx.  The
arch plugin answers packet starts from the stream: the packets decoded so far
in the session and a scan of the bytes radare2 hands it (64 bytes of
lookahead).  Function starts are not available to an arch plugin, so the
decoder applies a documented fallback: the call / b / compare-and-branch with
immediate forms whose F' = 0 tail sits at +2 and beqz.d are read unverified
(trailing ?, confidence medium, opex.target_guard = unverified); loop, far b,
bnez.d, the register compare-and-branch and the open-packet call.s are
treated as a failed guard.
2026-11-01 18:45:09 +01:00
n0p 3dfb0180d0 md32: changelog note for the emulator test expectation in usip mode 2026-11-01 18:45:09 +01:00
n0p 73831a1ee2 md32: emulator test expects the delayed-return stop in usip mode
With the packet decoder, 5ef9 is ret.d and the rest of the packet is its
delay slot, so md32-run stops with unsupported_delay_slot_execution and
zero completed steps, exactly as for the MS15E30 delayed branch.  README:
make test passes against radare2 6.2.5 on Linux as well.
2026-11-01 18:45:09 +01:00
n0p 68e9f6dfe3 md32: six group-5 16-bit forms missing from the MS15E30 table
rem16, ctz16 and the four complex half-word products (cmulcr16, cmuli16,
cmulr16, cmulci16) occupy 0xCA80-0xCABF, 0xCB00-0xCBFF and 0xD800-0xDFFF,
which the public table leaves undecoded.  Names and operand order follow
the neighbouring group-5 forms; the semantics are inferred from usage
(rem16 as a non-negative modulo, the cmul* variants as the cross-sum and
straight-difference terms) and are marked as such in the source.
2026-10-30 19:53:17 +01:00
n0p 2c54fda563 md32: document the uSIP mode
README: the uSIP mode section (packet model, what one pd line is,
mnemonics and operands, analysis, limitations) replaces the partial
support notes; build note for radare2 6.2.2.  CHANGELOG entry.
doc/usip.md: table format, constraint and context-rule semantics,
confidence levels, ABI, known limitations of the table-driven reading.
2026-10-30 16:28:21 +01:00
n0p a0ccecf534 md32: uSIP packet vectors in the plugin test
Exercise the usip mode on real packets: conditional branch with its tail,
b.s with a 48-bit delay-slot op, call with the S S O O layout (.unit
tails, delay = 3), interleaved 48-bit call.abs, hardware loop reference,
ret.d, the two-unit bz.s context rule, a truncated packet at the end of
the buffer, save/restore/ret and basic blocks that keep the delay slot.
2026-10-30 16:28:21 +01:00
n0p e94cc3060d md32: uSIP pseudo syntax
Pseudo rules for the uSIP mnemonics: # immediates, [base+off], [base]+
and [sp+off] memory operands, compare-and-branch, ld/st as dmemN[...],
movi/mov32, ALU, cmov, loop, save/restore.  test_parse.c updated.
2026-10-30 16:28:21 +01:00
n0p ac1af9c612 md32: wire the uSIP packet decoder into the arch plugin
In usip mode the plugin decodes whole packets (cached per session, 64
entries) and emits one op per run of adjacent units of the same
instruction; displaced tails become .unit ops that name their head.
Types, conditions, jump/fail/delay, loads/stores, immediates, save and
restore, sys and loop references come from the table; opex reports the
form, its confidence, the slot, the unit addresses and the packet
summary.  MAXOP_SIZE is 16 in this mode and regs() exposes the ABI.
The previous five hard-coded uSIP patterns are replaced by the table.
MS15E30 decoding is unchanged.
2026-10-30 16:28:21 +01:00
n0p 94bccea25c md32: table-driven VLIW packet decoder for uSIP
usip_decode.c reads the 16-bit big-endian units of a packet (closed by
bit 15), enumerates the group splits and head/tail assignments the table
allows (heads first, tails round-robin), scores them (unknown units,
instructions, groups, documented tie-break penalties), applies the
adjacency and context rules and returns one instruction per head with
the addresses of its units.  Control flow is restricted to slot 0 and
the rest of an open packet is its delay slot.
2026-10-30 16:28:21 +01:00
n0p 3f8dada173 md32: add the uSIP instruction table and its header generator
isa/usip_isa.json describes the uSIP (MD32 family, VLIW packet variant)
instruction set: 386 forms with masks, operand fields, constraints,
packet rules and a confidence level, plus the packet model (unit scan,
head/tail layout, tie-breaks, context rules) and the register/CSR model.
tools/gen_usip_tables.py generates usip_opcodes.h from it: every field
referenced by a format string or a constraint, constraints as structured
UsipCons records, 16-bit flags and the indices of the context-only forms.
2026-10-30 16:28:21 +01:00
pancake a21d29689b Add support for md32 architecture 2026-10-30 10:31:15 +01:00
pancake 099cb94abf Initial import of the gamegear emulator 2026-10-29 13:35:02 +01:00
pancake de674fbeb0 Add gameboy emulation documentation 2026-10-29 13:30:02 +01:00
pancake f81d48eaca Add gameboy usleep delays 2026-10-29 13:16:44 +01:00
pancake 610dd48707 Fix standalone r2gb test loading and ignore build outputs 2026-10-27 00:35:12 +01:00
pancake c6663b87e9 Initial import of the r2gb plugin 2026-10-27 00:30:24 +01:00
pancake f7dca9d52b Add asynchronous PCM streaming through auq 2026-10-27 00:28:32 +01:00
pancake f2a4b1dfa0 Fix the arpeggio demo 2026-10-26 23:37:46 +01:00
pancake b5b1101110 Fix the doom song 2026-10-26 23:30:34 +01:00
pancake 445c6a5a57 Fix build of r2au 2026-10-26 23:08:44 +01:00
Ricardo J. Rodríguez 5ab2c6aa7d msl: follow spec 1.1.1 register names and thread states
Thread Context (0x0011) changed in Memory Slice spec 1.1.0/1.1.1:
register names are now normative (Table 19g) and the block gained
Suspended/Partial flags, thread states 0x05-0x07 and a per-thread Arch
byte at +0x13.

debug.msl: map the ARM64 aliases fp/lr (and cpsr) that 1.1.0 producers
could write to x29/x30/pstate when seeding (consumer rule 29), using the
thread's Arch byte with the file header as fallback. `dpt` derives the
status letter from ThreadState (r/S/s/z) instead of only the Current flag.

core.msl (`dgm`): never write the fp/lr aliases on ARM64, tag the frame
pointer, status and link registers via r2's BP/SR/LR aliases, and set
Suspended alongside Current since the registers come from a halted
debuggee.
2026-10-26 18:38:36 +01:00
dependabot[bot] 1e989215d9 Bump libc from 0.2.190 to 0.2.191 in /x86iced
Bumps [libc](https://github.com/rust-lang/libc) from 0.2.190 to 0.2.191.
- [Release notes](https://github.com/rust-lang/libc/releases)
- [Changelog](https://github.com/rust-lang/libc/blob/0.2.191/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/libc/compare/0.2.190...0.2.191)

---
updated-dependencies:
- dependency-name: libc
  dependency-version: 0.2.191
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <[email protected]>
2026-10-26 13:48:46 +01:00
dependabot[bot] a2692a2380 Bump libc from 0.2.172 to 0.2.190 in /x86iced
Bumps [libc](https://github.com/rust-lang/libc) from 0.2.172 to 0.2.190.
- [Release notes](https://github.com/rust-lang/libc/releases)
- [Changelog](https://github.com/rust-lang/libc/blob/0.2.190/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/libc/compare/0.2.172...0.2.190)

---
updated-dependencies:
- dependency-name: libc
  dependency-version: 0.2.190
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <[email protected]>
2026-10-13 08:46:15 +02:00
pancake 614d94959e r2ida: import IDB C types into radare2 scripts 2026-09-27 07:36:17 +02:00
pancake 7a0269097b Fix PowerPC disassembler plugin 2026-09-27 07:14:34 +02:00
pancake c8f032c01d Fix MicroBlaze plugin build 2026-09-27 07:05:38 +02:00
pancake 188d102f6b Initial chrome devtools interface for radare2 2026-08-31 19:22:37 +02:00
Abhi 3275d32127 Build CI plugins from checkout 2026-07-29 15:13:39 +01:00
Abhi f4218097d2 Use radare2 GitHub Action in CI 2026-07-29 15:13:39 +01:00
Abhi 96dbf53b1c Fix x86iced for r2 6.1 ABI 2026-07-29 15:13:39 +01:00
pancake e3111fcba3 Remove the r2jadx attic 2026-06-27 18:51:29 +02:00
dependabot[bot] 5b0ea473f9 Bump libc from 0.2.154 to 0.2.172 in /x86iced
Bumps [libc](https://github.com/rust-lang/libc) from 0.2.154 to 0.2.172.
- [Release notes](https://github.com/rust-lang/libc/releases)
- [Changelog](https://github.com/rust-lang/libc/blob/0.2.172/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/libc/compare/0.2.154...0.2.172)

---
updated-dependencies:
- dependency-name: libc
  dependency-version: 0.2.172
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <[email protected]>
2026-06-27 18:39:34 +02:00
f28a2ec94c Add plugins for memory slice (msl)
* msl: add Memory Slice (.msl) plugins (io/bin/debug/core)

Loadable radare2 plugins for the Memory Slice process-dump format:

- io_msl    open a slice as a process address space (msl://); verifies
            the SHA-256 block chain and End-of-Capture FileHash on open,
            warning on a truncated or tampered slice
- bin_msl   parse a slice as a CORE object (arch/bits/os, entry, maps)
- debug_msl emulated ESIL debug backend, incl. reverse exec (dsb/aesb)
- core_msl  producer: "dgm"/"dgma" write a slice from a live debug session

Build/install with the local Makefile (pkg-config r_core) or via r2pm.
test/genmsl.py emits a valid synthetic slice for exercising the read path.

* msl: select and list captured threads in the debug backend

A slice can capture several threads (one Thread Context block each); the debug
backend only seeded the Current thread. Expose every captured thread:

- .threads callback: `dpt` / `dptj` lists each captured thread with its PC.
- .select callback: `dpt=<tid>` re-seeds the register file from that thread
  and seeks to its captured PC, so any thread can be emulated.

msl_seed_regs now takes a target tid (>=0 exact, <0 Current with first-thread
fallback) and reports the chosen tid, which msl_ensure stores in dbg->tid.

Also fixes a double-unref of the mmap buffer (msl_seed_regs used to unref a
buffer owned by its caller), and accounts for r_debug_select swapping the
register arena after .select returns (seed both arenas so the new thread's
registers survive the swap). test/genmsl.py gains --mt to emit a second,
non-Current thread for exercising listing and selection.

* msl: resolve module symbols and PE exports in bin.msl

The bin plugin presented a slice as maps only. Parse ModuleEntry (0x0002)
blocks and expose them as libraries (`il`) and symbols (`is`): one symbol per
module base plus, for PE images whose headers are captured, one FUNC symbol per
exported function at its address. A VA->file-offset translator over the
captured-run maps reads the module image (DOS/PE headers, export directory).
radare2 then names call targets -- `sym.kernel32.dll_CreateFileW` -- instead of
bare addresses.

test/genmsl.py gains --pe (a minimal in-memory PE export table) and a
memory_region() helper. ELF .dynsym resolution is left to the Python tools.

* msl: note thread listing/selection in the plugin table

The debug.msl row documented reverse execution but not the `dpt` / `dpt=<tid>`
thread listing and selection; mention it for consistency with the body.

---------

Co-authored-by: Ricardo J. Rodríguez <ricardo@thanatos>
Co-authored-by: Claude Opus 4.8 (1M context) <[email protected]>
2026-06-27 09:51:49 +02:00
pancake 80925aeba6 r2jadx: Use r2.log instead of console.log 2026-05-11 15:44:41 +02:00
pancake 45f9bc841c r2jadx: Use better r2js and improve xrefs caching and more 2026-05-11 12:09:41 +02:00
pancake 69f93467a1 r2jadx: refactor into separate files 2026-05-11 07:53:17 +02:00
pancake 67b24be239 r2jadx: add -s to search words 2026-05-11 07:43:26 +02:00
pancake cd9cc5c190 r2jadx: add pd:j alias 2026-05-11 07:26:42 +02:00
pancake 568a7fd146 r2jadx: config -e with optable color and addresses 2026-05-11 07:22:21 +02:00
pancake d276feb5e8 Fix help message for r2jadx 2026-05-11 06:11:22 +02:00
pancake c3b9864f1d Rewrite r2jadx to typescript 2026-05-10 09:57:56 +02:00
Nerijus Bendžiūnas 7a6e3737c8 fix(r2k): allow Linux module to compile using clang
__FORCE_ORDER is a GCC-specific input constraint not supported
by clang. Use a "memory" clobber on clang instead.

Signed-off-by: Nerijus Bendžiūnas <[email protected]>
2026-02-28 17:46:22 +01:00
pancake 430b6fa559 Minor fix for the rar cpu code 2026-01-09 07:29:22 +01:00
pancake 1cf58513ad Fix r2doom build 2025-10-03 23:15:11 +02:00
Takumi Matsuura da8623bdbe Change to prioritize using uv 2025-10-03 13:58:38 +02:00
pancake 43057468c6 Add r2604 badge 2025-09-30 14:07:19 +02:00
pancake 7ed4cb393f Assume keys in afen can have spaces 2025-09-30 14:05:07 +02:00
pancake 031b7c20c0 Implement 'afen*' command to dump the database 2025-09-30 14:01:32 +02:00
pancake 9edd5e922b Release 6.0.0 2025-09-22 18:38:39 +02:00
satk0 dea1f62f8f Remove global var in afen 2025-09-22 15:54:03 +02:00
pancake e9306ef9fe Fix x86iced build for r2-6.0 2025-09-16 17:10:17 +02:00
pancake 941e0e8f81 Fix the VC4 build 2025-09-16 16:41:11 +02:00
satk0 fdcf847944 Make afen work 2025-09-16 15:41:57 +02:00
pancake e9035eda1c Rewrite all the asm plugins into arch ones 2025-09-04 12:08:37 +02:00
pancake f2d4e0d371 Fix vc4 build 2025-09-04 11:17:25 +02:00
pancake f06bef6f21 Do not build afen 2025-09-04 01:06:35 +02:00
pancake aac87e940d Fix build of the bin.gguf plugin 2025-09-02 19:38:24 +02:00
Abhi 6c0afb35c2 r2angr: fix latest cmake issues on termux (#386)
* fix latest cmake issues on termux

Affected packages: unicorn, pypcode

* pin angr version

angr since `9.2.155` moved to rust toolchain, which can't be compiled in termux due to bug in rustc not us.

* Update angr

just in case user installed r2 from package manager

* small fixes

* fix: illegal number

```shell
r2angr: 8: [: Illegal number:
```
2025-08-30 01:39:59 +02:00
pancake 1b276095d4 Add a chiptune song created with r2ai 2025-08-27 18:33:22 +02:00
pancake e90d99b9f4 Add more openai-generated versions of the "doom song" 2025-08-27 18:06:47 +02:00
pancake e0bb03cdd1 Fix r2au for the r2-6.x 2025-08-27 17:38:01 +02:00
pancake 6c9df38c66 FIx vc4 and blackfin 2025-03-13 19:27:49 +01:00
pancake 38e79b50b1 Fix build with latest r2 from git 2025-03-12 16:28:10 +01:00
pancake b03125fc99 Move rlcc from libr/egg/rlcc and shlr/mpc 2025-02-06 23:02:37 +01:00
pancake 36f9503eda Fix gguf plugin name 2025-02-06 19:18:10 +01:00
pancake 3a25b7f345 Fix hexagon install 2024-12-11 15:31:52 +01:00
pancake b91c295be3 Remove awful function and warning from squashfs 2024-12-04 16:47:19 +01:00
pancake 9e4c70872e Fix build of fs-squashfs 2024-12-04 11:50:32 +01:00
pancake 94f8d2dc94 Update build instructions for the r2k plugin 2024-12-02 15:37:00 +01:00
pancake 89624cc37c r2k: Fix write on protected regions, lock RCU when acessing tasks fixing races 2024-12-02 15:32:27 +01:00
NighterMan 42aed83113 Fix r2k-linux build on latest Linux kernels 6.4.x 2024-12-01 23:52:32 +01:00
pancake 4d944cce9a Release 5.9.6 2024-11-05 18:30:09 +01:00
pancake 49a91651d2 Fix invalid pfb string in r2svd when the bitstruct have 0 fields 2024-10-31 08:50:51 +01:00
Roman Valls Guimera 3596e7f1a5 Repoint cmsis-svd repo to upstream cmsis-svd org 2024-10-22 06:52:53 +02:00
Abhi 54ff412976 Fix setup on termux (#367)
* Fix installation on termux
* remove binutils & build-essential
  * They should already be present if the user has installed R2.
* remove un-necessary install
2024-10-21 17:49:49 +02:00
dependabot[bot] 3d2fa7985b Bump serde_json from 1.0.124 to 1.0.132 in /x86iced
Bumps [serde_json](https://github.com/serde-rs/json) from 1.0.124 to 1.0.132.
- [Release notes](https://github.com/serde-rs/json/releases)
- [Commits](https://github.com/serde-rs/json/compare/v1.0.124...1.0.132)

---
updated-dependencies:
- dependency-name: serde_json
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <[email protected]>
2024-10-21 17:49:10 +02:00
pancake 3064bbcb7f Fix license names 2024-10-21 17:48:39 +02:00
pancake 97d8b87bf5 Fix license name for blackfin 2024-10-21 17:48:35 +02:00
pancake 26450ea9b9 Fix the CI 2024-09-30 20:10:22 +02:00
pancake 14d385082c Inverse r2 version check for r2svd 2024-09-30 13:10:12 +02:00
pancake 3a92956545 os.path.join is UB. thank you py3 2024-09-30 12:41:05 +02:00
pancake 5ef0b34d57 Install r2svd with symlink 2024-09-30 12:30:36 +02:00
pancake 57f3c159e0 Setuptools is dead, not just deprecated. workarounding with more hacks 2024-09-30 12:26:21 +02:00
pancake 991ee0f685 Setuptools was deprecated, so we need it now 2024-09-30 12:19:41 +02:00
pancake 4e72a04103 Join paths properly 2024-09-30 12:16:14 +02:00
pancake 9a61bb6f7d Use our cmsis-svd fork 2024-09-30 12:15:39 +02:00
pancake 9c22aa709d Parse register fields and support ascii art stuff for r2svd 2024-09-29 19:23:14 +02:00
Roman Valls Guimera ccefb4237d Fix setuptools deprecations and switch to version-1.0 of cmsis_svd 2024-09-29 12:11:59 +02:00
Roman Valls Guimera ef93ab4c91 Deprecate setuptools:
% r2svd --help
/Users/rvalls/.local/share/radare2/prefix/bin/r2svd:9: DeprecationWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html
  import pkg_resources
2024-09-29 12:11:59 +02:00
sha0coder 496b46918b r2ida first version 2024-09-27 22:05:03 +02:00
Nitan Alexandru Marcel 82b3a8e97d Use TMPDIR env or fallback to /tmp for temporary log file (#360) 2024-09-05 16:27:41 +02:00
pancake 0350bec1e7 One venv for angr and arg for structurer 2024-08-31 16:18:57 +02:00
pancake 6e06bcd365 Force the latest capstone to fix angr on arm64 boxes 2024-08-31 16:11:48 +02:00
pancake b170500a27 Honor R2_BADDR in r2angr if set 2024-08-29 20:54:47 +02:00
pancake ece2da866a Show r2poke version 2024-08-29 20:53:41 +02:00
pancake fecf53943b Enable the alien tokens for gnupoke4 2024-08-29 20:53:36 +02:00
pancake dda5cb2d70 Improved output and hints for r2angr 2024-08-29 18:31:16 +02:00
pancake ebe772353a oops 2024-08-29 18:22:22 +02:00
pancake d6f4f63aca Add r2angr wrapper script for decompiling 2024-08-29 17:55:45 +02:00
pancake 343dce1014 atombios not ported, but at least dont break the build 2024-08-26 10:55:50 +02:00
dependabot[bot] 3bb3fbf753 Bump serde from 1.0.201 to 1.0.208 in /x86iced
Bumps [serde](https://github.com/serde-rs/serde) from 1.0.201 to 1.0.208.
- [Release notes](https://github.com/serde-rs/serde/releases)
- [Commits](https://github.com/serde-rs/serde/compare/v1.0.201...v1.0.208)

---
updated-dependencies:
- dependency-name: serde
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <[email protected]>
2024-08-19 10:53:02 +02:00
dependabot[bot] 42131f6bd6 Bump serde_json from 1.0.117 to 1.0.124 in /x86iced
Bumps [serde_json](https://github.com/serde-rs/json) from 1.0.117 to 1.0.124.
- [Release notes](https://github.com/serde-rs/json/releases)
- [Commits](https://github.com/serde-rs/json/compare/v1.0.117...v1.0.124)

---
updated-dependencies:
- dependency-name: serde_json
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <[email protected]>
2024-08-19 09:25:47 +02:00
satk0 663b25a8fc Make afen function specific (#351) 2024-08-01 22:43:01 +02:00
pancake b0f48b0194 Support GNU Poke4 for r2poke 2024-07-11 17:08:10 +02:00
satk0 6e4ece2732 Fix rparse to rcore binding for afen (#346) 2024-06-25 18:07:32 +02:00
Sylvain Pelissier 628a9d20d0 Update ci.yml with afen plugin
Add r2afen build in CI.
2024-05-22 08:16:50 +02:00
311 changed files with 376799 additions and 18785 deletions

No files matched your search

+15 -35
View File
@@ -12,24 +12,17 @@ jobs:
name: Build radare2 extras and r2pipe
runs-on: ubuntu-22.04
env:
BUILDS: 'asahi blackfin blessr2 keystone-lib keystone r2svd unicorn-lib vc4 x86iced'
TESTS: 'keystone vc4'
R2PIPE_TESTS: 'r2pipe-js r2pipe-py'
EXTERNAL_BUILDS: 'keystone-lib unicorn-lib'
LOCAL_BUILDS: 'asahi blackfin blessr2 keystone microblaze ppcdisasm r2svd vc4 x86iced'
steps:
- uses: actions/checkout@v3
with:
repository: radareorg/radare2
ref: master
path: ./radare2
- name: Install dependencies
run: |
sudo apt-get --assume-yes update
sudo apt-get --assume-yes install libjansson-dev libboost-dev libcurl4-openssl-dev python3-wheel python3-setuptools && sudo pip3 install meson ninja
- name: Install radare2
run: |
export PATH=$PATH:/usr/local/bin
meson --prefix=/usr --buildtype=release build && ninja -C build && sudo ninja -C build install
working-directory: radare2
- uses: radareorg/github-actions@v3
with:
from-git: true
- uses: actions/checkout@v3
with:
ref: ${{ github.event.pull_request.head.sha }}
@@ -39,32 +32,19 @@ jobs:
- name: Compile and install plugins
run: |
set -e
export R2PM_GITDIR=`pwd`
export R2PM_GITSKIP=1
for p in $BUILDS ; do
for p in $EXTERNAL_BUILDS ; do
echo $p
r2pm -i $p
done
set +e
R2PM_GITDIR="$(r2pm -H R2PM_GITDIR)"
for p in $LOCAL_BUILDS ; do
echo $p
ln -s "$GITHUB_WORKSPACE/radare2-extras" "$R2PM_GITDIR/$p"
R2PM_OFFLINE=1 r2pm -i $p
done
make -C radare2-extras/mn103 install
- name: Test plugins
working-directory: radare2/test
run: |
set -e
export R2PM_GITDIR=`pwd`
export R2PM_GITSKIP=1
for p in $TESTS ; do
echo $p
make $p
done
set +e
- name: Compile and install r2pipe
run: |
set -e
export R2PM_GITDIR=`pwd`
export R2PM_GITSKIP=1
for p in $R2PIPE_TESTS ; do
echo $p
r2pm -i $p
done
set +e
make keystone
r2r -u "$GITHUB_WORKSPACE/radare2-extras/test/db/extras"
+13 -11
View File
@@ -1,6 +1,7 @@
radare2-extras
==============
# radare2-extras
[![GithubCI Status](https://github.com/radareorg/radare2-extras/actions/workflows/ci.yml/badge.svg?branch=master)](https://github.com/radareorg/radare2-extras/actions?query=workflow%3A%22ci%22)
[![radare2](https://img.shields.io/badge/radare2-6.0.4-green)](https://github.com/radareorg/radare2)
This repository contains extra plugins for radare2.
@@ -14,13 +15,6 @@ repository are the following:
* Duplicates functionality from r2 (no need to have
multiple disassemblers for the same arch in core)
The compiled plugins will be installed at
/usr/lib/radare2-extras/$(VERSION)
Some of the plugins/code doesnt compiles, it will be reviewed
and cleaned up, merged into core, updated or removed.
In addition, this repository will be useful to new contributors,
comers who want to write his own r2 plugins for example.
@@ -29,8 +23,16 @@ repository to be as concise as possible, and reduce the
amount of unnecessary plugins to shrink the install size and
keep it usable for 99% of users.
Building
========
## Building
The recommended way to build and install those plugins for users
is to use r2pm. See the [radare2 plugins](https://github.com/radareorg/radare2#plugins) documentation for details.
## Notable plugins
* [`msl`](msl/) — Memory Slice (`.msl`) support: open/emulate process memory
dumps (`io`/`bin`/`debug` plugins, with ESIL reverse execution) and produce
them from a live debug session (`dgm`/`dgma`, `core` plugin).
* [`r2gg`](r2gg/) — Game Gear emulation through Z80 ESIL, with color terminal
display, controls, Sega cartridge banking, interrupts, and stereo PSG audio.
+3 -3
View File
@@ -13,15 +13,15 @@ to any text, thus enabling a creation of variables from expressions.
Build:
r2pm -r meson build
r2pm -r meson setup build
Install:
meson install -C build
## Running:
## Run:
r2 -e asm.pseudo=true <file>
r2 -e asm.parser=afen -e asm.pseudo=true <file>
## Usage:
+221 -46
View File
@@ -4,74 +4,246 @@
#include <r_core.h>
static RList *old_names;
static RList *new_names;
typedef struct RAfenRepl {
char *old_name;
char *new_name;
} RAfenRepl;
// afen parser
static int r_afen_parse(RParse *p, const char *data, char *str) {
int res = true;
char *input = strdup (data);
#if R2_VERSION_NUMBER >= 50909
#else
static R_TH_LOCAL HtUP *ht; // hash table
#endif
int n = r_list_length(old_names);
#if R2_VERSION_NUMBER >= 50909
static void fini(RAsmPluginSession *aps) {
RParse *p = aps->rasm->parse;
R_FREE (p->retleave_asm);
}
#endif
if (n){
RListIter *s_iter_old = NULL;
RListIter *s_iter_new = NULL;
s_iter_old = old_names->head;
s_iter_new = new_names->head;
for (int i = 0; i < n; ++i) {
input = r_str_replace_all (input, s_iter_old->data, s_iter_new->data);
s_iter_old = r_list_iter_get_next(s_iter_old);
s_iter_new = r_list_iter_get_next(s_iter_new);
static char *parse(RCore *core, const char *data, HtUP *ht) {
char *out = strdup (data);
#if R2_VERSION_NUMBER >= 50909
RAnalFunction *fcn = r_anal_get_function_at (core->anal, core->addr);
#else
RAnalFunction *fcn = r_anal_get_function_at (core->anal, core->offset);
#endif
if (fcn) {
RVector *vec = ht_up_find (ht, fcn->addr, NULL);
if (vec) {
RAfenRepl *repl;
r_vector_foreach (vec, repl) {
out = r_str_replace_all (out, repl->old_name, repl->new_name);
}
}
}
return out;
}
// afen parser
#if R2_VERSION_NUMBER >= 50909
static char *r_parse_afen(RAsmPluginSession *aps, const char *data) {
char* out = parse ((RCore *) aps->rasm->user, data, aps->data);
return out;
}
#else
static int r_parse_afen(RParse *p, const char *data, char *str) {
char* out = parse ((RCore *) p->analb.anal->user, data, ht);
strcpy (str, out);
return true;
}
#endif
// RParse plugin Definition Info
#if R2_VERSION_NUMBER >= 50909
RAsmPlugin r_parse_plugin_afen = {
.meta = {
.name = "afen",
.desc = "Afen parse plugin",
},
.parse = r_parse_afen,
.fini = fini,
// .subvar = subvar,
};
#else
RParsePlugin r_parse_plugin_afen = {
.name = "afen",
.desc = "Afen parse plugin",
.parse = r_parse_afen,
};
#endif
static inline void repl_free_afen(void *e, void *user ) {
RAfenRepl *repl = (RAfenRepl *) e;
if (repl) {
R_FREE (repl->old_name);
R_FREE (repl->new_name);
}
}
static inline void vector_value_free_afen(HtUPKv *kv) {
RVector *vec = (RVector *) kv->value;
if (vec) {
r_vector_free (vec);
}
}
static bool print_afen_rules(void *user, const ut64 key, const void *value) {
RCore *core = (RCore *) user;
RVector *vec = (RVector *) value;
RAfenRepl *repl;
r_vector_foreach (vec, repl) {
r_cons_printf (core->cons, "'@0x%08"PFMT64x"'afen \"%s\" \"%s\"\n", key, repl->new_name, repl->old_name);
}
return true;
}
// setup afen parser
#if R2_VERSION_NUMBER >= 50909
static bool r_core_init_afen(RCorePluginSession *cps) {
RCore *core = (RCore *) cps->core;
r_asm_plugin_add (core->rasm, &r_parse_plugin_afen);
RAsmPluginSession *afen_aps = NULL;
RListIter *iter;
RAsmPluginSession *aps;
r_list_foreach (core->rasm->sessions, iter, aps) {
if (aps && aps->plugin && aps->plugin->meta.name &&
!strcmp(aps->plugin->meta.name, "afen")) {
afen_aps = aps;
break;
}
}
if (!afen_aps) {
R_LOG_ERROR ("Failed to find afen plugin session");
return false;
}
strcpy (str, input);
return res;
}
HtUP /*<ut64, RVector<RAfenRepl*>>*/ *ht = ht_up_new (NULL, vector_value_free_afen, NULL);
if (!ht) {
R_LOG_ERROR ("Fail to initialize hashtable");
ht_up_free (ht);
return false;
}
afen_aps->data = ht;
cps->data = ht;
// sets afen parser
static int r_cmd_init(void *user, const char *input) {
return true;
}
#else
static bool r_core_init_afen(void *user, const char *input) {
RCmd *rcmd = (RCmd *) user;
RCore *core = (RCore *) rcmd->data;
old_names = r_list_new ();
new_names = r_list_new ();
core->parser->cur->parse = r_afen_parse;
return true;
}
r_parse_plugin_add (core->parser, &r_parse_plugin_afen);
static int r_cmd_fini(void *user, const char *input) {
r_list_free(old_names);
r_list_free(new_names);
/*<ut64, RVector<RAfenRepl*>>*/ ht = ht_up_new (NULL, vector_value_free_afen, NULL);
if (!ht) {
R_LOG_ERROR ("Fail to initialize hashtable");
ht_up_free (ht);
return false;
}
return true;
}
#endif
static int r_cmd_afen_client(void *user, const char *input) {
if (r_str_startswith (input, "afen")) {
int *argc = (int*) malloc(sizeof(int));
char **argv = r_str_argv(input, argc);
#if R2_VERSION_NUMBER >= 50909
static bool r_core_fini_afen(RCorePluginSession *cps) {
HtUP *ht = cps->data;
ht_up_free (ht);
ht = NULL;
if (*argc != 3) {
r_cons_printf("Usage: afen new_name old_name\n");
return true;
}
#else
static bool r_core_fini_afen(void *user, const char *input) {
ht_up_free (ht);
ht = NULL;
return true;
}
#endif
static bool check_for_afen_command(RCore *core, const char *input, HtUP *ht) {
if (r_str_startswith (input, "afen*")) {
ht_up_foreach(ht, print_afen_rules, core);
return true;
} else if (r_str_startswith (input, "afen")) {
int argc = 0;
char **argv = r_str_argv (input, &argc);
if (!argv || argc != 3) {
R_LOG_INFO ("Usage: afen new_name old_name");
r_str_argv_free (argv);
return true;
}
#if R2_VERSION_NUMBER >= 50909
RAnalFunction *fcn = r_anal_get_function_at (core->anal, core->addr);
#else
RAnalFunction *fcn = r_anal_get_function_at (core->anal, core->offset);
#endif
if (!fcn) {
#if R2_VERSION_NUMBER >= 50909
R_LOG_ERROR ("No Function at 0x%08" PFMT64x, core->addr);
#else
R_LOG_ERROR ("No Function at 0x%08" PFMT64x, core->offset);
#endif
R_LOG_INFO ("Use afen inside a function!");
r_str_argv_free (argv);
return false;
}
RVector *vec = ht_up_find (ht, fcn->addr, NULL);
if (!vec) {
vec = r_vector_new (sizeof (RAfenRepl), repl_free_afen, NULL);
ht_up_insert (ht, fcn->addr, vec);
}
bool updated = false;
RAfenRepl *repl;
r_vector_foreach (vec, repl) {
if (repl->old_name && argv[2] && !strcmp (repl->old_name, argv[2])) {
if (repl->new_name) {
R_FREE (repl->new_name);
}
repl->new_name = strdup (argv[1]);
updated = true;
break;
}
}
if (updated) {
r_str_argv_free (argv);
return true;
}
r_list_append(new_names, argv[1]);
r_list_append(old_names, argv[2]);
repl = R_NEW0 (RAfenRepl);
repl->new_name = strdup (argv[1]);
repl->old_name = strdup (argv[2]);
r_vector_push (vec, repl);
r_str_argv_free (argv);
return true;
}
return false;
}
// PLUGIN Definition Info
#if R2_VERSION_NUMBER >= 50909
static bool r_core_call_afen(RCorePluginSession *cps, const char *input) {
return check_for_afen_command(cps->core, input, cps->data);
}
#else
static bool r_core_call_afen(void *user, const char *input) {
return check_for_afen_command((RCore *) user, input, ht);
}
#endif
// RCore plugin Definition Info
RCorePlugin r_core_plugin_afen = {
.meta = {
.name = "core-afen",
@@ -79,9 +251,9 @@ RCorePlugin r_core_plugin_afen = {
.author = "satk0",
.license = "GPLv3",
},
.call = r_cmd_afen_client,
.init = r_cmd_init,
.fini = r_cmd_fini
.call = r_core_call_afen,
.init = r_core_init_afen,
.fini = r_core_fini_afen
};
@@ -89,6 +261,9 @@ RCorePlugin r_core_plugin_afen = {
R_API RLibStruct radare_plugin = {
.type = R_LIB_TYPE_CORE,
.data = &r_core_plugin_afen,
.version = R2_VERSION
.version = R2_VERSION,
#if R2_VERSION_NUMBER >= 50909
.abiversion = R2_ABIVERSION,
#endif
};
#endif
Vendored
+31 -10
View File
@@ -1,5 +1,5 @@
#!/bin/sh
# This script was automatically generated by ACR v2.1.4
# This script was automatically generated by ACR v2.2.4
# @author: pancake <nopcode.org>
# @url: http://www.nopcode.org
# @repo: git clone https://github.com/radare/acr
@@ -67,13 +67,27 @@ if [ -e "${VPATH}/config.guess" ]; then
sh ${VPATH}/config.guess
return
fi
CPU="`uname -m|sed -e 's, ,,g'|cut -d - -f 1`"
CPU="`uname -m | tr 'A-Z' 'a-z' | sed -e 's, ,,g' | cut -d - -f 1`"
OS="`uname -s|tr A-Z a-z`"
uname -r | grep -qE "(Microsoft|WSL)" 2>/dev/null && OS="wsl"
GNU="`uname --help 2>&1 | grep gnu`"
[ "${GNU}" ] && OS="${OS}-gnu"
[ "${CPU}" = ppc ] && CPU="powerpc"
echo "${CPU}-unknown-${OS}"
# normalize CPU
case "${CPU}" in
ppc*|powermac*|powermacintosh*|powerpc*)
if echo "${CPU}" | grep -q '64'; then
CPU=powerpc64
else
CPU=powerpc
fi
;;
*) ;;
esac
VENDOR="unknown"
if [ "${OS}" = "darwin" ]; then
VENDOR=apple
fi
echo "${CPU}-${VENDOR}-${OS}"
}
SEARCHPATH="/usr /usr/local /usr/pkg /sw"
@@ -114,12 +128,12 @@ done
: ${INSTALL_PROGRAM_STRIP:=${INSTALL} -m 755 -s}
: ${INSTALL_MAN:=${INSTALL} -m 444}
: ${INSTALL_LIB:=${INSTALL} -m 755 -c}
PKGNAME='radare2-extras' ; VERSION='5.9.0' ; VERSION_MAJOR=5; VERSION_MINOR=9; VERSION_PATCH=0; VERSION_NUMBER=50900; CONTACT_MAIL="[email protected]" ; CONTACT_NAME="pancake" ; CONTACT="pancake <[email protected]>" ;
PKGNAME='radare2-extras' ; VERSION='6.0.0' ; VERSION_MAJOR=6; VERSION_MINOR=0; VERSION_PATCH=0; VERSION_NUMBER=60000; CONTACT_MAIL="[email protected]" ; CONTACT_NAME="pancake" ; CONTACT="pancake <[email protected]>" ;
}
show_usage() {
cat <<EOF2
'configure' configures radare2-extras-5.9.0 to adapt to many kinds of systems.
'configure' configures radare2-extras-6.0.0 to adapt to many kinds of systems.
Usage: ./configure [OPTION]... [VAR=VALUE]...
@@ -201,10 +215,10 @@ ocho() {
show_version() {
if [ "$QUIET" = 1 ]; then
echo "5.9.0"
echo "6.0.0"
exit 0
fi
echo "radare2-extras-5.9.0 configuration script done with acr v2.1.4.
echo "radare2-extras-6.0.0 configuration script done with acr v2.2.4.
The 'Free Software Foundation' message is only for autodetection.
Originally written by pancake <nopcode.org>."
exit 0
@@ -233,7 +247,7 @@ case $flag in
show_version ; ;;
-r|--r|--report)
echo "PKGNAME: radare2-extras"
echo "VERSION: 5.9.0"
echo "VERSION: 6.0.0"
echo "AUTHOR: pancake"
echo "EMAIL: [email protected]"
echo "LANGS: c"
@@ -455,7 +469,14 @@ for A in ${ENVWORDS} ; do
[ "${A}" = VPATH ] && continue
[ "${A}" = srcdir ] && continue
eval "VAR=\$${A}"
VAR="`echo ${VAR} | sed -e 's/\,/\\\,/g'`"
case "" in
mingw*|cygwin*|msys*)
VAR="`echo ${VAR} | sed -e 's/\\/\\\\/g' -e 's/\,/\\\,/g'`"
;;
*)
VAR="`echo ${VAR} | sed -e 's/\,/\\\,/g'`"
;;
esac
[ $COUNT = 10 ] && COUNT=0 && SEDFLAGS="${SEDFLAGS}' -e '"
COUNT=$(($COUNT+1))
SEDFLAGS="${SEDFLAGS}s,@${A}@,${VAR},g;"
+1 -1
View File
@@ -1,5 +1,5 @@
PKGNAME radare2-extras
VERSION 5.9.0
VERSION 6.0.0
CONTACT pancake ; [email protected]
USE_PKGCONFIG!
+27 -6
View File
@@ -1,5 +1,5 @@
#!/bin/sh
# This script was automatically generated by ACR v2.1.4
# This script was automatically generated by ACR v2.2.4
# @author: pancake <nopcode.org>
# @url: http://www.nopcode.org
# @repo: git clone https://github.com/radare/acr
@@ -65,13 +65,27 @@ if [ -e "${VPATH}/config.guess" ]; then
sh ${VPATH}/config.guess
return
fi
CPU="`uname -m|sed -e 's, ,,g'|cut -d - -f 1`"
CPU="`uname -m | tr 'A-Z' 'a-z' | sed -e 's, ,,g' | cut -d - -f 1`"
OS="`uname -s|tr A-Z a-z`"
uname -r | grep -qE "(Microsoft|WSL)" 2>/dev/null && OS="wsl"
GNU="`uname --help 2>&1 | grep gnu`"
[ "${GNU}" ] && OS="${OS}-gnu"
[ "${CPU}" = ppc ] && CPU="powerpc"
echo "${CPU}-unknown-${OS}"
# normalize CPU
case "${CPU}" in
ppc*|powermac*|powermacintosh*|powerpc*)
if echo "${CPU}" | grep -q '64'; then
CPU=powerpc64
else
CPU=powerpc
fi
;;
*) ;;
esac
VENDOR="unknown"
if [ "${OS}" = "darwin" ]; then
VENDOR=apple
fi
echo "${CPU}-${VENDOR}-${OS}"
}
SEARCHPATH="/usr /usr/local /usr/pkg /sw"
@@ -201,7 +215,7 @@ if [ "$QUIET" = 1 ]; then
echo "0.2"
exit 0
fi
echo "radare2-keystone-0.2 configuration script done with acr v2.1.4.
echo "radare2-keystone-0.2 configuration script done with acr v2.2.4.
The 'Free Software Foundation' message is only for autodetection.
Originally written by pancake <nopcode.org>."
exit 0
@@ -415,7 +429,14 @@ for A in ${ENVWORDS} ; do
[ "${A}" = VPATH ] && continue
[ "${A}" = srcdir ] && continue
eval "VAR=\$${A}"
VAR="`echo ${VAR} | sed -e 's/\,/\\\,/g'`"
case "" in
mingw*|cygwin*|msys*)
VAR="`echo ${VAR} | sed -e 's/\\/\\\\/g' -e 's/\,/\\\,/g'`"
;;
*)
VAR="`echo ${VAR} | sed -e 's/\,/\\\,/g'`"
;;
esac
[ $COUNT = 10 ] && COUNT=0 && SEDFLAGS="${SEDFLAGS}' -e '"
COUNT=$(($COUNT+1))
SEDFLAGS="${SEDFLAGS}s,@${A}@,${VAR},g;"
+1
View File
@@ -16,6 +16,7 @@ all: arch_hexagon.${SO}
arch_hexagon.$(SO): $(OBJS)
$(CC) -shared -fPIC -o arch_hexagon.$(SO) $(OBJS) $(LDFLAGS)
rm -f $(PD)/arch_hexagon.$(SO)
mkdir -p $(PD)
cp -f arch_hexagon.$(SO) $(PD)/arch_hexagon.$(SO)
clean:
+3
View File
@@ -1,5 +1,8 @@
R2PM_PLUGDIR ?=$(HOME)/.config/radare2/plugins
all:
@echo
atombios:
cd p ; $(MAKE) asm_atombios.$(LIBEXT)
+1 -1
View File
@@ -90,7 +90,7 @@ static int m32c_op(RAnal *anal, RAnalOp *op, ut64 addr, const ut8 *b, int len, R
RAnalPlugin r_anal_plugin_m32c = {
.name = "m32c",
.desc = "m32c analysis plugin",
.license = "LGPL3",
.license = "LGPL-3.0-only",
.arch = "m32c",
.esil = false,
.bits = 32,
+1 -1
View File
@@ -94,7 +94,7 @@ RAsmPlugin r_asm_plugin_m32c_gnu = {
.name = "m32c.gnu",
.arch = "m32c",
.author = "pancake",
.license = "GPL3",
.license = "GPL-3.0-only",
.bits = 16 | 32,
.endian = R_SYS_ENDIAN_LITTLE,
.desc = "M32C CPU",
+10
View File
@@ -0,0 +1,10 @@
# build artifacts
*.o
*.dylib
*.so
*.a
# editor / assistant caches
.pmai/
.DS_Store
build/
+68
View File
@@ -0,0 +1,68 @@
# Build the r2 vc4 asm/anal plugin straight from this directory.
# Mirrors libr/asm/p/vc4.mk + libr/plugs.mk but works standalone.
CC?=cc
VC4DIR=$(shell pwd)
PLUGDIR=$(abspath $(VC4DIR)/../../p)
PLUGSRC=$(PLUGDIR)/arch_vc4.c
R2_CFLAGS?=$(shell pkg-config --cflags r_arch r_asm r_util 2>/dev/null || pkg-config --cflags r_asm r_util 2>/dev/null || echo -I$(shell r2 -H R2_INCDIR 2>/dev/null))
R2_LDFLAGS?=$(shell pkg-config --libs r_arch r_asm r_util 2>/dev/null || pkg-config --libs r_asm r_util 2>/dev/null || echo -L$(shell r2 -H R2_LIBDIR 2>/dev/null) -lr_anal -lr_arch -lr_asm -lr_util)
R2HOME?=$(shell r2 -H R2_USER_PLUGINS 2>/dev/null || echo $(HOME)/.local/share/radare2/plugins)
UNAME_S?=$(shell uname -s)
ifeq ($(UNAME_S),Darwin)
LIBEXT?=dylib
else
LIBEXT?=so
endif
TARGET=arch_vc4.$(LIBEXT)
PSEUDO=asm_vc4.$(LIBEXT)
CFLAGS+=$(R2_CFLAGS)
CFLAGS+=-g -O2 -Wall -fPIC
CFLAGS+=-I$(VC4DIR) -I$(VC4DIR)/include -I$(VC4DIR)/include/opcode
CFLAGS+=-I$(VC4DIR)/../include
LDFLAGS+=$(R2_LDFLAGS) -lr_anal
LDFLAGS+=-shared
OBJ=arch_vc4.o \
vc4-dis.o vc4-asm.o vc4-desc.o vc4-ibld.o vc4-opc.o \
cgen-bitset.o cgen-dis.o cgen-asm.o cgen-opc.o
all: $(TARGET) $(PSEUDO)
%.o: %.c
$(CC) -c $(CFLAGS) $< -o $@
# binutils/cgen generated sources use the dashes in their names
vc4-%.o: vc4-%.c
$(CC) -c $(CFLAGS) $< -o $@
# the r2 glue lives in libr/asm/p/
arch_vc4.o: $(PLUGSRC) vc4_anal.inc.c
$(CC) -c $(CFLAGS) $(PLUGSRC) -o $@
$(TARGET): $(OBJ)
$(CC) -o $(TARGET) $(OBJ) $(LDFLAGS)
$(PSEUDO): pseudo.o
$(CC) -o $(PSEUDO) pseudo.o $(LDFLAGS)
install: $(TARGET) $(PSEUDO)
mkdir -p $(R2HOME)
cp -f $(TARGET) $(R2HOME)
-codesign -f -s - $(R2HOME)/$(TARGET) 2>/dev/null || true
uninstall:
rm -f $(R2HOME)/$(TARGET) $(R2HOME)/$(PSEUDO)
clean:
rm -f $(OBJ) $(TARGET) pseudo.o $(PSEUDO)
mrproper: clean
$(MAKE) -C libvc4 clean 2>/dev/null || true
.PHONY: all install uninstall clean mrproper
+16
View File
@@ -0,0 +1,16 @@
/* Minimal safe-ctype.h for the vc4 cgen sources, avoids depending on
libiberty's _sch_istable. */
#ifndef SAFE_CTYPE_H
#define SAFE_CTYPE_H
#include <ctype.h>
#define ISALNUM(c) isalnum ((unsigned char) (c))
#define ISALPHA(c) isalpha ((unsigned char) (c))
#define ISDIGIT(c) isdigit ((unsigned char) (c))
#define ISSPACE(c) isspace ((unsigned char) (c))
#define TOLOWER(c) tolower ((unsigned char) (c))
#define TOUPPER(c) toupper ((unsigned char) (c))
#endif
+2
View File
@@ -28,6 +28,8 @@
file (check in a non-ANSI environment!), it should be. */
#include "ansidecl.h"
#include <stdlib.h>
#include <string.h>
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
+291
View File
@@ -0,0 +1,291 @@
/* radare - LGPL - Copyright 2026 - pancake */
#include <r_asm.h>
static const char *pseudo_rules[] = {
"mov/2/$1 = $2",
"add/2/$1 += $2",
"add/3/$1 = $2 + $3",
"sub/2/$1 -= $2",
"sub/3/$1 = $2 - $3",
"rsub/2/$1 = $2 - $1",
"rsub/3/$1 = $3 - $2",
"mul/2/$1 *= $2",
"mul/3/$1 = $2 * $3",
"div/3/$1 = $2 / $3",
"mulhd/3/$1 = ($2 * $3) >> 32",
"and/2/$1 &= $2",
"and/3/$1 = $2 & $3",
"or/2/$1 |= $2",
"or/3/$1 = $2 | $3",
"eor/2/$1 ^= $2",
"eor/3/$1 = $2 ^ $3",
"bic/2/$1 &= ~$2",
"bic/3/$1 = $2 & ~$3",
"not/2/$1 = ~$2",
"neg/2/$1 = -$2",
"abs/2/$1 = abs ($2)",
"shl/2/$1 <<= $2",
"shl/3/$1 = $2 << $3",
"lsr/2/$1 >>= $2",
"lsr/3/$1 = $2 >> $3",
"asr/2/$1 = (st32)$1 >> $2",
"asr/3/$1 = (st32)$2 >> $3",
"ror/2/$1 = ror ($1, $2)",
"ror/3/$1 = ror ($2, $3)",
"min/2/$1 = min ($1, $2)",
"min/3/$1 = min ($2, $3)",
"max/2/$1 = max ($1, $2)",
"max/3/$1 = max ($2, $3)",
"bitset/2/$1 |= 1 << $2",
"bitset/3/$1 = $2 | (1 << $3)",
"bitclear/2/$1 &= ~(1 << $2)",
"bitclear/3/$1 = $2 & ~(1 << $3)",
"bitflip/2/$1 ^= 1 << $2",
"bitflip/3/$1 = $2 ^ (1 << $3)",
"btest/2/flags = $1 & (1 << $2)",
"bmask/2/$1 &= (1 << $2) - 1",
"bmask/3/$1 = $2 & ((1 << $3) - 1)",
"signext/2/$1 = signext ($1, $2)",
"signext/3/$1 = signext ($2, $3)",
"addscale/2/$1 += $2",
"addscale/3/$1 = $2 + $3",
"subscale/2/$1 -= $2",
"subscale/3/$1 = $2 - $3",
"adds/3/$1 = sat ($2 + $3)",
"subs/3/$1 = sat ($2 - $3)",
"msb/2/$1 = msb ($2)",
"count/2/$1 = popcount ($2)",
"brev/2/$1 = bitreverse ($2)",
"clamp16/2/$1 = clamp16 ($2)",
"cmp/2/flags = $1 - $2",
"cmn/2/flags = $1 + $2",
"fadd/3/$1 = $2 + $3",
"fsub/3/$1 = $2 - $3",
"frsub/3/$1 = $3 - $2",
"fmul/3/$1 = $2 * $3",
"fnmul/3/$1 = -($2 * $3)",
"fdiv/3/$1 = $2 / $3",
"fmax/3/$1 = fmax ($2, $3)",
"fmin/3/$1 = fmin ($2, $3)",
"fabs/2/$1 = fabs ($2)",
"frcp/2/$1 = 1 / $2",
"frsqrt/2/$1 = 1 / sqrt ($2)",
"fceil/2/$1 = ceil ($2)",
"ffloor/2/$1 = floor ($2)",
"flog2/2/$1 = log2 ($2)",
"fexp2/2/$1 = exp2 ($2)",
"fcmp/2/flags = $1 - $2",
"ftrunc/3/$1 = (int)($2 $3)",
"floor/3/$1 = (int)floor ($2 $3)",
"flts/3/$1 = (float)($2 $3)",
"fltu/3/$1 = (float)(unsigned)($2 $3)",
"lea/2/$1 = &$2",
"ld/2/$1 = (ut32)$2",
"ldh/2/$1 = (ut16)$2",
"ldsh/2/$1 = (st16)$2",
"ldb/2/$1 = (ut8)$2",
"ldsb/2/$1 = (st8)$2",
"st/2/(ut32)$2 = $1",
"sth/2/(ut16)$2 = $1",
"stb/2/(ut8)$2 = $1",
"b/1/goto $1",
"j/1/goto $1",
"bl/1/$1 ()",
"jl/1/$1 ()",
"tbb/1/goto table8[$1]",
"tbh/1/goto table16[$1]",
"version/1/$1 = cpuid",
"rts/0/return",
"rti/0/return from interrupt",
"swi/1/syscall ($1)",
"bkpt/0/breakpoint",
"ei/0/enable interrupts",
"di/0/disable interrupts",
"nop/0/",
NULL
};
// condition suffix and the operator used by compare and branch forms
static const char *conds[][2] = {
{ "eq", "==" }, { "ne", "!=" }, { "lt", "<" }, { "le", "<=" },
{ "gt", ">" }, { "ge", ">=" }, { "hi", ">u" }, { "ls", "<=u" },
{ "cs", "<u" }, { "lo", "<u" }, { "cc", ">=u" }, { "hs", ">=u" },
{ "mi", NULL }, { "pl", NULL }, { "vs", NULL }, { "vc", NULL },
{ "f", NULL }, { NULL, NULL }
};
static int cond_index(const char *s) {
int i;
for (i = 0; conds[i][0]; i++) {
if (!strcmp (s, conds[i][0])) {
return i;
}
}
return -1;
}
// "(r1+8)" -> "[r1 + 8]", "(r1)" -> "[r1]", "#imm" -> "imm"
static char *normalize(const char *data) {
RStrBuf *sb = r_strbuf_new ("");
const char *p;
for (p = data; *p; p++) {
if (*p == '#') {
continue;
}
if (*p == '(' && p > data && (p[-1] == ',' || p[-1] == ' ')) {
const char *close = strchr (p, ')');
if (close) {
char *in = r_str_ndup (p + 1, close - p - 1);
in = r_str_replace (in, "+-", " - ", 1);
in = r_str_replace (in, "+", " + ", 1);
in = r_str_replace (in, " + + ", "++", 1);
r_strbuf_appendf (sb, "[%s]", in);
free (in);
p = close;
continue;
}
}
r_strbuf_append_n (sb, p, 1);
}
return r_strbuf_drain (sb);
}
static char *transform(const char *data) {
char *res = r_str_pseudo_transform (pseudo_rules, data);
if (res && strcmp (res, data)) {
return res;
}
free (res);
return NULL;
}
// "addcmpb<cond> a,b,c,dst" and "b<cond> a,b,dst" compare after the add
static char *cmpbranch(const char *str, const char *cond, const char *op, bool add) {
char *rule;
if (!strcmp (cond, "f")) {
rule = add? strdup ("x/4/$1 += $2"): strdup ("x/3/");
} else if (add) {
rule = op? r_str_newf ("x/4/$1 += $2; if ($1 %s $3) goto $4", op)
: r_str_newf ("x/4/$1 += $2; if (%s ($1 - $3)) goto $4", cond);
} else {
rule = op? r_str_newf ("x/3/if ($1 %s $2) goto $3", op)
: r_str_newf ("x/3/if (%s ($1 - $2)) goto $3", cond);
}
const char *rules[] = { rule, NULL };
const char *args = strchr (str, ' ');
char *s = r_str_newf ("x%s", args? args: "");
char *res = r_str_pseudo_transform (rules, s);
free (s);
free (rule);
return res;
}
// r_str_pseudo_transform turns "a + -1" into "a -1", make it "a - 1"
static char *fix_minus(char *s) {
RStrBuf *sb = r_strbuf_new ("");
char *p;
for (p = s; *p; p++) {
r_strbuf_append_n (sb, p, 1);
if (p > s && p[0] == ' ' && p[1] == '-' && isdigit ((ut8)p[2]) && isalnum ((ut8)p[-1])) {
r_strbuf_append (sb, "- ");
p++;
}
}
free (s);
return r_strbuf_drain (sb);
}
static char *parse(RAsmPluginSession *aps, const char *data) {
char *str = normalize (data);
char *sp = strchr (str, ' ');
char *args = sp? sp: "";
char *mn = r_str_ndup (str, sp? sp - str: strlen (str));
// mnemonic: base[.cond][.m|.s][.ss|.su|.us|.uu]
int cond = -1;
char *dot = strchr (mn, '.');
if (dot) {
char *t = dot;
*dot = 0;
while (t) {
char *part = t + 1;
t = strchr (part, '.');
if (t) {
*t = 0;
}
int c = cond_index (part);
if (c >= 0) {
cond = c;
}
}
}
char *res = NULL;
int ci = -1;
int nargs = *args? (int)r_str_char_count (args, ',') + 1: 0;
if (r_str_startswith (mn, "addcmpb")) {
ci = mn[7]? cond_index (mn + 7): -1;
if (!mn[7]) {
char *s = r_str_newf ("x%s", args);
const char *rules[] = { "x/4/$1 += $2; goto $4", NULL };
res = r_str_pseudo_transform (rules, s);
free (s);
} else if (ci >= 0) {
res = cmpbranch (str, conds[ci][0], conds[ci][1], true);
}
} else if (mn[0] == 'b' && mn[1] && (ci = cond_index (mn + 1)) >= 0) {
if (nargs == 3) {
res = cmpbranch (str, conds[ci][0], conds[ci][1], false);
} else if (strcmp (conds[ci][0], "f")) {
res = r_str_newf ("if (%s) goto%s", conds[ci][0], args);
}
} else if (!strcmp (mn, "ldm") || !strcmp (mn, "stm")) {
// ldm r6-r7,pc,(sp++) / stm r6-r7,lr,(--sp)
char *regs = r_str_trim_dup (args);
char *last = (char *)r_str_rchr (regs, NULL, ',');
if (last) {
*last = 0;
}
bool ret = strstr (regs, ",pc") || !strcmp (regs, "pc");
res = r_str_newf ("%s %s%s", (*mn == 'l')? "pop": "push", regs, ret? "; return": "");
free (regs);
} else {
char *s = r_str_newf ("%s%s", mn, args);
char *body = transform (s);
free (s);
if (body) {
if (cond >= 0 && strcmp (conds[cond][0], "f")) {
res = r_str_newf ("if (%s) %s", conds[cond][0], body);
free (body);
} else if (cond >= 0) {
free (body);
} else {
res = body;
}
}
}
free (mn);
free (str);
if (!res) {
return strdup (data);
}
res = r_str_replace (res, "+= -", "-= ", 1);
return fix_minus (res);
}
RAsmPlugin r_asm_plugin_vc4 = {
.meta = {
.name = "vc4",
.desc = "VideoCore IV pseudo syntax",
.author = "pancake",
.license = "LGPL-3.0-only",
},
.parse = parse,
};
#ifndef R2_PLUGIN_INCORE
R_API RLibStruct radare_plugin = {
.type = R_LIB_TYPE_ASM,
.data = &r_asm_plugin_vc4,
.version = R2_VERSION
};
#endif
+49
View File
@@ -0,0 +1,49 @@
# r2plugin
This directory contains the make and meson files required to link the
vc4 (VideoCore IV) plugins statically inside radare2, using the XPS
(static external plugins) mechanism. See `libr/xps/README.md` in the
radare2 source tree for the full details.
Two plugins are registered directly, without a core wrapper, so both
`rasm2` and `r2` get them:
- `arch.vc4`: cgen based disassembler and analysis, linked into libr_arch
- `asm.vc4`: pseudo syntax (`e asm.pseudo=true`), linked into libr_asm
## Usage
Run these commands from the radare2 source tree:
```console
mkdir -p libr/xps/p
ln -s ../../../../radare2-extras/libr/asm/arch/vc4 libr/xps/p/vc4
echo 'EXTERNAL_PLUGINS+=vc4' >> libr/xps/config.mk
make -C libr/xps clean all
```
Then build radare2 as usual:
```console
./configure && make -j
# or
meson setup build --reconfigure && meson compile -C build
```
The meson build needs a radare2 that provides `xps_arch_plugins`,
`xps_asm_plugins` and `r_{arch,asm}_additional_{sources,inc}`.
Verify the plugins are linked in:
```console
rasm2 -L | grep vc4
rasm2 -a vc4 -d 01000200
r2 -NN -qc 'La~vc4;Lp~vc4' --
```
## Notes
- `libvc4/` is not linked: the plugin only uses the cgen disassembler.
- `r2plugin/arch/arch_vc4.c` includes `libr/asm/p/arch_vc4.c`, which
lives outside this directory.
- Object files for the make build are stored under `build/r2plugin/`.
@@ -0,0 +1,4 @@
/* radare - LGPL - Copyright 2026 - pancake */
/* the r2 glue lives in libr/asm/p, outside the XPS directory */
#include "../../../../p/arch_vc4.c"
+5
View File
@@ -0,0 +1,5 @@
/* radare - LGPL - Copyright 2026 - pancake */
#ifdef R2_ARCH_H
extern RArchPlugin r_arch_plugin_vc4;
#endif
+22
View File
@@ -0,0 +1,22 @@
VC4_ARCH_WD=$(LIBR)/xps/p/vc4
VC4_ARCH_BUILD=$(VC4_ARCH_WD)/build/r2plugin/arch
VC4_ARCH_SRC=\
vc4-dis.c vc4-asm.c vc4-desc.c vc4-ibld.c vc4-opc.c \
cgen-bitset.c cgen-dis.c cgen-asm.c cgen-opc.c
VC4_ARCH_OBJ=$(addprefix $(VC4_ARCH_BUILD)/,$(VC4_ARCH_SRC:.c=.o))
VC4_ARCH_OBJ+=$(VC4_ARCH_BUILD)/arch_vc4.o
EXTERNAL_STATIC_OBJS+=$(VC4_ARCH_OBJ)
# must come before r2's libr/arch/include, which ships its own sysdep.h, mybfd.h..
VC4_ARCH_CFLAGS=-I$(VC4_ARCH_WD) -I$(VC4_ARCH_WD)/include \
-I$(VC4_ARCH_WD)/include/opcode -I$(VC4_ARCH_WD)/../include
$(VC4_ARCH_BUILD)/arch_vc4.o: $(VC4_ARCH_WD)/r2plugin/arch/arch_vc4.c $(VC4_ARCH_WD)/../../p/arch_vc4.c
@mkdir -p $(dir $@)
$(CC) -c $(VC4_ARCH_CFLAGS) $(CFLAGS) -o $@ $<
$(VC4_ARCH_BUILD)/%.o: $(VC4_ARCH_WD)/%.c
@mkdir -p $(dir $@)
$(CC) -c $(VC4_ARCH_CFLAGS) $(CFLAGS) -o $@ $<
-include $(VC4_ARCH_OBJ:.o=.d)
+5
View File
@@ -0,0 +1,5 @@
/* radare - LGPL - Copyright 2026 - pancake */
#ifdef R2_ASM_H
extern RAsmPlugin r_asm_plugin_vc4;
#endif
+9
View File
@@ -0,0 +1,9 @@
VC4_ASM_WD=$(LIBR)/xps/p/vc4
VC4_ASM_OBJ=$(VC4_ASM_WD)/build/r2plugin/asm/pseudo.o
EXTERNAL_STATIC_OBJS+=$(VC4_ASM_OBJ)
$(VC4_ASM_OBJ): $(VC4_ASM_WD)/pseudo.c
@mkdir -p $(dir $@)
$(CC) -c $(CFLAGS) -o $@ $<
-include $(VC4_ASM_OBJ:.o=.d)
+9
View File
@@ -0,0 +1,9 @@
EXTERNAL_PLUGINS+=vc4
.PHONY: vc4
vc4: p/vc4
p/vc4:
cd p && git clone --depth 1 https://github.com/radareorg/radare2-extras
ln -fs radare2-extras/libr/asm/arch/vc4 p/vc4
+35
View File
@@ -0,0 +1,35 @@
# vc4 XPS integration for radare2.
# Included from libr/xps/meson.build when this directory lives under
# libr/xps/p/vc4/. Links the arch plugin into libr_arch and the pseudo
# plugin into libr_asm, so rasm2 and r2 get vc4 without external files.
xps_arch_plugins += ['vc4']
# p/vc4 is usually a symlink, resolve it before going above this directory
vc4_shared_inc = run_command('realpath',
join_paths(meson.current_source_dir(), '..', '..', 'include'),
check: true).stdout().strip()
r_arch_additional_inc += include_directories(
'..',
'../include',
'../include/opcode',
vc4_shared_inc,
)
r_arch_additional_sources += files(
'../vc4-dis.c',
'../vc4-asm.c',
'../vc4-desc.c',
'../vc4-ibld.c',
'../vc4-opc.c',
'../cgen-bitset.c',
'../cgen-dis.c',
'../cgen-asm.c',
'../cgen-opc.c',
'arch/arch_vc4.c',
)
xps_asm_plugins += ['vc4']
r_asm_additional_sources += files('../pseudo.c')
+8
View File
@@ -0,0 +1,8 @@
/* radare - LGPL - Copyright 2026 - pancake */
#ifdef R2_ARCH_H
#include "arch/deps.h"
#endif
#ifdef R2_ASM_H
#include "asm/deps.h"
#endif
+2
View File
@@ -0,0 +1,2 @@
arch.vc4
asm.vc4
File diff suppressed because it is too large. Load diff
+52977 -655
View File
File diff suppressed because it is too large. Load diff
+128 -32
View File
@@ -42,12 +42,12 @@ This file is part of the GNU Binutils and/or GDB, the GNU debugger.
/* Maximum size of any insn (in bytes). */
#define CGEN_MAX_INSN_SIZE 10
#define CGEN_MAX_EXTRA_OPCODE_OPERANDS 2
#define CGEN_MAX_EXTRA_OPCODE_OPERANDS 3
#define CGEN_INT_INSN_P 0
/* Maximum number of syntax elements in an instruction. */
#define CGEN_ACTUAL_MAX_SYNTAX_ELEMENTS 20
#define CGEN_ACTUAL_MAX_SYNTAX_ELEMENTS 26
/* CGEN_MNEMONIC_OPERANDS is defined if mnemonics have operands.
e.g. In "b,a foo" the ",a" is an operand. If mnemonics have operands
@@ -55,7 +55,7 @@ This file is part of the GNU Binutils and/or GDB, the GNU debugger.
#define CGEN_MNEMONIC_OPERANDS
/* Maximum number of fields in an instruction. */
#define CGEN_ACTUAL_MAX_IFMT_OPERANDS 9
#define CGEN_ACTUAL_MAX_IFMT_OPERANDS 15
/* Enums. */
@@ -76,7 +76,7 @@ typedef enum insn_op15_13 {
/* Enum declaration for insn float ops. */
typedef enum insn_floatops {
ALUFOP_FADD, ALUFOP_FSUB, ALUFOP_FMUL, ALUFOP_FDIV
, ALUFOP_FCMP, ALUFOP_FABS, ALUFOP_FRSB, ALUFOP_FMAX
, ALUFOP_FCMP, ALUFOP_FABS, ALUFOP_FRSUB, ALUFOP_FMAX
, ALUFOP_FRCP, ALUFOP_FRSQRT, ALUFOP_FNMUL, ALUFOP_FMIN
, ALUFOP_FCEIL, ALUFOP_FFLOOR, ALUFOP_FLOG2, ALUFOP_FEXP2
} INSN_FLOATOPS;
@@ -86,7 +86,7 @@ typedef enum insn_alu16op {
ALU16OP_MOV, ALU16OP_CMN, ALU16OP_ADD, ALU16OP_BIC
, ALU16OP_MUL, ALU16OP_EOR, ALU16OP_SUB, ALU16OP_AND
, ALU16OP_NOT, ALU16OP_ROR, ALU16OP_CMP, ALU16OP_RSUB
, ALU16OP_BTST, ALU16OP_OR, ALU16OP_BMASK, ALU16OP_MAX
, ALU16OP_BTEST, ALU16OP_OR, ALU16OP_BMASK, ALU16OP_MAX
, ALU16OP_BSET, ALU16OP_MIN, ALU16OP_BCLR, ALU16OP_ADDS2
, ALU16OP_BCHG, ALU16OP_ADDS4, ALU16OP_ADDS8, ALU16OP_ADDS16
, ALU16OP_SIGNEXT, ALU16OP_NEG, ALU16OP_LSR, ALU16OP_MSB
@@ -96,7 +96,7 @@ typedef enum insn_alu16op {
/* Enum declaration for insn alu16 imm ops. */
typedef enum insn_alu16opi {
ALU16OPI_MOV, ALU16OPI_ADD, ALU16OPI_MUL, ALU16OPI_SUB
, ALU16OPI_NOT, ALU16OPI_CMP, ALU16OPI_BTST, ALU16OPI_BMASK
, ALU16OPI_NOT, ALU16OPI_CMP, ALU16OPI_BTEST, ALU16OPI_BMASK
, ALU16OPI_BSET, ALU16OPI_BCLR, ALU16OPI_BCHG, ALU16OPI_ADDS8
, ALU16OPI_SIGNEXT, ALU16OPI_LSR, ALU16OPI_SHL, ALU16OPI_ASR
} INSN_ALU16OPI;
@@ -106,7 +106,7 @@ typedef enum insn_alu32op {
ALU32OP_MOV, ALU32OP_CMN, ALU32OP_ADD, ALU32OP_BIC
, ALU32OP_MUL, ALU32OP_EOR, ALU32OP_SUB, ALU32OP_AND
, ALU32OP_NOT, ALU32OP_ROR, ALU32OP_CMP, ALU32OP_RSUB
, ALU32OP_BTST, ALU32OP_OR, ALU32OP_BMASK, ALU32OP_MAX
, ALU32OP_BTEST, ALU32OP_OR, ALU32OP_BMASK, ALU32OP_MAX
, ALU32OP_BSET, ALU32OP_MIN, ALU32OP_BCLR, ALU32OP_ADDS2
, ALU32OP_BCHG, ALU32OP_ADDS4, ALU32OP_ADDS8, ALU32OP_ADDS16
, ALU32OP_SIGNEXT, ALU32OP_NEG, ALU32OP_LSR, ALU32OP_MSB
@@ -141,10 +141,17 @@ typedef enum insn_op7_6 {
OP7_6_0, OP7_6_1, OP7_6_2, OP7_6_3
} INSN_OP7_6;
/* Enum declaration for access sizes. */
typedef enum accsz_op7_6 {
ACCSZ7_6_, ACCSZ7_6_H, ACCSZ7_6_B, ACCSZ7_6_SH
} ACCSZ_OP7_6;
/* Enum declaration for access size. */
typedef enum accsz_10_8 {
ACCSZ10_8_LD, ACCSZ10_8_ST, ACCSZ10_8_LDH, ACCSZ10_8_STH
, ACCSZ10_8_LDB, ACCSZ10_8_STB, ACCSZ10_8_LDSH, ACCSZ10_8_LDSB
} ACCSZ_10_8;
/* Enum declaration for access size (32 bit insns). */
typedef enum accsz_7_5 {
ACCSZ7_5_LD, ACCSZ7_5_ST, ACCSZ7_5_LDH, ACCSZ7_5_STH
, ACCSZ7_5_LDB, ACCSZ7_5_STB, ACCSZ7_5_LDSH, ACCSZ7_5_LDSB
} ACCSZ_7_5;
/* Enum declaration for insn bits 7-5. */
typedef enum insn_op7_5 {
@@ -205,6 +212,67 @@ typedef enum insn_op22_21 {
OP22_21_0, OP22_21_1, OP22_21_2, OP22_21_3
} INSN_OP22_21;
/* Enum declaration for Vector ops (< 48). */
typedef enum insn_vecops {
VECOP_MOV, VECOP_BITPLANES, VECOP_EVEN, VECOP_ODD
, VECOP_INTERL, VECOP_INTERH, VECOP_BITREV, VECOP_ROR
, VECOP_SHL, VECOP_SHLS, VECOP_LSR, VECOP_ASR
, VECOP_SIGNSHL, VECOP_OP13, VECOP_SIGNASL, VECOP_SIGNASLS
, VECOP_AND, VECOP_OR, VECOP_EOR, VECOP_BIC
, VECOP_COUNT, VECOP_MSB, VECOP_OP22, VECOP_OP23
, VECOP_MIN, VECOP_MAX, VECOP_DIST, VECOP_DISTS
, VECOP_CLIP, VECOP_SIGN, VECOP_CLIPS, VECOP_TESTMAG
, VECOP_ADD, VECOP_ADDS, VECOP_ADDC, VECOP_ADDSC
, VECOP_SUB, VECOP_SUBS, VECOP_SUBC, VECOP_SUBSC
, VECOP_RSUB, VECOP_RSUBS, VECOP_RSUBC, VECOP_RSUBSC
, VECOP_OP44, VECOP_OP45, VECOP_OP46, VECOP_OP47
} INSN_VECOPS;
/* Enum declaration for Vector memory ops. */
typedef enum insn_vecmemops {
VMEMOP_LD, VMEMOP_LOOKUPM, VMEMOP_LOOKUPML, VMEMOP_MEM03
, VMEMOP_ST, VMEMOP_INDEXWRITEM, VMEMOP_INDEXWRITEML, VMEMOP_MEM07
, VMEMOP_MEMREAD, VMEMOP_MEMWRITE, VMEMOP_MEM10, VMEMOP_MEM11
, VMEMOP_MEM12, VMEMOP_MEM13, VMEMOP_MEM14, VMEMOP_MEM15
, VMEMOP_MEM16, VMEMOP_MEM17, VMEMOP_MEM18, VMEMOP_MEM19
, VMEMOP_MEM20, VMEMOP_MEM21, VMEMOP_MEM22, VMEMOP_MEM23
, VMEMOP_GETACC, VMEMOP_MEM25, VMEMOP_MEM26, VMEMOP_MEM27
, VMEMOP_MEM28, VMEMOP_MEM29, VMEMOP_MEM30, VMEMOP_MEM31
} INSN_VECMEMOPS;
/* Enum declaration for Vector memory op width. */
typedef enum insn_memwidth {
VMEMWIDTH_8, VMEMWIDTH_16, VMEMWIDTH_32, VMEMWIDTH_UNK
} INSN_MEMWIDTH;
/* Enum declaration for Vector memory op saturation. */
typedef enum insn_memsat {
VMEMSAT_, VMEMSAT_S32, VMEMSAT_UNK, VMEMSAT_S16
} INSN_MEMSAT;
/* Enum declaration for Multiply operations. */
typedef enum insn_mulop {
VMULXOP_MULLSS = 48, VMULXOP_OP481 = 48, VMULXOP_MULLSSS = 49, VMULXOP_OP491 = 49
, VMULXOP_MULMSS = 50, VMULXOP_OP501 = 50, VMULXOP_MULMSSS = 51, VMULXOP_OP511 = 51
, VMULXOP_MULHDSS = 52, VMULXOP_MUL32SS = 52, VMULXOP_MULHDSU = 53, VMULXOP_MUL32SU = 53
, VMULXOP_MULHDUS = 54, VMULXOP_MUL32US = 54, VMULXOP_MULHDUU = 55, VMULXOP_MUL32UU = 55
, VMULXOP_MULHNSS = 56, VMULXOP_OP561 = 56, VMULXOP_MULHNSU = 57, VMULXOP_OP571 = 57
, VMULXOP_MULHNUS = 58, VMULXOP_OP581 = 58, VMULXOP_MULHNUU = 59, VMULXOP_OP591 = 59
, VMULXOP_MULHDTSS = 60, VMULXOP_OP601 = 60, VMULXOP_MULHDTSU = 61, VMULXOP_OP611 = 61
, VMULXOP_OP620 = 62, VMULXOP_OP621 = 62, VMULXOP_OP630 = 63, VMULXOP_OP631 = 63
} INSN_MULOP;
/* Enum declaration for SREG setting for 48-bit ops. */
typedef enum insn_sreg {
SREG_R0, SREG_R1, SREG_R2, SREG_R3
, SREG_R4, SREG_R5, SREG_R6, SREG_R7
} INSN_SREG;
/* Enum declaration for Vector direction bit for 48-bit ops. */
typedef enum insn_vec48dir {
VECDIR_H, VECDIR_V
} INSN_VEC48DIR;
/* Attributes. */
/* Enum declaration for machine type selection. */
@@ -248,7 +316,7 @@ typedef enum cgen_ifld_attr {
typedef enum ifield_type {
VC4_F_NIL, VC4_F_ANYOF, VC4_F_OPLEN, VC4_F_OP15_13
, VC4_F_OP15_11, VC4_F_OP11_8, VC4_F_LDSTOFF, VC4_F_OP11_9
, VC4_F_OP11_10, VC4_F_OP11, VC4_F_OP10_9, VC4_F_OP10_7
, VC4_F_OP11_10, VC4_F_OP11, VC4_F_OP10_8, VC4_F_OP10_7
, VC4_F_ADDSPOFFSET, VC4_F_OP10_0, VC4_F_ALU16OP, VC4_F_ALU16OPI
, VC4_F_OP9_8, VC4_F_OP9_5, VC4_F_SPOFFSET, VC4_F_OP8_5
, VC4_F_OP8_4, VC4_F_OP8_4_SHL3, VC4_F_OP8, VC4_F_OP7_4
@@ -265,7 +333,18 @@ typedef enum ifield_type {
, VC4_F_OP21_16S_SHL6, VC4_F_OP21_16S_SHL7, VC4_F_OP21_16S_SHL8, VC4_F_OP20_16
, VC4_F_OP47_16, VC4_F_PCREL32_48, VC4_F_OP47_43, VC4_F_OFFSET27_48
, VC4_F_PCREL27_48, VC4_F_OP79_48, VC4_F_OFFSET23BITS, VC4_F_OFFSET27BITS
, VC4_F_OFFSET12, VC4_F_MAX
, VC4_F_OFFSET12, VC4_F_OP15_10, VC4_F_OP9, VC4_F_OP8_3
, VC4_F_OP2_0, VC4_F_OP4_3, VC4_F_OP31_22, VC4_F_OP31_28
, VC4_F_OP31_29, VC4_F_OP28, VC4_F_OP27_22, VC4_F_OP21_19
, VC4_F_OP21_18, VC4_F_OP18, VC4_F_OP17_16, VC4_F_OP37_32
, VC4_F_OP38, VC4_F_OP41_32, VC4_F_OP42, VC4_F_OP43
, VC4_F_OP47_44, VC4_F_OP38_32, VC4_F_OP41_39, VC4_F_OP41_38
, VC4_F_OP51_48, VC4_F_OP57_52, VC4_F_OP63_58, VC4_F_OP69_64
, VC4_F_OP76_70, VC4_F_OP79_77, VC4_F_OP65_64, VC4_F_OP69_66
, VC4_F_VEC80DREG, VC4_F_VEC80AREG, VC4_F_VEC80BREG, VC4_F_VEC80MODS
, VC4_F_VEC80MODS_MEM, VC4_F_VEC80IMM, VC4_F_VEC80LDADDR, VC4_F_VEC80STADDR
, VC4_F_DUMMYABITS, VC4_F_VEC48DREG, VC4_F_VEC48AREG, VC4_F_VEC48BREG
, VC4_F_MAX
} IFIELD_TYPE;
#define MAX_IFLD ((int) VC4_F_MAX)
@@ -291,9 +370,9 @@ typedef enum cgen_hw_attr {
/* Enum declaration for vc4 hardware types. */
typedef enum cgen_hw_type {
HW_H_MEMORY, HW_H_SINT, HW_H_UINT, HW_H_ADDR
, HW_H_IADDR, HW_H_REG, HW_H_FASTREG, HW_H_PPREG
, HW_H_BASEREG, HW_H_COND, HW_H_ACCSZ, HW_H_PC
, HW_MAX
, HW_H_IADDR, HW_H_REG, HW_H_FASTREG, HW_H_PREG
, HW_H_PPREG, HW_H_BASEREG, HW_H_COND, HW_H_DOTCOND
, HW_H_PC, HW_H_ELTSIZE, HW_MAX
} CGEN_HW_TYPE;
#define MAX_HW ((int) HW_MAX)
@@ -325,23 +404,37 @@ typedef enum cgen_operand_attr {
typedef enum cgen_operand_type {
VC4_OPERAND_PC, VC4_OPERAND_CONDCODE, VC4_OPERAND_PCRELCC, VC4_OPERAND_LDSTOFF
, VC4_OPERAND_ALU16SREG, VC4_OPERAND_ALU16IMM, VC4_OPERAND_ALU16IMM_SHL3, VC4_OPERAND_ALU16DREG
, VC4_OPERAND_ALU32DREG, VC4_OPERAND_IMM6, VC4_OPERAND_FLOATIMM6, VC4_OPERAND_IMM6_SHL1
, VC4_OPERAND_IMM6_SHL2, VC4_OPERAND_IMM6_SHL3, VC4_OPERAND_IMM6_SHL4, VC4_OPERAND_IMM6_SHL5
, VC4_OPERAND_IMM6_SHL6, VC4_OPERAND_IMM6_SHL7, VC4_OPERAND_IMM6_SHL8, VC4_OPERAND_ALU32BREG
, VC4_OPERAND_PPSTARTREG, VC4_OPERAND_PPENDREG0, VC4_OPERAND_PPENDREG6, VC4_OPERAND_PPENDREG16
, VC4_OPERAND_PPENDREG24, VC4_OPERAND_SWI_IMM, VC4_OPERAND_SPOFFSET, VC4_OPERAND_ADDSPOFFSET
, VC4_OPERAND_ALU32AREG, VC4_OPERAND_ALU32COND, VC4_OPERAND_ALU48ISREG, VC4_OPERAND_ALU48IDREG
, VC4_OPERAND_ALU32DREG, VC4_OPERAND_PREGDST, VC4_OPERAND_PREGSRC, VC4_OPERAND_DISP5
, VC4_OPERAND_IMM6, VC4_OPERAND_FLOATIMM6, VC4_OPERAND_IMM6_SHL1, VC4_OPERAND_IMM6_SHL2
, VC4_OPERAND_IMM6_SHL3, VC4_OPERAND_IMM6_SHL4, VC4_OPERAND_IMM6_SHL5, VC4_OPERAND_IMM6_SHL6
, VC4_OPERAND_IMM6_SHL7, VC4_OPERAND_IMM6_SHL8, VC4_OPERAND_ALU32BREG, VC4_OPERAND_PPSTARTREG
, VC4_OPERAND_PPENDREG0, VC4_OPERAND_PPENDREG6, VC4_OPERAND_PPENDREG16, VC4_OPERAND_PPENDREG24
, VC4_OPERAND_SWI_IMM, VC4_OPERAND_SPOFFSET, VC4_OPERAND_ADDSPOFFSET, VC4_OPERAND_ALU32AREG
, VC4_OPERAND_ALU32MISSINGAREG, VC4_OPERAND_ALU32COND, VC4_OPERAND_ALU48ISREG, VC4_OPERAND_ALU48IDREG
, VC4_OPERAND_MEM48SREG, VC4_OPERAND_ALU48IMMU, VC4_OPERAND_ALU48PCREL, VC4_OPERAND_MEM48OFFSET27
, VC4_OPERAND_MEM48PCREL27, VC4_OPERAND_ACCSZ, VC4_OPERAND_ACCSZ32, VC4_OPERAND_CONDCODEBCC32
, VC4_OPERAND_BCC32SREG, VC4_OPERAND_PCREL10BITS, VC4_OPERAND_PCREL8BITS, VC4_OPERAND_BCC32IMM
, VC4_OPERAND_ADDCMPBAREG, VC4_OPERAND_ADDCMPBIMM, VC4_OPERAND_OFFSET23BITS, VC4_OPERAND_OFFSET27BITS
, VC4_OPERAND_OFFSET12, VC4_OPERAND_OFFSET16, VC4_OPERAND_OFFSET16_SHL1, VC4_OPERAND_OFFSET16_SHL2
, VC4_OPERAND_OFFSET16_SHL3, VC4_OPERAND_OFFSET16_SHL4, VC4_OPERAND_PCREL16, VC4_OPERAND_OFF16BASEREG
, VC4_OPERAND_OPERAND10_0, VC4_OPERAND_OPERAND47_16, VC4_OPERAND_OPERAND79_48, VC4_OPERAND_MAX
, VC4_OPERAND_MEM48PCREL27, VC4_OPERAND_CONDCODEBCC32, VC4_OPERAND_BCC32SREG, VC4_OPERAND_PCREL10BITS
, VC4_OPERAND_PCREL8BITS, VC4_OPERAND_BCC32IMM, VC4_OPERAND_ADDCMPBAREG, VC4_OPERAND_ADDCMPBIMM
, VC4_OPERAND_OFFSET23BITS, VC4_OPERAND_OFFSET27BITS, VC4_OPERAND_OFFSET12, VC4_OPERAND_OFFSET16
, VC4_OPERAND_OFFSET16_SHL1, VC4_OPERAND_OFFSET16_SHL2, VC4_OPERAND_OFFSET16_SHL3, VC4_OPERAND_OFFSET16_SHL4
, VC4_OPERAND_PCREL16, VC4_OPERAND_OFF16BASEREG, VC4_OPERAND_OPERAND10_0, VC4_OPERAND_OPERAND47_16
, VC4_OPERAND_OPERAND79_48, VC4_OPERAND_SHL1, VC4_OPERAND_SHL2, VC4_OPERAND_SHL3
, VC4_OPERAND_SHL4, VC4_OPERAND_SHL5, VC4_OPERAND_SHL6, VC4_OPERAND_SHL7
, VC4_OPERAND_SHL8, VC4_OPERAND_V80D32REG, VC4_OPERAND_V80A32REG, VC4_OPERAND_V80B32REG
, VC4_OPERAND_V80IMM, VC4_OPERAND_V80MODS, VC4_OPERAND_V80MODS_MEM, VC4_OPERAND_SETF_MOD
, VC4_OPERAND_V48IMM_MODS, VC4_OPERAND_VMEMWIDTH, VC4_OPERAND_VEC_LDADDR, VC4_OPERAND_VEC_STADDR
, VC4_OPERAND_DUMMYABITS, VC4_OPERAND_DUMMYDBITS, VC4_OPERAND_V48SCLR, VC4_OPERAND_V48IMM
, VC4_OPERAND_V48DREG_H, VC4_OPERAND_V48DREG_V, VC4_OPERAND_V48AREG_H, VC4_OPERAND_V48AREG_V
, VC4_OPERAND_V48BREG_H, VC4_OPERAND_V48BREG_V, VC4_OPERAND_DPLUS_SR0, VC4_OPERAND_APLUS_SR0
, VC4_OPERAND_BPLUS_SR0, VC4_OPERAND_DPLUS_SR1, VC4_OPERAND_APLUS_SR1, VC4_OPERAND_BPLUS_SR1
, VC4_OPERAND_DPLUS_SR2, VC4_OPERAND_APLUS_SR2, VC4_OPERAND_BPLUS_SR2, VC4_OPERAND_DPLUS_SR3
, VC4_OPERAND_APLUS_SR3, VC4_OPERAND_BPLUS_SR3, VC4_OPERAND_DPLUS_SR4, VC4_OPERAND_APLUS_SR4
, VC4_OPERAND_BPLUS_SR4, VC4_OPERAND_DPLUS_SR5, VC4_OPERAND_APLUS_SR5, VC4_OPERAND_BPLUS_SR5
, VC4_OPERAND_DPLUS_SR6, VC4_OPERAND_APLUS_SR6, VC4_OPERAND_BPLUS_SR6, VC4_OPERAND_DPLUS_SR7
, VC4_OPERAND_APLUS_SR7, VC4_OPERAND_BPLUS_SR7, VC4_OPERAND_MAX
} CGEN_OPERAND_TYPE;
/* Number of operands types. */
#define MAX_OPERANDS 59
#define MAX_OPERANDS 114
/* Maximum number of operands referenced by any insn. */
#define MAX_OPERAND_INSTANCES 8
@@ -352,8 +445,8 @@ typedef enum cgen_operand_type {
typedef enum cgen_insn_attr {
CGEN_INSN_ALIAS, CGEN_INSN_VIRTUAL, CGEN_INSN_UNCOND_CTI, CGEN_INSN_COND_CTI
, CGEN_INSN_SKIP_CTI, CGEN_INSN_DELAY_SLOT, CGEN_INSN_RELAXABLE, CGEN_INSN_RELAXED
, CGEN_INSN_NO_DIS, CGEN_INSN_PBB, CGEN_INSN_END_BOOLS, CGEN_INSN_START_NBOOLS = 31
, CGEN_INSN_MACH, CGEN_INSN_END_NBOOLS
, CGEN_INSN_NO_DIS, CGEN_INSN_PBB, CGEN_INSN_SWITCH, CGEN_INSN_END_BOOLS
, CGEN_INSN_START_NBOOLS = 31, CGEN_INSN_MACH, CGEN_INSN_END_NBOOLS
} CGEN_INSN_ATTR;
/* Number of non-boolean elements in cgen_insn_attr. */
@@ -371,6 +464,7 @@ typedef enum cgen_insn_attr {
#define CGEN_ATTR_CGEN_INSN_RELAXED_VALUE(attrs) (((attrs)->bool_ & (1 << CGEN_INSN_RELAXED)) != 0)
#define CGEN_ATTR_CGEN_INSN_NO_DIS_VALUE(attrs) (((attrs)->bool_ & (1 << CGEN_INSN_NO_DIS)) != 0)
#define CGEN_ATTR_CGEN_INSN_PBB_VALUE(attrs) (((attrs)->bool_ & (1 << CGEN_INSN_PBB)) != 0)
#define CGEN_ATTR_CGEN_INSN_SWITCH_VALUE(attrs) (((attrs)->bool_ & (1 << CGEN_INSN_SWITCH)) != 0)
/* cgen.h uses things we just defined. */
#include "opcode/cgen.h"
@@ -387,10 +481,12 @@ extern const CGEN_ATTR_TABLE vc4_cgen_insn_attr_table[];
extern CGEN_KEYWORD vc4_cgen_opval_h_reg;
extern CGEN_KEYWORD vc4_cgen_opval_h_fastreg;
extern CGEN_KEYWORD vc4_cgen_opval_h_preg;
extern CGEN_KEYWORD vc4_cgen_opval_h_ppreg;
extern CGEN_KEYWORD vc4_cgen_opval_h_basereg;
extern CGEN_KEYWORD vc4_cgen_opval_h_cond;
extern CGEN_KEYWORD vc4_cgen_opval_h_accsz;
extern CGEN_KEYWORD vc4_cgen_opval_h_dotcond;
extern CGEN_KEYWORD vc4_cgen_opval_h_eltsize;
extern const CGEN_HW_ENTRY vc4_cgen_hw_table[];
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
+68136 -870
View File
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
+2 -1
View File
@@ -1,5 +1,7 @@
ARCHS=
ARCHS=
ARCHS+=x86_udis.mk
ARCHS+=spc700.mk
ARCHS+=ba2.mk
@@ -21,4 +23,3 @@ ARCHS+=atombios.mk
include ../../plugs.mk
+51
View File
@@ -0,0 +1,51 @@
#include <r_lib.h>
#include <r_arch.h>
#include "../arch/arm/arm.h"
static bool decode(RArchSession *as, RAnalOp *op, RArchDecodeMask mask) {
int *p = (int*)op->bytes; // thumb is 16-bit, using host endianness assumption here
char buf_asm[64] = {0};
int len = armthumb_disassemble(buf_asm, (ut32)op->addr, *p);
if (len <= 0) {
op->type = R_ANAL_OP_TYPE_UNK;
op->size = 0;
if (mask & R_ARCH_OP_MASK_DISASM) op->mnemonic = strdup("(data)");
return false;
}
op->size = len;
if (mask & R_ARCH_OP_MASK_DISASM) op->mnemonic = strdup(buf_asm);
return true;
}
static int info(RArchSession *s, ut32 q) {
switch (q) {
case R_ARCH_INFO_MINOP_SIZE: return 2;
case R_ARCH_INFO_MAXOP_SIZE: return 4;
default: return 2;
}
}
RArchPlugin r_arch_plugin_armthumb = {
.meta = {
.name = "arm.thumb",
.desc = "ARM THUMB disassembler",
.author = "pancake",
.version = R2_VERSION,
.license = "LGPL3",
.status = R_PLUGIN_STATUS_OK,
},
.arch = "arm",
.bits = R_SYS_BITS_PACK1(16),
.endian = R_SYS_ENDIAN_LITTLE,
.info = &info,
.decode = &decode,
};
#ifndef R2_PLUGIN_INCORE
R_API RLibStruct radare_plugin = {
.type = R_LIB_TYPE_ARCH,
.data = &r_arch_plugin_armthumb,
.version = R2_VERSION
};
#endif
+54
View File
@@ -0,0 +1,54 @@
#include <r_lib.h>
#include <r_arch.h>
#include <r_util.h>
#include "../arch/atombios/atombios.h"
static bool decode(RArchSession *as, RAnalOp *op, RArchDecodeMask mask) {
if (!(mask & R_ARCH_OP_MASK_DISASM)) {
op->size = 0;
return true;
}
char out[1024];
out[0] = 0;
int sz = atombios_disassemble(op->bytes, op->size, out);
if (sz <= 0) {
op->mnemonic = strdup("invalid");
op->size = 0;
return false;
}
op->mnemonic = strdup(out);
op->size = sz;
return true;
}
static int info(RArchSession *s, ut32 q) {
switch (q) {
case R_ARCH_INFO_MINOP_SIZE: return 1;
case R_ARCH_INFO_MAXOP_SIZE: return 8;
default: return 1;
}
}
RArchPlugin r_arch_plugin_atombios = {
.meta = {
.name = "atombios",
.desc = "AtomBIOS",
.author = "damo22",
.version = R2_VERSION,
.license = "LGPL3",
.status = R_PLUGIN_STATUS_OK,
},
.arch = "atombios",
.bits = R_SYS_BITS_PACK3(16, 32, 64),
.endian = R_SYS_ENDIAN_NONE,
.info = &info,
.decode = &decode,
};
#ifndef R2_PLUGIN_INCORE
R_API RLibStruct radare_plugin = {
.type = R_LIB_TYPE_ARCH,
.data = &r_arch_plugin_atombios,
.version = R2_VERSION
};
#endif
+64
View File
@@ -0,0 +1,64 @@
/* RArch plugin for BA2 using local disassembler */
#include <r_lib.h>
#include <r_arch.h>
#include <r_util.h>
#include <string.h>
#include "../arch/ba2/ba2_disas.c"
static bool decode(RArchSession *as, RAnalOp *op, RArchDecodeMask mask) {
struct op_cmd cmd = { .instr = "", .operands = "" };
int ret = ba2_decode_opcode(op->addr, op->bytes, op->size, &cmd, NULL, NULL);
if ((op->size < ret) || (!ret && op->size < 6)) {
if (mask & R_ARCH_OP_MASK_DISASM) op->mnemonic = strdup("truncated");
op->size = 0;
op->type = R_ANAL_OP_TYPE_ILL;
return false;
}
if (ret > 0) {
if (mask & R_ARCH_OP_MASK_DISASM) {
char buf[128];
if (*cmd.operands) snprintf(buf, sizeof(buf), "%s %s", cmd.instr, cmd.operands);
else snprintf(buf, sizeof(buf), "%s", cmd.instr);
op->mnemonic = strdup(buf);
}
op->size = ret;
return true;
}
if (mask & R_ARCH_OP_MASK_DISASM) op->mnemonic = strdup("invalid");
op->size = 0;
op->type = R_ANAL_OP_TYPE_ILL;
return false;
}
static int info(RArchSession *s, ut32 q) {
switch (q) {
case R_ARCH_INFO_MINOP_SIZE: return 2;
case R_ARCH_INFO_MAXOP_SIZE: return 8;
default: return 2;
}
}
RArchPlugin r_arch_plugin_ba2 = {
.meta = {
.name = "ba2",
.desc = "Beyond Architecture 2 disassembler",
.author = "radare2-extras",
.version = R2_VERSION,
.license = "LGPL3",
.status = R_PLUGIN_STATUS_OK,
},
.arch = "ba2",
.bits = R_SYS_BITS_PACK1(32),
.endian = R_SYS_ENDIAN_LITTLE,
.info = &info,
.decode = &decode,
};
#ifndef R2_PLUGIN_INCORE
R_API RLibStruct radare_plugin = {
.type = R_LIB_TYPE_ARCH,
.data = &r_arch_plugin_ba2,
.version = R2_VERSION
};
#endif
+12 -4
View File
@@ -1,4 +1,4 @@
/* radare - LGPL - Copyright 2015-2023 - pancake */
/* radare - LGPL - Copyright 2015-2024 - pancake */
#include <r_lib.h>
#include <r_asm.h>
@@ -207,11 +207,19 @@ static char *getregs(RArchSession *as) {
static int info(RArchSession *s, ut32 q) {
switch (q) {
#if R2_VERSION_NUMBER >= 50909
case R_ARCH_INFO_MINOP_SIZE:
return 2;
case R_ARCH_INFO_MAXOP_SIZE:
return 4;
}
#else
case R_ARCH_INFO_MIN_OP_SIZE:
return 2;
case R_ARCH_INFO_MAX_OP_SIZE:
return 4;
}
#endif
// i think data align is 4
return 2;
}
@@ -227,9 +235,9 @@ RArchPlugin r_arch_plugin_blackfin = {
.meta = {
.name = "blackfin",
.desc = "BlackFIN architecture plugin",
.author = "",
.version = "",
.license = "GPL",
.author = "pancake",
.version = "0.2",
.license = "GPL-3.0-only",
.status = R_PLUGIN_STATUS_OK,
},
.arch = "blackfin",
+42
View File
@@ -0,0 +1,42 @@
#include <r_lib.h>
#include <r_arch.h>
static bool decode(RArchSession *as, RAnalOp *op, RArchDecodeMask mask) {
op->type = R_ANAL_OP_TYPE_UNK;
if (mask & R_ARCH_OP_MASK_DISASM) op->mnemonic = strdup("(dcpu16: unimplemented)");
op->size = 2;
return true;
}
static int info(RArchSession *s, ut32 q) {
switch (q) {
case R_ARCH_INFO_MINOP_SIZE: return 2;
case R_ARCH_INFO_MAXOP_SIZE: return 4;
default: return 2;
}
}
RArchPlugin r_arch_plugin_dcpu16 = {
.meta = {
.name = "dcpu16",
.desc = "DCPU-16 (stub)",
.author = "radare2-extras",
.version = R2_VERSION,
.license = "LGPL3",
.status = R_PLUGIN_STATUS_BETA,
},
.arch = "dcpu16",
.bits = R_SYS_BITS_PACK1(16),
.endian = R_SYS_ENDIAN_LITTLE,
.info = &info,
.decode = &decode,
};
#ifndef R2_PLUGIN_INCORE
R_API RLibStruct radare_plugin = {
.type = R_LIB_TYPE_ARCH,
.data = &r_arch_plugin_dcpu16,
.version = R2_VERSION
};
#endif
+6 -4
View File
@@ -26,11 +26,13 @@ static int assemble(RAsm *a, RAsmOp *op, const char *buf) {
}
RAsmPlugin r_a_plugin_evm = {
.name = "evm",
.author = "pancake",
.version = "0.0.1",
.meta = {
.name = "evm",
.author = "pancake",
.version = "0.0.1",
.license = "MIT",
},
.arch = "evm",
.license = "MIT",
.bits = 32,
.endian = R_SYS_ENDIAN_BIG,
.desc = "evm",
+69
View File
@@ -0,0 +1,69 @@
#include <r_lib.h>
#include <r_arch.h>
#include <r_util.h>
#include "m68k/m68k_disasm/m68k_disasm.h"
static bool decode(RArchSession *as, RAnalOp *op, RArchDecodeMask mask) {
m68k_word bof[8] = {0};
int iaddr = (int)op->addr;
char opcode[256] = {0};
char operands[256] = {0};
const unsigned char *buf2;
static struct DisasmPara_68k dp;
int ilen;
memcpy(bof, op->bytes, R_MIN(op->size, sizeof(bof)));
dp.opcode = opcode;
dp.operands = operands;
dp.iaddr = (m68k_word *)(size_t)iaddr;
dp.instr = bof;
buf2 = (const ut8*)M68k_Disassemble(&dp);
if (!buf2) {
op->size = 2; // invalid, assume 2
if (mask & R_ARCH_OP_MASK_DISASM) op->mnemonic = strdup("invalid");
op->type = R_ANAL_OP_TYPE_ILL;
return false;
}
ilen = (int)(buf2 - (const ut8*)bof);
if (mask & R_ARCH_OP_MASK_DISASM) {
char buf[512];
if (*operands) snprintf(buf, sizeof(buf), "%s %s", opcode, operands);
else snprintf(buf, sizeof(buf), "%s", opcode);
r_str_replace_ch(buf, '#', 0, 1);
op->mnemonic = strdup(buf);
}
op->size = ilen;
return true;
}
static int info(RArchSession *s, ut32 q) {
switch (q) {
case R_ARCH_INFO_MINOP_SIZE: return 2;
case R_ARCH_INFO_MAXOP_SIZE: return 10;
default: return 2;
}
}
RArchPlugin r_arch_plugin_m68k_net = {
.meta = {
.name = "m68k.net",
.desc = "Motorola 68000",
.author = "nibble",
.version = R2_VERSION,
.license = "BSD",
.status = R_PLUGIN_STATUS_OK,
},
.arch = "m68k",
.bits = R_SYS_BITS_PACK2(16, 32),
.endian = R_SYS_ENDIAN_BIG,
.info = &info,
.decode = &decode,
};
#ifndef R2_PLUGIN_INCORE
R_API RLibStruct radare_plugin = {
.type = R_LIB_TYPE_ARCH,
.data = &r_arch_plugin_m68k_net,
.version = R2_VERSION
};
#endif
+41
View File
@@ -0,0 +1,41 @@
#include <r_lib.h>
#include <r_arch.h>
static bool decode(RArchSession *as, RAnalOp *op, RArchDecodeMask mask) {
op->type = R_ANAL_OP_TYPE_UNK;
if (mask & R_ARCH_OP_MASK_DISASM) op->mnemonic = strdup("(mc6809: unimplemented)");
op->size = 1;
return true;
}
static int info(RArchSession *s, ut32 q) {
switch (q) {
case R_ARCH_INFO_MINOP_SIZE: return 1;
case R_ARCH_INFO_MAXOP_SIZE: return 3;
default: return 1;
}
}
RArchPlugin r_arch_plugin_mc6809 = {
.meta = {
.name = "mc6809",
.desc = "Motorola 6809 (stub)",
.author = "radare2-extras",
.version = R2_VERSION,
.license = "LGPL3",
.status = R_PLUGIN_STATUS_BASIC,
},
.arch = "mc6809",
.bits = R_SYS_BITS_PACK1(8),
.endian = R_SYS_ENDIAN_BIG,
.info = &info,
.decode = &decode,
};
#ifndef R2_PLUGIN_INCORE
R_API RLibStruct radare_plugin = {
.type = R_LIB_TYPE_ARCH,
.data = &r_arch_plugin_mc6809,
.version = R2_VERSION
};
#endif
+56
View File
@@ -0,0 +1,56 @@
#include <r_lib.h>
#include <r_arch.h>
#include <r_util.h>
#include "msil/demsil.c"
static bool decode(RArchSession *as, RAnalOp *op, RArchDecodeMask mask) {
if (!(mask & R_ARCH_OP_MASK_DISASM)) {
op->size = 0;
return true;
}
ut32 n;
ILOPCODE_STRUCT ilopar[8];
int o = DisasMSIL(op->bytes, op->size, op->addr, ilopar, 8, &n);
if (o <= 0) {
op->type = R_ANAL_OP_TYPE_ILL;
op->size = 0;
op->mnemonic = strdup("invalid");
return false;
}
op->size = o;
op->mnemonic = strdup(ilopar[0].Mnemonic);
return true;
}
static int info(RArchSession *s, ut32 q) {
switch (q) {
case R_ARCH_INFO_MINOP_SIZE: return 1;
case R_ARCH_INFO_MAXOP_SIZE: return 8;
default: return 1;
}
}
RArchPlugin r_arch_plugin_msil = {
.meta = {
.name = "msil",
.desc = "Microsoft IL",
.author = "capi_x, pancake",
.version = R2_VERSION,
.license = "PD",
.status = R_PLUGIN_STATUS_OK,
},
.arch = "msil",
.bits = R_SYS_BITS_PACK3(16, 32, 64),
.endian = R_SYS_ENDIAN_LITTLE,
.info = &info,
.decode = &decode,
};
#ifndef R2_PLUGIN_INCORE
R_API RLibStruct radare_plugin = {
.type = R_LIB_TYPE_ARCH,
.data = &r_arch_plugin_msil,
.version = R2_VERSION
};
#endif
+73
View File
@@ -0,0 +1,73 @@
#include <r_lib.h>
#include <r_arch.h>
#include <r_util.h>
#include "ppc/ppc_disasm/ppc_disasm.h"
static bool decode(RArchSession *as, RAnalOp *op, RArchDecodeMask mask) {
if (!op->bytes || op->size < 4) {
return false;
}
ppc_word iaddr = (ppc_word)op->addr;
ppc_word instr = R_ARCH_CONFIG_IS_BIG_ENDIAN(as->config)
? r_read_be32(op->bytes) : r_read_le32(op->bytes);
char opcode[128] = {0};
char operands[128] = {0};
struct DisasmPara_PPC dp = {0};
dp.opcode = opcode;
dp.operands = operands;
dp.iaddr = &iaddr;
dp.instr = &instr;
PPC_Disassemble(&dp, 1);
op->size = 4;
if (dp.type == PPCINSTR_BRANCH && !(instr & 2)) {
char *target = strstr(operands, "0x");
if (target) {
snprintf(target, sizeof(operands) - (target - operands), "0x%x",
(unsigned int)(ppc_word)(op->addr + dp.displacement));
}
}
if (dp.flags & PPCF_ILLEGAL) {
op->type = R_ANAL_OP_TYPE_ILL;
return false;
}
if (mask & R_ARCH_OP_MASK_DISASM) {
op->mnemonic = r_str_newf("%s%s%s", opcode, *operands ? " " : "", operands);
}
return true;
}
static int info(RArchSession *s, ut32 q) {
switch (q) {
case R_ARCH_INFO_MINOP_SIZE:
case R_ARCH_INFO_MAXOP_SIZE:
case R_ARCH_INFO_INVOP_SIZE:
case R_ARCH_INFO_CODE_ALIGN:
return 4;
default:
return -1;
}
}
RArchPlugin r_arch_plugin_ppc_disasm = {
.meta = {
.name = "ppc.disasm",
.desc = "Tiny PowerPC disassembly",
.author = "pancake, nibble",
.version = R2_VERSION,
.license = "GPL3",
.status = R_PLUGIN_STATUS_OK,
},
.arch = "ppc",
.bits = R_SYS_BITS_PACK1(32),
.endian = R_SYS_ENDIAN_BIG | R_SYS_ENDIAN_LITTLE,
.info = &info,
.decode = &decode,
};
#ifndef R2_PLUGIN_INCORE
R_API RLibStruct radare_plugin = {
.type = R_LIB_TYPE_ARCH,
.data = &r_arch_plugin_ppc_disasm,
.version = R2_VERSION
};
#endif
+50
View File
@@ -0,0 +1,50 @@
#include <r_lib.h>
#include <r_arch.h>
#include <r_util.h>
#include <psosvm/vmas/vmas.h>
static bool decode(RArchSession *as, RAnalOp *op, RArchDecodeMask mask) {
char buf_asm[64] = {0};
psosvmasm_init();
int sz = psosvm_disasm(op->bytes, buf_asm);
if (sz > 0) {
if (mask & R_ARCH_OP_MASK_DISASM) op->mnemonic = strdup(buf_asm);
op->size = sz;
return true;
}
if (mask & R_ARCH_OP_MASK_DISASM) op->mnemonic = strdup("(data)");
op->size = 0;
return false;
}
static int info(RArchSession *s, ut32 q) {
switch (q) {
case R_ARCH_INFO_MINOP_SIZE: return 1;
case R_ARCH_INFO_MAXOP_SIZE: return 4;
default: return 1;
}
}
RArchPlugin r_arch_plugin_psosvm = {
.meta = {
.name = "psosvm",
.desc = "Smartcard PSOSVM",
.author = "nibble",
.version = R2_VERSION,
.license = "BSD",
.status = R_PLUGIN_STATUS_OK,
},
.arch = "psosvm",
.bits = R_SYS_BITS_PACK2(8, 16),
.endian = R_SYS_ENDIAN_LITTLE,
.info = &info,
.decode = &decode,
};
#ifndef R2_PLUGIN_INCORE
R_API RLibStruct radare_plugin = {
.type = R_LIB_TYPE_ARCH,
.data = &r_arch_plugin_psosvm,
.version = R2_VERSION
};
#endif
+94
View File
@@ -0,0 +1,94 @@
/* RArch port of SPC700 disassembler (minimal text-only) */
#include <r_lib.h>
#include <r_arch.h>
#include <r_util.h>
#include <string.h>
#include "../arch/spc700/spc700_opcode_table.h"
static int op_len(int t) {
switch (t) {
case SPC_OP: return 1;
case SPC_ARG8_1: return 2;
case SPC_ARG8_2: return 3;
case SPC_ARG16: return 3;
}
return 0;
}
static bool decode(RArchSession *as, RAnalOp *op, RArchDecodeMask mask) {
if (op->size < 1) {
op->type = R_ANAL_OP_TYPE_ILL;
if (mask & R_ARCH_OP_MASK_DISASM) {
op->mnemonic = strdup("invalid");
}
return false;
}
int t = spc_op_table[op->bytes[0]].type;
int len = op_len(t);
if (op->size < len) {
op->type = R_ANAL_OP_TYPE_UNK;
op->size = 0;
if (mask & R_ARCH_OP_MASK_DISASM) {
op->mnemonic = strdup("(truncated)");
}
return false;
}
if (mask & R_ARCH_OP_MASK_DISASM) {
const char *fmt = spc_op_table[op->bytes[0]].name;
char buf[64];
switch (t) {
case SPC_OP:
r_str_ncpy(buf, fmt, sizeof(buf));
break;
case SPC_ARG8_1:
snprintf(buf, sizeof(buf), fmt, op->bytes[1]);
break;
case SPC_ARG8_2:
snprintf(buf, sizeof(buf), fmt, op->bytes[1], op->bytes[2]);
break;
case SPC_ARG16:
snprintf(buf, sizeof(buf), fmt, (int)(op->bytes[1] + 0x100 * op->bytes[2]));
break;
default:
r_str_ncpy(buf, "invalid", sizeof(buf));
break;
}
op->mnemonic = strdup(buf);
}
op->size = len;
return true;
}
static int info(RArchSession *s, ut32 q) {
switch (q) {
case R_ARCH_INFO_MINOP_SIZE: return 1;
case R_ARCH_INFO_MAXOP_SIZE: return 3;
default: return 1;
}
}
RArchPlugin r_arch_plugin_spc700 = {
.meta = {
.name = "spc700",
.desc = "SPC700, SNES sound chip",
.author = "condret, pancake",
.version = R2_VERSION,
.license = "LGPL3",
.status = R_PLUGIN_STATUS_OK,
},
.arch = "spc700",
.bits = R_SYS_BITS_PACK1(16),
.endian = R_SYS_ENDIAN_NONE,
.info = &info,
.decode = &decode,
};
#ifndef R2_PLUGIN_INCORE
R_API RLibStruct radare_plugin = {
.type = R_LIB_TYPE_ARCH,
.data = &r_arch_plugin_spc700,
.version = R2_VERSION
};
#endif
+61
View File
@@ -0,0 +1,61 @@
#include <r_lib.h>
#include <r_arch.h>
#include <r_util.h>
#include "../arch/swf/swfdis.h"
static bool decode(RArchSession *as, RAnalOp *op, RArchDecodeMask mask) {
if (!(mask & R_ARCH_OP_MASK_DISASM)) {
op->size = 0;
return true;
}
if (!as || !as->arch || !as->arch->binb.bin || !as->arch->binb.bin->cur) {
op->mnemonic = strdup("invalid");
op->type = R_ANAL_OP_TYPE_ILL;
return false;
}
RBin *bin = as->arch->binb.bin;
RBinObject *obj = bin->cur ? bin->cur->bo : NULL;
if (!obj) {
op->mnemonic = strdup("invalid");
op->size = 0;
return false;
}
RStrBuf sb;
r_strbuf_init(&sb);
int dlen = r_asm_swf_disass(obj, &sb, op->bytes, op->size, op->addr);
op->size = dlen > 0 ? dlen : 0;
op->mnemonic = r_strbuf_drain(&sb);
return dlen > 0;
}
static int info(RArchSession *s, ut32 q) {
switch (q) {
case R_ARCH_INFO_MINOP_SIZE: return 1;
case R_ARCH_INFO_MAXOP_SIZE: return 8;
default: return 1;
}
}
RArchPlugin r_arch_plugin_swf = {
.meta = {
.name = "swf",
.desc = "SWF",
.author = "xarkes, pancake",
.version = R2_VERSION,
.license = "LGPL3",
.status = R_PLUGIN_STATUS_OK,
},
.arch = "swf",
.bits = R_SYS_BITS_PACK1(32),
.endian = R_SYS_ENDIAN_LITTLE,
.info = &info,
.decode = &decode,
};
#ifndef R2_PLUGIN_INCORE
R_API RLibStruct radare_plugin = {
.type = R_LIB_TYPE_ARCH,
.data = &r_arch_plugin_swf,
.version = R2_VERSION
};
#endif
+248 -895
View File
File diff suppressed because it is too large. Load diff
+53
View File
@@ -0,0 +1,53 @@
#include <r_lib.h>
#include <r_arch.h>
#include <r_util.h>
#include "x86/bea/BeaEngine.h"
static bool decode(RArchSession *as, RAnalOp *op, RArchDecodeMask mask) {
DISASM dis = {0};
dis.EIP = (long long)op->bytes;
dis.VirtualAddr = op->addr;
dis.Archi = ((as && as->config && as->config->bits == 64) ? 64 : 0);
dis.SecurityBlock = op->size;
if (as && as->config && as->config->syntax == R_ARCH_SYNTAX_ATT) {
dis.Options = 0x400;
}
int sz = Disasm(&dis);
op->size = (sz > 0)? sz: 0;
if (mask & R_ARCH_OP_MASK_DISASM) {
op->mnemonic = strdup(dis.CompleteInstr ? dis.CompleteInstr : "invalid");
}
return sz > 0;
}
static int info(RArchSession *s, ut32 q) {
switch (q) {
case R_ARCH_INFO_MINOP_SIZE: return 1;
case R_ARCH_INFO_MAXOP_SIZE: return 15;
default: return 1;
}
}
RArchPlugin r_arch_plugin_x86_bea = {
.meta = {
.name = "x86.bea",
.desc = "x86 BeaEngine disassembler",
.author = "pancake, nibble",
.version = R2_VERSION,
.license = "LGPL",
.status = R_PLUGIN_STATUS_OK,
},
.arch = "x86",
.bits = R_SYS_BITS_PACK3(16, 32, 64),
.endian = R_SYS_ENDIAN_LITTLE,
.info = &info,
.decode = &decode,
};
#ifndef R2_PLUGIN_INCORE
R_API RLibStruct radare_plugin = {
.type = R_LIB_TYPE_ARCH,
.data = &r_arch_plugin_x86_bea,
.version = R2_VERSION
};
#endif
+50
View File
@@ -0,0 +1,50 @@
/* RArch plugin for x86 Olly disassembler */
#include <r_lib.h>
#include <r_arch.h>
#include <r_util.h>
#include "x86/ollyasm/disasm.h"
static bool decode(RArchSession *as, RAnalOp *op, RArchDecodeMask mask) {
t_disasm d = {0};
int sz = Disasm_olly(op->bytes, op->size, op->addr, &d, DISASM_FILE);
if (sz <= 0) {
if (mask & R_ARCH_OP_MASK_DISASM) op->mnemonic = strdup("invalid");
op->size = 0;
return false;
}
if (mask & R_ARCH_OP_MASK_DISASM) op->mnemonic = strdup(d.result ? d.result : "");
op->size = sz;
return true;
}
static int info(RArchSession *s, ut32 q) {
switch (q) {
case R_ARCH_INFO_MINOP_SIZE: return 1;
case R_ARCH_INFO_MAXOP_SIZE: return 15;
default: return 1;
}
}
RArchPlugin r_arch_plugin_x86_olly = {
.meta = {
.name = "x86.olly",
.desc = "OllyDBG x86 disassembler",
.author = "pancake, nibble",
.version = R2_VERSION,
.license = "GPL2",
.status = R_PLUGIN_STATUS_OK,
},
.arch = "x86",
.bits = R_SYS_BITS_PACK3(16, 32, 64),
.endian = R_SYS_ENDIAN_LITTLE,
.info = &info,
.decode = &decode,
};
#ifndef R2_PLUGIN_INCORE
R_API RLibStruct radare_plugin = {
.type = R_LIB_TYPE_ARCH,
.data = &r_arch_plugin_x86_olly,
.version = R2_VERSION
};
#endif
+41
View File
@@ -0,0 +1,41 @@
#include <r_lib.h>
#include <r_arch.h>
static bool decode(RArchSession *as, RAnalOp *op, RArchDecodeMask mask) {
op->type = R_ANAL_OP_TYPE_UNK;
if (mask & R_ARCH_OP_MASK_DISASM) op->mnemonic = strdup("(x86.tab: unimplemented)");
op->size = 0;
return false;
}
static int info(RArchSession *s, ut32 q) {
switch (q) {
case R_ARCH_INFO_MINOP_SIZE: return 1;
case R_ARCH_INFO_MAXOP_SIZE: return 15;
default: return 1;
}
}
RArchPlugin r_arch_plugin_x86_tab = {
.meta = {
.name = "x86.tab",
.desc = "x86 table disassembler (stub)",
.author = "radare2-extras",
.version = R2_VERSION,
.license = "LGPL3",
.status = R_PLUGIN_STATUS_BASIC,
},
.arch = "x86",
.bits = R_SYS_BITS_PACK3(16, 32, 64),
.endian = R_SYS_ENDIAN_LITTLE,
.info = &info,
.decode = &decode,
};
#ifndef R2_PLUGIN_INCORE
R_API RLibStruct radare_plugin = {
.type = R_LIB_TYPE_ARCH,
.data = &r_arch_plugin_x86_tab,
.version = R2_VERSION
};
#endif
+98
View File
@@ -0,0 +1,98 @@
/* radare2-extras: RArch plugin wrapping udis86 for x86 */
#include <r_lib.h>
#include <r_arch.h>
#include <r_asm.h>
#include <string.h>
#include "udis86/types.h"
#include "udis86/extern.h"
static bool decode(RArchSession *as, RAnalOp *op, RArchDecodeMask mask) {
ud_t d;
ud_init(&d);
/* set syntax based on session config */
if (as && as->config) {
switch (as->config->syntax) {
case R_ARCH_SYNTAX_ATT:
ud_set_syntax(&d, UD_SYN_ATT);
break;
default:
ud_set_syntax(&d, UD_SYN_INTEL);
break;
}
ud_set_mode(&d, as->config->bits);
} else {
ud_set_syntax(&d, UD_SYN_INTEL);
ud_set_mode(&d, 32);
}
ud_set_input_buffer(&d, (uint8_t *)op->bytes, op->size);
ud_set_pc(&d, op->addr);
int opsize = ud_disassemble(&d);
if (opsize < 1) {
op->type = R_ANAL_OP_TYPE_ILL;
op->size = 0;
if (mask & R_ARCH_OP_MASK_DISASM) {
op->mnemonic = strdup("invalid");
}
return false;
}
if (mask & R_ARCH_OP_MASK_DISASM) {
const char *asmstr = ud_insn_asm(&d);
if (!asmstr) {
asmstr = "";
}
char *out = strdup(asmstr);
if (as && as->config && as->config->syntax == R_ARCH_SYNTAX_JZ) {
if (!strncmp(out, "je ", 3)) {
memcpy(out, "jz", 2);
} else if (!strncmp(out, "jne ", 4)) {
memcpy(out, "jnz", 3);
}
}
op->mnemonic = out;
}
op->size = opsize;
return true;
}
static int info(RArchSession *s, ut32 q) {
switch (q) {
case R_ARCH_INFO_MINOP_SIZE:
return 1;
case R_ARCH_INFO_MAXOP_SIZE:
return 15;
default:
return 1;
}
}
RArchPlugin r_arch_plugin_x86_udis = {
.meta = {
.name = "x86.udis",
.desc = "udis86 x86-16,32,64",
.author = "pancake, nibble",
.version = R2_VERSION,
.license = "BSD",
.status = R_PLUGIN_STATUS_OK,
},
.arch = "x86",
.bits = R_SYS_BITS_PACK3(16, 32, 64),
.endian = R_SYS_ENDIAN_LITTLE,
.info = &info,
.decode = &decode,
};
#ifndef R2_PLUGIN_INCORE
R_API RLibStruct radare_plugin = {
.type = R_LIB_TYPE_ARCH,
.data = &r_arch_plugin_x86_udis,
.version = R2_VERSION
};
#endif
+40
View File
@@ -0,0 +1,40 @@
#include <r_lib.h>
#include <r_arch.h>
static bool decode(RArchSession *as, RAnalOp *op, RArchDecodeMask mask) {
if (mask & R_ARCH_OP_MASK_DISASM) op->mnemonic = strdup("(zydis: unavailable on this host)");
op->size = 0;
return false;
}
static int info(RArchSession *s, ut32 q) {
switch (q) {
case R_ARCH_INFO_MINOP_SIZE: return 1;
case R_ARCH_INFO_MAXOP_SIZE: return 15;
default: return 1;
}
}
RArchPlugin r_arch_plugin_x86_zyan = {
.meta = {
.name = "x86.zyan",
.desc = "x86 Zydis disassembler (stub on non-x86)",
.author = "mrexodia",
.version = R2_VERSION,
.license = "MIT",
.status = R_PLUGIN_STATUS_BASIC,
},
.arch = "x86",
.bits = R_SYS_BITS_PACK3(16, 32, 64),
.endian = R_SYS_ENDIAN_LITTLE,
.info = &info,
.decode = &decode,
};
#ifndef R2_PLUGIN_INCORE
R_API RLibStruct radare_plugin = {
.type = R_LIB_TYPE_ARCH,
.data = &r_arch_plugin_x86_zyan,
.version = R2_VERSION
};
#endif
+49
View File
@@ -0,0 +1,49 @@
#include <r_lib.h>
#include <r_arch.h>
#include <r_util.h>
#include "../arch/z80/z80.c"
static bool decode(RArchSession *as, RAnalOp *op, RArchDecodeMask mask) {
if (mask & R_ARCH_OP_MASK_DISASM) {
char out[128];
int dlen = z80dis(0, op->bytes, out, op->size);
if (dlen < 0) dlen = 0;
op->size = dlen;
op->mnemonic = strdup(out);
return dlen > 0;
}
return true;
}
static int info(RArchSession *s, ut32 q) {
switch (q) {
case R_ARCH_INFO_MINOP_SIZE: return 1;
case R_ARCH_INFO_MAXOP_SIZE: return 4;
default: return 1;
}
}
RArchPlugin r_arch_plugin_z80 = {
.meta = {
.name = "z80",
.desc = "Zilog Z80",
.author = "pancake",
.version = R2_VERSION,
.license = "NC-GPL2",
.status = R_PLUGIN_STATUS_OK,
},
.arch = "z80",
.bits = R_SYS_BITS_PACK1(8),
.endian = R_SYS_ENDIAN_NONE,
.info = &info,
.decode = &decode,
};
#ifndef R2_PLUGIN_INCORE
R_API RLibStruct radare_plugin = {
.type = R_LIB_TYPE_ARCH,
.data = &r_arch_plugin_z80,
.version = R2_VERSION
};
#endif
+49
View File
@@ -0,0 +1,49 @@
#include <r_lib.h>
#include <r_arch.h>
#include <r_util.h>
#include "../arch/z80_nc/disasm.c"
static bool decode(RArchSession *as, RAnalOp *op, RArchDecodeMask mask) {
if (mask & R_ARCH_OP_MASK_DISASM) {
char out[128];
int dlen = z80dis(0, op->bytes, out, op->size);
if (dlen < 0) dlen = 0;
op->size = dlen;
op->mnemonic = strdup(out);
return dlen > 0;
}
return true;
}
static int info(RArchSession *s, ut32 q) {
switch (q) {
case R_ARCH_INFO_MINOP_SIZE: return 1;
case R_ARCH_INFO_MAXOP_SIZE: return 4;
default: return 1;
}
}
RArchPlugin r_arch_plugin_z80_nc = {
.meta = {
.name = "z80.nc",
.desc = "Zilog Z80 non-commercial",
.author = "pancake",
.version = R2_VERSION,
.license = "NC-GPL2",
.status = R_PLUGIN_STATUS_OK,
},
.arch = "z80",
.bits = R_SYS_BITS_PACK1(8),
.endian = R_SYS_ENDIAN_NONE,
.info = &info,
.decode = &decode,
};
#ifndef R2_PLUGIN_INCORE
R_API RLibStruct radare_plugin = {
.type = R_LIB_TYPE_ARCH,
.data = &r_arch_plugin_z80_nc,
.version = R2_VERSION
};
#endif
+9 -6
View File
@@ -1,14 +1,17 @@
OBJ_ARMTHUMB=asm_armthumb.o
OBJ_ARMTHUMB+=../arch/arm/armthumb.o
OBJ_ARMTHUMB=arch_armthumb.o
OBJ_ARMTHUMB+=armthumb_src.o
STATIC_OBJ+=${OBJ_ARMTHUMB}
TARGET_ARMTHUMB=asm_armthumb.${LIBEXT}
TARGET_ARMTHUMB=arch_armthumb.${LIBEXT}
ALL_TARGETS+=${TARGET_ARMTHUMB}
$(OBJ_ARMTHUMB): %.o : %.c
arch_armthumb.o: arch_armthumb.c
$(CC) -c $(CFLAGS) $< -o $@
armthumb_src.o: ../arch/arm/armthumb.c
$(CC) -c $(CFLAGS) -I../arch/arm -o $@ $<
${TARGET_ARMTHUMB}: ${OBJ_ARMTHUMB}
${CC} $(call libname,asm_armthumb) ${LDFLAGS} \
${CFLAGS} -o asm_armthumb.${LIBEXT} ${OBJ_ARMTHUMB}
${CC} $(call libname,arch_armthumb) ${LDFLAGS} \
${CFLAGS} -o ${TARGET_ARMTHUMB} ${OBJ_ARMTHUMB}
-49
View File
@@ -1,49 +0,0 @@
/* radare - LGPL - Copyright 2010-2018 - pancake */
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include <r_types.h>
#include <r_util.h>
#include <r_lib.h>
#include <r_asm.h>
#include "../arch/arm/arm.h"
static int disassemble(RAsm *a, RAsmOp *op, const ut8 *buf, int len) {
int *p = (int*)buf; // TODO : endian
char buf_asm[64] = {0};
op->size = armthumb_disassemble (buf_asm, (ut32)a->pc, *p);
if (op->size > 0) {
r_strbuf_set (&op->buf_asm, buf_asm);
} else {
r_strbuf_set (&op->buf_asm, " (data)");
}
return op->size;
}
#if 0
static int assemble(RAsm *a, RAsmOp *op, const char *buf) {
int opcode = armass_assemble (buf, a->pc, true);
if (opcode==-1)
return -1;
r_mem_copyendian (op->buf, (void *)&opcode, 2, a->big_endian);
return armthumb_length (opcode);
}
#endif
RAsmPlugin r_asm_plugin_armthumb = {
.name = "arm.thumb",
.arch = "arm",
.bits = 16,
.desc = "ARM THUMB disassembly plugin",
.disassemble = &disassemble,
// .assemble = &assemble
};
#ifndef R2_PLUGIN_INCORE
RLibStruct radare_plugin = {
.type = R_LIB_TYPE_ASM,
.data = &r_asm_plugin_armthumb,
.version = R2_VERSION
};
#endif
-40
View File
@@ -1,40 +0,0 @@
/* radare - LGPL - Copyright 2018 - damo22 */
#include <r_types.h>
#include <r_lib.h>
#include <r_asm.h>
#include "../arch/atombios/atombios.h"
static int disassemble(RAsm *a, RAsmOp *op, const ut8 *buf, int len) {
char res[1024];
res[0] = 0;
op->size = atombios_disassemble (buf, len, res);
r_strbuf_set (&op->buf_asm, res);
return op->size;
}
static int assemble(RAsm *a, RAsmOp *op, const char *buf) {
return 0; // n
}
RAsmPlugin r_asm_plugin_atombios = {
.name = "atombios",
.author = "damo22",
.version = "0.0.1",
.arch = "atombios",
.license = "LGPL3",
.bits = 32 | 64,
.endian = R_SYS_ENDIAN_NONE,
.desc = "AtomBIOS",
.disassemble = &disassemble,
.assemble = &assemble
};
#ifndef CORELIB
RLibStruct radare_plugin = {
.type = R_LIB_TYPE_ASM,
.data = &r_asm_plugin_atombios,
.version = R2_VERSION
};
#endif
-47
View File
@@ -1,47 +0,0 @@
#include <stdio.h>
#include <string.h>
#include <r_types.h>
#include <r_lib.h>
#include <r_util.h>
#include <r_asm.h>
#include "../../asm/arch/ba2/ba2_disas.c"
static int disassemble(RAsm *a, RAsmOp *op, const ut8 *buf, int len) {
struct op_cmd cmd = {
.instr = "",
.operands = ""
};
int ret = ba2_decode_opcode (a->pc, buf, len, &cmd, NULL, NULL);
if((len < ret) || (!ret && len<6)){
r_strbuf_set (&op->buf_asm, "truncated");
op->size = 0;
return 0;
}
if (ret > 0) {
snprintf (op->buf_asm.buf, sizeof(op->buf_asm.buf), "%s %s", cmd.instr, cmd.operands);
}else{
r_strbuf_set (&op->buf_asm, "invalid");
return -1;
}
return op->size = ret;
}
RAsmPlugin r_asm_plugin_ba2 = {
.name = "ba2",
.license = "LGPL3",
.desc = "Beyond Architecture 2 disassembly plugin",
.arch = "ba2",
.bits = 32,
.endian = R_SYS_ENDIAN_LITTLE,
.disassemble = &disassemble
};
#ifndef R2_PLUGIN_INCORE
R_API RLibStruct radare_plugin = {
.type = R_LIB_TYPE_ASM,
.data = &r_asm_plugin_ba2,
.version = R2_VERSION
};
#endif
-47
View File
@@ -1,47 +0,0 @@
/* radare2 - LGPL - Copyright 2012-2021 pancake */
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include <r_types.h>
#include <r_util.h>
#include <r_lib.h>
#include <r_asm.h>
#include "../arch/dcpu16/dcpu16.h"
#include "../arch/dcpu16/dis.c"
#include "../arch/dcpu16/asm.c"
static int disassemble(RAsm *a, RAsmOp *op, const ut8 *buf, int len) {
char buf_asm[96];
if (len < 2) {
return -1; // at least 2 bytes!
}
op->size = dcpu16_disasm (buf_asm, sizeof (buf_asm), (const ut16*)buf, len, NULL);
r_strbuf_set (&op->buf_asm, (op->size > 0) ? buf_asm: "(data)");
return op->size;
}
static int assemble(RAsm *a, RAsmOp *op, const char *buf) {
int len = dcpu16_assemble ((ut8*)r_strbuf_get (&op->buf), buf);
op->buf.len = len;
return len;
}
RAsmPlugin r_asm_plugin_dcpu16 = {
.name = "dcpu16",
.arch = "dpcu",
.bits = 16,
.endian = R_SYS_ENDIAN_LITTLE,
.desc = "Mojang's DCPU-16",
.license = "PD",
.disassemble = &disassemble,
.assemble = &assemble
};
#ifndef R2_PLUGIN_INCORE
R_API RLibStruct radare_plugin = {
.type = R_LIB_TYPE_ASM,
.data = &r_asm_plugin_dcpu16,
.version = R2_VERSION
};
#endif
-63
View File
@@ -1,63 +0,0 @@
/* radare - GPL3 - Copyright 2009-2015 - nibble */
#include <stdio.h>
#include <string.h>
#include <r_types.h>
#include <r_lib.h>
#include <r_util.h>
#include <r_asm.h>
#include "m68k/m68k_disasm/m68k_disasm.h"
static int disassemble(RAsm *a, RAsmOp *aop, const ut8 *buf, int len) {
m68k_word bof[8] = {0};
int iaddr = (int)a->pc;
char opcode[256], operands[256];
const unsigned char *buf2;
int ilen ;
static struct DisasmPara_68k dp;
char *buf_asm;
r_strf_buffer (256);
/* initialize DisasmPara */
*operands = *opcode = 0;
memcpy (bof, buf, R_MIN(len, sizeof(bof)));
dp.opcode = opcode;
dp.operands = operands;
dp.iaddr = (m68k_word *) (size_t)iaddr;
dp.instr = bof;
buf2 = (const ut8*)M68k_Disassemble (&dp);
if (!buf2) {
// invalid instruction
return aop->size = 2;
}
ilen = buf2 - (const ut8*)bof;
if (*operands) {
buf_asm = r_strf ("%s %s", opcode, operands);
} else {
buf_asm = r_strf ("%s", opcode);
}
r_str_replace_ch (buf_asm, '#', 0, 1);
r_asm_op_set_asm (aop, buf_asm);
aop->size = ilen;
return aop->size;
}
RAsmPlugin r_asm_plugin_m68k = {
.name = "m68k.net",
.arch = "m68k",
.license = "BSD",
.bits = 16|32,
.endian = R_SYS_ENDIAN_BIG,
.desc = "Motorola 68000",
.disassemble = &disassemble,
};
#ifndef CORELIB
RLibStruct radare_plugin = {
.type = R_LIB_TYPE_ASM,
.data = &r_asm_plugin_m68k,
.version = R2_VERSION
};
#endif
File diff suppressed because it is too large. Load diff
-43
View File
@@ -1,43 +0,0 @@
/* radare - Public Domain - Copyright 2011-2015 - capi_x, pancake */
#include <stdio.h>
#include <r_types.h>
#include <r_lib.h>
#include <r_util.h>
#include <r_asm.h>
#include "msil/demsil.c"
static int arch_msil_disasm(RStrBuf *buf_asm, const ut8 *buf, ut64 seek) {
ut32 n;
int o;
DISASMSIL_OFFSET CodeBase = seek;
ILOPCODE_STRUCT ilopar[8];
o = DisasMSIL (buf, 16, CodeBase, ilopar, 8, &n);
r_strbuf_setf (buf_asm, "%s", ilopar[0].Mnemonic);
return o;
}
static int disassemble(RAsm *a, RAsmOp *op, const ut8 *buf, int len) {
return (op->size = arch_msil_disasm (&op->buf_asm, buf, a->pc));
}
RAsmPlugin r_asm_plugin_msil = {
.name = "msil",
.arch = "msil",
.license = "PD",
.bits = 16|32|64,
.desc = ".NET Microsoft Intermediate Language",
.init = NULL,
.fini = NULL,
.disassemble = &disassemble,
.assemble = NULL
};
#ifndef CORELIB
RLibStruct radare_plugin = {
.type = R_LIB_TYPE_ASM,
.data = &r_asm_plugin_msil,
.version = R2_VERSION
};
#endif
-48
View File
@@ -1,48 +0,0 @@
/* radare - GPL3 - Copyright 2009-2018 pancake, nibble */
#include <stdio.h>
#include <string.h>
#include <r_types.h>
#include <r_lib.h>
#include <r_util.h>
#include <r_asm.h>
#include "ppc/ppc_disasm/ppc_disasm.h"
static int disassemble(RAsm *a, RAsmOp *aop, const ut8 *buf, int len) {
ppc_word iaddr = (ppc_word)a->pc;
ppc_word bof[4];
char opcode[128];
char operands[128];
static struct DisasmPara_PPC dp;
/* initialize DisasmPara */
memcpy (bof, buf, 4);
dp.opcode = opcode;
dp.operands = operands;
dp.iaddr = &iaddr;
dp.instr = bof;
PPC_Disassemble (&dp, a->config->big_endian);
char res[64] = {0};
snprintf (res, sizeof (res), "%s %s", opcode, operands);
r_strbuf_set (&aop->buf_asm, res);
aop->size = 4;
return aop->size;
}
RAsmPlugin r_asm_plugin_ppc_disasm = {
.name = "ppc.disasm",
.arch = "ppc",
.bits = 32,
.desc = "Tiny PowerPC disassembly plugin",
.disassemble = &disassemble,
};
#ifndef CORELIB
RLibStruct radare_plugin = {
.type = R_LIB_TYPE_ASM,
.data = &r_asm_plugin_ppc_disasm,
.version = R2_VERSION
};
#endif
-44
View File
@@ -1,44 +0,0 @@
/* radare - LGPL - Copyright 2009-2013 - nibble */
#include <r_types.h>
#include <r_util.h>
#include <r_lib.h>
#include <r_asm.h>
#include <psosvm/vmas/vmas.h>
static int disassemble(RAsm *a, struct r_asm_op_t *op, const ut8 *buf, int len) {
char buf_asm[64] = {0};
psosvmasm_init();
op->size = psosvm_disasm(buf, buf_asm);
if (op->size > 0) {
r_asm_op_set_asm (op, buf_asm);
} else {
r_asm_op_set_asm (op, " (data)");
}
return op->size;
}
static int assemble(RAsm *a, RAsmOp *op, const char *buf) {
op->size = psosvm_assemble((ut8*)r_strbuf_get (&op->buf), buf);
return op->size;
}
RAsmPlugin r_asm_plugin_psosvm = {
.name = "psosvm",
.desc = "Smartcard PSOS Virtual Machine",
.license = "BSD",
.arch = "psosvm",
.bits = 8|16,
.init = NULL,
.fini = NULL,
.disassemble = &disassemble,
.assemble = &assemble
};
#ifndef CORELIB
struct r_lib_struct_t radare_plugin = {
.type = R_LIB_TYPE_ASM,
.data = &r_asm_plugin_psosvm,
.version = R2_VERSION
};
#endif
-35
View File
@@ -1,35 +0,0 @@
/* radare - LGPL - Copyright 2012-2020 - pancake, condret */
#include <r_types.h>
#include <r_util.h>
#include <r_asm.h>
#include <sdb.h>
#include <r_lib.h>
#include "../arch/spc700/spc700dis.c"
static int disassemble(RAsm *a, RAsmOp *r_op, const ut8 *buf, int len) {
int dlen = spc700Disass (r_op, buf, len);
if (dlen < 0) {
dlen = 0;
}
r_op->size = dlen;
return dlen;
}
RAsmPlugin r_asm_plugin_spc700 = {
.name = "spc700",
.desc = "spc700, snes' sound-chip",
.arch = "spc700",
.license = "LGPL3",
.bits = 16,
.endian = R_SYS_ENDIAN_NONE, // is this LE?
.disassemble = &disassemble,
};
#ifndef R2_PLUGIN_INCORE
R_API RLibStruct radare_plugin = {
.type = R_LIB_TYPE_ASM,
.data = &r_asm_plugin_spc700,
.version = R2_VERSION
};
#endif
-33
View File
@@ -1,33 +0,0 @@
/* radare - LGPL3 - Copyright 2016-2021 - xarkes, pancake */
#include <r_types.h>
#include <r_lib.h>
#include <r_util.h>
#include <r_asm.h>
#include "../arch/swf/swfdis.h"
static int disassemble(RAsm *a, RAsmOp *op, const ut8 *buf, int len) {
RBin *bin = a->binb.bin;
RBinObject *obj = bin->cur->o;
int dlen = r_asm_swf_disass (obj, &op->buf_asm, buf, len, a->pc);
op->size = dlen;
return dlen;
}
RAsmPlugin r_asm_plugin_swf = {
.name = "swf",
.arch = "swf",
.license = "LGPL3",
.bits = 32,
.desc = "SWF",
.disassemble = &disassemble,
};
#ifndef CORELIB
struct r_lib_struct_t radare_plugin = {
.type = R_LIB_TYPE_ASM,
.data = &r_asm_plugin_swf,
.version = R2_VERSION
};
#endif
-47
View File
@@ -1,47 +0,0 @@
/* radare - GPL3 - Copyright 2009-2015 - pancake, nibble */
#include <stdio.h>
#include <string.h>
#include <r_types.h>
#include <r_lib.h>
#include <r_util.h>
#include <r_asm.h>
#include "x86/bea/BeaEngine.h"
//#include "fastcall_x86.h"
static int disassemble(RAsm *a, RAsmOp *aop, const ut8 *buf, int len) {
static DISASM disasm_obj;
memset (&disasm_obj, '\0', sizeof (DISASM));
disasm_obj.EIP = (long long)buf;
disasm_obj.VirtualAddr = a->pc;
disasm_obj.Archi = ((a->config->bits == 64) ? 64 : 0);
disasm_obj.SecurityBlock = len;
if (a->config->syntax == R_ASM_SYNTAX_ATT)
disasm_obj.Options = 0x400;
else disasm_obj.Options = 0;
aop->size = Disasm (&disasm_obj);
r_asm_op_set_asm (aop, disasm_obj.CompleteInstr);
return aop->size;
}
static RAsmPlugin r_asm_plugin_x86_bea = {
.name = "x86.bea",
.desc = "x86 BeaEngine disassembler plugin",
.arch = "x86",
.bits = 16 | 32 | 64,
.disassemble = &disassemble,
.license = "LGPL"
};
#ifndef CORELIB
struct r_lib_struct_t radare_plugin = {
.type = R_LIB_TYPE_ASM,
.data = &r_asm_plugin_x86_bea,
.version = R2_VERSION
};
#endif
-60
View File
@@ -1,60 +0,0 @@
/* radare - LGPL - Copyright 2009-2018 - pancake, nibble */
#include <stdio.h>
#include <string.h>
#include <r_types.h>
#include <r_lib.h>
#include <r_asm.h>
#include "x86/ollyasm/disasm.h"
static int disassemble(RAsm *a, RAsmOp *op, const ut8 *buf, int len) {
t_disasm disasm_obj;
op->size = Disasm_olly (buf, len, a->pc, &disasm_obj, DISASM_FILE);
r_asm_op_set_asm (op, disasm_obj.result);
return op->size;
}
static int assemble(RAsm *a, RAsmOp *op, const char *buf) {
char buf_err[128];
static t_asmmodel asm_obj;
int attempt, constsize, oattempt = 0, oconstsize = 0, ret = 0, oret = 0xCAFE;
/* attempt == 0: First attempt */
/* constsize == 0: Address constants and inmediate data of 16/32b */
for (constsize = 0; constsize < 4; constsize++) {
for (attempt = 0; ret > 0; attempt++) {
ret = Assemble ((char*)buf, a->pc, &asm_obj, attempt, constsize, buf_err);
if (ret > 0 && ret < oret) {
oret = ret;
oattempt = attempt;
oconstsize = constsize;
}
}
}
op->size = R_MAX (0, Assemble ((char*)buf, a->pc, &asm_obj, oattempt, oconstsize, buf_err));
if (op->size > 0) {
r_asm_op_set_buf (op, (const ut8*)asm_obj.code, R_MIN (16, op->size));
}
return op->size;
}
RAsmPlugin r_asm_plugin_x86_olly = {
.name = "x86.olly",
.license = "GPL2",
.desc = "OllyDBG X86 disassembler",
.arch = "x86",
.bits = 32,
.endian = R_SYS_ENDIAN_LITTLE,
.disassemble = &disassemble,
.assemble = &assemble,
};
#ifndef CORELIB
RLibStruct radare_plugin = {
.type = R_LIB_TYPE_ASM,
.data = &r_asm_plugin_x86_olly,
.version = R2_VERSION
};
#endif
File diff suppressed because it is too large. Load diff
-91
View File
@@ -1,91 +0,0 @@
/* radare - LGPL - Copyright 2009-2018 - pancake, nibble */
#include <stdio.h>
#include <string.h>
#include <r_types.h>
#include <r_lib.h>
#include <r_asm.h>
#include "udis86/types.h"
#include "udis86/extern.h"
// TODO : split into get/set... we need a way to create binary masks from asm buffers
// -- move this shit into r_anal.. ??
// -- delta, size, mode.. mode is for a->pc-5, register handling and things like this
static bool modify(RAsm *a, ut8 *buf, int field, ut64 val) {
ut32 val32 = (ut32)val;
switch (buf[0]) {
case 0x68: // push dword
if (field == R_ASM_MOD_RAWVALUE || field == R_ASM_MOD_VALUE) {
memcpy (buf+1, &val, sizeof (val32));
}
return 5;
case 0xe8: // call
if (field == R_ASM_MOD_RAWVALUE) {
memcpy (buf+1, &val32, sizeof (val32));
} else
if (field == R_ASM_MOD_VALUE) {
val32 = (ut32)(val-a->pc-5);
memcpy (buf+1, &val32, sizeof (val32));
}
return 5;
case 0xeb: // jmp short
case 0x73: // jnz
if (field == R_ASM_MOD_RAWVALUE) {
buf[1] = (char)val;
} else
if (field == R_ASM_MOD_VALUE) {
buf[1] = (char)(val-a->pc);
}
return 2;
}
return 0;
}
static int disassemble(RAsm *a, RAsmOp *op, const ut8 *buf, int len) {
int opsize;
static ud_t d = {0};
static int osyntax = 0;
if (!d.dis_mode)
ud_init (&d);
if (osyntax != a->config->syntax) {
ud_set_syntax (&d, (a->config->syntax==R_ASM_SYNTAX_ATT)?
UD_SYN_ATT: UD_SYN_INTEL);
osyntax = a->config->syntax;
}
ud_set_input_buffer (&d, (uint8_t*) buf, len);
ud_set_pc (&d, a->pc);
ud_set_mode (&d, a->config->bits);
opsize = ud_disassemble (&d);
r_strbuf_set (&op->buf_asm, ud_insn_asm (&d));
char *buf_asm = r_strbuf_get (&op->buf_asm);
if (opsize<1 || strstr (buf_asm, "invalid"))
opsize = 0;
op->size = opsize;
if (a->config->syntax == R_ASM_SYNTAX_JZ) {
if (!strncmp (buf_asm, "je ", 3)) {
memcpy (buf_asm, "jz", 2);
} else if (!strncmp (buf_asm, "jne ", 4)) {
memcpy (buf_asm, "jnz", 3);
}
}
return opsize;
}
RAsmPlugin r_asm_plugin_x86_udis = {
.name = "x86.udis",
.desc = "udis86 x86-16,32,64",
.arch = "x86",
.license = "BSD",
.bits = 16 | 32 | 64,
.endian = R_SYS_ENDIAN_LITTLE,
.disassemble = &disassemble,
.modify = &modify,
};
#ifndef CORELIB
RLibStruct radare_plugin = {
.type = R_LIB_TYPE_ASM,
.data = &r_asm_plugin_x86_udis,
.version = R2_VERSION
};
#endif
-47
View File
@@ -1,47 +0,0 @@
/* radare - GPL3 - Copyright 2017 - mrexodia */
#include <stdio.h>
#include <string.h>
#include <r_types.h>
#include <r_lib.h>
#include <r_util.h>
#include <r_asm.h>
#include "x86/zyan/include/Zydis/Zydis.h"
static int disassemble(RAsm *a, RAsmOp *aop, const ut8 *buf, int len) {
static ZydisInstructionDecoder decr;
static ZydisInstructionInfo info;
static ZydisInstructionFormatter fmtr;
ZydisDecoderInitInstructionDecoder (&decr, a->config->bits);
memset (&info, 0, sizeof (info));
ZydisStatus st = ZydisDecoderDecodeInstruction (&decr, buf, len, a->pc, &info);
if (ZYDIS_SUCCESS (st)) {
ZydisFormatterInitInstructionFormatter (&fmtr, ZYDIS_FORMATTER_STYLE_INTEL);
char str[128];
str[0] = 0;
ZydisFormatterFormatInstruction (&fmtr, &info, str, sizeof (str));
r_strbuf_set (&aop->buf_asm, str);
}
return aop->size = info.length;
}
static RAsmPlugin r_asm_plugin_x86_zyan = {
.name = "x86.zyan",
.desc = "x86 Zyan Disassembler Engine plugin",
.arch = "x86",
.bits = 16 | 32 | 64,
.disassemble = &disassemble,
.license = "MIT"
};
#ifndef CORELIB
RLibStruct radare_plugin = {
.type = R_LIB_TYPE_ASM,
.data = &r_asm_plugin_x86_zyan,
.version = R2_VERSION
};
#endif
-38
View File
@@ -1,38 +0,0 @@
/* radare - LGPL - Copyright 2012-2013 - pancake */
#include <r_types.h>
#include <r_util.h>
#include <r_lib.h>
#include <r_asm.h>
#include "../arch/z80/z80.c"
static int do_assemble(RAsm *a, RAsmOp *op, const char *buf) {
return op->size = z80asm (op->buf, buf);
}
static int do_disassemble(RAsm *a, RAsmOp *op, const ut8 *buf, int len) {
int dlen = z80dis (0, buf, op->buf_asm, len);
if (dlen<0) dlen = 0;
op->size = dlen;
return op->size;
}
RAsmPlugin r_asm_plugin_z80 = {
.name = "z80",
.desc = "Zilog Z80",
.license = "NC-GPL2", //NON-COMMERCIAL",
.arch = "z80",
.bits = 8,
.endian = R_SYS_ENDIAN_NONE,
.disassemble = &do_disassemble,
.assemble = &do_assemble,
};
#ifndef CORELIB
struct r_lib_struct_t radare_plugin = {
.type = R_LIB_TYPE_ASM,
.data = &r_asm_plugin_z80,
.version = R2_VERSION
};
#endif
-34
View File
@@ -1,34 +0,0 @@
/* radare - LGPL - Copyright 2012-2020 - pancake */
#include <r_types.h>
#include <r_util.h>
#include <r_lib.h>
#include <r_asm.h>
#include "../arch/z80_nc/disasm.c"
static int do_disassemble(RAsm *a, RAsmOp *op, const ut8 *buf, int len) {
char str[128];
int dlen = z80dis (0, buf, str, len);
r_strbuf_set (&op->buf_asm, str);
if (dlen<0) dlen = 0;
op->size = dlen;
return op->size;
}
RAsmPlugin r_asm_plugin_z80 = {
.name = "z80.nc",
.desc = "Zilog Z80 non-commerical",
.license = "NC-GPL2", //NON-COMMERCIAL",
.arch = "z80",
.bits = 8,
.endian = R_SYS_ENDIAN_NONE,
.disassemble = &do_disassemble,
};
#ifndef CORELIB
RLibStruct radare_plugin = {
.type = R_LIB_TYPE_ASM,
.data = &r_asm_plugin_z80,
.version = R2_VERSION
};
#endif
+4 -4
View File
@@ -1,12 +1,12 @@
OBJ_ATOMBIOS=asm_atombios.o
OBJ_ATOMBIOS=arch_atombios.o
OBJ_ATOMBIOS+=../arch/atombios/atombios.o
TARGET_ATOMBIOS=asm_atombios.${LIBEXT}
TARGET_ATOMBIOS=arch_atombios.${LIBEXT}
STATIC_OBJ+=${OBJ_ATOMBIOS}
$(OBJ_ATOMBIOS): %.o : %.c
arch_atombios.o: arch_atombios.c
$(CC) -c $(CFLAGS) $< -o $@
ALL_TARGETS+=${TARGET_ATOMBIOS}
${TARGET_ATOMBIOS}: ${OBJ_ATOMBIOS}
${CC} -g $(call libname,asm_atombios) ${LDFLAGS} ${CFLAGS} -o ${TARGET_ATOMBIOS} ${OBJ_ATOMBIOS} -lr_util
${CC} -g $(call libname,arch_atombios) ${LDFLAGS} ${CFLAGS} -o ${TARGET_ATOMBIOS} ${OBJ_ATOMBIOS}
+3 -3
View File
@@ -1,9 +1,9 @@
OBJ_BA2=asm_ba2.o
OBJ_BA2=arch_ba2.o
CFLAGS_BA2=$(CFLAGS)
CFLAGS_BA2+=-I../arch/ba2/
STATIC_OBJ+=${OBJ_BA2}
TARGET_BA2=asm_ba2.${LIBEXT}
TARGET_BA2=arch_ba2.${LIBEXT}
ALL_TARGETS+=${TARGET_BA2}
@@ -11,4 +11,4 @@ $(OBJ_BA2): %.o : %.c
$(CC) -c $(CFLAGS_BA2) $< -o $@
${TARGET_BA2}: ${OBJ_BA2}
${CC} -lr_util ${CFLAGS_BA2} -o ${TARGET_BA2} ${OBJ_BA2}
${CC} ${LDFLAGS} ${CFLAGS_BA2} -o ${TARGET_BA2} ${OBJ_BA2}
+3 -3
View File
@@ -1,13 +1,13 @@
OBJ_DCPU16=asm_dcpu16.o
OBJ_DCPU16=arch_dcpu16.o
#OBJ_DCPU16+=../arch/dcpu16/asm.o
#OBJ_DCPU16+=../arch/dcpu16/dis.o
STATIC_OBJ+=${OBJ_DCPU16}
TARGET_DCPU16=asm_dcpu16.${EXT_SO}
TARGET_DCPU16=arch_dcpu16.${EXT_SO}
ifeq ($(WITHPIC),1)
ALL_TARGETS+=${TARGET_DCPU16}
${TARGET_DCPU16}: ${OBJ_DCPU16}
${CC} $(call libname,asm_dcpu16) ${LDFLAGS} ${CFLAGS} -o asm_dcpu16.${EXT_SO} ${OBJ_DCPU16}
${CC} $(call libname,arch_dcpu16) ${LDFLAGS} ${CFLAGS} -o ${TARGET_DCPU16} ${OBJ_DCPU16}
endif
+3 -3
View File
@@ -1,10 +1,10 @@
OBJ_M68K=asm_m68k_net.o
OBJ_M68K=arch_m68k_net.o
OBJ_M68K+=../arch/m68k/m68k_disasm/m68k_disasm.o
STATIC_OBJ+=${OBJ_M68K}
TARGET_M68K=asm_m68k_net.${LIBEXT}
TARGET_M68K=arch_m68k_net.${LIBEXT}
ALL_TARGETS+=${TARGET_M68K}
${TARGET_M68K}: ${OBJ_M68K}
${CC} -shared ${CFLAGS} -o asm_m68k_net.${LIBEXT} ${OBJ_M68K} ${LDFLAGS}
${CC} -shared ${CFLAGS} -o ${TARGET_M68K} ${OBJ_M68K} ${LDFLAGS}
+4 -4
View File
@@ -1,8 +1,8 @@
OBJ_MC6809=asm_mc6809.o
OBJ_MC6809=arch_mc6809.o
STATIC_OBJ+=${OBJ_MC6809}
TARGET_MC6809=asm_mc6809.${LIBEXT}
TARGET_MC6809=arch_mc6809.${LIBEXT}
ALL_TARGETS+=${TARGET_MC6809}
@@ -10,5 +10,5 @@ $(OBJ_MC6809): %.o : %.c
$(CC) -c $(CFLAGS) $< -o $@
${TARGET_MC6809}: ${OBJ_MC6809}
${CC} $(call libname,asm_mc6809) ${LDFLAGS} \
${CFLAGS} -o asm_mc6809.${LIBEXT} ${OBJ_MC6809}
${CC} $(call libname,arch_mc6809) ${LDFLAGS} \
${CFLAGS} -o ${TARGET_MC6809} ${OBJ_MC6809}
+3 -5
View File
@@ -1,15 +1,13 @@
OBJ_MSIL=asm_msil.o
OBJ_MSIL=arch_msil.o
#OBJ_MSIL+=../arch/msil/demsil.o
STATIC_OBJ+=${OBJ_MSIL}
TARGET_MSIL=asm_msil.${LIBEXT}
TARGET_MSIL=arch_msil.${LIBEXT}
#ifeq ($(WITHPIC),1)
ALL_TARGETS+=${TARGET_MSIL}
$(OBJ_MSIL): %.o : %.c
$(CC) -c $(CFLAGS) $< -o $@
${TARGET_MSIL}: ${OBJ_MSIL}
${CC} $(call libname,asm_msil) ${LDFLAGS} ${CFLAGS} -o asm_msil.${LIBEXT} ${OBJ_MSIL}
#endif
${CC} $(call libname,arch_msil) ${LDFLAGS} ${CFLAGS} -o ${TARGET_MSIL} ${OBJ_MSIL}
+8 -3
View File
@@ -1,9 +1,14 @@
OBJ_PPC_DISASM+=../arch/ppc/ppc_disasm/ppc_disasm.o asm_ppc_disasm.o
OBJ_PPC_DISASM=arch_ppc_disasm.o
OBJ_PPC_DISASM+=../arch/ppc/ppc_disasm/ppc_disasm.o
STATIC_OBJ+=${OBJ_PPC_DISASM}
TARGET_PPC_DISASM=asm_ppc_disasm.${LIBEXT}
TARGET_PPC_DISASM=arch_ppc_disasm.${LIBEXT}
ALL_TARGETS+=${TARGET_PPC_DISASM}
${TARGET_PPC_DISASM}: ${OBJ_PPC_DISASM}
${CC} ${CFLAGS} -o asm_ppc_disasm.${LIBEXT} ${OBJ_PPC_DISASM} ${LDFLAGS}
${CC} ${CFLAGS} -o ${TARGET_PPC_DISASM} ${OBJ_PPC_DISASM} ${LDFLAGS}
# Keep older r2pm recipes working until they use the arch_ target.
asm_ppc_disasm.${LIBEXT}: ${TARGET_PPC_DISASM}
cp -f ${TARGET_PPC_DISASM} $@
+3 -3
View File
@@ -1,10 +1,10 @@
OBJ_PSOSVM=asm_psosvm.o
OBJ_PSOSVM=arch_psosvm.o
OBJ_PSOSVM+=../arch/psosvm/vmas/vmas.o
STATIC_OBJ+=${OBJ_PSOSVM}
TARGET_PSOSVM=asm_psosvm.${LIBEXT}
TARGET_PSOSVM=arch_psosvm.${LIBEXT}
ALL_TARGETS+=${TARGET_PSOSVM}
${TARGET_PSOSVM}: ${OBJ_PSOSVM}
${CC} $(call libname,asm_psosvm) ${LDFLAGS} ${CFLAGS} -o asm_psosvm.${LIBEXT} ${OBJ_PSOSVM}
${CC} $(call libname,arch_psosvm) ${LDFLAGS} ${CFLAGS} -o ${TARGET_PSOSVM} ${OBJ_PSOSVM}
+3 -3
View File
@@ -1,9 +1,9 @@
OBJ_SPC700=asm_spc700.o
OBJ_SPC700=arch_spc700.o
STATIC_OBJ+=${OBJ_SPC700}
TARGET_SPC700=asm_spc700.${LIBEXT}
TARGET_SPC700=arch_spc700.${LIBEXT}
ALL_TARGETS+=${TARGET_SPC700}
${TARGET_SPC700}: ${OBJ_SPC700}
${CC} $(call libname,asm_spc700) ${CFLAGS} -o ${TARGET_SPC700} ${OBJ_SPC700} -lr_asm -lr_util
${CC} $(call libname,arch_spc700) ${LDFLAGS} ${CFLAGS} -o ${TARGET_SPC700} ${OBJ_SPC700}
+3 -3
View File
@@ -1,11 +1,11 @@
OBJ_SWF=asm_swf.o
OBJ_SWF=arch_swf.o
OBJ_SWF+=../arch/swf/swfdis.o
STATIC_OBJ+=${OBJ_SWF}
TARGET_SWF=asm_swf.$(LIBEXT)
TARGET_SWF=arch_swf.$(LIBEXT)
ALL_TARGETS+=${TARGET_SWF}
CFLAGS_SWF=-I../arch/swf
${TARGET_SWF}: ${OBJ_SWF}
${CC} ${CFLAGS} ${CFLAGS_SWF} $(LDFLAGS) -o ${TARGET_SWF} ${OBJ_SWF} -lr_util
${CC} ${CFLAGS} ${CFLAGS_SWF} $(LDFLAGS) -o ${TARGET_SWF} ${OBJ_SWF}
+28 -16
View File
@@ -1,18 +1,13 @@
OBJ_VC4=arch_vc4.o
OBJ_VC4+=../arch/vc4/vc4-dis.o
OBJ_VC4+=../arch/vc4/vc4-asm.o
OBJ_VC4+=../arch/vc4/vc4-desc.o
OBJ_VC4+=../arch/vc4/vc4-ibld.o
OBJ_VC4+=../arch/vc4/vc4-opc.o
OBJ_VC4+=../arch/vc4/cgen-bitset.o
OBJ_VC4+=../arch/vc4/cgen-dis.o
OBJ_VC4+=../arch/vc4/cgen-asm.o
OBJ_VC4+=../arch/vc4/cgen-opc.o
OBJ_VC4+=../arch/vc4/libvc4/eval.o
OBJ_VC4+=../arch/vc4/libvc4/decode.o
OBJ_VC4+=../arch/vc4/libvc4/vc4_decode.o
OBJ_VC4+=../arch/vc4/libvc4/vc4_arch.o
OBJ_VC4+=../arch/vc4/libvc4/vc4_util.o
OBJ_VC4+=vc4-dis.o
OBJ_VC4+=vc4-asm.o
OBJ_VC4+=vc4-desc.o
OBJ_VC4+=vc4-ibld.o
OBJ_VC4+=vc4-opc.o
OBJ_VC4+=cgen-bitset.o
OBJ_VC4+=cgen-dis.o
OBJ_VC4+=cgen-asm.o
OBJ_VC4+=cgen-opc.o
SRC_VC4=$(patsubst %.o, %.c, $(OBJ_VC4))
@@ -20,14 +15,31 @@ CFLAGS_VC4=$(R2_CFLAGS)
CFLAGS_VC4+=-g -I$(TOP)/shlr
CFLAGS_VC4+=-Wall -shared -fPIC ${LDFLAGS_LIB}
CFLAGS_VC4+=-I../arch/vc4/ -I../arch/vc4/libvc4/ -I../arch/vc4/include/ -I../arch/vc4/include/opcode/ -I../arch/include/
CFLAGS_VC4+=-I../arch/vc4/ -I../arch/vc4/include/ -I../arch/vc4/include/opcode/ -I../arch/include/
CFLAGS+=$(CFLAGS_VC4)
STATIC_OBJ+=${OBJ_VC4}
TARGET_VC4=arch_vc4.${LIBEXT}
ALL_TARGETS+=${TARGET_VC4}
$(OBJ_VC4): %.o : %.c
vc4-dis.o: ../arch/vc4/vc4-dis.c
$(CC) -c $(CFLAGS_VC4) $< -o $@
vc4-asm.o: ../arch/vc4/vc4-asm.c
$(CC) -c $(CFLAGS_VC4) $< -o $@
vc4-desc.o: ../arch/vc4/vc4-desc.c
$(CC) -c $(CFLAGS_VC4) $< -o $@
vc4-ibld.o: ../arch/vc4/vc4-ibld.c
$(CC) -c $(CFLAGS_VC4) $< -o $@
vc4-opc.o: ../arch/vc4/vc4-opc.c
$(CC) -c $(CFLAGS_VC4) $< -o $@
cgen-bitset.o: ../arch/vc4/cgen-bitset.c
$(CC) -c $(CFLAGS_VC4) $< -o $@
cgen-dis.o: ../arch/vc4/cgen-dis.c
$(CC) -c $(CFLAGS_VC4) $< -o $@
cgen-asm.o: ../arch/vc4/cgen-asm.c
$(CC) -c $(CFLAGS_VC4) $< -o $@
cgen-opc.o: ../arch/vc4/cgen-opc.c
$(CC) -c $(CFLAGS_VC4) $< -o $@
${TARGET_VC4}: ${OBJ_VC4}
+3 -3
View File
@@ -1,8 +1,8 @@
OBJ_X86_BEA=asm_x86_bea.o
OBJ_X86_BEA=arch_x86_bea.o
OBJ_X86_BEA+=../arch/x86/bea/BeaEngine.o
STATIC_OBJ+=${OBJ_X86_BEA}
TARGET_X86_BEA=asm_x86_bea.$(LIBEXT)
TARGET_X86_BEA=arch_x86_bea.$(LIBEXT)
ALL_TARGETS+=${TARGET_X86_BEA}
CFLAGS_BEA=$(CFLAGS)
@@ -11,7 +11,7 @@ CFLAGS_BEA+=-I../arch/x86/bea/src
CFLAGS_BEA+=-I../arch/x86/bea/include
CFLAGS_BEA+=-DUint64=uint64_t
$(OBJ_X86_BEA): %.o : %.c
arch_x86_bea.o: arch_x86_bea.c
$(CC) -c $(CFLAGS_BEA) $< -o $@
${TARGET_X86_BEA}: ${OBJ_X86_BEA}
+4 -4
View File
@@ -1,15 +1,15 @@
OBJ_X86_OLLY=asm_x86_olly.o
OBJ_X86_OLLY=arch_x86_olly.o
OBJ_X86_OLLY+=../arch/x86/ollyasm/disasm.o
OBJ_X86_OLLY+=../arch/x86/ollyasm/asmserv.o
OBJ_X86_OLLY+=../arch/x86/ollyasm/assembl.o
STATIC_OBJ+=${OBJ_X86_OLLY}
TARGET_X86_OLLY=asm_x86_olly.${LIBEXT}
TARGET_X86_OLLY=arch_x86_olly.${LIBEXT}
ALL_TARGETS+=${TARGET_X86_OLLY}
$(OBJ_X86_OLLY): %.o : %.c
arch_x86_olly.o: arch_x86_olly.c
$(CC) -c $(CFLAGS) $< -o $@
${TARGET_X86_OLLY}: ${OBJ_X86_OLLY}
${CC} $(call libname,asm_x86_olly) ${LDFLAGS} ${CFLAGS} -o ${TARGET_X86_OLLY} ${OBJ_X86_OLLY}
${CC} $(call libname,arch_x86_olly) ${LDFLAGS} ${CFLAGS} -o ${TARGET_X86_OLLY} ${OBJ_X86_OLLY}
+3 -3
View File
@@ -1,7 +1,7 @@
OBJ_X86_TAB=asm_x86_tab.o
OBJ_X86_TAB=arch_x86_tab.o
STATIC_OBJ+=${OBJ_X86_TAB}
TARGET_X86_TAB=asm_x86_tab.$(LIBEXT)
TARGET_X86_TAB=arch_x86_tab.$(LIBEXT)
ALL_TARGETS+=${TARGET_X86_TAB}
@@ -9,4 +9,4 @@ $(OBJ_X86_TAB): %.o : %.c
$(CC) -c $(CFLAGS) $< -o $@
${TARGET_X86_TAB}: ${OBJ_X86_TAB}
${CC} $(call libname,asm_x86_tab) ${LDFLAGS} ${CFLAGS} -o ${TARGET_X86_TAB} ${OBJ_X86_TAB}
${CC} $(call libname,arch_x86_tab) ${LDFLAGS} ${CFLAGS} -o ${TARGET_X86_TAB} ${OBJ_X86_TAB}
+3 -4
View File
@@ -1,12 +1,11 @@
CFLAGS_UDIS86=$(CFLAGS)
CFLAGS_UDIS86+=-I../arch/x86
OBJ_X86_UDIS86=asm_x86_udis.o
OBJ_X86_UDIS86=arch_x86_udis.o
SRC_X86_UDIS86=../arch/x86/udis86/*.c
STATIC_OBJ+=${OBJ_X86_UDIS86}
TARGET_X86_UDIS86=asm_x86_udis.${LIBEXT}
TARGET_X86_UDIS86=arch_x86_udis.${LIBEXT}
ALL_TARGETS+=${TARGET_X86_UDIS86}
@@ -14,4 +13,4 @@ $(OBJ_X86_UDIS86): %.o : %.c
$(CC) -c $(CFLAGS_UDIS86) $< -o $@
${TARGET_X86_UDIS86}: ${OBJ_X86_UDIS86}
${CC} $(call libname,asm_x86_udis) ${LDFLAGS} ${CFLAGS_UDIS86} -o ${TARGET_X86_UDIS86} ${OBJ_X86_UDIS86} ${SRC_X86_UDIS86}
${CC} $(call libname,arch_x86_udis) ${LDFLAGS} ${CFLAGS_UDIS86} -o ${TARGET_X86_UDIS86} ${OBJ_X86_UDIS86} ${SRC_X86_UDIS86}
+25 -10
View File
@@ -1,21 +1,36 @@
CFLAGS_ZYAN=$(CFLAGS)
CFLAGS_ZYAN+=-I../arch/x86/zyan/include
OBJ_X86_ZYAN=asm_x86_zyan.o
OBJ_X86_ZYAN+=../arch/x86/zyan/src/Decoder.o
OBJ_X86_ZYAN+=../arch/x86/zyan/src/Formatter.o
OBJ_X86_ZYAN+=../arch/x86/zyan/src/InstructionTable.o
OBJ_X86_ZYAN+=../arch/x86/zyan/src/Mnemonic.o
OBJ_X86_ZYAN+=../arch/x86/zyan/src/Register.o
OBJ_X86_ZYAN+=../arch/x86/zyan/src/Utils.o
OBJ_X86_ZYAN+=../arch/x86/zyan/src/Zydis.o
OBJ_X86_ZYAN=arch_x86_zyan.o
OBJ_X86_ZYAN+=zyan_Decoder.o
OBJ_X86_ZYAN+=zyan_Formatter.o
OBJ_X86_ZYAN+=zyan_InstructionTable.o
OBJ_X86_ZYAN+=zyan_Mnemonic.o
OBJ_X86_ZYAN+=zyan_Register.o
OBJ_X86_ZYAN+=zyan_Utils.o
OBJ_X86_ZYAN+=zyan_Zydis.o
STATIC_OBJ+=${OBJ_X86_ZYAN}
TARGET_X86_ZYAN=asm_x86_zyan.$(LIBEXT)
TARGET_X86_ZYAN=arch_x86_zyan.$(LIBEXT)
ALL_TARGETS+=${TARGET_X86_ZYAN}
$(OBJ_X86_ZYAN): %.o : %.c
arch_x86_zyan.o: arch_x86_zyan.c
$(CC) -c $(CFLAGS_ZYAN) $< -o $@
${TARGET_X86_ZYAN}: ${OBJ_X86_ZYAN}
${CC} ${LDFLAGS} ${CFLAGS_ZYAN} -o ${TARGET_X86_ZYAN} ${OBJ_X86_ZYAN}
zyan_Decoder.o: ../arch/x86/zyan/src/Decoder.c
$(CC) -c $(CFLAGS_ZYAN) -o $@ $<
zyan_Formatter.o: ../arch/x86/zyan/src/Formatter.c
$(CC) -c $(CFLAGS_ZYAN) -o $@ $<
zyan_InstructionTable.o: ../arch/x86/zyan/src/InstructionTable.c
$(CC) -c $(CFLAGS_ZYAN) -o $@ $<
zyan_Mnemonic.o: ../arch/x86/zyan/src/Mnemonic.c
$(CC) -c $(CFLAGS_ZYAN) -o $@ $<
zyan_Register.o: ../arch/x86/zyan/src/Register.c
$(CC) -c $(CFLAGS_ZYAN) -o $@ $<
zyan_Utils.o: ../arch/x86/zyan/src/Utils.c
$(CC) -c $(CFLAGS_ZYAN) -o $@ $<
zyan_Zydis.o: ../arch/x86/zyan/src/Zydis.c
$(CC) -c $(CFLAGS_ZYAN) -o $@ $<
+3 -3
View File
@@ -1,11 +1,11 @@
OBJ_Z80=asm_z80.o
OBJ_Z80=arch_z80.o
STATIC_OBJ+=${OBJ_Z80}
TARGET_Z80=asm_z80.${LIBEXT}
TARGET_Z80=arch_z80.${LIBEXT}
ifeq ($(WITHPIC),1)
ALL_TARGETS+=${TARGET_Z80}
${TARGET_Z80}: ${OBJ_Z80}
${CC} $(call libname,asm_z80) ${LDFLAGS} ${CFLAGS} -o ${TARGET_Z80} ${OBJ_Z80} -lr_util
${CC} $(call libname,arch_z80) ${LDFLAGS} ${CFLAGS} -o ${TARGET_Z80} ${OBJ_Z80}
endif
+3 -3
View File
@@ -1,7 +1,7 @@
OBJ_Z80=asm_z80_nc.o
OBJ_Z80=arch_z80_nc.o
STATIC_OBJ+=${OBJ_Z80}
TARGET_Z80=asm_z80_nc.${LIBEXT}
TARGET_Z80=arch_z80_nc.${LIBEXT}
ALL_TARGETS+=${TARGET_Z80}
@@ -9,4 +9,4 @@ $(OBJ_Z80): %.o : %.c
$(CC) -c $(CFLAGS) $< -o $@
${TARGET_Z80}: ${OBJ_Z80}
${CC} $(call libname,asm_z80_nc) ${CFLAGS} -o ${TARGET_Z80} ${OBJ_Z80} -lr_util
${CC} $(call libname,arch_z80_nc) ${CFLAGS} -o ${TARGET_Z80} ${OBJ_Z80}
+15 -13
View File
@@ -1,4 +1,4 @@
/* radare - LGPL - Copyright 2023 - pancake */
/* radare - LGPL - Copyright 2023-2025 - pancake */
#include <r_bin.h>
enum {
@@ -52,7 +52,9 @@ static RBinInfo *info(RBinFile *bf) {
}
static bool check(RBinFile *hello, RBuffer *buf) {
r_return_val_if_fail (buf, false);
if (!buf) {
return false;
}
ut8 tmp[64] = {0};
int read_length = r_buf_read_at (buf, 0, tmp, sizeof (tmp));
@@ -82,7 +84,7 @@ static bool check(RBinFile *hello, RBuffer *buf) {
break;
}
R_LOG_DEBUG ("KeyNameLen: %d", textlen);
char *text = r_str_ndup (data + 8, textlen);
char *text = r_str_ndup ((const char *)(data + 8), textlen);
R_LOG_INFO ("KeyName: %s", text);
free (text);
pos += textlen;
@@ -95,7 +97,7 @@ static bool check(RBinFile *hello, RBuffer *buf) {
ut64 vlen = r_read_le64 (data + 8 + textlen + 4);
R_LOG_DEBUG ("KeyValueSize: %d", vlen);
vlen = R_MIN (vlen, sizeof (data) - 16 + textlen + 4);
char *text = r_str_ndup (data + 8 + textlen + 4 + 8, vlen);
char *text = r_str_ndup ((const char *)(data + 8 + textlen + 4 + 8), vlen);
R_LOG_INFO ("KeyValue: %s", text);
free (text);
pos += vlen + 8;
@@ -140,7 +142,7 @@ static bool check(RBinFile *hello, RBuffer *buf) {
R_LOG_ERROR ("Invalid tensor name");
break;
}
char *text = r_str_ndup (data + 8, textlen);
char *text = r_str_ndup ((const char *)(data + 8), textlen);
R_LOG_INFO ("Tensor[%d]: %s", i, text);
free (text);
pos += textlen;
@@ -152,23 +154,23 @@ static bool check(RBinFile *hello, RBuffer *buf) {
}
static RList *entries(RBinFile *hello) {
r_return_val_if_fail (hello, NULL);
if (!hello) {
return NULL;
}
RList *ret = r_list_newf (free);
if (ret) {
RBinAddr *ptr = R_NEW0 (RBinAddr);
if (ptr) {
ptr->paddr = ptr->vaddr = 0;
r_list_append (ret, ptr);
}
ptr->paddr = ptr->vaddr = 0;
r_list_append (ret, ptr);
}
return ret;
}
RBinPlugin r_bin_plugin_hello = {
.meta = {
.name = "hello",
.desc = "hello world for rbin",
.license = "LGPL3",
.name = "gguf",
.desc = "GGUF bin parser",
.license = "MIT",
},
.load = &load,
.destroy = &destroy,
+14 -6
View File
@@ -9,7 +9,7 @@ int sq_mount(RFSRoot *root, ut64 delta);
int sq_dir(const char *path, SquashDirCallback cb, void *user);
unsigned char *sq_cat(const char *path, int *len);
static RFSFile *fs_squash_open(RFSRoot *root, const char *path) {
static RFSFile *fs_squash_open(RFSRoot *root, const char *path, bool create) {
int size = 0;
unsigned char *buf = sq_cat (path, &size);
if (buf) {
@@ -27,15 +27,15 @@ static RFSFile *fs_squash_open(RFSRoot *root, const char *path) {
return NULL;
}
static bool fs_squash_read(RFSFile *file, ut64 addr, int len) {
static int fs_squash_read(RFSFile *file, ut64 addr, int len) {
int size = 0;
unsigned char *buf = sq_cat (file->path, &size);
if (buf) {
file->data = buf;
// file->size = size;
return file;
return size;
}
return NULL;
return -1;
}
static void fs_squash_close(RFSFile *file) {
@@ -88,7 +88,7 @@ static RList *fs_squash_dir(RFSRoot *root, const char *path, int view /*ignored*
return list;
}
static int fs_squash_mount(RFSRoot *root) {
static bool fs_squash_mount(RFSRoot *root) {
root->ptr = NULL;
return sq_mount (root, root->delta);
}
@@ -98,9 +98,17 @@ static void fs_squash_umount(RFSRoot *root) {
}
RFSPlugin r_fs_plugin_io = {
#if 1
.meta = {
.name = "squashfs",
.desc = "SquashFS filesystem (XZ + LZMA)",
.license = "LGPL-3.0-only",
},
#else
.name = "squashfs",
.desc = "SquashFS filesystem (XZ + LZMA)",
.license = "GPL",
.license = "LGPL-3.0-only",
#endif
.open = fs_squash_open,
.read = fs_squash_read,
.close = fs_squash_close,
+1 -27
View File
@@ -1571,8 +1571,7 @@ int read_super(char *source) {
memcpy(&sBlk_3, &sblk, sizeof(squashfs_super_block_3));
swap = 1;
} else {
ERROR("Can't find a SQUASHFS superblock on %s\n",
source);
// ERROR("Can't find a SQUASHFS superblock on %s\n", source);
goto failed_mount;
}
}
@@ -1649,23 +1648,6 @@ failed_mount:
}
struct pathname *process_extract_files(struct pathname *path, char *filename)
{
FILE *fd;
char name[16384];
fd = fopen(filename, "r");
if(fd == NULL)
EXIT_UNSQUASH("Could not open %s, because %s\n", filename,
strerror(errno));
while(fscanf(fd, "%16384[^\n]\n", name) != EOF)
path = add_path(path, name, name);
fclose(fd);
return path;
}
/*
* reader thread. This thread processes read requests queued by the
@@ -2043,14 +2025,6 @@ int main(int argc, char *argv[])
strcmp(argv[i], "-li") == 0) {
info = TRUE;
short_ls = FALSE;
} else if(strcmp(argv[i], "-ef") == 0 ||
strcmp(argv[i], "-e") == 0) {
if(++i == argc) {
fprintf(stderr, "%s: -ef missing filename\n",
argv[0]);
exit(1);
}
path = process_extract_files(path, argv[i]);
} else if(strcmp(argv[i], "-regex") == 0 ||
strcmp(argv[i], "-r") == 0)
use_regex = TRUE;
+10
View File
@@ -0,0 +1,10 @@
*.so
*.dylib
*.dSYM/
__pycache__/
test/test_md32
test/test_parse
tools/md32-run
.pmai/
usipdata/
+489
View File
@@ -0,0 +1,489 @@
# Changelog
## Unreleased
### SCQ16 table update (229 forms), the open-reading marker, the broadcast ports, the confidence levels and the public test vectors
* `isa/scq16_isa.json` / `scq16_opcodes.h`: 229 forms / 402 bit alternatives.
`jr rn` (6f ec) reads a 5-bit register field (r0-r31); `btst rd, rd, #pos`
(67 f8-fb) has a 5-bit position; `ctz` is its own form without the
hypothetical flag, `sqr?` belongs to the `op41` placeholder (hypothetical);
`and rd, rs, #0x1|#0x3|#0xf` (2 bytes), `add rd, rs, #-1` (2 bytes) and the
4-byte `sb rd, off(rb)` are `high`, the 4-byte `btst rd, rs, #pos` is `medium`
(settled by execution results).
* `tools/gen_scq16_tables.py`: the flag `SCQ16_FL_OPEN` (an open reading: a
family placeholder or a provisional name) and, for an open alternative
without a template, the uniform ESIL marker `REF,ALT,open`; `export --hyp`
applies the declared plugin hypotheses of `isa/scq16_hyp.json` and records
the file's sha256 in the JSON meta and in the header. The file is empty:
the packing ESIL / p-code of `op41.fld rd, rs, rt, #pos` is carried by the
ISA source (still flagged hypothetical), so every ESIL the plugin emits
comes from the source.
* `scq16_vu.inc.c` / `scq16_arch.inc.c`: the scalar ports `v0-v31` are the
broadcast ports of the vector register file: a write by `vbcast` /
`vbcast.i` / `vbcast.i?` reaches the 64 lanes of `vr_k` (an ESIL register-
write voyeur); the custom op `open` (no effect); `aoj` reports `open`,
`reading`, `hypothetical` and `confidence` per unit.
* `ctz` of a zero operand: -1 under the table ESIL (`31 - clz(0)`); documented
as an open question against the hardware (32).
* `asm_md32.c`: pseudo rule of `op41.fld`.
* `test/scq16_vectors.json` + `test/test_scq16_vectors.py`: 195 public
bytes-only vectors with the expected result in the big-endian regime of the
harness and in the little-endian regime of the core data memory;
`test/test_scq16.py` (267 checks) and `test/test_md32.c`: the new forms, the
marker, the broadcast, the confidence levels, `ctz(0)`.
* `doc/scq16.md`, README: the new forms, the open marker, the broadcast ports,
the declared limits of the vector unit model, the hypothesis file, the
confidence levels, `ctz(0)`.
### SCQ16 table update (402 bit alternatives), the `.post` convention and the vector unit model
* `isa/scq16_isa.json` / `scq16_opcodes.h`: 228 forms / 402 bit alternatives.
`ctz rd, rs` (41 f3 0x22) is an established operation; new provisional
readings: `sqr? rd, rs` (41 f3 0x23), `sra? rd, rd, #pos` (67 fc-fd),
`vrd? rd, vb1[x]` (1a xy), `and? #0xf000?` (67 98-9b and the 2-byte 00/01 with
k = 6), `and? #0xc000?` (67 b4-b7); `op41.fld rd, rs, rt, #pos` reads its third
field as a register; `lw.post rd, [rb] += 4` (21) has a 4-bit destination;
the 3-bit post-increment of the `6e` `.post` family is signed; `sra rd, rd, #imm`
(09) is established; the load templates with a post-increment write rd last
(with `rd == rb` the loaded value wins).
* `scq16_vu.inc.c` (new) / `scq16_arch.inc.c`: the vector unit model of the ESIL:
the register file `vr0-vr31` (128 bytes each, four 256-bit quarters in the
profile), `vp0-vp7` and `va0-va7`; `vop` models `v.mem.ld`, `v.mem.st` and
`v.move.mv` (loads/stores through the VU pointers with the count of `va[A]`
and a post-increment, register copies) and leaves every other op9 without effect.
* `asm_md32.c`: pseudo rule of `sqr`.
* `doc/scq16.md`, README: the new forms, the VU model, the `.post`
convention, the callee-saved profile (r16-r31).
* `test/test_scq16.py`, `test/test_md32.c`: the new forms and the VU model.
### SCQ16 table update (228 forms), the `j.d1` target rule and the vector names
* `isa/scq16_isa.json` / `scq16_opcodes.h`: 228 forms / 400 bit alternatives.
The exporter (`tools/gen_scq16_tables.py export`) takes the ESIL, the delayed
transfers (SETJT/SETD) and the hypothetical flag from the form-description
module itself (its HYP table) and applies no overlay of its own. Vector
names: the established operations `v.move.mv`, `v.mem.ld` and `v.mem.st`
print without the `?` (`vector.firm_op9`), the provisional ones keep it in
the table string.
New or renamed: `cmov.ge rd, rs, #imm, ra`, `cmov.eq rd, rs, rx, ra` (the
register form), the provisional `cmov.leu?` / `cmov.ltu?` / `cmov.lt?` /
`cmov.le?`, `mv rd, rs` (67 c8), `bset` / `btst rd, rd, #pos` (3 bytes),
`lbu.post rd, [rb] += inc` with 5-bit registers (6e q2) and the 23 page as
`lbu.post rd, [rb] += simm3` (-4..-1), `and rd, rs, #0x3fff` (67 a4-a7), the
6-byte `and rd, rs, #imm16` (74 sub 1), the provisional `ctz?` / `clb?` (41 f3),
`vcfg4c? v, rs, #0xc` with the hypothetical `p_k <- rs`, `ld46?` as a
hypothetical byte load with a post-increment, `lbu? rd, off(sp)` (ex `lb?`),
`addsp sp, #imm` (14 8x-fx), `fxts` without the `?`; `halt` and `sys41` carry
the empty ESIL (no modelled effect); `5c 40-6f` is the 4-byte `beq rA, rB`.
* `scq16_decode.c`: `j.d1 56 0x-3x` decided by its target (stand-alone units
and B slots); every ESIL memory access cuts its address to 32 bits (negative
frame offsets wrapped in the 64-bit ESIL machine); the `?` of a vector name
comes with the table string.
* `scq16_arch.inc.c`: a unit with the empty ESIL no longer blocks the ESIL of
its packet; opex `named` / `provisional` of vector ops follow the table name.
* `asm_md32.c`: pseudo rules of `cmov.ge`/`cmov.leu`/`cmov.le`, `sys41`, `ctz`/`clb`.
* `tools/scq16_flags.r2`: the data-space bases (DM, I/O window, DM2) as flags.
* `test/test_scq16.py`, `test/test_md32.c`: the new forms, `j.d1` by target,
`.d2` across two `aes` steps, negative stack offsets, the vector names.
### SCQ16 mode (cpu=scq16): the table (218 forms), the byte-granular packet decoder, analysis and ESIL
* `isa/scq16_isa.json` / `tools/gen_scq16_tables.py` / `scq16_opcodes.h` /
`scq16_decode.c`: the SCQ16 (MD32 family, byte-granular packet variant) as
a third cpu of the plugin: 218 forms / 389 bit alternatives generated from
the ISA table, which carries the plugin semantics (the VU ports as
registers, delayed transfers as SETJT/SETD, the hypothetical readings
flagged), the length rule by first-byte leaves, packets `{ A ‖ B }` with
the head shifted by the borrowed bit, masked orphans, 4-byte vector ops by
op9 class (v.<class>[.<name>?]) and 8-byte bundles.
* `arch_md32.c` / `scq16_arch.inc.c`: analysis (types, targets relative to the
packet start, delay slots counted in instructions, `do` as a loop
reference, opex with the unit/packet/bundle structure), ESIL for the scalar
forms with parallel packet semantics (temporaries t0-t3), delayed transfers
via SETJT/SETD, the VU scalar ports as registers (vu*, v*, va*, vp*, vs*,
vb1_/vb3_/vb5_*, udf*) and vector ops as the custom op `vop`; register
profile with sp/lr as csr14/csr15, a0 and the loop registers; byte alignment,
MAXOP 12.
* `asm_md32.c`: SCQ16 pseudo-syntax (packets as `parallel { ...; ...; }`).
* `test/test_scq16.py`, `test/test_md32.c`: bytes-only checks of cpu=scq16.
* `doc/scq16.md`, README "SCQ16 mode".
### uSIP table update (760 forms), the parallel packet, the 22-bit branches and the slot pairs
* `isa/usip_isa.json` / `usip_opcodes.h`: 760 forms (46 added, 12 retired,
41 modified). The packet executes in parallel and every read sees the
state before the packet (`structure.packet.execution`,
`USIP_PACKET_EXEC_PARALLEL`; no decoding rule depends on an intra-packet
order). New: `movi rB, #imm17` (the op 7 head with the null-field tail, a
17-bit rotated immediate; `movi_min16` / `movi_m32767` retired: with m = 0
their value was -65536 / -65535), `movhi` with the small F' = 0 tails
(`c001` = 0x10000000, even f12 = 0x1000..0x7000), the 16-bit `ld.w rB,
[rA -/+ 4]` of the first slot and the one-unit `st.w rB, [rA -/+ 4]`,
`addi rA, #-4 / -2 / -1` of the class-E cell, `loop rX, last, x16` (B = 1,
the former `loop.b1?`), the guard `loop_b4_straddle16` on the twelve
`loop #N` entries (bit 4 of the head must agree with "the packet at the end
crosses a 16-byte line") and the `loop #N?` rule
(`structure.packet.loop_imm_q`: N = 0 or the end at pc + 2^k), the m = 1
`loop #N` without the `?`, the 22-bit displacement of every `b<cond>.l`
(`U1[7:0] : T[13:12] : T[11:0]`: backward and +4096..+8191 cells) and the
fifteen `bcc48_*_64x` entries (the 64-bit variant whose extension unit is
any 16-bit unit X, with the guard `not_over_validated_call32`), the op c
F = 1 branches with the F' = 0 tail exactly at +2 (`beqz_F0c` / `bnez_F0c` /
`bleu_rr_F0c` / `bltu_rr_F0c`, `ctx:tail_at_plus2`) and the op 9 F = S = 0
cell of >= 4 units (`bne_imm8_F0s0` / `blt_imm8_F0s0`), `bz.s` with the P4
cell F = 0 in 2- and 3-unit packets (`bz_s_P4_F0`), the slot pairs
(`stslot_F0_k16`, the op c pairs `stslot_slotc_h / _t` and their `stslot?`
twins, `ctx:slotc_pair` / `ctx:call_within_2_packets`, `ctx:op4imm_head` on
`stslot_F0_q`, `ldslot_S0_pos1` without the `?`), the fusion at distance 2
`add rB, rA, #rot12` (`add2_rot12`, `fuse_pair` + `tail_adjacency` 2),
`ld.h / ld.hu` with the F' = 0 tail at +2 and any base (`rf0dall_ld_h /
ld_hu`, `ctx:rf0dall_guards`), `saturate`, `mfacc` of the C cell and
`sext16 / zext16` with S = 0 without the `?`; the CSR names `ag0-ag3.{base?,
len?, idx?}` for 0x30-0x3e; the score rules lr32 / rr7 / spodd / rf0dall
nowaw in `structure.packet.tie_breaks`.
* `tools/gen_usip_tables.py`: the guards `loop_b4_straddle16` (exported with
the head field `b4`) and `not_over_validated_call32`, seven new context
conditions, `FUSE | ADJ2` for the fusion at distance 2, the constants of the
packet model and of the `loop #N?` rule.
* `usip_decode.c`: slotpair0 before the layout, the 22-bit prefix
displacement and the 64-bit X variant (the branch keeps U0 U1 T, X is the
first instruction of the delay slot; the guard against a validated 32-bit
call / b of U0 + X), the straddle guard of `loop #N`
(`UsipGuardCtx.packet_units`) and the `loop #N?` text, `ctx:tail_at_plus2`
(fall-through, never `.word`; the fallback pairs carry their distance),
the rf0dall guardians in the f0ctx pass, `bz.s` of the P4 cell F = 0, the
post rules R-add2 (`.hword` heads only) / R-fslot0c before the split pass
and after the prefix paths, R-slotc in the split pass and `slotc_mark`
after the packet (the two following packets through `packet_at`), the
F-slot0 readings by rule, the score rules lr32 / rr7 / spodd / rf0dall
nowaw. Unverified policy: the `loop_imm_F1S0` reading is no longer
accepted (wrong too often), the R-F0c / R-F0s0 branches are (right in
nearly every case), the `b<cond>.l` prefix forms only in their forward cell
below 4096 units (the 22-bit cells and the X variant need the target
validated), the x16 loops as the other `loop rX`.
* `arch_md32.c`: the `packet_units` callback (the units of the packet at the
loop end, from the bytes at hand or the session's cache; an eight-unit run
without a closer is unknown).
* `asm_md32.c`: pseudo syntax for `loop rX, last, x16` and `saturate`.
* Tests: `test/test_plugin.py` vectors for the parallel packet, `movi #imm17`,
the small `movhi` cells, the 16-bit `ld.w` / `st.w` with +-4, the class-E
`addi`, `loop x16`, `loop #N` with the straddle guard (accepted and
rejected), `loop #N?` (validated and unverified), the backward 22-bit
`b<cond>.l` (validated and `.word`), the 64-bit X variant (validated and
fallback), `beqz` of R-F0c (validated and unverified), `blt.d` of R-F0s0
(validated and fallback), `bz.s` of the P4 cell F = 0 (2 and 3 units,
validated and unknown), slotpair0, the op c slot pairs with and without a
call, R-fslot0c, R-add2 and rf0dall; the `loop`, `asr16`, `ld_h_Fp0`,
`movi #-32768 / #-32767`, `loop.b1?`, `loop #256?`, `ldslot?`, `stslot?`
and `saturate?` vectors updated to the new readings; `test/test_parse.c`
vectors for the new pseudo rules.
### uSIP table update (726 forms), the loop cells and the slot splits
* `isa/usip_isa.json` / `usip_opcodes.h`: 726 forms (52 added, 13 retired,
14 modified). New: the `loop #N` count is the collected head field (bits
13:5, no +1), `loop #N` with the F' = 0 tail exactly at +2
(`loop_imm_*_F1_Fp0`), with h = 1 (N >= 128) and with m = 1 (N >= 256,
printed `loop #N?`), `bz.s` in 4- and 3-unit packets (`bz_s_P4_u4` /
`bz_s_P4_u3`), the split entries of the slot family `stslot` / `stslot?` /
`ldslot?` (F-slot0, S0-slot, the S3 cells `ldslot/stslot #48-63`;
`split_role`), the fusion entry `op72? rA, #k, asr#b` (`fuse_pair`),
`op2z? rA`, `lsl/asr r8-r15, #B`, the W6 cells `ld.h/st.h rB, [r8+rrr]` and
`[rA]+` with h = 1, `sub r14, #f12/2` with any F/F' (`spfix_sub_sp`
retired), `st.w [sp], #imm14`, `st.abs` with the hi F' = 0, `add rB, rB,
#imm27` / `st.h? [rB], #sat` selected by the immediate value (also the
cell-E triples), `add? rB, r15, #rot12` and `ld.h? / ld.hu? rB, [r15+off]`
with the F' = 0 tail, `saturate? rd, rs1`, `movi #simm6` in the delay slot
of a validated branch, `mtcsr #0x30-0x3e`, `ld.h / ld.hu / lea / movi
#-32768 / #-32767 / ld.hu [rA+rB]` without the `?` (twelve `*_q` ids
replaced); the constraints `any(rA != 14, m == 1, tail_adjacent == false)`
on `beq_imm8_d` (the op 9 `beq.d` with base sp and the adjacent tail is
not a branch) and `any(m == 1, rA >= 8, x == 0, rB != 15)` on the seven
op a `*_s0f1` / `*_imm8_F0` entries (the `bgt rA, #-1` head class takes
only the adjacent S = 1 tail); the ABI passes eight arguments in r0-r7.
* `tools/gen_usip_tables.py`: the flags `FUSE`, `SPLIT` / `SPLITBARE` (with a
`USIP_FORM_*` index for every split and fusion entry), the constraint op
`instr_index`, `any` with up to four alternatives that may be a context
condition or an instruction position, six new context conditions; the
`loopn` operand type is the collected field.
* `usip_decode.c`: the score in twentieths (al1 = 0.3), the explicit
candidates loopcand / R-brHHTT / R-b111pre / R-b111ctl with the
`b111_layout` context extended to them, the `bz.s` rules of 4- and 3-unit
packets (the rest re-parsed as the delay slot, the 3-unit one with the
target beyond the packet and no write of rA), the S3 renames and the split
pass of the slot family with the split-tail reading and the nowaw guardian,
the fusion after the renames, R-movi6d, the R-w6h1 loop guard evaluated
with the packet being parsed, the R-loopA adjacency (`.word` at any
distance but +2), rf0dmidwaw, the score rules R-waw / al1 / R-bsnext /
P2W-P2H prefix / sat40 H H T T / rf0dpen, the instruction position of the
renames. Unverified fallback: the loop entries with the F' = 0 tail at +2
and the h = 1 heads with the S = 1 tail (and the adjacent F = 0 tail) are
accepted; the m = 1 (`loop #N?`) and the other h = 1 entries are not (wrong
too often when unverified).
* `arch_md32.c`: the stores of an immediate (`[rB]` / `[sp], #imm`) carry the
value in `val` and `[sp]` the stack access; the new mnemonics keep their
kinds (`op2z?` / `op72?` / `saturate?` are unknown operations).
* `asm_md32.c`: pseudo syntax for the stores of an immediate (also to `[sp]`),
the absolute `st.abs` / `ld.abs`, the `?` of a count (`loop#? #256?`).
* Tests: `test/test_plugin.py` vectors for the loop count, the F' = 0 / h = 1 /
m = 1 loops (validated and unverified), the 4- and 3-unit `bz.s` (validated
and unknown), beq9sp, the `bgt rA, #-1` cell, the W6 h = 1 cells and the
loop guard, `op2z?`, the h = 1 shifts, the 16-bit `lea`, the splits
(R-slot4n, R-op4imm in 2 and more units, S0-slot, S3), `op72?`,
`saturate?`, sat40 H H T T, R-waw with the P2W prefix, R-b111pre,
R-b111ctl, R-bsnext, the omitted weak cell of R-brHHTT, `sub r14`,
`st.w [sp]`, `st.abs` hi F' = 0, addq / cell E by value, `mtcsr` of the
accumulator CSRs, R-1eX0F0, R-movi6d; the `lea`, `loop#`, `mtcsr`, `movi
#-32768 / #-32767`, `ld.h` / `ld.hu` of R-1eX0 / R-ldF0 / R-hhttF0 / R-F0d,
`op2z?` and two R-waw vectors updated to the new readings;
`test/test_parse.c` vectors for the new pseudo rules.
### uSIP table update (687 forms), the target filter and the F = 0 branch cells
* `isa/usip_isa.json` / `usip_opcodes.h`: 687 forms (56 added, 3 retired,
71 modified). New: the `b<cond>.d` cells with head F = 0 (`bne.d`, `ble.d`,
`bgeu.d`, `bge.d`, `bne.u8.d`, `beq.u8.d`, `bleu.d`, read only in the
(B class, tail distance) cells of `usip_br0_cells[]`; the five weak cells of
`usip_br0_cells_weak[]` are never taken), `bgt.d` of the F = S = 0 cell back
in the table, `ret.s.d`, `loop.b1? rX, last=` and the `?ss=N` loops, `bz.s`
with bit 3 = 0, the ld/st type 111 `ld.bu` / `st.b` (`st.b?` retired) with
the byte displacement `sext12(f[0]:f[10:1]:f[11])` (`USIP_A_OFFB`, also on
`ld.b`), `ld.b` / `st.h` with F != S of op 1 exactly at +2, `ld.h?` / `ld.hu?`
with the F' = 0 tail as the second head of H H T T and by the deferred tail
of a head with base sp (context group `f0ctx`), the bit-field pair
`fxtu`/`fxts`/`fup` in H H T T and the BF_SEL cells
`fup`/`fup?`/`fxtu`/`fxtu?`/`fxts?` (renamed from `.bf?` with the nowaw
guardian), the 16-bit op 2 shifts `lsl`/`lsl?`/`asr`/`asr? rA, #B` (`addi4`
retired), `ldslot`/`stslot` with m = 1, `.stimm16?`, `ld.w?`/`st.w?` for the
`f12 = 1 / 3 mod 4` word classes, `add r14` / `sub r14` (spfix),
`movi? #-32767`, `movi rA, #-1` with F = 0, `mtcsr?` of the accumulator CSRs
with a named 16-bit tail; the known target as a validation filter on the
F = S = 0 cells, `bne.d #-1`, the loops with the F' = 1 tail, the open `b.s`
(also a function start) and the near `b` (any packet start of the image or a
function start), with fall-through on failure for the F = S = 0 cells
(`USIP_F_GUARDFT`); the operand conventions of six families revised
(`mul`/`divs`/`divu`/`mulu64 A<k>, r<rrr>, rB`, the op 7f bit ops,
`cls1`/`clz`/`ctz`, the op 6 compare-immediates, the 48-bit `add`, `asr16`);
`known16 = false` on the four h = 0 word slots. Thirty-one entries are
post-layout renames.
* `tools/gen_usip_tables.py`: the operand type `offb`, the flags `GUARDFT` /
`B111` / `F0CTX` (`flags` is `ut32`), the constraint ops `br0_cells` /
`br0_cells_live` (cell masks), `bf_valid`, the guards `tail_named16` and
`target_packet_start_any_or_function_start`, the `any` sub-operations
`packet_len`, `guard`, `range`, `br0_cells`, large value sets
(`usip_value_sets[]`), the new context conditions, the tables
`usip_br0_cells[]`, `usip_br0_cells_weak[]`, `usip_c48sym_table[]`; form
names sanitised into C identifiers.
* `usip_decode.c`: the fall-through guards, the fifth guard kind with the
optional `UsipGuardCtx.packet_start_any` callback, the R-br0 cells by B class
and tail distance, the `b111` group in the 2-unit packet and in H H T T (which
now takes tt = 11 tails), the context conditions `b111_layout` /
`hhtt_second_head` / `f0d_triple` / `bfpair` / `bf_dst_not_written` /
`rest_named_no_q`, the `f0ctx` pass on the `.word` pairs and the re-read of
the R-F0d middle unit, R-op1fs (a ld/st entry with `ADJ2` undoes the pair at
any other distance), the `bz_s_P5` context rule, the m = 1 R7 slots, P2H,
R-lr16, R-align48 and R-c48sym in the score, the `b.s` guard admitting a
function start, the loop F' = 0 rule by field; immediates glued to a letter
or `=` (`A0`, `?ss=2`, `w=0`) printed in decimal. Unverified fallback: the
forms whose guard is a validation filter keep their reading when the target
is unknown (`b.s?`, `b?`, `loop?`, `bne.d?` ...; conditional branches only
forward), a definite "not a packet start" rejects them.
* `arch_md32.c`: `UsipGuardCtx` with designated initialisers; the lowest packet
start decoded in the session separates "not a packet start" from "unknown"
for backward targets; `offb` as a `disp` operand in `opex`; stack deltas for
`addsp` and the `add r14, r14, #imm` / `sub r14, #imm` pairs.
* `asm_md32.c`: pseudo syntax for the 2-operand `lsl` / `asr`.
* Tests: `test/test_plugin.py` vectors for the F = S = 0 and R-br0 cells
(validated by the session, rejected with fall-through, unknown backward,
unverified forward), `ret.s.d`, `movi #-1` F = 0, the op 2 shifts, the open
`b.s` rejected / unverified, `bz.s` P5 (2-unit, validated, unknown), the m = 1
slots, `loop.b1?` and the `?ss=N` loops, `movi? #-32767`, the `asr16` clamp,
the bit-field pair and the BF_SEL cells, `ld.bu`/`st.b` with the byte
displacement (plain, 2-unit b111, H H T T), `ld.b`/`st.h` F != S at +2 and
the undo at +1, `ld.h?`/`ld.hu?` of R-hhttF0 / R-F0d, spfix, NEGQ,
`.stimm16?`, `mtcsr?` with a named tail; the `loop`, open `b.s`, `mtcsr`,
`movhi` tt = 10 and `save w=` vectors updated; `test/test_parse.c` vectors
for the new pseudo rules.
### uSIP table update (634 forms), decoder rules and the K-tie cascade
* `isa/usip_isa.json` / `usip_opcodes.h`: 634 forms (52 added, 12 retired,
103 modified). New: the 14-bit word displacement of the two-unit
`ld.w`/`st.w` (W14: `f12 = 2 mod 4` is `+0x1000 + (f12 & ~3)`), `nop.ctl`
for `5e0d`/`1e0d`/`de0d` (never a tail, never a head with a tail), the
bit-field family `fxtu`/`fxts`/`fup`/`fup? rB, rs1, #w, #pos`,
`movi? rB, #-32768`, the register forms `bset`/`bext rd, rs1, rB`, `mtacc?
Ak, rs1:rB` (was `clr.a?`), `sgt rB, rA, #-1` with F = S = 1, `addi rA,
#32` next to `cop rA`, the 16-bit `lsl`/`lsl?`/`sext16`/`zext16` variants,
`ld.w?`/`ld.h?`/`ld.hu? rB, [r15+off]`, `.ldF0?` and the F' = 0 `ld.h?`/
`ld.hu?`, `.3eX0?`, the 20 `b<cond>.d` cells with the `[0][1][tt]` tail at
+2, `movhi` with the tt = 10 tail (IEEE test), 16 non-canonical 48-bit
constants admitted by a value table, the double-class split (`.op4t0`,
`.movi6?`, `.st.h?`/`.st.b?`/`.ld.h?`/`.ld.b?`, `ld.sp`); retired the
`.hi`/`.hilo` pair entries and every `not_hi1010` constraint (H1: a
hi(1010)-shaped unit is an ordinary head unless a 48-bit instruction claims
it), `osl_0_15_2`, `clr.a?`. Twenty entries are post-layout renames
(`rename_from`).
* `tools/gen_usip_tables.py`: `rename_from` lists per entry, the constraint
ops `tail_adjacent`, `ieee_short` and the 48-bit value table membership, the
`any` sub-operation `tail_adjacent`, the context conditions
`cop_rA_in_packet` / `not_c48_lo_follows`, `USIP_MAXVALS` 12, the tables
`usip_never_tail`, `usip_never_head_with_tail` and `usip_c48_table`; the
rename entries are exempt from the 16-bit position-class checks.
* `usip_decode.c`: W14, the never-tail and never-head-with-tail units from the
tables, H1 (the forced hi(1010) decode is gone; `.hi`/`.lo` only after a
48-bit-family head in the packet), the 48-bit value table in the partial
admission, P2W (no alignment penalty for the `= 2 mod 4` word offsets in the
H H T T layout), callin (`UsipGuardCtx.inside_function`), the post-layout
renames (`apply_renames`), the K-tie cascade (`dedup` and `nowaw` over the
tied readings of the packet; `du2` over the neighbouring packets the caller
supplies through `UsipGuardCtx.packet_at` / `branch_target`, first-pass
readings with `USIP_GUARD_NO_CASCADE`), `UsipPacket.tiebreak`; the failed op
C compare-and-branch guard is printed `.dsp` (unnamed data either way).
Unverified fallback extended to the S0F1 cells whose unverified readings are
right in nearly every case (`bne`/`blt`/`bgeu`/`bgtu`/`bge` with immediate,
`beqz.d`/`bnez.d`, `bleu` register) and to `loop rX` with the F' = 0 tail
when the head has F = 1 and the S = 1 tail sits at +2.
* `arch_md32.c`: the cascade context (packets decoded earlier in the session,
first-pass readings of the packets inside the bytes at hand, the branch
targets seen so far), `opex.packet.tiebreak`, `ireg` = `r15` for the r15-based
loads, types for `fxtu`/`fxts` (`cast`) and `fup` (`or`).
* `asm_md32.c`: pseudo syntax for `fxtu`/`fxts`/`fup`, `mtacc`, the 2-operand
`addi`, `sext16`/`zext16`, `asr16`; `nop.ctl` reads `nop`.
* Tests: `test/test_plugin.py` vectors for W14, `nop.ctl`, the bit-field
family, `mtacc?`, `movi? #-32768`, `sgt #-1`, the register `bset`/`bext`, the
S0F1 branches (unverified, validated by the session, not validated), the
r15-based loads, `.ldF0?`, the F' = 0 `ld.h?`, the 48-bit value table,
`.3eX0?`, the `lsl`/`sext16`/`zext16` renames, `cop ‖ addi`, `.hi`, `movhi`
tt = 10, `.op4t0`; the op8 slot split vector updated; `test/test_parse.c`
vectors for the new pseudo rules.
### uSIP table update (594 forms) and the prior-free packet parser
* `isa/usip_isa.json` / `usip_opcodes.h`: 594 forms (137 added, 18 retired,
76 modified). New: the 48/64-bit compare-and-branch prefix forms
`b<cond>.l rB, #imm9 / rA, target` (complete condition table incl. the
unsigned cells and the 64-bit twin with the `1e0d` unit), `loop# #N, last`,
the op 6 set-on-compare family `seq`/`sle`/`slt` and `sgt rB, rA, #rot10`,
`movhi` with the 20-bit value and the small cell, `movi?` for the op b class,
the 48-bit `mov32`/`add` constants by one formula, `st.w`/`st.h [rB], #imm`,
the cell-E triple by position, `ld.d`/`st.d` with the signed offset, the
closed negative half-word (`f12 - 0x1001`) and word (`4*sext10(f12 >> 2)`)
offsets, `add rB, rA, #rot12` for the odd f12 cell, `st.h` with the F' = 0
tail (deferred), the 16-bit first-slot `ld.h`/`st.h`, `movi rA!, #imm5`,
`xor rA, rB` alone, the position cells `ld.w?` (k = 0) / `mfacc?` (k >= 2),
6-bit `ldslot`/`stslot` and the `.op8?` split, `bset`/`bclr?`/`binv?`/`bext?
rd!`, `osl`, `jr rB`, the `sys` twins with F = S = 0, the H H T T loads/
stores, the bank bit of the compared register of the 32-bit branches;
retired `trap?`, `beqz.l`, `jr?`, `movhi?`, `ld.d?/st.d?` (now `ld.d`/`st.d`),
`.ld.abs`, `movi_max32`/`movi_sext27`/`add_r15_imm27` (now `mov32`/`add`),
`sgn?`/`scmp?` (now `sgt`), `bgt.d` of op a.
* `tools/gen_usip_tables.py`: operand types `offh`/`offw`/`loopn` and the
redefined `movhi`, flags `USIP_F_ADJDEF`/`PREFIX`/`RENAME`/`HHTT`, 8 bit
ranges per field, 64-bit entries, constraints `gt`, `odd`, `packet_len_ge`,
`head_index`/`head_pos_ge`, `ctx`, the guard `head_not_validated_bs`, `any`
with up to three alternatives incl. set membership, the `bcc48` condition
table, `save w=4` = `{LR, r8}`.
* `usip_decode.c`: the prefix forms matched on the first units before the
layout (failing guard = not taken), the prior-free total order
`(s0, I, Fv, -A, K)` replacing the enumeration order and the group count,
the grammar rules (`5e0d` never a tail, the deferred `st.h` tail with its undo
and the validated-`b.s` guard, the `.d` SP-negative rejection, the 3-unit and
H H T T explicit candidates with the forced decode of hi(1010) heads, the
`0e10 3fc0 c000` trio, the `loop #N` F = 1 adjacency, the op8 slot split), the
alignment exception `f12 = 3 mod 4 >= 0xf00`, the +0.5 add relabel, +1.0
identical units, +0.75 store-of-immediate triples and +0.5 mfcsr pair
penalties, the position cells (deferred `head_index`/`packet_len`/`ctx`
constraints with fall-through), the late guard evaluation with the undo of a
pair, three tails for the 64-bit forms. Unverified fallback extended to the
prefix forms and to `loop #N` (F = S = 1, F = 0 with the tail adjacent, F = 1
with the S = 0 tail at +2).
* `arch_md32.c`: conditions `bequ`/`bneu`, types for `sle` (`cmp`) and `osl`
(`shl`), `val` = N for `loop #N`, the signed offsets as `disp` operands in
`opex`.
* `asm_md32.c`: pseudo syntax for `loop#`, `sle`, `bequ`/`bneu`, the 2-operand
`xor`, `mfacc`, `bset`/`bclr`/`binv`/`bext`, `osl`; the `?` marker stripped
repeatedly (`ble.l??`); `ld.d`/`ld.w` no longer sign-extended.
* Tests: `test/test_plugin.py` vectors for `loop#` (validated at +1 and +2,
unverified), `b<cond>.l` (validated, unverified, not taken, 64-bit),
`ld.d`/`st.d` with a negative offset, the negative half-word and word offsets,
`seq`/`sle`/`sgt`, `movhi`, the 16-bit first-slot `st.h`, the deferred `st.h`
and its undo by a validated `b.s`, H H T T, the op8 split, the `0e10` trio,
`cop` with F = S = 0, `xor`, `movi rA!`, `bset rd!`, `osl`; the `jr`, `ld.d`,
`movhi` and bank-bit (`bnez r15!`, `beqz.d r2!`) vectors updated;
`test/test_parse.c` vectors for the new pseudo rules.
### MS15E30: `cmulr16`/`cmuli16` names
* `md32_opcodes.h`: the names of 0xDA00 (`cmulr16`, a*c - b*d) and 0xDC00
(`cmuli16`, a*d + b*c) follow the little-endian layout of the data memory (the
high half of a 32-bit complex word is at +2 and holds the real part); the
earlier assignment assumed a big-endian data memory. Vectors in
`test/test_md32.c` and `test/test_plugin.py`.
### uSIP table update (475 forms) and decoder rules
* `isa/usip_isa.json` / `usip_opcodes.h`: 475 forms (110 added, 24 retired,
140 modified). Port I/O `ior`/`iow` replace `mfcr`/`mtcr`; `mtcsr` is back and
`mfcsr` accepts F' = 0; the `sys` shape is split by its tail field (`cop`,
`rti`, `lpexit?`, `isync?`, `ieon`, `ieoff`, `trap?`, `sys?`, `ret`, `ret?`,
`jr?`, `call rB`); `nop32`, `cmov r15`, `add rB, rA, #rot12` for the whole
op 0 cell, `sne`, `scmp?`, `movhi?`, `extu`, `movi #-1`, `addsp`, `lea?`,
`st.w [sp+4/12/20]`, `ld.d?`/`st.d?` (64-bit pairs), `st.b?`, the stack-slot
closers (`ldslot`/`stslot`, `.slot?`, `lsl #1/#2`, `movi #simm6`, `.bit4?`,
`.ext8?`), `ld.hu` for type 110, unsigned 12-bit ld/st offsets, `ld.bu` in
the class-E cells, per-operand bank bits (`rB!` by `x`, `rA!` by `m`, `rs1!`
by `ss`), `save w=2` = four words; the 48-bit `call` with the far tail is
retired (those packets are `call`/`b` with the F' = 0 tail at +2).
* `tools/gen_usip_tables.py`: `movhi` operand type, `base` as a constant added
to register/immediate fields, `scale` on immediates, `ge` and `any`
constraints, membership masks for the large CSR sets, the target guards as
constraint records, flag `USIP_F_ADJ2`, kinds `io`/`jr`, the `sys` name
table, extended CSR names, kind names; the header stays reproducible.
* `usip_decode.c`: F' = 0 control tails exactly at +2, target guards evaluated
after the match (32-bit: failure = `.word`; 16-bit `call.s`: fall-through),
`packet_len` constraints with the real packet length (stand-alone closers),
16-bit closers matched with bit 15, rules R0 (the final closer may be its own
group) and R7 (first-slot `ldslot`/`stslot`/`lea?` when the rest of the
packet is named), the `1dX6 + named tail` and validated-guard tie-breaks;
`UsipGuardCtx` lets the caller answer the guards.
* `arch_md32.c`: packet starts for the guards from the session (packets seen)
and from the bytes at hand (64 bytes of lookahead); function starts are not
available to an arch plugin, the documented fallback applies (`call?`,
`beqz.d?`... = unverified, `opex.target_guard`, confidence `medium`); types
`io`, `rjmp` (`jr?`), `ret` for `rti`, `trap`, `refptr` 8 for the 64-bit
pairs, `cast` for `extu`; CSR names in `opex`.
* `asm_md32.c`: pseudo syntax for the new mnemonics (`ior`/`iow`, `mfcsr`/
`mtcsr`, `addsp`, `ldslot`/`stslot`, `jr`, `nop32`, `sne`, `scmp`, `movhi`,
`extu`, the system ops, 64-bit loads/stores, the `?` marker).
* Tests: `test/test_plugin.py` vectors for `ior`/`iow`, `nop32`, the 32-bit
`ret`, `jr?`, `addsp`, `ld.d?`, the first-slot slot/`lea?` forms, `movhi?`
and the guarded 3-unit control packets (validated, failed and unverified);
`test/test_parse.c` vectors for the new pseudo rules; the `mov32`/`ld.b`
vectors now show the bank bit of the register it applies to (`r15!`).
### uSIP mode rewritten as a table-driven VLIW packet decoder
* `isa/usip_isa.json`: the instruction table (386 forms with masks, operand
fields, constraints and a confidence level) and the packet model;
`tools/gen_usip_tables.py` generates `usip_opcodes.h` from it.
* `usip_decode.c`/`.h`: packet decoder (16-bit unit scan, packets closed by
bit 15, heads-first/round-robin head-tail pairing per group, slot-0-only
control flow, delay slot = rest of the packet, 48-bit forms with hi/lo units,
documented tie-breaks and context rules).
* `arch_md32.c` (`cpu=usip`): one op per run of adjacent units of the same
instruction, `.unit` ops for displaced tails, packet cache in the session,
analysis types/conditions/targets/delay/fail for the whole control-flow
family, loads/stores and immediates, `opex` with form/confidence/packet info,
a register profile with the ABI, `MAXOP_SIZE` 16 in this mode. The previous
five hard-coded patterns (`b0`-`b7`, `save16`, two call shapes) are replaced
by named conditions and the table.
* `asm_md32.c`: pseudo syntax for the uSIP mnemonics (`#` immediates, `[base+off]`
memory operands, compare-and-branch, `save`/`restore`, `loop`).
* `test/test_plugin.py`: uSIP packet vectors (control flow in slot 0, delay
slots, interleaved `S S O O` layout, 48-bit forms, hardware loop, context
rule, truncated packet); `test/test_parse.c` updated for the new mnemonics.
* `test/test_emulator.py`: in usip mode the probe `5ef9 901a` is a delayed return,
so the strict stop is `unsupported_delay_slot_execution` (still zero steps).
* Documentation: README "uSIP mode", `doc/usip.md`.
+61
View File
@@ -0,0 +1,61 @@
R2 ?= r2
PKG_CONFIG ?= pkg-config
PYTHON ?= python3
CC ?= cc
SO_EXT := $(shell $(R2) -H R2_LIBEXT)
PLUGIN = arch_md32.$(SO_EXT)
ASM_PLUGIN = asm_md32.$(SO_EXT)
R2_PLUGIN_PATH ?= $(shell $(R2) -H R2_USER_PLUGINS)
CPPFLAGS += $(shell $(PKG_CONFIG) --cflags r_arch)
CFLAGS += -Wall -Wextra -Wno-unused-parameter -fPIC -O2
LDLIBS += $(shell $(PKG_CONFIG) --libs r_arch)
all: $(PLUGIN) $(ASM_PLUGIN) tools/md32-run
USIP_SRC = usip_decode.c
USIP_HDR = usip_decode.h usip_opcodes.h
# the SCQ16 decoder is included by scq16_arch.inc.c (one table instance): dependencies only
SCQ16_HDR = scq16_arch.inc.c scq16_vu.inc.c scq16_decode.c scq16_decode.h scq16_opcodes.h
$(PLUGIN): arch_md32.c md32_opcodes.h $(USIP_SRC) $(USIP_HDR) $(SCQ16_HDR)
$(CC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) -shared -o $@ arch_md32.c $(USIP_SRC) $(LDLIBS)
$(ASM_PLUGIN): asm_md32.c
$(CC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) -shared -o $@ asm_md32.c $(shell $(PKG_CONFIG) --libs r_asm)
install: $(PLUGIN) $(ASM_PLUGIN) tools/md32-run
mkdir -p "$(DESTDIR)$(R2_PLUGIN_PATH)"
cp -f $(PLUGIN) $(ASM_PLUGIN) "$(DESTDIR)$(R2_PLUGIN_PATH)/"
uninstall:
rm -f "$(DESTDIR)$(R2_PLUGIN_PATH)/$(PLUGIN)"
rm -f "$(DESTDIR)$(R2_PLUGIN_PATH)/$(ASM_PLUGIN)"
tools/md32-run: tools/md32-run.c arch_md32.c md32_opcodes.h $(USIP_SRC) $(USIP_HDR) $(SCQ16_HDR)
$(CC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) -o $@ tools/md32-run.c $(USIP_SRC) $(shell $(PKG_CONFIG) --libs r_anal)
test/test_md32: test/test_md32.c arch_md32.c md32_opcodes.h $(USIP_SRC) $(USIP_HDR) $(SCQ16_HDR)
$(CC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) -o $@ test/test_md32.c $(USIP_SRC) $(LDLIBS)
test/test_parse: test/test_parse.c asm_md32.c
$(CC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) -o $@ test/test_parse.c $(shell $(PKG_CONFIG) --libs r_asm)
test: $(PLUGIN) $(ASM_PLUGIN) tools/md32-run test/test_md32 test/test_parse
./test/test_md32
./test/test_parse
$(PYTHON) test/test_plugin.py
$(PYTHON) test/test_emulator.py
$(PYTHON) test/test_firmware.py
$(PYTHON) test/test_scq16.py
$(PYTHON) test/test_scq16_vectors.py
usip_opcodes.h: isa/usip_isa.json tools/gen_usip_tables.py
$(PYTHON) tools/gen_usip_tables.py $< -o $@
scq16_opcodes.h: isa/scq16_isa.json tools/gen_scq16_tables.py
$(PYTHON) tools/gen_scq16_tables.py $< -o $@
clean:
rm -f arch_md32.so arch_md32.dylib asm_md32.so asm_md32.dylib test/test_md32 test/test_parse tools/md32-run
.PHONY: all install uninstall test clean
+491
View File
@@ -0,0 +1,491 @@
# MD32 architecture plugin
Native radare2 `RArchPlugin` for the MediaTek MD32 **MS15E30** ISA. The decoder
covers all **258 encoding forms** in the public vendor disassembler, including
16/32-bit instructions, packed instruction pairs, DSP operations, control
registers, and hardware-loop setup. It has no runtime dependency on Python,
Ghidra, Capstone, or vendor binutils.
The plugin serves three encodings of the same modem DSP line, selected with
`asm.cpu`:
* **MS15E30** (the default): the public MD32 ISA, 16/32-bit instructions.
* **uSIP** (`e asm.cpu=usip`): a later MD32 variant that packs 16-bit units into
VLIW packets. Same register model and much of the same vocabulary as MS15E30,
but a different encoding; see [uSIP mode](#usip-mode).
* **SCQ16** (`e asm.cpu=scq16`): a byte-granular, big-endian packet encoding
that is **not** an MD32 encoding. It is served by this plugin because its
scalar programming model (32 general registers, `sp`/`lr` as control
registers, calling convention, the scalar operations and their ESIL) follows
MD32 closely; its instruction table is its own. See [SCQ16 mode](#scq16-mode).
The remaining DSP cores of the same modem use an unrelated SIMD ISA
(byte-granular, little-endian) and are out of this plugin's scope.
## Build and use
Requires radare2 development headers/libraries, `pkg-config`, a C compiler, and
make. Tested with radare2 6.2.5 on macOS arm64 and on Linux x86-64 (`make test`),
and 6.2.2 on Linux x86-64 (against 6.2.2 the optional `tools/md32-run` runner does not build because
`r_esil_set_fault` is missing from that release: build the two plugins with
`make arch_md32.so asm_md32.so`).
```sh
make
make install
r2 -a md32 -b 32 -e cfg.bigendian=true firmware.be.bin
```
`make install` copies the architecture and assembly parse plugins to
`r2 -H R2_USER_PLUGINS`. Override `R2_PLUGIN_PATH` to choose another location.
`make uninstall` removes both.
Without installation, load the built library using `L /absolute/path/arch_md32.dylib`
inside r2 (`.so` on Linux), then set `e asm.arch=md32`.
For pseudocode display, enable `e asm.pseudo=true`. The `md32` assembly parser
is selected automatically with `asm.arch=md32`; select it explicitly with
`e asm.parser=md32` if needed. Without installation, load `asm_md32.dylib`
alongside `arch_md32.dylib` before selecting the architecture.
The parser covers scalar moves, arithmetic, bit operations, signed/unsigned
comparisons, calls, jumps and Harvard data-memory accesses. For example,
`lw r2, (r1+=0x8)` becomes `r2 = dmem32[r1]; r1 += 0x8`. Signed byte/halfword
loads use `sext8`/`sext16`; packed pairs display as `parallel { ...; ...; }`.
Delayed control flow and unresolved DSP operations retain their assembly text.
In `usip` mode the same rules apply to the uSIP mnemonics (`ld.w r0, [r8+0x4]`
becomes `r0 = dmem32[r8 + 0x4]`, `bnez r15, 0x418` becomes
`if (r15 != 0) goto 0x418`); format-only `.xxx` forms and `.unit` tails keep
their text. This is a display parser; it does not add instruction encodings or
ESIL semantics.
Instructions use big-endian byte order and two-byte alignment. Older VPU/DSP
blobs store the instruction stream in reversed **four-byte storage words**.
Normalize those files before opening them:
```sh
python3 tools/swap_words.py vpu_p.bin firmware.be.bin
```
This is not ordinary per-instruction byte swapping: a four-byte storage word
may contain two instructions or part of an instruction crossing its boundary.
Do not apply this conversion to the already big-endian uSIP samples.
## Supplied uSIP samples
```sh
r2 -a md32 -b 32 -e cfg.bigendian=true -c 'e asm.cpu=usip' \
-m 0x400e0000 third_party/r2pkg/bin/usip_sec0.bin
r2 -a md32 -b 32 -e cfg.bigendian=true -c 'e asm.cpu=usip' \
-m 0x1ca34000 third_party/r2pkg/bin/usip_ddr.bin
```
Optional symbol flags, generated directly from the supplied inventory:
```sh
python3 tools/usip_symbols.py --section sec0 > /tmp/usip-sec0.r2
python3 tools/usip_symbols.py --section ddr > /tmp/usip-ddr.r2
```
Load the corresponding script with `. /tmp/usip-sec0.r2` or
`. /tmp/usip-ddr.r2`. The first 0x400 bytes of sec0 are the vector table;
use the symbol inventory to choose code entry points. These are supplied load
aliases; the reset-vector conflict reported by `tools/analyze_firmware.py`
means they are not a validated boot memory map.
## uSIP mode
`e asm.cpu=usip` selects the decoder for the **uSIP** variant of the MD32 family
(VLIW execute packets of 16-bit units). The instruction set is described by the
table `isa/usip_isa.json` (760 forms, generated into `usip_opcodes.h` by
`tools/gen_usip_tables.py`) and by the packet model implemented in
`usip_decode.c`. The table is an empirical description, not a vendor
specification: every form carries a confidence level (`high`, `medium`, `low`,
`format-only`) that the `aoj` output reports under `opex.confidence`.
### The packet model
* The unit is the 16-bit big-endian halfword. A **packet** is the run of units up
to and including the first one with bit 15 set (at most 8 units); packets start
at 2-byte alignment and the units of a packet execute in parallel.
* An **instruction** is a *head* (bit 15 = 0) plus 0, 1 or 2 *tails*
(16/32/48 bits; the 64-bit `b<cond>.l` prefix forms have three). Tails are not
necessarily adjacent to their head: a packet is a sequence of groups laid out
*heads first, then tails round-robin* (`S S O O` is two 32-bit instructions
interleaved; `x008 X hi lo hi' lo'` a 48-bit call interleaved with another
48-bit op). No bit selects the layout. The decoder enumerates every group split
and head/tail assignment the table allows, adds the explicit candidates of the
packet grammar (the 3-unit `[head][op16][F' = 0 tail]`, the 4-unit `H H T T`
pair of loads/stores) and keeps the smallest reading in the **prior-free total
order** `(s0, I, Fv, -A, K)`: unknown units plus the documented tie-break
penalties, then the number of instructions, then the heads whose tail
adjacency contradicts the F pattern (head F = 0 and next unit bit 14 = 1 means
an adjacent tail, otherwise a deferred one), then minus the number of adjacent
tails, then the lexicographic key of the assignment. Readings tied on the first
four go through the **K-tie cascade**: `dedup` (identical instruction texts),
`nowaw` (the only reading without a double register write) and `du2` (a
differential use-definition score over the neighbouring packets); a tie the
cascade decides is reported as `opex.packet.tiebreak`, one it cannot decide is
left to the key and reported as `opex.packet.ambiguous`.
* The **prefix forms**: a packet whose first three (four) units are a 48-bit
(64-bit, with the `1e0d` extension unit) `b<cond>.l rB, #imm9 / rA, target`
whose target is a packet start of the same function is that instruction plus
its delay slot (the rest of the packet); a failing guard just means the normal
layout. The absolute `call.abs`/`b.abs` prefix (`x008 + hi + lo`) is the other
prefix rule.
* Only **slot 0** (the first unit) can be control flow: `b<cond>`, `b`, `call`,
`loop rX`/`loop #N`, `ret`, the 16-bit `bz.s`/`bnz.s`/`b.s`/`call.s`,
`call.abs`/`b.abs`, the `b<cond>.l` prefix forms (the 32-bit `ret`/`ret?`,
`jr rB` and `call rB` of the `sys` shape may sit anywhere). The tail of a
branch/call/loop is at +1 or +2; the control tails with F' = 0 (`call`/`b`/
`b<cond>` with a 16-bit op in between) and `loop #N` with F = 1 and an S = 0
tail sit exactly at +2. When the control instruction does not close the
packet, the **rest of the packet is its delay slot** (both paths execute it).
The plugin reports `delay` = number of ops that follow in the packet and
`fail` = the next packet.
* Grammar rules of the layout: `5e0d` is never a tail and `5e0d`/`1e0d` never
take one (they are the structural no-op `nop.ctl`); a unit with bits 12:9 =
1010 is a `hi` syllable only inside a formed 48-bit instruction, otherwise an
ordinary head (a lone `.hi`/`.lo` only after a 48-bit-family head in the
packet); the `st.h` with the F' = 0 tail takes it at +2 or farther (an
adjacent tail is two 16-bit ops) and in the first slot loses against a `b.s`
head whose target is a packet start; an op 5 head on SP never takes a negative
`ld.d`/`st.d` tail; the immediate set-on-compare forms need an adjacent tail;
an `.op8?` pair of two slot-family units is two `ldslot`/`stslot` ops; an op 0
head takes `hi + lo` as one of 16 non-canonical 48-bit constants admitted by
value; the identical-bit cells `mfacc?` (k >= 2) and `add?`/`st.h?` (cell E)
are selected by the position of the head inside the packet. Once the layout
is decided, twenty **post-layout renames** relabel the instructions they
match (`nop.ctl`, the 16-bit `lsl`/`lsl?`/`sext16`/`zext16` variants, `addi
rA, #32` next to `cop rA`, `ld.w?` of cell A, the r15-based loads, the
register `bset`/`bext`, `.ldF0?` and the F' = 0 `ld.h?`/`ld.hu?`, `.3eX0?`).
* Some control forms carry a **target guard**: `loop`, `loop #N`, `b<cond>` and
`beqz.d`/`bnez.d` with the F' = 0 tail, the `b<cond>.d` with the `[0][1][tt]`
tail at +2 and the `b<cond>.l` prefix forms need a target at a packet start of
the same function, `call` with the F' = 0 tail and the open-packet `call.s`
need a function start, far `b` either. A 32-bit pair whose guard fails is data
(`.word`; the op C compare-and-branch cell leaves a `.dsp` pair); the 16-bit
`call.s` falls through to the plain reading; a prefix form is simply not
taken. A relative `call` into the middle of a known function pays a tie-break
penalty (`callin`) when the embedder can tell. See
[target guards](#target-guards) for what the plugin can check.
* Hardware loops: `loop rX, last=ADDR` / `loop# #N, last=ADDR` repeat the
following instructions up to `ADDR` (inclusive) `rX` / `N` times; they are
reported as a reference (`ptr`), not a branch (`val` = N).
### What one `pd` line is
A decode is one **op per run of adjacent units that belong to the same
instruction**: an instruction whose tails are adjacent is one op of 4, 6 or 8
bytes; an interleaved instruction shows its head as a 2-byte op with the full
operands and its displaced tails as `.unit 0xNNNN (mnemonic @ head)` ops, so that
every address of the stream is covered exactly once and the sizes add up. The
decoder needs the packet context: the decode at a packet start parses the whole
packet and caches it in the session, the following decodes inside the packet
(linear disassembly, function analysis) reuse that reading, and a decode at an
address that is not cached is treated as a packet start — true for branch
targets and function starts, not for an arbitrary mid-packet address, which may
then read differently than in the linear listing. `R_ARCH_INFO_MAXOP_SIZE` is
16 in this mode so that `ao`/analysis see the whole packet.
### Mnemonics and operands
Registers `r0-r15` (`r14` = SP, `r15` = LR); the second bank is written `rN!`
on the operand it applies to (bit `x` = the data/destination register, bit `m` =
the source/base register, also the compared register of the 32-bit branches and
the destination of `movi rA!, #imm5`, `ss & 2` = the first source of the
three-register ALU forms). Accumulators `A0-A3` (`mfacc rA, Ak.{lo,hi,ext}`),
port I/O `ior rB, [rA]`/`iow rB, [rA]` (`rA` holds the port number; there is no
classic CSR bank on this core), extended CSRs by number (`mfcsr rB, #nn`,
`mtcsr #nn, rA`), the system shape by name (`cop rA`, `rti`, `ieon`, `ieoff`,
`idle`, `lpexit?`, `isync?`, `sys #n`; with the F = S = 0 tail the packet stays
open), `nop32`, `addsp #imm` (SP adjust), `lea rA, [sp+off]`,
`ldslot`/`stslot rB, #k` (stack-slot access, 6-bit slot: the stack arguments
from the ninth on; `stslot?`/`ldslot?` where the slot or the role is open),
`sub r14, #imm` (frame allocation), `st.w [sp], #imm` (the ninth stack argument),
`ld.d`/`st.d rB:rB+1, [rA+off]` (64-bit pairs, signed offset multiple of 4),
`st.w`/`st.h [rB], #imm` (store of an immediate), `mov32 rB, #imm32` /
`add rB, rB, #imm32` (48-bit constants, by formula or by the value table),
`movhi rB, #imm` (20 bits << 12), `movi? rB, #imm20` / `movi? rB, #-32768`, the
set-on-compare family `seq`/`sne`/`sle`/`slt`/`sgt rB, rA, #imm`, `osl rB, rs1,
#1` (funnel shift), `bset`/`bclr?`/`binv?`/`bext? rd!, rs1, #imm5` and the
register forms `bset`/`bext rd, rs1, rB`, the bit-field family
`fxtu`/`fxts`/`fup rB, rs1, #w, #pos` (extract unsigned / signed, insert; `extu`,
`asr16`, `osl` keep their names), `mtacc? Ak, rs1:rB`, `nop.ctl`, `jr rB`.
Immediates carry a `#`; memory operands are `[rA+off]`, `[rA-off]` (the closed
negative bands of the half-word and word offsets; the word offsets have 14 bits:
`[rA+0x1xxx]`), `[rA]+`, `[rA+rB]`, `[sp+off]`, `[r15+off]`, `[#addr]`. Branch
targets and `loop` ends are printed absolute; the 48/64-bit compare-and-branch
forms are `b<cond>.l rB, #imm9, target` / `b<cond>.l rB, rA, target` (`bne beq
ble blt bge bgt bgeu bgtu`, the open cells `ble.l?`, `bneu.l?`, `bequ.l?`,
`bcc48?`), the delayed 32-bit ones `b<cond>.d` (also with the `[0][1][tt]` tail
at +2). Forms whose operation is unknown but whose grouping is established are
**format-only** and start with `.` (`.hword`, `.word`, `.w48`, `.dsp`, `.op4imm`,
`.op4t0`, `.ldF0?`, `.3eX0?`, `.slot?`, `.hi`/`.lo`/`.ext` ...) or end with `?`
(`ld.w?`, `mtacc?`, `fup?`): they are grouped correctly so that the packet and
delay slot model stays right, and reported with the `unk` type. `.hi`, `.lo`,
`.ext`, `.be79`, the 2- to 4-unit `bz.s`, the first-slot `ldslot`/`stslot`/`lea`, the
split `ldslot`/`stslot` halves (the `.op8?` pairs and the post-layout splits of the
slot family), the fused `op72?` pair, `movi #simm6` in a delay slot and the
`H H T T` loads/stores come from context rules, not plain table entries.
A control instruction printed with a trailing `?` (`call?`, `beqz.d?`, `bne.l?`,
`loop#?`, `bne.d?`) is one whose target guard could not be evaluated (see below).
### Target guards
The guarded forms need to know whether the target is a packet start of the
current function or a function start. The plugin derives **packet starts from
the stream**: the packets decoded earlier in the session (backward targets, and
forward targets of a region already decoded, e.g. after `aa` or on a second
`pd`) and a scan of the bytes radare2 hands the decoder past the current packet
(at most 64 bytes of lookahead). A forward target farther away is unknown.
**Function starts are not available** to an arch plugin (radare2 gives it no
typed access to RAnal). When a guard cannot be evaluated the plugin applies a
fallback measured on the sample the table was built from: the forms whose
unverified readings are right in nearly every case are read anyway, printed
with a trailing `?`, confidence `medium` and `opex.target_guard = "unverified"`
(`call` with the F' = 0 tail at +2, `b` with the F' = 0 tail, `b<cond> rA, #imm`
with the F' = 0 tail, `beqz.d`, the `b<cond>.l` prefix forms with a forward
target, `loop #N` with F = S = 1, with F = 0 and the tail adjacent, with F = 1
and the S = 0 tail at +2, with the F' = 0 tail at +2 and with h = 1 (N >= 128)
and the S = 1 tail or the adjacent F = 0 tail, `loop rX` with F = 1 and the
S = 1 F' = 0 tail at +2, and the `b<cond>.d` cells with the `[0][1][tt]` tail
`bne`/`blt`/`bgeu`/`bgtu`/`bge` with immediate, `beqz.d`/`bnez.d` and `bleu`
with registers); the others are treated as a failed guard (`loop rX` with the
other F' = 0 tails, `loop #N` with F = 0 and the tail at +2, the m = 1
`loop #N?` heads and the other h = 1 loop cells, far `b`, `bnez.d` of the
F = S = 0 cell, the register `b<cond>` with the F' = 0 tail, the other
`b<cond>.d` cells, the open-packet `call.s`), i.e. `.word`, the plain 16-bit
reading or the normal layout. The forms whose guard is a validation filter (the
F = S = 0 and the F = 0 `b<cond>.d` cells, `bne.d #-1`, the hardware loops with
the F' = 1 tail, the near `b`, the open `b.s`) keep their reading when the
target is unknown (printed with the `?` too) and are rejected by a known target
that is not a packet start; a conditional branch whose unknown target lies
backward is not read. A validated guard reports `opex.target_guard =
"validated"`. The K-tie cascade sees the packets decoded earlier in the session
and the ones inside the same lookahead (see `doc/usip.md` §7 for what is
approximated).
### Analysis
Operation types: `cjmp` with `cond` for the compare-and-branch forms (there are
no flags on this core; `bequ`/`bneu` are the unsigned equality cells of the
48-bit forms), `jmp`, `call`/`rcall`, `ret` (also `rti`), `rjmp` for `jr rB`,
`io` for `ior`/`iow` (`ireg` = the port register), `load`/`store` with
`refptr`/`ireg`/`disp` (`stackop` on `r14`; `refptr` 8 for `ld.d`/`st.d`; the
signed offsets also appear as the `off` operand of `opex`), `mov` with `val` for
the immediate moves (`movi`, `movi?`, `mov32`, `movhi`),
`add`/`sub`/`and`/`or`/`xor`/`shl`/`shr`/`sar`/`mul`/`div`/`cmp`/`cmov`/`cast`
(`osl` is a `shl`, the set-on-compare family `cmp`, `fxtu`/`fxts` `cast`, `fup`
`or`), `lea` for `lea`/`lea?`, `nop` for `nop32`/`nop.ctl`, `rpush`/`pop` for
`save`/`restore`, `trap` for `trap?`, `swi` for the other system ops; `loop #N`
carries the count in `val`. `opex` carries the form id, confidence, kind, slot,
unit addresses, the delay-slot flag, the target-guard status, the packet's
ambiguity / tie-break and the operands.
The register profile exposes the ABI (`SP=r14`, `LR=r15`, arguments `r0-r7`,
return `r0`). No ESIL is produced for uSIP.
### Limitations
* The reading is table-driven, deterministic and prior-free. Four kinds of
packets can read differently from the intended one: packets where several
head/tail assignments tie on the first four keys of the layout order and the
K-tie cascade cannot decide (flagged by `opex.packet.ambiguous`) or decides
them with a shorter context than a whole-function scan would give (`du2`),
control flow in open packets (`call`/`b`/`loop`/`loop #N`/`b.s` followed by
delay-slot ops) when the branch reading is not the cheapest one (a `loop #N`
reading with a 16-bit middle unit often writes a register twice with the
stolen tail, which the R-waw rule charges), the guarded forms whose
target the plugin cannot check (far `b` to another function or beyond the
lookahead, the open-packet `call.s`, `loop`/`bnez.d`, the `b<cond>.d` register
cells and the `bz.s` of 3-unit and longer packets with a forward target
beyond the lookahead), and the `call` pairs whose tail choice depends on the
`callin` tie-break. A disassembler that knows the function table can prefer
the reading whose target is a function start or a packet boundary and answer
`callin`; `UsipGuardCtx` in `usip_decode.h` is the hook for that knowledge.
* Open points of the ISA: the remaining layout ties, the sign and width of the
`?` forms (`ld.d?`/`st.d?` with b10, `ld.w?`/`st.w?` in the 0x800-0xeff band,
`seq?`/`sle?` with large immediates, `mov32?`, `lea?`, `mfacc?`, `add?`/`st.h?`
of cell E, `bcc48?`, `movi?`, `mtacc?`, `fup?`, `.ldF0?`), the `f12 = 1 / 3
mod 4` word displacements below 0x800, `.op4t0` (a stolen tail), `.3eX0?`,
`ld.w` vs `add` in the op 0 F = S = 1 cell, the exact
`save w` frame size, `sys #2/#4/#8`, `L_mult` vs `L_mult.e`, why the scheduler
inserts `nop.ctl`, the `?ss=N` loops, the sign of the
`ld.w?`/`st.w?` word classes, `.stimm16?`, the `lsl?`/`asr?` cells without an
idiom.
* A decode in the middle of a packet without the packet cached (e.g. `ao` at an
arbitrary address) sees a different packet than the linear listing.
* At the end of a map, `ao` pads the read with `0xff`, which is a legal closing
unit; the disassembly path (`pd`) gets the exact bytes and marks the packet
`truncated`.
See [doc/usip.md](doc/usip.md) for the table format and the constraint and
context-rule semantics.
## SCQ16 mode
`e asm.cpu=scq16` selects the decoder for the **SCQ16**, a byte-granular
encoding of the same modem DSP line (not an MD32 encoding; it shares the
scalar programming model, see the introduction) whose instruction stream is byte-granular: units of 2 to 6
bytes (vector operations are 4 bytes, bundles 8), optionally paired in a
**packet** `{ A ‖ B }` whose two units execute in parallel. The table is an
empirical description, not a vendor specification: every form carries a
confidence level (`high`, `medium`, `low`, `format-only`) that the `aoj` output
reports under `opex.units[].confidence`. Select it with
```sh
r2 -a md32 -b 32 -e cfg.bigendian=true -e asm.cpu=scq16 firmware.be.bin
```
Functions may start at odd addresses (`asm.cpu=scq16` sets the code and
function alignment to 1). Inside a session set `e asm.cpu=scq16` before
`e asm.arch=md32` (or re-select `asm.arch` afterwards): the register profile
of the SCQ16 (`sp`/`lr` as csr14/csr15, the VU ports) is read when the arch
session is created. The table is `isa/scq16_isa.json`, compiled into
`scq16_opcodes.h` by `tools/gen_scq16_tables.py`. See
[doc/scq16.md](doc/scq16.md) for the encoding model, the length rule and the
form families.
### What one `pd` line is
* a stand-alone unit: `lw r5, 0x4(r1)`, `jal.d1 0x00001010`;
* a packet: `{ mv r1, r3 ‖ beqz r5, #0, 0x0000100e }`: the first
byte of the head has its bit 7 set, the head is read shifted left by one bit
with the top bit of the second unit borrowed in (the `transformed` field of
`aoj` shows the head as decoded); control flow only lives in the second
slot, and its targets are relative to the packet start;
* a vector operation: `v.alu3 op9=0x1c1 A0 B0 F1,F2,F3`: the op9 code is
printed with its class (`v.<class>`), with an established operation name
when there is one (`v.move.mv`, `v.mem.ld`, `v.mem.st`) and with a
provisional name as `v.<class>.<name>?`; the fields A/B/F1-F3 are shown raw;
* a bundle: `vbundle v.mem.ld op9=0x00a … ‖ add r2, r6 ‖ add r3, r1`: a
32-bit vector operation and two 15-bit scalar slots in 8 bytes.
Provisional mnemonics carry a `?` (`sel?`, `cmov.leu?`, `vrd?`, `vwr?`,
`vpmem?`, `lhu.post?`, `ld46?`, `sqr?`, `sra?`, `vwait?`…): the encoding is fixed, the
operation is not. Family placeholders (`op41`, `op43`, `op67`, `op6f`, `alu41`…) print
their fields and are not named. Both are OPEN readings: `aoj` reports them with
`open: true` and `reading: provisional | placeholder` (`established` otherwise, and
`hypothetical: true` when the ESIL is the reading of a hypothesis), and an open
reading without semantics has the uniform ESIL marker `REF,ALT,open` (no effect).
### Analysis and ESIL
`aoj` gives the type, `jump`/`fail` (fall-through after the delay slots,
which are counted in instructions: `.d1` one, `.d2` two), `delay`, the loop
end of `do` as a reference (`ptr`) with the count in `reg`/`val`, loads and
stores with `refptr`/`ireg`/`disp`, the stack ops, and an `opex` with the
`shape` (unit/packet/bundle), the `units[]` (slot, address, size, mnemonic,
form, confidence, operands) and `parallel`.
The ESIL covers the scalar forms: a packet is emitted as A followed by B with
the registers that B reads and A writes copied to the temporaries `t0-t3`
first (parallel semantics), delayed transfers use `SETJT`/`SETD` so that `aes`
executes the slot before the jump (a `.d2` transfer takes two `aes` steps),
memory addresses are cut to 32 bits, `do` writes `lc0/le0/ls0`, division fills
`a0l`/`a0h`. The VU scalar ports are registers (`vu0-vu31` for `vget`,
`v0-v31` as the scalar shadow of `vbcast`, `va0-va7`, `vp0-vp7`, `vs0-vs15`,
`vb1_*`/`vb3_*`/`vb5_*`, `udf0-udf31`) and every vector operation is the custom
op `vop` (op9, A, B, F1, F2, F3). `vop` models the three established vector
operations on a vector register file `vr0-vr31` (128 bytes each, shown as the
256-bit quarters `vrK_0..vrK_3`): `v.mem.ld` loads `va[A]` halves from the
pointer `vp[2*F2 + F3[4]]` into `vr[F1 >> 2]`, `v.mem.st` stores them from `vr0`,
both post-incrementing the pointer, and `v.move.mv` copies `vr[F3]` into
`vr[F1]`; every other vector op has no effect. `vbcast v_k, rs` / `vbcast.i`
write the scalar port `v_k` and the plugin broadcasts the low 16 bits to the 64
lanes of `vr_k`. Forms without an established operation have the marker ESIL
`REF,ALT,open`, except the hypothetical readings flagged in the table (among them
the packing of `op41.fld`, carried by the ISA source; the file of
plugin hypotheses `isa/scq16_hyp.json` is empty). `ctz` of a zero operand gives
-1 in the ESIL (`31 - clz(0)`); whether the hardware returns 32 is open.
Registers: `r0-r31`, `pc`, `sr`/`ipc`/`isr`/`lf`, the loop registers
`ls0-2`/`le0-2`/`lc0-2`, `sp` and `lr` as the special registers csr14/csr15
(the public MD32 ABI: arguments r3-r6, return r1; r16-r31 are callee-saved,
r0-r15 caller-saved), the accumulator `a0` (`a0l`/`a0h`), the VU state.
The data-space bases (main data memory at 0, the I/O window at 0x8000, the
second data memory at 0x40000) can be added as flags with
`. tools/scq16_flags.r2`; the data memory is little-endian while the code is
big-endian. `j.d1 56` with the top bits of its second byte clear is decided by
its target (see doc/scq16.md).
## Analysis and emulation
The MS15E30 decoder provides operation types, direct targets, register-indirect
jumps/calls, returns, condition codes, delay counts, memory widths and signedness,
operand values, JSON operands, and the register profile. Relative targets wrap
at 32 bits. Delay-slot counts are in decoded instructions/bundles; the
fallthrough address is computed from their actual lengths when lookahead is
available. If lookahead is insufficient, delayed fallthrough remains unknown.
ESIL covers register/immediate moves, ordinary integer arithmetic and logic,
logical/arithmetic shifts, leading-bit counts, scalar min/max, conditional
inversion, multiplication, loads/stores, and immediate control flow,
including signed/unsigned comparisons. It does not model carry/borrow flags,
DSP saturation/rounding, interrupt status restoration, delayed control-flow
execution, hardware-loop execution, or parallel bundle execution. These
instructions still disassemble. Hardware-loop setup reports the loop-end
reference; automatic loop back edges are not inferred.
A packed pair is one four-byte decode unit, displayed as `slot0 | slot1`.
Control flow in its second slot is retained. Other pairs have `unk` as their
aggregate operation type, and operand JSON records their slot numbers. This
preserves decode boundaries without inventing a sequential execution model.
Program and data memory are separate on MD32; r2's usual flat memory view needs
appropriate maps for your firmware before memory emulation is useful.
## Verification
```sh
make test
```
This runs native decoder/parser tests, exhaustive halfword/truncation checks, actual r2
plugin/analysis/ESIL tests, and checks all **1,128 functions / 100,275 instruction
lengths** against the supplied uSIP inventory. The original private `dsp.bin` and
`DbgInfo` files are not required.
Optional independent vendor comparison (see [research notes](doc/research.md)
for downloads and checksums):
```sh
python3 -m venv /tmp/md32-verify
/tmp/md32-verify/bin/pip install unicorn
/tmp/md32-verify/bin/python test/test_oracle.py /tmp/md32-objdump
```
The test emulates the vendor's original x86-64 disassembly function using
Unicorn and compares decoded text, operands, validity, and lengths. Use
`--quick` for a smaller run or `--firmware firmware.be.bin` to add a firmware
image. The checked run included **141,924 cases with zero mismatches**, including
all halfword patterns, randomized operands for every vendor instruction form,
packed pairs, and the MT8173 VPU program image.
See [doc/research.md](doc/research.md) for provenance, the binutils findings,
MD380 distinction, and remaining research questions.
## Firmware exploration and strict ESIL execution
The newer `third_party/v2/r2pkg` bundle adds BRP and a CSV inventory covering
1,301 functions. `tools/analyze_firmware.py` reports the startup probes,
purpose/structure, points of interest, missing encodings, string scan, mapping
conflicts and plugin fixes, and writes the complete listings plus the
three-image loader script into a local `usipdata/` directory. Those artifacts
are derived from the third-party firmware, so the directory is gitignored and
not shipped.
```sh
make test
python3 tools/analyze_firmware.py
r2 -a md32 -c '. usipdata/load-usip.r2' malloc://1
tools/md32-run --cpu usip \
--image third_party/v2/r2pkg/bin/usip_sec0.bin@0x400e0000 --vector
```
The runner uses separate code/data maps. Add `--data FILE@BASE` for known data,
`--ram BASE:SIZE` for uninitialized RAM, `--zero BASE:SIZE` for deliberately
zeroed RAM, and `--reg NAME=VALUE` for known register state. It reports JSON and
stops on unresolved semantics, unknown memory/register state or unmodeled MMIO.
A reported stop is an analysis result, not a successful firmware boot. The
supplied uSIP reset/startup probes currently complete zero instructions.
Loaded 100 of 311 files, more files were not shown because too many files have changed in this diff. Show more