]> oss.titaniummirror.com Git - msp430-gcc.git/blobdiff - gcc/config/pdp11/pdp11.c
Imported gcc-4.4.3
[msp430-gcc.git] / gcc / config / pdp11 / pdp11.c
index 505456550bd72a0e0b718e6e593564f7b64aeaef..f6171356a1255e998c4a2410478c80292a1a4439 100644 (file)
@@ -1,27 +1,28 @@
 /* Subroutines for gcc2 for pdp11.
-   Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2001
-   Free Software Foundation, Inc.
+   Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2001, 2004, 2005,
+   2006, 2007, 2008 Free Software Foundation, Inc.
    Contributed by Michael K. Gschwind (mike@vlsivie.tuwien.ac.at).
 
-This file is part of GNU CC.
+This file is part of GCC.
 
-GNU CC is free software; you can redistribute it and/or modify
+GCC is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
+the Free Software Foundation; either version 3, or (at your option)
 any later version.
 
-GNU CC is distributed in the hope that it will be useful,
+GCC is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
-along with GNU CC; see the file COPYING.  If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA.  */
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
 
 #include "config.h"
 #include "system.h"
+#include "coretypes.h"
+#include "tm.h"
 #include "rtl.h"
 #include "regs.h"
 #include "hard-reg-set.h"
@@ -39,6 +40,7 @@ Boston, MA 02111-1307, USA.  */
 #include "tm_p.h"
 #include "target.h"
 #include "target-def.h"
+#include "df.h"
 
 /*
 #define FPU_REG_P(X)   ((X)>=8 && (X)<14)
@@ -49,14 +51,107 @@ Boston, MA 02111-1307, USA.  */
    defined in tm.h */
 int current_first_parm_offset;
 
+/* Routines to encode/decode pdp11 floats */
+static void encode_pdp11_f (const struct real_format *fmt,
+                           long *, const REAL_VALUE_TYPE *);
+static void decode_pdp11_f (const struct real_format *,
+                           REAL_VALUE_TYPE *, const long *);
+static void encode_pdp11_d (const struct real_format *fmt,
+                           long *, const REAL_VALUE_TYPE *);
+static void decode_pdp11_d (const struct real_format *,
+                           REAL_VALUE_TYPE *, const long *);
+
+/* These two are taken from the corresponding vax descriptors
+   in real.c, changing only the encode/decode routine pointers.  */
+const struct real_format pdp11_f_format =
+  {
+    encode_pdp11_f,
+    decode_pdp11_f,
+    2,
+    1,
+    24,
+    24,
+    -127,
+    127,
+    15,
+    false,
+    false,
+    false,
+    false,
+    false,
+    false,
+    false,
+    false
+  };
+
+const struct real_format pdp11_d_format =
+  {
+    encode_pdp11_d,
+    decode_pdp11_d,
+    2,
+    1,
+    56,
+    56,
+    -127,
+    127,
+    15,
+    false,
+    false,
+    false,
+    false,
+    false,
+    false,
+    false,
+    false
+  };
+
+static void
+encode_pdp11_f (const struct real_format *fmt ATTRIBUTE_UNUSED, long *buf,
+               const REAL_VALUE_TYPE *r)
+{
+  (*vax_f_format.encode) (fmt, buf, r);
+  buf[0] = ((buf[0] >> 16) & 0xffff) | ((buf[0] & 0xffff) << 16);
+}
+
+static void
+decode_pdp11_f (const struct real_format *fmt ATTRIBUTE_UNUSED,
+               REAL_VALUE_TYPE *r, const long *buf)
+{
+  long tbuf;
+  tbuf = ((buf[0] >> 16) & 0xffff) | ((buf[0] & 0xffff) << 16);
+  (*vax_f_format.decode) (fmt, r, &tbuf);
+}
+
+static void
+encode_pdp11_d (const struct real_format *fmt ATTRIBUTE_UNUSED, long *buf,
+               const REAL_VALUE_TYPE *r)
+{
+  (*vax_d_format.encode) (fmt, buf, r);
+  buf[0] = ((buf[0] >> 16) & 0xffff) | ((buf[0] & 0xffff) << 16);
+  buf[1] = ((buf[1] >> 16) & 0xffff) | ((buf[1] & 0xffff) << 16);
+}
+
+static void
+decode_pdp11_d (const struct real_format *fmt ATTRIBUTE_UNUSED,
+               REAL_VALUE_TYPE *r, const long *buf)
+{
+  long tbuf[2];
+  tbuf[0] = ((buf[0] >> 16) & 0xffff) | ((buf[0] & 0xffff) << 16);
+  tbuf[1] = ((buf[1] >> 16) & 0xffff) | ((buf[1] & 0xffff) << 16);
+  (*vax_d_format.decode) (fmt, r, tbuf);
+}
+
 /* This is where the condition code register lives.  */
 /* rtx cc0_reg_rtx; - no longer needed? */
 
