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.