]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
pdp11-protos.h (pdp11_cannot_change_mode_class, [...]): Declare.
authorPaul Koning <pkoning@equallogic.com>
Fri, 29 Oct 2010 14:32:59 +0000 (14:32 +0000)
committerPaul Koning <pkoning@gcc.gnu.org>
Fri, 29 Oct 2010 14:32:59 +0000 (10:32 -0400)
* config/pdp11/pdp11-protos.h (pdp11_cannot_change_mode_class,
pdp11_secondary_memory_needed): Declare.
* config/pdp11/predicates.md (float_operand): New predicate.
* config/pdp11/pdp11.md (RETVAL_REGNUM): New constant.
(cbranchdf4, movdf): Change predicate.
(movsf): Handle FPU register case.
(truncdfsf2, extendsfdf2): Add FPU register case.
* config/pdp11/pdp11.c (TARGET_SECONDARY_RELOAD,
TARGET_REGISTER_MOVE_COST, TARGET_PREFERRED_RELOAD_CLASS,
TARGET_PREFERRED_OUTPUT_RELOAD_CLASS): Define.
(pdp11_register_move_cost): Update cost matrix.
(pdp11_cannot_change_mode_class, pdp11_preferred_reload_class,
pdp11_preferred_output_reload_class, pdp11_secondary_reload,
pdp11_secondary_memory_needed): New function.
(pdp11_return_in_memory): Add other float types.
* config/pdp11/pdp11.h (HARD_REGNO_MODE_OK): Add other float
types.
(SECONDARY_MEMORY_NEEDED, CANNOT_CHANGE_MODE_CLASS): Define.
(PREFERRED_RELOAD_CLASS, SECONDARY_RELOAD_CLASS,
REGISTER_MOVE_COST): Delete.
(BASE_RETURN_VALUE_REG): Add other float types.

From-SVN: r166060

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

index 0bd68104025af6c0dd77c3f4be945a552f887636..68af1080d13dfa5ac9f6d761754c77223fc0fd42 100644 (file)
@@ -1,3 +1,27 @@
+2010-10-29  Paul Koning  <pkoning@equallogic.com>
+
+       * config/pdp11/pdp11-protos.h (pdp11_cannot_change_mode_class,
+       pdp11_secondary_memory_needed): Declare.
+       * config/pdp11/predicates.md (float_operand): New predicate.
+       * config/pdp11/pdp11.md (RETVAL_REGNUM): New constant.
+       (cbranchdf4, movdf): Change predicate.
+       (movsf): Handle FPU register case.
+       (truncdfsf2, extendsfdf2): Add FPU register case.
+       * config/pdp11/pdp11.c (TARGET_SECONDARY_RELOAD,
+       TARGET_REGISTER_MOVE_COST, TARGET_PREFERRED_RELOAD_CLASS,
+       TARGET_PREFERRED_OUTPUT_RELOAD_CLASS): Define.
+       (pdp11_register_move_cost): Update cost matrix.
+       (pdp11_cannot_change_mode_class, pdp11_preferred_reload_class,
+       pdp11_preferred_output_reload_class, pdp11_secondary_reload,
+       pdp11_secondary_memory_needed): New function.
+       (pdp11_return_in_memory): Add other float types.
+       * config/pdp11/pdp11.h (HARD_REGNO_MODE_OK): Add other float
+       types. 
+       (SECONDARY_MEMORY_NEEDED, CANNOT_CHANGE_MODE_CLASS): Define.
+       (PREFERRED_RELOAD_CLASS, SECONDARY_RELOAD_CLASS,
+       REGISTER_MOVE_COST): Delete.
+       (BASE_RETURN_VALUE_REG): Add other float types.
+
 2010-10-29  Nick Clifton<nickc@redhat.com>
 
        * doc/invoke.texi: Document -mam34 and -mtune options.
index 3b0e59a6200ed44e1bd965afd9948dde5b0b644b..a8da5a666bfde96aa6313b3825501da28ff60920 100644 (file)
@@ -31,7 +31,11 @@ extern const char *output_move_quad (rtx *);
 extern const char *output_block_move (rtx *);
 extern const char *output_jump (enum rtx_code, int, int);
 extern void print_operand_address (FILE *, rtx);
-extern int pdp11_register_move_cost (enum reg_class, enum reg_class);
+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);
+
 #endif /* RTX_CODE */
 
 extern void output_ascii (FILE *, const char *, int);
