[multiple changes]

2003-06-16  Alexandre Oliva  <aoliva@redhat.com>
* config/mn10300/mn10300.c (mn10300_unspec_int_label_counter):
Moved from...
* config/mn10300/mn10300.md (GOTaddr2picreg): ... here.
* config/mn10300/mn10300.h: GTY-declare it.
2003-06-11  Alexandre Oliva  <aoliva@redhat.com>
* config/mn10300/mn10300.c (mn10300_encode_section_info): Fix
prototype.  Use incoming RTL argument.
2002-12-12  Alexandre Oliva  <aoliva@redhat.com>
* config/mn10300/mn10300.md (int_label): Move C statements...
(GOTaddr2picreg): ... here.
2002-08-15  Alexandre Oliva  <aoliva@redhat.com>
* config/mn10300/mn10300.h (ENCODE_SECTION_INFO): Move...
* config/mn10300/mn10300.c (mn10300_encode_section_info):
... here.  New function.(TARGET_ENCODE_SECTION_INFO): Define to it.
2001-11-04  Alexandre Oliva  <aoliva@redhat.com>
* config/mn10300/mn10300.md (builtin_setjmp_receiver): Fix typo in
pattern name.
(mn10300_loadPC): Define as insn splittable after reload.
2001-05-13  Alexandre Oliva  <aoliva@redhat.com>
* config/sh/mn10300.h (JUMP_TABLES_IN_TEXT_SECTION): Let them
be defined in .rodata even in PIC, now that the assembler
supports that.
2001-05-09  Alexandre Oliva  <aoliva@redhat.com>
* config/mn10300/mn10300.h (GOT_SYMBOL_NAME): Don't let the
symbol take an underscore prefix.
2001-04-14  Alexandre Oliva  <aoliva@redhat.com>
* config/mn10300/mn10300-protos.h (legitimate_pic_operand_p,
legitimize_pic_address): Declare.
* config/mn10300/mn10300.h (CONDITIONAL_REGISTER_USAGE): Mark
the PIC register as fixed.
(EXTRA_CONSTRAINT): Match UNSPEC_PLT and UNSPEC_PIC for 'S'.
(GO_IF_LEGITIMATE_ADDRESS): Require legitimate_pic_operand for
PIC.
(LEGITIMATE_PIC_OPERAND_P): Define.
(PIC_OFFSET_TABLE_REGNUM): Define.
(GOT_SYMBOL_NAME): Define.
(SYMBOLIC_CONST_P): Define.
(ENCODE_SECTION_INFO): Use SYMBOL_REF_FLAG to mark local
symbols.
(MN10300_GLOBAL_P): Test it.
(OUTPUT_ADDR_CONST_EXTRA): Handle PIC-related unspecs.
(JUMP_TABLES_IN_TEXT_SECTION): Enable for PIC.
* config/mn10300/mn10300.c (print_operand): Handle unspec.
(expand_prologue): Set PIC register.
(call_address_operand): Don't match SYMBOL_REFs in PIC.
(legitimize_address): Call legitimize_pic_address.
(legitimize_pic_address): New fn.
(legitimate_pic_operand_p): New fn.
* config/mn10300/mn10300.md (PIC_REG, SP_REG): New constants.
(UNSPEC_INT_LABEL, UNSPEC_PIC, UNSPEC_GOT, UNSPEC_GOTOFF,
UNSPEC_PLT): New constants.
(pop_pic_reg): New insn.
(movsi): Adjust non-PIC addresses.
(builtin_setjmp_receiver): Restore the PIC register.
(casesi): New insn.
(call): Adjust non-PIC addresses.
(int_label, GOTaddr2picreg): New expands.
(am33_loadPC): New insn.
(mn10300_loadPC): New expand.
(call_next_insn): New insn.
(add_GOT_to_pic_reg): New expand.
(symGOT2reg, symGOT2reg_i): New expands.
(symGOTOFF2reg, symGOTOFF2reg_i): New expands.
(sym2PIC, sym2PLT): New expands.

