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 */
# define AOF_FILTER 0x1
# define AOF_IMPLICIT 0x1 /* for registers */
# define AOF_SIGNED 0x2 /* for immediate */
# define AOF_SOFFSET 0x3
@ -75,9 +76,9 @@ typedef uint32_t ArchOperand;
# define AO_IMMEDIATE(flags, offset, size) ((AOT_IMMEDIATE << AOD_TYPE) \
| (flags << AOD_FLAGS) | (offset << AOD_OFFSET) \
| (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) \
| (size << AOD_SIZE))
| (size << AOD_SIZE) | (id << AOD_VALUE))
# define AO_DREGISTER(flags, offset, dsize) ((AOT_DREGISTER << AOD_TYPE) \
| (flags << AOD_FLAGS) | (offset << AOD_OFFSET) \
| (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 */
static int _operands_operands(ArchInstruction * ai, AsOperand ** operands,
size_t operands_cnt);
static int _operands_operands(Arch * arch, ArchInstruction * ai,
AsOperand ** operands, size_t operands_cnt);
ArchInstruction * arch_get_instruction_by_operands(Arch * arch,
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)
continue;
found = 1;
if(_operands_operands(ai, operands, operands_cnt) == 0)
if(_operands_operands(arch, ai, operands, operands_cnt) == 0)
return ai;
}
error_set_code(1, "%s \"%s\"", found ? "Invalid arguments to"
@ -191,11 +191,12 @@ ArchInstruction * arch_get_instruction_by_operands(Arch * arch,
return NULL;
}
static int _operands_operands(ArchInstruction * ai, AsOperand ** operands,
size_t operands_cnt)
static int _operands_operands(Arch * arch, ArchInstruction * ai,
AsOperand ** operands, size_t operands_cnt)
{
size_t i;
uint32_t operand;
ArchRegister * ar;
for(i = 0; i < operands_cnt; i++)
{
@ -203,12 +204,30 @@ static int _operands_operands(ArchInstruction * ai, AsOperand ** operands,
return -1;
operand = (i == 0) ? ai->op1 : ((i == 1) ? ai->op2 : ai->op3);
#ifdef DEBUG
fprintf(stderr, "DEBUG: %s() %lu %u, %u\n", __func__, i,
AO_GET_TYPE(operand),
fprintf(stderr, "DEBUG: %s() operand %lu, type %u, type %u\n",
__func__, i, AO_GET_TYPE(operand),
AO_GET_TYPE(operands[i]->operand));
#endif
if(AO_GET_TYPE(operand) != AO_GET_TYPE(operands[i]->operand))
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 */
}
return 0;
@ -248,6 +267,9 @@ ArchRegister * arch_get_register_by_name(Arch * arch, char const * name)
{
size_t i;
#ifdef DEBUG
fprintf(stderr, "DEBUG: %s(\"%s\")\n", __func__, name);
#endif
for(i = 0; i < arch->registers_cnt; i++)
if(strcmp(arch->plugin->registers[i].name, name) == 0)
return &arch->plugin->registers[i];

View File

@ -21,6 +21,24 @@
/* i386 */
/* 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 */
#define REG(name, size, id) { "" # name, size, id },
static ArchRegister _i386_registers[] =
@ -28,6 +46,7 @@ static ArchRegister _i386_registers[] =
#include "i386.reg"
{ NULL, 0, 0 }
};
#undef REG
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 */
#define OP1F (1 << 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 },
{ "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 },
{ "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 },

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

View File

@ -1,7 +1,7 @@
/* $Id$ */
/* generic */
/* registers */
#define OP_RD AO_REGISTER(0, 25, 5)
#define OP_RD AO_REGISTER(0, 25, 5, 0)
/* conditional branching */
/* opcodes */
@ -57,8 +57,8 @@
#define OPIA1F (4 << AOD_SIZE)
#define OPIA2F (4 << AOD_SIZE)
/* registers */
#define OPIA_RS1 AO_REGISTER(0, 14, 5)
#define OPIA_RS2 AO_REGISTER(0, 0, 5)
#define OPIA_RS1 AO_REGISTER(0, 14, 5, 0)
#define OPIA_RS2 AO_REGISTER(0, 0, 5, 0)
/* helpers */
#define OPIA1(opcode) (0x80000000 | opcode << 19)
#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_operand(Code * code, ArchInstruction * ai,
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,
size_t operands_cnt)
@ -326,33 +328,38 @@ static int _instruction_variable_immediate(Code * code, ArchOperand operand,
#ifdef DEBUG
fprintf(stderr, "DEBUG: %s()\n", __func__);
#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:
break;
case sizeof(u8):
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 */
u8 = *(uint8_t*)value;
buf = &u8;
size = 1;
}
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(
errno));
return 0;
@ -371,12 +378,24 @@ static int _instruction_variable_operand(Code * code, ArchInstruction * ai,
case AOT_IMMEDIATE:
return _instruction_variable_immediate(code, operand,
aso->value);
case AOT_REGISTER:
return _instruction_variable_register(code, operand,
aso->value);
default:
/* FIXME implement */
return -1;
return -error_set_code(1, "%s", strerror(ENOSYS));
}
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
switch(AO_GET_SIZE(ai->opcode))
{

View File

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

View File

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