Consider all sizes to be in bits instead

This commit is contained in:
Pierre Pronchery 2011-04-13 14:43:26 +00:00
parent 83e77c93bf
commit 09d598f1ff
9 changed files with 163 additions and 78 deletions

View File

@ -62,6 +62,7 @@ typedef uint32_t ArchOperand;
/* flags */ /* flags */
# define AOF_FILTER 0x1 # define AOF_FILTER 0x1
# define AOF_IMPLICIT 0x1 /* for registers */
# define AOF_SIGNED 0x2 /* for immediate */ # define AOF_SIGNED 0x2 /* for immediate */
# define AOF_SOFFSET 0x3 # define AOF_SOFFSET 0x3
@ -75,9 +76,9 @@ typedef uint32_t ArchOperand;
# define AO_IMMEDIATE(flags, offset, size) ((AOT_IMMEDIATE << AOD_TYPE) \ # define AO_IMMEDIATE(flags, offset, size) ((AOT_IMMEDIATE << AOD_TYPE) \
| (flags << AOD_FLAGS) | (offset << AOD_OFFSET) \ | (flags << AOD_FLAGS) | (offset << AOD_OFFSET) \
| (size << AOD_SIZE)) | (size << AOD_SIZE))
# define AO_REGISTER(flags, offset, size) ((AOT_REGISTER << AOD_TYPE) \ # define AO_REGISTER(flags, offset, size, id) ((AOT_REGISTER << AOD_TYPE) \
| (flags << AOD_FLAGS) | (offset << AOD_OFFSET) \ | (flags << AOD_FLAGS) | (offset << AOD_OFFSET) \
| (size << AOD_SIZE)) | (size << AOD_SIZE) | (id << AOD_VALUE))
# define AO_DREGISTER(flags, offset, dsize) ((AOT_DREGISTER << AOD_TYPE) \ # define AO_DREGISTER(flags, offset, dsize) ((AOT_DREGISTER << AOD_TYPE) \
| (flags << AOD_FLAGS) | (offset << AOD_OFFSET) \ | (flags << AOD_FLAGS) | (offset << AOD_OFFSET) \
| (dsize << AOD_SIZE)) | (dsize << AOD_SIZE))

View File

