Initial support for the UXN machine ##arch

This commit is contained in:
pancake 2024-07-10 19:03:46 +02:00 committed by pancake
parent 9d8fa62011
commit 33607b853e
5 changed files with 207 additions and 2 deletions

View File

@ -72,6 +72,7 @@ arch.sparc_gnu
arch.tms320
arch.tricore
arch.tricore_cs
arch.uxn
arch.v810
arch.v850
arch.vax

10
libr/arch/p/uxn.mk Normal file
View File

@ -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
libr/arch/p/uxn/plugin.c Normal file
View File

@ -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

View File

@ -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

View File

@ -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;
@ -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;
@ -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
}