OSDN Git Service

* Makefile.in (final.o): Depend on target.h.
[pf3gnuchains/gcc-fork.git] / gcc / config / 1750a / 1750a.c
index 5e80e28..39a0ebb 100644 (file)
@@ -1,12 +1,13 @@
 /* Subroutines for insn-output.c for MIL-STD-1750.
-   Copyright (C) 1994, 1995 Free Software Foundation, Inc.
-   Contributed by O.M.Kellogg, DASA (okellogg@salyko.cube.net).
+   Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999,
+   2000 Free Software Foundation, Inc.
+   Contributed by O.M.Kellogg, DASA (kellogg@space.otn.dasa.de)
 
 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,22 @@ 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 <string.h>
-
 #define __datalbl
 #include "config.h"
+#include "system.h"
 #include "rtl.h"
 #include "tree.h"
+#include "function.h"
 #include "expr.h"
 #define HAVE_cc0
 #include "conditions.h"
 #include "real.h"
+#include "regs.h"
+#include "output.h"
+#include "flags.h"
+#include "tm_p.h"
+#include "target.h"
+#include "target-def.h"
 
 struct datalabel_array datalbl[DATALBL_ARRSIZ];
 int datalbl_ndx = -1;
@@ -39,10 +43,111 @@ struct jumplabel_array jmplbl[JMPLBL_ARRSIZ];
 int jmplbl_ndx = -1;
 int label_pending = 0, program_counter = 0;
 enum section current_section = Normal;
-char *sectname[4] =
+const char *const sectname[4] =
 {"Init", "Normal", "Konst", "Static"};
 
-int
+static int which_bit PARAMS ((int));
+static void output_function_prologue PARAMS ((FILE *, HOST_WIDE_INT));
+static void output_function_epilogue PARAMS ((FILE *, HOST_WIDE_INT));
+\f
+/* Initialize the GCC target structure.  */
+#undef TARGET_ASM_FUNCTION_PROLOGUE
+#define TARGET_ASM_FUNCTION_PROLOGUE output_function_prologue
+#undef TARGET_ASM_FUNCTION_EPILOGUE
+#define TARGET_ASM_FUNCTION_EPILOGUE output_function_epilogue
+
+struct gcc_target target = TARGET_INITIALIZER;
+\f
+/* Generate the assembly code for function entry.  FILE is a stdio
+   stream to output the code to.  SIZE is an int: how many units of
+   temporary storage to allocate.
+
+   Refer to the array `regs_ever_live' to determine which registers to
+   save; `regs_ever_live[I]' is nonzero if register number I is ever
+   used in the function.  This function is responsible for knowing
+   which registers should not be saved even if used.  */
+
+static void
+output_function_prologue (file, size)
+     FILE *file;
+     HOST_WIDE_INT size;
+{
+  if (flag_verbose_asm)
+    {
+      int regno, regs_used = 0;
+
+      fprintf (file, "\t; registers used: ");
+      for (regno = 0; regno < 14; regno++)
+       if (regs_ever_live[regno])
+         {
+           fprintf (file, " %s", reg_names[regno]);
+           regs_used++;
+         }
+
+      if (regs_used == 0)
+       fprintf (file, "(none)");
+    }
+
+  if (size > 0)
+    {
+      fprintf (file, "\n\t%s\tr15,%d",
+              (size <= 16 ? "sisp" : "sim"), size);
+      if (flag_verbose_asm)
+       fprintf (file, "  ; reserve local-variable space");
+    }
+
+  if (frame_pointer_needed)
+    {
+      fprintf(file, "\n\tpshm\tr14,r14");
+      if (flag_verbose_asm)
+       fprintf (file, "  ; push old frame");
+      fprintf (file, "\n\tlr\tr14,r15");
+      if (flag_verbose_asm)
+       fprintf (file, "  ; set new frame");
+    }
+
+  fprintf (file, "\n");
+  program_counter = 0;
+  jmplbl_ndx = -1;
+}
+
+/* This function generates the assembly code for function exit.
+   Args are as for output_function_prologue ().
+
+   The function epilogue should not depend on the current stack
+   pointer!  It should use the frame pointer only.  This is mandatory
+   because of alloca; we also take advantage of it to omit stack
+   adjustments before returning. */
+
+static void
+output_function_epilogue (file, size)
+     FILE *file;
+     HOST_WIDE_INT size;
+{
+  if (frame_pointer_needed)
+    {
+      fprintf (file, "\tlr\tr15,r14");
+      if (flag_verbose_asm)
+        fprintf (file, "  ; set stack ptr to frame ptr");
+      fprintf (file, "\n\tpopm\tr14,r14");
+      if (flag_verbose_asm)
+        fprintf (file, "  ; restore previous frame ptr");
+      fprintf (file, "\n");
+    }
+
+  if (size > 0)
+    {
+      fprintf (file, "\t%s\tr15,%d",
+              (size <= 16 ? "aisp" : "aim"), size);
+      if (flag_verbose_asm)
+       fprintf (file, "  ; free up local-var space");
+      fprintf (file, "\n");
+    }
+
+  fprintf (file, "\turs\tr15\n\n");
+}
+
+void
 notice_update_cc (exp)
      rtx exp;
 {
@@ -52,24 +157,18 @@ notice_update_cc (exp)
       /* Jumps do not alter the cc's.  */
       if (SET_DEST (exp) == pc_rtx)
        return;
-      /* Moving register into memory doesn't alter the cc's.
-        It may invalidate the RTX's which we remember the cc's came from.  */
-      if (GET_CODE (SET_DEST (exp)) == MEM)
-       {
-         if (cc_status.value1 && GET_CODE (cc_status.value1) == MEM)
-           cc_status.value1 = 0;
-         if (cc_status.value2 && GET_CODE (cc_status.value2) == MEM)
-           cc_status.value2 = 0;
-         return;
-       }
+      /* Moving a register or constant into memory doesn't alter the cc's. */
+      if (GET_CODE (SET_DEST (exp)) == MEM
+         && (src_code == REG || src_code == CONST_INT))
+       return;
       /* Function calls clobber the cc's.  */
-      else if (src_code == CALL)
+      if (src_code == CALL)
        {
          CC_STATUS_INIT;
          return;
        }
       /* Emulated longword bit-ops leave cc's incorrect */
-      else if (GET_MODE (SET_DEST (exp)) == HImode ?
+      if (GET_MODE (SET_DEST (exp)) == HImode ?
               src_code == AND || src_code == IOR ||
               src_code == XOR || src_code == NOT : 0)
        {
@@ -77,24 +176,17 @@ notice_update_cc (exp)
          return;
        }
       /* Tests and compares set the cc's in predictable ways.  */
-      else if (SET_DEST (exp) == cc0_rtx)
+      if (SET_DEST (exp) == cc0_rtx)
        {
          CC_STATUS_INIT;
          cc_status.value1 = SET_SRC (exp);
          return;
        }
-      /* Anything that lands in a reg will set cc_status. */
-      else if (REG_P (SET_DEST (exp)))
-       {
-         cc_status.flags = CC_NO_OVERFLOW;
-         cc_status.value1 = SET_SRC (exp);
-         cc_status.value2 = SET_DEST (exp);
-         return;
-       }
-      else
-       {
-         CC_STATUS_INIT;
-       }
+      /* Anything else will set cc_status. */
+      cc_status.flags = CC_NO_OVERFLOW;
+      cc_status.value1 = SET_SRC (exp);
+      cc_status.value2 = SET_DEST (exp);
+      return;
     }
   else if (GET_CODE (exp) == PARALLEL
           && GET_CODE (XVECEXP (exp, 0, 0)) == SET)
@@ -121,10 +213,9 @@ function_arg (cum, mode, type, named)
      int cum;
      enum machine_mode mode;
      tree type;
-     int named;
+     int named ATTRIBUTE_UNUSED;
 {
   int size;
-  rtx result;
 
   if (MUST_PASS_IN_STACK (mode, type))
     return (rtx) 0;
@@ -133,31 +224,12 @@ function_arg (cum, mode, type, named)
   else
     size = GET_MODE_SIZE (mode);
   if (cum + size < 12)
-    return gen_rtx (REG, mode, cum);
+    return gen_rtx_REG (mode, cum);
   else
     return (rtx) 0;
 }
 
 
-#ifndef STRDUP
-char *
-strdup (str)
-     char *str;
-{
-  char *p;
-  if (str == NULL)
-    return NULL;
-  if ((p = (char *) malloc (strlen (str) + 1)) == NULL)
-    {
-      fprintf (stderr, "dynamic memory exhausted");
-      abort ();
-    }
-  return strcpy (p, str);
-}
-
-#endif
-
-
 double
 get_double (x)
      rtx x;
@@ -176,86 +248,107 @@ get_double (x)
 
 char *
 float_label (code, value)
-     char code;
+     int code;
      double value;
 {
-  int i = 1;
   static char label[32];
   char *p;
 
   label[0] = code;
   p = label + 1;
-  sprintf (p, "%lf", value);
+  sprintf (p, "%f", value);
   while (*p)
     {
       *p = (*p == '+') ? 'p' :
        (*p == '-') ? 'm' : *p;
       p++;
     }
-  return strdup (label);
+  return xstrdup (label);
 }
 
 
-char *
+const char *
 movcnt_regno_adjust (op)
      rtx *op;
 {
-  static char outstr[40];
-  int cntreg = REGNO (op[2]), cntreg_1750 = REGNO (op[0]) + 1;
-  int dstreg = REGNO (op[0]), srcreg = REGNO (op[1]);
+  static char outstr[80];
+  int op0r = REGNO (op[0]), op1r = REGNO (op[1]), op2r = REGNO (op[2]);
+#define dstreg op0r
+#define srcreg op1r
+#define cntreg op2r
+#define cntreg_1750 (op0r + 1)
 
   if (cntreg == cntreg_1750)
-    sprintf (outstr, "mov r%%0,r%%1");
-  else if (dstreg + 1 == srcreg && srcreg == cntreg + 2)
-    sprintf (outstr, "xwr r%d,r%d\n\tmov r%%0,r%%1", cntreg, dstreg);
-  else if (dstreg + 1 == srcreg && srcreg < cntreg)
-    sprintf (outstr, "xwr r%d,r%d\n\tmov r%%0,r%%1", srcreg, cntreg);
-  else if (srcreg + 1 == cntreg && dstreg > cntreg)
-    sprintf (outstr, "xwr r%d,r%d\n\tmov r%%0,r%%1", srcreg, dstreg);
+    sprintf (outstr, "mov r%d,r%d", op0r, op1r);
+  else if (dstreg + 1 == srcreg && cntreg > srcreg)
+    sprintf (outstr, "xwr r%d,r%d\n\tmov r%d,r%d", op2r, op1r, op0r, op2r);
+  else if (dstreg == cntreg + 1)
+    sprintf (outstr, "xwr r%d,r%d\n\tmov r%d,r%d", op0r, op2r, op2r, op1r);
+  else if (dstreg == srcreg + 1)
+    sprintf (outstr, "xwr r%d,r%d\n\txwr r%d,r%d\n\tmov r%d,r%d",
+            op0r, op1r, op0r, op2r, op1r, op2r);
+  else if (cntreg + 1 == srcreg)
+    sprintf (outstr, "xwr r%d,r%d\n\txwr r%d,r%d\n\tmov r%d,r%d",
+            op2r, op1r, op0r, op2r, op2r, op0r);
+  else if (cntreg == srcreg + 1)
+    sprintf (outstr, "xwr r%d,r%d\n\tmov r%d,r%d", op0r, op1r, op1r, op0r);
   else
-    sprintf (outstr, "xwr r%d,r%d\n\tmov r%%0,%%1\n\txwr r%d,r%d",
-            cntreg, cntreg_1750, cntreg_1750, cntreg);
+    sprintf (outstr, "xwr r%d,r%d\n\tmov r%d,r%d\n\txwr r%d,r%d",
+            op2r, cntreg_1750, op0r, op1r, op2r, cntreg_1750);
   return outstr;
 }
 
-char *
+const char *
 mod_regno_adjust (instr, op)
-     char *instr;
+     const char *instr;
      rtx *op;
 {
   static char outstr[40];
-  char *r = (!strncmp (instr, "dvr", 3) ? "r" : "");
+  const char *r = (!strncmp (instr, "dvr", 3) ? "r" : "");
   int modregno_gcc = REGNO (op[3]), modregno_1750 = REGNO (op[0]) + 1;
 
-  if (modregno_gcc == modregno_1750)
+  if (modregno_gcc == modregno_1750
+      || (reg_renumber != NULL
+         && reg_renumber[modregno_gcc] >= 0
+         && reg_renumber[modregno_gcc] == reg_renumber[modregno_1750]))
     sprintf (outstr, "%s r%%0,%s%%2", instr, r);
   else
     sprintf (outstr, "lr r%d,r%d\n\t%s r%%0,%s%%2\n\txwr r%d,r%d",
-       modregno_gcc, modregno_1750, instr, r, modregno_1750, modregno_gcc);
+            modregno_gcc, modregno_1750, instr, r, modregno_1750,
+            modregno_gcc);
   return outstr;
 }
 
 
