OSDN Git Service

i * libgcc1-test.c, libgcc1.c, config/i386/perform.h: Delete file.
[pf3gnuchains/gcc-fork.git] / gcc / config / pdp11 / pdp11.c
index 38f1c86..b298ea0 100644 (file)
@@ -1,12 +1,13 @@
 /* Subroutines for gcc2 for pdp11.
-   Copyright (C) 1994 Free Software Foundation, Inc.
+   Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999
+   Free Software Foundation, Inc.
    Contributed by Michael K. Gschwind (mike@vlsivie.tuwien.ac.at).
 
 This file is part of GNU CC.
 
 GNU CC 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 1, or (at your option)
+the Free Software Foundation; either version 2, or (at your option)
 any later version.
 
 GNU CC is distributed in the hope that it will be useful,
@@ -19,19 +20,21 @@ 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.  */
 
-#ifndef FILE
-#include <stdio.h>
-#endif
 #include "config.h"
+#include "system.h"
 #include "rtl.h"
 #include "regs.h"
 #include "hard-reg-set.h"
 #include "real.h"
 #include "insn-config.h"
 #include "conditions.h"
-#include "insn-flags.h"
+#include "function.h"
 #include "output.h"
 #include "insn-attr.h"
+#include "flags.h"
+#include "recog.h"
+#include "tree.h"
+#include "tm_p.h"
 
 /*
 #define FPU_REG_P(X)   ((X)>=8 && (X)<14)
@@ -45,7 +48,8 @@ int current_first_parm_offset;
 /* This is where the condition code register lives.  */
 /* rtx cc0_reg_rtx; - no longer needed? */
 
-static rtx find_addr_reg (); 
+static rtx find_addr_reg PARAMS ((rtx)); 
+static const char *singlemove_string PARAMS ((rtx *)); 
 
 /* Nonzero if OP is a valid second operand for an arithmetic insn.  */
 
@@ -60,7 +64,7 @@ arith_operand (op, mode)
 int
 const_immediate_operand (op, mode)
      rtx op;
-     enum machine_mode mode;
+     enum machine_mode mode ATTRIBUTE_UNUSED;
 {
   return (GET_CODE (op) == CONST_INT);
 }
@@ -68,7 +72,7 @@ const_immediate_operand (op, mode)
 int 
 immediate15_operand (op, mode)
      rtx op;
-     enum machine_mode mode;
+     enum machine_mode mode ATTRIBUTE_UNUSED;
 {
     return (GET_CODE (op) == CONST_INT && ((INTVAL (op) & 0x8000) == 0x0000));
 }
@@ -76,7 +80,7 @@ immediate15_operand (op, mode)
 int
 expand_shift_operand (op, mode)
   rtx op;
