diff options
Diffstat (limited to 'opcodes/i386-dis.c')
-rw-r--r-- | opcodes/i386-dis.c | 71 |
1 files changed, 61 insertions, 10 deletions
diff --git a/opcodes/i386-dis.c b/opcodes/i386-dis.c index 9fd62f231b..511355ead0 100644 --- a/opcodes/i386-dis.c +++ b/opcodes/i386-dis.c @@ -50,6 +50,7 @@ static void oappend (const char *); static void append_seg (void); static void OP_indirE (int, int); static void print_operand_value (char *, int, bfd_vma); +static void print_displacement (char *, bfd_vma); static void OP_E (int, int); static void OP_G (int, int); static bfd_vma get64 (void); @@ -4629,6 +4630,50 @@ print_operand_value (char *buf, int hex, bfd_vma disp) } } +/* Put DISP in BUF as signed hex number. */ + +static void +print_displacement (char *buf, bfd_vma disp) +{ + bfd_signed_vma val = disp; + char tmp[30]; + int i, j = 0; + + if (val < 0) + { + buf[j++] = '-'; + val = -disp; + + /* Check for possible overflow. */ + if (val < 0) + { + switch (address_mode) + { + case mode_64bit: + strcpy (buf + j, "0x8000000000000000"); + break; + case mode_32bit: + strcpy (buf + j, "0x80000000"); + break; + case mode_16bit: + strcpy (buf + j, "0x8000"); + break; + } + return; + } + } + + buf[j++] = '0'; + buf[j++] = 'x'; + + sprintf_vma (tmp, val); + for (i = 0; tmp[i] == '0'; i++) + continue; + if (tmp[i] == '\0') + i--; + strcpy (buf + j, tmp + i); +} + static void intel_operand_size (int bytemode, int sizeflag) { @@ -4779,8 +4824,10 @@ OP_E (int bytemode, int sizeflag) intel_operand_size (bytemode, sizeflag); append_seg (); - if ((sizeflag & AFLAG) || address_mode == mode_64bit) /* 32 bit address mode */ + if ((sizeflag & AFLAG) || address_mode == mode_64bit) { + /* 32/64 bit address mode */ + int havedisp; int havesib; int havebase; int base; @@ -4829,10 +4876,15 @@ OP_E (int bytemode, int sizeflag) break; } + havedisp = havebase || (havesib && (index != 4 || scale != 0)); + if (!intel_syntax) if (modrm.mod != 0 || (base & 7) == 5) { - print_operand_value (scratchbuf, !riprel, disp); + if (havedisp || riprel) + print_displacement (scratchbuf, disp); + else + print_operand_value (scratchbuf, 1, disp); oappend (scratchbuf); if (riprel) { @@ -4841,9 +4893,7 @@ OP_E (int bytemode, int sizeflag) } } - if (havebase - || (intel_syntax && riprel) - || (havesib && (index != 4 || scale != 0))) + if (havedisp || (intel_syntax && riprel)) { *obufp++ = open_char; if (intel_syntax && riprel) @@ -4890,7 +4940,7 @@ OP_E (int bytemode, int sizeflag) disp = - (bfd_signed_vma) disp; } - print_operand_value (scratchbuf, modrm.mod != 1, disp); + print_displacement (scratchbuf, disp); oappend (scratchbuf); } @@ -4942,7 +4992,7 @@ OP_E (int bytemode, int sizeflag) if (!intel_syntax) if (modrm.mod != 0 || modrm.rm == 6) { - print_operand_value (scratchbuf, 0, disp); + print_displacement (scratchbuf, disp); oappend (scratchbuf); } @@ -4951,9 +5001,10 @@ OP_E (int bytemode, int sizeflag) *obufp++ = open_char; *obufp = '\0'; oappend (index16[modrm.rm]); - if (intel_syntax && disp) + if (intel_syntax + && (disp || modrm.mod != 0 || modrm.rm == 6)) { - if ((bfd_signed_vma) disp > 0) + if ((bfd_signed_vma) disp >= 0) { *obufp++ = '+'; *obufp = '\0'; @@ -4965,7 +5016,7 @@ OP_E (int bytemode, int sizeflag) disp = - (bfd_signed_vma) disp; } - print_operand_value (scratchbuf, modrm.mod != 1, disp); + print_displacement (scratchbuf, disp); oappend (scratchbuf); } |