On Sun, Mar 4, 2012 at 2:40 PM, Uros Bizjak <ubiz...@gmail.com> wrote:
> On Sun, Mar 4, 2012 at 11:01 PM, H.J. Lu <hjl.to...@gmail.com> 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.

Reply via email to