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_SIGNED 0x2 /* for immediate */
# define AOF_SOFFSET 0x3
# define AOF_OFFSETSIZE 0x4 /* for registers */
/* macros */
# 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 */
static int _operands_operands(Arch * arch, ArchInstruction * ai,
AsOperand ** operands, size_t operands_cnt);
static int _operands_operands_immediate(uint32_t operand, AsOperand * aso);
ArchInstruction * arch_get_instruction_by_operands(Arch * arch,
char const * name, AsOperand ** operands, size_t operands_cnt)
@ -212,6 +213,19 @@ static int _operands_operands(Arch * arch, ArchInstruction * ai,
return -1;
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:
/* check if it exists */
ar = arch_get_register_by_name(arch,
@ -228,11 +242,34 @@ static int _operands_operands(Arch * arch, ArchInstruction * ai,
}
break;
}
/* FIXME check AOF_SIGNED */
}
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 */
char const * arch_get_name(Arch * arch)

View File

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

View File

@ -14,6 +14,8 @@
/* helpers */
#define OP1F (1 << 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_UW AO_IMMEDIATE(0, 0, W)
@ -23,6 +25,8 @@
{ "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", 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", 0x15, OP1F, OP_UW, OP_AX, AOT_NONE },
{ "nop", 0x90, OP1F, AOT_NONE, AOT_NONE, AOT_NONE },

View File

@ -1,15 +1,15 @@
REG(ah, 8, 0x00)
REG(al, 8, 0x01)
REG(bh, 8, 0x02)
REG(al, 8, 0x00)
REG(cl, 8, 0x01)
REG(dl, 8, 0x02)
REG(bl, 8, 0x03)
REG(ch, 8, 0x04)
REG(cl, 8, 0x05)
REG(dh, 8, 0x06)
REG(dl, 8, 0x07)
REG(ah, 8, 0x04)
REG(bh, 8, 0x05)
REG(ch, 8, 0x06)
REG(dh, 8, 0x07)
REG(ax, 16, 0x00)
REG(bx, 16, 0x01)
REG(cx, 16, 0x02)
REG(dx, 16, 0x03)
REG(cx, 16, 0x01)
REG(dx, 16, 0x02)
REG(bx, 16, 0x03)
REG(sp, 16, 0x04)
REG(bp, 16, 0x05)
REG(si, 16, 0x06)
@ -22,9 +22,9 @@ REG(fs, 16, 0x0c)
REG(gs, 16, 0x0d)
#ifndef ARCH_i386_real
REG(eax,32, 0x00)
REG(ebx,32, 0x01)
REG(ecx,32, 0x02)
REG(edx,32, 0x03)
REG(ecx,32, 0x01)
REG(edx,32, 0x02)
REG(ebx,32, 0x03)
REG(esi,32, 0x04)
REG(edi,32, 0x05)
REG(esp,32, 0x06)

View File

@ -185,6 +185,8 @@ static int _instruction_fixed_register(Code * code, ArchOperand operand,
AsOperand * aso, uint32_t * pu);
static int _instruction_variable(Code * code, ArchInstruction * ai,
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,
void * value);
static int _instruction_variable_opcode(Code * code, ArchInstruction * ai);
@ -316,6 +318,30 @@ static int _instruction_variable(Code * code, ArchInstruction * ai,
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,
void * value)
{
@ -329,7 +355,7 @@ static int _instruction_variable_immediate(Code * code, ArchOperand operand,
fprintf(stderr, "DEBUG: %s()\n", __func__);
#endif
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)
{
u8 = *(uint8_t*)value;
@ -378,6 +404,9 @@ static int _instruction_variable_operand(Code * code, ArchInstruction * ai,
case AOT_IMMEDIATE:
return _instruction_variable_immediate(code, operand,
aso->value);
case AOT_DREGISTER:
return _instruction_variable_dregister(code, operand,
aso->value);
case AOT_REGISTER:
return _instruction_variable_register(code, operand,
aso->value);

View File

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