Initial implementation of the MIPS assembler

This commit is contained in:
pancake 2012-08-31 13:50:05 +02:00
parent 5c236fa0e3
commit a395c8d6c8
4 changed files with 138 additions and 2 deletions

View File

@ -120,6 +120,7 @@ static int mips_op(RAnal *anal, RAnalOp *op, ut64 addr, const ut8 *b, int len) {
} else
if ((optype & 0x3e) == 2) {
#if 0
// J-TYPE
|--[0]--| |--[1]--| |--[2]--| |--[3]--|
1111 1111 1111 1111 1111 1111 1111 1111
\_op__/\______address____________________/

View File

@ -0,0 +1,132 @@
/* radare - Copyright 2012 - pancake */
#include <r_types.h>
static const char * const regs[32] = {
"zero", "at", "v0", "v1", "a0", "a1", "a2", "a3",
"a4", "a5", "a6", "a7", "t0", "t1", "t2", "t3",
"s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
"t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra",
NULL
};
static struct {
const char *name;
int type;
int args;
int n;
} ops[] = {
{ "nop", 'N', 0, NULL },
{ "lui", 'I', 2, 15 },
{ "sw", 'I', 3, 43 },
{ "sh", 'I', 3, 41 },
{ "sb", 'I', 3, 40 },
{ "lw", 'I', 3, 35 },
{ "lh", 'I', 3, 33 },
{ "lb", 'I', 3, 32 },
{ "ori", 'I', 3, 13 },
{ "andi", 'I', 3, 12 },
{ "xori", 'I', 3, 14 },
{ "addi", 'I', 3, 8 },
{ "addiu", 'I', 3, 9 },
{ "bnez", 'I', 2, 5 },
{ "jalr", 'R', 1, 9 },
{ "jr", 'R', 1, 8 },
{ "jal", 'J', 1, 3 },
{ "j", 'J', 1, 2 },
{ NULL }
};
static int mips_r (ut8 *b, int op, int rs, int rt, int rd, int sa, int fun) {
if (rs == -1 || rt == -1) return -1;
b[3] = ((op<<2)&0xfc) | ((rs>>3)&3);
b[2] = (rs<<5) | (rt&0x1f);
b[1] = ((rd<<3)&0xff) | (sa>>2);
b[0] = (fun&0x3f) | ((sa&3)<<5);
return 4;
}
static int mips_i (ut8 *b, int op, int rs, int rt, int imm) {
if (rs == -1 || rt == -1) return -1;
b[3] = ((op<<2)&0xfc) | ((rs>>3)&3);
b[2] = (rs<<5) | (rt);
b[1] = (imm>>8) &0xff;
b[0] = imm & 0xff;
return 4;
}
static int mips_j (ut8 *b, int op, int addr) {
addr /= 4;
b[3] = ((op<<2)&0xfc) | ((addr>>24)&3);
b[2] = (addr>>16)&0xff;
b[1] = (addr>>8) &0xff;
b[0] = addr & 0xff;
return 4;
}
static int getreg (const char *p) {
int n = (int) r_num_get (NULL, p);
if (n==0) {
if (strcmp (p, "0")) {
for (n=0; regs[n]; n++) {
if (!strcmp (p, regs[n]))
return n;
}
} else n = -1;
}
return n;
}
int mips_assemble(const char *str, ut64 pc, ut8 *out) {
int i, hasp;
char *s = strdup (str);
char w0[32], w1[32], w2[32], w3[32];
r_str_replace_char (s, ',', ' ');
hasp = r_str_replace_char (s, '(', ' ');
r_str_replace_char (s, ')', ' ');
*out = 0;
*w0=*w1=*w2=*w3=0;
sscanf (s, "%31s", w0);
if (*w0)
for (i=0; ops[i].name; i++) {
if (!strcmp (ops[i].name, w0)) {
switch (ops[i].args) {
case 1: sscanf (s, "%31s %31s", w0, w1); break;
case 2: sscanf (s, "%31s %31s %31s", w0, w1, w2); break;
case 3: sscanf (s, "%31s %31s %31s %31s", w0, w1, w2, w3); break;
}
if (hasp) {
char tmp[32];
strcpy (tmp, w2);
strcpy (w2, w3);
strcpy (w3, tmp);
}
switch (ops[i].type) {
case 'N': // nop
memset (out, 0, 4);
break;
case 'R':
switch (ops[i].args) {
case 1: return mips_r (out, 0, getreg (w1), getreg (w2), getreg (w3), 0, ops[i].n);
case 2: return mips_i (out, ops[i].n, 0, getreg (w1), getreg (w2)); break;
case 3: return mips_i (out, ops[i].n, getreg (w1), getreg (w2), getreg (w3)); break;
}
break;
case 'I':
switch (ops[i].args) {
case 2: return mips_i (out, ops[i].n, 0, getreg (w1), getreg (w2)); break;
case 3: return mips_i (out, ops[i].n, getreg (w2), getreg (w1), getreg (w3)); break;
}
break;
case 'J':
switch (ops[i].args) {
case 1: return mips_j (out, ops[i].n, getreg (w1)); break;
}
break;
}
return -1;
}
}
free (s);
return -1;
}

View File

@ -356,7 +356,7 @@ R_API char* r_str_replace(char *str, const char *key, const char *val, int g);
R_API void r_str_cpy(char *dst, const char *src);
R_API int r_str_bits (char *strout, const ut8 *buf, int len, const char *bitz);
R_API int r_str_rwx(const char *str);
R_API void r_str_replace_char (char *s, int a, int b);
R_API int r_str_replace_char (char *s, int a, int b);
R_API const char *r_str_rwx_i(int rwx);
R_API void r_str_writef(int fd, const char *fmt, ...);
R_API char **r_str_argv(const char *str, int *_argc);

View File

@ -69,12 +69,14 @@ main () {
}
#endif
R_API void r_str_replace_char (char *s, int a, int b) {
R_API int r_str_replace_char (char *s, int a, int b) {
int ret = 0;
char *o = s;
for (; *o; s++, o++) {
if (*o==a) {
if (b) {
*s = b;
ret++;
continue;
}
o++;
@ -82,6 +84,7 @@ R_API void r_str_replace_char (char *s, int a, int b) {
*s = *o;
}
*s = 0;
return ret;
}
// TODO: do not use toupper.. must support modes to also append lowercase chars like in r1