Apply Philip Blundell <pb@nexus.co.uk>'s patch to add PIC support to the Thumb.
From-SVN: r28268
This commit is contained in:
parent
3a27d5755d
commit
4bdc1ac79d
5 changed files with 488 additions and 25 deletions
|
@ -1,3 +1,51 @@
|
|||
Mon Jul 26 17:24:51 1999 Philip Blundell <pb@nexus.co.uk>
|
||||
|
||||
* config/arm/thumb.h (THUMB_FLAG_SINGLE_PIC_BASE): Define.
|
||||
(TARGET_SINGLE_PIC_BASE): Likewise.
|
||||
(GOT_PCREL, NEED_GOT_RELOC, NEED_PLT_RELOC): Provide default
|
||||
definitions.
|
||||
(TARGET_CALLEE_INTERWORKING): Fix typo in comment.
|
||||
(TARGET_SWITCHES): Add -m{no-}single-pic-base.
|
||||
(TARGET_OPTIONS): Add -mpic-register=N.
|
||||
(OUTPUT_INT_ADDR_CONST): New macro.
|
||||
(INDEX_REGISTER_RTX_P, PIC_OFFSET_TABLE_REGNUM, FINALIZE_PIC,
|
||||
LEGITIMATE_PIC_OPERAND_P): Likewise.
|
||||
(LEGITIMIZE_ADDRESS, GOT_IF_LEGITIMATE_ADDRESS): Support PIC.
|
||||
(ASM_OUTPUT_INT): Use OUTPUT_INT_ADDR_CONST rather than calling
|
||||
output_addr_const directly.
|
||||
(PRINT_OPERAND_PUNCT_VALID_P): Accept `|' for compatibility with
|
||||
ARM port.
|
||||
(thumb_pic_register, thumb_pic_register_string): Declare.
|
||||
|
||||
* config/arm/thumb.c (symbol_mentioned_p): New function: Imported
|
||||
from arm.c.
|
||||
(label_mentioned_p): New function: Imported from arm.c.
|
||||
(legitimize_pic_address): New function: Imported from arm.c.
|
||||
(is_pic):New function: Imported from arm.c.
|
||||
(thumb_finalize_pic):New function: Imported from arm.c.
|
||||
(add_constant): Cope with PIC constants.
|
||||
(fixit): Cope with PIC constants.
|
||||
(output_return): Do not treat the PIC register as live if
|
||||
TARGET_SINGLE_PIC_BASE is true.
|
||||
(thumb_function_prologue): Do not treat the PIC register as live if
|
||||
TARGET_SINGLE_PIC_BASE is true.
|
||||
(thumb_expand_prologue): Do not treat the PIC register as live if
|
||||
TARGET_SINGLE_PIC_BASE is true.
|
||||
(thumb_unexpand_epilogue): Do not treat the PIC register as live if
|
||||
TARGET_SINGLE_PIC_BASE is true.
|
||||
(thumb_print_operand): Accept '|'.
|
||||
(thumb_override_options): Process PIC options.
|
||||
|
||||
* config/arm/thumb.md (movsi): Support PIC.
|
||||
(call_insn): Change "i" constraint to "X".
|
||||
(call_value_insn): Likewise.
|
||||
(consttable_4, consttable_8, consttable_end): Set and clear
|
||||
"making_const_table" as appropriate.
|
||||
(pic_load_addr, pic_add_dot_plus_four): New insns.
|
||||
|
||||
* invoke.texi (Thumb Options): Fix spelling. Document new
|
||||
options -msingle-pic-base and -mpic-register=.
|
||||
|
||||
1999-07-26 Andrew Haley <aph@cygnus.com>
|
||||
|
||||
* config/m32r/initfini.c (__init): Use a full word immediate for
|
||||
|
|
|
@ -32,6 +32,9 @@ Boston, MA 02111-1307, USA. */
|
|||
#include "flags.h"
|
||||
#include "tree.h"
|
||||
#include "expr.h"
|
||||
#include "insn-config.h"
|
||||
#include "recog.h"
|
||||
#include "toplev.h"
|
||||
|
||||
|
||||
int current_function_anonymous_args = 0;
|
||||
|
@ -40,12 +43,19 @@ int current_function_anonymous_args = 0;
|
|||
char * structure_size_string = NULL;
|
||||
int arm_structure_size_boundary = 32; /* Used to be 8 */
|
||||
|
||||
/* The register number to be used for the PIC offset register. */
|
||||
const char * thumb_pic_register_string = NULL;
|
||||
int thumb_pic_register = 10;
|
||||
|
||||
/* True if we are currently building a constant table. */
|
||||
int making_const_table;
|
||||
|
||||
|
||||
/* Predicates */
|
||||
int
|
||||
reload_memory_operand (op, mode)
|
||||
rtx op;
|
||||
enum machine_mode mode;
|
||||
enum machine_mode mode ATTRIBUTE_UNUSED ;
|
||||
{
|
||||
int regno = true_regnum (op);
|
||||
|
||||
|
@ -70,7 +80,6 @@ int
|
|||
thumb_shiftable_const (val)
|
||||
HOST_WIDE_INT val;
|
||||
{
|
||||
unsigned HOST_WIDE_INT x = val;
|
||||
unsigned HOST_WIDE_INT mask = 0xff;
|
||||
int i;
|
||||
|
||||
|
@ -105,6 +114,221 @@ thumb_trivial_epilogue ()
|
|||
#endif
|
||||
}
|
||||
|
||||
|
||||
/* Return TRUE if X references a SYMBOL_REF. */
|
||||
int
|
||||
symbol_mentioned_p (x)
|
||||
rtx x;
|
||||
{
|
||||
register char * fmt;
|
||||
register int i;
|
||||
|
||||
if (GET_CODE (x) == SYMBOL_REF)
|
||||
return 1;
|
||||
|
||||
fmt = GET_RTX_FORMAT (GET_CODE (x));
|
||||
for (i = GET_RTX_LENGTH (GET_CODE (x)) - 1; i >= 0; i--)
|
||||
{
|
||||
if (fmt[i] == 'E')
|
||||
{
|
||||
register int j;
|
||||
|
||||
for (j = XVECLEN (x, i) - 1; j >= 0; j--)
|
||||
if (symbol_mentioned_p (XVECEXP (x, i, j)))
|
||||
return 1;
|
||||
}
|
||||
else if (fmt[i] == 'e' && symbol_mentioned_p (XEXP (x, i)))
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Return TRUE if X references a LABEL_REF. */
|
||||
int
|
||||
label_mentioned_p (x)
|
||||
rtx x;
|
||||
{
|
||||
register char * fmt;
|
||||
register int i;
|
||||
|
||||
if (GET_CODE (x) == LABEL_REF)
|
||||
return 1;
|
||||
|
||||
fmt = GET_RTX_FORMAT (GET_CODE (x));
|
||||
for (i = GET_RTX_LENGTH (GET_CODE (x)) - 1; i >= 0; i--)
|
||||
{
|
||||
if (fmt[i] == 'E')
|
||||
{
|
||||
register int j;
|
||||
|
||||
for (j = XVECLEN (x, i) - 1; j >= 0; j--)
|
||||
if (label_mentioned_p (XVECEXP (x, i, j)))
|
||||
return 1;
|
||||
}
|
||||
else if (fmt[i] == 'e' && label_mentioned_p (XEXP (x, i)))
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
rtx
|
||||
legitimize_pic_address (orig, mode, reg)
|
||||
rtx orig;
|
||||
enum machine_mode mode;
|
||||
rtx reg;
|
||||
{
|
||||
if (GET_CODE (orig) == SYMBOL_REF)
|
||||
{
|
||||
rtx pic_ref, address;
|
||||
rtx insn;
|
||||
int subregs = 0;
|
||||
|
||||
if (reg == 0)
|
||||
{
|
||||
if (reload_in_progress || reload_completed)
|
||||
abort ();
|
||||
else
|
||||
reg = gen_reg_rtx (Pmode);
|
||||
|
||||
subregs = 1;
|
||||
}
|
||||
|
||||
#ifdef AOF_ASSEMBLER
|
||||
/* The AOF assembler can generate relocations for these directly, and
|
||||
understands that the PIC register has to be added into the offset.
|
||||
*/
|
||||
insn = emit_insn (gen_pic_load_addr_based (reg, orig));
|
||||
#else
|
||||
if (subregs)
|
||||
address = gen_reg_rtx (Pmode);
|
||||
else
|
||||
address = reg;
|
||||
|
||||
emit_insn (gen_pic_load_addr (address, orig));
|
||||
|
||||
pic_ref = gen_rtx_MEM (Pmode,
|
||||
gen_rtx_PLUS (Pmode, pic_offset_table_rtx,
|
||||
address));
|
||||
RTX_UNCHANGING_P (pic_ref) = 1;
|
||||
insn = emit_move_insn (reg, pic_ref);
|
||||
#endif
|
||||
current_function_uses_pic_offset_table = 1;
|
||||
/* Put a REG_EQUAL note on this insn, so that it can be optimized
|
||||
by loop. */
|
||||
REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EQUAL, orig,
|
||||
REG_NOTES (insn));
|
||||
return reg;
|
||||
}
|
||||
else if (GET_CODE (orig) == CONST)
|
||||
{
|
||||
rtx base, offset;
|
||||
|
||||
if (GET_CODE (XEXP (orig, 0)) == PLUS
|
||||
&& XEXP (XEXP (orig, 0), 0) == pic_offset_table_rtx)
|
||||
return orig;
|
||||
|
||||
if (reg == 0)
|
||||
{
|
||||
if (reload_in_progress || reload_completed)
|
||||
abort ();
|
||||
else
|
||||
reg = gen_reg_rtx (Pmode);
|
||||
}
|
||||
|
||||
if (GET_CODE (XEXP (orig, 0)) == PLUS)
|
||||
{
|
||||
base = legitimize_pic_address (XEXP (XEXP (orig, 0), 0), Pmode, reg);
|
||||
offset = legitimize_pic_address (XEXP (XEXP (orig, 0), 1), Pmode,
|
||||
base == reg ? 0 : reg);
|
||||
}
|
||||
else
|
||||
abort ();
|
||||
|
||||
if (GET_CODE (offset) == CONST_INT)
|
||||
{
|
||||
/* The base register doesn't really matter, we only want to
|
||||
test the index for the appropriate mode. */
|
||||
if (INDEX_REGISTER_RTX_P (offset) && GET_MODE_SIZE (mode) <= 4)
|
||||
goto win;
|
||||
|
||||
if (! reload_in_progress && ! reload_completed)
|
||||
offset = force_reg (Pmode, offset);
|
||||
else
|
||||
abort ();
|
||||
|
||||
win:
|
||||
if (GET_CODE (offset) == CONST_INT)
|
||||
return plus_constant_for_output (base, INTVAL (offset));
|
||||
}
|
||||
|
||||
if (GET_MODE_SIZE (mode) > 4)
|
||||
{
|
||||
emit_insn (gen_addsi3 (reg, base, offset));
|
||||
return reg;
|
||||
}
|
||||
|
||||
return gen_rtx_PLUS (Pmode, base, offset);
|
||||
}
|
||||
else if (GET_CODE (orig) == LABEL_REF)
|
||||
current_function_uses_pic_offset_table = 1;
|
||||
|
||||
return orig;
|
||||
}
|
||||
|
||||
static rtx pic_rtx;
|
||||
|
||||
int
|
||||
is_pic(x)
|
||||
rtx x;
|
||||
{
|
||||
if (x == pic_rtx)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
thumb_finalize_pic ()
|
||||
{
|
||||
#ifndef AOF_ASSEMBLER
|
||||
rtx l1, pic_tmp, pic_tmp2, seq;
|
||||
rtx global_offset_table;
|
||||
|
||||
if (current_function_uses_pic_offset_table == 0 || TARGET_SINGLE_PIC_BASE)
|
||||
return;
|
||||
|
||||
if (! flag_pic)
|
||||
abort ();
|
||||
|
||||
start_sequence ();
|
||||
l1 = gen_label_rtx ();
|
||||
|
||||
global_offset_table = gen_rtx_SYMBOL_REF (Pmode, "_GLOBAL_OFFSET_TABLE_");
|
||||
/* On the Thumb the PC register contains 'dot + 4' at the time of the
|
||||
addition. XXX Is this true? */
|
||||
pic_tmp = plus_constant (gen_rtx_LABEL_REF (Pmode, l1), 4);
|
||||
if (GOT_PCREL)
|
||||
pic_tmp2 = gen_rtx_CONST (VOIDmode,
|
||||
gen_rtx_PLUS (Pmode, global_offset_table, pc_rtx));
|
||||
else
|
||||
pic_tmp2 = gen_rtx_CONST (VOIDmode, global_offset_table);
|
||||
|
||||
pic_rtx = gen_rtx_CONST (Pmode, gen_rtx_MINUS (Pmode, pic_tmp2, pic_tmp));
|
||||
|
||||
emit_insn (gen_pic_load_addr (pic_offset_table_rtx, pic_rtx));
|
||||
emit_insn (gen_pic_add_dot_plus_four (pic_offset_table_rtx, l1));
|
||||
|
||||
seq = gen_sequence ();
|
||||
end_sequence ();
|
||||
emit_insn_after (seq, get_insns ());
|
||||
|
||||
/* Need to emit this whether or not we obey regdecls,
|
||||
since setjmp/longjmp can cause life info to screw up. */
|
||||
emit_insn (gen_rtx_USE (VOIDmode, pic_offset_table_rtx));
|
||||
#endif /* AOF_ASSEMBLER */
|
||||
}
|
||||
|
||||
|
||||
/* Routines for handling the constant pool */
|
||||
/* This is unashamedly hacked from the version in sh.c, since the problem is
|
||||
|
@ -194,6 +418,10 @@ add_constant (x, mode)
|
|||
if (mode == SImode && GET_CODE (x) == MEM && CONSTANT_P (XEXP (x, 0))
|
||||
&& CONSTANT_POOL_ADDRESS_P (XEXP (x, 0)))
|
||||
x = get_pool_constant (XEXP (x, 0));
|
||||
#ifndef AOF_ASSEMBLER
|
||||
else if (GET_CODE (x) == UNSPEC && XINT (x, 1) == 3)
|
||||
x = XVECEXP (x, 0, 0);
|
||||
#endif
|
||||
|
||||
/* First see if we've already got it */
|
||||
|
||||
|
@ -272,6 +500,10 @@ fixit (src, mode)
|
|||
rtx src;
|
||||
enum machine_mode mode;
|
||||
{
|
||||
#ifndef AOF_ASSEMBLER
|
||||
if (GET_CODE (src) == UNSPEC && XINT (src, 1) == 3)
|
||||
return 1;
|
||||
#endif
|
||||
return ((CONSTANT_P (src)
|
||||
&& (GET_CODE (src) != CONST_INT
|
||||
|| ! (CONST_OK_FOR_LETTER_P (INTVAL (src), 'I')
|
||||
|
@ -1004,7 +1236,8 @@ output_return ()
|
|||
return_used_this_function = 1;
|
||||
|
||||
for (regno = 0; regno < 8; regno++)
|
||||
if (regs_ever_live[regno] && ! call_used_regs[regno])
|
||||
if (regs_ever_live[regno] && ! call_used_regs[regno]
|
||||
&& ! (TARGET_SINGLE_PIC_BASE && (regno == thumb_pic_register)))
|
||||
live_regs_mask |= 1 << regno;
|
||||
|
||||
if (live_regs_mask == 0)
|
||||
|
@ -1120,7 +1353,8 @@ thumb_function_prologue (f, frame_size)
|
|||
}
|
||||
|
||||
for (regno = 0; regno < 8; regno++)
|
||||
if (regs_ever_live[regno] && ! call_used_regs[regno])
|
||||
if (regs_ever_live[regno] && ! call_used_regs[regno]
|
||||
&& ! (TARGET_SINGLE_PIC_BASE && (regno == thumb_pic_register)))
|
||||
live_regs_mask |= 1 << regno;
|
||||
|
||||
if (live_regs_mask || ! leaf_function_p () || far_jump_used_p())
|
||||
|
@ -1214,7 +1448,8 @@ thumb_function_prologue (f, frame_size)
|
|||
|
||||
for (regno = 8; regno < 13; regno++)
|
||||
{
|
||||
if (regs_ever_live[regno] && ! call_used_regs[regno])
|
||||
if (regs_ever_live[regno] && ! call_used_regs[regno]
|
||||
&& ! (TARGET_SINGLE_PIC_BASE && (regno == thumb_pic_register)))
|
||||
high_regs_pushed++;
|
||||
}
|
||||
|
||||
|
@ -1226,7 +1461,8 @@ thumb_function_prologue (f, frame_size)
|
|||
|
||||
for (next_hi_reg = 12; next_hi_reg > 7; next_hi_reg--)
|
||||
{
|
||||
if (regs_ever_live[next_hi_reg] && ! call_used_regs[next_hi_reg])
|
||||
if (regs_ever_live[next_hi_reg] && ! call_used_regs[next_hi_reg]
|
||||
&& ! (TARGET_SINGLE_PIC_BASE && (next_hi_reg == thumb_pic_register)))
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -1253,7 +1489,9 @@ thumb_function_prologue (f, frame_size)
|
|||
for (next_hi_reg--; next_hi_reg > 7; next_hi_reg--)
|
||||
{
|
||||
if (regs_ever_live[next_hi_reg]
|
||||
&& ! call_used_regs[next_hi_reg])
|
||||
&& ! call_used_regs[next_hi_reg]
|
||||
&& ! (TARGET_SINGLE_PIC_BASE
|
||||
&& (next_hi_reg == thumb_pic_register)))
|
||||
break;
|
||||
}
|
||||
else
|
||||
|
@ -1289,7 +1527,8 @@ thumb_expand_prologue ()
|
|||
{
|
||||
live_regs_mask = 0;
|
||||
for (regno = 0; regno < 8; regno++)
|
||||
if (regs_ever_live[regno] && ! call_used_regs[regno])
|
||||
if (regs_ever_live[regno] && ! call_used_regs[regno]
|
||||
&& ! (TARGET_SINGLE_PIC_BASE && (regno == thumb_pic_register)))
|
||||
live_regs_mask |= 1 << regno;
|
||||
|
||||
if (amount < 512)
|
||||
|
@ -1399,12 +1638,14 @@ thumb_unexpanded_epilogue ()
|
|||
return "";
|
||||
|
||||
for (regno = 0; regno < 8; regno++)
|
||||
if (regs_ever_live[regno] && ! call_used_regs[regno])
|
||||
if (regs_ever_live[regno] && ! call_used_regs[regno]
|
||||
&& ! (TARGET_SINGLE_PIC_BASE && (regno == thumb_pic_register)))
|
||||
live_regs_mask |= 1 << regno;
|
||||
|
||||
for (regno = 8; regno < 13; regno++)
|
||||
{
|
||||
if (regs_ever_live[regno] && ! call_used_regs[regno])
|
||||
if (regs_ever_live[regno] && ! call_used_regs[regno]
|
||||
&& ! (TARGET_SINGLE_PIC_BASE && (regno == thumb_pic_register)))
|
||||
high_regs_pushed ++;
|
||||
}
|
||||
|
||||
|
@ -1455,7 +1696,8 @@ thumb_unexpanded_epilogue ()
|
|||
}
|
||||
|
||||
for (next_hi_reg = 8; next_hi_reg < 13; next_hi_reg++)
|
||||
if (regs_ever_live[next_hi_reg] && ! call_used_regs[next_hi_reg])
|
||||
if (regs_ever_live[next_hi_reg] && ! call_used_regs[next_hi_reg]
|
||||
&& ! (TARGET_SINGLE_PIC_BASE && (next_hi_reg == thumb_pic_register)))
|
||||
break;
|
||||
|
||||
while (high_regs_pushed)
|
||||
|
@ -1483,7 +1725,9 @@ thumb_unexpanded_epilogue ()
|
|||
reg_names[next_hi_reg], reg_names[regno]);
|
||||
for (next_hi_reg++; next_hi_reg < 13; next_hi_reg++)
|
||||
if (regs_ever_live[next_hi_reg] &&
|
||||
! call_used_regs[next_hi_reg])
|
||||
! call_used_regs[next_hi_reg]
|
||||
&& ! (TARGET_SINGLE_PIC_BASE
|
||||
&& (next_hi_reg == thumb_pic_register)))
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -1788,6 +2032,10 @@ thumb_print_operand (f, x, code)
|
|||
fputs (ASM_COMMENT_START, f);
|
||||
return;
|
||||
|
||||
case '|':
|
||||
/* fputs (REGISTER_PREFIX, f); */
|
||||
return;
|
||||
|
||||
case '_':
|
||||
fputs (user_label_prefix, f);
|
||||
return;
|
||||
|
@ -2042,10 +2290,23 @@ thumb_override_options ()
|
|||
warning ("Structure size boundary can only be set to 8 or 32");
|
||||
}
|
||||
|
||||
if (flag_pic)
|
||||
if (thumb_pic_register_string != NULL)
|
||||
{
|
||||
warning ("Position independent code not supported. Ignored");
|
||||
flag_pic = 0;
|
||||
int pic_register;
|
||||
|
||||
if (! flag_pic)
|
||||
warning ("-mpic-register= is useless without -fpic");
|
||||
|
||||
pic_register = decode_reg_name (thumb_pic_register_string);
|
||||
|
||||
/* Prevent the user from choosing an obviously stupid PIC register. */
|
||||
if (pic_register < 0 || call_used_regs[pic_register]
|
||||
|| pic_register == HARD_FRAME_POINTER_REGNUM
|
||||
|| pic_register == STACK_POINTER_REGNUM
|
||||
|| pic_register >= PC_REGNUM)
|
||||
error ("Unable to use '%s' for PIC register", thumb_pic_register_string);
|
||||
else
|
||||
thumb_pic_register = pic_register;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -59,6 +59,7 @@ Boston, MA 02111-1307, USA. */
|
|||
#define THUMB_FLAG_BACKTRACE 0x0002
|
||||
#define THUMB_FLAG_LEAF_BACKTRACE 0x0004
|
||||
#define ARM_FLAG_THUMB 0x1000 /* same as in arm.h */
|
||||
#define THUMB_FLAG_SINGLE_PIC_BASE 0x4000 /* same as in arm.h */
|
||||
#define THUMB_FLAG_CALLEE_SUPER_INTERWORKING 0x40000
|
||||
#define THUMB_FLAG_CALLER_SUPER_INTERWORKING 0x80000
|
||||
|
||||
|
@ -71,8 +72,17 @@ extern int target_flags;
|
|||
#define TARGET_BACKTRACE (leaf_function_p() \
|
||||
? (target_flags & THUMB_FLAG_LEAF_BACKTRACE) \
|
||||
: (target_flags & THUMB_FLAG_BACKTRACE))
|
||||
#define TARGET_SINGLE_PIC_BASE (target_flags & THUMB_FLAG_SINGLE_PIC_BASE)
|
||||
|
||||
/* Set if externally visable functions should assume that they
|
||||
#ifndef GOT_PCREL
|
||||
#define GOT_PCREL 0
|
||||
#endif
|
||||
|
||||
#ifndef NEED_GOT_RELOC
|
||||
#define NEED_GOT_RELOC 1
|
||||
#endif
|
||||
|
||||
/* Set if externally visible functions should assume that they
|
||||
might be called in ARM mode, from a non-thumb aware code. */
|
||||
#define TARGET_CALLEE_INTERWORKING \
|
||||
(target_flags & THUMB_FLAG_CALLEE_SUPER_INTERWORKING)
|
||||
|
@ -101,6 +111,9 @@ extern int target_flags;
|
|||
{"no-callee-super-interworking", -THUMB_FLAG_CALLEE_SUPER_INTERWORKING}, \
|
||||
{"caller-super-interworking", THUMB_FLAG_CALLER_SUPER_INTERWORKING}, \
|
||||
{"no-caller-super-interworking", -THUMB_FLAG_CALLER_SUPER_INTERWORKING}, \
|
||||
{"single-pic-base", THUMB_FLAG_SINGLE_PIC_BASE, \
|
||||
"Do not load the PIC register in function prologues" }, \
|
||||
{"no-single-pic-base", -THUMB_FLAG_SINGLE_PIC_BASE, "" }, \
|
||||
SUBTARGET_SWITCHES \
|
||||
{"", TARGET_DEFAULT} \
|
||||
}
|
||||
|
@ -108,6 +121,8 @@ extern int target_flags;
|
|||
#define TARGET_OPTIONS \
|
||||
{ \
|
||||
{ "structure-size-boundary=", & structure_size_string }, \
|
||||
{ "pic-register=", & thumb_pic_register_string, \
|
||||
"Specify the register to be used for PIC addressing" } \
|
||||
}
|
||||
|
||||
#define REGISTER_PREFIX ""
|
||||
|
@ -170,7 +185,7 @@ extern int target_flags;
|
|||
#define ASM_OUTPUT_INT(STREAM,VALUE) \
|
||||
{ \
|
||||
fprintf (STREAM, "\t.word\t"); \
|
||||
output_addr_const (STREAM, (VALUE)); \
|
||||
OUTPUT_INT_ADDR_CONST (STREAM, (VALUE)); \
|
||||
fprintf (STREAM, "\n"); \
|
||||
}
|
||||
|
||||
|
@ -556,6 +571,9 @@ enum reg_class
|
|||
((REGNO) < 8 \
|
||||
|| (unsigned) reg_renumber[REGNO] < 8)
|
||||
|
||||
#define INDEX_REGISTER_RTX_P(X) \
|
||||
(GET_CODE (X) == REG && REG_OK_FOR_INDEX_P (X))
|
||||
|
||||
/* ??? This looks suspiciously wrong. */
|
||||
/* We need to leave BASE_REGS reloads alone, in order to avoid caller_save
|
||||
lossage. Caller_saves requests a BASE_REGS reload (caller_save_spill_class)
|
||||
|
@ -633,6 +651,9 @@ int thumb_shiftable_const ();
|
|||
|
||||
#define STATIC_CHAIN_REGNUM 9
|
||||
|
||||
/* Define this if the program counter is overloaded on a register. */
|
||||
#define PC_REGNUM 15
|
||||
|
||||
#define FRAME_POINTER_REQUIRED 0
|
||||
|
||||
#define ELIMINABLE_REGS \
|
||||
|
@ -797,6 +818,39 @@ int thumb_shiftable_const ();
|
|||
(FNADDR)); \
|
||||
}
|
||||
|
||||
|
||||
/* Position Independent Code. */
|
||||
/* We decide which register to use based on the compilation options and
|
||||
the assembler in use. @@@ Actually, we don't currently for Thumb. */
|
||||
extern int thumb_pic_register;
|
||||
|
||||
/* The register number of the register used to address a table of static
|
||||
data addresses in memory. */
|
||||
#define PIC_OFFSET_TABLE_REGNUM thumb_pic_register
|
||||
|
||||
#define FINALIZE_PIC thumb_finalize_pic ()
|
||||
|
||||
/* We can't directly access anything that contains a symbol,
|
||||
nor can we indirect via the constant pool. */
|
||||
#define LEGITIMATE_PIC_OPERAND_P(X) \
|
||||
(! symbol_mentioned_p (X) \
|
||||
&& (! CONSTANT_POOL_ADDRESS_P (X) \
|
||||
|| ! symbol_mentioned_p (get_pool_constant (X))))
|
||||
|
||||
/* We need to know when we are making a constant pool; this determines
|
||||
whether data needs to be in the GOT or can be referenced via a GOT
|
||||
offset. */
|
||||
extern int making_const_table;
|
||||
|
||||
#define CONDITIONAL_REGISTER_USAGE \
|
||||
{ \
|
||||
if (flag_pic) \
|
||||
{ \
|
||||
fixed_regs[PIC_OFFSET_TABLE_REGNUM] = 1; \
|
||||
call_used_regs[PIC_OFFSET_TABLE_REGNUM] = 0; \
|
||||
} \
|
||||
}
|
||||
|
||||
|
||||
/* Implicit Calls to Library Routines */
|
||||
|
||||
|
@ -884,7 +938,7 @@ int thumb_shiftable_const ();
|
|||
goto WIN; \
|
||||
/* This is PC relative data before MACHINE_DEPENDENT_REORG runs. */ \
|
||||
else if (GET_MODE_SIZE (MODE) >= 4 && CONSTANT_P (X) \
|
||||
&& CONSTANT_POOL_ADDRESS_P (X)) \
|
||||
&& CONSTANT_POOL_ADDRESS_P (X) && ! flag_pic) \
|
||||
goto WIN; \
|
||||
/* This is PC relative data after MACHINE_DEPENDENT_REORG runs. */ \
|
||||
else if (GET_MODE_SIZE (MODE) >= 4 && reload_completed \
|
||||
|
@ -955,6 +1009,12 @@ int thumb_shiftable_const ();
|
|||
&& (INTVAL (XEXP (X, 1)) & 3) == 0) \
|
||||
goto WIN; \
|
||||
} \
|
||||
else if (GET_MODE_CLASS (MODE) != MODE_FLOAT \
|
||||
&& GET_CODE (X) == SYMBOL_REF \
|
||||
&& CONSTANT_POOL_ADDRESS_P (X) \
|
||||
&& ! (flag_pic \
|
||||
&& symbol_mentioned_p (get_pool_constant (X)))) \
|
||||
goto WIN; \
|
||||
}
|
||||
|
||||
/* ??? If an HImode FP+large_offset address is converted to an HImode
|
||||
|
@ -985,7 +1045,10 @@ int thumb_shiftable_const ();
|
|||
|
||||
#define GO_IF_MODE_DEPENDENT_ADDRESS(ADDR,LABEL)
|
||||
|
||||
#define LEGITIMIZE_ADDRESS(X,OLDX,MODE,WIN)
|
||||
extern struct rtx_def * legitimize_pic_address ();
|
||||
#define LEGITIMIZE_ADDRESS(X, OLDX, MODE, WIN) \
|
||||
if (flag_pic) \
|
||||
(X) = legitimize_pic_address (OLDX, MODE, NULL_RTX);
|
||||
|
||||
#define LEGITIMATE_CONSTANT_P(X) \
|
||||
(GET_CODE (X) == CONST_INT \
|
||||
|
@ -1078,6 +1141,28 @@ int thumb_shiftable_const ();
|
|||
|
||||
/* Position Independent Code */
|
||||
|
||||
extern const char * thumb_pic_register_string;
|
||||
extern int thumb_pic_register;
|
||||
|
||||
/* The register number of the register used to address a table of static
|
||||
data addresses in memory. */
|
||||
#define PIC_OFFSET_TABLE_REGNUM thumb_pic_register
|
||||
|
||||
#define FINALIZE_PIC thumb_finalize_pic ()
|
||||
|
||||
/* We can't directly access anything that contains a symbol,
|
||||
nor can we indirect via the constant pool. */
|
||||
#define LEGITIMATE_PIC_OPERAND_P(X) \
|
||||
(! symbol_mentioned_p (X) \
|
||||
&& (! CONSTANT_POOL_ADDRESS_P (X) \
|
||||
|| ! symbol_mentioned_p (get_pool_constant (X))))
|
||||
|
||||
/* We need to know when we are making a constant pool; this determines
|
||||
whether data needs to be in the GOT or can be referenced via a GOT
|
||||
offset. */
|
||||
extern int making_const_table;
|
||||
|
||||
|
||||
#define PRINT_OPERAND(STREAM,X,CODE) \
|
||||
thumb_print_operand((STREAM), (X), (CODE))
|
||||
|
||||
|
@ -1102,7 +1187,33 @@ int thumb_shiftable_const ();
|
|||
output_addr_const ((STREAM), (X)); \
|
||||
}
|
||||
|
||||
#define PRINT_OPERAND_PUNCT_VALID_P(CODE) ((CODE) == '@' || ((CODE) == '_'))
|
||||
/* Handles PIC addr specially */
|
||||
#define OUTPUT_INT_ADDR_CONST(STREAM,X) \
|
||||
{ \
|
||||
if (flag_pic && GET_CODE(X) == CONST && is_pic(X)) \
|
||||
{ \
|
||||
output_addr_const(STREAM, XEXP (XEXP (XEXP (X, 0), 0), 0)); \
|
||||
fputs(" - (", STREAM); \
|
||||
output_addr_const(STREAM, XEXP (XEXP (XEXP (X, 0), 1), 0)); \
|
||||
fputs(")", STREAM); \
|
||||
} \
|
||||
else output_addr_const(STREAM, X); \
|
||||
\
|
||||
/* Mark symbols as position independent. We only do this in the \
|
||||
.text segment, not in the .data segment. */ \
|
||||
if (NEED_GOT_RELOC && flag_pic && making_const_table && \
|
||||
(GET_CODE(X) == SYMBOL_REF || GET_CODE(X) == LABEL_REF)) \
|
||||
{ \
|
||||
if (GET_CODE(X) == SYMBOL_REF && CONSTANT_POOL_ADDRESS_P(X)) \
|
||||
fprintf(STREAM, "(GOTOFF)"); \
|
||||
else if (GET_CODE (X) == LABEL_REF) \
|
||||
fprintf(STREAM, "(GOTOFF)"); \
|
||||
else \
|
||||
fprintf(STREAM, "(GOT)"); \
|
||||
} \
|
||||
}
|
||||
|
||||
#define PRINT_OPERAND_PUNCT_VALID_P(CODE) ((CODE) == '@' || ((CODE) == '_') || ((CODE) == '|'))
|
||||
|
||||
/* Emit a special directive when defining a function name.
|
||||
This is used by the assembler to assit with interworking. */
|
||||
|
|
|
@ -43,6 +43,11 @@
|
|||
if (GET_CODE (operands[0]) != REG)
|
||||
operands[1] = force_reg (SImode, operands[1]);
|
||||
}
|
||||
if (CONSTANT_P (operands[1]) && flag_pic)
|
||||
operands[1] = legitimize_pic_address (operands[1], SImode,
|
||||
((reload_in_progress
|
||||
|| reload_completed)
|
||||
? operands[0] : 0));
|
||||
")
|
||||
|
||||
(define_insn "*movsi_insn"
|
||||
|
@ -1051,7 +1056,7 @@
|
|||
|
||||
|
||||
(define_insn "*call_insn"
|
||||
[(call (mem:SI (match_operand:SI 0 "" "i"))
|
||||
[(call (mem:SI (match_operand:SI 0 "" "X"))
|
||||
(match_operand:SI 1 "" ""))]
|
||||
"GET_CODE (operands[0]) == SYMBOL_REF"
|
||||
"bl\\t%a0"
|
||||
|
@ -1059,7 +1064,7 @@
|
|||
|
||||
(define_insn "*call_value_insn"
|
||||
[(set (match_operand 0 "register_operand" "=l")
|
||||
(call (mem:SI (match_operand 1 "" "i"))
|
||||
(call (mem:SI (match_operand 1 "" "X"))
|
||||
(match_operand 2 "" "")))]
|
||||
"GET_CODE (operands[1]) == SYMBOL_REF"
|
||||
"bl\\t%a1"
|
||||
|
@ -1110,6 +1115,7 @@
|
|||
""
|
||||
"*
|
||||
{
|
||||
making_const_table = TRUE;
|
||||
switch (GET_MODE_CLASS (GET_MODE (operands[0])))
|
||||
{
|
||||
case MODE_FLOAT:
|
||||
|
@ -1132,6 +1138,7 @@
|
|||
""
|
||||
"*
|
||||
{
|
||||
making_const_table = TRUE;
|
||||
switch (GET_MODE_CLASS (GET_MODE (operands[0])))
|
||||
{
|
||||
case MODE_FLOAT:
|
||||
|
@ -1153,7 +1160,7 @@
|
|||
[(unspec_volatile [(const_int 0)] 4)]
|
||||
""
|
||||
"*
|
||||
/* Nothing to do (currently). */
|
||||
making_const_table = FALSE;
|
||||
return \"\";
|
||||
")
|
||||
|
||||
|
@ -1164,3 +1171,26 @@
|
|||
assemble_align (32);
|
||||
return \"\";
|
||||
")
|
||||
|
||||
/* When generating pic, we need to load the symbol offset into a register.
|
||||
So that the optimizer does not confuse this with a normal symbol load
|
||||
we use an unspec. The offset will be loaded from a constant pool entry,
|
||||
since that is the only type of relocation we can use. */
|
||||
|
||||
(define_insn "pic_load_addr"
|
||||
[(set (match_operand:SI 0 "register_operand" "=r")
|
||||
(unspec:SI [(match_operand 1 "" "")] 3))]
|
||||
"flag_pic"
|
||||
"ldr\\t%0, %a1")
|
||||
|
||||
(define_insn "pic_add_dot_plus_four"
|
||||
[(set (match_operand 0 "register_operand" "+r")
|
||||
(plus:SI (match_dup 0) (const (plus:SI (pc) (const_int 4)))))
|
||||
(use (label_ref (match_operand 1 "" "")))]
|
||||
"flag_pic"
|
||||
"*
|
||||
ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\",
|
||||
CODE_LABEL_NUMBER (operands[1]));
|
||||
return \"add\\t%0, %|pc\";
|
||||
")
|
||||
|
||||
|
|
|
@ -276,6 +276,8 @@ in the following sections.
|
|||
-mnop-fun-dllimport -mno-nop-fun-dllimport
|
||||
-mcallee-super-interworking -mno-callee-super-interworking
|
||||
-mcaller-super-interworking -mno-caller-super-interworking
|
||||
-msingle-pic-base -mno-single-pic-base
|
||||
-mpic-register=
|
||||
|
||||
@emph{MN10200 Options}
|
||||
-mrelax
|
||||
|
@ -4395,7 +4397,7 @@ Generate code for a processor running in big-endian mode.
|
|||
@item -mstructure-size-boundary=<n>
|
||||
@kindex -mstructure-size-boundary
|
||||
The size of all structures and unions will be rounded up to a multiple
|
||||
of the number of bits set by this option. Permissable values are 8 and
|
||||
of the number of bits set by this option. Permissible values are 8 and
|
||||
32. The default value varies for different toolchains. For the COFF
|
||||
targeted toolchain the default value is 8. Specifying the larger number
|
||||
can produced faster, more efficient code, but can also increase the size
|
||||
|
@ -4421,7 +4423,18 @@ non-interworking code.
|
|||
Allows calls via function pointers (including virtual functions) to
|
||||
execute correctly regardless of whether the target code has been
|
||||
compiled for interworking or not. There is a small overhead in the cost
|
||||
of executing a funciton pointer if this option is enabled.
|
||||
of executing a function pointer if this option is enabled.
|
||||
|
||||
@item -msingle-pic-base
|
||||
@kindex -msingle-pic-base
|
||||
Treat the register used for PIC addressing as read-only, rather than
|
||||
loading it in the prologue for each function. The run-time system is
|
||||
responsible for initialising this register with an appropriate value
|
||||
before execution begins.
|
||||
|
||||
@item -mpic-register=<reg>
|
||||
@kindex -mpic-register=
|
||||
Specify the register to be used for PIC addressing. The default is R10.
|
||||
|
||||
@end table
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue