OSDN Git Service

* config/pdp11/pdp11-protos.h (pdp11_initial_elimination_offset,
authorpkoning <pkoning@138bc75d-0d04-0410-961f-82ee72b054a4>
Sat, 20 Nov 2010 19:11:32 +0000 (19:11 +0000)
committerpkoning <pkoning@138bc75d-0d04-0410-961f-82ee72b054a4>
Sat, 20 Nov 2010 19:11:32 +0000 (19:11 +0000)
pdp11_regno_reg_class): New functions.
* config/pdp11/pdp11.md (define_constants): Add register numbers.
* config/pdp11/pdp11.c (pdp11_regno_reg_class,
pdp11_sp_frame_offset, pdp11_initial_elimination_offset): New
functions.
* config/pdp11/pdp11.h (FIXED_REGISTERS, CALL_USED_REGISTERS): Add
frame pointer and argument pointer pseudo-registers.
(ARG_POINTER_REGNUM): Define.
(REG_CLASS_CONTENTS, REGNO_REG_CLASS): Add frame pointer and
argument pointer.
(FIRST_PARM_OFFSET): Update for argument pointer.
(INITIAL_FRAME_POINTER_OFFSET): Delete.
(ELIMINABLE_REGS, INITIAL_ELIMINATION_OFFSET): New macros.
(REGNO_OK_FOR_BASE_P, REGNO_OK_FOR_INDEX_P, REGISTER_NAMES): Add
frame pointer and argument pointer.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@166978 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/config/pdp11/pdp11-protos.h
gcc/config/pdp11/pdp11.c
gcc/config/pdp11/pdp11.h
gcc/config/pdp11/pdp11.md

index 758f7ae..c6da1be 100644 (file)
@@ -1,3 +1,22 @@
+2010-11-20  Paul Koning  <ni1d@arrl.net>
+
+       * config/pdp11/pdp11-protos.h (pdp11_initial_elimination_offset,
+       pdp11_regno_reg_class): New functions.
+       * config/pdp11/pdp11.md (define_constants): Add register numbers.
+       * config/pdp11/pdp11.c (pdp11_regno_reg_class,
+       pdp11_sp_frame_offset, pdp11_initial_elimination_offset): New
+       functions. 
+       * config/pdp11/pdp11.h (FIXED_REGISTERS, CALL_USED_REGISTERS): Add
+       frame pointer and argument pointer pseudo-registers.
+       (ARG_POINTER_REGNUM): Define.
+       (REG_CLASS_CONTENTS, REGNO_REG_CLASS): Add frame pointer and
+       argument pointer. 
+       (FIRST_PARM_OFFSET): Update for argument pointer.
+       (INITIAL_FRAME_POINTER_OFFSET): Delete.
+       (ELIMINABLE_REGS, INITIAL_ELIMINATION_OFFSET): New macros.
+       (REGNO_OK_FOR_BASE_P, REGNO_OK_FOR_INDEX_P, REGISTER_NAMES): Add
+       frame pointer and argument pointer. 
+       
 2010-11-20  Jakub Jelinek  <jakub@redhat.com>
 
        PR debug/46561
index a8da5a6..97f0589 100644 (file)
@@ -35,6 +35,8 @@ extern bool pdp11_cannot_change_mode_class (enum machine_mode,
                                             enum machine_mode, enum reg_class);
 extern bool pdp11_secondary_memory_needed (reg_class_t, reg_class_t, 
                                           enum machine_mode);
+extern int pdp11_initial_elimination_offset (int, int);
+extern enum reg_class pdp11_regno_reg_class (int);
 
 #endif /* RTX_CODE */
 
index 760026d..617a7f5 100644 (file)
@@ -300,7 +300,7 @@ pdp11_output_function_prologue (FILE *stream, HOST_WIDE_INT size)
        asm_fprintf (stream, "\tsub $%#wo, sp\n", fsize);
 
     /* save CPU registers  */
-    for (regno = 0; regno <= PC_REGNUM; regno++)                               
+    for (regno = R0_REGNUM; regno <= PC_REGNUM; regno++)                               
       if (df_regs_ever_live_p (regno) && ! call_used_regs[regno])      
            if (! ((regno == FRAME_POINTER_REGNUM)                      
                   && frame_pointer_needed))                            
@@ -379,7 +379,7 @@ pdp11_output_function_epilogue (FILE *stream, HOST_WIDE_INT size)
        k = 2*j;
        
        /* change fp -> r5 due to the compile error on libgcc2.c */
-       for (i = PC_REGNUM ; i >= 0 ; i--)                                      
+       for (i = PC_REGNUM ; i >= R0_REGNUM ; i--)                                      
          if (df_regs_ever_live_p (i) && ! call_used_regs[i])           
                fprintf(stream, "\tmov %#" HOST_WIDE_INT_PRINT "o(r5), %s\n",
                        (-fsize-2*j--)&0xffff, reg_names[i]);
@@ -1706,6 +1706,71 @@ pdp11_secondary_memory_needed (reg_class_t c1, reg_class_t c2,
   return (fromfloat != tofloat);
 }
 
+/* Return the class number of the smallest class containing
+   reg number REGNO.  */
+enum reg_class
+pdp11_regno_reg_class (int regno)
+{ 
+  if (regno == FRAME_POINTER_REGNUM || regno == ARG_POINTER_REGNUM)
+    return GENERAL_REGS;
+  else if (regno > AC3_REGNUM)
+    return NO_LOAD_FPU_REGS;
+  else if (regno >= AC0_REGNUM)
+    return LOAD_FPU_REGS;
+  else if (regno & 1)
+    return MUL_REGS;
+  else
+    return GENERAL_REGS;
+}
+
+
+static int
+pdp11_sp_frame_offset (void)
+{
+  int offset = 0, regno;
+  offset = get_frame_size();
+  for (regno = 0; regno <= PC_REGNUM; regno++)
+    if (df_regs_ever_live_p (regno) && ! call_used_regs[regno])
+      offset += 2;
+  for (regno = AC0_REGNUM; regno <= AC5_REGNUM; regno++)
+    if (df_regs_ever_live_p (regno) && ! call_used_regs[regno])
+      offset += 8;
+  
+  return offset;
+}   
+
+/* Return the offset between two registers, one to be eliminated, and the other
+   its replacement, at the start of a routine.  */
+
+int
+pdp11_initial_elimination_offset (int from, int to)
+{
+  int spoff;
+  
+  if (from == ARG_POINTER_REGNUM && to == HARD_FRAME_POINTER_REGNUM)
+    return 4;
+  else if (from == FRAME_POINTER_REGNUM
+          && to == HARD_FRAME_POINTER_REGNUM)
+    return 0;
+  else
+    {
+      gcc_assert (to == STACK_POINTER_REGNUM);
+
+      /* Get the size of the register save area.  */
+      spoff = pdp11_sp_frame_offset ();
+      if (from == FRAME_POINTER_REGNUM)
+       return spoff;
+
+      gcc_assert (from == ARG_POINTER_REGNUM);
+
+      /* If there is a frame pointer, that is saved too.  */
+      if (frame_pointer_needed)
+       spoff += 2;
+      
+      /* Account for the saved PC in the function call.  */
+      return spoff + 2;
+    }
+}    
 
 /* A copy of output_addr_const modified for pdp11 expression syntax.
    output_addr_const also gets called for %cDIGIT and %nDIGIT, which we don't
index 494d8ce..2d06b7d 100644 (file)
@@ -149,11 +149,9 @@ extern const struct real_format pdp11_d_format;
    reg 5       = fp;  not necessarily! 
 */
 
-/* don't let them touch fp regs for the time being !*/
-
 #define FIXED_REGISTERS  \
 {0, 0, 0, 0, 0, 0, 1, 1, \
- 0, 0, 0, 0, 0, 0     }
+ 0, 0, 0, 0, 0, 0, 1, 1 }
 
 
 
@@ -167,7 +165,7 @@ extern const struct real_format pdp11_d_format;
 /* don't know about fp */
 #define CALL_USED_REGISTERS  \
 {1, 1, 0, 0, 0, 0, 1, 1, \
- 0, 0, 0, 0, 0, 0 }
+ 0, 0, 0, 0, 0, 0, 1, 1 }
 
 
 /* Make sure everything's fine if we *don't* have an FPU.
@@ -183,7 +181,7 @@ extern const struct real_format pdp11_d_format;
   if (!TARGET_FPU)                             \
     {                                          \
       COPY_HARD_REG_SET (x, reg_class_contents[(int)FPU_REGS]); \
-      for (i = 0; i < FIRST_PSEUDO_REGISTER; i++ ) \
+      for (i = R0_REGNUM; i < FIRST_PSEUDO_REGISTER; i++ ) \
        if (TEST_HARD_REG_BIT (x, i))           \
        fixed_regs[i] = call_used_regs[i] = 1;  \
     }                                          \
@@ -239,9 +237,6 @@ extern const struct real_format pdp11_d_format;
 /* Specify the registers used for certain standard purposes.
    The values of these macros are register numbers.  */
 
-/* Base register for access to arguments of the function.  */
-#define ARG_POINTER_REGNUM FRAME_POINTER_REGNUM
-
 /* Register in which static-chain is passed to a function.  */
 /* ??? - i don't want to give up a reg for this! */
 #define STATIC_CHAIN_REGNUM 4
