radare2/shlr/rar/cpu.c

147 lines
3.1 KiB
C

/* RAR-VM assembler/disassembler by pancake for radare with love */
/* this implementation is licensed under LGPLv3 - 2012 */
#include <stdio.h>
#include <string.h>
// XXX little endian only?
/* helpers */
#define eprintf(x,...) fprintf(stderr,x,##__VA_ARGS__)
#define SKIPSPACES(x) if (x) while (*x==' '||*x=='\t') x++
static const char *skipspaces(const char *x) { SKIPSPACES(x); return x; }
//static const char *regs = "r0\x00r1\x00r2\x00r3\x00r4\x00r5\x00r6\x00r7";
//static const char *getregi(int n) { return (n>=0&&n<=7)? regs+(3*n): "r?"; }
static int getreg(const char *s) {
if (s[0]=='r' && s[2]=='\0') {
int n = s[1]-'0';
if (n<8) return n;
}
return -1;
}
// ugly global vars
typedef struct {
int bits;
unsigned char *out;
} Bitbuf;
//static void clrbit(Bitbuf *bb) { memset (bb->out, 0, 1+(bb->bits/8)); }
static int bitget(Bitbuf *bb, int bit) {
if (bit>=bb->bits) return -1;
return (bb->out[bit/8] & (1<<((bit%8))))? 1: 0;
}
static void bitadd(Bitbuf *bb, unsigned int v, int n) {
int i, b, bit;
for (i=0; i<n; i++, bb->bits++) {
b = (bb->bits+i)/8;
bit = (bb->bits+i)%8;
//printf ("[%d].%d = %d\n", b, bit, v& (1<<(n-i-1)));
if (!bit) bb->out[b] = 0;
//printf ("BIT (%d)\n", n-i-1);
//if (v&(1<<(n-i-1))) bb->out[b] |= 1<<bit;
if (v&(1<<(n-i-1))) bb->out[b] |= 1<<bit;
// printf ("%d", oz);
}
//printf ("\n");
}
#define T_BYTE (1<<2)
#define T_JUMP (1<<3)
#define T_PROC (1<<4)
#define NOPS 53
static struct {
const char *name;
int flags;
} opcodes [NOPS] = {
{ "mov", 3|T_BYTE },
{ "cmp", 3|T_BYTE },
{ "add", 3|T_BYTE },
{ "sub", 1|T_BYTE },
{ "jz", 1|T_JUMP },
{ "jnz", 1|T_JUMP },
{ "inc", 1|T_BYTE },
{ "dec", 1|T_BYTE },
{ "jmp", 1|T_JUMP },
{ "xor", 3|T_BYTE },
{ "and", 3|T_BYTE },
{ "or", 3|T_BYTE },
{ "test", 3|T_BYTE },
{ "js", 1|T_JUMP },
{ "jb", 1|T_JUMP },
{ "jbe", 1|T_JUMP },
{ "ja", 1|T_JUMP },
{ "jae", 1|T_JUMP },
{ "push", 1 },
{ "pop", 1 },
{ "call", 1|T_PROC },
{ "ret", T_PROC },
{ "not", 1|T_BYTE },
{ "shl", 3|T_BYTE },
{ "shr", 3|T_BYTE },
{ "sar", 3|T_BYTE },
{ "neg", 1|T_BYTE },
{ "pusha",0 },
{ "popa", 0 },
{ "pushf",0 },
{ "popf", 0 },
{ "movzx",3 },
{ "movsx",3 },
{ "xchg", 3|T_BYTE },
{ "mul", 3|T_BYTE },
{ "div", 3|T_BYTE },
{ "adc", 3|T_BYTE },
{ "sbb", 3|T_BYTE },
{ "print",0 },
{ "movb", 0 },
{ "movd", 0 },
{ "cmpb", 0 },
{ "cmpd", 0 },
{ "addb", 0 },
{ "addd", 0 },
{ "subb", 0 },
{ "subd", 0 },
{ "incb", 0 },
{ "incd", 0 },
{ "decb", 0 },
{ "decd", 0 },
{ "negb", 0 },
{ "negd", 0 },
};
#if 0
static int bitnum (Bitbuf *bb, int n, int c) {
int i, ret = 0;
if (n<bb->bits)
for (i=0; i<c; i++)
if (bitget (bb, n+i)>0)
ret |= (1<<i);
return ret;
}
#else
static int bitnum (Bitbuf *bb, int n, int c) {
int i, ret = 0;
if (n<bb->bits)
for (i=0; i<c; i++)
if (bitget (bb, n+i)>0)
ret |= (1<<(c-i-1));
return ret;
}
#endif
static inline const char *opcode_str (int n) {
if (n>=0 && n<NOPS)
return opcodes[n].name;
return NULL;
}
static inline int opcode_num (const char *s) {
int i;
for (i=0; opcodes[i].name; i++)
if (!strcmp (s, opcodes[i].name))
return i;
return -1;
}