-/* Auxiliary to `nonindirect_operand':
-   Check if op is a valid memory operand for 1750A arith./logic (non-move)
-   instructions. */
+/* Check if op is a valid memory operand for 1750A Load/Store instructions
+   (memory indirection permitted.)  */
+
 int
 memop_valid (op)
      rtx op;
 {
-  if (GET_MODE (op) != Pmode && GET_MODE (op) != VOIDmode)
+  static int recurred = 0;
+  int valid_operand;
+
+  if (GET_MODE (op) != Pmode && GET_MODE (op) != VOIDmode
+      && GET_MODE (op) != QImode)
     return 0;
   switch (GET_CODE (op))
     {
     case MEM:
+      if (!recurred && GET_CODE (XEXP (op, 0)) == REG)
+       return 1;
     case MINUS:
     case MULT:
     case DIV:
       return 0;
     case PLUS:
-      if (!memop_valid (XEXP (op, 0)))
-       return 0;
-      return memop_valid (XEXP (op, 1));
+      recurred = 1;
+      valid_operand = memop_valid (XEXP (op, 0));
+      if (valid_operand)
+       valid_operand = memop_valid (XEXP (op, 1));
+       recurred = 0;
+       return valid_operand;
     case REG:
       if (REGNO (op) > 0)
        return 1;
@@ -271,39 +364,65 @@ memop_valid (op)
     }
 }
 