-static rtx find_addr_reg PARAMS ((rtx)); 
-static const char *singlemove_string PARAMS ((rtx *));
-static bool pdp11_assemble_integer PARAMS ((rtx, unsigned int, int));
-static void pdp11_output_function_prologue PARAMS ((FILE *, HOST_WIDE_INT));
-static void pdp11_output_function_epilogue PARAMS ((FILE *, HOST_WIDE_INT));
+static bool pdp11_handle_option (size_t, const char *, int);
+static rtx find_addr_reg (rtx); 
+static const char *singlemove_string (rtx *);
+static bool pdp11_assemble_integer (rtx, unsigned int, int);
+static void pdp11_output_function_prologue (FILE *, HOST_WIDE_INT);
+static void pdp11_output_function_epilogue (FILE *, HOST_WIDE_INT);
+static bool pdp11_rtx_costs (rtx, int, int, int *, bool);
+static bool pdp11_return_in_memory (const_tree, const_tree);
 \f
 /* Initialize the GCC target structure.  */
 #undef TARGET_ASM_BYTE_OP
@@ -78,38 +173,59 @@ static void pdp11_output_function_epilogue PARAMS ((FILE *, HOST_WIDE_INT));
 #undef TARGET_ASM_CLOSE_PAREN
 #define TARGET_ASM_CLOSE_PAREN "]"
 
+#undef TARGET_DEFAULT_TARGET_FLAGS
+#define TARGET_DEFAULT_TARGET_FLAGS \
+  (MASK_FPU | MASK_45 | MASK_ABSHI_BUILTIN | TARGET_UNIX_ASM_DEFAULT)
+#undef TARGET_HANDLE_OPTION
+#define TARGET_HANDLE_OPTION pdp11_handle_option
+
+#undef TARGET_RTX_COSTS
+#define TARGET_RTX_COSTS pdp11_rtx_costs
+
+#undef TARGET_RETURN_IN_MEMORY
+#define TARGET_RETURN_IN_MEMORY pdp11_return_in_memory
+
 struct gcc_target targetm = TARGET_INITIALIZER;
 \f
+/* Implement TARGET_HANDLE_OPTION.  */
+
+static bool
+pdp11_handle_option (size_t code, const char *arg ATTRIBUTE_UNUSED,
+                    int value ATTRIBUTE_UNUSED)
+{
+  switch (code)
+    {
+    case OPT_m10:
+      target_flags &= ~(MASK_40 | MASK_45);
+      return true;
+
+    default:
+      return true;
+    }
+}
+
 /* Nonzero if OP is a valid second operand for an arithmetic insn.  */
 
 int
-arith_operand (op, mode)
-     rtx op;
-     enum machine_mode mode;
+arith_operand (rtx op, enum machine_mode mode)
 {
   return (register_operand (op, mode) || GET_CODE (op) == CONST_INT);
 }
 
 int
-const_immediate_operand (op, mode)
-     rtx op;
-     enum machine_mode mode ATTRIBUTE_UNUSED;
+const_immediate_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
 {
   return (GET_CODE (op) == CONST_INT);
 }
 
 int 
-immediate15_operand (op, mode)
-     rtx op;
-     enum machine_mode mode ATTRIBUTE_UNUSED;
+immediate15_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
 {
     return (GET_CODE (op) == CONST_INT && ((INTVAL (op) & 0x8000) == 0x0000));
 }
 
 int
