Skip to content

Commit

Permalink
Initial support for the UXN machine ##arch
Browse files Browse the repository at this point in the history
  • Loading branch information
radare authored and trufae committed Jul 10, 2024
1 parent 9d8fa62 commit 33607b8
Show file tree
Hide file tree
Showing 5 changed files with 207 additions and 2 deletions.
1 change: 1 addition & 0 deletions dist/plugins-cfg/plugins.def.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ arch.sparc_gnu
arch.tms320
arch.tricore
arch.tricore_cs
arch.uxn
arch.v810
arch.v850
arch.vax
Expand Down
10 changes: 10 additions & 0 deletions libr/arch/p/uxn.mk
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
OBJ_UXN=p/uxn/plugin.o
# OBJ_UXN+=p/uxn/uxndisass.o

STATIC_OBJ+=$(OBJ_UXN)
TARGET_UXN=p/arch_uxn.$(EXT_SO)

ALL_TARGETS+=$(TARGET_UXN)

${TARGET_UXN}: $(OBJ_UXN)
${CC} $(call libname,arch_uxn) $(LDFLAGS) $(CFLAGS) -o arch_uxn.$(EXT_SO) $(OBJ_UXN)
43 changes: 43 additions & 0 deletions libr/arch/p/uxn/plugin.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/* radare2 - PD - Copyright 2024 - pancake */

#include <r_arch.h>
#include "uxndisass.inc.c"

static bool uxn_decode(RArchSession *a, RAnalOp *op, RArchDecodeMask mask) {
char text[32];

int len = uxn_disassemble (op->bytes, op->size, text, sizeof (text));
if (len > 0) {
op->type = R_ANAL_OP_TYPE_MOV;
op->size = len;
op->mnemonic = strdup (text);
} else {
op->size = 1;
}
return true;
}

static int archinfo(RArchSession *a, ut32 q) {
return 1;
}

const RArchPlugin r_arch_plugin_uxn = {
.meta = {
.name = "uxn",
.desc = "UXN",
.license = "PD",
},
.bits = 32,
.arch = "uxn",
.info = archinfo,
.decode = &uxn_decode,
// .encode = &uxn_encode,
};

#ifndef R2_PLUGIN_INCORE
R_API RLibStruct radare_plugin = {
.type = R_LIB_TYPE_ARCH,
.data = &r_arch_plugin_uxn,
.version = R2_VERSION
};
#endif
150 changes: 150 additions & 0 deletions libr/arch/p/uxn/uxndisass.inc.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
/* radare2 - PD - Copyright 2024 - pancake */

#include <r_util.h>

#define MAX_INSTRUCTION_LEN 16
#define NUM_INSTRUCTIONS 256

typedef struct {
uint8_t opcode;
int operand;
} Instruction;

