]> git.ipfire.org Git - thirdparty/elfutils.git/commitdiff
Fix a couple of x86-64 disassembler cases.
authorUlrich Drepper <drepper@redhat.com>
Mon, 14 Jan 2008 19:17:36 +0000 (19:17 +0000)
committerUlrich Drepper <drepper@redhat.com>
Mon, 14 Jan 2008 19:17:36 +0000 (19:17 +0000)
config/ChangeLog
config/elfutils.spec.in
libcpu/ChangeLog
libcpu/defs/i386
libcpu/i386_data.h
libcpu/i386_disasm.c
libcpu/i386_parse.y
tests/ChangeLog
tests/testfile45.S.bz2
tests/testfile45.expect.bz2

index e580747a019d63ea7ff949a1232c844069d0b003..9d7546841b18cf383cbd858b07963946fe0cb8f3 100644 (file)
@@ -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.
index 380e5c5af5f505750a7606baa40077461c4355ac..f48c3983d8b5761d251966099d13a22b58b8e69f 100644 (file)
@@ -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-
index e87f75733bfe7a6b029df8e923a3f05af7b0cc44..598d51945dbc019643622b5a23ea75635d8605ae 100644 (file)
@@ -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.
index b545c48160f0594f8339fe1e4ec54f6082af5a26..1b4bbb4a507800f3cfb762a41e7a45a5b0cc2332 100644 (file)
@@ -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}
index 43eb13f957f8933ddaf3eb72e2499a9965e40c90..42e665009569700e673d4ba200d57c45662aa765 100644 (file)
@@ -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)
 {
index f8a06cc49f07e984011dc3035c8afa02e883a23a..d8bcf9b3261d917b4d50ce2b4978575d2cdadb34 100644 (file)
@@ -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;
index 896b11d0a3644795247b56eeaca246a9f221e6b4..9b2ab33e2795df235219e3b24d0fa277aac72ec1 100644 (file)
@@ -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;
 }
 
index 95ed7833765b4a6f5c24858408d31f6a5386bd76..10417266572040599f0f27663858b9af8f0626f2 100644 (file)
@@ -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
index 55e0c2d3067c7719bb6e20cc2a8d828a2a3151a3..2d44ed8f3fc99180d0f9c36e38f2276e82486a9c 100644 (file)
Binary files a/tests/testfile45.S.bz2 and b/tests/testfile45.S.bz2 differ
index adce5e0ede2e601ecd0dc2e2aaccd8bfd4ed24b4..f571afd1d64b63558a819edbe3c8b6a958bcc21c 100644 (file)
Binary files a/tests/testfile45.expect.bz2 and b/tests/testfile45.expect.bz2 differ