index 6850baafc5cdf86571d3871a592cfccb864e928b..c586b9ccf6dc28d3bee289a0485e0b865e7f1ca4 100644 (file)
@@ -216,7 +216,17 @@ static const struct default_options pdp11_option_optimization_table[] =
 #undef TARGET_TRAMPOLINE_INIT
 #define TARGET_TRAMPOLINE_INIT pdp11_trampoline_init
 
-struct gcc_target targetm = TARGET_INITIALIZER;
+#undef  TARGET_SECONDARY_RELOAD
+#define TARGET_SECONDARY_RELOAD pdp11_secondary_reload
+
+#undef  TARGET_REGISTER_MOVE_COST 
+#define TARGET_REGISTER_MOVE_COST pdp11_register_move_cost
+
+#undef  TARGET_PREFERRED_RELOAD_CLASS
+#define TARGET_PREFERRED_RELOAD_CLASS pdp11_preferred_reload_class
+
+#undef  TARGET_PREFERRED_OUTPUT_RELOAD_CLASS
+#define TARGET_PREFERRED_OUTPUT_RELOAD_CLASS pdp11_preferred_output_reload_class
 \f
 /* Implement TARGET_HANDLE_OPTION.  */
 
@@ -417,7 +427,7 @@ pdp11_output_function_epilogue (FILE *stream, HOST_WIDE_INT size)
        
        /* get ACs */
        for (i = AC5_REGNUM; i >= AC0_REGNUM; i--)
-         if (df_regs_ever_live_p (i) && call_used_regs[i])
+         if (df_regs_ever_live_p (i) && call_used_regs[i])
                via_ac = i;
        
        for (i = AC5_REGNUM; i >= AC0_REGNUM; i--)
@@ -1054,22 +1064,23 @@ static const int move_costs[N_REG_CLASSES][N_REG_CLASSES] =
              /* NO  MUL  GEN  LFPU  NLFPU FPU ALL */
 
 /* NO */     {  0,   0,   0,    0,    0,    0,   0},
-/* MUL */    {  0,   2,   2,   10,   22,   22,  22},
-/* GEN */    {  0,   2,   2,   10,   22,   22,  22},
-/* LFPU */   {  0,  10,  10,    2,    2,    2,  10},
-/* NLFPU */  {  0,  22,  22,    2,    2,    2,  22},
-/* FPU */    {  0,  22,  22,    2,    2,    2,  22},
-/* ALL */    {  0,  22,  22,   10,   22,   22,  22}
+/* MUL */    {  0,   2,   2,   22,   22,   22,  22},
+/* GEN */    {  0,   2,   2,   22,   22,   22,  22},
+/* LFPU */   {  0,  22,  22,    2,    2,    2,  22},
+/* NLFPU */  {  0,  22,  22,    2,   10,   10,  22},
+/* FPU */    {  0,  22,  22,    2,   10,   10,  22},
+/* ALL */    {  0,  22,  22,   22,   22,   22,  22}
 }  ;
 
 
 /* -- note that some moves are tremendously expensive, 
    because they require lots of tricks! do we have to 
    charge the costs incurred by secondary reload class 
-   -- as we do here with 22 -- or not ? */
+   -- as we do here with 10 -- or not ? */
 
-int 
-pdp11_register_move_cost (enum reg_class c1, enum reg_class c2)
+static int 
+pdp11_register_move_cost (enum machine_mode mode ATTRIBUTE_UNUSED,
+                         reg_class_t c1, reg_class_t c2)
 {
     return move_costs[(int)c1][(int)c2];
 }
@@ -1634,6 +1645,108 @@ legitimate_const_double_p (rtx address)
   return 0;
 }
 
