gas: 2004-06-03 Jan Beulich * config/tc-i386.c: Adjust immediates to only those permissible for the selected instruction suffix. Don't treat 32-bit addressing in 64-bit mode specially except for the width of the used base and/or index registers. Force zero displacement on rip-relative addressing when there is no other displacement. * testsuite/gas/i386/x86-64-addr32.[ds]: New test for x86-64 32-bit addressing in 64-bit mode. * testsuite/gas/i386/x86-64-rip.[ds]: New test for x86-64 rip-relative addressing. * testsuite/gas/i386/i386.exp: Run the two new tests. opcodes: 2004-06-03 Jan Beulich * i386-dis.c: Show rip-relative addressing in 64-bit mode regardless of address size prefix in effect. --- /home/jbeulich/src/binutils/mainline/2004-06-03.09.12/gas/config/tc-i386.c 2004-04-20 14:17:14.000000000 +0200 +++ 2004-06-03.09.12/gas/config/tc-i386.c 2004-06-03 10:22:33.663347560 +0200 @@ -1914,15 +1930,13 @@ i.types[op] = Imm64 | Imm32S; break; case LONG_MNEM_SUFFIX: - i.types[op] = Imm32 | Imm64; + i.types[op] = Imm32; break; case WORD_MNEM_SUFFIX: - i.types[op] = Imm16 | Imm32 | Imm64; - break; + i.types[op] = Imm16; break; case BYTE_MNEM_SUFFIX: - i.types[op] = Imm8 | Imm8S | Imm16 | Imm32S | Imm32; - break; + i.types[op] = Imm8 | Imm8S; break; } break; @@ -2496,7 +2516,7 @@ unsigned int overlap0, overlap1, overlap2; overlap0 = i.types[0] & i.tm.operand_types[0]; - if ((overlap0 & (Imm8 | Imm8S | Imm16 | Imm32 | Imm32S)) + if ((overlap0 & (Imm8 | Imm8S | Imm16 | Imm32 | Imm32S | Imm64)) && overlap0 != Imm8 && overlap0 != Imm8S && overlap0 != Imm16 && overlap0 != Imm32S && overlap0 != Imm32 && overlap0 != Imm64) @@ -2529,7 +2549,7 @@ i.types[0] = overlap0; overlap1 = i.types[1] & i.tm.operand_types[1]; - if ((overlap1 & (Imm8 | Imm8S | Imm16 | Imm32S | Imm32)) + if ((overlap1 & (Imm8 | Imm8S | Imm16 | Imm32S | Imm32 | Imm64)) && overlap1 != Imm8 && overlap1 != Imm8S && overlap1 != Imm16 && overlap1 != Imm32S && overlap1 != Imm32 && overlap1 != Imm64) @@ -2725,21 +2745,7 @@ if (i.index_reg == 0) { /* Operand is just */ - if ((flag_code == CODE_16BIT) ^ (i.prefix[ADDR_PREFIX] != 0) - && (flag_code != CODE_64BIT)) - { - i.rm.regmem = NO_BASE_REGISTER_16; - i.types[op] &= ~Disp; - i.types[op] |= Disp16; - } - else if (flag_code != CODE_64BIT - || (i.prefix[ADDR_PREFIX] != 0)) - { - i.rm.regmem = NO_BASE_REGISTER; - i.types[op] &= ~Disp; - i.types[op] |= Disp32; - } - else + if (flag_code == CODE_64BIT) { /* 64bit mode overwrites the 32bit absolute addressing by RIP relative addressing and @@ -2748,8 +2754,17 @@ i.rm.regmem = ESCAPE_TO_TWO_BYTE_ADDRESSING; i.sib.base = NO_BASE_REGISTER; i.sib.index = NO_INDEX_REGISTER; - i.types[op] &= ~Disp; - i.types[op] |= Disp32S; + i.types[op] = ((i.prefix[ADDR_PREFIX] == 0) ? Disp32S : Disp32); + } + else if ((flag_code == CODE_16BIT) ^ (i.prefix[ADDR_PREFIX] != 0)) + { + i.rm.regmem = NO_BASE_REGISTER_16; + i.types[op] = Disp16; + } + else + { + i.rm.regmem = NO_BASE_REGISTER; + i.types[op] = Disp32; } } else /* !i.base_reg && i.index_reg */ @@ -2774,6 +2789,8 @@ i.types[op] &= ~Disp; i.types[op] |= Disp32S; i.flags[op] = Operand_PCrel; + if (! i.disp_operands) + fake_zero_displacement = 1; } else if (i.base_reg->reg_type & Reg16) { @@ -2810,10 +2827,7 @@ if (flag_code == CODE_64BIT && (i.types[op] & Disp)) { - if (i.types[op] & Disp8) - i.types[op] = Disp8 | Disp32S; - else - i.types[op] = Disp32S; + i.types[op] = (i.types[op] & Disp8) | (i.prefix[ADDR_PREFIX] == 0 ? Disp32S : Disp32); } i.rm.regmem = i.base_reg->reg_num; if ((i.base_reg->reg_flags & RegRex) != 0) @@ -3993,28 +4007,16 @@ ok = 1; if (flag_code == CODE_64BIT) { - if (i.prefix[ADDR_PREFIX] == 0) - { - /* 64bit checks. */ - if ((i.base_reg - && ((i.base_reg->reg_type & Reg64) == 0) - && (i.base_reg->reg_type != BaseIndex - || i.index_reg)) - || (i.index_reg - && ((i.index_reg->reg_type & (Reg64 | BaseIndex)) - != (Reg64 | BaseIndex)))) - ok = 0; - } - else - { - /* 32bit checks. */ - if ((i.base_reg - && (i.base_reg->reg_type & (Reg32 | RegRex)) != Reg32) - || (i.index_reg - && ((i.index_reg->reg_type & (Reg32 | BaseIndex | RegRex)) - != (Reg32 | BaseIndex)))) - ok = 0; - } + unsigned RegXX = (i.prefix[ADDR_PREFIX] == 0 ? Reg64 : Reg32); + + if ((i.base_reg + && ((i.base_reg->reg_type & RegXX) == 0) + && (i.base_reg->reg_type != BaseIndex + || i.index_reg)) + || (i.index_reg + && ((i.index_reg->reg_type & (RegXX | BaseIndex)) + != (RegXX | BaseIndex)))) + ok = 0; } else { @@ -4047,8 +4049,7 @@ if (!ok) { #if INFER_ADDR_PREFIX - if (flag_code != CODE_64BIT - && i.prefix[ADDR_PREFIX] == 0 && stackop_size != '\0') + if (i.prefix[ADDR_PREFIX] == 0) { i.prefix[ADDR_PREFIX] = ADDR_PREFIX_OPCODE; i.prefixes += 1; @@ -4057,7 +4058,7 @@ FIXME. There doesn't seem to be any real need for separate Disp16 and Disp32 flags. The same goes for Imm16 and Imm32. Removing them would probably clean up the code quite a lot. */ - if (i.types[this_operand] & (Disp16 | Disp32)) + if (flag_code != CODE_64BIT && (i.types[this_operand] & (Disp16 | Disp32))) i.types[this_operand] ^= (Disp16 | Disp32); fudged = 1; goto tryprefix; @@ -4070,9 +4071,8 @@ as_bad (_("`%s' is not a valid %s bit base/index expression"), operand_string, flag_code_names[flag_code]); - return 0; } - return 1; + return ok; } /* Parse OPERAND_STRING into the i386_insn structure I. Returns non-zero --- /home/jbeulich/src/binutils/mainline/2004-06-03.09.12/gas/testsuite/gas/i386/i386.exp 2004-05-12 05:06:10.000000000 +0200 +++ 2004-06-03.09.12/gas/testsuite/gas/i386/i386.exp 2004-06-03 10:19:33.595722000 +0200 @@ -105,7 +105,9 @@ set ASFLAGS "$ASFLAGS --64" run_dump_test "x86_64" + run_dump_test "x86-64-addr32" run_dump_test "x86-64-opcode" + run_dump_test "x86-64-rip" run_list_test "x86-64-inval" "-al" set ASFLAGS "$old_ASFLAGS" --- /home/jbeulich/src/binutils/mainline/2004-06-03.09.12/gas/testsuite/gas/i386/x86-64-addr32.d 1970-01-01 01:00:00.000000000 +0100 +++ 2004-06-03.09.12/gas/testsuite/gas/i386/x86-64-addr32.d 2004-06-02 14:45:09.000000000 +0200 @@ -0,0 +1,13 @@ +#as: -J +#objdump: -drw +#name: x86-64 32-bit addressing + +.*: +file format elf64-x86-64 + +Disassembly of section .text: + +0+000 <.text>: +[ ]*0:[ ]+67 48 8d 80 00 00 00 00[ ]+addr32[ ]+lea[ ]+0x0\(%[re]ax\),%rax.* +[ ]*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.* --- /home/jbeulich/src/binutils/mainline/2004-06-03.09.12/gas/testsuite/gas/i386/x86-64-addr32.s 1970-01-01 01:00:00.000000000 +0100 +++ 2004-06-03.09.12/gas/testsuite/gas/i386/x86-64-addr32.s 2004-06-02 14:05:47.000000000 +0200 @@ -0,0 +1,5 @@ +.text + lea symbol(%eax), %rax + lea symbol(%r8d), %rax + addr32 lea symbol(%rip), %rax + addr32 lea symbol, %rax --- /home/jbeulich/src/binutils/mainline/2004-06-03.09.12/gas/testsuite/gas/i386/x86-64-rip.d 1970-01-01 01:00:00.000000000 +0100 +++ 2004-06-03.09.12/gas/testsuite/gas/i386/x86-64-rip.d 2004-06-02 14:13:16.000000000 +0200 @@ -0,0 +1,13 @@ +#as: -J +#objdump: -drw +#name: x86-64 rip addressing + +.*: +file format elf64-x86-64 + +Disassembly of section .text: + +0+000 <.text>: +[ ]*0:[ ]+8d 05 00 00 00 00[ ]+lea[ ]+0\(%rip\),%eax[ ]*(#.*)? +[ ]*6:[ ]+8d 05 11 11 11 11[ ]+lea[ ]+286331153\(%rip\),%eax[ ]*(#.*)? +[ ]*c:[ ]+8d 05 01 00 00 00[ ]+lea[ ]+1\(%rip\),%eax[ ]*(#.*)? +[ ]*12:[ ]+8d 05 00 00 00 00[ ]+lea[ ]+0\(%rip\),%eax[ ]*(#.*)? --- /home/jbeulich/src/binutils/mainline/2004-06-03.09.12/gas/testsuite/gas/i386/x86-64-rip.s 1970-01-01 01:00:00.000000000 +0100 +++ 2004-06-03.09.12/gas/testsuite/gas/i386/x86-64-rip.s 2004-06-02 12:00:40.000000000 +0200 @@ -0,0 +1,5 @@ +.text + leal symbol(%rip), %eax + leal 0x11111111(%rip), %eax + leal 1(%rip), %eax + leal (%rip), %eax --- /home/jbeulich/src/binutils/mainline/2004-06-03.09.12/opcodes/i386-dis.c 2004-03-12 14:38:16.000000000 +0100 +++ 2004-06-03.09.12/opcodes/i386-dis.c 2004-06-03 10:20:39.466708088 +0200 @@ -3094,7 +3096,7 @@ if ((base & 7) == 5) { havebase = 0; - if (mode_64bit && !havesib && (sizeflag & AFLAG)) + if (mode_64bit && !havesib) riprel = 1; disp = get32s (); }