diff options
author | Jan Beulich <jbeulich@suse.com> | 2020-07-15 08:53:55 +0200 |
---|---|---|
committer | Jan Beulich <jbeulich@suse.com> | 2020-07-15 08:53:55 +0200 |
commit | 36938cabf0efcb053d1585e8580a4b3db438ca4e (patch) | |
tree | e7193f8c5b4f0cc83b6a76a4d5a35f0b86058abd /opcodes | |
parent | a8a48c756c0da3a49008662e14ae582764ddd0bb (diff) | |
download | gdb-36938cabf0efcb053d1585e8580a4b3db438ca4e.zip gdb-36938cabf0efcb053d1585e8580a4b3db438ca4e.tar.gz gdb-36938cabf0efcb053d1585e8580a4b3db438ca4e.tar.bz2 |
x86: avoid attaching suffixes to unambiguous insns
"Unambiguous" is is in particular taking as reference the assembler,
which also accepts certain insns - despite them allowing for varying
operand size, and hence in principle being ambiguous - without any
suffix. For example, from the very beginning of the life of x86-64 I had
trouble understanding why a plain and simple RET had to be printed as
RETQ. In case someone really used the 16-bit form, RETW disambiguates
the two quite fine.
Diffstat (limited to 'opcodes')
-rw-r--r-- | opcodes/ChangeLog | 14 | ||||
-rw-r--r-- | opcodes/i386-dis.c | 143 |
2 files changed, 58 insertions, 99 deletions
diff --git a/opcodes/ChangeLog b/opcodes/ChangeLog index 9a972d4..7fff032 100644 --- a/opcodes/ChangeLog +++ b/opcodes/ChangeLog @@ -1,3 +1,17 @@ +2020-07-15 Jan Beulich <jbeulich@suse.com> + + * i386-dis.c (dis386): Adjust 'P', 'T', 'U', and '@' + description. Drop '&' description. Use P for push of immediate, + pushf/popf, enter, and leave. Use %LP for lret/retf. + (dis386_twobyte): Use P for push/pop of fs/gs. + (reg_table): Use P for push/pop. Use @ for near call/jmp. + (x86_64_table): Use P for far call/jmp. + (putop): Drop handling of 'U' and '&'. Move and adjust handling + of '@'. Adjust handling of 'P' and 'T'. Drop case_P and case_Q + labels. + (OP_J): Drop marking of REX_W as used for v_mode (ISA-dependent) + and dqw_mode (unconditional). + 2020-07-14 H.J. Lu <hongjiu.lu@intel.com> PR gas/26237 diff --git a/opcodes/i386-dis.c b/opcodes/i386-dis.c index 511e632..ef539ca 100644 --- a/opcodes/i386-dis.c +++ b/opcodes/i386-dis.c @@ -1738,16 +1738,15 @@ struct dis386 { 'M' => print 'r' if intel_mnemonic is false. 'N' => print 'n' if instruction has no wait "prefix" 'O' => print 'd' or 'o' (or 'q' in Intel mode) - 'P' => print 'w', 'l' or 'q' if instruction has an operand size prefix, - or suffix_always is true. print 'q' if rex prefix is present. + 'P' => behave as 'T' except with register operand outside of suffix_always + mode 'Q' => print 'w', 'l' or 'q' for memory operand or suffix_always is true 'R' => print 'w', 'l' or 'q' ('d' for 'l' and 'e' in Intel mode) 'S' => print 'w', 'l' or 'q' if suffix_always is true - 'T' => print 'q' in 64bit mode if instruction has no operand size - prefix and behave as 'P' otherwise - 'U' => print 'q' in 64bit mode if instruction has no operand size - prefix and behave as 'Q' otherwise + 'T' => print 'w', 'l'/'d', or 'q' if instruction has an operand size + prefix or if suffix_always is true. + 'U' unused. 'V' => print 'q' in 64bit mode if instruction has no operand size prefix and behave as 'S' otherwise 'W' => print 'b', 'w' or 'l' ('d' in Intel mode) @@ -1758,11 +1757,9 @@ struct dis386 { '%' => add 1 upper case letter to the macro. '^' => print 'w', 'l', or 'q' (Intel64 ISA only) depending on operand size prefix or suffix_always is true (lcall/ljmp). - '@' => print 'q' for Intel64 ISA, 'w' or 'q' for AMD64 ISA depending - on operand size prefix. - '&' => print 'q' in 64bit mode for Intel64 ISA or if instruction - has no operand size prefix for AMD64 ISA, behave as 'P' - otherwise + '@' => in 64bit mode for Intel64 ISA or if instruction + has no operand sizing prefix, print 'q' if suffix_always is true or + nothing otherwise; behave as 'P' in all other cases 2 upper case letter macros: "XY" => print 'x' or 'y' if suffix_always is true or no register @@ -1907,9 +1904,9 @@ static const struct dis386 dis386[] = { { Bad_Opcode }, /* op size prefix */ { Bad_Opcode }, /* adr size prefix */ /* 68 */ - { "pushT", { sIv }, 0 }, + { "pushP", { sIv }, 0 }, { "imulS", { Gv, Ev, Iv }, 0 }, - { "pushT", { sIbT }, 0 }, + { "pushP", { sIbT }, 0 }, { "imulS", { Gv, Ev, sIb }, 0 }, { "ins{b|}", { Ybr, indirDX }, 0 }, { X86_64_TABLE (X86_64_6D) }, @@ -1965,8 +1962,8 @@ static const struct dis386 dis386[] = { { "cR{t|}O", { XX }, 0 }, { X86_64_TABLE (X86_64_9A) }, { Bad_Opcode }, /* fwait */ - { "pushfT", { XX }, 0 }, - { "popfT", { XX }, 0 }, + { "pushfP", { XX }, 0 }, + { "popfP", { XX }, 0 }, { "sahf", { XX }, 0 }, { "lahf", { XX }, 0 }, /* a0 */ @@ -2015,10 +2012,10 @@ static const struct dis386 dis386[] = { { REG_TABLE (REG_C6) }, { REG_TABLE (REG_C7) }, /* c8 */ - { "enterT", { Iw, Ib }, 0 }, - { "leaveT", { XX }, 0 }, - { "{l|}ret{|f}P", { Iw }, 0 }, - { "{l|}ret{|f}P", { XX }, 0 }, + { "enterP", { Iw, Ib }, 0 }, + { "leaveP", { XX }, 0 }, + { "{l|}ret{|f}%LP", { Iw }, 0 }, + { "{l|}ret{|f}%LP", { XX }, 0 }, { "int3", { XX }, 0 }, { "int", { Ib }, 0 }, { X86_64_TABLE (X86_64_CE) }, @@ -2261,8 +2258,8 @@ static const struct dis386 dis386_twobyte[] = { { "setle", { Eb }, 0 }, { "setg", { Eb }, 0 }, /* a0 */ - { "pushT", { fs }, 0 }, - { "popT", { fs }, 0 }, + { "pushP", { fs }, 0 }, + { "popP", { fs }, 0 }, { "cpuid", { XX }, 0 }, { "btS", { Ev, Gv }, 0 }, { "shldS", { Ev, Gv, Ib }, 0 }, @@ -2270,8 +2267,8 @@ static const struct dis386 dis386_twobyte[] = { { REG_TABLE (REG_0FA6) }, { REG_TABLE (REG_0FA7) }, /* a8 */ - { "pushT", { gs }, 0 }, - { "popT", { gs }, 0 }, + { "pushP", { gs }, 0 }, + { "popP", { gs }, 0 }, { "rsm", { XX }, 0 }, { "btsS", { Evh1, Gv }, 0 }, { "shrdS", { Ev, Gv, Ib }, 0 }, @@ -2695,7 +2692,7 @@ static const struct dis386 reg_table[][8] = { }, /* REG_8F */ { - { "popU", { stackEv }, 0 }, + { "pop{P|}", { stackEv }, 0 }, { XOP_8F_TABLE (XOP_09) }, { Bad_Opcode }, { Bad_Opcode }, @@ -2821,11 +2818,11 @@ static const struct dis386 reg_table[][8] = { { { "incQ", { Evh1 }, 0 }, { "decQ", { Evh1 }, 0 }, - { "call{&|}", { NOTRACK, indirEv, BND }, 0 }, + { "call{@|}", { NOTRACK, indirEv, BND }, 0 }, { MOD_TABLE (MOD_FF_REG_3) }, - { "jmp{&|}", { NOTRACK, indirEv, BND }, 0 }, + { "jmp{@|}", { NOTRACK, indirEv, BND }, 0 }, { MOD_TABLE (MOD_FF_REG_5) }, - { "pushU", { stackEv }, 0 }, + { "push{P|}", { stackEv }, 0 }, { Bad_Opcode }, }, /* REG_0F00 */ @@ -4072,7 +4069,7 @@ static const struct dis386 x86_64_table[][2] = { /* X86_64_9A */ { - { "{l|}call{T|}", { Ap }, 0 }, + { "{l|}call{P|}", { Ap }, 0 }, }, /* X86_64_C2 */ @@ -4128,7 +4125,7 @@ static const struct dis386 x86_64_table[][2] = { /* X86_64_EA */ { - { "{l|}jmp{T|}", { Ap }, 0 }, + { "{l|}jmp{P|}", { Ap }, 0 }, }, /* X86_64_0F01_REG_0 */ @@ -10637,56 +10634,33 @@ putop (const char *in_template, int sizeflag) if (!(rex & REX_W)) used_prefixes |= (prefixes & PREFIX_DATA); break; - case '&': - if (!intel_syntax - && address_mode == mode_64bit - && isa64 == intel64) - { - *obufp++ = 'q'; - break; - } - /* Fall through. */ - case 'T': - if (!intel_syntax - && address_mode == mode_64bit - && ((sizeflag & DFLAG) || (rex & REX_W))) + case '@': + if (address_mode == mode_64bit + && (isa64 == intel64 || (rex & REX_W) + || !(prefixes & PREFIX_DATA))) { - *obufp++ = 'q'; + if (sizeflag & SUFFIX_ALWAYS) + *obufp++ = 'q'; break; } /* Fall through. */ - goto case_P; case 'P': if (l == 0) { - case_P: - if (intel_syntax) - { - if ((rex & REX_W) == 0 - && (prefixes & PREFIX_DATA)) - { - if ((sizeflag & DFLAG) == 0) - *obufp++ = 'w'; - used_prefixes |= (prefixes & PREFIX_DATA); - } - break; - } - if ((prefixes & PREFIX_DATA) - || (rex & REX_W) - || (sizeflag & SUFFIX_ALWAYS)) + if (need_modrm && modrm.mod == 3 && !(sizeflag & SUFFIX_ALWAYS)) + break; + /* Fall through. */ + case 'T': + if ((!(rex & REX_W) && (prefixes & PREFIX_DATA)) + || ((sizeflag & SUFFIX_ALWAYS) + && address_mode != mode_64bit)) { - USED_REX (REX_W); - if (rex & REX_W) - *obufp++ = 'q'; - else - { - if (sizeflag & DFLAG) - *obufp++ = 'l'; - else - *obufp++ = 'w'; - used_prefixes |= (prefixes & PREFIX_DATA); - } + *obufp++ = (sizeflag & DFLAG) ? + intel_syntax ? 'd' : 'l' : 'w'; + used_prefixes |= (prefixes & PREFIX_DATA); } + else if (sizeflag & SUFFIX_ALWAYS) + *obufp++ = 'q'; } else if (l == 1 && last[0] == 'L') { @@ -10710,22 +10684,9 @@ putop (const char *in_template, int sizeflag) else abort (); break; - case 'U': - if (intel_syntax) - break; - if (address_mode == mode_64bit - && ((sizeflag & DFLAG) || (rex & REX_W))) - { - if (modrm.mod != 3 || (sizeflag & SUFFIX_ALWAYS)) - *obufp++ = 'q'; - break; - } - /* Fall through. */ - goto case_Q; case 'Q': if (l == 0) { - case_Q: if (intel_syntax && !alt) break; USED_REX (REX_W); @@ -10964,20 +10925,6 @@ putop (const char *in_template, int sizeflag) used_prefixes |= (prefixes & PREFIX_DATA); } break; - case '@': - if (intel_syntax) - break; - if (address_mode == mode_64bit - && (isa64 == intel64 - || ((sizeflag & DFLAG) || (rex & REX_W)))) - *obufp++ = 'q'; - else if ((prefixes & PREFIX_DATA)) - { - if (!(sizeflag & DFLAG)) - *obufp++ = 'w'; - used_prefixes |= (prefixes & PREFIX_DATA); - } - break; } if (len == l) @@ -12563,9 +12510,7 @@ OP_J (int bytemode, int sizeflag) disp -= 0x100; break; case v_mode: - if (isa64 != intel64) case dqw_mode: - USED_REX (REX_W); if ((sizeflag & DFLAG) || (address_mode == mode_64bit && ((isa64 == intel64 && bytemode != dqw_mode) |