+/* Implement CANNOT_CHANGE_MODE_CLASS.  */
+bool
+pdp11_cannot_change_mode_class (enum machine_mode from,
+                               enum machine_mode to,
+                               enum reg_class rclass)
+{
+  /* Also, FPU registers contain a whole float value and the parts of
+     it are not separately accessible.
+
+     So we disallow all mode changes involving FPRs.  */
+  if (FLOAT_MODE_P (from) != FLOAT_MODE_P (to))
+    return true;
+  
+  return reg_classes_intersect_p (FPU_REGS, rclass);
+}
+
+/* TARGET_PREFERRED_RELOAD_CLASS
+
+   Given an rtx X being reloaded into a reg required to be
+   in class CLASS, return the class of reg to actually use.
+   In general this is just CLASS; but on some machines
+   in some cases it is preferable to use a more restrictive class.  
+
+loading is easier into LOAD_FPU_REGS than FPU_REGS! */
+
+static reg_class_t
+pdp11_preferred_reload_class (rtx x, reg_class_t class)
+{
+  if (class == FPU_REGS)
+    return LOAD_FPU_REGS;
+  if (class == ALL_REGS)
+    {
+      if (FLOAT_MODE_P (GET_MODE (x)))
+       return LOAD_FPU_REGS;
+      else
+       return GENERAL_REGS;
+    }
+  return class;
+}
+
+/* TARGET_PREFERRED_OUTPUT_RELOAD_CLASS
+
+   Given an rtx X being reloaded into a reg required to be
+   in class CLASS, return the class of reg to actually use.
+   In general this is just CLASS; but on some machines
+   in some cases it is preferable to use a more restrictive class.  
+
+loading is easier into LOAD_FPU_REGS than FPU_REGS! */
+
+static reg_class_t
+pdp11_preferred_output_reload_class (rtx x, reg_class_t class)
+{
+  if (class == FPU_REGS)
+    return LOAD_FPU_REGS;
+  if (class == ALL_REGS)
+    {
+      if (FLOAT_MODE_P (GET_MODE (x)))
+       return LOAD_FPU_REGS;
+      else
+       return GENERAL_REGS;
+    }
+  return class;
+}
+
+
+/* TARGET_SECONDARY_RELOAD.
+
+   FPU registers AC4 and AC5 (class NO_LOAD_FPU_REGS) require an 
+   intermediate register (AC0-AC3: LOAD_FPU_REGS).  Everything else
+   can be loade/stored directly.  */
+reg_class_t 
+pdp11_secondary_reload (bool in_p ATTRIBUTE_UNUSED,
+                       rtx x,
+                       reg_class_t reload_class,
+                       enum machine_mode reload_mode ATTRIBUTE_UNUSED,
+                       secondary_reload_info *sri ATTRIBUTE_UNUSED)
+{
+  if (reload_class != NO_LOAD_FPU_REGS || GET_CODE (x) != REG ||
+      REGNO_REG_CLASS (REGNO (x)) == LOAD_FPU_REGS)
+    return NO_REGS;
+  
+  return LOAD_FPU_REGS;
+}
+
+/* Target routine to check if register to register move requires memory.
+
+   The answer is yes if we're going between general register and FPU 
+   registers.  The mode doesn't matter in making this check.
+*/
+bool 
+pdp11_secondary_memory_needed (reg_class_t c1, reg_class_t c2, 
+                              enum machine_mode mode ATTRIBUTE_UNUSED)
+{
+  int fromfloat = (c1 == LOAD_FPU_REGS || c1 == NO_LOAD_FPU_REGS || 
+                  c1 == FPU_REGS);
+  int tofloat = (c2 == LOAD_FPU_REGS || c2 == NO_LOAD_FPU_REGS || 
+                c2 == FPU_REGS);
+  
+  return (fromfloat != tofloat);
+}
+
+
 /* 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
    use, and for debugging output, which we don't support with this port either.
@@ -1751,7 +1864,7 @@ pdp11_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED)
      ac0 if DFmode and FPU present - compatibility problem with
      libraries for non-floating point....  */
   return (TYPE_MODE (type) == DImode
-         || (TYPE_MODE (type) == DFmode && ! TARGET_AC0));
+         || (FLOAT_MODE_P (TYPE_MODE (type)) && ! TARGET_AC0));
 }
 
 /* Worker function for TARGET_FUNCTION_VALUE.
@@ -1854,3 +1967,5 @@ pdp11_function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode,
           ? GET_MODE_SIZE (mode)
           : int_size_in_bytes (type));
 }
+
+struct gcc_target targetm = TARGET_INITIALIZER;
index 1b1e713344baea97d8a24b2c7189e9a74ddb3475..08b9d675cdea0af18ca54f7b1d147de054b0de0d 100644 (file)
@@ -215,15 +215,19 @@ extern const struct real_format pdp11_d_format;
     
 
 /* Value is 1 if hard register REGNO can hold a value of machine-mode MODE.
-   On the pdp, the cpu registers can hold any mode - check alignment
+   On the pdp, the cpu registers can hold any mode other than float
+   (because otherwise we may end up being asked to move from CPU to FPU
+   register, which isn't a valid operation on the PDP11).
+   For CPU registers, check alignment.
 
-   FPU can only hold DF - simplifies life!
+   FPU accepts SF and DF but actually holds a DF - simplifies life!
 */
 #define HARD_REGNO_MODE_OK(REGNO, MODE) \
 (((REGNO) <= PC_REGNUM)?                               \
   ((GET_MODE_BITSIZE(MODE) <= 16)                      \
-   || (GET_MODE_BITSIZE(MODE) >= 32 && !((REGNO) & 1)))        \
-  :(MODE) == DFmode)
+   || (GET_MODE_BITSIZE(MODE) >= 32 &&                 \
+       !((REGNO) & 1) && !FLOAT_MODE_P (MODE)))                \
+  :FLOAT_MODE_P (MODE))
     
 
 /* Value is 1 if it is a good idea to tie two pseudo registers
@@ -322,18 +326,9 @@ enum reg_class { NO_REGS, MUL_REGS, GENERAL_REGS, LOAD_FPU_REGS, NO_LOAD_FPU_REG
 
 #define IRA_COVER_CLASSES { GENERAL_REGS, FPU_REGS, LIM_REG_CLASSES }
 
-/* Given an rtx X being reloaded into a reg required to be
-   in class CLASS, return the class of reg to actually use.
-   In general this is just CLASS; but on some machines
-   in some cases it is preferable to use a more restrictive class.  
-
-loading is easier into LOAD_FPU_REGS than FPU_REGS! */
-
-#define PREFERRED_RELOAD_CLASS(X,CLASS)        \
-(((CLASS) != FPU_REGS)?(CLASS):LOAD_FPU_REGS)
-
-#define SECONDARY_RELOAD_CLASS(CLASS,MODE,x)   \
-(((CLASS) == NO_LOAD_FPU_REGS && !(REG_P(x) && LOAD_FPU_REG_P(REGNO(x))))?LOAD_FPU_REGS:NO_REGS)
+/* Hook for testing if memory is needed for moving between registers.  */
+#define SECONDARY_MEMORY_NEEDED(class1, class2, m) \
+  pdp11_secondary_memory_needed (class1, class2, m)
 
 /* Return the maximum number of consecutive registers
    needed to represent mode MODE in a register of class CLASS.  */