-  enum machine_mode mode;
+  enum machine_mode mode ATTRIBUTE_UNUSED;
 {
     return (GET_CODE (op) == CONST_INT 
            && abs (INTVAL(op)) > 1 
@@ -97,12 +101,8 @@ output_function_prologue(stream, size)
   FILE *stream;
   int size;
 {                                                             
-    extern char call_used_regs[];                                      
-    extern int frame_pointer_needed;                           
-
     int fsize = ((size) + 1) & ~1;                                     
-    int regno, nregs, i;                                               
-    int offset = 0;
+    int regno;
 
     int via_ac = -1;
     
@@ -110,8 +110,7 @@ output_function_prologue(stream, size)
 
     /* if we are outputting code for main, 
        the switch FPU to right mode if TARGET_FPU */
-    if ( (strcmp ("main", current_function_name) == 0)
-        && TARGET_FPU)
+    if (MAIN_NAME_P (DECL_NAME (current_function_decl)) && TARGET_FPU)
     {
        fprintf(stream, "\t;/* switch cpu to double float, single integer */\n");
        fprintf(stream, "\tsetd\n");
@@ -130,7 +129,7 @@ output_function_prologue(stream, size)
 
     /* make frame */
     if (fsize)                                                 
-       fprintf (stream, "\tsub $%d, sp\n", fsize);                     
+       fprintf (stream, "\tsub $%o, sp\n", fsize);                     
 
     /* save CPU registers  */
     for (regno = 0; regno < 8; regno++)                                
@@ -196,11 +195,8 @@ output_function_epilogue(stream, size)
   FILE *stream;
   int size;
 {                                                              
-    extern char call_used_regs[];                                      
-    extern int may_call_alloca;
-
     int fsize = ((size) + 1) & ~1;                                     
-    int nregs, regno, i, j, k, adjust_fp;                              
+    int i, j, k;
 
     int via_ac;
     
@@ -220,7 +216,7 @@ output_function_epilogue(stream, size)
        
        for (i =7 ; i >= 0 ; i--)                                       
            if (regs_ever_live[i] && ! call_used_regs[i])               
-               fprintf(stream, "\tmov %d(fp), %s\n",-fsize-2*j--, reg_names[i]);
+               fprintf(stream, "\tmov %o(fp), %s\n",-fsize-2*j--, reg_names[i]);
 
        /* get ACs */                                           
        via_ac = FIRST_PSEUDO_REGISTER -1;
@@ -238,7 +234,7 @@ output_function_epilogue(stream, size)
                && regs_ever_live[i]
                && ! call_used_regs[i])
            {
-               fprintf(stream, "\tfldd %d(fp), %s\n", -fsize-k, reg_names[i]);
+               fprintf(stream, "\tfldd %o(fp), %s\n", -fsize-k, reg_names[i]);
                k -= 8;
            }
            
@@ -249,7 +245,7 @@ output_function_epilogue(stream, size)
                if (! LOAD_FPU_REG_P(via_ac))
                    abort();
                    
-               fprintf(stream, "\tfldd %d(fp), %s\n", -fsize-k, reg_names[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]);
                k -= 8;
            }
@@ -291,7 +287,7 @@ output_function_epilogue(stream, size)
                fprintf(stream, "\tmov (sp)+, %s\n", reg_names[i]);     
                                                                
        if (fsize)                                              
-           fprintf((stream), "\tadd $%d, sp\n", fsize);                
+           fprintf((stream), "\tadd $%o, sp\n", fsize);                
     }                  
                                        
     fprintf (stream, "\trts pc\n");                                    
@@ -300,7 +296,7 @@ output_function_epilogue(stream, size)
        
 /* Return the best assembler insn template
    for moving operands[1] into operands[0] as a fullword.  */
-static char *
+static const char *
 singlemove_string (operands)
      rtx *operands;
 {
@@ -314,7 +310,7 @@ singlemove_string (operands)
 /* Output assembler code to perform a doubleword move insn
    with operands OPERANDS.  */
 
-char *
+const char *
 output_move_double (operands)
      rtx *operands;
 {
@@ -370,14 +366,14 @@ output_move_double (operands)
     {
       operands[0] = XEXP (XEXP (operands[0], 0), 0);
       output_asm_insn ("sub $4,%0", operands);
-      operands[0] = gen_rtx (MEM, SImode, operands[0]);
+      operands[0] = gen_rtx_MEM (SImode, operands[0]);
       optype0 = OFFSOP;
     }
   if (optype0 == POPOP && optype1 == PUSHOP)
     {
       operands[1] = XEXP (XEXP (operands[1], 0), 0);
       output_asm_insn ("sub $4,%1", operands);
-      operands[1] = gen_rtx (MEM, SImode, operands[1]);
+      operands[1] = gen_rtx_MEM (SImode, operands[1]);
       optype1 = OFFSOP;
     }
 
@@ -400,14 +396,14 @@ output_move_double (operands)
      operands in OPERANDS to be suitable for the low-numbered word.  */
 
   if (optype0 == REGOP)
-    latehalf[0] = gen_rtx (REG, HImode, REGNO (operands[0]) + 1);
+    latehalf[0] = gen_rtx_REG (HImode, REGNO (operands[0]) + 1);
   else if (optype0 == OFFSOP)
     latehalf[0] = adj_offsettable_operand (operands[0], 2);
   else
     latehalf[0] = operands[0];
 
   if (optype1 == REGOP)
-    latehalf[1] = gen_rtx (REG, HImode, REGNO (operands[1]) + 1);
+    latehalf[1] = gen_rtx_REG (HImode, REGNO (operands[1]) + 1);
   else if (optype1 == OFFSOP)
     latehalf[1] = adj_offsettable_operand (operands[1], 2);
   else if (optype1 == CNSTOP)
@@ -417,10 +413,8 @@ output_move_double (operands)
            /* now the mess begins, high word is in lower word??? 
 
               that's what ashc makes me think, but I don't remember :-( */
-           latehalf[1] = gen_rtx(CONST_INT, VOIDmode, 
-                                 INTVAL(operands[1])>>16);
-           operands[1] = gen_rtx(CONST_INT, VOIDmode,
-                                 INTVAL(operands[1])&0xff);
+           latehalf[1] = GEN_INT (INTVAL(operands[1]) >> 16);
+           operands[1] = GEN_INT (INTVAL(operands[1]) & 0xff);
        }
       else if (GET_CODE (operands[1]) == CONST_DOUBLE)
        {
@@ -494,7 +488,7 @@ output_move_double (operands)
 /* Output assembler code to perform a quadword move insn
    with operands OPERANDS.  */
 
-char *
+const char *
 output_move_quad (operands)
      rtx *operands;
 {
@@ -566,14 +560,14 @@ output_move_quad (operands)
              u.i[1] = CONST_DOUBLE_HIGH (operands[1]); 
              
              if (u.d == 0.0)
-                 return "clrd %0";
+                 return "{clrd|clrf} %0";
          }
              
-         return "ldd %1, %0";
+         return "{ldd|movf} %1, %0";
       }
       
       if (FPU_REG_P(REGNO(operands[1])))
-         return "std %1, %0";
+         return "{std|movf} %1, %0";
   }
       
   /* If one operand is decrementing and one is incrementing
@@ -584,14 +578,14 @@ output_move_quad (operands)
     {
       operands[0] = XEXP (XEXP (operands[0], 0), 0);
       output_asm_insn ("sub $8,%0", operands);
-      operands[0] = gen_rtx (MEM, DImode, operands[0]);
+      operands[0] = gen_rtx_MEM (DImode, operands[0]);
       optype0 = OFFSOP;
     }
   if (optype0 == POPOP && optype1 == PUSHOP)
     {
       operands[1] = XEXP (XEXP (operands[1], 0), 0);
       output_asm_insn ("sub $8,%1", operands);
-      operands[1] = gen_rtx (MEM, SImode, operands[1]);
+      operands[1] = gen_rtx_MEM (SImode, operands[1]);
       optype1 = OFFSOP;
     }
 
@@ -614,14 +608,14 @@ output_move_quad (operands)
      operands in OPERANDS to be suitable for the low-numbered word.  */
 
   if (optype0 == REGOP)
-    latehalf[0] = gen_rtx (REG, SImode, REGNO (operands[0]) + 2);
+    latehalf[0] = gen_rtx_REG (SImode, REGNO (operands[0]) + 2);
   else if (optype0 == OFFSOP)
     latehalf[0] = adj_offsettable_operand (operands[0], 4);
   else
     latehalf[0] = operands[0];
 
   if (optype1 == REGOP)
-    latehalf[1] = gen_rtx (REG, SImode, REGNO (operands[1]) + 2);
+    latehalf[1] = gen_rtx_REG (SImode, REGNO (operands[1]) + 2);
   else if (optype1 == OFFSOP)
     latehalf[1] = adj_offsettable_operand (operands[1], 4);
   else if (optype1 == CNSTOP)
@@ -638,17 +632,19 @@ output_move_quad (operands)
            abort();
            
 #ifndef HOST_WORDS_BIG_ENDIAN
-         latehalf[1] = gen_rtx (CONST_INT, VOIDmode,
-                                CONST_DOUBLE_LOW (operands[1]));
-         operands[1] = gen_rtx (CONST_INT, VOIDmode,
-                                CONST_DOUBLE_HIGH (operands[1]));
+         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_rtx (CONST_INT, VOIDmode,
-                                CONST_DOUBLE_HIGH (operands[1]));
-         operands[1] = gen_rtx (CONST_INT, VOIDmode,
-                                CONST_DOUBLE_LOW (operands[1]));
+         latehalf[1] = GEN_INT (CONST_DOUBLE_HIGH (operands[1]));
+         operands[1] = GEN_INT (CONST_DOUBLE_LOW (operands[1]));
 #endif /* HOST_WORDS_BIG_ENDIAN */
        }
+      else if (GET_CODE(operands[1]) == CONST_INT)
+       {
+         latehalf[1] = GEN_INT (0);
+       }
+      else
+       abort();
     }
   else
     latehalf[1] = operands[1];