From-SVN: r69169
This commit is contained in:
Alexandre Oliva 2003-07-10 03:25:32 +00:00 committed by Alexandre Oliva
parent e7f042e4cd
commit d177606965
5 changed files with 498 additions and 1 deletions

View file

@ -1,3 +1,72 @@
2003-07-09 Alexandre Oliva <aoliva@redhat.com>
2003-06-16 Alexandre Oliva <aoliva@redhat.com>
* config/mn10300/mn10300.c (mn10300_unspec_int_label_counter):
Moved from...
* config/mn10300/mn10300.md (GOTaddr2picreg): ... here.
* config/mn10300/mn10300.h: GTY-declare it.
2003-06-11 Alexandre Oliva <aoliva@redhat.com>
* config/mn10300/mn10300.c (mn10300_encode_section_info): Fix
prototype. Use incoming RTL argument.
2002-12-12 Alexandre Oliva <aoliva@redhat.com>
* config/mn10300/mn10300.md (int_label): Move C statements...
(GOTaddr2picreg): ... here.
2002-08-15 Alexandre Oliva <aoliva@redhat.com>
* config/mn10300/mn10300.h (ENCODE_SECTION_INFO): Move...
* config/mn10300/mn10300.c (mn10300_encode_section_info):
... here. New function.
(TARGET_ENCODE_SECTION_INFO): Define to it.
2001-11-04 Alexandre Oliva <aoliva@redhat.com>
* config/mn10300/mn10300.md (builtin_setjmp_receiver): Fix typo in
pattern name.
(mn10300_loadPC): Define as insn splittable after reload.
2001-05-13 Alexandre Oliva <aoliva@redhat.com>
* config/sh/mn10300.h (JUMP_TABLES_IN_TEXT_SECTION): Let them
be defined in .rodata even in PIC, now that the assembler
supports that.
2001-05-09 Alexandre Oliva <aoliva@redhat.com>
* config/mn10300/mn10300.h (GOT_SYMBOL_NAME): Don't let the
symbol take an underscore prefix.
2001-04-14 Alexandre Oliva <aoliva@redhat.com>
* config/mn10300/mn10300-protos.h (legitimate_pic_operand_p,
legitimize_pic_address): Declare.
* config/mn10300/mn10300.h (CONDITIONAL_REGISTER_USAGE): Mark
the PIC register as fixed.
(EXTRA_CONSTRAINT): Match UNSPEC_PLT and UNSPEC_PIC for 'S'.
(GO_IF_LEGITIMATE_ADDRESS): Require legitimate_pic_operand for
PIC.
(LEGITIMATE_PIC_OPERAND_P): Define.
(PIC_OFFSET_TABLE_REGNUM): Define.
(GOT_SYMBOL_NAME): Define.
(SYMBOLIC_CONST_P): Define.
(ENCODE_SECTION_INFO): Use SYMBOL_REF_FLAG to mark local
symbols.
(MN10300_GLOBAL_P): Test it.
(OUTPUT_ADDR_CONST_EXTRA): Handle PIC-related unspecs.
(JUMP_TABLES_IN_TEXT_SECTION): Enable for PIC.
* config/mn10300/mn10300.c (print_operand): Handle unspec.
(expand_prologue): Set PIC register.
(call_address_operand): Don't match SYMBOL_REFs in PIC.
(legitimize_address): Call legitimize_pic_address.
(legitimize_pic_address): New fn.
(legitimate_pic_operand_p): New fn.
* config/mn10300/mn10300.md (PIC_REG, SP_REG): New constants.
(UNSPEC_INT_LABEL, UNSPEC_PIC, UNSPEC_GOT, UNSPEC_GOTOFF,
UNSPEC_PLT): New constants.
(pop_pic_reg): New insn.
(movsi): Adjust non-PIC addresses.
(builtin_setjmp_receiver): Restore the PIC register.
(casesi): New insn.
(call): Adjust non-PIC addresses.
(int_label, GOTaddr2picreg): New expands.
(am33_loadPC): New insn.
(mn10300_loadPC): New expand.
(call_next_insn): New insn.
(add_GOT_to_pic_reg): New expand.
(symGOT2reg, symGOT2reg_i): New expands.
(symGOTOFF2reg, symGOTOFF2reg_i): New expands.
(sym2PIC, sym2PLT): New expands.
2003-07-09 Alexandre Oliva <aoliva@redhat.com>
* config/mn10300/mn10300.h (PREDICATE_CODES): Define.