@@ -298,19 +293,14 @@ enum reg_class { NO_REGS, MUL_REGS, GENERAL_REGS, LOAD_FPU_REGS, NO_LOAD_FPU_REG
    This is an initializer for a vector of HARD_REG_SET
    of length N_REG_CLASSES.  */
 
-#define REG_CLASS_CONTENTS {{0}, {0x00aa}, {0x00ff}, {0x0f00}, {0x3000}, {0x3f00}, {0x3fff}}
+#define REG_CLASS_CONTENTS {{0}, {0x00aa}, {0xc0ff}, {0x0f00}, {0x3000}, {0x3f00}, {0xffff}}
 
 /* The same information, inverted:
    Return the class number of the smallest class containing
    reg number REGNO.  This could be a conditional expression
    or could index an array.  */
 
-#define REGNO_REG_CLASS(REGNO)                 \
-((REGNO) >= AC0_REGNUM ? \
- ((REGNO) <= AC3_REGNUM ? LOAD_FPU_REGS : \
-  NO_LOAD_FPU_REGS) :                     \
- (((REGNO) & 1) ? MUL_REGS : GENERAL_REGS))
-
+#define REGNO_REG_CLASS(REGNO) pdp11_regno_reg_class (REGNO)
 
 /* The class value for index registers, and the one for base regs.  */
 #define INDEX_REG_CLASS GENERAL_REGS
@@ -369,13 +359,8 @@ enum reg_class { NO_REGS, MUL_REGS, GENERAL_REGS, LOAD_FPU_REGS, NO_LOAD_FPU_REG
    stack */
 extern int current_first_parm_offset;
 
-/* Offset of first parameter from the argument pointer register value.  
-   For the pdp11, this is nonzero to account for the return address.
-       1 - return address
-       2 - frame pointer, if needed
-
-*/
-#define FIRST_PARM_OFFSET(FNDECL) ((frame_pointer_needed) ? 4 : 2)
+/* Offset of first parameter from the argument pointer register value.  */
+#define FIRST_PARM_OFFSET(FNDECL) 0
 
 /* Define how to find the value returned by a function.
    VALTYPE is the data type of the value (as a tree).
@@ -425,20 +410,28 @@ extern int may_call_alloca;
 
 #define EXIT_IGNORE_STACK      1
 
-#define INITIAL_FRAME_POINTER_OFFSET(DEPTH_VAR)        \
-{                                                              \
-  int offset, regno;                                           \
-  offset = get_frame_size();                                   \
-  for (regno = 0; regno <= PC_REGNUM; regno++)                 \
-    if (df_regs_ever_live_p (regno) && ! call_used_regs[regno])        \
-      offset += 2;                                             \
-  for (regno = AC0_REGNUM; regno <= AC5_REGNUM; regno++)       \
-    if (df_regs_ever_live_p (regno) && ! call_used_regs[regno])        \
-      offset += 8;                                             \
-  /* offset -= 2;   no fp on stack frame */                    \
-  (DEPTH_VAR) = offset;                                                \
-}   
-    
+/* Definitions for register eliminations.
+
+   This is an array of structures.  Each structure initializes one pair
+   of eliminable registers.  The "from" register number is given first,
+   followed by "to".  Eliminations of the same "from" register are listed
+   in order of preference.
+
+   There are two registers that can always be eliminated on the pdp11.
+   The frame pointer and the arg pointer can be replaced by either the
+   hard frame pointer or to the stack pointer, depending upon the
+   circumstances.  The hard frame pointer is not used before reload and
+   so it is not eligible for elimination.  */
+
+#define ELIMINABLE_REGS                                        \
+{{ ARG_POINTER_REGNUM, STACK_POINTER_REGNUM},          \
+ { ARG_POINTER_REGNUM, HARD_FRAME_POINTER_REGNUM},     \
+ { FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM},                \
+ { FRAME_POINTER_REGNUM, HARD_FRAME_POINTER_REGNUM}}   \
+
+#define INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET) \
+  ((OFFSET) = pdp11_initial_elimination_offset ((FROM), (TO)))
+
 \f
 /* Addressing modes, and classification of registers for them.  */
 
@@ -454,10 +447,11 @@ extern int may_call_alloca;
    Since they use reg_renumber, they are safe only once reg_renumber
    has been allocated, which happens in local-alloc.c.  */
 
-#define REGNO_OK_FOR_INDEX_P(REGNO) \
-  ((REGNO) <= PC_REGNUM || (unsigned) reg_renumber[REGNO] <= PC_REGNUM)
 #define REGNO_OK_FOR_BASE_P(REGNO)  \
-  ((REGNO) <= PC_REGNUM || (unsigned) reg_renumber[REGNO] <= PC_REGNUM)
+  ((REGNO) <= PC_REGNUM || (unsigned) reg_renumber[REGNO] <= PC_REGNUM || \
+   (REGNO) == ARG_POINTER_REGNUM || (REGNO) == FRAME_POINTER_REGNUM)
+
+#define REGNO_OK_FOR_INDEX_P(REGNO) REGNO_OK_FOR_BASE_P (REGNO)
 
 /* Now macros that check whether X is a register and also,
    strictly, whether it is in a specified class.
@@ -743,7 +737,7 @@ extern struct rtx_def *cc0_reg_rtx;
 
 #define REGISTER_NAMES \
 {"r0", "r1", "r2", "r3", "r4", "r5", "sp", "pc",     \
- "ac0", "ac1", "ac2", "ac3", "ac4", "ac5" }
+ "ac0", "ac1", "ac2", "ac3", "ac4", "ac5", "fp", "ap" }
 
 /* Globalizing directive for a label.  */
 #define GLOBAL_ASM_OP "\t.globl "
index 1176440..6f76458 100644 (file)
 (define_constants
   [
    ;; Register numbers
+   (R0_REGNUM            0)
    (RETVAL_REGNUM        0)
-   (FRAME_POINTER_REGNUM  5)
+   (HARD_FRAME_POINTER_REGNUM  5)
    (STACK_POINTER_REGNUM  6)
    (PC_REGNUM             7)
    (AC0_REGNUM            8)
    (AC3_REGNUM            11)
    (AC4_REGNUM            12)
    (AC5_REGNUM            13)
-   (FIRST_PSEUDO_REGISTER 14)
+   ;; The next two are not physical registers but are used for addressing
+   ;; arguments.
+   (FRAME_POINTER_REGNUM  14)
+   (ARG_POINTER_REGNUM    15)
+   (FIRST_PSEUDO_REGISTER 16)
    ;; Branch offset limits, as byte offsets from instruction address
    (MIN_BRANCH            -254)
    (MAX_BRANCH            256)