]> oss.titaniummirror.com Git - msp430-gcc.git/blobdiff - gcc/config/mn10200/mn10200.c
Imported gcc-4.4.3
[msp430-gcc.git] / gcc / config / mn10200 / mn10200.c
diff --git a/gcc/config/mn10200/mn10200.c b/gcc/config/mn10200/mn10200.c
deleted file mode 100644 (file)
index 4fa4c2e..0000000
+++ /dev/null
@@ -1,1594 +0,0 @@
-/* Subroutines for insn-output.c for Matsushita MN10200 series
-   Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002
-   Free Software Foundation, Inc.
-   Contributed by Jeff Law (law@cygnus.com).
-
-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 2, or (at your option)
-any later version.
-
-GNU CC 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.  */
-
-#include "config.h"
-#include "system.h"
-#include "rtl.h"
-#include "tree.h"
-#include "regs.h"
-#include "hard-reg-set.h"
-#include "real.h"
-#include "insn-config.h"
-#include "conditions.h"
-#include "output.h"
-#include "insn-attr.h"
-#include "flags.h"
-#include "recog.h"
-#include "expr.h"
-#include "function.h"
-#include "obstack.h"
-#include "ggc.h"
-#include "toplev.h"
-#include "tm_p.h"
-#include "target.h"
-#include "target-def.h"
-
-/* Global registers known to hold the value zero.
-
-   Normally we'd depend on CSE and combine to put zero into a
-   register and re-use it.
-
-   However, on the mn10x00 processors we implicitly use the constant
-   zero in tst instructions, so we might be able to do better by
-   loading the value into a register in the prologue, then re-useing
-   that register throughout the function.
-
-   We could perform similar optimizations for other constants, but with
-   gcse due soon, it doesn't seem worth the effort.
-
-   These variables hold a rtx for a register known to hold the value
-   zero throughout the entire function, or NULL if no register of
-   the appropriate class has such a value throughout the life of the
-   function.  */
-rtx zero_dreg;
-rtx zero_areg;
-
-static void count_tst_insns PARAMS ((int *));
-
-/* Note whether or not we need an out of line epilogue.  */
-static int out_of_line_epilogue;
-\f
-/* Initialize the GCC target structure.  */
-#undef TARGET_ASM_ALIGNED_HI_OP
-#define TARGET_ASM_ALIGNED_HI_OP "\t.hword\t"
-
-struct gcc_target targetm = TARGET_INITIALIZER;
-\f
-/* Indicate this file was compiled by gcc and what optimization
-   level was used.  */
-void
-asm_file_start (file)
-     FILE *file;
-{
-  fprintf (file, "#\tGCC For the Matsushita MN10200\n");
-  if (optimize)
-    fprintf (file, "# -O%d\n", optimize);
-  else
-    fprintf (file, "\n\n");
-  output_file_directive (file, main_input_filename);
-  ggc_add_rtx_root (&zero_dreg, 1);
-  ggc_add_rtx_root (&zero_areg, 1);
-}
-
-/* Print operand X using operand code CODE to assembly language output file
-   FILE.  */
-
-void
-print_operand (file, x, code)
-     FILE *file;
-     rtx x;
-     int code;
-{
-  switch (code)
-    {
-      case 'b':
-      case 'B':
-       /* These are normal and reversed branches.  */
-       switch (code == 'b' ? GET_CODE (x) : reverse_condition (GET_CODE (x)))
-         {
-         case NE:
-           fprintf (file, "ne");
-           break;
-         case EQ:
-           fprintf (file, "eq");
-           break;
-         case GE:
-           fprintf (file, "ge");
-           break;
-         case GT:
-           fprintf (file, "gt");
-           break;
-         case LE:
-           fprintf (file, "le");
-           break;
-         case LT:
-           fprintf (file, "lt");
-           break;
-         case GEU:
-           fprintf (file, "cc");
-           break;
-         case GTU:
-           fprintf (file, "hi");
-           break;
-         case LEU:
-           fprintf (file, "ls");
-           break;
-         case LTU:
-           fprintf (file, "cs");
-           break;
-         default:
-           abort ();
-         }
-       break;
-      case 'C':
-       /* This is used for the operand to a call instruction;
-          if it's a REG, enclose it in parens, else output
-          the operand normally.  */
-       if (GET_CODE (x) == REG)
-         {
-           fputc ('(', file);
-           print_operand (file, x, 0);
-           fputc (')', file);
-         }
-       else
-         print_operand (file, x, 0);
-       break;
-     
-      /* These are the least significant word in a 32bit value.
-        'o' allows us to sign extend a constant if doing so
-        makes for more compact code.  */
-      case 'L':
-      case 'o':
-       switch (GET_CODE (x))
-         {
-         case MEM:
-           fputc ('(', file);
-           output_address (XEXP (x, 0));
-           fputc (')', file);
-           break;
-
-         case REG:
-           fprintf (file, "%s", reg_names[REGNO (x)]);
-           break;
-
-         case SUBREG:
-           fprintf (file, "%s", reg_names[subreg_regno (x)]);
-           break;
-
-         case CONST_DOUBLE:
-           if (code == 'L')
-             {
-               long val;
-               REAL_VALUE_TYPE rv;
-
-               REAL_VALUE_FROM_CONST_DOUBLE (rv, x);
-               REAL_VALUE_TO_TARGET_SINGLE (rv, val);
-               print_operand_address (file, GEN_INT (val & 0xffff));
-             }
-           else
-             {
-               long val;
-               REAL_VALUE_TYPE rv;
-
-               REAL_VALUE_FROM_CONST_DOUBLE (rv, x);
-               REAL_VALUE_TO_TARGET_SINGLE (rv, val);
-
-               val &= 0xffff;
-               val = (((val) & 0xffff) ^ (~0x7fff)) + 0x8000;
-               print_operand_address (file, GEN_INT (val));
-             }
-           break;
-
-         case CONST_INT:
-           if (code == 'L')
-             print_operand_address (file, GEN_INT ((INTVAL (x) & 0xffff)));
-           else
-             {
-               unsigned int val = INTVAL (x) & 0xffff;
-               val = (((val) & 0xffff) ^ (~0x7fff)) + 0x8000;
-               print_operand_address (file, GEN_INT (val));
-             }
-           break;
-         default:
-           abort ();
-         }
-       break;
-
-      /* Similarly, but for the most significant word.  */
-      case 'H':
-      case 'h':
-       switch (GET_CODE (x))
-         {
-         case MEM:
-           fputc ('(', file);
-           x = adjust_address (x, HImode, 2);
-           output_address (XEXP (x, 0));
-           fputc (')', file);
-           break;
-
-         case REG:
-           fprintf (file, "%s", reg_names[REGNO (x) + 1]);
-           break;
-
-         case SUBREG:
-           fprintf (file, "%s", reg_names[subreg_regno (x) + 1]);
-           break;
-
-         case CONST_DOUBLE:
-           if (code == 'H')
-             {
-               long val;
-               REAL_VALUE_TYPE rv;
-
-               REAL_VALUE_FROM_CONST_DOUBLE (rv, x);
-               REAL_VALUE_TO_TARGET_SINGLE (rv, val);
-
-               print_operand_address (file, GEN_INT ((val >> 16) & 0xffff));
-             }
-           else
-             {
-               long val;
-               REAL_VALUE_TYPE rv;
-
-               REAL_VALUE_FROM_CONST_DOUBLE (rv, x);
-               REAL_VALUE_TO_TARGET_SINGLE (rv, val);
-
-               val = (val >> 16) & 0xffff;
-               val = (((val) & 0xffff) ^ (~0x7fff)) + 0x8000;
-
-               print_operand_address (file, GEN_INT (val));
-             }
-           break;
-
-         case CONST_INT:
-           if (code == 'H')
-             print_operand_address (file,
-                                    GEN_INT ((INTVAL (x) >> 16) & 0xffff));
-           else
-             {
-               unsigned int val = (INTVAL (x) >> 16) & 0xffff;
-               val = (((val) & 0xffff) ^ (~0x7fff)) + 0x8000;
-
-               print_operand_address (file, GEN_INT (val));
-             }
-           break;
-         default:
-           abort ();
-         }
-       break;
-
-      /* Output ~CONST_INT.  */
-      case 'N':
-       if (GET_CODE (x) != CONST_INT)
-         abort ();
-        fprintf (file, "%d", ~INTVAL (x));
-        break;
-
-      /* An address which can not be register indirect, if it is
-        register indirect, then turn it into reg + disp.  */
-      case 'A':
-       if (GET_CODE (x) != MEM)
-         abort ();
-       if (GET_CODE (XEXP (x, 0)) == REG)
-         x = gen_rtx_PLUS (PSImode, XEXP (x, 0), GEN_INT (0));
-       else
-         x = XEXP (x, 0);
-       fputc ('(', file);
-       output_address (x);
-       fputc (')', file);
-       break;
-
-      case 'Z':
-        print_operand (file, XEXP (x, 1), 0);
-       break;
-
-      /* More cases where we can sign-extend a CONST_INT if it
-        results in more compact code.  */
-      case 's':
-      case 'S':
-       if (GET_CODE (x) == CONST_INT)
-         {
-           int val = INTVAL (x);
-
-           if (code == 's')
-             x = GEN_INT (((val & 0xffff) ^ (~0x7fff)) + 0x8000);
-           else
-             x = GEN_INT (((val & 0xff) ^ (~0x7f)) + 0x80);
-         }
-        /* FALL THROUGH */
-      default:
-       switch (GET_CODE (x))
-         {
-         case MEM:
-           fputc ('(', file);
-           output_address (XEXP (x, 0));
-           fputc (')', file);
-           break;
-
-         case REG:
-           fprintf (file, "%s", reg_names[REGNO (x)]);
-           break;
-
-         case SUBREG:
-           fprintf (file, "%s", reg_names[subreg_regno (x)]);
-           break;
-
-         case CONST_INT:
-         case CONST_DOUBLE:
-         case SYMBOL_REF:
-         case CONST:
-         case LABEL_REF:
-         case CODE_LABEL:
-           print_operand_address (file, x);
-           break;
-         default:
-           abort ();
-         }
-       break;
-   }
-}
-
-/* Output assembly language output for the address ADDR to FILE.  */
-
-void
-print_operand_address (file, addr)
-     FILE *file;
-     rtx addr;
-{
-  switch (GET_CODE (addr))
-    {
-    case REG:
-      print_operand (file, addr, 0);
-      break;
-    case PLUS:
-      {
-       rtx base, index;
-       /* The base and index could be in any order, so we have
-          to figure out which is the base and which is the index.
-          Uses the same code as GO_IF_LEGITIMATE_ADDRESS.  */
-       if (REG_P (XEXP (addr, 0))
-           && REG_OK_FOR_BASE_P (XEXP (addr, 0)))
-         base = XEXP (addr, 0), index = XEXP (addr, 1);
-       else if (REG_P (XEXP (addr, 1))
-           && REG_OK_FOR_BASE_P (XEXP (addr, 1)))
-         base = XEXP (addr, 1), index = XEXP (addr, 0);
-       else
-         abort ();
-       print_operand (file, index, 0);
-       fputc (',', file);
-       print_operand (file, base, 0);;
-       break;
-      }
-    case SYMBOL_REF:
-      output_addr_const (file, addr);
-      break;
-    default:
-      output_addr_const (file, addr);
-      break;
-    }
-}
-
-/* Count the number of tst insns which compare an address register
-   with zero.  */
-static void 
-count_tst_insns (areg_countp)
-     int *areg_countp;
-{
-  rtx insn;
-
-  /* Assume no tst insns exist.  */
-  *areg_countp = 0;
-
-  /* If not optimizing, then quit now.  */
-  if (!optimize)
-    return;
-
-  /* Walk through all the insns.  */
-  for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
-    {
-      rtx pat;
-
-      /* Ignore anything that is not a normal INSN.  */
-      if (GET_CODE (insn) != INSN)
-       continue;
-
-      /* Ignore anything that isn't a SET.  */
-      pat = PATTERN (insn);
-      if (GET_CODE (pat) != SET)
-       continue;
-
-      /* Check for a tst insn.  */
-      if (SET_DEST (pat) == cc0_rtx
-         && GET_CODE (SET_SRC (pat)) == REG
-         && REGNO_REG_CLASS (REGNO (SET_SRC (pat))) == ADDRESS_REGS)
-       (*areg_countp)++;
-    }
-}
-
-/* Return the total size (in bytes) of the current function's frame.
-   This is the size of the register save area + the size of locals,
-   spills, etc.  */
-int
-total_frame_size ()
-{
-  unsigned int size = get_frame_size ();
-  unsigned int outgoing_args_size = current_function_outgoing_args_size;
-  int i;
-
-  /* First figure out if we're going to use an out of line
-     prologue, if so we have to make space for all the
-     registers, even if we don't use them.  */
-  if (optimize && !current_function_needs_context && !frame_pointer_needed)
-    {
-      int inline_count, outline_count;
-
-      /* Compute how many bytes an inline prologue would take.
-
-         Each address register store takes two bytes, each data register
-        store takes three bytes.  */
-      inline_count = 0;
-      if (regs_ever_live[5])
-       inline_count += 2;
-      if (regs_ever_live[6])
-       inline_count += 2;
-      if (regs_ever_live[2])
-       inline_count += 3;
-      if (regs_ever_live[3])
-       inline_count += 3;
-
-      /* If this function has any stack, then the stack adjustment
-        will take two (or more) bytes.  */
-      if (size || outgoing_args_size
-         || regs_ever_live[5] || regs_ever_live[6]
-         || regs_ever_live[2] || regs_ever_live[3])
-      inline_count += 2;
-
-      /* Multiply the current count by two and add one to account for the
-        epilogue insns.  */
-      inline_count = inline_count * 2 + 1;
-    
-      /* Now compute how many bytes an out of line sequence would take.  */
-      /* A relaxed jsr will be three bytes.  */
-      outline_count = 3;
-
-      /* If there are outgoing arguments, then we will need a stack
-        pointer adjustment after the call to the prologue, two
-        more bytes.  */
-      outline_count += (outgoing_args_size == 0 ? 0 : 2);
-
-      /* If there is some local frame to allocate, it will need to be
-        done before the call to the prologue, two more bytes.  */
-      if (get_frame_size () != 0)
-       outline_count += 2;
-
-      /* Now account for the epilogue, multiply the base count by two,
-        then deal with optimizing away the rts instruction.  */
-      outline_count = outline_count * 2 + 1;
-
-      if (get_frame_size () == 0 && outgoing_args_size == 0)
-       outline_count -= 1;
-
-      /* If an out of line prologue is smaller, use it.  */
-      if (inline_count > outline_count)
-       return size + outgoing_args_size + 16;
-    }
-
-
-  for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
-    {
-      if ((regs_ever_live[i] && !call_used_regs[i] && ! fixed_regs[i])
-         || (i == FRAME_POINTER_REGNUM && frame_pointer_needed))
-       size += 4;
-    }
-
-  return (size + outgoing_args_size);
-}
-
-/* Expand the prologue into RTL.  */
-void
-expand_prologue ()
-{
-  unsigned int size = total_frame_size ();
-  unsigned int outgoing_args_size = current_function_outgoing_args_size;
-  int offset, i;
-
-  zero_areg = NULL_RTX;
-  zero_dreg = NULL_RTX;
-
-  /* If optimizing, see if we should do an out of line prologue/epilogue
-     sequence.
-
-     We don't support out of line prologues if the current function
-     needs a context or frame pointer.  */
-  if (optimize && !current_function_needs_context && !frame_pointer_needed)
-    {
-      int inline_count, outline_count, areg_count;
-
-      /* We need to end the current sequence so that count_tst_insns can
-        look at all the insns in this function.  Normally this would be
-        unsafe, but it's OK in the prologue/epilogue expanders.  */
-      end_sequence ();
-
-      /* Get a count of the number of tst insns which use address
-        registers (it's not profitable to try and improve tst insns
-        which use data registers).  */
-      count_tst_insns (&areg_count);
-
-      /* Now start a new sequence.  */
-      start_sequence ();
-
-      /* Compute how many bytes an inline prologue would take.
-
-         Each address register store takes two bytes, each data register
-        store takes three bytes.  */
-      inline_count = 0;
-      if (regs_ever_live[5])
-       inline_count += 2;
-      if (regs_ever_live[6])
-       inline_count += 2;
-      if (regs_ever_live[2])
-       inline_count += 3;
-      if (regs_ever_live[3])
-       inline_count += 3;
-
-      /* If this function has any stack, then the stack adjustment
-        will take two (or more) bytes.  */
-      if (size || outgoing_args_size
-         || regs_ever_live[5] || regs_ever_live[6]
-         || regs_ever_live[2] || regs_ever_live[3])
-      inline_count += 2;
-
-      /* Multiply the current count by two and add one to account for the
-        epilogue insns.  */
-      inline_count = inline_count * 2 + 1;
-    
-      /* Now compute how many bytes an out of line sequence would take.  */
-      /* A relaxed jsr will be three bytes.  */
-      outline_count = 3;
-
-      /* If there are outgoing arguments, then we will need a stack
-        pointer adjustment after the call to the prologue, two
-        more bytes.  */
-      outline_count += (outgoing_args_size == 0 ? 0 : 2);
-
-      /* If there is some local frame to allocate, it will need to be
-        done before the call to the prologue, two more bytes.  */
-      if (get_frame_size () != 0)
-       outline_count += 2;
-
-      /* Now account for the epilogue, multiply the base count by two,
-        then deal with optimizing away the rts instruction.  */
-      outline_count = outline_count * 2 + 1;
-
-      if (get_frame_size () == 0 && outgoing_args_size == 0)
-       outline_count -= 1;
-     
-      /* If an out of line prologue is smaller, use it.  */
-      if (inline_count > outline_count)
-       {
-         if (get_frame_size () != 0)
-           emit_insn (gen_addpsi3 (stack_pointer_rtx, stack_pointer_rtx,
-                                   GEN_INT (-size + outgoing_args_size + 16)));
-         emit_insn (gen_outline_prologue_call ());
-
-         if (outgoing_args_size)
-           emit_insn (gen_addpsi3 (stack_pointer_rtx, stack_pointer_rtx,
-                                   GEN_INT (-outgoing_args_size)));
-       
-         out_of_line_epilogue = 1;
-
-         /* Determine if it is profitable to put the value zero into a register
-            for the entire function.  If so, set ZERO_DREG and ZERO_AREG.  */
-
-         /* First see if we could load the value into a data register
-            since that's the most efficient way.  */
-         if (areg_count > 1
-             && (!regs_ever_live[2] || !regs_ever_live[3]))
-           {
-             if (!regs_ever_live[2])
-               {
-                 regs_ever_live[2] = 1;
-                 zero_dreg = gen_rtx_REG (HImode, 2);
-               }
-             if (!regs_ever_live[3])
-               {
-                 regs_ever_live[3] = 1;
-                 zero_dreg = gen_rtx_REG (HImode, 3);
-               }
-           }
-
-         /* Now see if we could load the value into an address register.  */
-         if (zero_dreg == NULL_RTX
-             && areg_count > 2
-             && (!regs_ever_live[5] || !regs_ever_live[6]))
-           {
-             if (!regs_ever_live[5])
-               {
-                 regs_ever_live[5] = 1;
-                 zero_areg = gen_rtx_REG (HImode, 5);
-               }
-             if (!regs_ever_live[6])
-               {
-                 regs_ever_live[6] = 1;
-                 zero_areg = gen_rtx_REG (HImode, 6);
-               }
-           }
-
-         if (zero_dreg)
-           emit_move_insn (zero_dreg, const0_rtx);
-
-         if (zero_areg)
-           emit_move_insn (zero_areg, const0_rtx);
-
-         return;
-       }
-    }
-
-  out_of_line_epilogue = 0;
-
-  /* Temporarily stuff the static chain onto the stack so we can
-     use a0 as a scratch register during the prologue.  */
-  if (current_function_needs_context)
-    {
-      emit_insn (gen_addpsi3 (stack_pointer_rtx, stack_pointer_rtx,
-                             GEN_INT (-4)));
-      emit_move_insn (gen_rtx_MEM (PSImode, stack_pointer_rtx),
-                     gen_rtx_REG (PSImode, STATIC_CHAIN_REGNUM));
-    }
-
-  if (frame_pointer_needed)
-    {
-      /* Store a2 into a0 temporarily.  */
-      emit_move_insn (gen_rtx_REG (PSImode, 4), frame_pointer_rtx);
-
-      /* Set up the frame pointer.  */
-      emit_move_insn (frame_pointer_rtx, stack_pointer_rtx);
-    }
-
-  /* Make any necessary space for the saved registers and local frame.  */
-  if (size)
-    emit_insn (gen_addpsi3 (stack_pointer_rtx, stack_pointer_rtx,
-                           GEN_INT (-size)));
-
-  /* Save the callee saved registers.  They're saved into the top
-     of the frame, using the stack pointer.  */
-  for (i = 0, offset = outgoing_args_size;
-       i < FIRST_PSEUDO_REGISTER; i++)
-    {
-      if ((regs_ever_live[i] && !call_used_regs[i] && ! fixed_regs[i])
-         || (i == FRAME_POINTER_REGNUM && frame_pointer_needed))
-       {
-         int regno;
-
-         /* If we're saving the frame pointer, then it will be found in
-            register 4 (a0).  */
-         regno = (i == FRAME_POINTER_REGNUM && frame_pointer_needed) ? 4 : i;
-       
-         emit_move_insn (gen_rtx_MEM (PSImode,
-                                      plus_constant (stack_pointer_rtx,
-                                                     offset)),
-                         gen_rtx_REG (PSImode, regno));
-         offset += 4;
-       }
-    }
-
-  /* Now put the static chain back where the rest of the function
-     expects to find it.  */
-  if (current_function_needs_context)
-    {
-      emit_move_insn (gen_rtx_REG (PSImode, STATIC_CHAIN_REGNUM),
-                     gen_rtx (MEM, PSImode,
-                              gen_rtx_PLUS (PSImode, stack_pointer_rtx,
-                                            GEN_INT (size))));
-    }
-}
-
-/* Expand the epilogue into RTL.  */
-void
-expand_epilogue ()
-{
-  unsigned int size;
-  unsigned int outgoing_args_size = current_function_outgoing_args_size;
-  int offset, i, temp_regno;
-  rtx basereg;
-
-  size = total_frame_size ();
-
-  if (DECL_RESULT (current_function_decl)
-      && DECL_RTL (DECL_RESULT (current_function_decl))
-      && REG_P (DECL_RTL (DECL_RESULT (current_function_decl))))
-    temp_regno = (REGNO (DECL_RTL (DECL_RESULT (current_function_decl))) == 4
-                 ? 0 : 4);
-  else
-    temp_regno = 4;
-
-  /* Emit an out of line epilogue sequence if it's profitable to do so.  */
-  if (out_of_line_epilogue)
-    {
-      /* If there were no outgoing arguments and no local frame, then
-        we will be able to omit the rts at the end of this function,
-        so just jump to the epilogue_noreturn routine.  */
-      if (get_frame_size () == 0 && outgoing_args_size == 0)
-       {
-         emit_jump_insn (gen_outline_epilogue_jump ());
-         return;
-       }
-
-      if (outgoing_args_size)
-       emit_insn (gen_addpsi3 (stack_pointer_rtx, stack_pointer_rtx,
-                               GEN_INT (outgoing_args_size)));
-
-      if (temp_regno == 0)
-       emit_insn (gen_outline_epilogue_call_d0 ());
-      else if (temp_regno == 4)
-       emit_insn (gen_outline_epilogue_call_a0 ());
-
-      if (get_frame_size () != 0)
-       emit_insn (gen_addpsi3 (stack_pointer_rtx, stack_pointer_rtx,
-                               GEN_INT (size - outgoing_args_size - 16)));
-      emit_jump_insn (gen_return_internal ());
-      return;
-    }
-
-  /* Registers are restored from the frame pointer if we have one,
-     else they're restored from the stack pointer.  Figure out
-     the appropriate offset to the register save area for both cases.  */
-  if (frame_pointer_needed)
-    {
-      basereg = frame_pointer_rtx;
-      offset = -(size - outgoing_args_size);
-    }
-  else
-    {
-      basereg = stack_pointer_rtx;
-      offset = outgoing_args_size;
-    }
-
-  /* Restore each register.  */
-  for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
-    {
-      if ((regs_ever_live[i] && !call_used_regs[i] && ! fixed_regs[i])
-         || (i == FRAME_POINTER_REGNUM && frame_pointer_needed))
-       {
-         int regno;
-
-         /* Restore the frame pointer (if it exists) into a temporary
-            register.  */
-         regno = ((i == FRAME_POINTER_REGNUM && frame_pointer_needed)
-                  ? temp_regno : i);
-       
-         emit_move_insn (gen_rtx_REG (PSImode, regno),
-                         gen_rtx_MEM (PSImode,
-                                      plus_constant (basereg, offset)));
-         offset += 4;
-       }
-    }
-
-  if (frame_pointer_needed)
-    {
-      /* Deallocate this frame's stack.  */
-      emit_move_insn (stack_pointer_rtx, frame_pointer_rtx);
-      /* Restore the old frame pointer.  */
-      emit_move_insn (frame_pointer_rtx, gen_rtx_REG (PSImode, temp_regno));
-    }
-  else if (size)
-    {
-      /* Deallocate this function's stack.  */
-      emit_insn (gen_addpsi3 (stack_pointer_rtx, stack_pointer_rtx,
-                             GEN_INT (size)));
-    }
-
-  /* If we had to allocate a slot to save the context pointer,
-     then it must be deallocated here.  */
-  if (current_function_needs_context)
-    emit_insn (gen_addpsi3 (stack_pointer_rtx, stack_pointer_rtx, GEN_INT (4)));
-
-  /* Emit the return insn, if this function had no stack, then we
-     can use the standard return (which allows more optimizations),
-     else we have to use the special one which inhibits optimizations.  */
-  if (size == 0 && !current_function_needs_context)
-    emit_jump_insn (gen_return ());
-  else
-    emit_jump_insn (gen_return_internal ());
-}
-
-/* Update the condition code from the insn.  */
-
-void
-notice_update_cc (body, insn)
-     rtx body;
-     rtx insn;
-{
-  switch (get_attr_cc (insn))
-    {
-    case CC_NONE:
-      /* Insn does not affect CC at all.  */
-      break;
-
-    case CC_NONE_0HIT:
-      /* Insn does not change CC, but the 0'th operand has been changed.  */
-      if (cc_status.value1 != 0
-         && reg_overlap_mentioned_p (recog_data.operand[0], cc_status.value1))
-       cc_status.value1 = 0;
-      break;
-
-    case CC_SET_ZN:
-      /* Insn sets the Z,N flags of CC to recog_data.operand[0].
-        V,C is in an unusable state.  */
-      CC_STATUS_INIT;
-      cc_status.flags |= CC_OVERFLOW_UNUSABLE | CC_NO_CARRY;
-      cc_status.value1 = recog_data.operand[0];
-      break;
-
-    case CC_SET_ZNV:
-      /* Insn sets the Z,N,V flags of CC to recog_data.operand[0].
-        C is in an unusable state.  */
-      CC_STATUS_INIT;
-      cc_status.flags |= CC_NO_CARRY;
-      cc_status.value1 = recog_data.operand[0];
-      break;
-
-    case CC_COMPARE:
-      /* The insn is a compare instruction.  */
-      CC_STATUS_INIT;
-      cc_status.value1 = SET_SRC (body);
-      break;
-
-    case CC_CLOBBER:
-      /* Insn doesn't leave CC in a usable state.  */
-      CC_STATUS_INIT;
-      break;
-
-    default:
-      CC_STATUS_INIT;
-      break;
-    }
-}
-
-/* Return true if OP is a valid call operand.  Valid call operands
-   are SYMBOL_REFs and REGs.  */
-int
-call_address_operand (op, mode)
-     rtx op;
-     enum machine_mode mode ATTRIBUTE_UNUSED;
-{
-  return (GET_CODE (op) == SYMBOL_REF || GET_CODE (op) == REG);
-}
-
-/* Return true if OP is a memory operand with a constant address.
-   A special PSImode move pattern uses this predicate.  */
-int
-constant_memory_operand (op, mode)
-     rtx op;
-     enum machine_mode mode ATTRIBUTE_UNUSED;
-{
-  return GET_CODE (op) == MEM && CONSTANT_ADDRESS_P (XEXP (op, 0));
-}
-
-/* Return true if OP is valid for a psi mode truncation operand.
-   It must either be a memory operand which is valid for a PSImode
-   address, or if it is not a memory operand at all.  */
-int
-psimode_truncation_operand (op, mode)
-     rtx op;
-     enum machine_mode mode;
-{
-  return (general_operand (op, mode)
-         && (GET_CODE (op) != MEM
-             || memory_address_p (PSImode, XEXP (op, 0))));
-}
-
-/* What (if any) secondary registers are needed to move IN with mode
-   MODE into a register from in register class CLASS. 
-
-   We might be able to simplify this.  */
-enum reg_class
-secondary_reload_class (class, mode, in, input)
-     enum reg_class class;
-     enum machine_mode mode;
-     rtx in;
-     int input;
-{
-  /* Memory loads less than a full word wide can't have an
-     address or stack pointer destination.  They must use
-     a data register as an intermediate register.  */
-  if (input
-      && GET_CODE (in) == MEM
-      && (mode == QImode)
-      && class == ADDRESS_REGS)
-    return DATA_REGS;
-
-  /* Address register stores which are not PSImode need a scratch register.  */
-  if (! input
-      && GET_CODE (in) == MEM
-      && (mode != PSImode)
-      && class == ADDRESS_REGS)
-    return DATA_REGS;
-
-  /* Otherwise assume no secondary reloads are needed.  */
-  return NO_REGS;
-}
-
-\f
-/* Shifts.
-
-   We devote a fair bit of code to getting efficient shifts since we can only
-   shift one bit at a time, and each single bit shift may take multiple
-   instructions.
-
-   The basic shift methods:
-
-     * loop shifts -- emit a loop using one (or two on H8/S) bit shifts;
-     this is the default.  SHIFT_LOOP
-
-     * inlined shifts -- emit straight line code for the shift; this is
-     used when a straight line shift is about the same size or smaller
-     than a loop.  We allow the inline version to be slightly longer in
-     some cases as it saves a register.  SHIFT_INLINE
-
-     * There other oddballs.  Not worth explaining.  SHIFT_SPECIAL
-
-
-   HImode shifts:
-
-     1-4    do them inline
-
-     5-7    If ashift, then multiply, else loop.
-       
-     8-14 - If ashift, then multiply, if lshiftrt, then divide, else loop.
-     15   - rotate the bit we want into the carry, clear the destination,
-           (use mov 0,dst, not sub as sub will clobber the carry), then
-           move bit into place.
-
-   Don't Panic, it's not nearly as bad as the H8 shifting code!!!  */
-
-int
-nshift_operator (x, mode)
-     rtx x;
-     enum machine_mode mode ATTRIBUTE_UNUSED;
-{
-  switch (GET_CODE (x))
-    {
-    case ASHIFTRT:
-    case LSHIFTRT:
-    case ASHIFT:
-      return 1;
-
-    default:
-      return 0;
-    }
-}
-
-/* Called from the .md file to emit code to do shifts.
-   Returns a boolean indicating success
-   (currently this is always TRUE).  */
-
-int
-expand_a_shift (mode, code, operands)
-     enum machine_mode mode;
-     int code;
-     rtx operands[];
-{
-  emit_move_insn (operands[0], operands[1]);
-
-  /* need a loop to get all the bits we want  - we generate the
-     code at emit time, but need to allocate a scratch reg now  */
-
-  emit_insn (gen_rtx_PARALLEL
-            (VOIDmode,
-             gen_rtvec (2,
-                        gen_rtx_SET (VOIDmode, operands[0],
-                                     gen_rtx (code, mode,
-                                              operands[0], operands[2])),
-                        gen_rtx_CLOBBER (VOIDmode,
-                                         gen_rtx_SCRATCH (HImode)))));
-
-  return 1;
-}
-
-/* Shift algorithm determination.
-
-   There are various ways of doing a shift:
-   SHIFT_INLINE: If the amount is small enough, just generate as many one-bit
-                 shifts as we need.
-   SHIFT_SPECIAL: Hand crafted assembler.
-   SHIFT_LOOP:    If the above methods fail, just loop.  */
-
-enum shift_alg
-{
-  SHIFT_INLINE,
-  SHIFT_SPECIAL,
-  SHIFT_LOOP,
-  SHIFT_MAX
-};
-
-/* Symbols of the various shifts which can be used as indices.  */
-
-enum shift_type
-  {
-    SHIFT_ASHIFT, SHIFT_LSHIFTRT, SHIFT_ASHIFTRT
-  };
-
-/* Symbols of the various modes which can be used as indices.  */
-
-enum shift_mode
-  {
-    HIshift
-  };
-
-/* For single bit shift insns, record assembler and what bits of the
-   condition code are valid afterwards (represented as various CC_FOO
-   bits, 0 means CC isn't left in a usable state).  */
-
-struct shift_insn
-{
-  const char *assembler;
-  int cc_valid;
-};
-
-/* Assembler instruction shift table.
-
-   These tables are used to look up the basic shifts.
-   They are indexed by cpu, shift_type, and mode.
-*/
-
-static const struct shift_insn shift_one[3][3] =
-{
-  {
-/* SHIFT_ASHIFT */
-      { "add\t%0,%0", CC_OVERFLOW_UNUSABLE | CC_NO_CARRY },
-  },
-/* SHIFT_LSHIFTRT */
-  {
-      { "lsr\t%0", CC_NO_CARRY },
-  },
-/* SHIFT_ASHIFTRT */
-  {
-      { "asr\t%0", CC_NO_CARRY },
-  },
-};
-
-static enum shift_alg get_shift_alg PARAMS ((enum shift_type,
-                                            enum machine_mode, int,
-                                            const char **, int *));
-
-/* Given CPU, MODE, SHIFT_TYPE, and shift count COUNT, determine the best
-   algorithm for doing the shift.  The assembler code is stored in ASSEMBLER.
-   We don't achieve maximum efficiency in all cases, but the hooks are here
-   to do so.
-
-   For now we just use lots of switch statements.  Since we don't even come
-   close to supporting all the cases, this is simplest.  If this function ever
-   gets too big, perhaps resort to a more table based lookup.  Of course,
-   at this point you may just wish to do it all in rtl.  */
-
-static enum shift_alg
-get_shift_alg (shift_type, mode, count, assembler_p, cc_valid_p)
-     enum shift_type shift_type;
-     enum machine_mode mode;
-     int count;
-     const char **assembler_p;
-     int *cc_valid_p;
-{
-  /* The default is to loop.  */
-  enum shift_alg alg = SHIFT_LOOP;
-  enum shift_mode shift_mode;
-
-  /* We don't handle negative shifts or shifts greater than the word size,
-     they should have been handled already.  */
-
-  if (count < 0 || count > GET_MODE_BITSIZE (mode))
-    abort ();
-
-  switch (mode)
-    {
-    case HImode:
-      shift_mode = HIshift;
-      break;
-    default:
-      abort ();
-    }
-
-  /* Assume either SHIFT_LOOP or SHIFT_INLINE.
-     It is up to the caller to know that looping clobbers cc.  */
-  *assembler_p = shift_one[shift_type][shift_mode].assembler;
-  *cc_valid_p = shift_one[shift_type][shift_mode].cc_valid;
-
-  /* Now look for cases we want to optimize.  */
-
-  switch (shift_mode)
-    {
-    case HIshift:
-      if (count <= 4)
-       return SHIFT_INLINE;
-      else if (count < 15 && shift_type != SHIFT_ASHIFTRT)
-       {
-         switch (count)
-           {
-           case 5:
-             if (shift_type == SHIFT_ASHIFT)
-               *assembler_p = "mov 32,%4\n\tmul %4,%0";
-             else if (shift_type == SHIFT_LSHIFTRT)
-               *assembler_p
-                 = "sub %4,%4\n\tmov %4,mdr\n\tmov 32,%4\n\tdivu %4,%0";
-             *cc_valid_p = CC_NO_CARRY;
-             return SHIFT_SPECIAL;
-           case 6:
-             if (shift_type == SHIFT_ASHIFT)
-               *assembler_p = "mov 64,%4\n\tmul %4,%0";
-             else if (shift_type == SHIFT_LSHIFTRT)
-               *assembler_p
-                 = "sub %4,%4\n\tmov %4,mdr\n\tmov 64,%4\n\tdivu %4,%0";
-             *cc_valid_p = CC_NO_CARRY;
-             return SHIFT_SPECIAL;
-           case 7:
-             if (shift_type == SHIFT_ASHIFT)
-               *assembler_p = "mov 128,%4\n\tmul %4,%0";
-             else if (shift_type == SHIFT_LSHIFTRT)
-               *assembler_p
-                 = "sub %4,%4\n\tmov %4,mdr\n\tmov 128,%4\n\tdivu %4,%0";
-             *cc_valid_p = CC_NO_CARRY;
-             return SHIFT_SPECIAL;
-           case 8:
-             if (shift_type == SHIFT_ASHIFT)
-               *assembler_p = "mov 256,%4\n\tmul %4,%0";
-             else if (shift_type == SHIFT_LSHIFTRT)
-               *assembler_p
-                 = "sub %4,%4\n\tmov %4,mdr\n\tmov 256,%4\n\tdivu %4,%0";
-             *cc_valid_p = CC_NO_CARRY;
-             return SHIFT_SPECIAL;
-           case 9:
-             if (shift_type == SHIFT_ASHIFT)
-               *assembler_p = "mov 512,%4\n\tmul %4,%0";
-             else if (shift_type == SHIFT_LSHIFTRT)
-               *assembler_p
-                 = "sub %4,%4\n\tmov %4,mdr\n\tmov 512,%4\n\tdivu %4,%0";
-             *cc_valid_p = CC_NO_CARRY;
-             return SHIFT_SPECIAL;
-           case 10:
-             if (shift_type == SHIFT_ASHIFT)
-               *assembler_p = "mov 1024,%4\n\tmul %4,%0";
-             else if (shift_type == SHIFT_LSHIFTRT)
-               *assembler_p
-                 = "sub %4,%4\n\tmov %4,mdr\n\tmov 1024,%4\n\tdivu %4,%0";
-             *cc_valid_p = CC_NO_CARRY;
-             return SHIFT_SPECIAL;
-           case 11:
-             if (shift_type == SHIFT_ASHIFT)
-               *assembler_p = "mov 2048,%4\n\tmul %4,%0";
-             else if (shift_type == SHIFT_LSHIFTRT)
-               *assembler_p
-                 = "sub %4,%4\n\tmov %4,mdr\n\tmov 2048,%4\n\tdivu %4,%0";
-             *cc_valid_p = CC_NO_CARRY;
-             return SHIFT_SPECIAL;
-           case 12:
-             if (shift_type == SHIFT_ASHIFT)
-               *assembler_p = "mov 4096,%4\n\tmul %4,%0";
-             else if (shift_type == SHIFT_LSHIFTRT)
-               *assembler_p
-                 = "sub %4,%4\n\tmov %4,mdr\n\tmov 4096,%4\n\tdivu %4,%0";
-             *cc_valid_p = CC_NO_CARRY;
-             return SHIFT_SPECIAL;
-           case 13:
-             if (shift_type == SHIFT_ASHIFT)
-               *assembler_p = "mov 8192,%4\n\tmul %4,%0";
-             else if (shift_type == SHIFT_LSHIFTRT)
-               *assembler_p
-                 = "sub %4,%4\n\tmov %4,mdr\n\tmov 8192,%4\n\tdivu %4,%0";
-             *cc_valid_p = CC_NO_CARRY;
-             return SHIFT_SPECIAL;
-           case 14:
-             if (shift_type == SHIFT_ASHIFT)
-               *assembler_p = "mov 16384,%4\n\tmul %4,%0";
-             else if (shift_type == SHIFT_LSHIFTRT)
-               *assembler_p
-                 = "sub %4,%4\n\tmov %4,mdr\n\tmov 16384,%4\n\tdivu %4,%0";
-             *cc_valid_p = CC_NO_CARRY;
-             return SHIFT_SPECIAL;
-           }
-       }
-      else if (count == 15)
-       {
-          if (shift_type == SHIFT_ASHIFTRT)
-            {
-              *assembler_p = "add\t%0,%0\n\tsubc\t%0,%0\n";
-              *cc_valid_p = CC_NO_CARRY;
-              return SHIFT_SPECIAL;
-           }
-          if (shift_type == SHIFT_LSHIFTRT)
-            {
-              *assembler_p = "add\t%0,%0\n\tmov 0,%0\n\trol %0\n";
-              *cc_valid_p = CC_NO_CARRY;
-              return SHIFT_SPECIAL;
-           }
-          if (shift_type == SHIFT_ASHIFT)
-            {
-              *assembler_p = "ror\t%0\n\tmov 0,%0\n\tror %0\n";
-              *cc_valid_p = CC_NO_CARRY;
-              return SHIFT_SPECIAL;
-           }
-       }
-      break;
-
-    default:
-      abort ();
-    }
-
-  return alg;
-}
-
-/* Emit the assembler code for doing shifts.  */
-
-const char *
-emit_a_shift (insn, operands)
-     rtx insn ATTRIBUTE_UNUSED;
-     rtx *operands;
-{
-  static int loopend_lab;
-  const char *assembler;
-  int cc_valid;
-  rtx shift = operands[3];
-  enum machine_mode mode = GET_MODE (shift);
-  enum rtx_code code = GET_CODE (shift);
-  enum shift_type shift_type;
-  enum shift_mode shift_mode;
-
-  loopend_lab++;
-
-  switch (mode)
-    {
-    case HImode:
-      shift_mode = HIshift;
-      break;
-    default:
-      abort ();
-    }
-
-  switch (code)
-    {
-    case ASHIFTRT:
-      shift_type = SHIFT_ASHIFTRT;
-      break;
-    case LSHIFTRT:
-      shift_type = SHIFT_LSHIFTRT;
-      break;
-    case ASHIFT:
-      shift_type = SHIFT_ASHIFT;
-      break;
-    default:
-      abort ();
-    }
-
-  if (GET_CODE (operands[2]) != CONST_INT)
-    {
-      /* Indexing by reg, so have to loop and test at top */
-      output_asm_insn ("mov    %2,%4", operands);
-      output_asm_insn ("cmp    0,%4", operands);
-      fprintf (asm_out_file, "\tble    .Lle%d\n", loopend_lab);
-
-      /* Get the assembler code to do one shift.  */
-      get_shift_alg (shift_type, mode, 1, &assembler, &cc_valid);
-    }
-  else
-    {
-      int n = INTVAL (operands[2]);
-      enum shift_alg alg;
-
-      /* If the count is negative, make it 0.  */
-      if (n < 0)
-       n = 0;
-      /* If the count is too big, truncate it.
-         ANSI says shifts of GET_MODE_BITSIZE are undefined - we choose to
-        do the intuitive thing.  */
-      else if (n > GET_MODE_BITSIZE (mode))
-       n = GET_MODE_BITSIZE (mode);
-
-      alg = get_shift_alg (shift_type, mode, n, &assembler, &cc_valid);
-
-
-      switch (alg)
-       {
-       case SHIFT_INLINE:
-         /* Emit one bit shifts.  */
-         while (n > 0)
-           {
-             output_asm_insn (assembler, operands);
-             n -= 1;
-           }
-
-         /* Keep track of CC.  */
-         if (cc_valid)
-           {
-             cc_status.value1 = operands[0];
-             cc_status.flags |= cc_valid;
-           }
-         return "";
-
-       case SHIFT_SPECIAL:
-         output_asm_insn (assembler, operands);
-
-         /* Keep track of CC.  */
-         if (cc_valid)
-           {
-             cc_status.value1 = operands[0];
-             cc_status.flags |= cc_valid;
-           }
-         return "";
-       }
-
-       {
-         fprintf (asm_out_file, "\tmov %d,%s\n", n,
-                  reg_names[REGNO (operands[4])]);
-         fprintf (asm_out_file, ".Llt%d:\n", loopend_lab);
-         output_asm_insn (assembler, operands);
-         output_asm_insn ("add -1,%4", operands);
-         fprintf (asm_out_file, "\tbne .Llt%d\n", loopend_lab);
-         return "";
-       }
-    }
-
-  fprintf (asm_out_file, ".Llt%d:\n", loopend_lab);
-  output_asm_insn (assembler, operands);
-  output_asm_insn ("add        -1,%4", operands);
-  fprintf (asm_out_file, "\tbne        .Llt%d\n", loopend_lab);
-  fprintf (asm_out_file, ".Lle%d:\n", loopend_lab);
-
-  return "";
-}
-
-/* Return an RTX to represent where a value with mode MODE will be returned
-   from a function.  If the result is 0, the argument is pushed.  */
-
-rtx
-function_arg (cum, mode, type, named)
-     CUMULATIVE_ARGS *cum;
-     enum machine_mode mode;
-     tree type;
-     int named;
-{
-  rtx result = 0;
-  int size, align;
-
-  /* We only support using 2 data registers as argument registers.  */
-  int nregs = 2;
-
-  /* Only pass named arguments in registers.  */
-  if (!named)
-    return NULL_RTX;
-
-  /* Figure out the size of the object to be passed.  We lie and claim
-     PSImode values are only two bytes since they fit in a single
-     register.  */
-  if (mode == BLKmode)
-    size = int_size_in_bytes (type);
-  else if (mode == PSImode)
-    size = 2;
-  else
-    size = GET_MODE_SIZE (mode);
-
-  /* Figure out the alignment of the object to be passed.  */
-    align = size;
-
-  cum->nbytes = (cum->nbytes + 1) & ~1;
-
-  /* Don't pass this arg via a register if all the argument registers
-     are used up.  */
-  if (cum->nbytes + size > nregs * UNITS_PER_WORD)
-    return 0;
-
-  switch (cum->nbytes / UNITS_PER_WORD)
-    {
-    case 0:
-      result = gen_rtx_REG (mode, 0);
-      break;
-    case 1:
-      result = gen_rtx_REG (mode, 1);
-      break;
-    default:
-      result = 0;
-    }
-
-  return result;
-}
-
-/* Return the number of registers to use for an argument passed partially
-   in registers and partially in memory.  */
-
-int
-function_arg_partial_nregs (cum, mode, type, named)
-     CUMULATIVE_ARGS *cum;
-     enum machine_mode mode;
-     tree type;
-     int named;
-{
-  int size, align;
-
-  /* We only support using 2 data registers as argument registers.  */
-  int nregs = 2;
-
-  return 0;
-  /* Only pass named arguments in registers.  */
-  if (!named)
-    return 0;
-
-  /* Figure out the size of the object to be passed.  */
-  if (mode == BLKmode)
-    size = int_size_in_bytes (type);
-  else if (mode == PSImode)
-    size = 2;
-  else
-    size = GET_MODE_SIZE (mode);
-
-  /* Figure out the alignment of the object to be passed.  */
-  align = size;
-
-  cum->nbytes = (cum->nbytes + 1) & ~1;
-
-  /* Don't pass this arg via a register if all the argument registers
-     are used up.  */
-  if (cum->nbytes > nregs * UNITS_PER_WORD)
-    return 0;
-
-  if (cum->nbytes + size <= nregs * UNITS_PER_WORD)
-    return 0;
-
-  /* Don't pass this arg via a register if it would be split between
-     registers and memory.  */
-  if (type == NULL_TREE
-      && cum->nbytes + size > nregs * UNITS_PER_WORD)
-    return 0;
-
-  return (nregs * UNITS_PER_WORD - cum->nbytes) / UNITS_PER_WORD;
-}
-
-rtx
-mn10200_va_arg (valist, type)
-     tree valist, type;
-{
-  HOST_WIDE_INT align, rsize;
-  tree t, ptr, pptr;
-
-  /* Compute the rounded size of the type.  */
-  align = PARM_BOUNDARY / BITS_PER_UNIT;
-  rsize = (((int_size_in_bytes (type) + align - 1) / align) * align);
-
-  t = build (POSTINCREMENT_EXPR, TREE_TYPE (valist), valist, 
-            build_int_2 ((rsize > 8 ? 4 : rsize), 0));
-  TREE_SIDE_EFFECTS (t) = 1;
-
-  ptr = build_pointer_type (type);
-
-  /* "Large" types are passed by reference.  */
-  if (rsize > 8)
-    {
-      pptr = build_pointer_type (ptr);
-      t = build1 (NOP_EXPR, pptr, t);
-      TREE_SIDE_EFFECTS (t) = 1;
-
-      t = build1 (INDIRECT_REF, ptr, t);
-      TREE_SIDE_EFFECTS (t) = 1;
-    }
-  else
-    {
-      t = build1 (NOP_EXPR, ptr, t);
-      TREE_SIDE_EFFECTS (t) = 1;
-    }
-
-  /* Calculate!  */
-  return force_reg (Pmode, expand_expr (t, NULL_RTX, Pmode, EXPAND_NORMAL));
-}
-
-const char *
-output_tst (operand, insn)
-     rtx operand, insn;
-{
-  
-  rtx temp;
-  int past_call = 0;
-
-  /* Only tst insns using address registers can be optimized.  */
-  if (REGNO_REG_CLASS (REGNO (operand)) != ADDRESS_REGS)
-    return "cmp 0,%0";
-
-  /* If testing an address register against zero, we can do better if
-     we know there's a register already holding the value zero.  First
-     see if a global register has been set to zero, else we do a search
-     for a register holding zero, if both of those fail, then we use a
-     compare against zero.  */
-  if (zero_dreg || zero_areg)
-    {
-      rtx xoperands[2];
-      xoperands[0] = operand;
-      xoperands[1] = zero_dreg ? zero_dreg : zero_areg;
-
-      output_asm_insn ("cmp %1,%0", xoperands);
-      return "";
-    }
-
-  /* We can save a byte if we can find a register which has the value
-     zero in it.  */
-  temp = PREV_INSN (insn);
-  while (temp)
-    {
-      rtx set;
-
-      /* We allow the search to go through call insns.  We record
-        the fact that we've past a CALL_INSN and reject matches which
-        use call clobbered registers.  */
-      if (GET_CODE (temp) == CODE_LABEL
-         || GET_CODE (temp) == JUMP_INSN
-         || GET_CODE (temp) == BARRIER)
-       break;
-
-      if (GET_CODE (temp) == CALL_INSN)
-       past_call = 1;
-
-      if (GET_CODE (temp) == NOTE)
-       {
-         temp = PREV_INSN (temp);
-         continue;
-       }
-
-      /* It must be an insn, see if it is a simple set. */
-      set = single_set (temp);
-      if (!set)
-       {
-         temp = PREV_INSN (temp);
-         continue;
-       }
-
-      /* Are we setting a register to zero?
-
-        If it's a call clobbered register, have we past a call?  */
-      if (REG_P (SET_DEST (set))
-         && SET_SRC (set) == CONST0_RTX (GET_MODE (SET_DEST (set)))
-         && !reg_set_between_p (SET_DEST (set), temp, insn)
-         && (!past_call 
-             || !call_used_regs[REGNO (SET_DEST (set))]))
-       {
-         rtx xoperands[2];
-         xoperands[0] = operand;
-         xoperands[1] = SET_DEST (set);
-
-         output_asm_insn ("cmp %1,%0", xoperands);
-         return "";
-       }
-      temp = PREV_INSN (temp);
-    }
-  return "cmp 0,%0";
-}
-
-/* Return nonzero if OP is a valid operand for a {zero,sign}_extendpsisi
-   instruction.
-
-   It accepts anything that is a general operand or the sum of the
-   stack pointer and a general operand.  */
-int
-extendpsi_operand (op, mode)
-     rtx op;
-     enum machine_mode mode;
-{
-  return (general_operand (op, mode)
-         || (GET_CODE (op) == PLUS
-             && XEXP (op, 0) == stack_pointer_rtx
-             && general_operand (XEXP (op, 1), VOIDmode)));
-}