More improvements to the support for the i386 architecture

This commit is contained in:
Pierre Pronchery 2011-04-13 16:08:51 +00:00
parent fd677cfe52
commit 79f5ba0237
7 changed files with 92 additions and 15 deletions

View File

@ -65,6 +65,7 @@ typedef uint32_t ArchOperand;
# define AOF_IMPLICIT 0x1 /* for registers */ # 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
# define AOF_OFFSETSIZE 0x4 /* for registers */
/* macros */ /* macros */
# define AO_GET_FLAGS(operand) ((operand & AOM_FLAGS) >> AOD_FLAGS) # define AO_GET_FLAGS(operand) ((operand & AOM_FLAGS) >> AOD_FLAGS)

View File

@ -165,6 +165,7 @@ 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(Arch * arch, ArchInstruction * ai, static int _operands_operands(Arch * arch, ArchInstruction * ai,
AsOperand ** operands, size_t operands_cnt); AsOperand ** operands, size_t operands_cnt);
static int _operands_operands_immediate(uint32_t operand, AsOperand * aso);
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)
@ -212,6 +213,19 @@ static int _operands_operands(Arch * arch, ArchInstruction * ai,
return -1; return -1;
switch(AO_GET_TYPE(operand)) switch(AO_GET_TYPE(operand))
{ {
case AOT_IMMEDIATE:
if(_operands_operands_immediate(operand,
operands[i]) != 0)
return -1;
break;
case AOT_DREGISTER:
/* check if it exists */
ar = arch_get_register_by_name(arch,
operands[i]->value);
if(ar == NULL)
return -1;
/* FIXME implement the rest */
break;
case AOT_REGISTER: case AOT_REGISTER:
/* check if it exists */ /* check if it exists */
ar = arch_get_register_by_name(arch, ar = arch_get_register_by_name(arch,
@ -228,11 +242,34 @@ static int _operands_operands(Arch * arch, ArchInstruction * ai,
} }
break; break;
} }
/* FIXME check AOF_SIGNED */
} }
return 0; return 0;
} }
static int _operands_operands_immediate(uint32_t operand, AsOperand * aso)
{
unsigned long value;
long lvalue;
unsigned long max;
/* check if the size fits */
if(AO_GET_FLAGS(operand) & AOF_SIGNED)
{
lvalue = *(unsigned long*)aso->value;
value = (lvalue >= 0) ? lvalue : -lvalue;
}
else
value = *(unsigned long*)aso->value;
/* apply negative offset */
if(AO_GET_FLAGS(operand) & AOF_SOFFSET)
value >>= AO_GET_OFFSET(operand);
max = 1;
max <<= AO_GET_SIZE(operand) + 1;
if(value > max - 1)
return -1;
return 0;
}
/* arch_get_name */ /* arch_get_name */
char const * arch_get_name(Arch * arch) char const * arch_get_name(Arch * arch)

View File

@ -27,6 +27,7 @@
enum enum
{ {
#include "i386.reg" #include "i386.reg"
REG_size_count
}; };
#undef REG #undef REG
@ -35,6 +36,7 @@ enum
enum enum
{ {
#include "i386.reg" #include "i386.reg"
REG_id_count
}; };
#undef REG #undef REG

View File

