Bogus position independent code(PIC) emitted for ColdFire v4e
Peter Barada
pbarada@mail.wm.sps.mot.com
Fri Dec 6 12:46:00 GMT 2002
>Unfortunately ColdFire v4e can't handle the addressing mode of the
>instruction at 0x80000108 since that requires a 32 bit offset.
>I need to modify the compiler to generate PIC code for that
>instruction to look like:
>
> move.l #0x18,%r
> move.l (%a5,%r),%a0
>
>where '%r' is a temporary register. I've started looking at
>legitimize_pic_address, (gcc/config/m68k/m68k.c) and my eyes starte to
>glaze over. The leading comment indicates that the "compiler loads
>the address of foo into a register". Is this legitimize_pic_address,
>or somewhere else that does this (say movsi)?
I started looking at brute-forcing a change in legitimize_pic_address...
I've modified the symbol/label clause of legitimize_pic_address to
look like:
/* First handle a simple SYMBOL_REF or LABEL_REF */
if (GET_CODE (orig) == SYMBOL_REF || GET_CODE (orig) == LABEL_REF)
{
if (reg == 0)
abort ();
if (TARGET_COLDFIRE)
{
/* Get the symbol into the register */
emit_insn (gen_rtx_SET (Pmode, reg, orig));
/* Now add the pic_offset_table_rtx to it and load indirect */
pic_ref = gen_rtx_MEM (Pmode,
gen_rtx_PLUS (Pmode,
pic_offset_table_rtx, reg));
}
else
{
pic_ref = gen_rtx_MEM (Pmode,
gen_rtx_PLUS (Pmode,
pic_offset_table_rtx, orig));
}
current_function_uses_pic_offset_table = 1;
RTX_UNCHANGING_P (pic_ref) = 1;
emit_move_insn (reg, pic_ref);
return reg;
}
Which generates the two pieces of rtl for hte ColdFire case:
;; Start of basic block 0, registers live: 13 [%a5] 14 [%a6] 15 [%sp]
(note 23 5 8 [bb 0] NOTE_INSN_BASIC_BLOCK)
(insn 8 23 10 (set:SI (reg/f:SI 30)
(symbol_ref/i:SI ("__gmon_start__"))) -1 (nil)
(expr_list:REG_EQUAL (symbol_ref/i:SI ("__gmon_start__"))
(nil)))
(insn 10 8 14 (set (reg/f:SI 30)
(mem/u:SI (plus:SI (reg:SI 13 %a5)
(reg/f:SI 30)) [0 S4 A8])) 30 {*m68k.md:993} (insn_list 8 (nil))
(nil))
(insn 14 10 15 (set (cc0)
(reg/f:SI 30)) 3 {*m68k.md:353} (insn_list 10 (nil))
(nil))
But unfortunately the compine pass puts it back together again:
;; Start of basic block 0, registers live: 13 [%a5] 14 [%a6] 15 [%sp]
(note 23 5 8 [bb 0] NOTE_INSN_BASIC_BLOCK)
(note 8 23 10 NOTE_INSN_DELETED)
(insn 10 8 14 (set (reg/f:SI 30)
(mem/u:SI (plus:SI (reg:SI 13 %a5)
(symbol_ref/i:SI ("__gmon_start__"))) [0 S4 A8])) 30 {*m68k.md:993} (nil)
(nil))
(insn 14 10 15 (set (cc0)
(reg/f:SI 30)) 3 {*m68k.md:353} (insn_list 10 (nil))
(nil))
This is valid for 68020 since an SImode can be part of the offset, but
its illegal for ColdFire. In INDIRECTABLE_1_ADDRESS_P I find:
|| (GET_CODE (X) == PLUS && XEXP (X, 0) == pic_offset_table_rtx \
&& flag_pic && GET_CODE (XEXP (X, 1)) == SYMBOL_REF) \
|| (GET_CODE (X) == PLUS && XEXP (X, 0) == pic_offset_table_rtx \
&& flag_pic && GET_CODE (XEXP (X, 1)) == LABEL_REF))
1) Should that have been:
|| (GET_CODE (X) == PLUS && XEXP (X, 0) == pic_offset_table_rtx \
&& flag_pic && GET_CODE (XEXP (X, 1)) == SYMBOL_REF) \
|| (GET_CODE (X) == PLUS && XEXP (X, 1) == pic_offset_table_rtx \
&& flag_pic && GET_CODE (XEXP (X, 0)) == LABEL_REF))
2) Should this be changed to:
|| (!TARGET_COLDFIRE && \
(GET_CODE (X) == PLUS && XEXP (X, 0) == pic_offset_table_rtx \
&& flag_pic && GET_CODE (XEXP (X, 1)) == SYMBOL_REF) \
|| (GET_CODE (X) == PLUS && XEXP (X, 0) == pic_offset_table_rtx \
&& flag_pic && GET_CODE (XEXP (X, 1)) == LABEL_REF))
To force an addition of a symbol ref and the PIC register to be
rejected, or am I overlooking something...
--
Peter Barada Peter.Barada@motorola.com
Wizard 781-852-2768 (direct)
WaveMark Solutions(wholly owned by Motorola) 781-270-0193 (fax)
More information about the Gcc
mailing list