static const char* instruction_mnemonics[NUM_INSTRUCTIONS] = {
"brk", "inc", "pop", "nip", "swp", "rot", "dup", "ovr",
"equ", "neq", "gth", "lth", "jmp", "jcn", "jsr", "sth",
"ldz", "stz", "ldr", "str", "lda", "sta", "dei", "deo",
"add", "sub", "mul", "div", "and", "ora", "eor", "sft",
"jci", "inc2", "pop2", "nip2", "swp2", "rot2", "dup2", "ovr2",
"equ2", "neq2", "gth2", "lth2", "jmp2", "jcn2", "jsr2", "sth2",
"ldz2", "stz2", "ldr2", "str2", "lda2", "sta2", "dei2", "deo2",
"add2", "sub2", "mul2", "div2", "and2", "ora2", "eor2", "sft2",
"jmi", "incr", "popr", "nipr", "swpr", "rotr", "dupr", "ovrr",
"equr", "neqr", "gthr", "lthr", "jmpr", "jcnr", "jsrr", "sthr",
"ldzr", "stzr", "ldrr", "strr", "ldar", "star", "deir", "deor",
"addr", "subr", "mulr", "divr", "andr", "orar", "eorr", "sftr",
"jsi", "inc2r", "pop2r", "nip2r", "swp2r", "rot2r", "dup2r", "ovr2r",
"equ2r", "neq2r", "gth2r", "lth2r", "jmp2r", "jcn2r", "jsr2r", "sth2r",
"ldz2r", "stz2r", "ldr2r", "str2r", "lda2r", "sta2r", "dei2r", "deo2r",
"add2r", "sub2r", "mul2r", "div2r", "and2r", "ora2r", "eor2r", "sft2r",
"lit", "inck", "popk", "nipk", "swpk", "rotk", "dupk", "ovrk",
"equk", "neqk", "gthk", "lthk", "jmpk", "jcnk", "jsrk", "sthk",
"ldzk", "stzk", "ldrk", "strk", "ldak", "stak", "deik", "deok",
"addk", "subk", "mulk", "divk", "andk", "orak", "eork", "sftk",
"lit2", "inc2k", "pop2k", "nip2k", "swp2k", "rot2k", "dup2k", "ovr2k",
"equ2k", "neq2k", "gth2k", "lth2k", "jmp2k", "jcn2k", "jsr2k", "sth2k",
"ldz2k", "stz2k", "ldr2k", "str2k", "lda2k", "sta2k", "dei2k", "deo2k",
"add2k", "sub2k", "mul2k", "div2k", "and2k", "ora2k", "eor2k", "sft2k",
"litr", "inckr", "popkr", "nipkr", "swpkr", "rotkr", "dupkr", "ovrkr",
"equkr", "neqkr", "gthkr", "lthkr", "jmpkr", "jcnkr", "jsrkr", "sthkr",
"ldzkr", "stzkr", "ldrkr", "strkr", "ldakr", "stakr", "deikr", "deokr",
"addkr", "subkr", "mulkr", "divkr", "andkr", "orakr", "eorkr", "sftkr",
"lit2r", "inc2kr", "pop2kr", "nip2kr", "swp2kr", "rot2kr", "dup2kr", "ovr2kr",
"equ2kr", "neq2kr", "gth2kr", "lth2kr", "jmp2kr", "jcn2kr", "jsr2kr", "sth2kr",
"ldz2kr", "stz2kr", "ldr2kr", "str2kr", "lda2kr", "sta2kr", "dei2kr", "deo2kr",
"add2kr", "sub2kr", "mul2kr", "div2kr", "and2kr", "ora2kr", "eor2kr", "sft2kr"
};

static int find_opcode(const char* mnemonic) {
char upper_mnemonic[MAX_INSTRUCTION_LEN];
r_str_ncpy (upper_mnemonic, mnemonic, sizeof (upper_mnemonic));
r_str_case (upper_mnemonic, false);
int i;

for (i = 0; i < NUM_INSTRUCTIONS; i++) {
if (!strcmp (instruction_mnemonics[i], upper_mnemonic)) {
return i;
}
}
return -1;
}

int uxn_assemble(const char* mnemonic, uint8_t* code, size_t code_size) {
int code_len = 0;
if (code_size < 3) {
return -1;
}
Instruction instr = {0};
char op[MAX_INSTRUCTION_LEN];
r_str_ncpy (op, mnemonic, sizeof (op));
char *arg = strchr (op, ' ');
int args = 0;
if (arg) {
*arg++ = 0;
instr.operand = atoi (arg);
args++;
}

int opcode = find_opcode(op);
if (opcode == -1) {
return -1;
}

instr.opcode = opcode;

code[code_len++] = instr.opcode;
if (args > 1) {
if (instr.opcode == 0x80 || (instr.opcode >= 0xA0 && instr.opcode <= 0xBF) ||
instr.opcode == 0x2C || instr.opcode == 0x2D || instr.opcode == 0x2E) {
// LIT2, JMP2, JCN2, JSR2, and their variations
code[code_len++] = (instr.operand >> 8) & 0xFF;
code[code_len++] = instr.operand & 0xFF;
} else if (instr.opcode == 0x60) { // JSI
code[code_len++] = instr.operand & 0xFF;
} else if (instr.opcode >= 0x80) {
code[code_len++] = instr.operand & 0xFF;
}
}

return code_len;
}