-/* extra predicate for recog: */
+
+/* predicate for the MOV instruction: */
 int
-nonindirect_operand (op, mode)
+mov_memory_operand (op, mode)
      rtx op;
-     enum machine_mode mode;
+     enum machine_mode mode ATTRIBUTE_UNUSED;
 {
-  int retval;
-
-  switch (GET_CODE (op))
-    {
-    case MEM:
-      retval = memop_valid (XEXP (op, 0));
-      return retval;
-    case REG:
-      return 1;
-    default:
-      if (!CONSTANT_P (op))
-       return 0;
-    }
-  return 1;
+  return (GET_CODE (op) == MEM && GET_CODE (XEXP (op, 0)) == REG);
 }
 
 /* predicate for the STC instruction: */
 int
 small_nonneg_const (op, mode)
      rtx op;
-     enum machine_mode mode;
+     enum machine_mode mode ATTRIBUTE_UNUSED;
 {
   if (GET_CODE (op) == CONST_INT && INTVAL (op) >= 0 && INTVAL (op) <= 15)
     return 1;
   return 0;
 }
 
+/* predicate for constant zero: */
+int
+zero_operand (op, mode)
+     rtx op;
+     enum machine_mode mode;
+{
+  return op == CONST0_RTX (mode);
+}
+
+
+/* predicate for 1750 `B' addressing mode (Base Register with Offset)
+   memory operand */
+int
+b_mode_operand (op)
+     rtx op;
+{
+  if (GET_CODE (op) == MEM)
+    {
+      rtx inner = XEXP (op, 0);
+      if (GET_CODE (inner) == REG && REG_OK_FOR_INDEX_P (inner))
+       return 1;
+      if (GET_CODE (inner) == PLUS)
+       {
+         rtx plus_op0 = XEXP (inner, 0);
+         if (GET_CODE (plus_op0) == REG && REG_OK_FOR_INDEX_P (plus_op0))
+           {
+             rtx plus_op1 = XEXP (inner, 1);
+             if (GET_CODE (plus_op1) == CONST_INT
+                 && INTVAL (plus_op1) >= 0
+                 && INTVAL (plus_op1) <= 255)
+               return 1;
+           }
+       }
+    }
+  return 0;
+}
+
+
 /* Decide whether to output a conditional jump as a "Jump Conditional"
    or as a "Branch Conditional": */
 