@ -163,8 +163,8 @@ ArchInstruction * arch_get_instruction_by_opcode(Arch * arch, uint8_t size,
/* arch_get_instruction_by_operands */ /* arch_get_instruction_by_operands */
static int _operands_operands(ArchInstruction * ai, AsOperand ** operands, static int _operands_operands(Arch * arch, ArchInstruction * ai,
size_t operands_cnt); AsOperand ** operands, size_t operands_cnt);
ArchInstruction * arch_get_instruction_by_operands(Arch * arch, ArchInstruction * arch_get_instruction_by_operands(Arch * arch,
char const * name, AsOperand ** operands, size_t operands_cnt) char const * name, AsOperand ** operands, size_t operands_cnt)
@ -183,7 +183,7 @@ ArchInstruction * arch_get_instruction_by_operands(Arch * arch,
if(strcmp(ai->name, name) != 0) if(strcmp(ai->name, name) != 0)
continue; continue;
found = 1; found = 1;
if(_operands_operands(ai, operands, operands_cnt) == 0) if(_operands_operands(arch, ai, operands, operands_cnt) == 0)
return ai; return ai;
} }
error_set_code(1, "%s \"%s\"", found ? "Invalid arguments to" error_set_code(1, "%s \"%s\"", found ? "Invalid arguments to"
@ -191,11 +191,12 @@ ArchInstruction * arch_get_instruction_by_operands(Arch * arch,
return NULL; return NULL;
} }
static int _operands_operands(ArchInstruction * ai, AsOperand ** operands, static int _operands_operands(Arch * arch, ArchInstruction * ai,
size_t operands_cnt) AsOperand ** operands, size_t operands_cnt)
{ {
size_t i; size_t i;
uint32_t operand; uint32_t operand;
ArchRegister * ar;
for(i = 0; i < operands_cnt; i++) for(i = 0; i < operands_cnt; i++)
{ {
@ -203,12 +204,30 @@ static int _operands_operands(ArchInstruction * ai, AsOperand ** operands,
return -1; return -1;
operand = (i == 0) ? ai->op1 : ((i == 1) ? ai->op2 : ai->op3); operand = (i == 0) ? ai->op1 : ((i == 1) ? ai->op2 : ai->op3);
#ifdef DEBUG #ifdef DEBUG
fprintf(stderr, "DEBUG: %s() %lu %u, %u\n", __func__, i, fprintf(stderr, "DEBUG: %s() operand %lu, type %u, type %u\n",
AO_GET_TYPE(operand), __func__, i, AO_GET_TYPE(operand),
AO_GET_TYPE(operands[i]->operand)); AO_GET_TYPE(operands[i]->operand));
#endif #endif
if(AO_GET_TYPE(operand) != AO_GET_TYPE(operands[i]->operand)) if(AO_GET_TYPE(operand) != AO_GET_TYPE(operands[i]->operand))
return -1; return -1;
switch(AO_GET_TYPE(operand))
{
case AOT_REGISTER:
/* check if it exists */
ar = arch_get_register_by_name(arch,
operands[i]->value);
if(ar == NULL)
return -1;
/* for implicit instructions it must match */
if(AO_GET_FLAGS(operand) & AOF_IMPLICIT)
{
if(AO_GET_SIZE(operand) != ar->size)
return -1;
if(AO_GET_VALUE(operand) != ar->id)
return -1;
}
break;
}
/* FIXME check AOF_SIGNED */ /* FIXME check AOF_SIGNED */
} }
return 0; return 0;
@ -248,6 +267,9 @@ ArchRegister * arch_get_register_by_name(Arch * arch, char const * name)
{ {
size_t i; size_t i;
#ifdef DEBUG
fprintf(stderr, "DEBUG: %s(\"%s\")\n", __func__, name);
#endif
for(i = 0; i < arch->registers_cnt; i++) for(i = 0; i < arch->registers_cnt; i++)
if(strcmp(arch->plugin->registers[i].name, name) == 0) if(strcmp(arch->plugin->registers[i].name, name) == 0)
return &arch->plugin->registers[i]; return &arch->plugin->registers[i];

View File

@ -21,6 +21,24 @@
/* i386 */ /* i386 */
/* private */ /* private */
/* types */
/* register sizes */
#define REG(name, size, id) REG_ ## name ## _size = size,
enum
{
#include "i386.reg"
};
#undef REG
/* register ids */
#define REG(name, size, id) REG_ ## name ## _id = id,
enum
{
#include "i386.reg"
};
#undef REG
/* variables */ /* variables */
#define REG(name, size, id) { "" # name, size, id }, #define REG(name, size, id) { "" # name, size, id },
static ArchRegister _i386_registers[] = static ArchRegister _i386_registers[] =
@ -28,6 +46,7 @@ static ArchRegister _i386_registers[] =
#include "i386.reg" #include "i386.reg"
{ NULL, 0, 0 } { NULL, 0, 0 }
}; };
#undef REG
static ArchInstruction _i386_instructions[] = static ArchInstruction _i386_instructions[] =
{ {

View File

@ -1,9 +1,28 @@
/* platform-specific */
#if defined(ARCH_amd64)
# define W 32
#elif defined(ARCH_i386_real)
# define W 16
#else /* i386 and compatible */
# define W 32
#endif
/* registers */
#define OP_al AO_REGISTER(AOF_IMPLICIT, 0, REG_al_size, REG_al_id)
#define OP_AX AO_REGISTER(AOF_IMPLICIT, 0, W, REG_ax_id)
/* helpers */ /* helpers */
#define OP1F (1 << AOD_SIZE) #define OP1F (1 << AOD_SIZE)
#define OP2F (2 << AOD_SIZE) #define OP2F (2 << AOD_SIZE)
#define OP_U8 AO_IMMEDIATE(0, 0, 1) #define OP_U8 AO_IMMEDIATE(0, 0, 8)
#define OP_UW AO_IMMEDIATE(0, 0, W)
{ "aaa", 0x37, OP1F, AOT_NONE, AOT_NONE, AOT_NONE }, { "aaa", 0x37, OP1F, AOT_NONE, AOT_NONE, AOT_NONE },
{ "aad", 0xd5a0, OP2F, AOT_NONE, AOT_NONE, AOT_NONE }, { "aad", 0xd50a, OP2F, AOT_NONE, AOT_NONE, AOT_NONE },
{ "aad", 0xd5, OP1F, OP_U8, AOT_NONE, AOT_NONE }, { "aad", 0xd5, OP1F, OP_U8, AOT_NONE, AOT_NONE },
{ "aam", 0xd40a, OP2F, AOT_NONE, AOT_NONE, AOT_NONE },
{ "aam", 0xd4, OP1F, OP_U8, AOT_NONE, AOT_NONE },
{ "aas", 0x3f, OP1F, AOT_NONE, AOT_NONE, AOT_NONE },
{ "adc", 0x14, OP1F, OP_U8, OP_al, AOT_NONE },
{ "adc", 0x15, OP1F, OP_UW, OP_AX, AOT_NONE },
{ "nop", 0x90, OP1F, AOT_NONE, AOT_NONE, AOT_NONE }, { "nop", 0x90, OP1F, AOT_NONE, AOT_NONE, AOT_NONE },

View File

@ -1,40 +1,40 @@
REG(ah, 8, 0x00)
REG(al, 8, 0x01)
REG(bh, 8, 0x02)
REG(bl, 8, 0x03)
REG(ch, 8, 0x04)
REG(cl, 8, 0x05)
REG(dh, 8, 0x06)
REG(dl, 8, 0x07)
REG(ax, 16, 0x00) REG(ax, 16, 0x00)
REG(ah, 8, 0x01) REG(bx, 16, 0x01)
REG(al, 8, 0x02) REG(cx, 16, 0x02)
REG(bx, 16, 0x03) REG(dx, 16, 0x03)
REG(bh, 8, 0x04) REG(sp, 16, 0x04)
REG(bl, 8, 0x05) REG(bp, 16, 0x05)
REG(cx, 16, 0x06) REG(si, 16, 0x06)
REG(ch, 8, 0x07) REG(di, 16, 0x07)
REG(cl, 8, 0x08) REG(cs, 16, 0x08)
REG(dx, 16, 0x09) REG(ss, 16, 0x09)
REG(dh, 8, 0x0a) REG(ds, 16, 0x0a)
REG(dl, 8, 0x0b) REG(es, 16, 0x0b)
REG(sp, 16, 0x0c) REG(fs, 16, 0x0c)
REG(bp, 16, 0x0d) REG(gs, 16, 0x0d)
REG(si, 16, 0x0e)
REG(di, 16, 0x0f)
REG(cs, 16, 0x10)
REG(ss, 16, 0x11)
REG(ds, 16, 0x12)
REG(es, 16, 0x13)
REG(fs, 16, 0x14)
REG(gs, 16, 0x15)
#ifndef ARCH_i386_real #ifndef ARCH_i386_real
REG(eax,32, 0x16) REG(eax,32, 0x00)
REG(ebx,32, 0x17) REG(ebx,32, 0x01)
REG(ecx,32, 0x18) REG(ecx,32, 0x02)
REG(edx,32, 0x19) REG(edx,32, 0x03)
REG(esi,32, 0x1a) REG(esi,32, 0x04)
REG(edi,32, 0x1b) REG(edi,32, 0x05)
REG(esp,32, 0x1c) REG(esp,32, 0x06)
REG(ebp,32, 0x1d) REG(ebp,32, 0x07)
#endif /* !ARCH_i386_real */ #endif /* !ARCH_i386_real */
REG(st0,32, 0x1f) REG(st0,32, 0x08)
REG(st1,32, 0x20) REG(st1,32, 0x09)
REG(st2,32, 0x21) REG(st2,32, 0x0a)
REG(st3,32, 0x22) REG(st3,32, 0x0b)
REG(st4,32, 0x23) REG(st4,32, 0x0c)
REG(st5,32, 0x24) REG(st5,32, 0x0d)
REG(st6,32, 0x25) REG(st6,32, 0x0e)
REG(st7,32, 0x26) REG(st7,32, 0x0f)

View File

@ -1,7 +1,7 @@
/* $Id$ */ /* $Id$ */
/* generic */ /* generic */
/* registers */ /* registers */
#define OP_RD AO_REGISTER(0, 25, 5) #define OP_RD AO_REGISTER(0, 25, 5, 0)
/* conditional branching */ /* conditional branching */
/* opcodes */ /* opcodes */
@ -57,8 +57,8 @@
#define OPIA1F (4 << AOD_SIZE) #define OPIA1F (4 << AOD_SIZE)
#define OPIA2F (4 << AOD_SIZE) #define OPIA2F (4 << AOD_SIZE)
/* registers */ /* registers */
#define OPIA_RS1 AO_REGISTER(0, 14, 5) #define OPIA_RS1 AO_REGISTER(0, 14, 5, 0)
#define OPIA_RS2 AO_REGISTER(0, 0, 5) #define OPIA_RS2 AO_REGISTER(0, 0, 5, 0)
/* helpers */ /* helpers */
#define OPIA1(opcode) (0x80000000 | opcode << 19) #define OPIA1(opcode) (0x80000000 | opcode << 19)
#define OPIA2(opcode) (0x80000000 | opcode << 19 | 0x1 << 13) #define OPIA2(opcode) (0x80000000 | opcode << 19 | 0x1 << 13)

View File

@ -190,6 +190,8 @@ static int _instruction_variable_immediate(Code * code, ArchOperand operand,
static int _instruction_variable_opcode(Code * code, ArchInstruction * ai); static int _instruction_variable_opcode(Code * code, ArchInstruction * ai);
static int _instruction_variable_operand(Code * code, ArchInstruction * ai, static int _instruction_variable_operand(Code * code, ArchInstruction * ai,
ArchOperand operand, AsOperand * aso); ArchOperand operand, AsOperand * aso);
static int _instruction_variable_register(Code * code, ArchOperand operand,
char const * name);
int code_instruction(Code * code, char const * name, AsOperand ** operands, int code_instruction(Code * code, char const * name, AsOperand ** operands,
size_t operands_cnt) size_t operands_cnt)
@ -326,33 +328,38 @@ static int _instruction_variable_immediate(Code * code, ArchOperand operand,
#ifdef DEBUG #ifdef DEBUG
fprintf(stderr, "DEBUG: %s()\n", __func__); fprintf(stderr, "DEBUG: %s()\n", __func__);
#endif #endif
switch((size = AO_GET_SIZE(operand))) if((size = AO_GET_SIZE(operand)) == 0)
return -error_set_code("%s", "Empty immediate value");
else if(size <= 8)
{ {
case 0: u8 = *(uint8_t*)value;
break; buf = &u8;
case sizeof(u8): size = 1;
u8 = *(uint8_t*)value;
buf = &u8;
break;
case sizeof(u16):
u16 = *(uint16_t*)value;
u16 = htons(u16);
buf = &u16;
break;
case 3: /* XXX check */
u32 = *(uint32_t*)value;
u32 = htonl(u32 << 8);
buf = &u32;
break;
case sizeof(u32):
u32 = *(uint32_t*)value;
u32 = htonl(u32);
buf = &u32;
break;
default:
return -1; /* XXX return error */
} }
if(size > 0 && fwrite(buf, size, 1, code->fp) != 1) else if(size <= 16)
{
u16 = *(uint16_t*)value;
u16 = htons(u16);
buf = &u16;
size = 2;
}
else if(size <= 24) /* FIXME merge with 32 */
{
u32 = *(uint32_t*)value;
u32 = htonl(u32 << 8);
buf = &u32;
size = 3;
}
else if(size <= 32)
{
u32 = *(uint32_t*)value;
u32 = htonl(u32);
buf = &u32;
size = 4;
}
else
return -error_set_code(1, "%u: Size not implemented", size);
if(fwrite(buf, size, 1, code->fp) != 1)
return -error_set_code(1, "%s: %s", code->filename, strerror( return -error_set_code(1, "%s: %s", code->filename, strerror(
errno)); errno));
return 0; return 0;
@ -371,12 +378,24 @@ static int _instruction_variable_operand(Code * code, ArchInstruction * ai,
case AOT_IMMEDIATE: case AOT_IMMEDIATE:
return _instruction_variable_immediate(code, operand, return _instruction_variable_immediate(code, operand,
aso->value); aso->value);
case AOT_REGISTER:
return _instruction_variable_register(code, operand,
aso->value);
default: default:
/* FIXME implement */ /* FIXME implement */
return -1; return -error_set_code(1, "%s", strerror(ENOSYS));
} }
return 0; return 0;
} }
static int _instruction_variable_register(Code * code, ArchOperand operand,
char const * name)
{
if(AO_GET_FLAGS(operand) & AOF_IMPLICIT)
return 0;
/* FIXME implement */
return -error_set_code(1, "%s: %s", name, strerror(ENOSYS));
}
#if 0 #if 0
switch(AO_GET_SIZE(ai->opcode)) switch(AO_GET_SIZE(ai->opcode))
{ {

View File

@ -555,7 +555,7 @@ static int _operand(State * state)
0, 0); 0, 0);
else else
(*p)->operand = AO_REGISTER(0, (*p)->operand = AO_REGISTER(0,
0, 0); 0, 0, 0);
/* FIXME check errors */ /* FIXME check errors */
(*p)->value = strdup(string); (*p)->value = strdup(string);
break; break;

View File

@ -2,4 +2,9 @@
aaa aaa
aad aad
aad $0x42 aad $0x42
aam
aam $0x42
aas
adc $0x42, %al
adc $0x42, %eax
nop nop