About to let each architecture plug-in output instructions itself
This commit is contained in:
parent
9e6b2bb0e9
commit
77f32dfab2
@ -40,11 +40,11 @@ typedef struct _ArchDescription
|
|||||||
/* operands */
|
/* operands */
|
||||||
typedef uint32_t ArchOperand;
|
typedef uint32_t ArchOperand;
|
||||||
# define AOT_NONE 0x0
|
# define AOT_NONE 0x0
|
||||||
# define AOT_CONSTANT 0x1 /* flags | offset | size | value */
|
# define AOT_CONSTANT 0x1 /* flags | 0 | size | value */
|
||||||
# define AOT_IMMEDIATE 0x2 /* flags | offset | 0 | size */
|
# define AOT_IMMEDIATE 0x2 /* flags | offset | 0 | size */
|
||||||
# define AOT_REGISTER 0x3 /* flags | offset | size | id */
|
# define AOT_REGISTER 0x3 /* flags | 0 | size | id */
|
||||||
# define AOT_DREGISTER 0x4 /* flags | offset | dsize | id */
|
# define AOT_DREGISTER 0x4 /* flags | dsize | rsize | id */
|
||||||
# define AOT_DREGISTER2 0x5 /* flags | offset | did | id */
|
# define AOT_DREGISTER2 0x5 /* flags | did | rsize | id */
|
||||||
|
|
||||||
/* displacement */
|
/* displacement */
|
||||||
# define AOD_FLAGS 24
|
# define AOD_FLAGS 24
|
||||||
@ -71,21 +71,34 @@ typedef uint32_t ArchOperand;
|
|||||||
/* macros */
|
/* macros */
|
||||||
# define AO_GET_FLAGS(operand) ((operand & AOM_FLAGS) >> AOD_FLAGS)
|
# define AO_GET_FLAGS(operand) ((operand & AOM_FLAGS) >> AOD_FLAGS)
|
||||||
# define AO_GET_OFFSET(operand) ((operand & AOM_OFFSET) >> AOD_OFFSET)
|
# define AO_GET_OFFSET(operand) ((operand & AOM_OFFSET) >> AOD_OFFSET)
|
||||||
|
# define AO_GET_DSIZE(operand) ((operand & AOM_OFFSET) >> AOD_OFFSET)
|
||||||
|
# define AO_GET_RSIZE(operand) ((operand & AOM_SIZE) >> AOD_SIZE)
|
||||||
# define AO_GET_SIZE(operand) ((operand & AOM_SIZE) >> AOD_SIZE)
|
# define AO_GET_SIZE(operand) ((operand & AOM_SIZE) >> AOD_SIZE)
|
||||||
# define AO_GET_TYPE(operand) ((operand & AOM_TYPE) >> AOD_TYPE)
|
# define AO_GET_TYPE(operand) ((operand & AOM_TYPE) >> AOD_TYPE)
|
||||||
# define AO_GET_VALUE(operand) ((operand & AOM_VALUE) >> AOD_VALUE)
|
# define AO_GET_VALUE(operand) ((operand & AOM_VALUE) >> AOD_VALUE)
|
||||||
|
|
||||||
# define AO_IMMEDIATE(flags, offset, size) ((AOT_IMMEDIATE << AOD_TYPE) \
|
# define AO_IMMEDIATE(flags, offset, size) \
|
||||||
| ((flags) << AOD_FLAGS) | ((offset) << AOD_OFFSET) \
|
((AOT_IMMEDIATE << AOD_TYPE) \
|
||||||
|
| ((flags) << AOD_FLAGS) \
|
||||||
|
| ((offset) << AOD_OFFSET) \
|
||||||
| ((size) << AOD_SIZE))
|
| ((size) << AOD_SIZE))
|
||||||
# define AO_REGISTER(flags, offset, size, id) ((AOT_REGISTER << AOD_TYPE) \
|
# define AO_REGISTER(flags, size, id) \
|
||||||
| ((flags) << AOD_FLAGS) | ((offset) << AOD_OFFSET) \
|
((AOT_REGISTER << AOD_TYPE) \
|
||||||
| ((size) << AOD_SIZE) | ((id) << AOD_VALUE))
|
| ((flags) << AOD_FLAGS) \
|
||||||
# define AO_DREGISTER(flags, offset, dsize) ((AOT_DREGISTER << AOD_TYPE) \
|
| ((size) << AOD_SIZE) \
|
||||||
| (flags << AOD_FLAGS) | (offset << AOD_OFFSET) \
|
| ((id) << AOD_VALUE))
|
||||||
| (dsize << AOD_SIZE))
|
# define AO_DREGISTER(flags, dsize, rsize, id) \
|
||||||
# define AO_DREGISTER2(flags, offset) ((AOT_DREGISTER2 << AOD_TYPE) \
|
((AOT_DREGISTER << AOD_TYPE) \
|
||||||
| (flags << AOD_FLAGS) | (offset << AOD_OFFSET))
|
| ((flags) << AOD_FLAGS) \
|
||||||
|
| ((dsize) << AOD_OFFSET) \
|
||||||
|
| ((rsize) << AOD_SIZE) \
|
||||||
|
| ((id) << AOD_VALUE))
|
||||||
|
# define AO_DREGISTER2(flags, did, dsize, id) \
|
||||||
|
((AOT_DREGISTER2 << AOD_TYPE) \
|
||||||
|
| ((flags) << AOD_FLAGS) \
|
||||||
|
| ((did) << AOD_OFFSET) \
|
||||||
|
| ((dsize) << AOD_SIZE) \
|
||||||
|
| ((id) << AOD_VALUE))
|
||||||
|
|
||||||
typedef struct _ArchInstruction
|
typedef struct _ArchInstruction
|
||||||
{
|
{
|
||||||
@ -114,7 +127,7 @@ struct _ArchPlugin
|
|||||||
ArchRegister * registers;
|
ArchRegister * registers;
|
||||||
ArchInstruction * instructions;
|
ArchInstruction * instructions;
|
||||||
int (*filter)(ArchPlugin * arch, ArchInstruction * instruction,
|
int (*filter)(ArchPlugin * arch, ArchInstruction * instruction,
|
||||||
unsigned char * buf, size_t size);
|
ArchOperand operand, unsigned char * buf, size_t size);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* !DEVEL_ASM_ARCH_H */
|
#endif /* !DEVEL_ASM_ARCH_H */
|
||||||
|
62
src/arch.c
62
src/arch.c
@ -165,6 +165,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(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_dregister(Arch * arch, uint32_t operand,
|
||||||
|
AsOperand * aso);
|
||||||
static int _operands_operands_immediate(uint32_t operand, AsOperand * aso);
|
static int _operands_operands_immediate(uint32_t operand, AsOperand * aso);
|
||||||
static int _operands_operands_register(Arch * arch, uint32_t operand,
|
static int _operands_operands_register(Arch * arch, uint32_t operand,
|
||||||
AsOperand * aso);
|
AsOperand * aso);
|
||||||
@ -220,6 +222,10 @@ static int _operands_operands(Arch * arch, ArchInstruction * ai,
|
|||||||
return -1;
|
return -1;
|
||||||
break;
|
break;
|
||||||
case AOT_DREGISTER:
|
case AOT_DREGISTER:
|
||||||
|
if(_operands_operands_dregister(arch, operand,
|
||||||
|
operands[i]) != 0)
|
||||||
|
return -1;
|
||||||
|
break;
|
||||||
case AOT_REGISTER:
|
case AOT_REGISTER:
|
||||||
if(_operands_operands_register(arch, operand,
|
if(_operands_operands_register(arch, operand,
|
||||||
operands[i]) != 0)
|
operands[i]) != 0)
|
||||||
@ -230,6 +236,29 @@ static int _operands_operands(Arch * arch, ArchInstruction * ai,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int _operands_operands_dregister(Arch * arch, uint32_t operand,
|
||||||
|
AsOperand * aso)
|
||||||
|
{
|
||||||
|
unsigned long dereference;
|
||||||
|
unsigned long max;
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
fprintf(stderr, "DEBUG: %s() %ld\n", __func__, aso->dereference);
|
||||||
|
#endif
|
||||||
|
if(_operands_operands_register(arch, operand, aso) != 0)
|
||||||
|
return -1;
|
||||||
|
if(aso->dereference == 0)
|
||||||
|
return 0;
|
||||||
|
dereference = (aso->dereference > 0) ? aso->dereference
|
||||||
|
: -aso->dereference;
|
||||||
|
/* check if the size fits */
|
||||||
|
max = 1;
|
||||||
|
max <<= AO_GET_DSIZE(operand);
|
||||||
|
if(dereference > max - 1)
|
||||||
|
return -1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int _operands_operands_immediate(uint32_t operand, AsOperand * aso)
|
static int _operands_operands_immediate(uint32_t operand, AsOperand * aso)
|
||||||
{
|
{
|
||||||
unsigned long value;
|
unsigned long value;
|
||||||
@ -248,7 +277,7 @@ static int _operands_operands_immediate(uint32_t operand, AsOperand * aso)
|
|||||||
if(AO_GET_FLAGS(operand) & AOF_SOFFSET)
|
if(AO_GET_FLAGS(operand) & AOF_SOFFSET)
|
||||||
value >>= AO_GET_OFFSET(operand);
|
value >>= AO_GET_OFFSET(operand);
|
||||||
max = 1;
|
max = 1;
|
||||||
max <<= AO_GET_SIZE(operand) + 1;
|
max <<= AO_GET_SIZE(operand);
|
||||||
if(value > max - 1)
|
if(value > max - 1)
|
||||||
return -1;
|
return -1;
|
||||||
return 0;
|
return 0;
|
||||||
@ -257,24 +286,24 @@ static int _operands_operands_immediate(uint32_t operand, AsOperand * aso)
|
|||||||
static int _operands_operands_register(Arch * arch, uint32_t operand,
|
static int _operands_operands_register(Arch * arch, uint32_t operand,
|
||||||
AsOperand * aso)
|
AsOperand * aso)
|
||||||
{
|
{
|
||||||
ArchRegister * ar;
|
|
||||||
ArchDescription * desc;
|
ArchDescription * desc;
|
||||||
|
uint32_t size;
|
||||||
|
ArchRegister * ar;
|
||||||
|
|
||||||
|
/* obtain the size */
|
||||||
|
if((desc = arch->plugin->description) != NULL
|
||||||
|
&& desc->instruction_size != 0)
|
||||||
|
size = desc->instruction_size;
|
||||||
|
else
|
||||||
|
size = AO_GET_SIZE(operand);
|
||||||
/* check if it exists */
|
/* check if it exists */
|
||||||
ar = arch_get_register_by_name(arch, aso->value);
|
if((ar = arch_get_register_by_name_size(arch, aso->value, size))
|
||||||
if(ar == NULL)
|
== NULL)
|
||||||
return -1;
|
|
||||||
/* check the size only for variable-length opcode encoding */
|
|
||||||
desc = arch->plugin->description;
|
|
||||||
if((desc == NULL || desc->instruction_size == 0)
|
|
||||||
&& AO_GET_SIZE(operand) != ar->size)
|
|
||||||
return -1;
|
return -1;
|
||||||
/* for implicit instructions it must match */
|
/* for implicit instructions it must match */
|
||||||
if(AO_GET_FLAGS(operand) & AOF_IMPLICIT)
|
if(AO_GET_FLAGS(operand) & AOF_IMPLICIT
|
||||||
{
|
&& AO_GET_VALUE(operand) != ar->id)
|
||||||
if(AO_GET_VALUE(operand) != ar->id)
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -342,8 +371,8 @@ ArchRegister * arch_get_register_by_name_size(Arch * arch, char const * name,
|
|||||||
|
|
||||||
/* useful */
|
/* useful */
|
||||||
/* arch_filter */
|
/* arch_filter */
|
||||||
int arch_filter(Arch * arch, ArchInstruction * instruction, unsigned char * buf,
|
int arch_filter(Arch * arch, ArchInstruction * instruction, ArchOperand operand,
|
||||||
size_t size)
|
unsigned char * buf, size_t size)
|
||||||
{
|
{
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
fprintf(stderr, "DEBUG: %s(\"%s\")\n", __func__, instruction->name);
|
fprintf(stderr, "DEBUG: %s(\"%s\")\n", __func__, instruction->name);
|
||||||
@ -351,5 +380,6 @@ int arch_filter(Arch * arch, ArchInstruction * instruction, unsigned char * buf,
|
|||||||
if(arch->plugin->filter == NULL)
|
if(arch->plugin->filter == NULL)
|
||||||
return -error_set_code(1, "%s: %s", arch->plugin->name,
|
return -error_set_code(1, "%s: %s", arch->plugin->name,
|
||||||
"Instruction filter required but not defined");
|
"Instruction filter required but not defined");
|
||||||
return arch->plugin->filter(arch->plugin, instruction, buf, size);
|
return arch->plugin->filter(arch->plugin, instruction, operand, buf,
|
||||||
|
size);
|
||||||
}
|
}
|
||||||
|
@ -53,7 +53,7 @@ ArchRegister * arch_get_register_by_name_size(Arch * arch, char const * name,
|
|||||||
uint32_t size);
|
uint32_t size);
|
||||||
|
|
||||||
/* useful */
|
/* useful */
|
||||||
int arch_filter(Arch * arch, ArchInstruction * ai, unsigned char * buf,
|
int arch_filter(Arch * arch, ArchInstruction * ai, ArchOperand operand,
|
||||||
size_t size);
|
unsigned char * buf, size_t size);
|
||||||
|
|
||||||
#endif /* !ASM_ARCH_H */
|
#endif /* !ASM_ARCH_H */
|
||||||
|
@ -63,7 +63,7 @@ static ArchInstruction _i386_instructions[] =
|
|||||||
|
|
||||||
/* prototypes */
|
/* prototypes */
|
||||||
static int _i386_filter(ArchPlugin * plugin, ArchInstruction * instruction,
|
static int _i386_filter(ArchPlugin * plugin, ArchInstruction * instruction,
|
||||||
unsigned char * buf, size_t size);
|
ArchOperand operand, unsigned char * buf, size_t size);
|
||||||
|
|
||||||
|
|
||||||
/* public */
|
/* public */
|
||||||
@ -83,12 +83,20 @@ ArchPlugin arch_plugin =
|
|||||||
|
|
||||||
/* functions */
|
/* functions */
|
||||||
static int _i386_filter(ArchPlugin * plugin, ArchInstruction * instruction,
|
static int _i386_filter(ArchPlugin * plugin, ArchInstruction * instruction,
|
||||||
unsigned char * buf, size_t size)
|
ArchOperand operand, unsigned char * buf, size_t size)
|
||||||
{
|
{
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
fprintf(stderr, "DEBUG: %s() 0x%x\n", __func__, buf[0]);
|
fprintf(stderr, "DEBUG: %s(\"%s\", 0x%08x) buf[0]=0x%02x\n", __func__,
|
||||||
|
instruction->name, operand, buf[0]);
|
||||||
#endif
|
#endif
|
||||||
/* the filter function is only set for mod r/m bytes at the moment */
|
/* the filter function is only set for mod r/m bytes at the moment */
|
||||||
|
if(AO_GET_TYPE(operand) == AOT_REGISTER)
|
||||||
buf[0] |= 0xc0;
|
buf[0] |= 0xc0;
|
||||||
|
else if(AO_GET_TYPE(operand) == AOT_DREGISTER
|
||||||
|
&& AO_GET_DSIZE(operand) == W)
|
||||||
|
buf[0] |= 0x80;
|
||||||
|
else if(AO_GET_TYPE(operand) == AOT_DREGISTER
|
||||||
|
&& AO_GET_DSIZE(operand) == 8)
|
||||||
|
buf[0] |= 0x40;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -1,23 +1,29 @@
|
|||||||
/* platform-specific */
|
/* platform-specific */
|
||||||
#if defined(ARCH_amd64)
|
#if defined(ARCH_i386_real) /* i386 in real mode */
|
||||||
# define W 32
|
|
||||||
#elif defined(ARCH_i386_real)
|
|
||||||
# define W 16
|
# define W 16
|
||||||
#else /* i386 and compatible */
|
# define REG_AX_id REG_ax_id
|
||||||
|
#else /* i386 and compatible in 32-bit protected mode */
|
||||||
# define W 32
|
# define W 32
|
||||||
|
# define REG_AX_id REG_eax_id
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* registers */
|
/* registers */
|
||||||
#define OP_al AO_REGISTER(AOF_IMPLICIT, 0, REG_al_size, REG_al_id)
|
#define OP_al AO_REGISTER(AOF_IMPLICIT, REG_al_size, REG_al_id)
|
||||||
#define OP_AX AO_REGISTER(AOF_IMPLICIT, 0, W, REG_ax_id)
|
#define OP_AX AO_REGISTER(AOF_IMPLICIT, W, REG_AX_id)
|
||||||
|
|
||||||
/* helpers */
|
/* helpers */
|
||||||
#define OP1F (8 << AOD_SIZE)
|
#define OP1F (8 << AOD_SIZE)
|
||||||
#define OP2F (16 << AOD_SIZE)
|
#define OP2F (16 << AOD_SIZE)
|
||||||
#define OP_RM8_D AO_DREGISTER(AOF_SOFFSET, 8, 8)
|
/* mod r/m byte */
|
||||||
#define OP_RM8_R AO_REGISTER(AOF_SOFFSET | AOF_FILTER, 8, 8, 0)
|
#define OP_RM8_D0 AO_DREGISTER(0, 0, 8, 0)
|
||||||
#define OP_RMW_D AO_DREGISTER(AOF_SOFFSET, 8, W)
|
#define OP_RM8_D8 AO_DREGISTER(0, 8, 8, 0)
|
||||||
#define OP_RMW_R AO_REGISTER(AOF_SOFFSET | AOF_FILTER, 8, W, 0)
|
#define OP_RM8_DW AO_DREGISTER(0, W, 8, 0)
|
||||||
|
#define OP_RM8_RW AO_REGISTER(0, 8, 0)
|
||||||
|
#define OP_RMW_D0 AO_DREGISTER(0, 0, W, 0)
|
||||||
|
#define OP_RMW_D8 AO_DREGISTER(0, 8, W, 0)
|
||||||
|
#define OP_RMW_DW AO_DREGISTER(0, W, W, 0)
|
||||||
|
#define OP_RMW_RW AO_REGISTER(0, W, 0)
|
||||||
|
/* immediate values */
|
||||||
#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)
|
||||||
|
|
||||||
@ -29,8 +35,12 @@
|
|||||||
{ "aas", 0x3f, OP1F, AOT_NONE, AOT_NONE, AOT_NONE },
|
{ "aas", 0x3f, OP1F, AOT_NONE, AOT_NONE, AOT_NONE },
|
||||||
{ "adc", 0x14, OP1F, OP_al, OP_U8, AOT_NONE },
|
{ "adc", 0x14, OP1F, OP_al, OP_U8, AOT_NONE },
|
||||||
{ "adc", 0x15, OP1F, OP_AX, OP_UW, AOT_NONE },
|
{ "adc", 0x15, OP1F, OP_AX, OP_UW, AOT_NONE },
|
||||||
{ "adc", 0x80, OP1F, OP_RM8_D, OP_U8, AOT_NONE },
|
{ "adc", 0x80, OP1F, OP_RM8_D0,OP_U8, AOT_NONE },
|
||||||
{ "adc", 0x80, OP1F, OP_RM8_R, OP_U8, AOT_NONE },
|
{ "adc", 0x80, OP1F, OP_RM8_D8,OP_U8, AOT_NONE },
|
||||||
{ "adc", 0x81, OP1F, OP_RMW_D, OP_UW, AOT_NONE },
|
{ "adc", 0x80, OP1F, OP_RM8_DW,OP_U8, AOT_NONE },
|
||||||
{ "adc", 0x81, OP1F, OP_RMW_R, OP_UW, AOT_NONE },
|
{ "adc", 0x80, OP1F, OP_RM8_RW,OP_U8, AOT_NONE },
|
||||||
|
{ "adc", 0x81, OP1F, OP_RMW_D0,OP_UW, AOT_NONE },
|
||||||
|
{ "adc", 0x81, OP1F, OP_RMW_D8,OP_UW, AOT_NONE },
|
||||||
|
{ "adc", 0x81, OP1F, OP_RMW_DW,OP_UW, AOT_NONE },
|
||||||
|
{ "adc", 0x81, OP1F, OP_RMW_RW,OP_UW, AOT_NONE },
|
||||||
{ "nop", 0x90, OP1F, AOT_NONE, AOT_NONE, AOT_NONE },
|
{ "nop", 0x90, OP1F, AOT_NONE, AOT_NONE, AOT_NONE },
|
||||||
|
@ -3,9 +3,9 @@ REG(cl, 8, 0x01)
|
|||||||
REG(dl, 8, 0x02)
|
REG(dl, 8, 0x02)
|
||||||
REG(bl, 8, 0x03)
|
REG(bl, 8, 0x03)
|
||||||
REG(ah, 8, 0x04)
|
REG(ah, 8, 0x04)
|
||||||
REG(bh, 8, 0x05)
|
REG(ch, 8, 0x05)
|
||||||
REG(ch, 8, 0x06)
|
REG(dh, 8, 0x06)
|
||||||
REG(dh, 8, 0x07)
|
REG(bh, 8, 0x07)
|
||||||
REG(ax, 16, 0x00)
|
REG(ax, 16, 0x00)
|
||||||
REG(cx, 16, 0x01)
|
REG(cx, 16, 0x01)
|
||||||
REG(dx, 16, 0x02)
|
REG(dx, 16, 0x02)
|
||||||
|
@ -39,11 +39,6 @@ static ArchInstruction _sparc_instructions[] =
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/* prototypes */
|
|
||||||
/* plug-in */
|
|
||||||
static int _sparc_filter(ArchPlugin * arch, ArchInstruction * instruction);
|
|
||||||
|
|
||||||
|
|
||||||
/* protected */
|
/* protected */
|
||||||
/* variables */
|
/* variables */
|
||||||
ArchPlugin arch_plugin =
|
ArchPlugin arch_plugin =
|
||||||
@ -53,15 +48,5 @@ ArchPlugin arch_plugin =
|
|||||||
&_sparc_description,
|
&_sparc_description,
|
||||||
_sparc_registers,
|
_sparc_registers,
|
||||||
_sparc_instructions,
|
_sparc_instructions,
|
||||||
_sparc_filter
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/* private */
|
|
||||||
/* functions */
|
|
||||||
/* sparc_filter */
|
|
||||||
static int _sparc_filter(ArchPlugin * arch, ArchInstruction * instruction)
|
|
||||||
{
|
|
||||||
/* FIXME implement */
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/* $Id$ */
|
/* $Id$ */
|
||||||
/* generic */
|
/* generic */
|
||||||
/* registers */
|
/* registers */
|
||||||
#define OP_RD AO_REGISTER(0, 25, 5, 0)
|
#define OP_RD AO_REGISTER(0, 32, 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, 0)
|
#define OPIA_RS1 AO_REGISTER(0, 32, 0)
|
||||||
#define OPIA_RS2 AO_REGISTER(0, 0, 5, 0)
|
#define OPIA_RS2 AO_REGISTER(0, 32, 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)
|
||||||
@ -81,8 +81,9 @@
|
|||||||
#define OPLS1F (4 << AOD_SIZE)
|
#define OPLS1F (4 << AOD_SIZE)
|
||||||
#define OPLS2F (4 << AOD_SIZE)
|
#define OPLS2F (4 << AOD_SIZE)
|
||||||
/* registers */
|
/* registers */
|
||||||
#define OPLS_RS1 AO_DREGISTER(0, 14, 5)
|
#define OPLS_RS1 AO_DREGISTER(0, 12, 32, 0)
|
||||||
#define OPLS_RS12 AO_DREGISTER2(AOF_FILTER, 0)
|
#define OPLS_RS1D AO_DREGISTER(0, 0, 32, 0)
|
||||||
|
#define OPLS_RS12 AO_DREGISTER2(0, 32, 32, 0)
|
||||||
/* helpers */
|
/* helpers */
|
||||||
#define OPLS1(opcode) (0xc0000000 | (opcode << 19))
|
#define OPLS1(opcode) (0xc0000000 | (opcode << 19))
|
||||||
#define OPLS2(opcode) (0xc0000000 | (opcode << 19) | (0x1 << 13))
|
#define OPLS2(opcode) (0xc0000000 | (opcode << 19) | (0x1 << 13))
|
||||||
@ -94,7 +95,7 @@
|
|||||||
#define OPSHF (4 << AOD_SIZE)
|
#define OPSHF (4 << AOD_SIZE)
|
||||||
/* helpers */
|
/* helpers */
|
||||||
#define OPSH(opcode) (opcode << 22)
|
#define OPSH(opcode) (opcode << 22)
|
||||||
#define OPSH_U21 AO_IMMEDIATE(AOF_SOFFSET, 10, 21)
|
#define OPSH_U21 AO_IMMEDIATE(AOF_SOFFSET, 10, 22)
|
||||||
|
|
||||||
|
|
||||||
/* instructions */
|
/* instructions */
|
||||||
@ -131,7 +132,7 @@
|
|||||||
{ "ldsb", OPLS1(ldsb), OPLS1F, OPLS_RS12,OP_RD, AOT_NONE },
|
{ "ldsb", OPLS1(ldsb), OPLS1F, OPLS_RS12,OP_RD, AOT_NONE },
|
||||||
{ "ldsh", OPLS1(ldsh), OPLS1F, OPLS_RS1, OP_RD, AOT_NONE },
|
{ "ldsh", OPLS1(ldsh), OPLS1F, OPLS_RS1, OP_RD, AOT_NONE },
|
||||||
{ "ldsh", OPLS1(ldsh), OPLS1F, OPLS_RS12,OP_RD, AOT_NONE },
|
{ "ldsh", OPLS1(ldsh), OPLS1F, OPLS_RS12,OP_RD, AOT_NONE },
|
||||||
{ "ldub", OPLS1(ldub), OPLS1F, OPLS_RS1, OP_RD, AOT_NONE },
|
{ "ldub", OPLS1(ldub), OPLS1F, OPLS_RS1D, OP_RD, AOT_NONE },
|
||||||
{ "ldub", OPLS1(ldub), OPLS1F, OPLS_RS12,OP_RD, AOT_NONE },
|
{ "ldub", OPLS1(ldub), OPLS1F, OPLS_RS12,OP_RD, AOT_NONE },
|
||||||
{ "lduh", OPLS1(lduh), OPLS1F, OPLS_RS1, OP_RD, AOT_NONE },
|
{ "lduh", OPLS1(lduh), OPLS1F, OPLS_RS1, OP_RD, AOT_NONE },
|
||||||
{ "lduh", OPLS1(lduh), OPLS1F, OPLS_RS12,OP_RD, AOT_NONE },
|
{ "lduh", OPLS1(lduh), OPLS1F, OPLS_RS12,OP_RD, AOT_NONE },
|
||||||
|
77
src/code.c
77
src/code.c
@ -43,8 +43,8 @@ struct _Code
|
|||||||
|
|
||||||
|
|
||||||
/* prototypes */
|
/* prototypes */
|
||||||
static int _code_filter(Code * code, ArchInstruction * ai, unsigned char * buf,
|
static int _code_filter(Code * code, ArchInstruction * ai, ArchOperand operand,
|
||||||
size_t size);
|
unsigned char * buf, size_t size);
|
||||||
|
|
||||||
|
|
||||||
/* functions */
|
/* functions */
|
||||||
@ -191,14 +191,14 @@ static int _instruction_fixed_register(Code * code, ArchOperand operand,
|
|||||||
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, ArchInstruction * ai,
|
static int _instruction_variable_dregister(Code * code, ArchInstruction * ai,
|
||||||
ArchOperand operand, char const * name);
|
ArchOperand operand, AsOperand * aso);
|
||||||
static int _instruction_variable_immediate(Code * code, ArchInstruction * ai,
|
static int _instruction_variable_immediate(Code * code, ArchInstruction * ai,
|
||||||
ArchOperand operand, void * value, int swap);
|
ArchOperand operand, void * value, int swap);
|
||||||
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, ArchInstruction * ai,
|
static int _instruction_variable_register(Code * code, ArchInstruction * ai,
|
||||||
ArchOperand operand, char const * name);
|
ArchOperand operand, AsOperand * aso);
|
||||||
|
|
||||||
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)
|
||||||
@ -324,30 +324,25 @@ static int _instruction_variable(Code * code, ArchInstruction * ai,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int _instruction_variable_dregister(Code * code, ArchInstruction * ai,
|
static int _instruction_variable_dregister(Code * code, ArchInstruction * ai,
|
||||||
ArchOperand operand, char const * name)
|
ArchOperand operand, AsOperand * aso)
|
||||||
{
|
{
|
||||||
ArchRegister * ar;
|
|
||||||
uint32_t value;
|
uint32_t value;
|
||||||
uint32_t size;
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
fprintf(stderr, "DEBUG: %s(0x%08x, \"%s\")\n", __func__, operand, name);
|
fprintf(stderr, "DEBUG: %s(0x%08x, \"%s\")\n", __func__, operand, name);
|
||||||
#endif
|
#endif
|
||||||
if(AO_GET_FLAGS(operand) & AOF_IMPLICIT)
|
if(_instruction_variable_register(code, ai, operand, aso) != 0)
|
||||||
return 0;
|
|
||||||
if((ar = arch_get_register_by_name_size(code->arch, name, AO_GET_SIZE(
|
|
||||||
operand))) == NULL)
|
|
||||||
return -1;
|
return -1;
|
||||||
value = ar->id;
|
/* write de-referencing value if expected */
|
||||||
if(AO_GET_FLAGS(operand) & AOF_SOFFSET)
|
if(AO_GET_DSIZE(operand) > 0)
|
||||||
{
|
{
|
||||||
size = AO_GET_OFFSET(operand);
|
value = aso->dereference;
|
||||||
operand &= ~(AOM_OFFSET | AOM_SIZE);
|
operand = AO_IMMEDIATE(0, 0, AO_GET_DSIZE(operand));
|
||||||
operand |= (size << AOD_SIZE);
|
if(_instruction_variable_immediate(code, ai, operand, &value,
|
||||||
|
0) != 0)
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
else
|
return 0;
|
||||||
value <<= AO_GET_OFFSET(operand);
|
|
||||||
return _instruction_variable_immediate(code, ai, operand, &value, 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _instruction_variable_immediate(Code * code, ArchInstruction * ai,
|
static int _instruction_variable_immediate(Code * code, ArchInstruction * ai,
|
||||||
@ -360,7 +355,8 @@ static int _instruction_variable_immediate(Code * code, ArchInstruction * ai,
|
|||||||
uint32_t u32;
|
uint32_t u32;
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
fprintf(stderr, "DEBUG: %s(%d)\n", __func__, swap);
|
fprintf(stderr, "DEBUG: %s(%d) size=%u\n", __func__, swap,
|
||||||
|
AO_GET_SIZE(operand));
|
||||||
#endif
|
#endif
|
||||||
if((size = AO_GET_SIZE(operand)) == 0)
|
if((size = AO_GET_SIZE(operand)) == 0)
|
||||||
return -error_set_code(1, "%s", "Empty immediate value");
|
return -error_set_code(1, "%s", "Empty immediate value");
|
||||||
@ -399,7 +395,7 @@ static int _instruction_variable_immediate(Code * code, ArchInstruction * ai,
|
|||||||
else
|
else
|
||||||
return -error_set_code(1, "%u: Size not implemented", size);
|
return -error_set_code(1, "%u: Size not implemented", size);
|
||||||
if(AO_GET_FLAGS(operand) & AOF_FILTER)
|
if(AO_GET_FLAGS(operand) & AOF_FILTER)
|
||||||
_code_filter(code, ai, buf, size);
|
_code_filter(code, ai, operand, buf, size);
|
||||||
if(fwrite(buf, size, 1, code->fp) != 1)
|
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));
|
||||||
@ -429,10 +425,10 @@ static int _instruction_variable_operand(Code * code, ArchInstruction * ai,
|
|||||||
operand, aso->value, 0);
|
operand, aso->value, 0);
|
||||||
case AOT_DREGISTER:
|
case AOT_DREGISTER:
|
||||||
return _instruction_variable_dregister(code, ai,
|
return _instruction_variable_dregister(code, ai,
|
||||||
operand, aso->value);
|
operand, aso);
|
||||||
case AOT_REGISTER:
|
case AOT_REGISTER:
|
||||||
return _instruction_variable_register(code, ai, operand,
|
return _instruction_variable_register(code, ai, operand,
|
||||||
aso->value);
|
aso);
|
||||||
default:
|
default:
|
||||||
/* FIXME implement */
|
/* FIXME implement */
|
||||||
return -error_set_code(1, "%s", strerror(ENOSYS));
|
return -error_set_code(1, "%s", strerror(ENOSYS));
|
||||||
@ -441,12 +437,35 @@ static int _instruction_variable_operand(Code * code, ArchInstruction * ai,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int _instruction_variable_register(Code * code, ArchInstruction * ai,
|
static int _instruction_variable_register(Code * code, ArchInstruction * ai,
|
||||||
ArchOperand operand, char const * name)
|
ArchOperand operand, AsOperand * aso)
|
||||||
{
|
{
|
||||||
|
char const * name = aso->value;
|
||||||
|
ArchRegister * ar;
|
||||||
|
uint32_t value;
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
fprintf(stderr, "DEBUG: %s(\"%s\")\n", __func__, name);
|
fprintf(stderr, "DEBUG: %s(0x%08x, \"%s\")\n", __func__, operand, name);
|
||||||
#endif
|
#endif
|
||||||
return _instruction_variable_dregister(code, ai, operand, name);
|
if(AO_GET_FLAGS(operand) & AOF_IMPLICIT)
|
||||||
|
return 0;
|
||||||
|
if((ar = arch_get_register_by_name_size(code->arch, name, AO_GET_SIZE(
|
||||||
|
operand))) == NULL)
|
||||||
|
return -1;
|
||||||
|
value = ar->id;
|
||||||
|
#if 0
|
||||||
|
if(AO_GET_FLAGS(operand) & AOF_SOFFSET)
|
||||||
|
{
|
||||||
|
size = AO_GET_OFFSET(operand);
|
||||||
|
operand &= ~(AOM_OFFSET | AOM_SIZE);
|
||||||
|
operand |= (size << AOD_SIZE);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
value <<= AO_GET_OFFSET(operand);
|
||||||
|
#else
|
||||||
|
operand &= ~(AOM_SIZE);
|
||||||
|
operand |= (8 << AOD_SIZE);
|
||||||
|
#endif
|
||||||
|
return _instruction_variable_immediate(code, ai, operand, &value, 0);
|
||||||
}
|
}
|
||||||
#if 0
|
#if 0
|
||||||
ArchRegister * ar;
|
ArchRegister * ar;
|
||||||
@ -662,8 +681,8 @@ int code_section(Code * code, char const * section)
|
|||||||
/* private */
|
/* private */
|
||||||
/* functions */
|
/* functions */
|
||||||
/* plug-in */
|
/* plug-in */
|
||||||
static int _code_filter(Code * code, ArchInstruction * ai, unsigned char * buf,
|
static int _code_filter(Code * code, ArchInstruction * ai, ArchOperand operand,
|
||||||
size_t size)
|
unsigned char * buf, size_t size)
|
||||||
{
|
{
|
||||||
return arch_filter(code->arch, ai, buf, size);
|
return arch_filter(code->arch, ai, operand, buf, size);
|
||||||
}
|
}
|
||||||
|
15
src/parser.c
15
src/parser.c
@ -512,6 +512,7 @@ static int _operand(State * state)
|
|||||||
state->operands = p;
|
state->operands = p;
|
||||||
p = &state->operands[state->operands_cnt];
|
p = &state->operands[state->operands_cnt];
|
||||||
(*p)->operand = 0;
|
(*p)->operand = 0;
|
||||||
|
(*p)->dereference = 0;
|
||||||
(*p)->value = NULL;
|
(*p)->value = NULL;
|
||||||
(*p)->value2 = NULL;
|
(*p)->value2 = NULL;
|
||||||
switch(token_get_code(state->token))
|
switch(token_get_code(state->token))
|
||||||
@ -552,10 +553,10 @@ static int _operand(State * state)
|
|||||||
case AS_CODE_REGISTER:
|
case AS_CODE_REGISTER:
|
||||||
if(code == AS_CODE_OPERATOR_LBRACKET)
|
if(code == AS_CODE_OPERATOR_LBRACKET)
|
||||||
(*p)->operand = AO_DREGISTER(0,
|
(*p)->operand = AO_DREGISTER(0,
|
||||||
0, 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;
|
||||||
@ -580,11 +581,19 @@ static int _operand(State * state)
|
|||||||
ret |= _space(state);
|
ret |= _space(state);
|
||||||
/* FIXME register or immediate value */
|
/* FIXME register or immediate value */
|
||||||
p = &state->operands[state->operands_cnt - 1]; /* XXX */
|
p = &state->operands[state->operands_cnt - 1]; /* XXX */
|
||||||
|
string = token_get_string(state->token);
|
||||||
switch(token_get_code(state->token))
|
switch(token_get_code(state->token))
|
||||||
{
|
{
|
||||||
|
case AS_CODE_IMMEDIATE:
|
||||||
|
(*p)->operand = AO_DREGISTER(0, 0, 0,
|
||||||
|
0);
|
||||||
|
(*p)->dereference = strtoul(string + 1,
|
||||||
|
NULL, 0);
|
||||||
|
break;
|
||||||
case AS_CODE_REGISTER:
|
case AS_CODE_REGISTER:
|
||||||
/* FIXME check everything... */
|
/* FIXME check everything... */
|
||||||
(*p)->operand = AO_DREGISTER2(0, 0);
|
(*p)->operand = AO_DREGISTER2(0, 0, 0,
|
||||||
|
0);
|
||||||
(*p)->value2 = strdup(string);
|
(*p)->value2 = strdup(string);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,8 @@
|
|||||||
aas
|
aas
|
||||||
adc %al, $0x42
|
adc %al, $0x42
|
||||||
adc %eax, $0x42
|
adc %eax, $0x42
|
||||||
adc [%eax], $0x42
|
adc [%edx], $0x42
|
||||||
|
adc [%ebx + $0x5], $0x42
|
||||||
adc %ecx, $0x42
|
adc %ecx, $0x42
|
||||||
adc [%edx], $0x42434445
|
adc [%edx], $0x42434445
|
||||||
adc %ebx, $0x42434445
|
adc %ebx, $0x42434445
|
||||||
|
Loading…
Reference in New Issue
Block a user