From 09d598f1ffb3117a32fa982c8d2b4341fcf7fc35 Mon Sep 17 00:00:00 2001 From: Pierre Pronchery Date: Wed, 13 Apr 2011 14:43:26 +0000 Subject: [PATCH] Consider all sizes to be in bits instead --- include/Asm/arch.h | 5 ++-- src/arch.c | 36 +++++++++++++++++----- src/arch/i386.c | 19 ++++++++++++ src/arch/i386.ins | 23 ++++++++++++-- src/arch/i386.reg | 74 +++++++++++++++++++++++----------------------- src/arch/sparc.ins | 6 ++-- src/code.c | 71 ++++++++++++++++++++++++++++---------------- src/parser.c | 2 +- test/i386.S | 5 ++++ 9 files changed, 163 insertions(+), 78 deletions(-) diff --git a/include/Asm/arch.h b/include/Asm/arch.h index 8cb7164..c8520c7 100644 --- a/include/Asm/arch.h +++ b/include/Asm/arch.h @@ -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)) diff --git a/src/arch.c b/src/arch.c index bc0c54b..36de4ab 100644 --- a/src/arch.c +++ b/src/arch.c @@ -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]; diff --git a/src/arch/i386.c b/src/arch/i386.c index bc81c69..10920f6 100644 --- a/src/arch/i386.c +++ b/src/arch/i386.c @@ -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[] = { diff --git a/src/arch/i386.ins b/src/arch/i386.ins index 470384a..64c7ccd 100644 --- a/src/arch/i386.ins +++ b/src/arch/i386.ins @@ -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 }, diff --git a/src/arch/i386.reg b/src/arch/i386.reg index d4e078c..171bcb0 100644 --- a/src/arch/i386.reg +++ b/src/arch/i386.reg @@ -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) diff --git a/src/arch/sparc.ins b/src/arch/sparc.ins index 0b2bef7..e86e065 100644 --- a/src/arch/sparc.ins +++ b/src/arch/sparc.ins @@ -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) diff --git a/src/code.c b/src/code.c index 0f30f70..8cacfe1 100644 --- a/src/code.c +++ b/src/code.c @@ -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)) { diff --git a/src/parser.c b/src/parser.c index ed0e327..299be72 100644 --- a/src/parser.c +++ b/src/parser.c @@ -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; diff --git a/test/i386.S b/test/i386.S index 5426c3e..c8457ba 100644 --- a/test/i386.S +++ b/test/i386.S @@ -2,4 +2,9 @@ aaa aad aad $0x42 + aam + aam $0x42 + aas + adc $0x42, %al + adc $0x42, %eax nop