View file

@ -26,6 +26,8 @@ extern void mn10300_va_start PARAMS ((tree, rtx));
#endif /* TREE_CODE */
extern struct rtx_def *legitimize_address PARAMS ((rtx, rtx, enum machine_mode));
extern rtx legitimize_pic_address (rtx, rtx);
extern int legitimate_pic_operand_p (rtx);
extern void print_operand PARAMS ((FILE *, rtx, int));
extern void print_operand_address PARAMS ((FILE *, rtx));
extern void mn10300_print_reg_list PARAMS ((FILE *, int));

View file

@ -44,6 +44,10 @@ Boston, MA 02111-1307, USA. */
#include "target.h"
#include "target-def.h"
/* This is used by GOTaddr2picreg to uniquely identify
UNSPEC_INT_LABELs. */
int mn10300_unspec_int_label_counter;
/* The size of the callee register save area. Right now we save everything
on entry since it costs us nothing in code size. It does cost us from a
speed standpoint, so we want to optimize this sooner or later. */
@ -75,6 +79,10 @@ static void mn10300_file_start PARAMS ((void));
#undef TARGET_ASM_FILE_START_FILE_DIRECTIVE
#define TARGET_ASM_FILE_START_FILE_DIRECTIVE true
#undef TARGET_ENCODE_SECTION_INFO
#define TARGET_ENCODE_SECTION_INFO mn10300_encode_section_info
static void mn10300_encode_section_info (tree, rtx, int);
struct gcc_target targetm = TARGET_INITIALIZER;
static void
@ -410,6 +418,7 @@ print_operand (file, x, code)
case CONST:
case LABEL_REF:
case CODE_LABEL:
case UNSPEC:
print_operand_address (file, x);
break;
default:
@ -881,6 +890,24 @@ expand_prologue ()
emit_insn (gen_addsi3 (stack_pointer_rtx,
stack_pointer_rtx,
GEN_INT (-size)));
if (flag_pic && regs_ever_live[PIC_OFFSET_TABLE_REGNUM])
{
rtx insn = get_last_insn ();
rtx last = emit_insn (gen_GOTaddr2picreg ());
/* Mark these insns as possibly dead. Sometimes, flow2 may
delete all uses of the PIC register. In this case, let it
delete the initialization too. */
do
{
insn = NEXT_INSN (insn);
REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_MAYBE_DEAD,
const0_rtx,
REG_NOTES (insn));
}
while (insn != last);
}
}
void
@ -1269,6 +1296,9 @@ call_address_operand (op, mode)
rtx op;
enum machine_mode mode ATTRIBUTE_UNUSED;
{
if (flag_pic)
return (EXTRA_CONSTRAINT (op, 'S') || GET_CODE (op) == REG);
return (GET_CODE (op) == SYMBOL_REF || GET_CODE (op) == REG);
}
@ -1756,6 +1786,9 @@ legitimize_address (x, oldx, mode)
rtx oldx ATTRIBUTE_UNUSED;
enum machine_mode mode ATTRIBUTE_UNUSED;
{
if (flag_pic && ! legitimate_pic_operand_p (x))
x = legitimize_pic_address (oldx, NULL_RTX);
/* Uh-oh. We might have an address for x[n-100000]. This needs
special handling to avoid creating an indexed memory address
with x-100000 as the base. */
@ -1786,6 +1819,75 @@ legitimize_address (x, oldx, mode)
return x;
}
/* Convert a non-PIC address in `orig' to a PIC address using @GOT or
@GOTOFF in `reg'. */
rtx
legitimize_pic_address (orig, reg)
rtx orig;
rtx reg;
{
if (GET_CODE (orig) == LABEL_REF
|| (GET_CODE (orig) == SYMBOL_REF
&& (CONSTANT_POOL_ADDRESS_P (orig)
|| ! MN10300_GLOBAL_P (orig))))
{
if (reg == 0)
reg = gen_reg_rtx (Pmode);
emit_insn (gen_symGOTOFF2reg (reg, orig));
return reg;
}
else if (GET_CODE (orig) == SYMBOL_REF)
{
if (reg == 0)
reg = gen_reg_rtx (Pmode);
emit_insn (gen_symGOT2reg (reg, orig));
return reg;
}
return orig;
}
/* Return zero if X references a SYMBOL_REF or LABEL_REF whose symbol
isn't protected by a PIC unspec; non-zero otherwise. */
int
legitimate_pic_operand_p (x)
rtx x;
{
register const char *fmt;
register int i;
if (GET_CODE (x) == SYMBOL_REF || GET_CODE (x) == LABEL_REF)
return 0;
if (GET_CODE (x) == UNSPEC
&& (XINT (x, 1) == UNSPEC_PIC
|| XINT (x, 1) == UNSPEC_GOT
|| XINT (x, 1) == UNSPEC_GOTOFF
|| XINT (x, 1) == UNSPEC_PLT))
return 1;
if (GET_CODE (x) == QUEUED)
return legitimate_pic_operand_p (QUEUED_VAR (x));
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 (! legitimate_pic_operand_p (XVECEXP (x, i, j)))
return 0;
}
else if (fmt[i] == 'e' && ! legitimate_pic_operand_p (XEXP (x, i)))
return 0;
}
return 1;
}
static int
mn10300_address_cost_1 (x, unsig)
rtx x;
@ -1973,3 +2075,23 @@ mn10300_wide_const_load_uses_clr (operands)
return val[0] == 0 || val[1] == 0;
}
/* If using PIC, mark a SYMBOL_REF for a non-global symbol so that we
may access it using GOTOFF instead of GOT. */
static void
mn10300_encode_section_info (decl, rtl, first)
tree decl;
rtx rtl;
int first;
{
rtx symbol;
if (GET_CODE (rtl) != MEM)
return;
symbol = XEXP (rtl, 0);
if (GET_CODE (symbol) != SYMBOL_REF)
return;
if (flag_pic)
SYMBOL_REF_FLAG (symbol) = (*targetm.binds_local_p) (decl);
}

