This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: AM33/2.0 support in mn10300-elf
- From: Alexandre Oliva <aoliva at redhat dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: 10 Jul 2003 00:24:50 -0300
- Subject: Re: AM33/2.0 support in mn10300-elf
- Organization: GCC Team, Red Hat
- References: <orel0z146j.fsf@free.redhat.lsd.ic.unicamp.br>
On Jul 9, 2003, Alexandre Oliva <aoliva@redhat.com> wrote:
> This patch adds support for AM33/2.0 to the mn10300-elf port.
> AM33/2.0 introduces a single-precision floating point unit to the
> original AM33.
This patch adds PIC support to mn10300-elf. Tested along with the
previous patch, on i686-pc-linux-gnu-x-mn10300-elf.
Index: gcc/ChangeLog
from 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>
Index: gcc/config/mn10300/mn10300-protos.h
===================================================================
RCS file: /cvs/uberbaum/gcc/config/mn10300/mn10300-protos.h,v
retrieving revision 1.8
diff -u -p -r1.8 mn10300-protos.h
--- gcc/config/mn10300/mn10300-protos.h 19 Jun 2003 21:47:18 -0000 1.8
+++ gcc/config/mn10300/mn10300-protos.h 10 Jul 2003 03:14:29 -0000
@@ -26,6 +26,8 @@ extern void mn10300_va_start PARAMS ((tr
#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));
Index: gcc/config/mn10300/mn10300.c
===================================================================
RCS file: /cvs/uberbaum/gcc/config/mn10300/mn10300.c,v
retrieving revision 1.53
diff -u -p -r1.53 mn10300.c
--- gcc/config/mn10300/mn10300.c 10 Jul 2003 02:56:29 -0000 1.53
+++ gcc/config/mn10300/mn10300.c 10 Jul 2003 03:14:33 -0000
@@ -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 ((
#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;
@@ -1972,4 +2074,24 @@ mn10300_wide_const_load_uses_clr (operan
}
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);
}
Index: gcc/config/mn10300/mn10300.h
===================================================================
RCS file: /cvs/uberbaum/gcc/config/mn10300/mn10300.h,v
retrieving revision 1.72
diff -u -p -r1.72 mn10300.h
--- gcc/config/mn10300/mn10300.h 10 Jul 2003 02:56:29 -0000 1.72
+++ gcc/config/mn10300/mn10300.h 10 Jul 2003 03:14:34 -0000
@@ -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. */
Index: gcc/config/mn10300/mn10300.md
===================================================================
RCS file: /cvs/uberbaum/gcc/config/mn10300/mn10300.md,v
retrieving revision 1.46
diff -u -p -r1.46 mn10300.md
--- gcc/config/mn10300/mn10300.md 10 Jul 2003 02:56:29 -0000 1.46
+++ gcc/config/mn10300/mn10300.md 10 Jul 2003 03:14:37 -0000
@@ -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)]
+ "" "")
--
Alexandre Oliva Enjoy Guarana', see http://www.ic.unicamp.br/~oliva/
Red Hat GCC Developer aoliva@{redhat.com, gcc.gnu.org}
CS PhD student at IC-Unicamp oliva@{lsd.ic.unicamp.br, gnu.org}
Free Software Evangelist Professional serial bug killer