summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorUlrich Drepper <drepper@redhat.com>2008-01-14 19:17:36 +0000
committerUlrich Drepper <drepper@redhat.com>2008-01-14 19:17:36 +0000
commit35f2fe6ed13dc314ccecdfe5cc5a155044019e18 (patch)
tree5539acd9f5cbb4011621b5a0743ed53e28eb0c54
parent947634833d2623225716a135134727bc446d04d1 (diff)
Fix a couple of x86-64 disassembler cases.
-rw-r--r--config/ChangeLog4
-rw-r--r--config/elfutils.spec.in1
-rw-r--r--libcpu/ChangeLog13
-rw-r--r--libcpu/defs/i38620
-rw-r--r--libcpu/i386_data.h73
-rw-r--r--libcpu/i386_disasm.c11
-rw-r--r--libcpu/i386_parse.y17
-rw-r--r--tests/ChangeLog5
-rw-r--r--tests/testfile45.S.bz2bin22745 -> 22739 bytes
-rw-r--r--tests/testfile45.expect.bz2bin75010 -> 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
index 55e0c2d3..2d44ed8f 100644
--- a/tests/testfile45.S.bz2
+++ b/tests/testfile45.S.bz2
Binary files differ
diff --git a/tests/testfile45.expect.bz2 b/tests/testfile45.expect.bz2
index adce5e0e..f571afd1 100644
--- a/tests/testfile45.expect.bz2
+++ b/tests/testfile45.expect.bz2
Binary files differ