@@ -324,9 +443,9 @@ find_jmplbl (labelnum)
   return -1;
 }
 
-char *
+const char *
 branch_or_jump (condition, targetlabel_number)
-     char *condition;
+     const char *condition;
      int targetlabel_number;
 {
   static char buf[30];
@@ -343,35 +462,128 @@ branch_or_jump (condition, targetlabel_number)
 }
 
 
+int
+unsigned_comparison_operator (insn)
+     rtx insn;
+{
+  switch (GET_CODE (insn))
+    {
+    case GEU:
+    case GTU:
+    case LEU:
+    case LTU:
+      return 1;
+    default:
+      return 0;
+    }
+}
+
+int
+next_cc_user_is_unsigned (insn)
+     rtx insn;
+{
+  if ( !(insn = next_cc0_user (insn)))
+    abort ();
+  else if (GET_CODE (insn) == JUMP_INSN
+          && GET_CODE (PATTERN (insn)) == SET
+          && GET_CODE (SET_SRC (PATTERN (insn))) == IF_THEN_ELSE)
+    return unsigned_comparison_operator (XEXP (SET_SRC (PATTERN (insn)), 0));
+  else if (GET_CODE (insn) == INSN
+          && GET_CODE (PATTERN (insn)) == SET)
+    return unsigned_comparison_operator (SET_SRC (PATTERN (insn)));
+  else
+    abort ();
+}
 
