From: H.J. Lu Date: Sat, 23 Sep 2006 23:10:14 +0000 (+0000) Subject: gas/ X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=539e75adb5c6632bd7e601a03185b865d751e23f;p=binutils-gdb.git gas/ 2006-09-23 H.J. Lu PR binutils/3235 * config/tc-i386.c (match_template): Check address size prefix to turn Disp64/Disp32/Disp16 operand into Disp32/Disp16/Disp32 operand. gas/testsuite/ 2006-09-23 H.J. Lu PR binutils/3235 * gas/i386/addr16.d: New file. * gas/i386/addr16.s: Likewise. * gas/i386/addr32.d: Likewise. * gas/i386/addr32.s: Likewise. * gas/i386/i386.exp: Add "addr16" and "addr32". * gas/i386/x86-64-addr32.s: Add tests for "add32 mov". * gas/i386/x86-64-addr32.d: Updated. opcodes/ 2006-09-23 H.J. Lu PR binutils/3235 * i386-dis.c (OP_OFF64): Get 32bit offset if there is an address size prefix. --- diff --git a/gas/ChangeLog b/gas/ChangeLog index 9fe98d45f2e..8648384a2b9 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,10 @@ +2006-09-23 H.J. Lu + + PR binutils/3235 + * config/tc-i386.c (match_template): Check address size prefix + to turn Disp64/Disp32/Disp16 operand into Disp32/Disp16/Disp32 + operand. + 2006-09-22 Alan Modra * config/tc-ppc.c (ppc_symbol_chars): Remove '+' and '-'. diff --git a/gas/config/tc-i386.c b/gas/config/tc-i386.c index 1e8534aea61..7cf514bc38b 100644 --- a/gas/config/tc-i386.c +++ b/gas/config/tc-i386.c @@ -2563,6 +2563,8 @@ match_template () unsigned int overlap0, overlap1, overlap2; unsigned int found_reverse_match; int suffix_check; + unsigned int operand_types [3]; + int addr_prefix_disp; #define MATCH(overlap, given, template) \ ((overlap & ~JumpAbsolute) \ @@ -2581,6 +2583,10 @@ match_template () overlap1 = 0; overlap2 = 0; found_reverse_match = 0; + operand_types [0] = 0; + operand_types [1] = 0; + operand_types [2] = 0; + addr_prefix_disp = -1; suffix_check = (i.suffix == BYTE_MNEM_SUFFIX ? No_bSuf : (i.suffix == WORD_MNEM_SUFFIX @@ -2596,6 +2602,8 @@ match_template () for (t = current_templates->start; t < current_templates->end; t++) { + addr_prefix_disp = -1; + /* Must have right number of operands. */ if (i.operands != t->operands) continue; @@ -2606,6 +2614,10 @@ match_template () && (t->opcode_modifier & IgnoreSize))) continue; + operand_types [0] = t->operand_types [0]; + operand_types [1] = t->operand_types [1]; + operand_types [2] = t->operand_types [2]; + /* In general, don't allow 64-bit operands in 32-bit mode. */ if (i.suffix == QWORD_MNEM_SUFFIX && flag_code != CODE_64BIT @@ -2613,8 +2625,8 @@ match_template () ? (!(t->opcode_modifier & IgnoreSize) && !intel_float_operand (t->name)) : intel_float_operand (t->name) != 2) - && (!(t->operand_types[0] & (RegMMX | RegXMM)) - || !(t->operand_types[t->operands > 1] & (RegMMX | RegXMM))) + && (!(operand_types[0] & (RegMMX | RegXMM)) + || !(operand_types[t->operands > 1] & (RegMMX | RegXMM))) && (t->base_opcode != 0x0fc7 || t->extension_opcode != 1 /* cmpxchg8b */)) continue; @@ -2628,41 +2640,76 @@ match_template () break; } - overlap0 = i.types[0] & t->operand_types[0]; + /* Address size prefix will turn Disp64/Disp32/Disp16 operand + into Disp32/Disp16/Disp32 operand. */ + if (i.prefix[ADDR_PREFIX] != 0) + { + unsigned int j, DispOn = 0, DispOff = 0; + + switch (flag_code) + { + case CODE_16BIT: + DispOn = Disp32; + DispOff = Disp16; + break; + case CODE_32BIT: + DispOn = Disp16; + DispOff = Disp32; + break; + case CODE_64BIT: + DispOn = Disp32; + DispOff = Disp64; + break; + } + + for (j = 0; j < 3; j++) + { + /* There should be only one Disp operand. */ + if ((operand_types[j] & DispOff)) + { + addr_prefix_disp = j; + operand_types[j] |= DispOn; + operand_types[j] &= ~DispOff; + break; + } + } + } + + overlap0 = i.types[0] & operand_types[0]; switch (t->operands) { case 1: - if (!MATCH (overlap0, i.types[0], t->operand_types[0])) + if (!MATCH (overlap0, i.types[0], operand_types[0])) continue; break; case 2: case 3: - overlap1 = i.types[1] & t->operand_types[1]; - if (!MATCH (overlap0, i.types[0], t->operand_types[0]) - || !MATCH (overlap1, i.types[1], t->operand_types[1]) + overlap1 = i.types[1] & operand_types[1]; + if (!MATCH (overlap0, i.types[0], operand_types[0]) + || !MATCH (overlap1, i.types[1], operand_types[1]) /* monitor in SSE3 is a very special case. The first register and the second register may have different sizes. */ || !((t->base_opcode == 0x0f01 && t->extension_opcode == 0xc8) || CONSISTENT_REGISTER_MATCH (overlap0, i.types[0], - t->operand_types[0], + operand_types[0], overlap1, i.types[1], - t->operand_types[1]))) + operand_types[1]))) { /* Check if other direction is valid ... */ if ((t->opcode_modifier & (D | FloatD)) == 0) continue; /* Try reversing direction of operands. */ - overlap0 = i.types[0] & t->operand_types[1]; - overlap1 = i.types[1] & t->operand_types[0]; - if (!MATCH (overlap0, i.types[0], t->operand_types[1]) - || !MATCH (overlap1, i.types[1], t->operand_types[0]) + overlap0 = i.types[0] & operand_types[1]; + overlap1 = i.types[1] & operand_types[0]; + if (!MATCH (overlap0, i.types[0], operand_types[1]) + || !MATCH (overlap1, i.types[1], operand_types[0]) || !CONSISTENT_REGISTER_MATCH (overlap0, i.types[0], - t->operand_types[1], + operand_types[1], overlap1, i.types[1], - t->operand_types[0])) + operand_types[0])) { /* Does not match either direction. */ continue; @@ -2678,12 +2725,12 @@ match_template () reverse match 3 operand instructions, and all 3 operand instructions only need to be checked for register consistency between operands 2 and 3. */ - overlap2 = i.types[2] & t->operand_types[2]; - if (!MATCH (overlap2, i.types[2], t->operand_types[2]) + overlap2 = i.types[2] & operand_types[2]; + if (!MATCH (overlap2, i.types[2], operand_types[2]) || !CONSISTENT_REGISTER_MATCH (overlap1, i.types[1], - t->operand_types[1], + operand_types[1], overlap2, i.types[2], - t->operand_types[2])) + operand_types[2])) continue; } @@ -2711,7 +2758,7 @@ match_template () { if (!intel_syntax && ((i.types[0] & JumpAbsolute) - != (t->operand_types[0] & JumpAbsolute))) + != (operand_types[0] & JumpAbsolute))) { as_warn (_("indirect %s without `*'"), t->name); } @@ -2727,6 +2774,11 @@ match_template () /* Copy the template we found. */ i.tm = *t; + + if (addr_prefix_disp != -1) + i.tm.operand_types[addr_prefix_disp] + = operand_types[addr_prefix_disp]; + if (found_reverse_match) { /* If we found a reverse match we must alter the opcode @@ -2735,8 +2787,8 @@ match_template () i.tm.base_opcode ^= found_reverse_match; - i.tm.operand_types[0] = t->operand_types[1]; - i.tm.operand_types[1] = t->operand_types[0]; + i.tm.operand_types[0] = operand_types[1]; + i.tm.operand_types[1] = operand_types[0]; } return 1; diff --git a/gas/testsuite/ChangeLog b/gas/testsuite/ChangeLog index 89892f7753d..fe1f119bdac 100644 --- a/gas/testsuite/ChangeLog +++ b/gas/testsuite/ChangeLog @@ -1,3 +1,16 @@ +2006-09-23 H.J. Lu + + PR binutils/3235 + * gas/i386/addr16.d: New file. + * gas/i386/addr16.s: Likewise. + * gas/i386/addr32.d: Likewise. + * gas/i386/addr32.s: Likewise. + + * gas/i386/i386.exp: Add "addr16" and "addr32". + + * gas/i386/x86-64-addr32.s: Add tests for "add32 mov". + * gas/i386/x86-64-addr32.d: Updated. + 2006-09-20 Kai Tietz * gas/all/gas.exp: Add support for x86_64-*-mingw64. diff --git a/gas/testsuite/gas/i386/addr16.d b/gas/testsuite/gas/i386/addr16.d new file mode 100644 index 00000000000..910d72570fc --- /dev/null +++ b/gas/testsuite/gas/i386/addr16.d @@ -0,0 +1,15 @@ +#objdump: -drw +#name: i386 16-bit addressing in 32-bit mode. + +.*: +file format .* + +Disassembly of section .text: + +0+000 <.text>: +[ ]*0:[ ]+67 a0 98 08 [ ]+addr16[ ]+mov[ ]+0x898,%al +[ ]*4:[ ]+67 66 a1 98 08 [ ]+addr16[ ]+mov[ ]+0x898,%ax +[ ]*9:[ ]+67 a1 98 08 [ ]+addr16[ ]+mov[ ]+0x898,%eax +[ ]*d:[ ]+67 a2 98 08 [ ]+addr16[ ]+mov[ ]+%al,0x898 +[ ]*11:[ ]+67 66 a3 98 08 [ ]+addr16[ ]+mov[ ]+%ax,0x898 +[ ]*16:[ ]+67 a3 98 08[ ]+addr16[ ]+mov[ ]+%eax,0x898 +#pass diff --git a/gas/testsuite/gas/i386/addr16.s b/gas/testsuite/gas/i386/addr16.s new file mode 100644 index 00000000000..b1510e79851 --- /dev/null +++ b/gas/testsuite/gas/i386/addr16.s @@ -0,0 +1,7 @@ + .text + addr16 mov 0x0898,%al + addr16 mov 0x0898,%ax + addr16 mov 0x0898,%eax + addr16 mov %al,0x0898 + addr16 mov %ax,0x0898 + addr16 mov %eax,0x0898 diff --git a/gas/testsuite/gas/i386/addr32.d b/gas/testsuite/gas/i386/addr32.d new file mode 100644 index 00000000000..5866a30c792 --- /dev/null +++ b/gas/testsuite/gas/i386/addr32.d @@ -0,0 +1,15 @@ +#objdump: -drw -mi8086 +#name: i386 32-bit addressing in 16-bit mode. + +.*: +file format .* + +Disassembly of section .text: + +0+000 <.text>: +[ ]*0:[ ]+67 a0 98 08 60 00[ ]+addr32[ ]+mov[ ]+0x600898,%al +[ ]*6:[ ]+67 a1 98 08 60 00[ ]+addr32[ ]+mov[ ]+0x600898,%ax +[ ]*c:[ ]+67 66 a1 98 08 60 00[ ]+addr32[ ]+mov[ ]+0x600898,%eax +[ ]*13:[ ]+67 a2 98 08 60 00[ ]+addr32[ ]+mov[ ]+%al,0x600898 +[ ]*19:[ ]+67 a3 98 08 60 00[ ]+addr32[ ]+mov[ ]+%ax,0x600898 +[ ]*1f:[ ]+67 66 a3 98 08 60 00[ ]+addr32[ ]+mov[ ]+%eax,0x600898 +#pass diff --git a/gas/testsuite/gas/i386/addr32.s b/gas/testsuite/gas/i386/addr32.s new file mode 100644 index 00000000000..3dab339dc25 --- /dev/null +++ b/gas/testsuite/gas/i386/addr32.s @@ -0,0 +1,8 @@ + .text + .code16 + addr32 mov 0x600898,%al + addr32 mov 0x600898,%ax + addr32 mov 0x600898,%eax + addr32 mov %al,0x600898 + addr32 mov %ax,0x600898 + addr32 mov %eax,0x600898 diff --git a/gas/testsuite/gas/i386/i386.exp b/gas/testsuite/gas/i386/i386.exp index 096b58ae649..aa2558ecd53 100644 --- a/gas/testsuite/gas/i386/i386.exp +++ b/gas/testsuite/gas/i386/i386.exp @@ -81,6 +81,8 @@ if [expr ([istarget "i*86-*-*"] || [istarget "x86_64-*-*"]) && [gas_32_check]] run_dump_test "nops-2" run_dump_test "nops-2-i386" run_dump_test "nops-2-merom" + run_dump_test "addr16" + run_dump_test "addr32" # These tests require support for 8 and 16 bit relocs, # so we only run them for ELF and COFF targets. diff --git a/gas/testsuite/gas/i386/x86-64-addr32.d b/gas/testsuite/gas/i386/x86-64-addr32.d index d22cff9c704..6cb20dc8719 100644 --- a/gas/testsuite/gas/i386/x86-64-addr32.d +++ b/gas/testsuite/gas/i386/x86-64-addr32.d @@ -11,4 +11,12 @@ Disassembly of section .text: [ ]*8:[ ]+67 49 8d 80 00 00 00 00[ ]+addr32[ ]+lea[ ]+0x0\(%r8d?\),%rax.* [ ]*10:[ ]+67 48 8d 05 00 00 00 00[ ]+addr32[ ]+lea[ ]+0\(%[re]ip\),%rax.* [ ]*18:[ ]+67 48 8d 04 25 00 00 00 00[ ]+addr32[ ]+lea[ ]+0x0,%rax.* +[ ]*21:[ ]+67 a0 98 08 60 00[ ]+addr32[ ]+mov[ ]+0x600898,%al +[ ]*27:[ ]+67 66 a1 98 08 60 00[ ]+addr32[ ]+mov[ ]+0x600898,%ax +[ ]*2e:[ ]+67 a1 98 08 60 00[ ]+addr32[ ]+mov[ ]+0x600898,%eax +[ ]*34:[ ]+67 48 a1 98 08 60 00[ ]+addr32[ ]+mov[ ]+0x600898,%rax +[ ]*3b:[ ]+67 a2 98 08 60 00[ ]+addr32[ ]+mov[ ]+%al,0x600898 +[ ]*41:[ ]+67 66 a3 98 08 60 00[ ]+addr32[ ]+mov[ ]+%ax,0x600898 +[ ]*48:[ ]+67 a3 98 08 60 00[ ]+addr32[ ]+mov[ ]+%eax,0x600898 +[ ]*4e:[ ]+67 48 a3 98 08 60 00[ ]+addr32[ ]+mov[ ]+%rax,0x600898 #pass diff --git a/gas/testsuite/gas/i386/x86-64-addr32.s b/gas/testsuite/gas/i386/x86-64-addr32.s index d18cbb91bcf..c32525ffa1f 100644 --- a/gas/testsuite/gas/i386/x86-64-addr32.s +++ b/gas/testsuite/gas/i386/x86-64-addr32.s @@ -3,3 +3,11 @@ lea symbol(%r8d), %rax addr32 lea symbol(%rip), %rax addr32 lea symbol, %rax + addr32 mov 0x600898,%al + addr32 mov 0x600898,%ax + addr32 mov 0x600898,%eax + addr32 mov 0x600898,%rax + addr32 mov %al,0x600898 + addr32 mov %ax,0x600898 + addr32 mov %eax,0x600898 + addr32 mov %rax,0x600898 diff --git a/opcodes/ChangeLog b/opcodes/ChangeLog index b48077def72..83c16bd3d9a 100644 --- a/opcodes/ChangeLog +++ b/opcodes/ChangeLog @@ -1,3 +1,9 @@ +2006-09-23 H.J. Lu + + PR binutils/3235 + * i386-dis.c (OP_OFF64): Get 32bit offset if there is an + address size prefix. + 2006-09-17 Mei Ligang * score-dis.c: New file. diff --git a/opcodes/i386-dis.c b/opcodes/i386-dis.c index bcf30802297..5172fc5cb9a 100644 --- a/opcodes/i386-dis.c +++ b/opcodes/i386-dis.c @@ -4693,7 +4693,8 @@ OP_OFF64 (int bytemode, int sizeflag) { bfd_vma off; - if (address_mode != mode_64bit) + if (address_mode != mode_64bit + || (prefixes & PREFIX_ADDR)) { OP_OFF (bytemode, sizeflag); return;