View file

@ -46,6 +46,8 @@ Boston, MA 02111-1307, USA. */
extern int target_flags;
extern GTY(()) int mn10300_unspec_int_label_counter;
/* Macros used in the machine description to test the flags. */
/* Macro to define tables used to set the flags.
@ -212,6 +214,8 @@ extern int target_flags;
i++) \
fixed_regs[i] = call_used_regs[i] = 1; \
} \
if (flag_pic) \
fixed_regs[PIC_OFFSET_TABLE_REGNUM] = 1; \
}
/* Return number of consecutive hard regs needed starting at reg REGNO
@ -735,6 +739,9 @@ struct cum_arg {int nbytes; };
#define EXTRA_CONSTRAINT(OP, C) \
((C) == 'R' ? OK_FOR_R (OP) \
: (C) == 'Q' ? OK_FOR_Q (OP) \
: (C) == 'S' && flag_pic \
? GET_CODE (OP) == UNSPEC && (XINT (OP, 1) == UNSPEC_PLT \
|| XINT (OP, 1) == UNSPEC_PIC) \
: (C) == 'S' ? GET_CODE (OP) == SYMBOL_REF \
: (C) == 'T' ? OK_FOR_T (OP) \
: 0)
@ -775,7 +782,8 @@ struct cum_arg {int nbytes; };
#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR) \
{ \
if (CONSTANT_ADDRESS_P (X)) \
if (CONSTANT_ADDRESS_P (X) \
&& (! flag_pic || legitimate_pic_operand_p (X))) \
goto ADDR; \
if (RTX_OK_FOR_BASE_P (X)) \
goto ADDR; \
@ -797,6 +805,8 @@ struct cum_arg {int nbytes; };
{ \
if (GET_CODE (index) == CONST_INT) \
goto ADDR; \
if (GET_CODE (index) == CONST) \
goto ADDR; \
} \
} \
}
@ -833,6 +843,60 @@ struct cum_arg {int nbytes; };
#define LEGITIMATE_CONSTANT_P(X) 1
/* Zero if this needs fixing up to become PIC. */
#define LEGITIMATE_PIC_OPERAND_P(X) (legitimate_pic_operand_p (X))
/* Register to hold the addressing base for
position independent code access to data items. */
#define PIC_OFFSET_TABLE_REGNUM PIC_REG
/* The name of the pseudo-symbol representing the Global Offset Table. */
#define GOT_SYMBOL_NAME "*_GLOBAL_OFFSET_TABLE_"
#define SYMBOLIC_CONST_P(X) \
((GET_CODE (X) == SYMBOL_REF || GET_CODE (X) == LABEL_REF) \
&& ! LEGITIMATE_PIC_OPERAND_P (X))
/* Non-global SYMBOL_REFs have SYMBOL_REF_FLAG enabled. */
#define MN10300_GLOBAL_P(X) (! SYMBOL_REF_FLAG (X))
/* Recognize machine-specific patterns that may appear within
constants. Used for PIC-specific UNSPECs. */
#define OUTPUT_ADDR_CONST_EXTRA(STREAM, X, FAIL) \
do \
if (GET_CODE (X) == UNSPEC && XVECLEN ((X), 0) == 1) \
{ \
switch (XINT ((X), 1)) \
{ \
case UNSPEC_INT_LABEL: \
asm_fprintf ((STREAM), ".%LLIL%d", \
INTVAL (XVECEXP ((X), 0, 0))); \
break; \
case UNSPEC_PIC: \
/* GLOBAL_OFFSET_TABLE or local symbols, no suffix. */ \
output_addr_const ((STREAM), XVECEXP ((X), 0, 0)); \
break; \
case UNSPEC_GOT: \
output_addr_const ((STREAM), XVECEXP ((X), 0, 0)); \
fputs ("@GOT", (STREAM)); \
break; \
case UNSPEC_GOTOFF: \
output_addr_const ((STREAM), XVECEXP ((X), 0, 0)); \
fputs ("@GOTOFF", (STREAM)); \
break; \
case UNSPEC_PLT: \
output_addr_const ((STREAM), XVECEXP ((X), 0, 0)); \
fputs ("@PLT", (STREAM)); \
break; \
default: \
goto FAIL; \
} \
break; \
} \
else \
goto FAIL; \
while (0)
/* Tell final.c how to eliminate redundant test instructions. */