-/* The PRINT_OPERAND and PRINT_OPERAND_ADDRESS macros have been
-   made functions: */
 
-print_operand (file, x, kode)
+static int addr_inc;
+
+/* A C compound statement to output to stdio stream STREAM the
+   assembler syntax for an instruction operand X.  X is an RTL
+   expression.
+
+   CODE is a value that can be used to specify one of several ways
+   of printing the operand.  It is used when identical operands
+   must be printed differently depending on the context.  CODE
+   comes from the `%' specification that was used to request
+   printing of the operand.  If the specification was just `%DIGIT'
+   then CODE is 0; if the specification was `%LTR DIGIT' then CODE
+   is the ASCII code for LTR.
+
+   If X is a register, this macro should print the register's name.
+   The names can be found in an array `reg_names' whose type is
+   `char *[]'.  `reg_names' is initialized from `REGISTER_NAMES'.
+
+   When the machine description has a specification `%PUNCT' (a `%'
+   followed by a punctuation character), this macro is called with
+   a null pointer for X and the punctuation character for CODE.
+
+   The 1750 specific codes are:
+   'J' for the negative of a constant
+   'Q' for printing addresses in B mode syntax
+   'd' for the second register in a pair
+   't' for the third register in a triple 
+   'b' for the bit number (using 1750 test bit convention)
+   'B' for the bit number of the 1's complement (for bit clear)
+   'w' for int - 16
+*/
+
+void
+print_operand (file, x, letter)
      FILE *file;
      rtx x;