R_IPI int uxn_disassemble(const uint8_t* code, size_t code_size, char *text, size_t text_size) {
Instruction instr = {0};
instr.opcode = code[0];

const char* op = instruction_mnemonics[instr.opcode];
if (!op) {
op = "invalid";
}

size_t len = 1;
if (instr.opcode == 0x80 || (instr.opcode >= 0xA0 && instr.opcode <= 0xBF) ||
instr.opcode == 0x2C || instr.opcode == 0x2D || instr.opcode == 0x2E) {
// LIT2, JMP2, JCN2, JSR2, and their variations
instr.operand = (code[1] << 8) | code[2];
snprintf(text, text_size, "%s 0x%04x", op, instr.operand);
len = 3;
} else if (instr.opcode == 0x60) { // JSI
instr.operand = code[1];
snprintf(text, text_size, "%s 0x%02x", op, instr.operand);
len = 2;
} else if (instr.opcode >= 0x80) {
instr.operand = code[1];
snprintf(text, text_size, "%s 0x%02x", op, instr.operand);
len = 2;
} else {
snprintf(text, text_size, "%s", op);
}

return len;
}

#if 0
const char* test_instructions[] = {
"BRK", "INC", "POP", "NIP", "SWP", "ROT", "DUP", "OVR",
"EQU", "NEQ", "GTH", "LTH", "JMP", "JCN", "JSR", "STH",
"LDZ", "STZ", "LDR", "STR", "LDA", "STA", "DEI", "DEO",
"ADD", "SUB", "MUL", "DIV", "AND", "ORA", "EOR", "SFT",
"LIT 42", "LIT2 1234", "JMP2 0x1000", "JSI 0x20",
"inc2r", "pop2k", "jsr2kr 0x3000"
"BRK", "INC", "POP", "NIP", "SWP", "ROT", "DUP", "OVR",
"EQU", "NEQ", "GTH", "LTH", "JMP", "JCN", "JSR", "STH",
"LDZ", "STZ", "LDR", "STR", "LDA", "STA", "DEI", "DEO",
"ADD", "SUB", "MUL", "DIV", "AND", "ORA", "EOR", "SFT",
"LIT 42", "LIT2 1234", "JMP2 0x1000", "JSI 0x20",
"inc2r", "pop2k", "jsr2kr 0x3000",
"JCN2 0x2000", "JSR2 0x3000",
"LIT2r 0xABCD", "JMP2k 0x4000", "JCN2k 0x5000", "JSR2k 0x6000"
};
#endif
5 changes: 3 additions & 2 deletions libr/include/r_arch.h
Original file line number Diff line number Diff line change
Expand Up @@ -312,6 +312,7 @@ extern const RArchPlugin r_arch_plugin_mcs96;
extern const RArchPlugin r_arch_plugin_mips_cs;
extern const RArchPlugin r_arch_plugin_mips_gnu;
extern const RArchPlugin r_arch_plugin_msp430;
extern const RArchPlugin r_arch_plugin_nds32;
extern const RArchPlugin r_arch_plugin_nios2;
extern const RArchPlugin r_arch_plugin_null;
extern const RArchPlugin r_arch_plugin_or1k;
Expand All @@ -333,9 +334,11 @@ extern const RArchPlugin r_arch_plugin_sm5xx;
extern const RArchPlugin r_arch_plugin_snes;
extern const RArchPlugin r_arch_plugin_sparc_cs;
extern const RArchPlugin r_arch_plugin_sparc_gnu;
extern const RArchPlugin r_arch_plugin_stm8;
extern const RArchPlugin r_arch_plugin_tms320;
extern const RArchPlugin r_arch_plugin_tricore;
extern const RArchPlugin r_arch_plugin_tricore_cs;
extern const RArchPlugin r_arch_plugin_uxn;
extern const RArchPlugin r_arch_plugin_v810;
extern const RArchPlugin r_arch_plugin_v850;
extern const RArchPlugin r_arch_plugin_vax;
Expand All @@ -345,11 +348,9 @@ extern const RArchPlugin r_arch_plugin_x86_cs;
extern const RArchPlugin r_arch_plugin_x86_nasm;
extern const RArchPlugin r_arch_plugin_x86_nz;
extern const RArchPlugin r_arch_plugin_xap;
extern const RArchPlugin r_arch_plugin_stm8;
extern const RArchPlugin r_arch_plugin_xcore_cs;
extern const RArchPlugin r_arch_plugin_xtensa;
extern const RArchPlugin r_arch_plugin_z80;
extern const RArchPlugin r_arch_plugin_nds32;

#ifdef __cplusplus
}
Expand Down

0 comments on commit 33607b8

Please sign in to comment.