View file

@ -37,6 +37,17 @@
;; clobber - value of cc is unknown
(define_attr "cc" "none,none_0hit,set_znv,set_zn,compare,clobber,invert"
(const_string "clobber"))
(define_constants [
(PIC_REG 6)
(SP_REG 9)
(UNSPEC_INT_LABEL 0)
(UNSPEC_PIC 1)
(UNSPEC_GOT 2)
(UNSPEC_GOTOFF 3)
(UNSPEC_PLT 4)
])
;; ----------------------------------------------------------------------
;; MOVE INSTRUCTIONS
@ -269,6 +280,12 @@
DONE;
}")
(define_insn "pop_pic_reg"
[(set (reg:SI PIC_REG)
(mem:SI (post_inc:SI (reg:SI SP_REG))))]
"reload_completed"
"movm (sp),[a2]")
(define_expand "movsi"
[(set (match_operand:SI 0 "general_operand" "")
(match_operand:SI 1 "general_operand" ""))]
@ -279,6 +296,33 @@
if (!register_operand (operand1, SImode)
&& !register_operand (operand0, SImode))
operands[1] = copy_to_mode_reg (SImode, operand1);
if (flag_pic)
{
rtx temp;
if (SYMBOLIC_CONST_P (operands[1]))
{
if (GET_CODE (operands[0]) == MEM)
operands[1] = force_reg (Pmode, operands[1]);
else
{
temp = no_new_pseudos ? operands[0] : gen_reg_rtx (Pmode);
operands[1] = legitimize_pic_address (operands[1], temp);
}
}
else if (GET_CODE (operands[1]) == CONST
&& GET_CODE (XEXP (operands[1], 0)) == PLUS
&& SYMBOLIC_CONST_P (XEXP (XEXP (operands[1], 0), 0)))
{
temp = no_new_pseudos ? operands[0] : gen_reg_rtx (Pmode);
temp = legitimize_pic_address (XEXP (XEXP (operands[1], 0), 0),
temp);
operands[1] = expand_binop (SImode, add_optab, temp,
XEXP (XEXP (operands[1], 0), 1),
no_new_pseudos ? temp
: gen_reg_rtx (Pmode),
0, OPTAB_LIB_WIDEN);
}
}
}")
(define_insn ""
@ -1666,6 +1710,43 @@
"jmp (%0)"
[(set_attr "cc" "none")])
(define_expand "builtin_setjmp_receiver"
[(match_operand 0 "" "")]
"flag_pic"
"
{
if (flag_pic)
emit_insn (gen_GOTaddr2picreg ());
DONE;
}")
(define_expand "casesi"
[(match_operand:SI 0 "register_operand" "")
(match_operand:SI 1 "immediate_operand" "")
(match_operand:SI 2 "immediate_operand" "")
(match_operand 3 "" "") (match_operand 4 "" "")]
""
"
{
rtx table = gen_reg_rtx (SImode);
rtx index = gen_reg_rtx (SImode);
rtx addr = gen_reg_rtx (Pmode);
emit_move_insn (table, gen_rtx_LABEL_REF (VOIDmode, operands[3]));
emit_move_insn (index, plus_constant (operands[0], - INTVAL (operands[1])));
emit_insn (gen_cmpsi (index, operands[2]));
emit_jump_insn (gen_bgtu (operands[4]));
emit_move_insn (index, gen_rtx_ASHIFT (SImode, index, GEN_INT (2)));
emit_move_insn (addr, gen_rtx_MEM (SImode,
gen_rtx_PLUS (SImode, table, index)));
if (flag_pic)
emit_move_insn (addr, gen_rtx_PLUS (SImode, addr, table));
emit_jump_insn (gen_tablejump (addr, operands[3]));
DONE;
}")
(define_insn "tablejump"
[(set (pc) (match_operand:SI 0 "register_operand" "a"))
(use (label_ref (match_operand 1 "" "")))]
@ -1681,6 +1762,20 @@
""
"
{
if (flag_pic && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF)
{
if (MN10300_GLOBAL_P (XEXP (operands[0], 0)))
{
/* The PLT code won't run on AM30, but then, there's no
shared library support for AM30 either, so we just assume
the linker is going to adjust all @PLT relocs to the
actual symbols. */
emit_insn (gen_rtx_USE (VOIDmode, pic_offset_table_rtx));
XEXP (operands[0], 0) = gen_sym2PLT (XEXP (operands[0], 0));
}
else
XEXP (operands[0], 0) = gen_sym2PIC (XEXP (operands[0], 0));
}
if (! call_address_operand (XEXP (operands[0], 0), VOIDmode))
XEXP (operands[0], 0) = force_reg (SImode, XEXP (operands[0], 0));
emit_call_insn (gen_call_internal (XEXP (operands[0], 0), operands[1]));
@ -1710,6 +1805,20 @@
""
"
{
if (flag_pic && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF)
{
if (MN10300_GLOBAL_P (XEXP (operands[1], 0)))
{
/* The PLT code won't run on AM30, but then, there's no
shared library support for AM30 either, so we just assume
the linker is going to adjust all @PLT relocs to the
actual symbols. */
emit_insn (gen_rtx_USE (VOIDmode, pic_offset_table_rtx));
XEXP (operands[1], 0) = gen_sym2PLT (XEXP (operands[1], 0));
}
else
XEXP (operands[1], 0) = gen_sym2PIC (XEXP (operands[1], 0));
}
if (! call_address_operand (XEXP (operands[1], 0), VOIDmode))
XEXP (operands[1], 0) = force_reg (SImode, XEXP (operands[1], 0));
emit_call_insn (gen_call_value_internal (operands[0],
@ -2402,3 +2511,134 @@
"add %0,%0\;bcc %1"
[(set_attr "cc" "clobber")])
(define_expand "int_label"
[(unspec [(match_operand:SI 0 "" "")] UNSPEC_INT_LABEL)]
"" "")
(define_expand "GOTaddr2picreg"
[(match_dup 0)]
"" "
{
/* It would be nice to be able to have int_label keep track of the
counter and all, but if we add C code to it, we'll get an insn
back, and we just want the pattern. */
operands[0] = gen_int_label (GEN_INT (mn10300_unspec_int_label_counter++));
if (TARGET_AM33)
emit_insn (gen_am33_loadPC (operands[0]));
else
emit_insn (gen_mn10300_loadPC (operands[0]));
emit_insn (gen_add_GOT_to_pic_reg (operands[0]));
DONE;
}
")
(define_insn "am33_loadPC"
[(parallel
[(set (reg:SI PIC_REG) (pc))
(use (match_operand 0 "" ""))])]
"TARGET_AM33"
"%0:\;mov pc,a2")
(define_insn_and_split "mn10300_loadPC"
[(parallel
[(set (reg:SI PIC_REG) (pc))
(use (match_operand 0 "" ""))])]
""
"#"
"reload_completed"
[(match_operand 0 "" "")]
"
{
rtx sp_reg = gen_rtx_REG (SImode, SP_REG);
int need_stack_space = (get_frame_size () == 0
&& current_function_outgoing_args_size == 0);
if (need_stack_space)
emit_move_insn (sp_reg, plus_constant (sp_reg, -4));
emit_insn (gen_call_next_insn (operands[0]));
if (need_stack_space)
emit_insn (gen_pop_pic_reg ());
else
emit_move_insn (pic_offset_table_rtx, gen_rtx_MEM (SImode, sp_reg));
DONE;
}")
(define_insn "call_next_insn"
[(parallel
[(set (mem:SI (reg:SI SP_REG)) (pc))
(use (match_operand 0 "" ""))])]
"reload_completed"
"calls %0\;%0:")
(define_expand "add_GOT_to_pic_reg"
[(set (reg:SI PIC_REG)
(plus:SI
(reg:SI PIC_REG)
(const
(unspec [(minus:SI
(match_dup 1)
(const (minus:SI
(const (match_operand:SI 0 "" ""))
(pc))))
] UNSPEC_PIC))))]
""
"
{
operands[1] = gen_rtx_SYMBOL_REF (VOIDmode, GOT_SYMBOL_NAME);
}")
(define_expand "symGOT2reg"
[(match_operand:SI 0 "" "")
(match_operand:SI 1 "" "")]
""
"
{
rtx insn = emit_insn (gen_symGOT2reg_i (operands[0], operands[1]));
RTX_UNCHANGING_P (SET_SRC (PATTERN (insn))) = 1;
REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EQUAL, operands[1],
REG_NOTES (insn));
DONE;
}")
(define_expand "symGOT2reg_i"
[(set (match_operand:SI 0 "" "")
(mem:SI (plus:SI (reg:SI PIC_REG)
(const (unspec [(match_operand:SI 1 "" "")]
UNSPEC_GOT)))))]
""
"")
(define_expand "symGOTOFF2reg"
[(match_operand:SI 0 "" "") (match_operand:SI 1 "" "")]
""
"
{
rtx insn = emit_insn (gen_symGOTOFF2reg_i (operands[0], operands[1]));
REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EQUAL, operands[1],
REG_NOTES (insn));
DONE;
}")
(define_expand "symGOTOFF2reg_i"
[(set (match_operand:SI 0 "" "")
(const (unspec [(match_operand:SI 1 "" "")] UNSPEC_GOTOFF)))
(set (match_dup 0) (plus:SI (match_dup 0) (reg:SI PIC_REG)))]
""
"")
(define_expand "sym2PIC"
[(unspec [(match_operand:SI 0 "" "")] UNSPEC_PIC)]
"" "")
(define_expand "sym2PLT"
[(unspec [(match_operand:SI 0 "" "")] UNSPEC_PLT)]
"" "")