@@ -739,40 +735,34 @@ find_addr_reg (addr)
 }
 \f
 /* Output an ascii string.  */
+void
 output_ascii (file, p, size)
      FILE *file;
-     char *p;
+     const char *p;
      int size;
 {
   int i;
 
-  fprintf (file, "\t.byte \"");
+  /* This used to output .byte "string", which doesn't work with the UNIX
+     assembler and I think not with DEC ones either.  */
+  fprintf (file, "\t.byte ");
 
   for (i = 0; i < size; i++)
     {
       register int c = p[i];
-      if (c == '\"' || c == '\\')
-       putc ('\\', file);
-      if (c >= ' ' && c < 0177)
-       putc (c, file);
-      else
-       {
-         fprintf (file, "\\%03o", c);
-         /* After an octal-escape, if a digit follows,
-            terminate one string constant and start another.
-            The Vax assembler fails to stop reading the escape
-            after three digits, so this is the only way we
-            can get it to parse the data properly.  */
-         if (i < size - 1 && p[i + 1] >= '0' && p[i + 1] <= '9')
-           fprintf (file, "\"\n\tstring \"");
-       }
+      if (c < 0)
+       c += 256;
+      fprintf (file, "%o", c);
+      if (i < size - 1)
+       putc (',', file);
     }
-  fprintf (file, "\"\n");
+  putc ('\n', file);
 }
 
 
 /* --- stole from out-vax, needs changes */
 