-expand_shift_operand (op, mode)
-  rtx op;
-  enum machine_mode mode ATTRIBUTE_UNUSED;
+expand_shift_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
 {
     return (GET_CODE (op) == CONST_INT 
            && abs (INTVAL(op)) > 1 
@@ -128,16 +244,14 @@ expand_shift_operand (op, mode)
 #ifdef TWO_BSD
 
 static void
-pdp11_output_function_prologue (stream, size)
-     FILE *stream;
-     HOST_WIDE_INT size;
+pdp11_output_function_prologue (FILE *stream, HOST_WIDE_INT size)
 {                                                             
   fprintf (stream, "\tjsr      r5, csv\n");
   if (size)
     {
       fprintf (stream, "\t/*abuse empty parameter slot for locals!*/\n");
       if (size > 2)
-       fprintf(stream, "\tsub $%d, sp\n", size - 2);
+       asm_fprintf (stream, "\tsub $%#wo, sp\n", size - 2);
 
     }
 }
@@ -145,16 +259,15 @@ pdp11_output_function_prologue (stream, size)
 #else  /* !TWO_BSD */
 
 static void
-pdp11_output_function_prologue (stream, size)
-     FILE *stream;
-     HOST_WIDE_INT size;
+pdp11_output_function_prologue (FILE *stream, HOST_WIDE_INT size)
 {                                                             
     HOST_WIDE_INT fsize = ((size) + 1) & ~1;
     int regno;
     int via_ac = -1;
 
     fprintf (stream,
-            "\n\t;     /* function prologue %s*/\n", current_function_name);
+            "\n\t;     /* function prologue %s*/\n",
+            current_function_name ());
 
     /* if we are outputting code for main, 
        the switch FPU to right mode if TARGET_FPU */
@@ -168,8 +281,8 @@ pdp11_output_function_prologue (stream, size)
     
     if (frame_pointer_needed)                                  
     {                                                          
-       fprintf(stream, "\tmov fp, -(sp)\n");                   
-       fprintf(stream, "\tmov sp, fp\n");                              
+       fprintf(stream, "\tmov r5, -(sp)\n");                   
+       fprintf(stream, "\tmov sp, r5\n");                              
     }                                                          
     else                                                               
     {                                                          
@@ -178,11 +291,11 @@ pdp11_output_function_prologue (stream, size)
 
     /* make frame */
     if (fsize)                                                 
-       fprintf (stream, "\tsub $%o, sp\n", fsize);                     
+       asm_fprintf (stream, "\tsub $%#wo, sp\n", fsize);
 
     /* save CPU registers  */
     for (regno = 0; regno < 8; regno++)                                
-       if (regs_ever_live[regno] && ! call_used_regs[regno])   
+      if (df_regs_ever_live_p (regno) && ! call_used_regs[regno])      
            if (! ((regno == FRAME_POINTER_REGNUM)                      
                   && frame_pointer_needed))                            
                fprintf (stream, "\tmov %s, -(sp)\n", reg_names[regno]);        
@@ -195,24 +308,23 @@ pdp11_output_function_prologue (stream, size)
     {
        /* ac0 - ac3 */                                         
        if (LOAD_FPU_REG_P(regno)
-           && regs_ever_live[regno] 
+           && df_regs_ever_live_p (regno) 
            && ! call_used_regs[regno])
        {
-           fprintf (stream, "\tfstd %s, -(sp)\n", reg_names[regno]);
+           fprintf (stream, "\tstd %s, -(sp)\n", reg_names[regno]);
            via_ac = regno;
        }
        
        /* maybe make ac4, ac5 call used regs?? */
        /* ac4 - ac5 */
        if (NO_LOAD_FPU_REG_P(regno)
-           && regs_ever_live[regno]
+           && df_regs_ever_live_p (regno)
            && ! call_used_regs[regno])
        {
-           if (via_ac == -1)
-               abort();
-           
-           fprintf (stream, "\tfldd %s, %s\n", reg_names[regno], reg_names[via_ac]);
-           fprintf (stream, "\tfstd %s, -(sp)\n", reg_names[via_ac]);
+         gcc_assert (via_ac != -1);
+         fprintf (stream, "\tldd %s, %s\n",
+                  reg_names[regno], reg_names[via_ac]);
+         fprintf (stream, "\tstd %s, -(sp)\n", reg_names[via_ac]);
        }
     }
 
@@ -243,9 +355,8 @@ pdp11_output_function_prologue (stream, size)
 #ifdef TWO_BSD
 
 static void
-pdp11_output_function_epilogue (stream, size)
-     FILE *stream;
-     HOST_WIDE_INT size ATTRIBUTE_UNUSED;
+pdp11_output_function_epilogue (FILE *stream,
+                               HOST_WIDE_INT size ATTRIBUTE_UNUSED)
 {                                                              
   fprintf (stream, "\t/* SP ignored by cret? */\n");
   fprintf (stream, "\tjmp cret\n");
@@ -254,9 +365,7 @@ pdp11_output_function_epilogue (stream, size)
 #else  /* !TWO_BSD */
 
 static void
-pdp11_output_function_epilogue (stream, size)
-     FILE *stream;
-     HOST_WIDE_INT size;
+pdp11_output_function_epilogue (FILE *stream, HOST_WIDE_INT size)
 {                                                              
     HOST_WIDE_INT fsize = ((size) + 1) & ~1;
     int i, j, k;
@@ -268,24 +377,26 @@ pdp11_output_function_epilogue (stream, size)
     if (frame_pointer_needed)                                  
     {                                                          
        /* hope this is safe - m68k does it also .... */                
-       regs_ever_live[FRAME_POINTER_REGNUM] = 0;                       
+        df_set_regs_ever_live (FRAME_POINTER_REGNUM, false);
                                                                
        for (i =7, j = 0 ; i >= 0 ; i--)                                
-           if (regs_ever_live[i] && ! call_used_regs[i])               
+         if (df_regs_ever_live_p (i) && ! call_used_regs[i])           
                j++;
        
        /* remember # of pushed bytes for CPU regs */
        k = 2*j;
        
+       /* change fp -> r5 due to the compile error on libgcc2.c */
        for (i =7 ; i >= 0 ; i--)                                       
-           if (regs_ever_live[i] && ! call_used_regs[i])               
-               fprintf(stream, "\tmov %o(fp), %s\n",-fsize-2*j--, reg_names[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]);
 
        /* get ACs */                                           
        via_ac = FIRST_PSEUDO_REGISTER -1;
        
        for (i = FIRST_PSEUDO_REGISTER; i > 7; i--)
-           if (regs_ever_live[i] && ! call_used_regs[i])
+         if (df_regs_ever_live_p (i) && ! call_used_regs[i])
            {
                via_ac = i;
                k += 8;
@@ -294,28 +405,29 @@ pdp11_output_function_epilogue (stream, size)
        for (i = FIRST_PSEUDO_REGISTER; i > 7; i--)
        {
            if (LOAD_FPU_REG_P(i)
-               && regs_ever_live[i]
+               && df_regs_ever_live_p (i)
                && ! call_used_regs[i])
            {
-               fprintf(stream, "\tfldd %o(fp), %s\n", -fsize-k, reg_names[i]);
+               fprintf(stream, "\tldd %#" HOST_WIDE_INT_PRINT "o(r5), %s\n",
+                       (-fsize-k)&0xffff, reg_names[i]);
                k -= 8;
            }
            
            if (NO_LOAD_FPU_REG_P(i)
-               && regs_ever_live[i]
+               && df_regs_ever_live_p (i)
                && ! call_used_regs[i])
            {
-               if (! LOAD_FPU_REG_P(via_ac))
-                   abort();
+               gcc_assert (LOAD_FPU_REG_P(via_ac));
                    
-               fprintf(stream, "\tfldd %o(fp), %s\n", -fsize-k, reg_names[via_ac]);
-               fprintf(stream, "\tfstd %s, %s\n", reg_names[via_ac], reg_names[i]);
+               fprintf(stream, "\tldd %#" HOST_WIDE_INT_PRINT "o(r5), %s\n",
+                       (-fsize-k)&0xffff, reg_names[via_ac]);
+               fprintf(stream, "\tstd %s, %s\n", reg_names[via_ac], reg_names[i]);
                k -= 8;
            }
        }
        
-       fprintf(stream, "\tmov fp, sp\n");                              
-       fprintf (stream, "\tmov (sp)+, fp\n");                          
+       fprintf(stream, "\tmov r5, sp\n");                              
+       fprintf (stream, "\tmov (sp)+, r5\n");                          
     }                                                          
     else                                                               
     {             
@@ -323,34 +435,34 @@ pdp11_output_function_epilogue (stream, size)
        
        /* get ACs */
        for (i = FIRST_PSEUDO_REGISTER; i > 7; i--)
-           if (regs_ever_live[i] && call_used_regs[i])
+         if (df_regs_ever_live_p (i) && call_used_regs[i])
                via_ac = i;
        
        for (i = FIRST_PSEUDO_REGISTER; i > 7; i--)
        {
            if (LOAD_FPU_REG_P(i)
-               && regs_ever_live[i]
+               && df_regs_ever_live_p (i)
                && ! call_used_regs[i])
-             fprintf(stream, "\tfldd (sp)+, %s\n", reg_names[i]);
+             fprintf(stream, "\tldd (sp)+, %s\n", reg_names[i]);
            
            if (NO_LOAD_FPU_REG_P(i)
-               && regs_ever_live[i]
+               && df_regs_ever_live_p (i)
                && ! call_used_regs[i])
            {
-               if (! LOAD_FPU_REG_P(via_ac))
-                   abort();
+               gcc_assert (LOAD_FPU_REG_P(via_ac));
                    
-               fprintf(stream, "\tfldd (sp)+, %s\n", reg_names[via_ac]);
-               fprintf(stream, "\tfstd %s, %s\n", reg_names[via_ac], reg_names[i]);
+               fprintf(stream, "\tldd (sp)+, %s\n", reg_names[via_ac]);
+               fprintf(stream, "\tstd %s, %s\n", reg_names[via_ac], reg_names[i]);
            }
        }
 
        for (i=7; i >= 0; i--)                                  
-           if (regs_ever_live[i] && !call_used_regs[i])                
+         if (df_regs_ever_live_p (i) && !call_used_regs[i])            
                fprintf(stream, "\tmov (sp)+, %s\n", reg_names[i]);     
                                                                
        if (fsize)                                              
-           fprintf((stream), "\tadd $%o, sp\n", fsize);                
+           fprintf((stream), "\tadd $%#" HOST_WIDE_INT_PRINT "o, sp\n",
+                   (fsize)&0xffff);                    
     }                  
                                        
     fprintf (stream, "\trts pc\n");                                    
@@ -362,8 +474,7 @@ pdp11_output_function_epilogue (stream, size)
 /* Return the best assembler insn template
    for moving operands[1] into operands[0] as a fullword.  */
 static const char *
-singlemove_string (operands)
-     rtx *operands;
+singlemove_string (rtx *operands)
 {
   if (operands[1] != const0_rtx)
     return "mov %1,%0";
@@ -376,8 +487,7 @@ singlemove_string (operands)
    with operands OPERANDS.  */
 
 const char *
-output_move_double (operands)
-     rtx *operands;
+output_move_double (rtx *operands)
 {
   enum { REGOP, OFFSOP, MEMOP, PUSHOP, POPOP, CNSTOP, RNDOP } optype0, optype1;
   rtx latehalf[2];
@@ -400,10 +510,11 @@ output_move_double (operands)
 
   if (REG_P (operands[1]))
     optype1 = REGOP;
-  else if (CONSTANT_P (operands[1]))
+  else if (CONSTANT_P (operands[1])
 #if 0
-          || GET_CODE (operands[1]) == CONST_DOUBLE)
+          || GET_CODE (operands[1]) == CONST_DOUBLE
 #endif
+          )
     optype1 = CNSTOP;
   else if (offsettable_memref_p (operands[1]))
     optype1 = OFFSOP;
@@ -420,8 +531,7 @@ output_move_double (operands)
      supposed to allow to happen.  Abort if we get one,
      because generating code for these cases is painful.  */
 
-  if (optype0 == RNDOP || optype1 == RNDOP)
-    abort ();
+  gcc_assert (optype0 != RNDOP && optype1 != RNDOP);
 
   /* If one operand is decrementing and one is incrementing
      decrement the former register explicitly
@@ -481,11 +591,9 @@ output_move_double (operands)
            latehalf[1] = GEN_INT (INTVAL(operands[1]) >> 16);
            operands[1] = GEN_INT (INTVAL(operands[1]) & 0xff);
        }
-      else if (GET_CODE (operands[1]) == CONST_DOUBLE)
-       {
-           /* immediate 32 bit values not allowed */
-           abort();
-       }
+       else
+         /* immediate 32-bit values not allowed */
+         gcc_assert (GET_CODE (operands[1]) != CONST_DOUBLE);
     }
   else
     latehalf[1] = operands[1];
@@ -554,14 +662,13 @@ output_move_double (operands)
    with operands OPERANDS.  */
 
 const char *
-output_move_quad (operands)
-     rtx *operands;
+output_move_quad (rtx *operands)
 {
   enum { REGOP, OFFSOP, MEMOP, PUSHOP, POPOP, CNSTOP, RNDOP } optype0, optype1;
   rtx latehalf[2];
   rtx addreg0 = 0, addreg1 = 0;
 
-  output_asm_insn(";; movdi/df: %1 -> %0", operands);
+  output_asm_insn(";/* movdi/df: %1 -> %0 */", operands);
   
   if (REG_P (operands[0]))
     optype0 = REGOP;
@@ -596,15 +703,13 @@ output_move_quad (operands)
      supposed to allow to happen.  Abort if we get one,
      because generating code for these cases is painful.  */
 
-  if (optype0 == RNDOP || optype1 == RNDOP)
-    abort ();
+  gcc_assert (optype0 != RNDOP && optype1 != RNDOP);
   
   /* check if we move a CPU reg to an FPU reg, or vice versa! */
   if (optype0 == REGOP && optype1 == REGOP)
       /* bogus - 64 bit cannot reside in CPU! */
-      if (CPU_REG_P(REGNO(operands[0]))
-         || CPU_REG_P (REGNO(operands[1])))
-         abort();
+      gcc_assert (!CPU_REG_P(REGNO(operands[0]))
+                 && !CPU_REG_P (REGNO(operands[1])));
   
   if (optype0 == REGOP || optype1 == REGOP)
   {
@@ -620,11 +725,10 @@ output_move_quad (operands)
       {
          if (GET_CODE(operands[1]) == CONST_DOUBLE)
          {
-             union { double d; int i[2]; } u;
-             u.i[0] = CONST_DOUBLE_LOW (operands[1]); 
-             u.i[1] = CONST_DOUBLE_HIGH (operands[1]); 
-             
-             if (u.d == 0.0)
+             REAL_VALUE_TYPE r;
+             REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]);
+
+             if (REAL_VALUES_EQUAL (r, dconst0))
                  return "{clrd|clrf} %0";
          }
              
@@ -687,29 +791,19 @@ output_move_quad (operands)
     {
       if (GET_CODE (operands[1]) == CONST_DOUBLE)
        {
-           /* floats only. not yet supported!
-
-            -- compute it into PDP float format, - internally,
-            just use IEEE and ignore possible problems ;-)
-
-            we might get away with it !!!! */
-
-           abort();
-           
-#ifndef HOST_WORDS_BIG_ENDIAN
-         latehalf[1] = GEN_INT (CONST_DOUBLE_LOW (operands[1]));
-         operands[1] = GEN_INT (CONST_DOUBLE_HIGH (operands[1]));
-#else /* HOST_WORDS_BIG_ENDIAN */
-         latehalf[1] = GEN_INT (CONST_DOUBLE_HIGH (operands[1]));
-         operands[1] = GEN_INT (CONST_DOUBLE_LOW (operands[1]));
-#endif /* HOST_WORDS_BIG_ENDIAN */
+         REAL_VALUE_TYPE r;
+         long dval[2];
+         REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]);
+         REAL_VALUE_TO_TARGET_DOUBLE (r, dval);
+         latehalf[1] = GEN_INT (dval[1]);
+         operands[1] = GEN_INT (dval[0]);
        }
       else if (GET_CODE(operands[1]) == CONST_INT)
        {
-         latehalf[1] = GEN_INT (0);
+         latehalf[1] = const0_rtx;
        }
       else
-       abort();
+       gcc_unreachable ();
     }
   else
     latehalf[1] = operands[1];
@@ -780,8 +874,7 @@ output_move_quad (operands)
    ADDR can be effectively incremented by incrementing REG.  */
 
 static rtx
-find_addr_reg (addr)
-     rtx addr;
+find_addr_reg (rtx addr)
 {
   while (GET_CODE (addr) == PLUS)
     {
@@ -801,10 +894,7 @@ find_addr_reg (addr)
 \f
 /* Output an ascii string.  */
 void
-output_ascii (file, p, size)
-     FILE *file;
-     const char *p;
-     int size;
+output_ascii (FILE *file, const char *p, int size)
 {
   int i;
 
@@ -817,7 +907,7 @@ output_ascii (file, p, size)
       register int c = p[i];
       if (c < 0)
        c += 256;
-      fprintf (file, "%o", c);
+      fprintf (file, "%#o", c);
       if (i < size - 1)
        putc (',', file);
     }
@@ -828,9 +918,7 @@ output_ascii (file, p, size)
 /* --- stole from out-vax, needs changes */
 
 void
-print_operand_address (file, addr)
-     FILE *file;
-     register rtx addr;
+print_operand_address (FILE *file, register rtx addr)
 {
   register rtx reg1, reg2, breg, ireg;
   rtx offset;
@@ -851,10 +939,12 @@ print_operand_address (file, addr)
       fprintf (file, "(%s)", reg_names[REGNO (addr)]);
       break;
 
+    case PRE_MODIFY:
     case PRE_DEC:
       fprintf (file, "-(%s)", reg_names[REGNO (XEXP (addr, 0))]);
       break;
 
+    case POST_MODIFY:
     case POST_INC:
       fprintf (file, "(%s)+", reg_names[REGNO (XEXP (addr, 0))]);
       break;
@@ -907,7 +997,7 @@ print_operand_address (file, addr)
        }
       if (offset != 0)
        {
-         if (addr != 0) abort ();
+         gcc_assert (addr == 0);
          addr = offset;
        }
       if (reg1 != 0 && GET_CODE (reg1) == MULT)
@@ -934,17 +1024,15 @@ print_operand_address (file, addr)
        output_address (addr);
       if (breg != 0)
        {
-         if (GET_CODE (breg) != REG)
-           abort ();
+         gcc_assert (GET_CODE (breg) == REG);
          fprintf (file, "(%s)", reg_names[REGNO (breg)]);
        }
       if (ireg != 0)
        {
          if (GET_CODE (ireg) == MULT)
            ireg = XEXP (ireg, 0);
-         if (GET_CODE (ireg) != REG)
-           abort ();
-         abort();
+         gcc_assert (GET_CODE (ireg) == REG);
+         gcc_unreachable(); /* ??? */
          fprintf (file, "[%s]", reg_names[REGNO (ireg)]);
        }
       break;
@@ -958,10 +1046,7 @@ print_operand_address (file, addr)
    pdp-specific version of output_addr_const.  */
 
 static bool
-pdp11_assemble_integer (x, size, aligned_p)
-     rtx x;
-     unsigned int size;
-     int aligned_p;
+pdp11_assemble_integer (rtx x, unsigned int size, int aligned_p)
 {
   if (aligned_p)
     switch (size)
@@ -984,7 +1069,7 @@ pdp11_assemble_integer (x, size, aligned_p)
 
 /* register move costs, indexed by regs */
 
-static int move_costs[N_REG_CLASSES][N_REG_CLASSES] = 
+static const int move_costs[N_REG_CLASSES][N_REG_CLASSES] = 
 {
              /* NO  MUL  GEN  LFPU  NLFPU FPU ALL */
 
@@ -1004,16 +1089,121 @@ static int move_costs[N_REG_CLASSES][N_REG_CLASSES] =
    -- as we do here with 22 -- or not ? */
 
 int 
-register_move_cost(c1, c2)
-  enum reg_class c1, c2;
+register_move_cost(enum reg_class c1, enum reg_class c2)
 {
     return move_costs[(int)c1][(int)c2];
 }
 
+static bool
+pdp11_rtx_costs (rtx x, int code, int outer_code ATTRIBUTE_UNUSED, int *total,
+                bool speed ATTRIBUTE_UNUSED)
+{
+  switch (code)
+    {
+    case CONST_INT:
+      if (INTVAL (x) == 0 || INTVAL (x) == -1 || INTVAL (x) == 1)
+       {
+         *total = 0;
+         return true;
+       }
+      /* FALLTHRU */
+
+    case CONST:
+    case LABEL_REF:
+    case SYMBOL_REF:
+      /* Twice as expensive as REG.  */
+      *total = 2;
+      return true;
+
+    case CONST_DOUBLE:
+      /* Twice (or 4 times) as expensive as 16 bit.  */
+      *total = 4;
+      return true;
+
+    case MULT:
+      /* ??? There is something wrong in MULT because MULT is not 
+         as cheap as total = 2 even if we can shift!  */
+      /* If optimizing for size make mult etc cheap, but not 1, so when 
+         in doubt the faster insn is chosen.  */
+      if (optimize_size)
+        *total = COSTS_N_INSNS (2);
+      else
+        *total = COSTS_N_INSNS (11);
+      return false;
+
+    case DIV:
+      if (optimize_size)
+        *total = COSTS_N_INSNS (2);
+      else
+        *total = COSTS_N_INSNS (25);
+      return false;
+
+    case MOD:
+      if (optimize_size)
+        *total = COSTS_N_INSNS (2);
+      else
+        *total = COSTS_N_INSNS (26);
+      return false;
+
+    case ABS:
+      /* Equivalent to length, so same for optimize_size.  */
+      *total = COSTS_N_INSNS (3);
+      return false;
+
+    case ZERO_EXTEND:
+      /* Only used for qi->hi.  */
+      *total = COSTS_N_INSNS (1);
+      return false;
+
+    case SIGN_EXTEND:
+      if (GET_MODE (x) == HImode)
+       *total = COSTS_N_INSNS (1);
+      else if (GET_MODE (x) == SImode)
+       *total = COSTS_N_INSNS (6);
+      else
+       *total = COSTS_N_INSNS (2);
+      return false;
+
+    case ASHIFT:
+    case LSHIFTRT:
+    case ASHIFTRT:
+      if (optimize_size)
+        *total = COSTS_N_INSNS (1);
+      else if (GET_MODE (x) ==  QImode)
+        {
+          if (GET_CODE (XEXP (x, 1)) != CONST_INT)
+           *total = COSTS_N_INSNS (8); /* worst case */
+          else
+           *total = COSTS_N_INSNS (INTVAL (XEXP (x, 1)));
+        }
+      else if (GET_MODE (x) == HImode)
+        {
+          if (GET_CODE (XEXP (x, 1)) == CONST_INT)
+            {
+             if (abs (INTVAL (XEXP (x, 1))) == 1)
+                *total = COSTS_N_INSNS (1);
+              else
+               *total = COSTS_N_INSNS (2.5 + 0.5 * INTVAL (XEXP (x, 1)));
+            }
+          else
+            *total = COSTS_N_INSNS (10); /* worst case */
+        }
+      else if (GET_MODE (x) == SImode)
+        {
+          if (GET_CODE (XEXP (x, 1)) == CONST_INT)
+           *total = COSTS_N_INSNS (2.5 + 0.5 * INTVAL (XEXP (x, 1)));
+          else /* worst case */
+            *total = COSTS_N_INSNS (18);
+        }
+      return false;
+
+    default:
+      return false;
+    }
+}
+
 const char *
-output_jump(pos, neg, length)
-  const char *pos, *neg;
-  int length;
+output_jump (const char *pos, const char *neg, int length)
 {
     static int x = 0;
     
@@ -1048,15 +1238,13 @@ output_jump(pos, neg, length)
        
       default:
        
-       abort();
+       gcc_unreachable ();
     }
     
 }
 
 void
-notice_update_cc_on_set(exp, insn)
-  rtx exp;
-  rtx insn ATTRIBUTE_UNUSED;
+notice_update_cc_on_set(rtx exp, rtx insn ATTRIBUTE_UNUSED)
 {
     if (GET_CODE (SET_DEST (exp)) == CC0)
     { 
@@ -1126,9 +1314,7 @@ notice_update_cc_on_set(exp, insn)
 
 
 int
-simple_memory_operand(op, mode)
-     rtx op;
-     enum machine_mode mode ATTRIBUTE_UNUSED;
+simple_memory_operand(rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
 {
     rtx addr;
 
@@ -1201,8 +1387,7 @@ simple_memory_operand(op, mode)
 
  
 const char *
-output_block_move(operands)
-  rtx *operands;
+output_block_move(rtx *operands)
 {
     static int count = 0;
     char buf[200];
@@ -1439,62 +1624,8 @@ output_block_move(operands)
     return "";
 }
 
-/* for future use */
 int
-comparison_operator_index(op)
-  rtx op;
-{
-    switch (GET_CODE(op))
-    {
-      case NE:
-       return 0;
-       
-      case EQ:
-       return 1;
-       
-      case GE:
-       return 2;
-       
-      case GT:
-       return 3;
-       
-      case LE:
-       return 4;
-       
-      case LT:
-       return 5;
-       
-      case GEU:
-       return 6;
-       
-      case GTU:
-       return 7;
-
-      case LEU:
-       return 8;
-       
-      case LTU:
-       return 9;
-       
-      default:
-       return -1;
-    }
-}    
-       
-/* tests whether the rtx is a comparison operator */
-int
-comp_operator (op, mode)
-  rtx op;
-  enum machine_mode mode ATTRIBUTE_UNUSED;
-{
-    return comparison_operator_index(op) >= 0;
-}
-
-    
-int
-legitimate_address_p (mode, address)
-  enum machine_mode mode;
-  rtx address;
+legitimate_address_p (enum machine_mode mode, rtx address)
 {
 /* #define REG_OK_STRICT */
     GO_IF_LEGITIMATE_ADDRESS(mode, address, win);
@@ -1507,15 +1638,28 @@ legitimate_address_p (mode, address)
 /* #undef REG_OK_STRICT */
 }
 
+/* This function checks whether a real value can be encoded as
+   a literal, i.e., addressing mode 27.  In that mode, real values
+   are one word values, so the remaining 48 bits have to be zero.  */
+int
+legitimate_const_double_p (rtx address)
+{
+  REAL_VALUE_TYPE r;
+  long sval[2];
+  REAL_VALUE_FROM_CONST_DOUBLE (r, address);
+  REAL_VALUE_TO_TARGET_DOUBLE (r, sval);
+  if ((sval[0] & 0xffff) == 0 && sval[1] == 0)
+    return 1;
+  return 0;
+}
+
 /* 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.
    So this copy should get called whenever needed.
 */
 void
-output_addr_const_pdp11 (file, x)
-     FILE *file;
-     rtx x;
+output_addr_const_pdp11 (FILE *file, rtx x)
 {
   char buf[256];
 
@@ -1523,10 +1667,8 @@ output_addr_const_pdp11 (file, x)
   switch (GET_CODE (x))
     {
     case PC:
-      if (flag_pic)
-       putc ('.', file);
-      else
-       abort ();
+      gcc_assert (flag_pic);
+      putc ('.', file);
       break;
 
     case SYMBOL_REF:
@@ -1546,7 +1688,7 @@ output_addr_const_pdp11 (file, x)
     case CONST_INT:
       /* Should we check for constants which are too big?  Maybe cutting
         them off to 16 bits is OK?  */
-      fprintf (file, "%ho", (unsigned short) INTVAL (x));
+      fprintf (file, "%#ho", (unsigned short) INTVAL (x));
       break;
 
     case CONST:
@@ -1559,10 +1701,8 @@ output_addr_const_pdp11 (file, x)
       if (GET_MODE (x) == VOIDmode)
        {
          /* We can use %o if the number is one word and positive.  */
-         if (CONST_DOUBLE_HIGH (x))
-           abort (); /* Should we just silently drop the high part?  */
-         else
-           fprintf (file, "%ho", (unsigned short) CONST_DOUBLE_LOW (x));
+         gcc_assert (!CONST_DOUBLE_HIGH (x));
+         fprintf (file, "%#ho", (unsigned short) CONST_DOUBLE_LOW (x));
        }
       else
        /* We can't handle floating point constants;
@@ -1571,7 +1711,7 @@ output_addr_const_pdp11 (file, x)
       break;
 
     case PLUS:
-      /* Some assemblers need integer constants to appear last (eg masm).  */
+      /* Some assemblers need integer constants to appear last (e.g. masm).  */
       if (GET_CODE (XEXP (x, 0)) == CONST_INT)
        {
          output_addr_const_pdp11 (file, XEXP (x, 1));
@@ -1617,3 +1757,18 @@ output_addr_const_pdp11 (file, x)
       output_operand_lossage ("invalid expression as operand");
     }
 }
+
+/* Worker function for TARGET_RETURN_IN_MEMORY.  */
+
+static bool
+pdp11_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED)
+{
+  /* Should probably return DImode and DFmode in memory, lest
+     we fill up all regs!
+
+     have to, else we crash - exception: maybe return result in 
+     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));
+}