rizin/libr/asm/arch/dcpu16/dis.c
2015-02-10 00:05:18 +01:00

126 lines
2.9 KiB
C

/* copypasted from http://pastie.org/3732465 */
/* adapted by pancake // public license */
/* known bugs: some (%s, NULL) happen */
#include <stdio.h>
#include <stdlib.h>
#include "dcpu16.h"
struct op_code {
ut8 opcode;
};
struct op_basic {
ut8 opcode;
ut8 a_type;
ut8 b_type;
ut16 a;
ut16 b;
};
struct op_nbasic {
ut8 __empty;
ut8 a_type;
ut8 opcode;
ut16 a;
};
typedef union {
struct op_code code;
struct op_basic b;
struct op_nbasic n;
} op;
static const int opCycle[] = {
0, 1, 2, 2, 2, 3, 3, 2, 2, 1, 1, 1, 2, 2, 2, 2
};
static const int opCycleB[] = { 0, 2 };
static const char* opName[] = {
"", "set",
"add", "sub", "mul", "div", "mod",
"shl", "shr", "and", "bor", "xor",
"ife", "ifn", "ifg", "ifb"
};
static const char* opNameB[] = { "reserved", "jsr" };
static const char* regs[] = {
"a", "b", "c", "x", "y", "z", "i", "j",
"pop", "peek", "push", "sp", "pc", "o"
};
static inline int needWord(ut8 type) {
return ((type <= 0x17) && (type > 0x0f)) \
|| (type == 0x1e) || (type == 0x1f);
}
static int valPrint(char *out, ut8 type, ut16 value) {
if (type <= 0x07) return sprintf(out, "%s", regs[type]);
if (type <= 0x0f) return sprintf(out, "[%s]", regs[type - 0x08]);
if (type <= 0x17) return sprintf(out, "[%s + %#hx]", regs[type - 0x10], value);
if (type <= 0x1d) return sprintf(out, "%s", regs[type - 0x18 + 0x08]);
if (type == 0x1e) return sprintf(out, "[%#hx]", value);
if (type == 0x1f) return sprintf(out, "%#hx", value);
return sprintf(out, "%#hx", (short)(type - 0x20));
}
static int instrPrint(char *out, const op* o) {
char arg[32], arg2[32];
if (o->code.opcode == 0) {
valPrint (arg, o->n.a_type, o->n.a);
return sprintf(out, "%s %s",
opNameB[o->n.opcode], arg);
}
valPrint (arg, o->b.a_type, o->b.a);
valPrint (arg2, o->b.b_type, o->b.b);
return sprintf(out, "%s %s, %s", opName[o->b.opcode], arg, arg2);
}
static int instrGet(ut16 in, op* o, ut16 a, ut16 b) {
int ret = 1;
o->code.opcode = in & 0xF;
if (!(o->code.opcode = in & 0xF)) {
/* Non basic op code */
o->n.opcode = (in >> 4) & 0x3F;
o->n.a_type = (in >> 10) & 0x3F;
if (needWord(o->n.a_type)) {
o->n.a = a;
ret++;
}
} else {
o->b.a_type = (in >> 4) & 0x3F;
o->b.b_type = (in >> 10) & 0x3F;
if (needWord(o->b.a_type)) {
o->b.a = a;
ret++;
if (needWord (o->b.b_type)) {
o->b.b = b;
ret++;
}
} else if (needWord(o->b.b_type)) {
o->b.b = a;
ret++;
}
}
return ret;
}
static int instrGetCycles(const op* o) {
if (o->code.opcode == 0)
return opCycleB[o->n.opcode] + needWord(o->n.a_type);
return opCycle[o->b.opcode] + needWord(o->b.a_type)
+ needWord(o->b.b_type);
}
int dcpu16_disasm(char *out, const ut16* inp, int len, int *cost) {
op o = {{0}};
int delta = instrGet (inp[0], &o, inp[1], inp[2]);
if (cost) *cost = instrGetCycles(&o) + ((o.b.opcode >= 0xc)?1:0);
instrPrint (out, &o);
//ind = (o.b.opcode >= 0xC);
return delta<<1;
}