-     enum rtx_code kode;
+     int letter;
 {
   switch (GET_CODE (x))
     {
     case REG:
-      fprintf (file, "%d", REGNO (x));
+      if (letter == 'd')
+       fprintf (file, "%d", REGNO (x) + 1);
+      else if (letter == 't')
+       fprintf (file, "%d", REGNO (x) + 2);
+      else
+       fprintf (file, "%d", REGNO (x));
       break;
+
     case SYMBOL_REF:
       fprintf (file, "%s", XSTR (x, 0));
+      if (letter == 'A')
+       fprintf (file, "+1");
       break;
+
     case LABEL_REF:
     case CONST:
     case MEM:
-      output_address (XEXP (x, 0));
+      if (letter == 'Q')
+       {
+         rtx inner = XEXP (x, 0);
+         switch (GET_CODE (inner))
+           {
+           case REG:
+             fprintf (file, "r%d,0", REGNO (inner));
+             break;
+           case PLUS:
+             fprintf (file, "r%d,%d", REGNO (XEXP (inner, 0)),
+                      INTVAL (XEXP (inner, 1)));
+             break;
+           default:
+             fprintf (file, "[ill Q code=%d]", GET_CODE (inner));
+           }
+       }
+      else
+       {
+         addr_inc = (letter == 'A' ? 1 : 0);
+         output_address (XEXP (x, 0));
+       }
       break;
+
     case CONST_DOUBLE:
 /*    {
        double value = get_double (x);
        char fltstr[32];
-       sprintf (fltstr, "%lf", value);
+       sprintf (fltstr, "%f", value);
 
-       if (kode == 'D' || kode == 'E')
+       if (letter == 'D' || letter == 'E')
          {
            int i, found = 0;
            for (i = 0; i <= datalbl_ndx; i++)
@@ -383,15 +595,15 @@ print_operand (file, x, kode)
            if (!found)
              {
                strcpy (datalbl[i = ++datalbl_ndx].value, fltstr);
-               datalbl[i].name = float_label (kode, value);
-               datalbl[i].size = (kode == 'E') ? 3 : 2;
+               datalbl[i].name = float_label (letter, value);
+               datalbl[i].size = (letter == 'E') ? 3 : 2;
                check_section (Konst);
                fprintf (file, "K%s \tdata%s %s ;p_o\n", datalbl[i].name,
-                       (kode == 'E' ? "ef" : "f"), fltstr);
+                       (letter == 'E' ? "ef" : "f"), fltstr);
                check_section (Normal);
              }
          }
-       else if (kode == 'F' || kode == 'G')
+       else if (letter == 'F' || letter == 'G')
          {
            int i, found = 0;
            for (i = 0; i <= datalbl_ndx; i++)
@@ -403,13 +615,13 @@ print_operand (file, x, kode)
            if (!found)
              {
                fprintf (stderr,
-                  "float value %lfnot found upon label reference\n", value);
+                  "float value %not found upon label reference\n", value);
                strcpy (datalbl[i = ++datalbl_ndx].value, fltstr);
-               datalbl[i].name = float_label (kode, value);
-               datalbl[i].size = (kode == 'G') ? 3 : 2;
+               datalbl[i].name = float_label (letter, value);
+               datalbl[i].size = (letter == 'G') ? 3 : 2;
                check_section (Konst);
                fprintf (file, "K%s \tdata%s %s ;p_o\n", datalbl[i].name,
-                       (kode == 'G' ? "ef" : "f"), fltstr);
+                       (letter == 'G' ? "ef" : "f"), fltstr);
                check_section (Normal);
              }
            fprintf (file, "%s ;P_O 'F'", datalbl[i].name);
@@ -418,24 +630,33 @@ print_operand (file, x, kode)
          fprintf (file, " %s  ;P_O cst_dbl ", fltstr);
       }
  */
-      fprintf (file, "%lf", get_double (x));
+      fprintf (file, "%f", get_double (x));
       break;
+
     case CONST_INT:
-      if (kode == 'J')
-       fprintf (file, "%d", -INTVAL (x));
-      else if (INTVAL (x) > 0x7FFF)
-       fprintf (file, "%d  ; range correction (val>0x7FFF) applied",
-                INTVAL (x) - 0x10000);
+      if (letter == 'J')
+       fprintf (file, HOST_WIDE_INT_PRINT_DEC, -INTVAL (x));
+      else if (letter == 'b')
+        fprintf (file, "%d", which_bit (INTVAL (x)));
+      else if (letter == 'B')
+        fprintf (file, "%d", which_bit (~INTVAL (x)));
+      else if (letter == 'w')
+       fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (x) - 16);
       else
-       fprintf (file, "%d", INTVAL (x));
+       fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (x));
       break;
+
     case CODE_LABEL:
       fprintf (file, "L%d", XINT (x, 3));
       break;
+
     case CALL:
