This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: AM33/2.0 support in mn10300-elf


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

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]