On Sun, Mar 4, 2012 at 2:40 PM, Uros Bizjak <[email protected]> wrote:
> On Sun, Mar 4, 2012 at 11:01 PM, H.J. Lu <[email protected]> wrote:
>
>>> @@ -13637,7 +13665,8 @@ ix86_print_operand (FILE *file, rtx x, int code)
>>> gcc_unreachable ();
>>> }
>>>
>>> - ix86_print_operand (file, x, 0);
>>> + ix86_print_operand (file, x,
>>> + TARGET_64BIT && REG_P (x) ? 'q' : 0);
>>> return;
>>>
>>> This is too big hammer. You output everything in DImode, so even if
>>> the address is in fact in SImode, you output it in DImode with an
>>> addr32 prefix.
>>>
>>
>> "%A" is only used in "jmp\t%A0" and there is no "jmp *%eax" instruction in
>> 64bit mode, only "jmp *%rax":
>>
>> [hjl@gnu-4 tmp]$ cat j.s
>> jmp *%eax
>> jmp *%rax
>> [hjl@gnu-4 tmp]$ gcc -c j.s
>> j.s: Assembler messages:
>> j.s:1: Error: operand type mismatch for `jmp'
>> [hjl@gnu-4 tmp]$
>>
>> It is OK for x32 since the upper 32bits are zero when we are loading "%eax".
>
> Just zero_extend register in wrong mode to DImode in indirect_jump and
> tablejump expanders. If above is true, then gcc will remove this
> extension automatically.
>
I tried:
diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
index 715e7ea..de5cf67 100644
--- a/gcc/config/i386/i386.md
+++ b/gcc/config/i386/i386.md
@@ -11100,10 +11100,15 @@
(set_attr "modrm" "0")])
(define_expand "indirect_jump"
- [(set (pc) (match_operand 0 "indirect_branch_operand" ""))])
+ [(set (pc) (match_operand 0 "indirect_branch_operand" ""))]
+ ""
+{
+ if (TARGET_X32)
+ operands[0] = convert_memory_address (word_mode, operands[0]);
+})
(define_insn "*indirect_jump"
- [(set (pc) (match_operand:P 0 "indirect_branch_operand" "rw"))]
+ [(set (pc) (match_operand:W 0 "indirect_branch_operand" "rw"))]
""
"jmp\t%A0"
[(set_attr "type" "ibr")
@@ -11145,12 +11150,12 @@
operands[0] = expand_simple_binop (Pmode, code, op0, op1, NULL_RTX, 0,
OPTAB_DIRECT);
}
- else if (TARGET_X32)
- operands[0] = convert_memory_address (Pmode, operands[0]);
+ if (TARGET_X32)
+ operands[0] = convert_memory_address (word_mode, operands[0]);
})
(define_insn "*tablejump_1"
- [(set (pc) (match_operand:P 0 "indirect_branch_operand" "rw"))
+ [(set (pc) (match_operand:W 0 "indirect_branch_operand" "rw"))
(use (label_ref (match_operand 1 "" "")))]
""
"jmp\t%A0"
and compiler does generate the same output. i386.c also has
xasm = "jmp\t%A0";
xasm = "call\t%A0";
for calls. There are no separate indirect call patterns. For x32,
only indirect register calls have to be in DImode. The direct call
should be in Pmode (SImode).
Since x86-64 hardware always zero-extends upper 32bits of 64bit
registers when loading its lower 32bits, it is safe and easier to just
to output 64bit registers for %A than zero-extend it by hand for all
jump/call patterns.
--
H.J.