@@ -343,6 +338,8 @@ loading is easier into LOAD_FPU_REGS than FPU_REGS! */
   1                                                                    \
 )
 
+#define CANNOT_CHANGE_MODE_CLASS(FROM, TO, CLASS) \
+  pdp11_cannot_change_mode_class (FROM, TO, CLASS)
 \f
 /* Stack layout; function entry, exit and calling.  */
 
@@ -386,7 +383,7 @@ extern int current_first_parm_offset;
    If the precise function being called is known, FUNC is its FUNCTION_DECL;
    otherwise, FUNC is 0.  */
 #define BASE_RETURN_VALUE_REG(MODE) \
- ((MODE) == DFmode ? 8 : 0
+ (FLOAT_MODE_P (MODE) ? AC0_REGNUM : RETVAL_REGNUM
 
 /* 1 if N is a possible register number for function argument passing.
    - not used on pdp */
@@ -674,10 +671,6 @@ extern int may_call_alloca;
 /* #define NO_FUNCTION_CSE */
 
 \f
-/* cost of moving one register class to another */
-#define REGISTER_MOVE_COST(MODE, CLASS1, CLASS2) \
-  pdp11_register_move_cost (CLASS1, CLASS2)
-
 /* Tell emit-rtl.c how to initialize special values on a per-function base.  */
 extern struct rtx_def *cc0_reg_rtx;
 
index 53097b75a775a507104c4806a375d2f208696791..ebedf60c566e9741b5188de2f78424955dfb2d32 100644 (file)
@@ -25,6 +25,7 @@
 (define_constants
   [
    ;; Register numbers
+   (RETVAL_REGNUM        0)
    (FRAME_POINTER_REGNUM  5)
    (STACK_POINTER_REGNUM  6)
    (PC_REGNUM             7)
 (define_expand "cbranchdf4"
   [(set (cc0)
         (compare (match_operand:DF 1 "general_operand")
-                (match_operand:DF 2 "general_operand")))
+                (match_operand:DF 2 "register_or_const0_operand")))
    (set (pc)
        (if_then_else (match_operator 0 "ordered_comparison_operator"
                       [(cc0) (const_int 0)])
 }"
   [(set_attr "length" "2,4,4,6")])
 
-;; do we have to supply all these moves? e.g. to 
-;; NO_LOAD_FPU_REGs ? 
 (define_insn "movdf"
-  [(set (match_operand:DF 0 "general_operand" "=a,fR,a,Q,g")
-        (match_operand:DF 1 "general_operand" "fFR,a,Q,a,g"))]
+  [(set (match_operand:DF 0 "float_operand" "=a,fR,a,Q,g")
+        (match_operand:DF 1 "float_operand" "fFR,a,Q,a,g"))]
   "TARGET_FPU"
   "* if (which_alternative ==0 || which_alternative == 2)
        return \"ldd %1, %0\";
   [(set_attr "length" "2,2,10,10,32")])
 
 (define_insn "movsf"
-  [(set (match_operand:SF 0 "general_operand" "=g,r,g")
-        (match_operand:SF 1 "general_operand" "r,rmF,g"))]
+  [(set (match_operand:SF 0 "float_operand" "=a,fR,a,Q,g")
+        (match_operand:SF 1 "float_operand" "fFR,a,Q,a,g"))]
   "TARGET_FPU"
-  "* return output_move_double (operands);"
-  [(set_attr "length" "16,16,16")])
+  "* if (which_alternative ==0 || which_alternative == 2)
+       return \"{ldcfd|movof} %1, %0\";
+     else if (which_alternative == 1 || which_alternative == 3)
+       return \"{stcdf|movfo} %1, %0\";
+     else 
+       return output_move_double (operands); "
+;; just a guess..
+  [(set_attr "length" "2,2,10,10,16")])
 
 ;; maybe fiddle a bit with move_ratio, then 
 ;; let constraints only accept a register ...
 ;;- truncation instructions
 
 (define_insn  "truncdfsf2"
-  [(set (match_operand:SF 0 "general_operand" "=r,R,Q")
-       (float_truncate:SF (match_operand:DF 1 "register_operand" "a,a,a")))]
+  [(set (match_operand:SF 0 "general_operand" "=f,R,Q")
+       (float_truncate:SF (match_operand:DF 1 "register_operand" "f,a,a")))]
   "TARGET_FPU"
   "* if (which_alternative ==0)
      {
-       output_asm_insn(\"{stcdf|movfo} %1, -(sp)\", operands);
-       output_asm_insn(\"mov (sp)+, %0\", operands);
-       operands[0] = gen_rtx_REG (HImode, REGNO (operands[0])+1);
-       output_asm_insn(\"mov (sp)+, %0\", operands);
        return \"\";
      }
      else if (which_alternative == 1)
      else 
        return \"{stcdf|movfo} %1, %0\";
   "
-  [(set_attr "length" "6,2,4")])
+  [(set_attr "length" "0,2,4")])
 
 
 (define_expand "truncsihi2"
 ;;- sign extension instructions
 
 (define_insn "extendsfdf2"
-  [(set (match_operand:DF 0 "register_operand" "=a,a,a")
-       (float_extend:DF (match_operand:SF 1 "general_operand" "r,R,Q")))]
+  [(set (match_operand:DF 0 "register_operand" "=f,a,a")
+       (float_extend:DF (match_operand:SF 1 "general_operand" "f,R,Q")))]
   "TARGET_FPU"
   "@
-   mov %1, -(sp)\;{ldcfd|movof} (sp)+,%0
+   /* nothing */
    {ldcfd|movof} %1, %0
    {ldcfd|movof} %1, %0"
-  [(set_attr "length" "4,2,4")])
+  [(set_attr "length" "0,2,4")])
 
 ;; does movb sign extend in register-to-register move?
 (define_insn "extendqihi2"
 }"
   [(set_attr "length" "4,8,8,12,4,4,8,6,6,12")])
 
+;; FIXME This definition is wrong, PR/41822
 (define_insn "andhi3"
   [(set (match_operand:HI 0 "general_operand" "=rR,rR,Q,Q")
        (and:HI (match_operand:HI 1 "general_operand" "0,0,0,0")
index 3864bbb7b156683175011d7db00d03c3f44b05ae..3cdf833a5a14684bdd7ae52c66178ca38c068231 100644 (file)
   sh = INTVAL (op);
   return (abs (sh) > 1 && abs (sh) <= 4);
 })
+
+;; Accept anything general-operand accepts, except that registers must
+;; be FPU registers.
+(define_predicate "float_operand"
+  (if_then_else (match_code "reg")
+               (ior 
+                (match_test "REGNO_REG_CLASS (REGNO (op)) == LOAD_FPU_REGS")
+                (match_test "REGNO_REG_CLASS (REGNO (op)) == NO_LOAD_FPU_REGS"))
+               (match_test "general_operand (op, mode)")))