-      fprintf (file, "CALL nargs=%d, func is either '%s' or '%s'",
-       XEXP (x, 1), XSTR (XEXP (XEXP (x, 0), 1), 0), XSTR (XEXP (x, 0), 1));
+      fprintf (file, "CALL nargs=");
+      fprintf (file, HOST_PTR_PRINTF, XEXP (x, 1));
+      fprintf (file, ", func is either '%s' or '%s'",
+              XSTR (XEXP (XEXP (x, 0), 1), 0), XSTR (XEXP (x, 0), 1));
       break;
+
     case PLUS:
       {
        rtx op0 = XEXP (x, 0), op1 = XEXP (x, 1);
@@ -444,7 +665,7 @@ print_operand (file, x, kode)
          switch (op0code)
            {
            case REG:
-             fprintf (file, "%d,r%d  ; p_o_PLUS for REG and CONST",
+             fprintf (file, "%d,r%d  ; p_o_PLUS for REG and CONST_INT",
                       INTVAL (op1), REGNO (op0));
              break;
            case SYMBOL_REF:
@@ -466,11 +687,15 @@ print_operand (file, x, kode)
          fprintf (file, "p_o_+: op0code=%d, op1code=%d", op0code, op1code);
       }
       break;
+
     default:
       fprintf (file, "p_o_UFO code=%d", GET_CODE (x));
     }
+
+  addr_inc = 0;
 }
 
+void
 print_operand_address (file, addr)
      FILE *file;
      rtx addr;
@@ -478,7 +703,7 @@ print_operand_address (file, addr)
   switch (GET_CODE (addr))
     {
     case REG:
-      fprintf (file, "0,r%d ; P_O_A", REGNO (addr));
+      fprintf (file, "%d,r%d ; P_O_A", addr_inc, REGNO (addr));
       break;
     case PLUS:
       {
@@ -493,11 +718,13 @@ print_operand_address (file, addr)
                fprintf (file, ",r%d ;P_O_A reg + const expr", REGNO (x));
                break;
              case CONST_INT:
-               fprintf (file, "%d,r%d", INTVAL (y), REGNO (x));
+               fprintf (file, "%d,r%d", INTVAL (y) + addr_inc, REGNO (x));
                break;
              case SYMBOL_REF:
-               fprintf (file, "%s,r%d  ; P_O_A reg + sym",
-                        XSTR (y, 0), REGNO (x));
+               fprintf (file, "%s", XSTR (y, 0));
+               if (addr_inc)
+                 fprintf (file, "+%d", addr_inc);
+               fprintf (file, ",r%d  ; P_O_A reg + sym", REGNO (x));
                break;
              case LABEL_REF:
                output_address (XEXP (y, 0));
@@ -515,7 +742,7 @@ print_operand_address (file, addr)
            switch (GET_CODE (y))
              {
              case CONST_INT:
-               fprintf (file, "%d+%s", INTVAL (y), XSTR (x, 0));
+               fprintf (file, "%d+%s", INTVAL (y) + addr_inc, XSTR (x, 0));
                break;
              case REG:
                fprintf (file, "%s,r%d ;P_O_A sym + reg",
@@ -557,6 +784,8 @@ print_operand_address (file, addr)
     case LABEL_REF:
     case SYMBOL_REF:
       fprintf (file, "%s", XSTR (addr, 0));
+      if (addr_inc)
+       fprintf (file, "+%d", addr_inc);
       break;
     case MEM:
       fprintf (file, "[memUFO:");
@@ -575,5 +804,41 @@ print_operand_address (file, addr)
               (int) GET_CODE (addr), INTVAL (addr));
       break;
     }
+  addr_inc = 0;
 }
 
+
+/*
+ *  Return non zero if the LS 16 bits of the given value has just one bit set,
+ *  otherwise return zero. Note this function may be used to detect one
+ *  bit clear by inverting the param.
+ */
+int
+one_bit_set_p (x)
+     int x;
+{
+  x &= 0xffff; 
+  return x && (x & (x - 1)) == 0;
+}
+
+
+/*
+ * Return the number of the least significant bit set, using the  same
+ * convention for bit numbering as in the MIL-STD-1750 sb instruction.
+ */
+static int
+which_bit (x)
+     int x;
+{
+  int b = 15;
+
+  while (b > 0 && (x & 1) == 0)
+    {
+      b--;
+      x >>= 1;
+    }
+
+  return b;
+}
+
+