diff options
author | Ulrich Drepper <drepper@redhat.com> | 2008-01-14 19:17:36 +0000 |
---|---|---|
committer | Ulrich Drepper <drepper@redhat.com> | 2008-01-14 19:17:36 +0000 |
commit | 35f2fe6ed13dc314ccecdfe5cc5a155044019e18 (patch) | |
tree | 5539acd9f5cbb4011621b5a0743ed53e28eb0c54 | |
parent | 947634833d2623225716a135134727bc446d04d1 (diff) |
Fix a couple of x86-64 disassembler cases.
-rw-r--r-- | config/ChangeLog | 4 | ||||
-rw-r--r-- | config/elfutils.spec.in | 1 | ||||
-rw-r--r-- | libcpu/ChangeLog | 13 | ||||
-rw-r--r-- | libcpu/defs/i386 | 20 | ||||
-rw-r--r-- | libcpu/i386_data.h | 73 | ||||
-rw-r--r-- | libcpu/i386_disasm.c | 11 | ||||
-rw-r--r-- | libcpu/i386_parse.y | 17 | ||||
-rw-r--r-- | tests/ChangeLog | 5 | ||||
-rw-r--r-- | tests/testfile45.S.bz2 | bin | 22745 -> 22739 bytes | |||
-rw-r--r-- | tests/testfile45.expect.bz2 | bin | 75010 -> 75022 bytes |
10 files changed, 127 insertions, 17 deletions
diff --git a/config/ChangeLog b/config/ChangeLog index e580747a..9d754684 100644 --- a/config/ChangeLog +++ b/config/ChangeLog @@ -1,7 +1,3 @@ -2008-01-12 Ulrich Drepper <drepper@redhat.com> - - * elfutils.spec.in: Add m4 to build requirements. - 2008-01-02 Ulrich Drepper <drepper@redhat.com> * elfutils.spec.in: Changes for disasm branch merge. diff --git a/config/elfutils.spec.in b/config/elfutils.spec.in index 380e5c5a..f48c3983 100644 --- a/config/elfutils.spec.in +++ b/config/elfutils.spec.in @@ -18,7 +18,6 @@ BuildRequires: glibc >= 2.7 BuildRequires: bison >= 1.875 BuildRequires: flex >= 2.5.4a BuildRequires: bzip2 -BuildRequires: m4 %define _gnu %{nil} %define _programprefix eu- diff --git a/libcpu/ChangeLog b/libcpu/ChangeLog index e87f7573..598d5194 100644 --- a/libcpu/ChangeLog +++ b/libcpu/ChangeLog @@ -1,3 +1,16 @@ +2008-01-14 Ulrich Drepper <drepper@redhat.com> + + * defs/i386: Add fixes for opcodes with register number in opcode, + 64-bit immediate forms, nop with rex.B. + * i386_data.h [X86_64] (FCT_imm64$w): New function. + (FCT_oreg): New function. + (FCT_oreg$w): New function. + * i386_disasm.c (i386_disasm): Reinitialize fmt always before + starting the loop to process the string. Handle 0x90 special for + x86-64. + * i386_parse.y (fillin_arg): Expand synonyms before concatening to + form the function name. + 2008-01-11 Ulrich Drepper <drepper@redhat.com> * i386_disasm.c (struct output_buffer): Remove symcb and symcbarg. diff --git a/libcpu/defs/i386 b/libcpu/defs/i386 index b545c481..1b4bbb4a 100644 --- a/libcpu/defs/i386 +++ b/libcpu/defs/i386 @@ -9,6 +9,7 @@ dnl floating point reg suffix %mask {imms8} 8 %mask {imm16} 16 %mask {reg} 3 +%mask {oreg} 3 %mask {reg16} 3 %mask {reg64} 3 %mask {tttn} 4 @@ -25,6 +26,7 @@ dnl like {r_m} but referencing 32- or 64-bit register %mask {disp8} 8 dnl imm really is 8/16/32 bit depending on the situation. %mask {imm} 8 +%mask {imm64} 8 %mask {imms} 8 %mask {rel} 32 %mask {abs} 32 @@ -56,6 +58,10 @@ dnl imm really is 8/16/32 bit depending on the situation. %synonym {xmmreg2} {xmmreg} %synonym {mmxreg1} {mmxreg} %synonym {mmxreg2} {mmxreg} +ifdef(`i386', +`%synonym {oreg} {reg} +%synonym {imm64} {imm} +')dnl %% ifdef(`i386', @@ -352,7 +358,9 @@ ifdef(`ASSEMBLER', 1110010{w},{imm8}:in {imm8},{ax}{w} 1110110{w}:in {dx},{ax}{w} 1111111{w},{mod}000{r_m}:inc{w} {mod}{r_m}{w} -01000{reg}:inc {reg} +ifdef(`i386', +`01000{reg}:inc {reg} +')dnl 0110110{w}:{R}ins{w} {dx},{es_di} 11001101,{imm8}:int {imm8} 11001100:int3 @@ -407,7 +415,7 @@ ifdef(`i386', 1000100{w},{mod}{reg}{r_m}:mov {reg}{w},{mod}{r_m}{w} 1000101{w},{mod}{reg}{r_m}:mov {mod}{r_m}{w},{reg}{w} 1100011{w},{mod}000{r_m},{imm}:mov{w} {imm}{w},{mod}{r_m}{w} -1011{w}{reg},{imm}:mov {imm}{w},{reg}{w} +1011{w}{oreg},{imm64}:mov {imm64}{w},{oreg}{w} 1010000{w},{abs}:mov {abs},{ax}{w} 1010001{w},{abs}:mov {ax}{w},{abs} 00001111,00100000,11{ccc}{reg64}:mov {ccc},{reg64} @@ -424,7 +432,11 @@ ifdef(`i386', 1111011{w},{mod}100{r_m}:mul{w} {mod}{r_m}{w} 1111011{w},{mod}011{r_m}:neg{w} {mod}{r_m}{w} 11110011,10010000:pause -10010000:nop +ifdef(`i386', +`10010000:nop +', +`10010000:INVALID +')dnl 1111011{w},{mod}010{r_m}:not{w} {mod}{r_m}{w} 0000100{w},{mod}{reg}{r_m}:or {reg}{w},{mod}{r_m}{w} 0000101{w},{mod}{reg}{r_m}:or {mod}{r_m}{w},{reg}{w} @@ -562,7 +574,7 @@ ifdef(`i386', 00001111,00110000:wrmsr 00001111,1100000{w},{mod}{reg}{r_m}:xadd {reg}{w},{mod}{r_m}{w} 1000011{w},{mod}{reg}{r_m}:xchg {reg}{w},{mod}{r_m}{w} -10010{reg}:xchg {ax},{reg} +10010{oreg}:xchg {ax},{oreg} 11010111:xlat {ds_bx} 0011000{w},{mod}{reg}{r_m}:xor {reg}{w},{mod}{r_m}{w} 0011001{w},{mod}{reg}{r_m}:xor {mod}{r_m}{w},{reg}{w} diff --git a/libcpu/i386_data.h b/libcpu/i386_data.h index 43eb13f9..42e66500 100644 --- a/libcpu/i386_data.h +++ b/libcpu/i386_data.h @@ -736,6 +736,39 @@ FCT_imm$w (struct output_data *d) } +#ifdef X86_64 +static int +FCT_imm64$w (struct output_data *d) +{ + if ((d->data[d->opoff2 / 8] & (1 << (7 - (d->opoff2 & 7)))) == 0 + || (*d->prefixes & has_data16) != 0) + return FCT_imm$w (d); + + size_t *bufcntp = d->bufcntp; + size_t avail = d->bufsize - *bufcntp; + int needed; + if (*d->prefixes & has_rex_w) + { + if (*d->param_start + 8 > d->end) + return -1; + uint64_t word = read_8ubyte_unaligned_inc (*d->param_start); + needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx64, word); + } + else + { + if (*d->param_start + 4 > d->end) + return -1; + int32_t word = read_4sbyte_unaligned_inc (*d->param_start); + needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx32, word); + } + if ((size_t) needed > avail) + return (size_t) needed - avail; + *bufcntp += needed; + return 0; +} +#endif + + static int FCT_imms (struct output_data *d) { @@ -1155,6 +1188,26 @@ FCT_reg (struct output_data *d) } +#ifdef X86_64 +static int +FCT_oreg (struct output_data *d) +{ + /* Special form where register comes from opcode. The rex.B bit is used, + rex.R and rex.X are ignored. */ + int save_prefixes = *d->prefixes; + + *d->prefixes = ((save_prefixes & ~has_rex_r) + | ((save_prefixes & has_rex_b) << (idx_rex_r - idx_rex_b))); + + int r = FCT_reg (d); + + *d->prefixes = save_prefixes; + + return r; +} +#endif + + static int FCT_reg64 (struct output_data *d) { @@ -1226,6 +1279,26 @@ FCT_reg$w (struct output_data *d) } +#ifdef X86_64 +static int +FCT_oreg$w (struct output_data *d) +{ + /* Special form where register comes from opcode. The rex.B bit is used, + rex.R and rex.X are ignored. */ + int save_prefixes = *d->prefixes; + + *d->prefixes = ((save_prefixes & ~has_rex_r) + | ((save_prefixes & has_rex_b) << (idx_rex_r - idx_rex_b))); + + int r = FCT_reg$w (d); + + *d->prefixes = save_prefixes; + + return r; +} +#endif + + static int FCT_freg (struct output_data *d) { diff --git a/libcpu/i386_disasm.c b/libcpu/i386_disasm.c index f8a06cc4..d8bcf9b3 100644 --- a/libcpu/i386_disasm.c +++ b/libcpu/i386_disasm.c @@ -268,8 +268,6 @@ i386_disasm (const uint8_t **startp, const uint8_t *end, GElf_Addr addr, const uint8_t *data = *startp; const uint8_t *begin = data; - fmt = save_fmt; - /* Recognize all prefixes. */ int last_prefix_bit = 0; while (data < end) @@ -512,6 +510,7 @@ i386_disasm (const uint8_t **startp, const uint8_t *end, GElf_Addr addr, output_data.data = data; unsigned long string_end_idx = 0; + fmt = save_fmt; while (*fmt != '\0') { if (*fmt != '%') @@ -581,6 +580,14 @@ i386_disasm (const uint8_t **startp, const uint8_t *end, GElf_Addr addr, { switch (*data) { +#ifdef X86_64 + case 0x90: + if (prefixes & has_rex_b) + goto not; + str = "nop"; + break; +#endif + case 0x98: if (prefixes & ~has_data16) goto print_prefix; diff --git a/libcpu/i386_parse.y b/libcpu/i386_parse.y index 896b11d0..9b2ab33e 100644 --- a/libcpu/i386_parse.y +++ b/libcpu/i386_parse.y @@ -802,7 +802,17 @@ fillin_arg (struct bitvalue *bytes, struct argname *name, /* Add some string which contains invalid characters. */ obstack_grow_str (&ob, "!!!INVALID!!!"); else - obstack_grow_str (&ob, runp->field->name); + { + char *fieldname = runp->field->name; + + struct synonym search = { .from = fieldname }; + + struct synonym **res = tfind (&search, &synonyms, compare_syn); + if (res != NULL) + fieldname = (*res)->to; + + obstack_grow_str (&ob, fieldname); + } /* Now compute the bit offset of the field. */ struct bitvalue *b = bytes; @@ -844,11 +854,6 @@ fillin_arg (struct bitvalue *bytes, struct argname *name, obstack_1grow (&ob, '\0'); char *fct = obstack_finish (&ob); - struct synonym search = { .from = fct }; - struct synonym **res = tfind (&search, &synonyms, compare_syn); - if (res != NULL) - fct = (*res)->to; - instr->operands[n].fct = fct; } diff --git a/tests/ChangeLog b/tests/ChangeLog index 95ed7833..10417266 100644 --- a/tests/ChangeLog +++ b/tests/ChangeLog @@ -1,3 +1,8 @@ +2008-01-14 Ulrich Drepper <drepper@redhat.com> + + * testfile45.S.bz2: Add more tests. + * testfile45.expect.bz2: Adjust. + 2008-01-11 Ulrich Drepper <drepper@redhat.com> * testfile45.expect.bz2: Adjust for adding of address for %rip based diff --git a/tests/testfile45.S.bz2 b/tests/testfile45.S.bz2 Binary files differindex 55e0c2d3..2d44ed8f 100644 --- a/tests/testfile45.S.bz2 +++ b/tests/testfile45.S.bz2 diff --git a/tests/testfile45.expect.bz2 b/tests/testfile45.expect.bz2 Binary files differindex adce5e0e..f571afd1 100644 --- a/tests/testfile45.expect.bz2 +++ b/tests/testfile45.expect.bz2 |