@ -14,6 +14,8 @@
/* helpers */ /* helpers */
#define OP1F (1 << AOD_SIZE) #define OP1F (1 << AOD_SIZE)
#define OP2F (2 << AOD_SIZE) #define OP2F (2 << AOD_SIZE)
#define OP_RM8 AO_DREGISTER(AOF_OFFSETSIZE, 8, 8)
#define OP_RMW AO_DREGISTER(AOF_OFFSETSIZE, 8, W)
#define OP_U8 AO_IMMEDIATE(0, 0, 8) #define OP_U8 AO_IMMEDIATE(0, 0, 8)
#define OP_UW AO_IMMEDIATE(0, 0, W) #define OP_UW AO_IMMEDIATE(0, 0, W)
@ -23,6 +25,8 @@
{ "aam", 0xd40a, OP2F, AOT_NONE, AOT_NONE, AOT_NONE }, { "aam", 0xd40a, OP2F, AOT_NONE, AOT_NONE, AOT_NONE },
{ "aam", 0xd4, OP1F, OP_U8, AOT_NONE, AOT_NONE }, { "aam", 0xd4, OP1F, OP_U8, AOT_NONE, AOT_NONE },
{ "aas", 0x3f, OP1F, AOT_NONE, AOT_NONE, AOT_NONE }, { "aas", 0x3f, OP1F, AOT_NONE, AOT_NONE, AOT_NONE },
{ "adc", 0x80, OP1F, OP_RM8, OP_U8, AOT_NONE },
{ "adc", 0x81, OP1F, OP_RMW, OP_UW, AOT_NONE },
{ "adc", 0x14, OP1F, OP_U8, OP_al, AOT_NONE }, { "adc", 0x14, OP1F, OP_U8, OP_al, AOT_NONE },
{ "adc", 0x15, OP1F, OP_UW, OP_AX, 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,15 +1,15 @@
REG(ah, 8, 0x00) REG(al, 8, 0x00)
REG(al, 8, 0x01) REG(cl, 8, 0x01)
REG(bh, 8, 0x02) REG(dl, 8, 0x02)
REG(bl, 8, 0x03) REG(bl, 8, 0x03)
REG(ch, 8, 0x04) REG(ah, 8, 0x04)
REG(cl, 8, 0x05) REG(bh, 8, 0x05)
REG(dh, 8, 0x06) REG(ch, 8, 0x06)
REG(dl, 8, 0x07) REG(dh, 8, 0x07)
REG(ax, 16, 0x00) REG(ax, 16, 0x00)
REG(bx, 16, 0x01) REG(cx, 16, 0x01)
REG(cx, 16, 0x02) REG(dx, 16, 0x02)
REG(dx, 16, 0x03) REG(bx, 16, 0x03)
REG(sp, 16, 0x04) REG(sp, 16, 0x04)
REG(bp, 16, 0x05) REG(bp, 16, 0x05)
REG(si, 16, 0x06) REG(si, 16, 0x06)
@ -22,9 +22,9 @@ REG(fs, 16, 0x0c)
REG(gs, 16, 0x0d) REG(gs, 16, 0x0d)
#ifndef ARCH_i386_real #ifndef ARCH_i386_real
REG(eax,32, 0x00) REG(eax,32, 0x00)
REG(ebx,32, 0x01) REG(ecx,32, 0x01)
REG(ecx,32, 0x02) REG(edx,32, 0x02)
REG(edx,32, 0x03) REG(ebx,32, 0x03)
REG(esi,32, 0x04) REG(esi,32, 0x04)
REG(edi,32, 0x05) REG(edi,32, 0x05)
REG(esp,32, 0x06) REG(esp,32, 0x06)

View File

@ -185,6 +185,8 @@ static int _instruction_fixed_register(Code * code, ArchOperand operand,
AsOperand * aso, uint32_t * pu); AsOperand * aso, uint32_t * pu);
static int _instruction_variable(Code * code, ArchInstruction * ai, static int _instruction_variable(Code * code, ArchInstruction * ai,
AsOperand ** operands, size_t operands_cnt); AsOperand ** operands, size_t operands_cnt);
static int _instruction_variable_dregister(Code * code, ArchOperand operand,
char const * name);
static int _instruction_variable_immediate(Code * code, ArchOperand operand, static int _instruction_variable_immediate(Code * code, ArchOperand operand,
void * value); void * value);
static int _instruction_variable_opcode(Code * code, ArchInstruction * ai); static int _instruction_variable_opcode(Code * code, ArchInstruction * ai);
@ -316,6 +318,30 @@ static int _instruction_variable(Code * code, ArchInstruction * ai,
return 0; return 0;
} }
static int _instruction_variable_dregister(Code * code, ArchOperand operand,
char const * name)
{
ArchRegister * ar;
uint32_t value;
uint32_t offset;
#ifdef DEBUG
fprintf(stderr, "DEBUG: %s(\"%s\")\n", __func__, name);
#endif
if((ar = arch_get_register_by_name(code->arch, name)) == NULL)
return -1;
value = ar->id;
if(AO_GET_FLAGS(operand) & AOF_OFFSETSIZE)
{
offset = AO_GET_OFFSET(operand);
operand &= ~(AOM_OFFSET | AOM_SIZE);
operand |= (offset << AOD_SIZE);
}
else
value <<= AO_GET_OFFSET(operand);
return _instruction_variable_immediate(code, operand, &value);
}
static int _instruction_variable_immediate(Code * code, ArchOperand operand, static int _instruction_variable_immediate(Code * code, ArchOperand operand,
void * value) void * value)
{ {
@ -329,7 +355,7 @@ static int _instruction_variable_immediate(Code * code, ArchOperand operand,
fprintf(stderr, "DEBUG: %s()\n", __func__); fprintf(stderr, "DEBUG: %s()\n", __func__);
#endif #endif
if((size = AO_GET_SIZE(operand)) == 0) if((size = AO_GET_SIZE(operand)) == 0)
return -error_set_code("%s", "Empty immediate value"); return -error_set_code(1, "%s", "Empty immediate value");
else if(size <= 8) else if(size <= 8)
{ {
u8 = *(uint8_t*)value; u8 = *(uint8_t*)value;
@ -378,6 +404,9 @@ 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_DREGISTER:
return _instruction_variable_dregister(code, operand,
aso->value);
case AOT_REGISTER: case AOT_REGISTER:
return _instruction_variable_register(code, operand, return _instruction_variable_register(code, operand,
aso->value); aso->value);

View File

@ -7,4 +7,8 @@
aas aas
adc $0x42, %al adc $0x42, %al
adc $0x42, %eax adc $0x42, %eax
adc [%eax], $0x42
adc [%ecx], $0x42
adc [%eax], $0x42434445
adc [%ecx], $0x42434445
nop nop