More improvements to the support for the i386 architecture
This commit is contained in:
parent
fd677cfe52
commit
79f5ba0237
@ -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)
|
||||
|
39
src/arch.c
39
src/arch.c
@ -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)
|
||||
|
@ -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
|
||||
|
||||
|
@ -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 },
|
||||
|
@ -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)
|
||||
|
31
src/code.c
31
src/code.c
@ -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);
|
||||
|
@ -7,4 +7,8 @@
|
||||
aas
|
||||
adc $0x42, %al
|
||||
adc $0x42, %eax
|
||||
adc [%eax], $0x42
|
||||
adc [%ecx], $0x42
|
||||
adc [%eax], $0x42434445
|
||||
adc [%ecx], $0x42434445
|
||||
nop
|
||||
|
Loading…
Reference in New Issue
Block a user