+void
 print_operand_address (file, addr)
      FILE *file;
      register rtx addr;
@@ -785,7 +775,10 @@ print_operand_address (file, addr)
   switch (GET_CODE (addr))
     {
     case MEM:
-      fprintf (file, "@");
+      if (TARGET_UNIX_ASM)
+       fprintf (file, "*");
+      else
+       fprintf (file, "@");
       addr = XEXP (addr, 0);
       goto retry;
 
@@ -892,7 +885,7 @@ print_operand_address (file, addr)
       break;
 
     default:
-      output_addr_const (file, addr);
+      output_addr_const_pdp11 (file, addr);
     }
 }
 
@@ -924,10 +917,10 @@ register_move_cost(c1, c2)
     return move_costs[(int)c1][(int)c2];
 }
 
-char *
+const char *
 output_jump(pos, neg, length)
+  const char *pos, *neg;
   int length;
-  char *pos, *neg;
 {
     static int x = 0;
     
@@ -970,7 +963,7 @@ output_jump(pos, neg, length)
 void
 notice_update_cc_on_set(exp, insn)
   rtx exp;
-  rtx insn;
+  rtx insn ATTRIBUTE_UNUSED;
 {
     if (GET_CODE (SET_DEST (exp)) == CC0)
     { 
@@ -1039,12 +1032,12 @@ notice_update_cc_on_set(exp, insn)
 }
 
 
-int simple_memory_operand(op, mode)
-  rtx op;
-  enum machine_mode mode;
+int
+simple_memory_operand(op, mode)
+     rtx op;
+     enum machine_mode mode ATTRIBUTE_UNUSED;
 {
-    rtx addr, plus0, plus1;
-    int offset = 0;
+    rtx addr;
 
     /* Eliminate non-memory operations */
     if (GET_CODE (op) != MEM)
@@ -1094,6 +1087,9 @@ int simple_memory_operand(op, mode)
       case PLUS:
        /* X(R0) - extra cost */
        return 0;
+
+      default:
+       break;
     }
     
     return FALSE;
@@ -1111,7 +1107,7 @@ int simple_memory_operand(op, mode)
  */
 
  
-char *
+const char *
 output_block_move(operands)
   rtx *operands;
 {
@@ -1119,7 +1115,7 @@ output_block_move(operands)
     char buf[200];
     
     if (GET_CODE(operands[2]) == CONST_INT
-       && TARGET_TIME)
+       && ! optimize_size)
     {
        if (INTVAL(operands[2]) < 16
            && INTVAL(operands[3]) == 1)
@@ -1261,7 +1257,7 @@ output_block_move(operands)
             bgt x
        */
 
-       if (TARGET_SPACE)
+       if (optimize_size)
            goto generate_compact_code;
        
        output_asm_insn("asr %4", operands);
@@ -1312,7 +1308,7 @@ output_block_move(operands)
        */
 
 
-       if (TARGET_SPACE)
+       if (optimize_size)
            goto generate_compact_code;
        
        output_asm_insn("asr %4", operands);
@@ -1396,7 +1392,7 @@ comparison_operator_index(op)
 int
 comp_operator (op, mode)
   rtx op;
-  enum machine_mode mode;
+  enum machine_mode mode ATTRIBUTE_UNUSED;
 {
     return comparison_operator_index(op) >= 0;
 }
@@ -1417,3 +1413,114 @@ legitimate_address_p (mode, address)
 
 /* #undef REG_OK_STRICT */
 }
+
+/* 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;
+{
+  char buf[256];
+
+ restart:
+  switch (GET_CODE (x))
+    {
+    case PC:
+      if (flag_pic)
+       putc ('.', file);
+      else
+       abort ();
+      break;
+
+    case SYMBOL_REF:
+      assemble_name (file, XSTR (x, 0));
+      break;
+
+    case LABEL_REF:
+      ASM_GENERATE_INTERNAL_LABEL (buf, "L", CODE_LABEL_NUMBER (XEXP (x, 0)));
+      assemble_name (file, buf);
+      break;
+
+    case CODE_LABEL:
+      ASM_GENERATE_INTERNAL_LABEL (buf, "L", CODE_LABEL_NUMBER (x));
+      assemble_name (file, buf);
+      break;
+
+    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));
+      break;
+
+    case CONST:
+      /* This used to output parentheses around the expression,
+        but that does not work on the 386 (either ATT or BSD assembler).  */
+      output_addr_const_pdp11 (file, XEXP (x, 0));
+      break;
+
+    case CONST_DOUBLE:
+      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));
+       }
+      else
+       /* We can't handle floating point constants;
+          PRINT_OPERAND must handle them.  */
+       output_operand_lossage ("floating constant misused");
+      break;
+
+    case PLUS:
+      /* Some assemblers need integer constants to appear last (eg masm).  */
+      if (GET_CODE (XEXP (x, 0)) == CONST_INT)
+       {
+         output_addr_const_pdp11 (file, XEXP (x, 1));
+         if (INTVAL (XEXP (x, 0)) >= 0)
+           fprintf (file, "+");
+         output_addr_const_pdp11 (file, XEXP (x, 0));
+       }
+      else
+       {
+         output_addr_const_pdp11 (file, XEXP (x, 0));
+         if (INTVAL (XEXP (x, 1)) >= 0)
+           fprintf (file, "+");
+         output_addr_const_pdp11 (file, XEXP (x, 1));
+       }
+      break;
+
+    case MINUS:
+      /* Avoid outputting things like x-x or x+5-x,
+        since some assemblers can't handle that.  */
+      x = simplify_subtraction (x);
+      if (GET_CODE (x) != MINUS)
+       goto restart;
+
+      output_addr_const_pdp11 (file, XEXP (x, 0));
+      fprintf (file, "-");
+      if (GET_CODE (XEXP (x, 1)) == CONST_INT
+         && INTVAL (XEXP (x, 1)) < 0)
+       {
+         fprintf (file, ASM_OPEN_PAREN);
+         output_addr_const_pdp11 (file, XEXP (x, 1));
+         fprintf (file, ASM_CLOSE_PAREN);
+       }
+      else
+       output_addr_const_pdp11 (file, XEXP (x, 1));
+      break;
+
+    case ZERO_EXTEND:
+    case SIGN_EXTEND:
+      output_addr_const_pdp11 (file, XEXP (x, 0));
+      break;
+
+    default:
+      output_operand_lossage ("invalid expression as operand");
+    }
+}