;;- Machine description for the Motorola DSP56600 for GNU C compiler
;;   Copyright ( C ) 1988 Free Software Foundation, Inc.
;;
;; 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 )
;; 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, 675 Mass Ave, Cambridge, MA 02139, USA.

;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.

;;- cpp macro #define NOTICE_UPDATE_CC in file tm.h handles condition code
;;- updates for most instructions.

;;  %letter escapes for operand printing. (via PRINT_OPERAND).
;;  %e - the high 16 bits of a CONST_DOUBLE.
;;  %h - the low 16 bits of a CONST_DOUBLE.
;;  %d - print the accumulator name, disregard MEM_IN_STRUCT kludge.
;;  %e - print 1 after accumulator operand. No affect on non-accum reg.
;;  %f - flip a conditional.
;;  %g - print alternate of x or y half-register.
;;  %h - print 0 after accumulator operand.
;;  %i - strip the 0/1 off an x or y half-register
;;  %j - n register associated with r register.
;;  %k - print 2 after accumulator operand.
;;  %m - print the source reg name, without a trailing 0 or 1, or
;;       print the accumulator name with a trailing 10.

;;  %r - output this as a long size constant.



;;  ...........................................................................
;;          MOVES, LOADS, STORES
    
( define_expand "movqi"
  [ ( set
      ( match_operand:QI 0 "general_operand" "" )
      ( match_operand:QI 1 "general_operand" "" )) ]
  ""
  "
{
    if ( ! really_reg_p ( operands[0] ) && ! really_reg_p ( operands[1] ))
    {
	operands[1] = force_reg ( QImode, operands[1] );
    }
}" )

( define_insn ""
  [ ( set ( match_operand:QI 0 "register_operand" "=r,m,r,r" )
	  ( match_operand:QI 1 "general_operand" "r,r,m,i" )) ]
  ""
  "*
{
    return move_single_integer ( operands );
}" "CAN_ACCEPT_SUBREG_ACC | CCS_NOT_AFFECTED" )

( define_insn ""
  [ ( set
      ( match_operand:QI 0 "general_operand" "=r,m,r,r" )
      ( match_operand:QI 1 "register_operand" "r,r,m,i" )) ]
  ""
  "*
{
    return move_single_integer ( operands );
}" "CAN_ACCEPT_SUBREG_ACC | CCS_NOT_AFFECTED" )


( define_expand "movsi"
  [ ( set
      ( match_operand:SI 0 "general_operand" "" )
      ( match_operand:SI 1 "general_operand" "" )) ]
  ""
  "
{
    if ( ! really_reg_p ( operands[0] ) && ! really_reg_p ( operands[1] ))
    {
	operands[1] = force_reg ( SImode, operands[1] );
    }
}" )

( define_insn ""
  [ ( set
      ( match_operand:SI 0 "register_operand" "=r,m,r,r" )
      ( match_operand:SI 1 "general_operand" "r,r,m,i" )) ]
  ""
  "*
{
    return move_single_integer ( operands );
}" "CAN_ACCEPT_SUBREG_ACC | CCS_NOT_AFFECTED" )

( define_insn ""
  [ ( set
      ( match_operand:SI 0 "general_operand" "=r,m,r,r" )
      ( match_operand:SI 1 "register_operand" "r,r,m,i" )) ]
  ""
  "*
{
    return move_single_integer ( operands );
}" "CAN_ACCEPT_SUBREG_ACC | CCS_NOT_AFFECTED" )

( define_insn ""
  [ ( set
      ( match_operand:SI 0 "general_operand" "=r,m,r,r" )
      ( subreg:SI ( match_operand:DI 1 "register_operand" "SD,SD,m,Gi" ) 0 )) ]
  ""
  "doneit" )

; This came up in user code --- it is intended to handle cases where a label
; plus an offset are being loaded into an address register --- it was
; generalized to all registers ("=r") in case this turns out to be useful.
; This code is generated in the strength reduction optimization (linv+biv)
( define_insn ""
  [ ( set ( match_operand:SI 0 "register_operand" "=r" )
	  ( plus:SI ( match_operand:SI 1 "immediate_operand" "" )
		    ( match_operand:SI 2 "immediate_operand" "" ) ) ) ]
  ""
  "*
{
    return \"move	#>(%1+%2),%0\";
}" );

( define_expand "movdi"
  [ ( set
      ( match_operand:DI 0 "general_operand" "" )
      ( match_operand:DI 1 "general_operand" "" )) ]
  ""
  "
{
    if ( ! really_reg_p ( operands[0] ) && ! really_reg_p ( operands[1] ))
    {
	operands[1] = force_reg ( DImode, operands[1] );
    }
}" )

( define_insn ""
  [ ( set
      ( match_operand:DI 0 "register_operand" "=S,D,S,D,S,D,S,D" )
      ( match_operand:DI 1 "general_operand" "Gi,Gi,m,m,S,S,D,D" )) ]
  ""
  "*
{
    return move_double_integer ( 0, operands );
}" "CAN_ACCEPT_SUBREG_ACC | CCS_NOT_AFFECTED" )

( define_insn ""
  [ ( set
      ( match_operand:DI 0 "general_operand" "=m,m,S,S,D,D" )
      ( match_operand:DI 1 "register_operand" "S,D,S,D,S,D" )) ]
  ""
  "*
{
    return move_double_integer ( 0, operands );
}" "CAN_ACCEPT_SUBREG_ACC | CCS_NOT_AFFECTED" )

( define_expand "movsz"
  [ ( set ( match_operand:SZ 0 "general_operand" "" )
	  ( match_operand:SZ 1 "general_operand" "" )) ]
  "TARGET_C_FOR_DSP"
  "
{
    if ( ! really_reg_p ( operands[0] ) && ! really_reg_p ( operands[1] ))
    {
	operands[1] = force_reg ( SZmode, operands[1] );
    }
}" )

( define_insn ""
  [ ( set ( match_operand:SZ 0 "register_operand" "=r,m,r,r" )
	  ( match_operand:SZ 1 "general_operand" "r,r,m,i" )) ]
  "TARGET_C_FOR_DSP"
  "*
{
    return move_single_fraction ( operands );
}" "CAN_ACCEPT_SUBREG_ACC | CCS_NOT_AFFECTED" )

( define_insn ""
  [ ( set ( match_operand:SZ 0 "general_operand" "=r,m,r,r" )
	  ( match_operand:SZ 1 "register_operand" "r,r,m,i" )) ]
  "TARGET_C_FOR_DSP"
  "*
{
    return move_single_fraction ( operands );
}" "CAN_ACCEPT_SUBREG_ACC | CCS_NOT_AFFECTED" )

( define_expand "movdz"
  [ ( set ( match_operand:DZ 0 "general_operand" "" )
	  ( match_operand:DZ 1 "general_operand" "" )) ]
  "TARGET_C_FOR_DSP"
  "
{
    if ( ! really_reg_p ( operands[0] ) && ! really_reg_p ( operands[1] ))
    {
	operands[1] = force_reg ( DZmode, operands[1] );
    }
}" )

( define_insn ""
  [ ( set ( match_operand:DZ 0 "register_operand" "=r,m,r,r" )
	  ( match_operand:DZ 1 "general_operand" "r,r,m,i" )) ]
  "TARGET_C_FOR_DSP"
  "*
{
    return move_double_fraction ( operands );
}" "CAN_ACCEPT_SUBREG_ACC | CCS_NOT_AFFECTED" )

( define_insn ""
  [ ( set ( match_operand:DZ 0 "general_operand" "=r,m,r,r" )
	  ( match_operand:DZ 1 "register_operand" "r,r,m,i" )) ]
  "TARGET_C_FOR_DSP"
  "*
{
    return move_double_fraction ( operands );
}" "CAN_ACCEPT_SUBREG_ACC | CCS_NOT_AFFECTED" )

( define_expand "movsf"
  [ ( set
      ( match_operand:SF 0 "general_operand" "" )
      ( match_operand:SF 1 "general_operand" "" )) ]
  ""
  "
{
    if ( ! really_reg_p ( operands[0] ) && ! really_reg_p ( operands[1] ))
    {
	operands[1] = force_reg ( SFmode, operands[1] );
    }
}" )
  
( define_insn ""
  [ ( set
      ( match_operand:SF 0 "register_operand" "=D,S,m,DS,DS" )
      ( match_operand:SF 1 "general_operand" "DS,DS,DS,m,G" )) ]
  ""
  "*
{
    return move_double_integer ( 1, operands );
}" "CAN_ACCEPT_SUBREG_ACC | CCS_NOT_AFFECTED" )

( define_insn ""
  [ ( set
      ( match_operand:SF 0 "general_operand" "=D,S,m,DS,DS" )
      ( match_operand:SF 1 "register_operand" "DS,DS,DS,m,G" )) ]
  ""
  "*
{
    return move_double_integer ( 1, operands );
}" "CAN_ACCEPT_SUBREG_ACC | CCS_NOT_AFFECTED" )

( define_expand "movdf"
  [ ( set
      ( match_operand:DF 0 "general_operand" "" )
      ( match_operand:DF 1 "general_operand" "" )) ]
  ""
  "
{
    if ( ! really_reg_p ( operands[0] ) && ! really_reg_p ( operands[1] ))
    {
	operands[1] = force_reg ( DFmode, operands[1] );
    }
}" )
  
( define_insn ""
  [ ( set
      ( match_operand:DF 0 "register_operand" "=D,S,m,DS,DS" )
      ( match_operand:DF 1 "general_operand" "DS,DS,DS,m,G" )) ]
  ""
  "*
{
    return move_double_integer ( 1, operands );
}" "CAN_ACCEPT_SUBREG_ACC | CCS_NOT_AFFECTED" )

( define_insn ""
  [ ( set
      ( match_operand:DF 0 "general_operand" "=D,S,m,DS,DS" )
      ( match_operand:DF 1 "register_operand" "DS,DS,DS,m,G" )) ]
  ""
  "*
{
    return move_double_integer ( 1, operands );
}" "CAN_ACCEPT_SUBREG_ACC | CCS_NOT_AFFECTED" )

;;  ...........................................................................
;;          BLOCKMOVES

( define_expand "movstrsi"
  [ ( parallel [ ( set ( match_operand:BLK 0 "memory_operand" "" )
		       ( match_operand:BLK 1 "memory_operand" "" ))
		 ( use ( match_operand:SI 2 "general_operand" "" ))
		 ( use ( match_operand:SI 3 "general_operand" "" )) ] ) ]
  ""
  "
{
    rtx op0_reg, op1_reg, cpy_reg;

    op0_reg = gen_reg_rtx ( SImode );
    emit_move_insn ( op0_reg, force_reg ( SImode, XEXP ( operands[0], 0 )));
    
    op1_reg = gen_reg_rtx ( SImode );
    emit_move_insn ( op1_reg, force_reg ( SImode, XEXP ( operands[1], 0 )));
    
    cpy_reg = gen_reg_rtx (( TARGET_L_MEMORY ) ? DImode : SImode );

    if ( CONST_DOUBLE == GET_CODE ( operands[2] ))
    {
	operands[2] = gen_rtx ( CONST_INT, VOIDmode, 
			       CONST_DOUBLE_LOW ( operands[2] ));
    }
    
    emit_insn (
	       gen_rtx ( PARALLEL, VOIDmode,
			gen_rtvec ( 7,
				   gen_rtx ( CLOBBER, VOIDmode, op0_reg ),
				   gen_rtx ( CLOBBER, VOIDmode, op1_reg ),
				   gen_rtx ( USE, VOIDmode, operands[2] ),
				   gen_rtx ( CLOBBER, VOIDmode, cpy_reg ),
				   gen_rtx ( SET, VOIDmode, operands[0],
					    operands[1] ),
				   gen_rtx ( USE, VOIDmode, op0_reg ),
				   gen_rtx ( USE, VOIDmode, op1_reg ))));
    DONE;
}" )


( define_insn ""
  [ ( parallel [ ( clobber ( match_operand:SI 0 "register_operand" "=A" ))
		 ( clobber ( match_operand:SI 1 "register_operand" "=A" ))
		 ( use ( match_operand:SI 2 "immediate_operand" "i" ))
		 ( clobber ( match_operand:SI 3 "register_operand" "=&r" ))
		 ( set ( match_operand:BLK 4 "memory_operand" "" )
		       ( match_operand:BLK 5 "memory_operand" "" ))
		 ( use ( match_operand:SI 6 "register_operand" "0" ))
		 ( use ( match_operand:SI 7 "register_operand" "1" )) ] ) ]
"! TARGET_L_MEMORY && INTVAL( operands[2] ) < 4096"
"*
{
    operands[8] = gen_label_rtx ( );

    switch ( INTVAL ( operands[2] ))
    {
    case 1:
	return fms ( \"move	@:(%1),%3\;\"
		     \"move	%3,@:(%0)\" );

    case 2:
	return fms ( \"move	@:(%1)+,%3\;\"
		     \"move	%3,@:(%0)+\;\"
		     \"move	@:(%1),%3\;\"
		     \"move	%3,@:(%0)\" );
	    
    case 3:
        if ( ! TARGET_CONSERVE_P_MEM )
        {
            return fms ( \"move	@:(%1)+,%3\;\"
                         \"move	%3,@:(%0)+\;\"
                         \"move	@:(%1)+,%3\;\"
                         \"move	%3,@:(%0)+\;\"
                         \"move	@:(%1),%3\;\"
                         \"move	%3,@:(%0)\" );
        }
    default:
	return fms ( \"do	#%2,%l8\;\"
		     \"move	@:(%1)+,%3\;\"
		     \"move	%3,@:(%0)+\\n\"
	       \"%l8\" );
    }
}" )

( define_insn ""
  [ ( parallel [ ( clobber ( match_operand:SI 0 "register_operand" "=A" ))
		 ( clobber ( match_operand:SI 1 "register_operand" "=A" ))
		 ( use ( match_operand:SI 2 "register_or_immediate_operand" "S" ))
		 ( clobber ( match_operand:SI 3 "register_operand" "=&r" ))
		 ( set ( match_operand:BLK 4 "memory_operand" "" )
		       ( match_operand:BLK 5 "memory_operand" "" ))
		 ( use ( match_operand:SI 6 "register_operand" "0" ))
		 ( use ( match_operand:SI 7 "register_operand" "1" )) ] ) ]
"! TARGET_L_MEMORY"
"*
{
    operands[8] = gen_label_rtx ( );

    return fms ( \"do	%2,%l8\;\"
                 \"move	@:(%1)+,%3\;\"
                 \"move	%3,@:(%0)+\\n\"
                 \"%l8\" );
}" )

( define_insn ""
  [ ( parallel [ ( clobber ( match_operand:SI 0 "register_operand" "=A,A" ))
		 ( clobber ( match_operand:SI 1 "register_operand" "=A,A" ))
		 ( use ( match_operand:SI 2 "immediate_operand" "i,i" ))
		 ( clobber ( match_operand:DI 3 "register_operand" "=&S,&D" ))
		 ( set ( match_operand:BLK 4 "memory_operand" "" )
		       ( match_operand:BLK 5 "memory_operand" "" ))
		 ( use ( match_operand:SI 6 "register_operand" "0,0" ))
		 ( use ( match_operand:SI 7 "register_operand" "1,0" )) ] ) ]
 "TARGET_L_MEMORY && INTVAL( operands[ 2 ] ) < 4096"
 "*
{
    operands[8] = gen_label_rtx ( );


    switch ( INTVAL ( operands[2] ))
    {
    case 1:
	return \"move	l:(%1),%m3\;\"
	       \"move	%m3,l:(%0)\";
		
    case 2:
	return \"move	l:(%1)+,%m3\;\"
	       \"move	%m3,l:(%0)+\;\"
	       \"move	l:(%1),%m3\;\"
	       \"move	%m3,l:(%0)\";

    case 3:
        if ( ! TARGET_CONSERVE_P_MEM )
        {
            return \"move	l:(%1)+,%m3\;\"
                   \"move	%m3,l:(%0)+\;\"
                   \"move	l:(%1)+,%m3\;\"
                   \"move	%m3,l:(%0)+\;\"
                   \"move	l:(%1),%m3\;\"
                   \"move	%m3,l:(%0)\";
        }
    default:
	return \"do	#%2,%l8\;\"
	       \"move	l:(%1)+,%m3\;\"
	       \"move	%m3,l:(%0)+\\n\"
	  \"%l8\";
    }
}" )

( define_insn ""
  [ ( parallel [ ( clobber ( match_operand:SI 0 "register_operand" "=A,A" ))
		 ( clobber ( match_operand:SI 1 "register_operand" "=A,A" ))
		 ( use ( match_operand:SI 2 "register_or_immediate_operand" "S,S" ))
		 ( clobber ( match_operand:DI 3 "register_operand" "=&S,&D" ))
		 ( set ( match_operand:BLK 4 "memory_operand" "" )
		       ( match_operand:BLK 5 "memory_operand" "" ))
		 ( use ( match_operand:SI 6 "register_operand" "0,0" ))
		 ( use ( match_operand:SI 7 "register_operand" "1,0" )) ] ) ]
 "TARGET_L_MEMORY"
 "*
{
    operands[8] = gen_label_rtx ( );


    return \"do	%2,%l8\;\"
           \"move	l:(%1)+,%m3\;\"
           \"move	%m3,l:(%0)+\\n\"
           \"%l8\";
}" )

;;  ...........................................................................
;;          ADDITIONS

;; We provide quick software emulation via a subroutine that emulates
;; a floating point instruction.

( define_insn "addsf3"
  [ ( set ( match_operand:SF 0 "register_operand" "=D" )
          ( plus:SF ( match_operand:SF 1 "register_operand" "0" )
                    ( match_operand:SF 2 "register_operand" "D" ))) ]
  ""
  "*return output_pic_dep ( \"%3sr	fadd_%2%0\", B, J, 3, operands );"
  "CCS_SET_CORRECTLY | BSR_LAST_OP" )

( define_insn "adddf3"
  [ ( set ( match_operand:DF 0 "register_operand" "=D" )
          ( plus:DF ( match_operand:DF 1 "register_operand" "0" )
                    ( match_operand:DF 2 "register_operand" "D" ))) ]
  ""
  "*return output_pic_dep ( \"%3sr	fadd_%2%0\", B, J, 3, operands );"
  "CCS_SET_CORRECTLY | BSR_LAST_OP" )

( define_expand "addsi3"
  [ ( set ( match_operand:SI 0 "register_operand" "" )
          ( plus:SI ( match_operand:SI 1 "register_operand" "" )
		    ( match_operand:SI 2 
				       "register_or_immediate_operand" "" ))) ]
  ""
  "" )

( define_insn "addsz3"
  [ ( set ( match_operand:SZ 0 "register_operand" "=D,D" )
          ( plus:SZ ( match_operand:SZ 1 "register_operand" "0,0" )
                    ( match_operand:SZ 2 "register_operand" "S,D" ))) ]
  ""
  "*
{
    if ( REGNO ( operands[2] ) == REGNO ( operands[0] ))
    {
        return \"asl    %0\";
    }
    else
    {
        return \"add    %2,%0\";
    }
}" )

;; When we do final frame pointer elimination, we end up transforming 
;; ( set ( reg ) ( fp )) into ( set ( reg ) ( plus ( sp ) ( const ))).
;; the following insn implements such an operation. these insns need to 
;; come before all other adds. if the fake fp is involved in an insn,
;; it is critical that it match one of these few, so that we can fix it
;; up properly. We do the same for global data pointers too.

(define_insn ""
  [ ( set ( match_operand:SI 0 "register_operand" "=r" )
	  ( plus:SI ( match_operand:SI 1 "register_operand" "r" )
		    ( match_operand:SI 2 "immediate_operand" "i" ))) ]
  "STACK_POINTER_REGNUM == REGNO ( operands[1] ) ||
   FRAME_POINTER_REGNUM == REGNO ( operands[1] ) ||
   ( TARGET_PID && DATA_POINTER_REGNUM == REGNO ( operands[1] ))"
  "*
{ 
    int dest_regno = REGNO ( operands[0] );
    
    if (( DSP_R0_REGNUM <= dest_regno && DSP_R7_REGNUM >= dest_regno ) ||
	( DSP_N0_REGNUM <= dest_regno && DSP_N7_REGNUM >= dest_regno ))
    {
	if ( 0 > INTVAL ( operands[2] ) && -64 <= INTVAL ( operands[2] ))
	{
	    return \"lua	(%1%2),%0\";
	}
	else if ( 63 >= INTVAL ( operands[2] ) && 0 <= INTVAL ( operands[2] ))
	{
	    return \"lua	(%1+%2),%0\";
	}
	else
	{
	    return \"move	#%2,%j1\;\"
		   \"lua	(%1)+%j1,%0\";
	}
    }
    else
    {
	if ( 0 > INTVAL ( operands[2] ) && -64 <= INTVAL ( operands[2] ))
	{
	    return \"lua	(%1%2),%j1\;\"
		   \"move	%j1,%0\";
	}
	else if ( 63 >= INTVAL ( operands[2] ) && 0 <= INTVAL ( operands[2] ))
	{
	    return \"lua	(%1+%2),%j1\;\"
		   \"move	%j1,%0\";
	}
	else
	{
	    return \"move	#%2,%j1\;\"
		   \"lua	(%1)+%j1,%0\";
	}
    }
}" "CCS_NOT_AFFECTED" )


( define_insn ""
  [ ( set ( match_operand:SI 0 "memory_operand" "=m" )
	  ( plus:SI ( match_operand:SI 1 "register_operand" "r" )
		    ( match_operand:SI 2 "immediate_operand" "i" ))) ]
  "STACK_POINTER_REGNUM == REGNO ( operands[1] ) ||
   FRAME_POINTER_REGNUM == REGNO ( operands[1] ) ||
   ( TARGET_PID && DATA_POINTER_REGNUM == REGNO ( operands[1] ))"
  "*
{
    static char conglom[BUFSIZ];
    char *mod_spot;
    
    operands[5] = operands[2];
    strcpy ( conglom, \"move	#%5,%j1\;lua	(%1)+%j1,%j1\;\" );
    which_alternative = 1;
    strcat ( conglom, move_single_integer ( operands ));
    * ( mod_spot = strrchr ( conglom, ',' ) - 1 ) =
	(char) ((int) '0' + STACK_POINTER_REGNUM - DSP_R0_REGNUM );
    * ( -- mod_spot ) = 'n';
    * ( -- mod_spot ) = '\\t';
    * ( mod_spot - 1 ) = ' ';
    
    return conglom;
}" "CCS_NOT_AFFECTED" )


( define_insn ""
  [ ( set ( match_operand:SI 0 "register_operand" "=A,D" )
	  ( plus:SI ( match_operand:SI 1 "register_operand" "0,0" )
		    ( const_int 1 ))) ]
  ""
  "*
{
    if ( which_alternative )
    {
	added_flags = CCS_SET_CORRECTLY;
	
	return \"add	#1,%0\";
    }
    else
    {
	added_flags = CCS_NOT_AFFECTED;
	
	return \"move	(%0)+\";
    }
}" )

( define_insn ""
  [ ( set ( match_operand:SI 0 "register_operand" "=A,D" )
	  ( plus:SI ( match_operand:SI 1 "register_operand" "0,0" )
		    ( const_int 2 ))) ]
  ""
  "*
{
    if ( which_alternative )
    {
	added_flags = CCS_SET_CORRECTLY;
	
	return \"add	#2,%0\";
    }
    else
    {
	added_flags = CCS_NOT_AFFECTED;
	
	return \"move	(%0)+\;move	(%0)+\";
    }
}" )

( define_insn ""
  [ ( set ( match_operand:SI 0 "register_operand" "=A,D" )
	  ( plus:SI ( match_operand:SI 1 "register_operand" "0,0" )
		    ( const_int -1 ))) ]
  ""
  "*
{
    if ( which_alternative )
    {
	added_flags = CCS_SET_CORRECTLY;
	
	return \"sub	#1,%0\";
    }
    else
    {
	added_flags = CCS_NOT_AFFECTED;
	
	return \"move	(%0)-\";
    }
}" )

( define_insn ""
  [ ( set ( match_operand:SI 0 "register_operand" "=A,D" )
	  ( plus:SI ( match_operand:SI 1 "register_operand" "0,0" )
		    ( const_int -2 ))) ]
  ""
  "*
{
    if ( which_alternative )
    {
	added_flags = CCS_SET_CORRECTLY;
	
	return \"sub	#2,%0\";
    }
    else
    {
	added_flags = CCS_NOT_AFFECTED;
	
	return \"move	(%0)-\;move	(%0)-\";
    }
}" )

( define_insn ""
  [ ( set ( match_operand:SI 0 "register_operand" "=D,D" )
          ( plus:SI ( match_operand:SI 1 "register_operand" "0,0" )
		    ( match_operand:SI 2 "register_operand" "S,D" ))) ]
  ""
  "*{ return ( REGNO ( operands[2] ) == REGNO ( operands[0] )) ?
	\"asl	%0\" : \"add	%2,%0\"; }" 
  "IFCCABLE_OP_CODE | CCS_SET_CORRECTLY" )

( define_insn ""
  [ ( set ( match_operand:SI 0 "register_operand" "=D" )
          ( plus:SI ( match_operand:SI 1 "register_operand" "0" )
		    ( match_operand:SI 2 "immediate_operand" "i" ))) ]
  ""
  "add	#%2,%0"
  "CCS_SET_CORRECTLY" )

( define_expand "adddi3"
  [ ( set ( match_operand:DI 0 "register_operand" "" )
	  ( plus:DI ( match_operand:DI 1 "register_operand" "" )
		    ( match_operand:DI 2 "register_or_crement_operand" "" ))) ]
  ""
  "" )

( define_insn ""
  [ ( set ( match_operand:DI 0 "register_operand" "=D" )
	  ( match_operator:DI 1 "plus_or_minus_operator"
	      [ ( match_operand:DI 2 "register_operand" "0" )
	        ( match_operand:DI 3 "crement_operand" "i" ) ] )) ]
  ""
  "*
{
    if ((( PLUS == GET_CODE ( operands[1] )) &&
	 ( 1 == INTVAL ( operands[3] ))) ||
	(( MINUS == GET_CODE ( operands[1] )) &&
	 ( -1 == INTVAL ( operands[3] ))))
    {
	return \"inc	%0\";
    }
    else
    {
	return \"dec	%0\";
    }
}" 
  "CCS_SET_CORRECTLY" )

( define_insn ""
  [ ( set ( match_operand:DI 0 "register_operand" "=D,D" )
          ( plus:DI ( match_operand:DI 1 "register_operand" "%0,0" )
                    ( match_operand:DI 2 "register_operand" "S,D" ))) ]
  ""
  "*{ return ( REGNO ( operands[2] ) == REGNO ( operands[0] )) ?
	\"asl	%0\" : \"add	%i2,%0\"; }"
  "IFCCABLE_OP_CODE | CCS_SET_CORRECTLY" )

( define_insn ""
  [ ( set ( match_operand:DI 0 "register_operand" "=D,&D" )
          ( plus:DI ( sign_extend:DI
		      ( match_operand:SI 1 "general_operand" "mr,mr" ))
		    ( match_operand:DI 2 "register_operand" "S,D" ))) ]
  ""
  "*
{
    if ( REG_P ( operands[1] ) && 
	REGNO ( operands[0] ) == REGNO ( operands[1] ))
    {
	return \"asr	#16,%0,%0\;add	%i2,%0\";
    }
    else
    {
	return \"move	%1,%0\;asr	#16,%0,%0\;add	%i2,%0\";
    }
}" "CCS_SET_CORRECTLY" )


;;  ...........................................................................
;;          SUBTRACTIONS

;; We provide quick software emulation via a subroutine that emulates
;; a floating point instruction.

( define_insn "subsf3"
  [ ( set ( match_operand:SF 0 "register_operand" "=D" )
          ( minus:SF ( match_operand:SF 1 "register_operand" "0" )
                     ( match_operand:SF 2 "register_operand" "D" ))) ]
  ""
  "*
{ return ( REGNO ( operands[0] ) == REGNO ( operands[2] )) ?
      \"clr	%0\" :
      output_pic_dep ( \"%3sr	fsub_%2%0\", B, J, 3, operands ); }"
  "CCS_SET_CORRECTLY | BSR_LAST_OP" )

( define_insn "subdf3"
  [ ( set ( match_operand:DF 0 "register_operand" "=D" )
          ( minus:DF ( match_operand:DF 1 "register_operand" "0" )
                     ( match_operand:DF 2 "register_operand" "D" ))) ]
  ""
  "*
{ return ( REGNO ( operands[0] ) == REGNO ( operands[2] )) ?
      \"clr	%0\" :
      output_pic_dep ( \"%3sr	fsub_%2%0\", B, J, 3, operands ); }"
  "CCS_SET_CORRECTLY | BSR_LAST_OP" )

( define_expand "subsi3"
  [ ( set ( match_operand:SI 0 "register_operand" "" )
	  ( minus:SI ( match_operand:SI 1 "register_operand" "" )
		     ( match_operand:SI 2
					"register_or_immediate_operand" "" )))]
  ""
  "" )

;; this define_insn needs to come before all other adds, as the stack adjusts
;; will need to match it specifically.

( define_insn ""
  [ ( set ( match_operand:SI 0 "register_operand" "=r" )
	  ( minus:SI ( match_operand:SI 1 "register_operand" "0" )
		     ( match_operand:SI 2 "immediate_operand" "i" ))) ]
  "STACK_POINTER_REGNUM == REGNO ( operands[0] )"
  "*
{
    if ( CONST_INT == GET_CODE ( operands[2] ))
    {
	switch ( INTVAL ( operands[2] ))
	{
	case 0:
	    return \"\";
	    
	case 1:
	    return \"move	(%0)-\";
	    
	case 2:
	    return \"move	(%0)-\;\"
	           \"move	(%0)-\";
	    
	case 3:
	    return \"move	(%0)-\;\"
                   \"move	(%0)-\;\"
		   \"move	(%0)-\";

	case 4:
	    if ( ! TARGET_CONSERVE_P_MEM )
	    {
		return \"move	(%0)-\;\"
		       \"move	(%0)-\;\"
		       \"move	(%0)-\;\"
		       \"move	(%0)-\";
	    }
	    break;

	case 5:
	    if ( ! TARGET_CONSERVE_P_MEM )
	    {
		return \"move	(%0)-\;\"
                       \"move	(%0)-\;\"
                       \"move	(%0)-\;\"
                       \"move	(%0)-\;\"
		       \"move	(%0)-\";
	    }
	    break;
	}
    }
    return \"move	#-(%2),%j0\;\"
           \"move	(%0)+%j0\";
}" "CCS_NOT_AFFECTED" )

( define_insn ""
  [ ( set ( match_operand:SI 0 "register_operand" "=A,D" )
	  ( minus:SI ( match_operand:SI 1 "register_operand" "0,0" )
		     ( const_int 1 ))) ]
  ""
  "*
{
    if ( which_alternative )
    {
	added_flags = CCS_SET_CORRECTLY;

	return \"sub	#1,%0\";
    }
    else
    {
	added_flags = CCS_NOT_AFFECTED;
	
	return \"move	(%0)-\";
    }
}" )

( define_insn ""
  [ ( set ( match_operand:SI 0 "register_operand" "=A,D" )
	  ( minus:SI ( match_operand:SI 1 "register_operand" "0,0" )
		     ( const_int 2 ))) ]
  ""
  "*
{
    if ( which_alternative )
    {
	added_flags = CCS_SET_CORRECTLY;

	return \"sub	#2,%0\";
    }
    else
    {
	added_flags = CCS_NOT_AFFECTED;
	
	return \"move	(%0)-\;move	(%0)-\";
    }
}" )

( define_insn ""
  [ ( set ( match_operand:SI 0 "register_operand" "=A,D" )
	  ( minus:SI ( match_operand:SI 1 "register_operand" "0,0" )
		     ( const_int -1 ))) ]
  ""
  "*
{
    if ( which_alternative )
    {
	added_flags = CCS_SET_CORRECTLY;

	return \"add	#1,%0\";
    }
    else
    {
	added_flags = CCS_NOT_AFFECTED;
	
	return \"move	(%0)+\";
    }
}" )

( define_insn ""
  [ ( set ( match_operand:SI 0 "register_operand" "=A,D" )
	  ( minus:SI ( match_operand:SI 1 "register_operand" "0,0" )
		     ( const_int -2 ))) ]
  ""
  "*
{
    if ( which_alternative )
    {
	added_flags = CCS_SET_CORRECTLY;

	return \"add	#2,%0\";
    }
    else
    {
	added_flags = CCS_NOT_AFFECTED;
	
	\"move	(%0)+\;move	(%0)+\";
    }
}" )

( define_insn ""
  [ ( set ( match_operand:SI 0 "register_operand" "=D" )
     ( minus:SI ( match_operand:SI 1 "register_operand" "0" )
                ( match_operand:SI 2 "immediate_operand" "i" ))) ]
  ""
  "sub	#%2,%0"
  "CCS_SET_CORRECTLY" )

( define_insn ""
  [ ( set ( match_operand:SI 0 "register_operand" "=D,D" )
     ( minus:SI ( match_operand:SI 1 "register_operand" "0,0" )
                ( match_operand:SI 2 "register_operand" "S,D" ))) ]
  ""
  "*{ return ( REGNO ( operands[2] ) == REGNO ( operands[0] )) ?
	 \"clr	%0\" : \"sub	%2,%0\"; }"
  "IFCCABLE_OP_CODE | CCS_SET_CORRECTLY" )

( define_expand "subdi3"
  [ ( set ( match_operand:DI 0 "register_operand" "" )
	  ( minus:DI ( match_operand:DI 1 "register_operand" "" )
		     ( match_operand:DI 2 "register_or_crement_operand" "" )))]
  "" "" )

( define_insn ""
  [ ( set ( match_operand:DI 0 "register_operand" "=D" )
	  ( minus:DI ( match_operand:DI 1 "register_operand" "0" )
		     ( const_int 1 ))) ]
  "" "dec	%0" "CCS_SET_CORRECTLY" )

( define_insn ""
  [ ( set ( match_operand:DI 0 "register_operand" "=D" )
	  ( minus:DI ( match_operand:DI 1 "register_operand" "0" )
		     ( const_int -1 ))) ]
  "" "inc	%0" "CCS_SET_CORRECTLY" )

( define_insn ""
  [ ( set ( match_operand:DI 0 "register_operand" "=D,D" )
	  ( minus:DI ( match_operand:DI 1 "register_operand" "0,0" )
		     ( match_operand:DI 2 "register_operand" "S,D" ))) ]
  ""
  "*{ return ( REGNO ( operands[2] ) == REGNO ( operands[0] )) ?
	 \"clr	%0\" : \"sub	%i2,%0\"; }"
  "IFCCABLE_OP_CODE | CCS_SET_CORRECTLY" )

( define_insn ""
  [ ( set ( match_operand:DI 0 "register_operand" "=D,&D" )
          ( minus:DI ( sign_extend:DI
		       ( match_operand:SI 1 "general_operand" "mr,mr" ))
		     ( match_operand:DI 2 "register_operand" "S,D" ))) ]
  ""
  "*
{
    if ( REG_P ( operands[1] ) && 
	REGNO ( operands[0] ) == REGNO ( operands[1] ))
    {
	return \"asr	#16,%0,%0\;sub	%i2,%0\";
    }
    else
    {
	return \"move	%1,%0\;asr	#16,%0,%0\;sub	%i2,%0\";
    }
}" "CCS_SET_CORRECTLY" )

( define_insn "subsz3"
  [ ( set ( match_operand:SZ 0 "register_operand" "=D,D" )
          ( minus:SZ ( match_operand:SZ 1 "register_operand" "0,0" )
                     ( match_operand:SZ 2 "register_operand" "D,S" ))) ]
  "TARGET_C_FOR_DSP"
  "*
{
    if ( REGNO ( operands[2] ) == REGNO ( operands[0] ))
    {
        return \"clr    %0\";
    }
    else
    {
        return \"sub    %2,%0\";
    }
}" )
 


;;  ...........................................................................
;;          MULTIPLICATIONS AND DIVISIONS

;; We provide quick software emulation via a subroutine that emulates
;; a floating point instruction.

( define_insn "mulsf3"
  [ ( set ( match_operand:SF 0 "register_operand" "=D" )
          ( mult:SF ( match_operand:SF 1 "register_operand" "0" )
                    ( match_operand:SF 2 "register_operand" "D" ))) ]
  ""
  "*return output_pic_dep ( \"%3sr	fmpy_%2%0\", B, J, 3, operands );"
  "CCS_SET_CORRECTLY | BSR_LAST_OP" )

( define_insn "muldf3"
  [ ( set ( match_operand:DF 0 "register_operand" "=D" )
          ( mult:DF ( match_operand:DF 1 "register_operand" "0" )
                    ( match_operand:DF 2 "register_operand" "D" ))) ]
  ""
  "*return output_pic_dep ( \"%3sr	fmpy_%2%0\", B, J, 3, operands );"
  "CCS_SET_CORRECTLY | BSR_LAST_OP" )

;; four shapes to match addl.

;( define_insn ""
;  [ ( set ( match_operand:SI 0 "register_operand" "=D" )
;	  ( plus:SI ( match_operand:SI 1 "register_operand" "D" )
;		    ( mult:SI ( match_dup 0 ) ( const_int 2 )))) ]
;  "" "addl	%1,%0" "IFCCABLE_OP_CODE | CCS_SET_CORRECTLY" )

;( define_insn ""
;  [ ( set ( match_operand:SI 0 "register_operand" "=D" )
;	  ( plus:SI ( match_operand:SI 1 "register_operand" "D" )
;		    ( mult:SI ( const_int 2 ) ( match_dup 0 )))) ]
;  "" "addl	%1,%0" "IFCCABLE_OP_CODE | CCS_SET_CORRECTLY" )

;( define_insn ""
;  [ ( set ( match_operand:SI 0 "register_operand" "=D" )
;	  ( plus:SI ( mult:SI ( match_dup 0 ) ( const_int 2 ))
;		    ( match_operand:SI 2 "register_operand" "D" ))) ]
;  "" "addl	%2,%0" "IFCCABLE_OP_CODE | CCS_SET_CORRECTLY" )

;( define_insn ""
;  [ ( set ( match_operand:SI 0 "register_operand" "=D" )
;	  ( plus:SI ( mult:SI ( const_int 2 ) ( match_dup 0 ))
;		    ( match_operand:SI 2 "register_operand" "D" ))) ]
;  "" "addl	%2,%0" "IFCCABLE_OP_CODE | CCS_SET_CORRECTLY" )


;; four shapes to match addr. note that the div matching shapes won't ever 
;; click, because of some "optimization" going on in the front end. This needs
;; to be looked into.

( define_insn ""
  [ ( set ( match_operand:SI 0 "register_operand" "=D" )
	  ( plus:SI ( match_operand:SI 1 "register_operand" "D" )
		    ( div:SI ( match_dup 0 ) ( const_int 2 )))) ]
  "" "addr	%1,%0\;move	#0,%h0" "CCS_SET_CORRECTLY" )

( define_insn ""
  [ ( set ( match_operand:SI 0 "register_operand" "=D" )
	  ( plus:SI ( div:SI ( match_dup 0 ) ( const_int 2 ))
		    ( match_operand:SI 2 "register_operand" "D" ))) ]
  "" "addr	%2,%0\;move	#0,%h0" "CCS_SET_CORRECTLY" )

( define_insn ""
  [ ( set ( match_operand:SI 0 "register_operand" "=&D" )
	  ( plus:SI ( match_operand:SI 1 "register_operand" "D" )
		    ( ashiftrt:SI ( match_dup 0 ) ( const_int 1 )))) ]
  "" "addr	%1,%0\;move	#0,%h0" "CCS_SET_CORRECTLY" )

( define_insn ""
  [ ( set ( match_operand:SI 0 "register_operand" "=D" )
	  ( plus:SI ( ashiftrt:SI ( match_dup 0 ) ( const_int 2 ))
		    ( match_operand:SI 2 "register_operand" "D" ))) ]
  "" "addr	%2,%0\;move	#0,%h0" "CCS_SET_CORRECTLY" )

( define_insn ""
  [ ( set ( match_operand:SI 0 "register_operand" "=D" )
	  ( plus:SI ( match_operand:SI 1 "register_operand" "0" )
		    ( mult:SI ( match_operand:SI 2 "register_operand" "%S" )
			      ( match_operand:SI 3 "pow_two_operand" "i" )))) ]
  ""
  "*
{
    operands[4] = gen_rtx
	( CONST_INT, VOIDmode, floor_log2 ( INTVAL ( operands[3] )));
    
    if ( MEM_IN_STRUCT_P ( insn ))
    {
	if ( RTX_UNCHANGING_P ( insn ))
	{
	    return \"mac	+%2,#(15-%4),%0\";
	}
	return \"mac	+%2,#(15-%4),%0\;\"
	       \"asl	#15,%0,%0\";
    }
    else if ( RTX_UNCHANGING_P ( insn ))
    {
	return \"asr	#15,%0,%0\;\"
	       \"mac	+%2,#(15-%4),%0\";
    }
    return \"asr	#15,%0,%0\;\"
	   \"mac	+%2,#(15-%4),%0\;\"
	   \"asl	#15,%0,%0\";

}" "INPUT_NORM_OPTIONAL | OUTPUT_NORM_OPTIONAL" )


( define_insn ""
  [ ( set ( match_operand:SI 0 "register_operand" "=D" )
	  ( plus:SI ( mult:SI ( match_operand:SI 1 "register_operand" "%S" )
			      ( match_operand:SI 2 "pow_two_operand" "i" ))
		    ( match_operand:SI 3 "register_operand" "0" ))) ]
  ""
  "*
{
    operands[4] = gen_rtx
	( CONST_INT, VOIDmode, floor_log2 ( INTVAL ( operands[2] )));
    
    if ( MEM_IN_STRUCT_P ( insn ))
    {
	if ( RTX_UNCHANGING_P ( insn ))
	{
	    return \"mac	+%1,#(15-%4),%0\";
	}
	return \"mac	+%1,#(15-%4),%0\;\"
	       \"asl	#15,%0,%0\";
    }
    else if ( RTX_UNCHANGING_P ( insn ))
    {
	return \"asr	#15,%0,%0\;\"
	       \"mac	+%1,#(15-%4),%0\";
    }
    return \"asr	#15,%0,%0\;\"
	   \"mac	+%1,#(15-%4),%0\;\"
	   \"asl	#15,%0,%0\";

}" "INPUT_NORM_OPTIONAL | OUTPUT_NORM_OPTIONAL" )

( define_insn ""
  [ ( set 
      ( match_operand:SI 0 "register_operand" "=D" )
      ( minus:SI ( match_operand:SI 1 "register_operand" "0" )
		 ( mult:SI ( match_operand:SI 2 "register_operand" "%S" )
			   ( match_operand:SI 3 "pow_two_operand" "i" )))) ]
  ""
  "*
{
    operands[4] = gen_rtx
	( CONST_INT, VOIDmode, floor_log2 ( INTVAL ( operands[3] )));
    
    if ( MEM_IN_STRUCT_P ( insn ))
    {
	if ( RTX_UNCHANGING_P ( insn ))
	{
	    return \"mac	-%2,#(15-%4),%0\";
	}
	return \"mac	-%2,#(15-%4),%0\;\"
	       \"asl	#15,%0,%0\";
    }
    else if ( RTX_UNCHANGING_P ( insn ))
    {
	return \"asr	#15,%0,%0\;\"
	       \"mac	-%2,#(15-%4),%0\";
    }
    return \"asr	#15,%0,%0\;\"
	   \"mac	-%2,#(15-%4),%0\;\"
	   \"asl	#15,%0,%0\";

}" "INPUT_NORM_OPTIONAL | OUTPUT_NORM_OPTIONAL" )


;; We have two shapes for mac+ because the mult may
;; turn up as either operand of the plus.

( define_insn ""
  [ ( set ( match_operand:SI 0 "register_operand" "=D,D" )
	  ( plus:SI ( match_operand:SI 1 "register_operand" "0,0" )
		    ( mult:SI ( match_operand:SI 2
				 "register_or_immediate_operand" "%S,i" )
			      ( match_operand:SI 3
				 "register_operand" "R,S" )))) ]
  ""
  "*
{
    if ( MEM_IN_STRUCT_P ( insn ))
    {
	if ( RTX_UNCHANGING_P ( insn ))
	{
	    return ( which_alternative ) ? \"maci	+#%2,%3,%0\" :
					   \"mac	+%2,%3,%0\";
	}
	return ( which_alternative ) ?

	       \"maci	+#%2,%3,%0\;\"
	       \"asl	#15,%0,%0\" :

	       \"mac	+%2,%3,%0\;\"
	       \"asl	#15,%0,%0\";
    }
    else if ( RTX_UNCHANGING_P ( insn ))
    {
	return ( which_alternative ) ?

	       \"asr	#15,%0,%0\;\"
	       \"maci	+#%2,%3,%0\" :

	       \"asr	#15,%0,%0\;\"
	       \"mac	+%2,%3,%0\";
    }
    return ( which_alternative ) ?

	   \"asr	#15,%0,%0\;\"
	   \"maci	+#%2,%3,%0\;\"
	   \"asl	#15,%0,%0\" :

	   \"asr	#15,%0,%0\;\"
	   \"mac	+%2,%3,%0\;\"
	   \"asl	#15,%0,%0\";

}" "INPUT_NORM_OPTIONAL | OUTPUT_NORM_OPTIONAL" )


( define_insn ""
  [ ( set ( match_operand:SI 0 "register_operand" "=D,D" )
	  ( plus:SI ( mult:SI ( match_operand:SI 1
			       "register_or_immediate_operand" "%S,i" )
			      ( match_operand:SI 2 "register_operand" "R,S" ))
		    ( match_operand:SI 3 "register_operand" "0,0" ))) ]
  ""
  "*
{
    if ( MEM_IN_STRUCT_P ( insn ))
    {
	if ( RTX_UNCHANGING_P ( insn ))
	{
	    return ( which_alternative ) ? \"maci	+#%1,%2,%0\" :
					   \"mac	+%1,%2,%0\";
	}
	return ( which_alternative ) ?

	       \"maci	+#%1,%2,%0\;\"
	       \"asl	#15,%0,%0\" :

	       \"mac	+%1,%2,%0\;\"
	       \"asl	#15,%0,%0\";
    }
    else if ( RTX_UNCHANGING_P ( insn ))
    {
	return ( which_alternative ) ?

	       \"asr	#15,%0,%0\;\"
	       \"maci	+#%1,%2,%0\" :

	       \"asr	#15,%0,%0\;\"
	       \"mac	+%1,%2,%0\";
    }
    return ( which_alternative ) ?

	   \"asr	#15,%0,%0\;\"
	   \"maci	+#%1,%2,%0\;\"
	   \"asl	#15,%0,%0\" :

	   \"asr	#15,%0,%0\;\"
	   \"mac	+%1,%2,%0\;\"
	   \"asl	#15,%0,%0\";

}" "INPUT_NORM_OPTIONAL | OUTPUT_NORM_OPTIONAL" )


( define_insn ""
  [ ( set ( match_operand:SI 0 "register_operand" "=D,D" )
	  ( minus:SI ( match_operand:SI 1 "register_operand" "0,0" )
		     ( mult:SI ( match_operand:SI 2
				"register_or_immediate_operand" "%S,i" )
			       ( match_operand:SI 3
				"register_operand" "R,S" )))) ]
  ""
  "*
{
    if ( MEM_IN_STRUCT_P ( insn ))
    {
	if ( RTX_UNCHANGING_P ( insn ))
	{
	    return ( which_alternative ) ? \"maci	-#%2,%3,%0\" :
		                           \"mac	-%2,%3,%0\";
	}
	return ( which_alternative ) ?

	       \"maci	-#%2,%3,%0\;\"
	       \"asl	#15,%0,%0\" :

	       \"mac	-%2,%3,%0\;\"
	       \"asl	#15,%0,%0\";
    }
    else if ( RTX_UNCHANGING_P ( insn ))
    {
	return ( which_alternative ) ?

	       \"asr	#15,%0,%0\;\"
	       \"maci	-#%2,%3,%0\" :

	       \"asr	#15,%0,%0\;\"
	       \"mac	-%2,%3,%0\";
    }
    return ( which_alternative ) ?

	   \"asr	#15,%0,%0\;\"
	   \"maci	-#%2,%3,%0\;\"
	   \"asl	#15,%0,%0\" :

	   \"asr	#15,%0,%0\;\"
	   \"mac	-%2,%3,%0\;\"
	   \"asl	#15,%0,%0\";

}" "INPUT_NORM_OPTIONAL | OUTPUT_NORM_OPTIONAL" )


;; we have a quick (breaks calling convention rules) subr. act as an inst.

( define_insn "muldi3"
  [ ( set ( match_operand:DI 0 "register_operand" "=D" )
          ( mult:DI ( match_operand:DI 1 "register_operand" "0" )
                    ( match_operand:DI 2 "register_operand" "D" ))) 
  ]
  ""
  "*return output_pic_dep ( \"%3sr	lmpy_%2%0\", B, J, 3, operands );"
  "CCS_SET_CORRECTLY | BSR_LAST_OP" )

;; normal, boring mults follow.

( define_insn ""
  [ ( set ( match_operand:SI 0 "register_operand" "=D" )
	  ( mult:SI ( match_operand:SI 1 "register_operand" "%S" )
		    ( match_operand:SI 2 "pow_two_operand" "i" ))) ]
  ""
  "*
{
    operands[3] = gen_rtx 
	( CONST_INT, VOIDmode, floor_log2 ( INTVAL ( operands[2] )));
    
    if ( RTX_UNCHANGING_P ( insn ))
    {
	return \"mpy	%1,#(15-%3),%0\";
    }
    return \"mpy	%1,#(15-%3),%0\;\"
           \"asl	#15,%0,%0\";
}" "OUTPUT_NORM_OPTIONAL" )

( define_insn ""
  [ ( set ( match_operand:SI 0 "register_operand" "=D" )
	  ( neg:SI ( mult:SI ( match_operand:SI 1 "register_operand" "%S" )
			     ( match_operand:SI 2 "pow_two_operand" "i" )))) ]
  ""
  "*
{
    operands[3] = gen_rtx 
	( CONST_INT, VOIDmode, floor_log2 ( INTVAL ( operands[2] )));
    
    if ( RTX_UNCHANGING_P ( insn ))
    {
	return \"mpy	-%1,#(15-%3),%0\";
    }
    return \"mpy	-%1,#(15-%3),%0\;\"
           \"asl	#15,%0,%0\";
}" "OUTPUT_NORM_OPTIONAL" )


( define_insn ""
  [ ( set ( match_operand:SI 0 "register_operand" "=D,D" )
	  ( mult:SI ( match_operand:SI 1 "register_operand" "%S,S" )
		    ( match_operand:SI 2
			       "register_or_immediate_operand" "R,i" ))) ]
  ""
  "*
{
    if ( RTX_UNCHANGING_P ( insn ))
    {
	return ( which_alternative ) ? \"mpyi	#%2,%1,%0\" :
			 	       \"mpy	%2,%1,%0\";
    }
    return ( which_alternative ) ?

           \"mpyi	#%2,%1,%0\;\"
	   \"asl	#15,%0,%0\" :

           \"mpy	%2,%1,%0\;\"
	   \"asl	#15,%0,%0\";

}" "OUTPUT_NORM_OPTIONAL" )

( define_insn ""
  [ ( set ( match_operand:SI 0 "register_operand" "=D,D" )
	  ( neg:SI ( mult:SI ( match_operand:SI 1 "register_operand" "%S,S" )
			     ( match_operand:SI 2
				"register_or_immediate_operand" "R,i" )))) ]
  ""
  "*
{
    if ( RTX_UNCHANGING_P ( insn ))
    {
	return ( which_alternative ) ? \"mpyi	-#%2,%1,%0\" :
			 	       \"mpy	-%2,%1,%0\";
    }
    return ( which_alternative ) ?

           \"mpyi	-#%2,%1,%0\;\"
	   \"asl	#15,%0,%0\" :

           \"mpy	-%2,%1,%0\;\"
	   \"asl	#15,%0,%0\";

}" "OUTPUT_NORM_OPTIONAL" )

( define_expand "mulsi3"
  [ ( set ( match_operand:SI 0 "register_operand" "" )
	  ( mult:SI ( match_operand:SI 1 "register_or_pow_two_operand" "" )
		    ( match_operand:SI 2 "register_operand" "" ))) ]
  ""
  "" )

( define_insn "mulsz3"
  [ ( set ( match_operand:SZ 0 "register_operand" "=D" )
	  ( mult:SZ ( match_operand:SZ 1 "register_operand" "%S" )
		    ( match_operand:SZ 2 "register_operand" "R" ))) ]
  "TARGET_C_FOR_DSP"
  "mpyr	%2,%1,%0" "CCS_SET_CORRECTLY" )

( define_insn "muldz3"
  [ ( set ( match_operand:DZ 0 "register_operand" "=D" )
	  ( mult:DZ ( match_operand:DZ 1 "register_operand" "%S" )
		    ( match_operand:DZ 2 "register_operand" "R" ))) ]
  "TARGET_C_FOR_DSP"
  "mpy	%2,%1,%0" "CCS_SET_CORRECTLY" )

( define_insn "umulsi3"
  [ ( set ( match_operand:SI 0 "register_operand" "=D,D" )
	  ( umult:SI ( match_operand:SI 1 "register_operand" "%S,S" )
		     ( match_operand:SI 2
			 "register_or_immediate_operand" "R,i" ))) ]
  ""
  "*{ return ( which_alternative ) ?
 	\"mpyi	#%2,%1,%0\;asl	#15,%0,%0\" :
 	\"mpy	%2,%1,%0\;asl	#15,%0,%0\"; }" )



;; We provide quick software emulation via a subroutine that emulates
;; a floating point instruction.

( define_insn "divdi3"
  [ ( set ( match_operand:DI 0 "register_operand" "=D" )
          ( div:DI ( match_operand:DI 1 "register_operand" "0" )
                   ( match_operand:DI 2 "register_operand" "D" ))) ]
  ""
  "*
{ return ( REGNO ( operands[0] ) == REGNO ( operands[2] )) ?
      \"clr	%0\;inc	%0\" :
      output_pic_dep ( \"%3sr	ldiv_%2%0\", B, J, 3, operands ); }"
  "CCS_SET_CORRECTLY | BSR_LAST_OP" )

( define_insn "moddi3"
  [ ( set ( match_operand:DI 0 "register_operand" "=D,D" )
          ( mod:DI ( match_operand:DI 1 "register_operand" "0,0" )
                   ( match_operand:DI 2 "register_operand" "S,D" ))) ]
  ""
  "*
{ return ( REGNO ( operands[0] ) == REGNO ( operands[2] )) ?
      \"clr	%0\" :
      output_pic_dep ( \"%3sr	lmod_%i2%0\", B, J, 3, operands ); }"
  "CCS_SET_CORRECTLY | BSR_LAST_OP" )


( define_insn "divsf3"
  [ ( set ( match_operand:SF 0 "register_operand" "=D" )
          ( div:SF ( match_operand:SF 1 "register_operand" "0" )
                   ( match_operand:SF 2 "register_operand" "D" ))) ]
  ""
  "*
{
    if ( REGNO ( operands[0] ) == REGNO ( operands[2] ))
    {
	return \"move	#>$3f80,%0\";
    }
    else
    {
	added_flags = CCS_SET_CORRECTLY;
	
	return output_pic_dep ( \"%3sr	fdiv_%2%0\", B, J, 3, operands );
    }
}" "BSR_LAST_OP" )

( define_insn "divdf3"
  [ ( set ( match_operand:DF 0 "register_operand" "=D" )
          ( div:DF ( match_operand:DF 1 "register_operand" "0" )
                   ( match_operand:DF 2 "register_operand" "D" ))) ]
  ""
  "*
{
    if ( REGNO ( operands[0] ) == REGNO ( operands[2] ))
    {
	return \"move	#>$3f80,%0\";
    }
    else
    {
	added_flags = CCS_SET_CORRECTLY;
	
        return output_pic_dep ( \"%3sr	fdiv_%2%0\", B, J, 3, operands );
    }
}" "BSR_LAST_OP" )

( define_insn "udivsi3"
  [ ( set ( match_operand:SI 0 "register_operand" "=D" )
	  ( udiv:SI ( match_operand:SI 1 "register_operand" "0" )
		    ( match_operand:SI 2 "register_operand" "D" ))) ]
  ""
  "*
{ return ( REGNO ( operands[0] ) == REGNO ( operands[2] )) ?
      \"clr	%0\;add	#1,%0\" :
      output_pic_dep ( \"%3sr	udiv_%2%0\", B, J, 3, operands ); }"
  "CCS_SET_CORRECTLY | BSR_LAST_OP" )

( define_insn "umodsi3"
  [ ( set ( match_operand:SI 0 "register_operand" "=D" )
	  ( umod:SI ( match_operand:SI 1 "register_operand" "0" )
		    ( match_operand:SI 2 "register_operand" "D" ))) ]
  ""
  "*
{ return ( REGNO ( operands[0] ) == REGNO ( operands[2] )) ?
      \"clr	%0\" :
      output_pic_dep ( \"%3sr	umod_%2%0\", B, J, 3, operands ); }"
  "CCS_SET_CORRECTLY | BSR_LAST_OP" )


( define_expand "divsi3"
  [ ( set ( match_operand:SI 0 "register_operand" "" )
	  ( div:SI ( match_operand:SI 1 "register_operand" "" )
		   ( match_operand:SI 2 "register_operand" "" ))) ]
  ""
  "
{
    if ( ! TARGET_CONSERVE_P_MEM )
    {
	emit_insn
	    ( gen_rtx 
	     ( PARALLEL, VOIDmode,
	      gen_rtvec ( 3,
			 gen_rtx ( SET, VOIDmode, operands[0],
				  gen_rtx ( DIV, SImode, 
					   operands[1], operands[2] )),
			 gen_rtx ( CLOBBER, VOIDmode, 
				  gen_reg_rtx ( SImode )),
			 gen_rtx ( CLOBBER, VOIDmode, 
				  gen_reg_rtx ( SImode )))));
	DONE;
    }
}" )

( define_insn ""
  [ ( set ( match_operand:SI 0 "register_operand" "=D" )
	  ( div:SI ( match_operand:SI 1 "register_operand" "0" )
		   ( match_operand:SI 2 "register_operand" "S" ))) ]
  "TARGET_CONSERVE_P_MEM"
  "*return output_pic_dep ( \"%5sr	idiv_%2%0\", B, J, 5, operands );"
  "CCS_SET_CORRECTLY | BSR_LAST_OP" )

( define_insn ""
  [ ( parallel [ ( set ( match_operand:SI 0 "register_operand" "=D" )
		       ( div:SI ( match_operand:SI 1 "register_operand" "0" )
				( match_operand:SI 2 "register_operand" "S" )))
		 ( clobber ( match_operand:SI 3 "register_operand" "=&D" ))
		 ( clobber ( match_operand:SI 4 "register_operand" "=&S" ))])]
  ""
  "*
{
    operands[5] = gen_label_rtx ( );
    
    if ( TARGET_REP ) 
    {
	return  \"tfr	%0,%3\;\"
		\"abs	%0\;\"
		\"clr	%0	%e0,%4\;\"
		\"move	%4,%h0\;\"
		\"asl	%0\;\"
		\"rep	#$10\;\"
		\"div	%2,%0\;\"
		\"eor	%2,%3\;\"
		\"bpl	%l5\;\"
		\"neg	%0\"
	\"\\n%l5\;move	%h0,%0\";
    }
    else
    {
	operands[6] = gen_label_rtx ( );

	return  \"tfr	%0,%3\;\"
                \"abs	%0\;\"
                \"clr	%0	%e0,%4\;\"
                \"move	%4,%h0\;\"
                \"asl	%0\;\"
                \"do	#$10,%l6\;\"
                \"div	%2,%0\"
        \"\\n%l6\;eor	%2,%3\;\"
                \"bpl	%l5\;\"
                \"neg	%0\"
        \"\\n%l5\;move	%h0,%0\";
    }
}" )


( define_expand "modsi3"
  [ ( set ( match_operand:SI 0 "register_operand" "" )
	  ( mod:SI ( match_operand:SI 1 "register_operand" "" )
		   ( match_operand:SI 2 "register_operand" "" ))) ]
  ""
  "
{
    emit_insn (
	       gen_rtx ( PARALLEL, VOIDmode,
			gen_rtvec ( 3,
				   gen_rtx ( SET, VOIDmode, operands[0],
					    gen_rtx ( MOD, SImode, 
						     operands[1],
						     operands[2] )),
				   gen_rtx ( CLOBBER, VOIDmode, 
					    gen_reg_rtx ( SImode )),
				   gen_rtx ( CLOBBER, VOIDmode, 
					    gen_reg_rtx ( SImode )))));
    DONE;
}" )


( define_insn ""
  [ ( parallel [ ( set ( match_operand:SI 0 "register_operand" "=D" )
		       ( mod:SI ( match_operand:SI 1 "register_operand" "0" )
				( match_operand:SI 2 "register_operand" "S" )))
		 ( clobber ( match_operand:SI 3 "register_operand" "=&D" ))
		 ( clobber ( match_operand:SI 4 "register_operand" "=&S" )) ] )
  ]
  "TARGET_CONSERVE_P_MEM"
  "*return output_pic_dep ( \"%5sr	imod_%2%0\", B, J, 5, operands );"
  "CCS_SET_CORRECTLY | BSR_LAST_OP" )

( define_insn ""
  [ ( parallel [ ( set ( match_operand:SI 0 "register_operand" "=D" )
		       ( mod:SI ( match_operand:SI 1 "register_operand" "0" )
				( match_operand:SI 2 "register_operand" "S" )))
		 ( clobber ( match_operand:SI 3 "register_operand" "=&D" ))
		 ( clobber ( match_operand:SI 4 "register_operand" "=&S" ))])]
  ""
  "*
{
    operands[5] = gen_label_rtx ( );
    
    if ( TARGET_REP ) 
    {
     return  \"tfr	%0,%3\;\"
	     \"abs	%0\;\"
	     \"clr	%0	%e0,%4\;\"
	     \"move	%4,%h0\;\"
	     \"asl	%0\;\"
	     \"rep	#$10\;\"
	     \"div	%2,%0\;\"
	     \"move	%e0,%4\;\"
	     \"move	%2,%0\;\"
	     \"abs	%0\;\"
	     \"add	%4,%0\;\"
	     \"asr	%0\;\"
	     \"tst	%3\;\"
	     \"bge	%l5\;\"
	     \"neg	%0\"
       \"\\n%l5\";
    }
    else
    {
	operands[6] = gen_label_rtx ( );

	return  \"tfr	%0,%3\;\"
	        \"abs	%0\;\"
		\"clr	%0	%e0,%4\;\"
		\"move	%4,%h0\;\"
		\"asl	%0\;\"
		\"do	#$10,%l6\;\"
		\"div	%2,%0\"
	\"\\n%l6\;move	%e0,%4\;\"
	        \"move	%2,%0\;\"
		\"abs	%0\;\"
		\"add	%4,%0\;\"
		\"asr	%0\;\"
		\"tst	%3\;\"
		\"bge	%l5\;\"
		\"neg	%0\"
	  \"\\n%l5\";
    }
}" )

;;  ...........................................................................
;;          NEGATIONS

;; We provide quick software emulation via a subroutine that emulates
;; a floating point instruction.

( define_insn "negsf2"
  [ ( set ( match_operand:SF 0 "register_operand" "=D" )
          ( neg:SF ( match_operand:SF 1 "register_operand" "0" ))) ]
  ""
  "*return output_pic_dep ( \"%2sr	fneg_%0\", B, J, 2, operands );"
  "CCS_SET_CORRECTLY | BSR_LAST_OP" )

( define_insn "negdf2"
  [ ( set ( match_operand:DF 0 "register_operand" "=D" )
          ( neg:DF ( match_operand:DF 1 "register_operand" "0" ))) ]
  ""
  "*return output_pic_dep ( \"%2sr	fneg_%0\", B, J, 2, operands );"
  "CCS_SET_CORRECTLY | BSR_LAST_OP" )

( define_insn "negsi2"
  [ ( set ( match_operand:SI 0 "register_operand" "=D" )
	  ( neg:SI ( match_operand:SI 1 "register_operand" "0" ))) ]
  "" "neg	%0" "IFCCABLE_OP_CODE | CCS_SET_CORRECTLY" )

( define_insn "negdi2"
  [ ( set ( match_operand:DI 0 "register_operand" "=D" )
	  ( neg:DI ( match_operand:DI 1 "register_operand" "0" ))) ]
  "" "neg	%0" "IFCCABLE_OP_CODE | CCS_SET_CORRECTLY" )

( define_insn ""
  [ ( set ( match_operand:DI 0 "register_operand" "=D,&D" )
          ( neg:DI ( sign_extend:DI
		     ( match_operand:SI 1 "general_operand" "mr,mr" )))) ]
  ""
  "*
{
    if ( REG_P ( operands[1] ) && 
	REGNO ( operands[0] ) == REGNO ( operands[1] ))
    {
	return \"asr	#16,%0,%0\;neg	%0\";
    }
    else
    {
	return \"move	%1,%0\;asr	#16,%0,%0\;neg	%0\";
    }
}" "CCS_SET_CORRECTLY" )

( define_insn "negsz2"
  [ ( set ( match_operand:SZ 0 "register_operand" "=D" )
          ( neg:SZ ( match_operand:SZ 1 "register_operand" "0" ))) ]
  "TARGET_C_FOR_DSP"
  "neg  %0  ; from negsz2" "IFCCABLE_OP_CODE | CCS_SET_CORRECTLY" )
 
( define_insn "negdz2"
  [ ( set ( match_operand:DZ 0 "register_operand" "=D" )
          ( neg:DZ ( match_operand:DZ 1 "register_operand" "0" ))) ]
  "TARGET_C_FOR_DSP"
  "neg  %0  ; from negdz2" "IFCCABLE_OP_CODE | CCS_SET_CORRECTLY" )

;;  ...........................................................................
;;          ABSOLUTE VALUES

( define_insn "abssi2"
  [ ( set ( match_operand:SI 0 "register_operand" "=D" )
	  ( abs:SI ( match_operand:SI 1 "register_operand" "0" ))) ]
  "" "abs	%0" "IFCCABLE_OP_CODE | CCS_SET_CORRECTLY" )

( define_insn "absdi2"
  [ ( set ( match_operand:DI 0 "register_operand" "=D" )
	  ( abs:DI ( match_operand:DI 1 "register_operand" "0" ))) ]
  "" "abs	%0" "IFCCABLE_OP_CODE | CCS_SET_CORRECTLY" )

( define_insn ""
  [ ( set ( match_operand:DI 0 "register_operand" "=D,&D" )
          ( abs:DI ( sign_extend:DI
		      ( match_operand:SI 1 "general_operand" "mr,mr" )))) ]
  ""
  "*
{
    if ( REG_P ( operands[1] ) && 
	REGNO ( operands[0] ) == REGNO ( operands[1] ))
    {
	return \"asr	#16,%0,%0\;abs	%2,%0\";
    }
    else
    {
	return \"move	%1,%0\;asr	#16,%0,%0\;abs	%0\";
    }
}" "CCS_SET_CORRECTLY" )

;;  ...........................................................................
;;          LOGICAL AND

( define_expand "andsi3"
  [ ( set ( match_operand:SI 0 "general_operand" "" )
	  ( and:SI ( match_operand:SI 1 "general_operand" "" )
		   ( match_operand:SI 2 "general_operand" "" ))) ]
  ""
  "gen_int_logical ( AND, operands ); DONE;" )

( define_insn ""
  [ ( set ( match_operand:SI 0 "register_operand" "=D,D" )
	  ( and:SI 
	    ( match_operand:SI 1 "register_operand" "0,0" )
	    ( match_operand:SI 2 "register_or_immediate_operand" "i,S" ))) ]
  ""
  "*
{
    if ( which_alternative )
    {
	return \"and	%2,%0\;move	%e0,%0\";
    }
    else
    {
	/* if the MS bit isn't affected, then don't worry about the
	   extension word. */
	
	if ( INTVAL ( operands[2] ) >> 15 )
	{
	    return \"and	#%2,%0\";
	}
	else
	{
	    return \"and	#%2,%0\;move	%e0,%0\";
	}
    }
}" )

( define_expand "anddi3"
  [ ( set ( match_operand:DI 0 "general_operand" "" )
	  ( and:DI ( match_operand:DI 1 "general_operand" "" )
		   ( match_operand:DI 2 "general_operand" "" ))) ]
  ""
  "gen_long_logical ( AND, operands ); DONE;" )

( define_insn ""
  [ ( set ( match_operand:DI 0 "register_operand" "=D" )
	  ( and:DI ( match_operand:DI 1 "register_operand" "0" )
		   ( match_operand:DI 2 "register_operand" "S" ))) ]
  "TARGET_CONSERVE_P_MEM"
  "*return output_pic_dep ( \"%3sr	land_%i2%0\", B, J, 3, operands );"
  "CCS_SET_CORRECTLY | BSR_LAST_OP" )

( define_insn ""
  [ ( set ( match_operand:DI 0 "register_operand" "=D,D" )
	  ( and:DI
	    ( match_operand:DI 1 "register_operand" "0,0" )
	    ( match_operand:DI 2 "register_or_immediate_operand" "G,S" ))) ]
  ""
  "*{ return output_long_reg_logical ( \"*and\", operands );}" )

;;  ...........................................................................
;;          LOGICAL INCLUSIVE OR

( define_expand "iorsi3"
  [ ( set ( match_operand:SI 0 "general_operand" "" )
	  ( ior:SI ( match_operand:SI 1 "general_operand" "" )
		   ( match_operand:SI 2 "general_operand" "" ))) ]
  ""
  "gen_int_logical ( IOR, operands ); DONE;" )

( define_insn ""
  [ ( set ( match_operand:SI 0 "register_operand" "=D,D" )
	  ( ior:SI ( match_operand:SI 1 "register_operand" "0,0" )
		   ( match_operand:SI 2 
			      "register_or_immediate_operand" "i,S" ))) ]
  ""
  "*
{
    if ( which_alternative )
    {
	return \"or	%2,%0\;move	%e0,%0\";
    }
    else
    {
	/* if the MS bit isn't affected, then don't worry about the
	   extension word. */
	
	if ( ! ( INTVAL ( operands[2] ) >> 15 ))
	{
	    return \"or	#%2,%0\;move	%e0,%0\";
	}
	else
	{
	    return \"or	#%2,%0\";
	}
    }
}" )

( define_expand "iordi3"
  [ ( set ( match_operand:DI 0 "general_operand" "" )
	  ( ior:DI ( match_operand:DI 1 "general_operand" "" )
		   ( match_operand:DI 2 "general_operand" "" ))) ]
  ""
  "gen_long_logical ( IOR, operands ); DONE;" )

( define_insn ""
  [ ( set ( match_operand:DI 0 "register_operand" "=D" )
	  ( ior:DI ( match_operand:DI 1 "register_operand" "0" )
		   ( match_operand:DI 2 "register_operand" "S" ))) ]
  "TARGET_CONSERVE_P_MEM"
  "*return output_pic_dep ( \"%3sr	lior_%i2%0\", B, J, 3, operands );"
  "CCS_SET_CORRECTLY | BSR_LAST_OP" )

( define_insn ""
  [ ( set ( match_operand:DI 0 "register_operand" "=D,D" )
	  ( ior:DI ( match_operand:DI 1 "register_operand" "0,0" )
		   ( match_operand:DI 2
			      "register_or_immediate_operand" "G,S" ))) ]
  ""
  "*{ return output_long_reg_logical ( \"*or\", operands );}" )

;;  ...........................................................................
;;          LOGICAL EXCLUSIVE OR

( define_expand "xorsi3"
  [ ( set ( match_operand:SI 0 "general_operand" "" )
	  ( xor:SI ( match_operand:SI 1 "general_operand" "" )
		   ( match_operand:SI 2 "general_operand" "" ))) ]
  ""
  "gen_int_logical ( XOR, operands ); DONE;" )

( define_insn ""
  [ ( set ( match_operand:SI 0 "register_operand" "=D,D" )
	  ( xor:SI ( match_operand:SI 1 "register_operand" "0,0" )
		   ( match_operand:SI 2
			      "register_or_immediate_operand" "i,S" ))) ]
  ""
  "*
{
    if ( which_alternative )
    {
	return \"eor	%2,%0\;move	%e0,%0\";
    }
    else
    {
	/* if the MS bit isn't affected, then don't worry about the
	   extension word. */
	
	if ( ! ( INTVAL ( operands[2] ) >> 15 ))
	{
	    return \"eor	#%2,%0\;move	%e0,%0\";
	}
	else
	{
	    return \"eor	#%2,%0\";
	}
    }
}" )

( define_expand "xordi3"
  [ ( set ( match_operand:DI 0 "general_operand" "" )
	  ( xor:DI ( match_operand:DI 1 "general_operand" "" )
		   ( match_operand:DI 2 "general_operand" "" ))) ]
  ""
  "gen_long_logical ( XOR, operands ); DONE;" )

( define_insn ""
  [ ( set ( match_operand:DI 0 "register_operand" "=D" )
	  ( xor:DI ( match_operand:DI 1 "register_operand" "0" )
		   ( match_operand:DI 2 "register_operand" "S" ))) ]
  "TARGET_CONSERVE_P_MEM"
  "*return output_pic_dep ( \"%3sr	lxor_%i2%0\", B, J, 3, operands );"
  "CCS_SET_CORRECTLY | BSR_LAST_OP" )

( define_insn ""
  [ ( set ( match_operand:DI 0 "register_operand" "=D,D" )
	  ( xor:DI ( match_operand:DI 1 "register_operand" "0,0" )
		   ( match_operand:DI 2
			      "register_or_immediate_operand" "G,S" ))) ]
  ""
  "*{ return output_long_reg_logical ( \"*eor\", operands );}" )

;;  ...........................................................................
;;          ONE'S COMPLEMENT

( define_insn "one_cmplsi2"
  [ ( set ( match_operand:SI 0 "register_operand" "=D" )
	  ( not:SI ( match_operand:SI 1 "register_operand" "0" ))) ]
  "" "not	%0\;move	%e0,%0" "CCS_SET_CORRECTLY" )

( define_insn ""
  [ ( set ( match_operand:DI 0 "register_operand" "=D" )
	  ( not:DI ( match_operand:DI 1 "register_operand" "0" ))) ]
  "TARGET_CONSERVE_P_MEM"
  "*return output_pic_dep ( \"%2sr	lnot_%0\", B, J, 2, operands );"
  "CCS_SET_CORRECTLY | BSR_LAST_OP" )

( define_insn "one_cmpldi2"
  [ ( set ( match_operand:DI 0 "register_operand" "=D" )
	  ( not:DI ( match_operand:DI 1 "register_operand" "0" ))) ]
  ""
  "not	%0	%h0,n6\;move	%e0,%h0\;move	n6,%e0\;not	%0\;move	%e0,n6\;move	%h0,%0\;move	n6,%h0" )


;;  ...........................................................................
;;          ARITHMETIC SHIFTS

;; note that we preceed each shift insn by an unnamed insn. the unnamed insn
;; is used to catch shifts with constant shift counts before said constants
;; are promoted to registers. 

( define_expand "ashlsi3"
  [ ( set ( match_operand:SI 0 "register_operand" "" )
	  ( ashift:SI 
	    ( match_operand:SI 1 "register_operand" "" )
	    ( match_operand:SI 2 "shift_count_operand" "" ))) ]
  ""
  "" )

( define_insn ""
  [ ( set ( match_operand:SI 0 "register_operand" "=D" )
 	  ( ashift:SI ( match_operand:SI 1 "register_operand" "0" )
		      ( const_int 1 ))) ]
  "" "asl	%0" "IFCCABLE_OP_CODE | CCS_SET_CORRECTLY" )

( define_insn ""
  [ ( set ( match_operand:SI 0 "register_operand" "=D,D" )
 	  ( ashift:SI ( match_operand:SI 1 "register_operand" "D,S" )
		      ( match_operand:SI 2 "immediate_operand" "i,i" ))) ]
  "0 < INTVAL ( operands[2] ) && 16 > INTVAL ( operands[2] )"
  "*
{
    if ( which_alternative )
    {
	return \"mpy	%1,#(15-%2),%0\;asl	#15,%0,%0\;move	%e0,%0\";
    }
    else
    {
	added_flags = CCS_SET_CORRECTLY;
	
	return \"asl	#%2,%1,%0\";
    }
}" )

( define_insn ""
  [ ( set ( match_operand:SI 0 "register_operand" "=D,D" )
 	  ( ashift:SI ( match_operand:SI 1 "register_operand" "D,D" )
		      ( match_operand:SI 2 "register_operand" "S,D" ))) ]
  "" "asl	%e2,%1,%0" "CCS_SET_CORRECTLY" )

( define_expand "ashrsi3"
  [ ( set ( match_operand:SI 0 "register_operand" "" )
	  ( ashiftrt:SI 
	    ( match_operand:SI 1 "register_operand" "" )
	    ( match_operand:SI 2 "shift_count_operand" "" ))) ]
  "" "" )

( define_insn ""
  [ ( set ( match_operand:SI 0 "register_operand" "=D" )
 	  ( ashiftrt:SI ( match_operand:SI 1 "register_operand" "0" )
		        ( const_int 1 ))) ]
  "" "asr	%0\;move	%e0,%0" )

( define_insn ""
  [ ( set ( match_operand:SI 0 "register_operand" "=D,D" )
 	  ( ashiftrt:SI ( match_operand:SI 1 "register_operand" "D,S" )
		        ( match_operand:SI 2 "immediate_operand" "i,i" ))) ]
  "0 < INTVAL ( operands[2] ) && 16 > INTVAL ( operands[2] )"
  "*{ return ( which_alternative ) ? 

          \"mpy	%1,#%2,%0\;\"
          \"move	%e0,%0\" :

          \"asr	#%2,%1,%0\;\"
          \"move	%e0,%0\"; }" )

( define_insn ""
  [ ( set ( match_operand:SI 0 "register_operand" "=D,D" )
 	  ( ashiftrt:SI ( match_operand:SI 1 "register_operand" "D,D" )
		        ( match_operand:SI 2 "register_operand" "S,D" ))) ]
  "" "asr	%e2,%1,%0\;move	%e0,%0" "CCS_SET_CORRECTLY" )

( define_expand "ashldi3"
  [ ( set ( match_operand:DI 0 "register_operand" "" )
	  ( ashift:DI
	    ( match_operand:DI 1 "register_operand" "" )
	    ( match_operand:SI 2 "register_or_1_operand" "" ))) ]
  "" "" )

( define_insn ""
  [ ( set ( match_operand:DI 0 "register_operand" "=D" )
 	  ( ashift:DI ( match_operand:DI 1 "register_operand" "0" )
		      ( const_int 1 ))) ]
  "" "asl	%0" "IFCCABLE_OP_CODE | CCS_SET_CORRECTLY" )

( define_insn ""
  [ ( set ( match_operand:DI 0 "register_operand" "=D" )
 	  ( ashift:DI ( match_operand:DI 1 "register_operand" "D" )
		      ( match_operand:SI 2 "immediate_operand" "i" ))) ]
  "16 >= INTVAL ( operands[2] )"
  "asl	#%2,%1,%0" "CCS_SET_CORRECTLY" )

( define_insn ""
  [ ( set ( match_operand:DI 0 "register_operand" "=D" )
 	  ( ashift:DI ( match_operand:DI 1 "register_operand" "0" )
		      ( match_operand:SI 2 "register_operand" "D" ))) ]
  ""
  "*return output_shift ( \"*asl\", operands );"
  "CCS_SET_CORRECTLY" )

( define_expand "ashrdi3"
  [ ( set ( match_operand:DI 0 "register_operand" "" )
	  ( ashiftrt:DI
	    ( match_operand:DI 1 "register_operand" "" )
	    ( match_operand:SI 2 "register_or_1_operand" "" ))) ]
  "" "" )

( define_insn ""
  [ ( set ( match_operand:DI 0 "register_operand" "=D" )
	  ( ashiftrt:DI ( match_operand:DI 1 "register_operand" "0" )
			( const_int 1 ))) ]
  "" "asr	%0" "IFCCABLE_OP_CODE | CCS_SET_CORRECTLY" )

( define_insn ""
  [ ( set ( match_operand:DI 0 "register_operand" "=D" )
	  ( ashiftrt:DI ( match_operand:DI 1 "register_operand" "D" )
			( match_operand:SI 2 "immediate_operand" "i" ))) ]
  "16 >= INTVAL ( operands[2] )"
  "asr	#%2,%1,%0" "CCS_SET_CORRECTLY" )

( define_insn ""
  [ ( set ( match_operand:DI 0 "register_operand" "=D" )
	  ( ashiftrt:DI ( match_operand:DI 1 "register_operand" "0" )
			( match_operand:SI 2 "register_operand" "D" ))) ]
  ""
  "*return output_shift ( \"*asr\", operands );"
  "CCS_SET_CORRECTLY" )

;;  ...........................................................................
;;          LOGICAL SHIFTS

( define_expand "lshlsi3"
  [ ( set ( match_operand:SI 0 "register_operand" "" )
	  ( lshift:SI 
	    ( match_operand:SI 1 "register_operand" "" )
	    ( match_operand:SI 2 "register_or_immediate_operand" "" ))) ]
  "" "" )

( define_insn ""
  [ ( set ( match_operand:SI 0 "register_operand" "=D" )
 	  ( lshift:SI ( match_operand:SI 1 "register_operand" "0" )
		      ( const_int 1 ))) ]
  "" "lsl	%0\;move	%e0,%0" "IFCCABLE_OP_CODE | CCS_SET_CORRECTLY" )

( define_insn ""
  [ ( set ( match_operand:SI 0 "register_operand" "=D" )
 	  ( lshift:SI ( match_operand:SI 1 "register_operand" "0" )
		      ( match_operand:SI 2 "immediate_operand" "i" ))) ]
  "0 < INTVAL ( operands[2] ) && 16 > INTVAL ( operands[2] )"
  "lsl	#%2,%0\;move	%e0,%0" "CCS_SET_CORRECTLY" )

( define_insn ""
  [ ( set ( match_operand:SI 0 "register_operand" "=D" )
 	  ( lshift:SI ( match_operand:SI 1 "register_operand" "0" )
		      ( match_operand:SI 2 "register_operand" "S" ))) ]
  "" "lsl	%e2,%0\;move	%e0,%0" "CCS_SET_CORRECTLY" )

( define_expand "lshrsi3"
  [ ( set ( match_operand:SI 0 "register_operand" "" )
	  ( lshiftrt:SI 
	    ( match_operand:SI 1 "register_operand" "" )
	    ( match_operand:SI 2 "register_or_immediate_operand" "" ))) ]
  "" "" )

( define_insn ""
  [ ( set ( match_operand:SI 0 "register_operand" "=D" )
 	  ( lshiftrt:SI ( match_operand:SI 1 "register_operand" "0" )
		        ( const_int 1 ))) ]
  "" "lsr	%0\;move	%e0,%0" "IFCCABLE_OP_CODE | CCS_SET_CORRECTLY" )

( define_insn ""
  [ ( set ( match_operand:SI 0 "register_operand" "=D" )
 	  ( lshiftrt:SI ( match_operand:SI 1 "register_operand" "0" )
		        ( match_operand:SI 2 "immediate_operand" "i" ))) ]
  "" "lsr	#%2,%0\;move	%e0,%0" "CCS_SET_CORRECTLY" )

( define_insn ""
  [ ( set ( match_operand:SI 0 "register_operand" "=D" )
 	  ( lshiftrt:SI ( match_operand:SI 1 "register_operand" "0" )
		        ( match_operand:SI 2 "register_operand" "S" ))) ]
  "" "lsr	%e2,%0\;move	%e0,%0" "CCS_SET_CORRECTLY" )

( define_expand "lshldi3"
  [ ( set ( match_operand:DI 0 "register_operand" "" )
	  ( lshift:DI
	    ( match_operand:DI 1 "register_operand" "" )
	    ( match_operand:SI 2 "register_or_1_operand" "" ))) ]
  "" "" )

( define_insn ""
  [ ( set ( match_operand:DI 0 "register_operand" "=D" )
 	  ( lshift:DI ( match_operand:DI 1 "register_operand" "0" )
		      ( const_int 1 ))) ]
  "" "asl	%0" "IFCCABLE_OP_CODE | CCS_SET_CORRECTLY" )


( define_insn ""
  [ ( set ( match_operand:DI 0 "register_operand" "=D" )
 	  ( lshift:DI ( match_operand:DI 1 "register_operand" "D" )
		      ( match_operand:SI 2 "immediate_operand" "i" ))) ]
  "16 >= INTVAL ( operands[2] )"
  "asl	#%2,%1,%0" "CCS_SET_CORRECTLY" )


( define_insn ""
  [ ( set ( match_operand:DI 0 "register_operand" "=D" )
	  ( lshift:DI ( match_operand:DI 1 "register_operand" "0" )
		      ( match_operand:SI 2 "register_operand" "D" ))) ]
  ""
  "*return output_shift ( \"*asl\", operands );"
  "CCS_SET_CORRECTLY" )

( define_expand "lshrdi3"
  [ ( set ( match_operand:DI 0 "register_operand" "" )
	  ( lshiftrt:DI
	    ( match_operand:DI 1 "register_operand" "" )
	    ( match_operand:SI 2 "register_or_1_operand" "" ))) ]
  "" "" )

( define_insn ""
  [ ( set ( match_operand:DI 0 "register_operand" "=D" )
	  ( lshiftrt:DI ( match_operand:DI 1 "register_operand" "0" )
			( const_int 1 ))) ]
  "" "move	#>0,%k0\;asr	%0" "CCS_SET_CORRECTLY" )


( define_insn ""
  [ ( set ( match_operand:DI 0 "register_operand" "=D" )
	  ( lshiftrt:DI ( match_operand:DI 1 "register_operand" "D" )
			( match_operand:SI 2 "immediate_operand" "i" ))) ]
  "16 >= INTVAL ( operands[2] )"
  "move	#>0,%k0\;asr	#%2,%1,%0" "CCS_SET_CORRECTLY" )



( define_insn ""
  [ ( set ( match_operand:DI 0 "register_operand" "=D" )
	  ( lshiftrt:DI ( match_operand:DI 1 "register_operand" "0" )
			( match_operand:SI 2 "register_operand" "D" ))) ]
  ""
  "*return output_shift ( \"*asr\", operands );"
  "CCS_SET_CORRECTLY" )

;;  ...........................................................................
;;          ROTATIONS

( define_insn ""
  [ ( set ( match_operand:SI 0 "register_operand" "=D" )
     ( rotate:SI ( match_operand:SI 1 "register_operand" "0" )
                 ( match_operand:SI 2 "immediate_operand" "i" ))) ]
  ""
  "*
{
    if ( 1 == INTVAL ( operands[2] ))
    {
	return \"rol	%0\";
    }
    else if ( 2 == INTVAL ( operands[2] ))
    {
	return \"rol	%0\;\"
	       \"rol	%0\";
    }
    else
    {
	operands[3] = gen_rtx
	    ( CONST_INT, VOIDmode, INTVAL ( operands[2] ) & 0xfff );
	
	if ( TARGET_REP )
	{
	    return \"rep	#%3\;\"
		   \"rol	%0\";
	}
	else
	{
	    operands[4] = gen_label_rtx ( );
	    
	    return \"do	#%3,%l4\;\"
		   \"rol	%0\"
	       \"\\n%l4\";
	}
    }
}"
  "CCS_SET_CORRECTLY" )

( define_insn "rotlsi3"
  [ ( set ( match_operand:SI 0 "register_operand" "=D" )
     ( rotate:SI ( match_operand:SI 1 "register_operand" "0" )
                 ( match_operand:SI 2 "register_operand" "D" ))) ]
  ""
  "*return output_shift ( \"*rol\", operands );" )

( define_insn ""
  [ ( set ( match_operand:SI 0 "register_operand" "=D" )
     ( rotatert:SI ( match_operand:SI 1 "register_operand" "0" )
                   ( match_operand:SI 2 "immediate_operand" "i" ))) ]
  ""
  "*
{
    if ( 1 == INTVAL ( operands[2] ))
    {
	return \"ror	%0\";
    }
    else if ( 2 == INTVAL ( operands[2] ))
    {
	return \"ror	%0\;\"
	       \"ror	%0\";
    }
    else
    {
	operands[3] = gen_rtx
	    ( CONST_INT, VOIDmode, INTVAL ( operands[2] ) & 0xfff );
	
	if ( TARGET_REP )
	{
	    return \"rep	#%3\;\"
		   \"ror	%0\";
	}
	else
	{
	    operands[4] = gen_label_rtx ( );
	    
	    return \"do	#%3,%l4\;\"
		   \"ror	%0\"
	       \"\\n%l4\";
	}
    }
}"
  "CCS_SET_CORRECTLY" )

( define_insn "rotrsi3"
  [ ( set ( match_operand:SI 0 "register_operand" "=D" )
     ( rotatert:SI ( match_operand:SI 1 "register_operand" "0" )
                   ( match_operand:SI 2 "register_operand" "D" ))) ]
  ""
  "*return output_shift ( \"*ror\", operands );" )

;;  ...........................................................................
;;          COMPARISONS

;; We provide quick software emulation via a subroutine that emulates
;; a floating point instruction.

( define_insn "cmpsf"
  [ ( set ( cc0 )
          ( compare ( match_operand:SF 0 "register_operand" "D" )
                    ( match_operand:SF 1 "register_operand" "D" ))) ]
  ""
  "*
{
    if ( REGNO ( operands[0] ) == REGNO ( operands[1] ))
    {
	return \"andi	#$00,ccr\;ori	#$04,ccr\";
    }
    else
    {
        return output_pic_dep ( \"%2sr	fcmp_%1%0\", B, J, 2, operands );
    }
}" "CCS_SET_CORRECTLY | BSR_LAST_OP" )

( define_insn "cmpdf"
  [ ( set ( cc0 )
          ( compare ( match_operand:DF 0 "register_operand" "D" )
                    ( match_operand:DF 1 "register_operand" "D" ))) ]
  ""
  "*
{
    if ( REGNO ( operands[0] ) == REGNO ( operands[1] ))
    {
	return \"andi	#$00,ccr\;ori	#$04,ccr\";
    }
    else
    {
        return output_pic_dep ( \"%2sr	fcmp_%1%0\", B, J, 2, operands );
    }
}" "CCS_SET_CORRECTLY | BSR_LAST_OP" )

( define_expand "cmpsi"
  [ ( set ( cc0 )
          ( compare ( match_operand:SI 0 "register_operand" "" )
                    ( match_operand:SI 1 "register_operand" "" ))) ]
  "" "" )

( define_insn ""
  [ ( set ( cc0 )
          ( compare ( match_operand:SI 0 "register_operand" "D,D" )
                    ( match_operand:SI 1
		     "register_or_immediate_operand" "SD,I" ))) ]
  "UNSIGNED_COMPARE_P ( insn )"
  "*return output_compare ( insn, operands );" "CCS_SET_CORRECTLY" )

( define_insn ""
  [ ( set ( cc0 )
          ( compare ( match_operand:SI 0 "register_operand" "D,D" )
                    ( match_operand:SI 1 
			       "register_or_immediate_operand" "SD,i" ))) ]
  ""
  "*return output_compare ( insn, operands );" "CCS_SET_CORRECTLY" )

( define_insn ""
  [ ( set ( cc0 )
          ( compare ( match_operand:DI 0 "register_operand" "D" )
                    ( match_operand:DI 1 "register_operand" "D" ))) ]
  "UNSIGNED_COMPARE_P( insn )"
  "*return output_compare ( insn, operands );" "CCS_SET_CORRECTLY" )

( define_insn "cmpdi"
  [ ( set ( cc0 )
          ( compare ( match_operand:DI 0 "register_operand" "D" )
                    ( match_operand:DI 1 "register_operand" "D" ))) ]
  ""
  "*return output_compare ( insn, operands );" "CCS_SET_CORRECTLY" )

( define_expand "cmpsz"
  [ ( set ( cc0 )
          ( compare ( match_operand:SZ 0 "register_operand" "" )
                    ( match_operand:SZ 1 "register_operand" "" ))) ]
  "" "" )
 
( define_insn ""
  [ ( set ( cc0 )
          ( compare ( match_operand:SZ 0 "register_operand" "D,D" )
                    ( match_operand:SZ 1
                               "register_or_immediate_operand" "SD,i" ))) ]
  ""
  "*return output_compare ( insn, operands );" "CCS_SET_CORRECTLY" )


;;  ...........................................................................
;;          TESTS

( define_insn "tstsi"
  [ ( set ( cc0 ) ( match_operand:SI 0 "register_operand" "D" )) ]
  ""
  "*return output_tst ( insn, operands );" "CCS_SET_CORRECTLY" )

( define_insn "tstdi"
  [ ( set ( cc0 ) ( match_operand:DI 0 "general_operand" "D" )) ]
  ""
  "*return output_tst ( insn, operands );" "CCS_SET_CORRECTLY" )

( define_insn "tstsz"
  [ ( set ( cc0 ) ( match_operand:SZ 0 "register_operand" "D" )) ]
  "TARGET_C_FOR_DSP"
  "*return output_tst ( insn, operands );" "CCS_SET_CORRECTLY" )
 
( define_insn "tstdz"
  [ ( set ( cc0 ) ( match_operand:DZ 0 "general_operand" "D" )) ]
  "TARGET_C_FOR_DSP"
  "*return output_tst ( insn, operands );" "CCS_SET_CORRECTLY" )


;;  ...........................................................................
;;          SCALAR CONVERSIONS USING TRUNCATION

( define_insn "truncdisi2"
  [ ( set ( match_operand:SI 0 "general_operand" "=S,D" )
	  ( truncate:SI ( match_operand:DI 1 "general_operand" "S,D" ))) ]
  "" "move	%h1,%0" "CCS_NOT_AFFECTED" )
	
( define_insn "truncdzsz2"
  [ ( set ( match_operand:SZ 0 "general_operand" "=S,D" )
	  ( truncate:SZ ( match_operand:DZ 1 "general_operand" "S,D" ))) ]
  "TARGET_C_FOR_DSP"
  "move	%1,%0" "CCS_NOT_AFFECTED" )

;;  ...........................................................................
;;          SCALAR CONVERSIONS USING ZERO EXTENSION

( define_expand "zero_extendqisi2"
  [ ( set ( match_operand:SI 0 "register_operand" "" )
	  ( zero_extend:SI ( match_operand:QI 1 "register_operand" "" ))) ]
  ""
  "
{
    if ( SUBREG == GET_CODE ( operands[1] ))
    {
	operands[1] = copy_rtx ( SUBREG_REG ( operands[1] ));
    }
    else
    {
	operands[1] = copy_rtx ( operands[1] );
    }	
    operands[1] = gen_rtx ( SUBREG, SImode, operands[1], 0 );
    
    emit_insn ( gen_rtx ( SET, VOIDmode, operands[0], operands[1] ));

    DONE;
}" )

( define_insn "zero_extendsidi2"
  [ ( set ( match_operand:DI 0 "general_operand" "=&S,&S,&D,&D" )
	  ( zero_extend:DI 
	   ( match_operand:SI 1 "general_operand" "S,D,S,D" ))) ]
  ""
  "*
{
    if ( DST_REGS == REGNO_REG_CLASS ( REGNO ( operands[0] )))
    {
	return \"clr	%0\;\"
	       \"move	%e1,%h0\";
    }
    else
    {
	added_flags = CCS_NOT_AFFECTED;

	return \"move	%e1,%0\;\"
	       \"move	#0,%g0\";
    }
}")

;;  ...........................................................................
;;          SCALAR CONVERSIONS USING SIGN EXTENSION

( define_expand "extendqisi2"
  [ ( set ( match_operand:SI 0 "register_operand" "" )
	  ( sign_extend:SI ( match_operand:QI 1 "register_operand" "" ))) ]
  ""
  "
{
    if ( SUBREG == GET_CODE ( operands[1] ))
    {
	operands[1] = copy_rtx ( SUBREG_REG ( operands[1] ));
    }
    else
    {
	operands[1] = copy_rtx ( operands[1] );
    }
    operands[1] = gen_rtx ( SUBREG, SImode, operands[1], 0 );
    
    emit_insn ( gen_rtx ( SET, VOIDmode, operands[0], operands[1] ));

    DONE;
}" )

( define_insn "extendsidi2"
  [ ( set ( match_operand:DI 0 "general_operand" "+S,D" )
	  ( sign_extend:DI ( match_operand:SI 1 "general_operand" "D,r" ))) ]
  ""
  "*
{
    if ( which_alternative )
    {
	if ( DSP_B_REGNUM < REGNO ( operands[1] ))
	{
	    return \"move	%1,%0\;asr	#16,%0,%0\";
	}
	else
	{
	    return \"asr	#16,%1,%0\";
	}
    }
    else
    {
	return \"move	%e1,%0\;move	%k1,%g0\";
    }
}" )

( define_insn "extendszdz2"
  [ ( set ( match_operand:DZ 0 "general_operand" "=S" )
	  ( sign_extend:DZ ( match_operand:SZ 1 "general_operand" "D" ))) ]
  "TARGET_C_FOR_DSP"
  "move	%1,%0\;move	#0,%g0" "CCS_NOT_AFFECTED" )

;;  ...........................................................................
;;          CONVERSIONS BETWEEN FLOAT AND DOUBLE

;; float and double are the same data type in DSP56KCC. we need these dummy
;; conversion INSNs so that gcc (expr.c) doesn't go and create library calls
;; to do the conversions. This version of gcc truly screws up libcalls, so 
;; we must avoid using them (basically the REG_RETVAL/REG_LIBCALL mechanism
;; doesn't work.

( define_insn "extendsfdf2"
  [ ( set ( match_operand:DF 0 "register_operand" "=S,D" )
	  ( float_extend:DF
	    ( match_operand:SF 1 "register_operand" "0,0" ))) ]
  "" "" )

( define_insn "truncsfdf2"
  [ ( set ( match_operand:SF 0 "register_operand" "=S,D" )
	  ( float_truncate:SF
	    ( match_operand:DF 1 "register_operand" "0,0" ))) ]
  "" "" )

;;  ...........................................................................
;;          CONVERSIONS BETWEEN FLOATING POINT AND INTEGER

 ;; Using the signed routine at this point - this is a bug.

( define_insn "floatunssisf2"
  [ ( set ( match_operand:SF 0 "register_operand" "=D" )
	  ( unsigned_float:SF ( match_operand:SI 1 "register_operand" "0" ))) ]
  ""
  "*return output_pic_dep ( \"%2sr	floatsidf_%0\", B, J, 2, operands );"
  "CCS_SET_CORRECTLY | BSR_LAST_OP" )

 ;; Using the signed routine at this point - this is a bug.

( define_insn "floatunssidf2"
  [ ( set ( match_operand:DF 0 "register_operand" "=D" )
	  ( unsigned_float:DF ( match_operand:SI 1 "register_operand" "0" ))) ]
  ""
  "*return output_pic_dep ( \"%2sr	floatsidf_%0\", B, J, 2, operands );"
  "CCS_SET_CORRECTLY | BSR_LAST_OP" )

 ;; Using the signed routine at this point - this is a bug.

( define_insn "floatsisf2"
  [ ( set ( match_operand:SF 0 "register_operand" "=D" )
	  ( float:SF ( match_operand:SI 1 "register_operand" "0" ))) ]
  ""
  "*return output_pic_dep ( \"%2sr	floatsidf_%0\", B, J, 2, operands );"
  "CCS_SET_CORRECTLY | BSR_LAST_OP" )
	
( define_insn "floatsidf2"
  [ ( set ( match_operand:DF 0 "register_operand" "=D" )
	  ( float:DF ( match_operand:SI 1 "register_operand" "0" ))) ]
  ""
  "*return output_pic_dep ( \"%2sr	floatsidf_%0\", B, J, 2, operands );"
  "CCS_SET_CORRECTLY | BSR_LAST_OP" )
	
( define_insn "fixsfsi2"
  [ ( set ( match_operand:SI 0 "register_operand" "=D" )
	  ( fix:SI ( match_operand:SF 1 "register_operand" "0" ))) ]
  ""
  "*return output_pic_dep ( \"%2sr	fixdfsi_%0\", B, J, 2, operands );"
  "CCS_SET_CORRECTLY | BSR_LAST_OP" )

( define_insn "fixdfsi2"
  [ ( set ( match_operand:SI 0 "register_operand" "=D" )
	  ( fix:SI ( match_operand:DF 1 "register_operand" "0" ))) ]
  ""
  "*return output_pic_dep ( \"%2sr	fixdfsi_%0\", B, J, 2, operands );"
  "CCS_SET_CORRECTLY | BSR_LAST_OP" )

( define_insn "fixunssfsi2"
  [ ( set ( match_operand:SI 0 "register_operand" "=D" )
	  ( unsigned_fix:SI ( match_operand:SF 1 "register_operand" "0" ))) ]
  ""
  "*return output_pic_dep ( \"%2sr	fixunsdfsi_%0\", B, J, 2, operands );"
  "CCS_SET_CORRECTLY | BSR_LAST_OP" )

 ;; Using the signed routine at this point - this is a bug.

( define_insn "fixunsdfsi2"
  [ ( set ( match_operand:SI 0 "register_operand" "=D" )
	  ( unsigned_fix:SI ( match_operand:DF 1 "register_operand" "0" ))) ]
  ""
  "*return output_pic_dep ( \"%2sr	fixunsdfsi_%0\", B, J, 2, operands );"
  "CCS_SET_CORRECTLY | BSR_LAST_OP" )

 ;; Using the signed routine at this point - this is a bug.

( define_insn "floatunsdisf2"
  [ ( set ( match_operand:SF 0 "register_operand" "=D" )
	  ( unsigned_float:SF ( match_operand:DI 1 "register_operand" "0" ))) ]
  ""
  "*return output_pic_dep ( \"%2sr	floatdidf_%0\", B, J, 2, operands );"
  "CCS_SET_CORRECTLY | BSR_LAST_OP" )

 ;; Using the signed routine at this point - this is a bug.

( define_insn "floatunsdidf2"
  [ ( set ( match_operand:DF 0 "register_operand" "=D" )
	  ( unsigned_float:DF ( match_operand:DI 1 "register_operand" "0" ))) ]
  ""
  "*return output_pic_dep ( \"%2sr	floatdidf_%0\", B, J, 2, operands );"
  "CCS_SET_CORRECTLY | BSR_LAST_OP" )

 ;; Using the signed routine at this point - this is a bug.

( define_insn "floatdisf2"
  [ ( set ( match_operand:SF 0 "register_operand" "=D" )
	  ( float:SF ( match_operand:DI 1 "register_operand" "0" ))) ]
  ""
  "*return output_pic_dep ( \"%2sr	floatdidf_%0\", B, J, 2, operands );"
  "CCS_SET_CORRECTLY | BSR_LAST_OP" )
	
( define_insn "floatdidf2"
  [ ( set ( match_operand:DF 0 "register_operand" "=D" )
	  ( float:DF ( match_operand:DI 1 "register_operand" "0" ))) ]
  ""
  "*return output_pic_dep ( \"%2sr	floatdidf_%0\", B, J, 2, operands );"
  "CCS_SET_CORRECTLY | BSR_LAST_OP" )
	
( define_insn "fixsfdi2"
  [ ( set ( match_operand:DI 0 "register_operand" "=D" )
	  ( fix:DI ( match_operand:SF 1 "register_operand" "0" ))) ]
  ""
  "*return output_pic_dep ( \"%2sr	fixdfdi_%0\", B, J, 2, operands );"
  "CCS_SET_CORRECTLY | BSR_LAST_OP" )

( define_insn "fixdfdi2"
  [ ( set ( match_operand:DI 0 "register_operand" "=D" )
	  ( fix:DI ( match_operand:DF 1 "register_operand" "0" ))) ]
  ""
  "*return output_pic_dep ( \"%2sr	fixdfdi_%0\", B, J, 2, operands );"
  "CCS_SET_CORRECTLY | BSR_LAST_OP" )

( define_insn "fixunssfdi2"
  [ ( set ( match_operand:DI 0 "register_operand" "=D" )
	  ( unsigned_fix:DI ( match_operand:SF 1 "register_operand" "0" ))) ]
  ""
  "*return output_pic_dep ( \"%2sr	fixunsdfdi_%0\", B, J, 2, operands );"
  "CCS_SET_CORRECTLY | BSR_LAST_OP" )

( define_insn "fixunsdfdi2"
  [ ( set ( match_operand:DI 0 "register_operand" "=D" )
	  ( unsigned_fix:DI ( match_operand:DF 1 "register_operand" "0" ))) ]
  ""
  "*return output_pic_dep ( \"%2sr	fixunsdfdi_%0\", B, J, 2, operands );"
  "CCS_SET_CORRECTLY | BSR_LAST_OP" )

( define_expand "fix_truncsfsi2"
  [ ( set ( match_operand:SI 0 "register_operand" "=D" )
	  ( fix:SI ( match_operand:SF 1 "register_operand" "0" ))) ]
  ""
  "" )

( define_expand "fix_truncdfsi2"
  [ ( set ( match_operand:SI 0 "register_operand" "=D" )
	  ( fix:SI ( match_operand:DF 1 "register_operand" "0" ))) ]
  ""
  "" )

( define_expand "fixuns_truncsfsi2"
  [ ( set ( match_operand:SI 0 "register_operand" "=D" )
	  ( unsigned_fix:SI ( match_operand:SF 1 "register_operand" "0" ))) ]
  ""
  "" )

( define_expand "fixuns_truncdfsi2"
  [ ( set ( match_operand:SI 0 "register_operand" "=D" )
	  ( unsigned_fix:SI ( match_operand:DF 1 "register_operand" "0" ))) ]
  ""
  "" )

( define_expand "fix_truncsfdi2"
  [ ( set ( match_operand:DI 0 "register_operand" "=D" )
	  ( fix:DI ( match_operand:SF 1 "register_operand" "0" ))) ]
  ""
  "" )

( define_expand "fix_truncdfdi2"
  [ ( set ( match_operand:DI 0 "register_operand" "=D" )
	  ( fix:DI ( match_operand:DF 1 "register_operand" "0" ))) ]
  ""
  "" )

( define_expand "fixuns_truncsfdi2"
  [ ( set ( match_operand:DI 0 "register_operand" "=D" )
	  ( unsigned_fix:DI ( match_operand:SF 1 "register_operand" "0" ))) ]
  ""
  "" )

( define_expand "fixuns_truncdfdi2"
  [ ( set ( match_operand:DI 0 "register_operand" "=D" )
	  ( unsigned_fix:DI ( match_operand:DF 1 "register_operand" "0" ))) ]
  ""
  "" )


;;  ...........................................................................
;;          CONVERSIONS BETWEEN FLOATING POINT AND FRACS
( define_insn "floatszdf2"
  [ ( set ( match_operand:DF 0 "register_operand" "=D" )
	  ( float:DF ( match_operand:SZ 1 "register_operand" "0" ))) ]
  ""
  "*return output_pic_dep ( \"%2sr	floatszdf_%0\", B, J, 2, operands );"
  "CCS_SET_CORRECTLY | BSR_LAST_OP" )

( define_insn "floatdzdf2"
  [ ( set ( match_operand:DF 0 "register_operand" "=D" )
	  ( float:DF ( match_operand:DZ 1 "register_operand" "0" ))) ]
  ""
  "*return output_pic_dep ( \"%2sr	floatdzdf_%0\", B, J, 2, operands );"
  "CCS_SET_CORRECTLY | BSR_LAST_OP" )


( define_insn "fracsfsz2"
  [ ( set ( match_operand:SZ 0 "register_operand" "=D" )
	  ( frac:SZ ( match_operand:SF 1 "register_operand" "0" ))) ]
  ""
  "*return output_pic_dep ( \"%2sr	fracsfsz_%0\", B, J, 2, operands );"
  "CCS_SET_CORRECTLY | BSR_LAST_OP" )

( define_insn "fixdfsz2"
  [ ( set ( match_operand:SZ 0 "register_operand" "=D" )
	  ( fix:SZ ( match_operand:DF 1 "register_operand" "0" ))) ]
  ""
  "*return output_pic_dep ( \"%2sr	fixdfsz_%0\", B, J, 2, operands );"
  "CCS_SET_CORRECTLY | BSR_LAST_OP" )

( define_insn "fixdfdz2"
  [ ( set ( match_operand:DZ 0 "register_operand" "=D" )
	  ( fix:DZ ( match_operand:DF 1 "register_operand" "0" ))) ]
  ""
  "*return output_pic_dep ( \"%2sr	fixdfdz_%0\", B, J, 2, operands );"
  "CCS_SET_CORRECTLY | BSR_LAST_OP" )


;;  ...........................................................................
;;          CONVERSIONS FROM INTEGERS TO FRACS
( define_expand "fracsisz2"
  [ ( set ( match_operand:SZ 0 "register_operand" "=D" )
          ( frac:SZ ( match_operand:SI 1 "register_operand" "0" ))) ]
  ""
  "" )
 
( define_insn ""
  [ ( set ( match_operand:SZ 0 "register_operand" "=D" )
          ( frac:SZ ( match_operand:SI 1 "register_operand" "0" ))) ]
  "TARGET_C_FOR_DSP"
  "; SI->SZ" "CCS_SET_CORRECTLY" )
 
;; Shot in the dark...
( define_expand "truncszsi2"
  [ ( set ( match_operand:SI 0 "register_operand" "=D" )
          ( truncate:SI ( match_operand:SZ 1 "register_operand" "0" ))) ]
  ""
  "" )
 
( define_insn ""
  [ ( set ( match_operand:SI 0 "register_operand" "=D" )
          ( truncate:SI ( match_operand:SZ 1 "register_operand" "0" ))) ]
  "TARGET_C_FOR_DSP"
  "; SZ->SI" "CCS_SET_CORRECTLY" )
 

;;  ...........................................................................
;;          CONDITIONAL JUMPS

( define_insn "do"
  [ ( parallel
      [ ( clobber ( cc0 ))
	( use ( match_operand:SI 0 "general_operand" "r,J" ))
	( set ( pc ) ( if_then_else ( eq ( cc0 ) ( const_int 0 ))
				    ( label_ref ( match_operand 1 "" "" ))
				    ( pc ))) ] ) ]
  ""
  "*return output_do ( insn, operands );" )

;; This shape should match the back-branch insn and produce no real code.
;; It is a placeholder so that the compiler knows that the do loop target
;; label is implicitly a branch.

( define_insn "od"
  [ ( parallel 
      [ ( clobber ( cc0 )) ( set ( pc ) ( match_operand 0 "" "" )) ] ) ]
  ""
  "*return output_od ( insn, operands );" )

;;  ...........................................................................
;;          CONDITIONAL 1/0 SETS

( define_expand "seq"
  [ ( parallel
      [ ( set ( match_operand:SI 0 "register_operand" "" )
	      ( eq ( cc0 ) ( const_int 0 )))
	( clobber ( match_operand:SI 1 "register_operand" "" )) ] ) ] 
  "" "{ operands[1] = gen_reg_rtx ( SImode ); }" )
    
( define_expand "sne"
  [ ( parallel
      [ ( set ( match_operand:SI 0 "register_operand" "" )
	      ( ne ( cc0 ) ( const_int 0 )))
	( clobber ( match_operand:SI 1 "register_operand" "" )) ] ) ] 
  "" "{ operands[1] = gen_reg_rtx ( SImode ); }" )
    
( define_expand "sgt"
  [ ( parallel
      [ ( set ( match_operand:SI 0 "register_operand" "" )
	      ( gt ( cc0 ) ( const_int 0 )))
	( clobber ( match_operand:SI 1 "register_operand" "" )) ] ) ] 
  "" "{ operands[1] = gen_reg_rtx ( SImode ); }" )
    
( define_expand "sge"
  [ ( parallel
      [ ( set ( match_operand:SI 0 "register_operand" "" )
	      ( ge ( cc0 ) ( const_int 0 )))
	( clobber ( match_operand:SI 1 "register_operand" "" )) ] ) ] 
  "" "{ operands[1] = gen_reg_rtx ( SImode ); }" )
    
( define_expand "slt"
  [ ( parallel
      [ ( set ( match_operand:SI 0 "register_operand" "" )
	      ( lt ( cc0 ) ( const_int 0 )))
	( clobber ( match_operand:SI 1 "register_operand" "" )) ] ) ] 
  "" "{ operands[1] = gen_reg_rtx ( SImode ); }" )
    
( define_expand "sle"
  [ ( parallel
      [ ( set ( match_operand:SI 0 "register_operand" "" )
	      ( le ( cc0 ) ( const_int 0 )))
	( clobber ( match_operand:SI 1 "register_operand" "" )) ] ) ] 
  "" "{ operands[1] = gen_reg_rtx ( SImode ); }" )
    
( define_expand "sequ"
  [ ( parallel
      [ ( set ( match_operand:SI 0 "register_operand" "" )
	      ( equ ( cc0 ) ( const_int 0 )))
	( clobber ( match_operand:SI 1 "register_operand" "" )) ] ) ] 
  "" "{ operands[1] = gen_reg_rtx ( SImode ); }" )
    
( define_expand "sneu"
  [ ( parallel
      [ ( set ( match_operand:SI 0 "register_operand" "" )
	      ( neu ( cc0 ) ( const_int 0 )))
	( clobber ( match_operand:SI 1 "register_operand" "" )) ] ) ] 
  "" "{ operands[1] = gen_reg_rtx ( SImode ); }" )
    
( define_expand "sgtu"
  [ ( parallel
      [ ( set ( match_operand:SI 0 "register_operand" "" )
	      ( gtu ( cc0 ) ( const_int 0 )))
	( clobber ( match_operand:SI 1 "register_operand" "" )) ] ) ] 
  "" "{ operands[1] = gen_reg_rtx ( SImode ); }" )
    
( define_expand "sgeu"
  [ ( parallel
      [ ( set ( match_operand:SI 0 "register_operand" "" )
	      ( geu ( cc0 ) ( const_int 0 )))
	( clobber ( match_operand:SI 1 "register_operand" "" )) ] ) ] 
  "" "{ operands[1] = gen_reg_rtx ( SImode ); }" )
    
( define_expand "sltu"
  [ ( parallel
      [ ( set ( match_operand:SI 0 "register_operand" "" )
	      ( ltu ( cc0 ) ( const_int 0 )))
	( clobber ( match_operand:SI 1 "register_operand" "" )) ] ) ] 
  "" "{ operands[1] = gen_reg_rtx ( SImode ); }" )
    
( define_expand "sleu"
  [ ( parallel
      [ ( set ( match_operand:SI 0 "register_operand" "" )
	      ( leu ( cc0 ) ( const_int 0 )))
	( clobber ( match_operand:SI 1 "register_operand" "" )) ] ) ] 
  "" "{ operands[1] = gen_reg_rtx ( SImode ); }" )
    
( define_insn ""
  [ ( parallel 
      [ ( set ( match_operand:SI 0 "register_operand" "=D,D" )
	      ( match_operator 2 "cond_operator" [ ( cc0 ) ( const_int 0 ) ] ))
	( clobber ( match_operand:SI 1 "register_operand" "=S,D" )) ] ) ]
  ""
  "move	#>1,%1\;move	#0,%0\;t%2	%1,%0" )

;; when the optimizer grinds on a conditional 1/0 set, either of the 
;; following two INSNs can be left hanging around. 

( define_insn ""
  [ ( parallel
      [ ( set ( match_operand:SI 0 "register_operand" "=r" )
	      ( match_operand:SI 1 "immediate_operand" "i"))
	( clobber ( match_operand:SI 2 "general_operand" "=mr" )) ] ) ]
  "" "*{ which_alternative = 3; return move_single_integer ( operands ); }" )

;;  ...........................................................................
;;          CONDITIONAL JUMPS 

( define_expand "beq"
  [ ( set ( pc ) ( if_then_else ( eq ( cc0 ) ( const_int 0 ))
				( label_ref ( match_operand 0 "" "" ))
				( pc ))) ] "" "" )
( define_expand "bne"
  [ ( set ( pc ) ( if_then_else ( ne ( cc0 ) ( const_int 0 ))
				( label_ref ( match_operand 0 "" "" ))
				( pc ))) ] "" "" )
( define_expand "bgt"
  [ ( set ( pc ) ( if_then_else ( gt ( cc0 ) ( const_int 0 ))
				( label_ref ( match_operand 0 "" "" ))
				( pc ))) ] "" "" )
( define_expand "bge"
  [ ( set ( pc ) ( if_then_else ( ge ( cc0 ) ( const_int 0 ))
				( label_ref ( match_operand 0 "" "" ))
				( pc ))) ] "" "" )
( define_expand "blt"
  [ ( set ( pc ) ( if_then_else ( lt ( cc0 ) ( const_int 0 ))
				( label_ref ( match_operand 0 "" "" ))
				( pc ))) ] "" "" )
( define_expand "ble"
  [ ( set ( pc ) ( if_then_else ( le ( cc0 ) ( const_int 0 ))
				( label_ref ( match_operand 0 "" "" ))
				( pc ))) ] "" "" )
( define_expand "bequ"
  [ ( set ( pc ) ( if_then_else ( equ ( cc0 ) ( const_int 0 ))
				( label_ref ( match_operand 0 "" "" ))
				( pc ))) ] "" "" )
( define_expand "bneu"
  [ ( set ( pc ) ( if_then_else ( neu ( cc0 ) ( const_int 0 ))
				( label_ref ( match_operand 0 "" "" ))
				( pc ))) ] "" "" )
( define_expand "bgtu"
  [ ( set ( pc ) ( if_then_else ( gtu ( cc0 ) ( const_int 0 ))
				( label_ref ( match_operand 0 "" "" ))
				( pc ))) ] "" "" )
( define_expand "bgeu"
  [ ( set ( pc ) ( if_then_else ( geu ( cc0 ) ( const_int 0 ))
				( label_ref ( match_operand 0 "" "" ))
				( pc ))) ] "" "" )
( define_expand "bltu"
  [ ( set ( pc ) ( if_then_else ( ltu ( cc0 ) ( const_int 0 ))
				( label_ref ( match_operand 0 "" "" ))
				( pc ))) ] "" "" )
( define_expand "bleu"
  [ ( set ( pc ) ( if_then_else ( leu ( cc0 ) ( const_int 0 ))
				( label_ref ( match_operand 0 "" "" ))
				( pc ))) ] "" "" )
( define_insn ""
  [ ( set ( pc )
	  ( if_then_else ( match_operator 1 "cond_operator"
					  [ ( cc0 ) ( const_int 0 ) ] )
			 ( label_ref ( match_operand 0 "" "" )) ( pc ))) ]
  ""
  "*return output_pic_dep ( \"%2%1	%l0\", B, J, 2, operands );"
  "CCS_NOT_AFFECTED" )

( define_insn ""
  [ ( set ( pc )
	  ( if_then_else ( match_operator 1 "cond_operator"
					  [ ( cc0 ) ( const_int 0 ) ] )
			 ( pc ) ( label_ref ( match_operand 0 "" "" )))) ]
  ""
  "*
{ 
    PUT_CODE ( operands[1], reverse_condition ( GET_CODE ( operands[1] )));

    return output_pic_dep ( \"%2%1	%l0\", B, J, 2, operands );
}" "CCS_NOT_AFFECTED" )

;;  ...........................................................................
;;          UNCONDITIONAL JUMP

( define_insn "jump"
  [ ( set ( pc ) ( label_ref ( match_operand 0 "" "" ) ) ) ]
  ""
  "*return output_pic_dep ( \"%1	%l0\", BRA, JMP, 1, operands );"
  "CCS_NOT_AFFECTED" )

;;  ...........................................................................
;;          TABLE JUMP ( SWITCH IMPLEMENTATION )


;;(define_insn "tablejump"
;;  [(set (pc) (match_operand:SI 0 "register_operand" "r"))
;;   (use (label_ref (match_operand 1 "" "")))]
;;  ""
;;  "jump (%0)" "CCS_NOT_AFFECTED" )

( define_insn "tablejump"
  [ ( parallel [ ( set ( pc ) ( match_operand:SI 0 "indirect_memory_operand" "m" ))
		 ( clobber ( match_operand:SI 1 "register_operand" "=A" ))
		 ( use ( label_ref ( match_operand 2 "" "" ))) ] ) ]	
  ""
  "*
{
    if ( TARGET_P_MEM_SWITCHTABLE )
    {
	return \"move	p:%f0,%1\;\"
	       \"jmp	(%1)\";
    }
    else
    {
	return output_pic_dep 
	    ( \"move	%0,%1\;\"
	      \"%3	(%1)\", BRA, JMP, 3, operands );
    }
}" "CCS_NOT_AFFECTED" )

;;  ...........................................................................
;;          BITFIELD ACTION

( define_insn ""
  [ ( set ( zero_extract:SI
	    ( match_operand:SI 0 "restricted_memory_operand" "m" )
	    ( match_operand:SI 1 "one_inclusive_eight_operand" "i" )
	    ( match_operand:SI 2 "immediate_operand" "i" ))
	  ( not ( sign_extract:SI
		  ( match_dup 0 ) ( match_dup 1 ) ( match_dup 2 )))) ]
  ""
  "*
{
    static char conglom[BUFSIZ];
    char *where = conglom;
    int bit;
    int start = INTVAL ( operands[2] );
    int limit = start + INTVAL ( operands[1] ) - 1;

    for ( bit = start; bit < limit; ++ bit )
    {
	sprintf ( where, \"bchg	#%d,%%0\;\", bit );
	where += strlen ( where );
    }
    sprintf ( where, \"bchg	#%d,%%0\", bit );

    return conglom;
}" )

( define_insn ""
  [ ( set ( zero_extract:SI
	    ( match_operand:SI 0 "register_operand" "r" )
	    ( match_operand:SI 1 "one_inclusive_eight_operand" "i" )
	    ( match_operand:SI 2 "immediate_operand" "i" ))
	  ( not ( sign_extract:SI
		  ( match_dup 0 ) ( match_dup 1 ) ( match_dup 2 )))) ]
  ""
  "*
{
    static char conglom[BUFSIZ];
    char *where = conglom;
    int bit;
    int start = INTVAL ( operands[2] );
    int limit = start + INTVAL ( operands[1] ) - 1;

    for ( bit = start; bit < limit; ++ bit )
    {
	sprintf ( where, \"bchg	#%d,%%0\;\", bit );
	where += strlen ( where );
    }
    sprintf ( where, \"bchg	#%d,%%0\", bit );

    return conglom;
}" )

;; the next four shapes are single bit-test branch instructions. we need
;; four shapes because we either test positive or test negative, and we
;; can either be dropping through as the else case or jumping as the
;; else case.

( define_insn ""
  [ ( set
      ( pc )
      ( if_then_else 
	( eq
	  ( compare
	    ( sign_extract 
	      ( match_operand:SI 0 "indirect_memory_operand" "m" )
	      ( const_int 1 ) 
	      ( match_operand:SI 1 "immediate_operand" "i" ))
	    ( match_operand:SI 3 "immediate_operand" "i" ))
	  ( const_int 0 ))
	( pc )
	( label_ref ( match_operand 2 "" "" )))) ]
  ""
  "*
{
    switch ( INTVAL ( operands[3] ))
    {
    case 0:
	return output_pic_dep ( \"%4set	#%1,%0,%l2\", BR, J, 4, operands );

    case 1:
	return output_pic_dep ( \"%4clr	#%1,%0,%l2\", BR, J, 4, operands );

    default:
	/* we know that a bit ins't going to be equal to anything
	   other than a 1 or 0, so hard code the false case. */

	return output_pic_dep ( \"%4	%l2\", BRA, JMP, 4, operands );
    }
}" )

( define_insn ""
  [ ( set
      ( pc )
      ( if_then_else 
	( eq
	  ( compare
	    ( sign_extract 
	      ( match_operand:SI 0 "register_operand" "r" )
	      ( const_int 1 ) 
	      ( match_operand:SI 1 "immediate_operand" "i" ))
	    ( match_operand:SI 3 "immediate_operand" "i" ))
	  ( const_int 0 ))
	( pc )
	( label_ref ( match_operand 2 "" "" )))) ]
  ""
  "*
{
    switch ( INTVAL ( operands[3] ))
    {
    case 0:
	return output_pic_dep ( \"%4set	#%1,%0,%l2\", BR, J, 4, operands );

    case 1:
	return output_pic_dep ( \"%4clr	#%1,%0,%l2\", BR, J, 4, operands );

    default:
	/* we know that a bit ins't going to be equal to anything
	   other than a 1 or 0, so hard code the false case. */

	return output_pic_dep ( \"%4	%l2\", BRA, JMP, 4, operands );
    }
}" )
    
( define_insn ""
  [ ( set
      ( pc )
      ( if_then_else 
	( ne
	  ( compare
	    ( sign_extract 
	      ( match_operand:SI 0 "indirect_memory_operand" "m" )
	      ( const_int 1 ) 
	      ( match_operand:SI 1 "immediate_operand" "i" ))
	    ( match_operand:SI 3 "immediate_operand" "i" ))
	  ( const_int 0 ))
	( pc )
	( label_ref ( match_operand 2 "" "" )))) ]
  ""
  "*
{
    switch ( INTVAL ( operands[3] ))
    {
    case 0:
	return output_pic_dep ( \"%4clr	#%1,%0,%l2\", BR, J, 4, operands );

    case 1:
	return output_pic_dep ( \"%4set	#%1,%0,%l2\", BR, J, 4, operands );

    default:
	/* we know that a bit ins't going to be equal to anything
	   other than a 1 or 0, so hard code the true case. */

	return \"\";
    }
}" )
    
( define_insn ""
  [ ( set
      ( pc )
      ( if_then_else 
	( ne
	  ( compare
	    ( sign_extract 
	      ( match_operand:SI 0 "register_operand" "r" )
	      ( const_int 1 ) 
	      ( match_operand:SI 1 "immediate_operand" "i" ))
	    ( match_operand:SI 3 "immediate_operand" "i" ))
	  ( const_int 0 ))
	( pc )
	( label_ref ( match_operand 2 "" "" )))) ]
  ""
  "*
{
    switch ( INTVAL ( operands[3] ))
    {
    case 0:
	return output_pic_dep ( \"%4clr	#%1,%0,%l2\", BR, J, 4, operands );

    case 1:
	return output_pic_dep ( \"%4set	#%1,%0,%l2\", BR, J, 4, operands );

    default:
	/* we know that a bit ins't going to be equal to anything
	   other than a 1 or 0, so hard code the true case. */

	return \"\";
    }
}" )
    
( define_insn ""
  [ ( set
      ( pc )
      ( if_then_else 
	( eq
	  ( compare
	    ( sign_extract 
	      ( match_operand:SI 0 "indirect_memory_operand" "m" )
	      ( const_int 1 ) 
	      ( match_operand:SI 1 "immediate_operand" "i" ))
	    ( match_operand:SI 3 "immediate_operand" "i" ))
	  ( const_int 0 ))
	( label_ref ( match_operand 2 "" "" ))
	( pc ))) ]
  ""
  "*
{
    switch ( INTVAL ( operands[3] ))
    {
    case 0:
	return output_pic_dep ( \"%4clr	#%1,%0,%l2\", BR, J, 4, operands );

    case 1:
	return output_pic_dep ( \"%4set	#%1,%0,%l2\", BR, J, 4, operands );

    default:
	/* we know that a bit ins't going to be equal to anything
	   other than a 1 or 0, so hard code the true case. */

	return \"\";
    }
}" )
    
( define_insn ""
  [ ( set
      ( pc )
      ( if_then_else 
	( eq
	  ( compare
	    ( sign_extract 
	      ( match_operand:SI 0 "register_operand" "r" )
	      ( const_int 1 ) 
	      ( match_operand:SI 1 "immediate_operand" "i" ))
	    ( match_operand:SI 3 "immediate_operand" "i" ))
	  ( const_int 0 ))
	( label_ref ( match_operand 2 "" "" ))
	( pc ))) ]
  ""
  "*
{
    switch ( INTVAL ( operands[3] ))
    {
    case 0:
	return output_pic_dep ( \"%4clr	#%1,%0,%l2\", BR, J, 4, operands );

    case 1:
	return output_pic_dep ( \"%4set	#%1,%0,%l2\", BR, J, 4, operands );

    default:
	/* we know that a bit ins't going to be equal to anything
	   other than a 1 or 0, so hard code the true case. */

	return \"\";
    }
}" )
    
( define_insn ""
  [ ( set
      ( pc )
      ( if_then_else 
	( ne
	  ( compare
	    ( sign_extract 
	      ( match_operand:SI 0 "indirect_memory_operand" "m" )
	      ( const_int 1 ) 
	      ( match_operand:SI 1 "immediate_operand" "i" ))
	    ( match_operand:SI 3 "immediate_operand" "i" ))
	  ( const_int 0 ))
	( label_ref ( match_operand 2 "" "" ))
	( pc ))) ]
  ""
  "*
{
    switch ( INTVAL ( operands[3] ))
    {
    case 0:
	return output_pic_dep ( \"%4set	#%1,%0,%l2\", BR, J, 4, operands );

    case 1:
	return output_pic_dep ( \"%4clr	#%1,%0,%l2\", BR, J, 4, operands );

    default:
	/* we know that a bit ins't going to be equal to anything
	   other than a 1 or 0, so hard code the false case. */

	return output_pic_dep ( \"%4	%l2\", BRA, JMP, 4, operands );
    }
}" )
    
( define_insn ""
  [ ( set
      ( pc )
      ( if_then_else 
	( ne
	  ( compare
	    ( sign_extract 
	      ( match_operand:SI 0 "register_operand" "r" )
	      ( const_int 1 ) 
	      ( match_operand:SI 1 "immediate_operand" "i" ))
	    ( match_operand:SI 3 "immediate_operand" "i" ))
	  ( const_int 0 ))
	( label_ref ( match_operand 2 "" "" ))
	( pc ))) ]
  ""
  "*
{
    switch ( INTVAL ( operands[3] ))
    {
    case 0:
	return output_pic_dep ( \"%4set	#%1,%0,%l2\", BR, J, 4, operands );

    case 1:
	return output_pic_dep ( \"%4clr	#%1,%0,%l2\", BR, J, 4, operands );

    default:
	/* we know that a bit ins't going to be equal to anything
	   other than a 1 or 0, so hard code the false case. */

	return output_pic_dep ( \"%4	%l2\", BRA, JMP, 4, operands );
    }
}" )
    
;; the next eight shapes are single bit-test branch instructions. we need
;; eight shapes because we either test positive or test negative, and we
;; can either be dropping through as the else case or jumping as the
;; else case. this is doubled again, to match bitwise and tests.

( define_insn ""
  [ ( set
      ( pc )
      ( if_then_else 
	( eq
	  ( sign_extract 
	    ( match_operand:SI 0 "indirect_memory_operand" "m" )
	    ( const_int 1 ) 
	    ( match_operand:SI 1 "immediate_operand" "i" ))
	  ( const_int 0 ))
	( pc )
	( label_ref ( match_operand 2 "" "" )))) ]
  ""
  "*return output_pic_dep ( \"%3set	#%1,%0,%l2\", BR, J, 3, operands );" )

( define_insn ""
  [ ( set
      ( pc )
      ( if_then_else 
	( eq
	  ( sign_extract 
	    ( match_operand:SI 0 "register_operand" "r" )
	    ( const_int 1 ) 
	    ( match_operand:SI 1 "immediate_operand" "i" ))
	  ( const_int 0 ))
	( pc )
	( label_ref ( match_operand 2 "" "" )))) ]
  ""
  "*return output_pic_dep ( \"%3set	#%1,%0,%l2\", BR, J, 3, operands );" )

( define_insn ""
  [ ( set
      ( pc )
      ( if_then_else
	( ne
	  ( sign_extract
	    ( match_operand:SI 0 "indirect_memory_operand" "m" )
	    ( const_int 1 ) 
	    ( match_operand:SI 1 "immediate_operand" "i" ))
	  ( const_int 0 ))
	( pc )
	( label_ref ( match_operand 2 "" "" )))) ]
  ""
  "*return output_pic_dep ( \"%3clr	#%1,%0,%l2\", BR, J, 3, operands );" )
      
( define_insn ""
  [ ( set
      ( pc )
      ( if_then_else
	( ne
	  ( sign_extract
	    ( match_operand:SI 0 "register_operand" "r" )
	    ( const_int 1 ) 
	    ( match_operand:SI 1 "immediate_operand" "i" ))
	  ( const_int 0 ))
	( pc )
	( label_ref ( match_operand 2 "" "" )))) ]
  ""
  "*return output_pic_dep ( \"%3clr	#%1,%0,%l2\", BR, J, 3, operands );" )
      
( define_insn ""
  [ ( set
      ( pc )
      ( if_then_else 
	( eq
	  ( sign_extract 
	    ( match_operand:SI 0 "indirect_memory_operand" "m" )
	    ( const_int 1 ) 
	    ( match_operand:SI 1 "immediate_operand" "i" ))
	  ( const_int 0 ))
	( label_ref ( match_operand 2 "" "" ))
	( pc ))) ]
  ""
  "*return output_pic_dep ( \"%3clr	#%1,%0,%l2\", BR, J, 3, operands );" )
      
( define_insn ""
  [ ( set
      ( pc )
      ( if_then_else 
	( eq
	  ( sign_extract 
	    ( match_operand:SI 0 "register_operand" "r" )
	    ( const_int 1 ) 
	    ( match_operand:SI 1 "immediate_operand" "i" ))
	  ( const_int 0 ))
	( label_ref ( match_operand 2 "" "" ))
	( pc ))) ]
  ""
  "*return output_pic_dep ( \"%3clr	#%1,%0,%l2\", BR, J, 3, operands );" )
      
( define_insn ""
  [ ( set
      ( pc )
      ( if_then_else 
	( ne
	  ( sign_extract 
	    ( match_operand:SI 0 "indirect_memory_operand" "m" )
	    ( const_int 1 ) 
	    ( match_operand:SI 1 "immediate_operand" "i" ))
	  ( const_int 0 ))
	( label_ref ( match_operand 2 "" "" ))
	( pc ))) ]
  ""
  "*return output_pic_dep ( \"%3set	#%1,%0,%l2\", BR, J, 3, operands );" )
      
( define_insn ""
  [ ( set
      ( pc )
      ( if_then_else 
	( ne
	  ( sign_extract 
	    ( match_operand:SI 0 "register_operand" "r" )
	    ( const_int 1 ) 
	    ( match_operand:SI 1 "immediate_operand" "i" ))
	  ( const_int 0 ))
	( label_ref ( match_operand 2 "" "" ))
	( pc ))) ]
  ""
  "*return output_pic_dep ( \"%3set	#%1,%0,%l2\", BR, J, 3, operands );" )
      
;; and now, the bitwise and tests.

( define_insn ""
  [ ( set
      ( pc )
      ( if_then_else 
	( eq
	  ( and:SI
	    ( match_operand:SI 0 "indirect_memory_operand" "m" )
	    ( match_operand:SI 1 "pow_two_operand" "i" ))
	  ( const_int 0 ))
	( pc )
	( label_ref ( match_operand 2 "" "" )))) ]
  ""
  "*
{
    operands[1] = gen_rtx 
	( CONST_INT, VOIDmode, floor_log2 ( INTVAL ( operands[1] )));

    return output_pic_dep ( \"%3set	#%1,%0,%l2\", BR, J, 3, operands );
}" )

( define_insn ""
  [ ( set
      ( pc )
      ( if_then_else 
	( eq
	  ( and:SI
	    ( match_operand:SI 0 "register_operand" "r" )
	    ( match_operand:SI 1 "pow_two_operand" "i" ))
	  ( const_int 0 ))
	( pc )
	( label_ref ( match_operand 2 "" "" )))) ]
  ""
  "*
{
    operands[1] = gen_rtx 
	( CONST_INT, VOIDmode, floor_log2 ( INTVAL ( operands[1] )));

    return output_pic_dep ( \"%3set	#%1,%0,%l2\", BR, J, 3, operands );
}" )

( define_insn ""
  [ ( set
      ( pc )
      ( if_then_else
	( ne
	  ( and:SI
	    ( match_operand:SI 0 "indirect_memory_operand" "m" )
	    ( match_operand:SI 1 "pow_two_operand" "i" ))
	  ( const_int 0 ))
	( pc )
	( label_ref ( match_operand 2 "" "" )))) ]
  ""
  "*
{
    operands[1] = gen_rtx 
	( CONST_INT, VOIDmode, floor_log2 ( INTVAL ( operands[1] )));

    return output_pic_dep ( \"%3clr	#%1,%0,%l2\", BR, J, 3, operands );
}" )
      
( define_insn ""
  [ ( set
      ( pc )
      ( if_then_else
	( ne
	  ( and:SI
	    ( match_operand:SI 0 "register_operand" "r" )
	    ( match_operand:SI 1 "pow_two_operand" "i" ))
	  ( const_int 0 ))
	( pc )
	( label_ref ( match_operand 2 "" "" )))) ]
  ""
  "*
{
    operands[1] = gen_rtx 
	( CONST_INT, VOIDmode, floor_log2 ( INTVAL ( operands[1] )));

    return output_pic_dep ( \"%3clr	#%1,%0,%l2\", BR, J, 3, operands );
}" )
      
( define_insn ""
  [ ( set
      ( pc )
      ( if_then_else 
	( eq
	  ( and:SI
	    ( match_operand:SI 0 "indirect_memory_operand" "m" )
	    ( match_operand:SI 1 "pow_two_operand" "i" ))
	  ( const_int 0 ))
	( label_ref ( match_operand 2 "" "" ))
	( pc ))) ]
  ""
  "*
{
    operands[1] = gen_rtx 
	( CONST_INT, VOIDmode, floor_log2 ( INTVAL ( operands[1] )));

    return output_pic_dep ( \"%3clr	#%1,%0,%l2\", BR, J, 3, operands );
}" )
      
( define_insn ""
  [ ( set
      ( pc )
      ( if_then_else 
	( eq
	  ( and:SI
	    ( match_operand:SI 0 "register_operand" "r" )
	    ( match_operand:SI 1 "pow_two_operand" "i" ))
	  ( const_int 0 ))
	( label_ref ( match_operand 2 "" "" ))
	( pc ))) ]
  ""
  "*
{
    operands[1] = gen_rtx 
	( CONST_INT, VOIDmode, floor_log2 ( INTVAL ( operands[1] )));

    return output_pic_dep ( \"%3clr	#%1,%0,%l2\", BR, J, 3, operands );
}" )
      
( define_insn ""
  [ ( set
      ( pc )
      ( if_then_else 
	( ne
	  ( and:SI
	    ( match_operand:SI 0 "indirect_memory_operand" "m" )
	    ( match_operand:SI 1 "pow_two_operand" "i" ))
	  ( const_int 0 ))
	( label_ref ( match_operand 2 "" "" ))
	( pc ))) ]
  ""
  "*
{
    operands[1] = gen_rtx 
	( CONST_INT, VOIDmode, floor_log2 ( INTVAL ( operands[1] )));

    return output_pic_dep ( \"%3set	#%1,%0,%l2\", BR, J, 3, operands );
}" )
      
( define_insn ""
  [ ( set
      ( pc )
      ( if_then_else 
	( ne
	  ( and:SI
	    ( match_operand:SI 0 "register_operand" "r" )
	    ( match_operand:SI 1 "pow_two_operand" "i" ))
	  ( const_int 0 ))
	( label_ref ( match_operand 2 "" "" ))
	( pc ))) ]
  ""
  "*
{
    operands[1] = gen_rtx 
	( CONST_INT, VOIDmode, floor_log2 ( INTVAL ( operands[1] )));

    return output_pic_dep ( \"%3set	#%1,%0,%l2\", BR, J, 3, operands );
}" )
      
;; this is a single bit test instruction

( define_insn ""
  [ ( set 
      ( cc0 ) 
      ( sign_extract 
	( match_operand:SI 0 "restricted_memory_operand" "m" )
	( const_int 1 ) 
	( match_operand:SI 1 "immediate_operand" "i" ))) ]
  ""
  "*
{
    /* This is a little tricky. the Motorola DSPs don't modify an CCs except 
       the C bit on a btst. This means that any following branch with a code
       like GT or LE won't get the result of the test. What we do is find the
       next point at which cc0 is relevant, and modify the jump code to be
       either NE or EQ. */

    if ( fixup_btst_cc_consumer ( insn ))
    {
	return \"btst	#%1,%0\";
    }
}" )

( define_insn ""
  [ ( set 
      ( cc0 ) 
      ( sign_extract 
	( match_operand:SI 0 "register_operand" "r" )
	( const_int 1 ) 
	( match_operand:SI 1 "immediate_operand" "i" ))) ]
  ""
  "*
{
    /* This is a little tricky. the Motorola DSPs don't modify an CCs except 
       the C bit on a btst. This means that any following branch with a code
       like GT or LE won't get the result of the test. What we do is find the
       next point at which cc0 is relevant, and modify the jump code to be
       either NE or EQ. */

    if ( fixup_btst_cc_consumer ( insn ))
    {
	return \"btst	#%1,%0\";
    }
}" )

( define_insn ""
  [ ( set
      ( cc0 )
      ( compare 
	( sign_extract 
	  ( match_operand:SI 0 "restricted_memory_operand" "m" )
	  ( const_int 1 ) 
	  ( match_operand:SI 1 "immediate_operand" "i" ))
	( match_operand:SI 2 "immediate_operand" "i" ))) ]
  ""
  "*
{
    switch ( INTVAL ( operands[2] ))
    {
    case 1:
	/* this is exactly the ! of a bit test. So issue a btst and flip
	   conditional that depends on this cc0 set. */

	flip_btst_cc_consumer ( insn );

	/* we *want* drop-thru here. */

    case 0:
	/* this is exactly the same as a bit test. */
	if ( fixup_btst_cc_consumer ( insn ))
	{
	    return \"btst	#%1,%0\";
	}
	break;

    default:
	/* this always resolves to !=. Don't issue anything, and harden
	   the branch that depends on it. */
	harden_btst_cc_consumer ( insn );
	
	return \"\";
    }
}" )

( define_insn ""
  [ ( set
      ( cc0 )
      ( compare 
	( sign_extract 
	  ( match_operand:SI 0 "register_operand" "r" )
	  ( const_int 1 ) 
	  ( match_operand:SI 1 "immediate_operand" "i" ))
	( match_operand:SI 2 "immediate_operand" "i" ))) ]
  ""
  "*
{
    switch ( INTVAL ( operands[2] ))
    {
    case 1:
	/* this is exactly the ! of a bit test. So issue a btst and flip
	   conditional that depends on this cc0 set. */

	flip_btst_cc_consumer ( insn );

	/* we *want* drop-thru here. */

    case 0:
	/* this is exactly the same as a bit test. */
	if ( fixup_btst_cc_consumer ( insn ))
	{
	    return \"btst	#%1,%0\";
	}
	break;

    default:
	/* this always resolves to !=. Don't issue anything, and harden
	   the branch that depends on it. */
	harden_btst_cc_consumer ( insn );
	
	return \"\";
    }
}" )

;; single bit test instruction

( define_insn ""
  [ ( set 
      ( cc0 )
      ( and:SI
	( match_operand:SI 0 "restricted_memory_operand" "m" )
	( match_operand:SI 1 "pow_two_operand" "i" ))) ]
  ""
  "*
{
    operands[1] = gen_rtx 
	( CONST_INT, VOIDmode, floor_log2 ( INTVAL ( operands[1] )));
    
    if ( fixup_btst_cc_consumer ( insn ))
    {
	return \"btst	#%1,%0\";
    }
}" )

( define_insn ""
  [ ( set 
      ( cc0 )
      ( and:SI
	( match_operand:SI 0 "register_operand" "r" )
	( match_operand:SI 1 "pow_two_operand" "i" ))) ]
  ""
  "*
{
    operands[1] = gen_rtx 
	( CONST_INT, VOIDmode, floor_log2 ( INTVAL ( operands[1] )));
    
    if ( fixup_btst_cc_consumer ( insn ))
    {
	return \"btst	#%1,%0\";
    }
}" )

;; these are single bit set, clear and extract instructions.

( define_expand "bitset"
  [ ( set 
      ( match_operand:SI 0 "register_or_restricted_memory_operand" "" )
      ( bitset:SI
	( match_dup 0 )
	( match_operand:SI 1 "immediate_operand" "" ))) ]
  ""
  "" )

( define_insn ""
  [ ( set ( match_operand:SI 0 "restricted_memory_operand" "+m" )
	  ( bitset:SI ( match_dup 0 )
		      ( match_operand:SI 1 "immediate_operand" "i" ))) ]
  "restricted_memref_p ( operands[0] )"
  "bset	#%1,%0" )

( define_insn ""
  [ ( set ( match_operand:SI 0 "register_operand" "=r" )
	  ( bitset:SI ( match_operand:SI 1 "register_operand" "0" )
		      ( match_operand:SI 2 "immediate_operand" "i" ))) ]
  ""
  "bset	#%2,%e0" )

( define_insn ""
  [ ( set ( match_operand:DI 0 "restricted_memory_operand" "+m" )
	  ( bitset:DI ( match_dup 0 )
		      ( match_operand:SI 1 "immediate_operand" "i" ))) ]
  "restricted_memref_p ( operands[0] )"
  "*return output_long_mem_bitop ( \"*set\", operands );" )

( define_insn ""
  [ ( set ( match_operand:DI 0 "register_operand" "=S,D" )
	  ( bitset:DI ( match_operand:DI 1 "register_operand" "0,0" )
		      ( match_operand:SI 2 "immediate_operand" "i,i" ))) ]
  ""
  "*return output_long_reg_bitop ( \"*set\", operands );" )

( define_expand "bitclr"
  [ ( set
      ( match_operand:SI 0 "register_or_restricted_memory_operand" "" )
      ( bitclr:SI 
	( match_dup 0 )
	( match_operand:SI 1 "immediate_operand" "" ))) ]
 "" "" )

( define_insn ""
  [ ( set ( match_operand:SI 0 "restricted_memory_operand" "+m" )
	  ( bitclr:SI ( match_dup 0 )
		      ( match_operand:SI 1 "immediate_operand" "i" ))) ]
  "restricted_memref_p ( operands[0] )"
  "bclr	#%1,%0" )

( define_insn ""
  [ ( set ( match_operand:SI 0 "register_operand" "=r" )
	  ( bitclr:SI ( match_operand:SI 1 "register_operand" "0" )
		      ( match_operand:SI 2 "immediate_operand" "i" ))) ]
  ""
  "bclr	#%2,%0" )

( define_insn ""
  [ ( set ( match_operand:DI 0 "restricted_memory_operand" "+m" )
	  ( bitclr:DI ( match_dup 0 )
		      ( match_operand:SI 1 "immediate_operand" "i" ))) ]
  "restricted_memref_p ( operands[0] )"
  "*return output_long_mem_bitop ( \"*clr\", operands );" )

( define_insn ""
  [ ( set ( match_operand:DI 0 "register_operand" "=S,D" )
	  ( bitclr:DI ( match_operand:DI 1 "register_operand" "0,0" )
		      ( match_operand:SI 2 "immediate_operand" "i,i" ))) ]
  ""
  "*return output_long_reg_bitop ( \"*clr\", operands );" )

( define_expand "bitchg"
  [ ( set
      ( match_operand:SI 0 "register_or_restricted_memory_operand" "" )
      ( bitchg:SI 
	( match_dup 0 )
	( match_operand:SI 1 "immediate_operand" "" ))) ]
 "" "" )

( define_insn ""
  [ ( set ( match_operand:SI 0 "restricted_memory_operand" "+m" )
	  ( bitchg:SI ( match_dup 0 )
		      ( match_operand:SI 1 "immediate_operand" "i" ))) ]
  "restricted_memref_p ( operands[0] )"
  "bchg	#%1,%0" )

( define_insn ""
  [ ( set ( match_operand:SI 0 "register_operand" "=r" )
	  ( bitchg:SI ( match_operand:SI 1 "register_operand" "0" )
		      ( match_operand:SI 2 "immediate_operand" "i" ))) ]
  ""
  "bchg	#%2,%0" )

( define_insn ""
  [ ( set ( match_operand:DI 0 "restricted_memory_operand" "+m" )
	  ( bitchg:DI ( match_dup 0 )
		      ( match_operand:SI 1 "immediate_operand" "i" ))) ]
  "restricted_memref_p ( operands[0] )"
  "*return output_long_mem_bitop ( \"*chg\", operands );" )

( define_insn ""
  [ ( set ( match_operand:DI 0 "register_operand" "=S,D" )
	  ( bitchg:DI ( match_operand:DI 1 "register_operand" "0,0" )
		      ( match_operand:SI 2 "immediate_operand" "i,i" ))) ]
  ""
  "*return output_long_reg_bitop ( \"*chg\", operands );" )

;; multi-bit insert and extract instructions.

( define_expand "insv"
  [ ( set ( zero_extract:SI 
	    ( match_operand:SI 0 "register_or_restricted_memory_operand" "" )
	    ( match_operand:SI 1 "immediate_operand" "" )
	    ( match_operand:SI 2 "immediate_operand" "" ))
	  ( match_operand:SI 3 "register_operand" "" )) ]
  "" "" )

( define_insn ""
  [ ( set ( zero_extract:SI
	    ( match_operand:SI 0 "register_or_restricted_memory_operand" "+D" )
	    ( match_operand:SI 1 "immediate_operand" "i" )
	    ( match_operand:SI 2 "immediate_operand" "i" ))
	  ( match_operand:SI 3 "register_operand" "S" )) ]
  ""
  "*
{
    int width = INTVAL ( operands[1] ), position = INTVAL ( operands[2] );

/* unfortunately this doesn't really solve the problem of not being able to generate code for these bad bitfield types --- just let it generate the wrong code...sigh
    if ( width > 16 || position + width + 16 > 40 )
        abort();
*/
    
    operands[4] = gen_rtx ( CONST_INT, VOIDmode,
			   ( width << 8 ) | ( position + 16 ));

    return \"insert	#%4,%3,%0\";
}" 
  "CCS_SET_CORRECTLY" )

;; we need to use the operand constraint register_or_restricted_memory_operand
;; even though the extract instructions only really support register_operands.
;; this is so that the btst instruction (and bsset, etc) can (almost) use
;; their full range of possible operands.

( define_expand "extv"
  [ ( set ( match_operand:SI 0 "register_operand" "" )
	  ( sign_extract:SI
	    ( match_operand:SI 1 "register_or_restricted_memory_operand" "" )
	    ( match_operand:SI 2 "immediate_operand" "" )
	    ( match_operand:SI 3 "immediate_operand" "" ))) ]
  "" "" )

( define_insn ""
  [ ( set ( match_operand:SI 0 "register_operand" "=D" )
	  ( sign_extract:SI
	    ( match_operand:SI 1 "register_or_restricted_memory_operand" "D" )
	    ( match_operand:SI 2 "immediate_operand" "i" )
	    ( match_operand:SI 3 "immediate_operand" "i" ))) ]
  ""
  "*
{
    int width = INTVAL ( operands[2] ), position = INTVAL ( operands[3] );
    
/* unfortunately this doesn't really solve the problem of not being able to generate code for these bad bitfield types --- just let it generate the wrong code...sigh
    if ( position + width + 16 > 40 )
        abort();
*/
    
    operands[4] = gen_rtx ( CONST_INT, VOIDmode,
			   ( width << 8 ) | ( position + 16 ));

    return \"extract	#%4,%1,%0\;asl	#16,%0,%0\";
}"
  "CCS_SET_CORRECTLY" )

( define_expand "extzv"
  [ ( set ( match_operand:SI 0 "register_operand" "" )
	  ( zero_extract:SI 
	    ( match_operand:SI 1 "register_or_restricted_memory_operand" "" )
	    ( match_operand:SI 2 "immediate_operand" "" )
	    ( match_operand:SI 3 "immediate_operand" "" ))) ]
  ""
  "" )

( define_insn ""
  [ ( set ( match_operand:SI 0 "register_operand" "=D" )
	  ( zero_extract:SI
	    ( match_operand:SI 1 "register_or_restricted_memory_operand" "D" )
	    ( match_operand:SI 2 "immediate_operand" "i" )
	    ( match_operand:SI 3 "immediate_operand" "i" ))) ]
  ""
  "*
{
    int width = INTVAL ( operands[2] ), position = INTVAL ( operands[3] );
    
/* unfortunately this doesn't really solve the problem of not being able to generate code for these bad bitfield types --- just let it generate the wrong code...sigh
    if ( position + width + 16 > 40 )
        abort();
*/
    
    operands[4] = gen_rtx ( CONST_INT, VOIDmode,
			   ( width << 8 ) | ( position + 16 ));

    return \"extractu	#%4,%1,%0\;asl	#16,%0,%0\";
}" "CCS_SET_CORRECTLY" )

;;  ...........................................................................
;;          SUBROUTINE CALLS

( define_expand "call"
  [ ( call ( match_operand:SI 0 "register_or_restricted_memory_operand" "" )
	   ( match_operand:SI 1 "immediate_operand" "" )) ]
  "" "" )

( define_insn ""
  [ ( call ( match_operand:SI 0 "restricted_memory_operand" "m" )
	   ( match_operand:SI 1 "immediate_operand" "i" )) ]
  ""
  "*
{
    switch ( INTVAL ( operands[1] ))
    {
    case 0:
	return output_pic_dep ( \"%2sr	%f0\", B, J, 2, operands );
	
    case 1:
	return output_pic_dep ( \"%2sr	%f0\;\"
				 \"move	(r6)-\", B, J, 2, operands );
	
    case 2:
	return output_pic_dep ( \"%2sr	%f0\;\"
				 \"move	(r6)-\;\"
				 \"move	(r6)-\", B, J, 2, operands );
	
    default:
	return output_pic_dep ( \"%2sr	%f0\;\"
				 \"move	#%1,n6\;\"
				 \"move	(r6)-n6\", B, J, 2, operands );
    }
}" "BSR_LAST_OP" )

( define_insn ""
  [ ( call ( match_operand:SI 0 "register_operand" "A" )
	   ( match_operand:SI 1 "immediate_operand" "i" )) ]
  ""
  "*
{
    switch ( INTVAL ( operands[1] ))
    {
    case 0:
	return output_pic_dep ( \"%2sr	%f0\", B, J, 2, operands );
	
    case 1:
	return output_pic_dep ( \"%2sr	%f0\;\"
				 \"move	(r6)-\", B, J, 2, operands );
	
    case 2:
	return output_pic_dep ( \"%2sr	%f0\;\"
				 \"move	(r6)-\;\"
				 \"move	(r6)-\", B, J, 2, operands );
	
    default:
	return output_pic_dep ( \"%2sr	%f0\;\"
				 \"move	#%1,n6\;\"
				 \"move	(r6)-n6\", B, J, 2, operands );
    }
}" "BSR_LAST_OP" )

( define_expand "call_value"
  [ ( set ( match_operand 0 "" "" )
	  ( call
	    ( match_operand:SI 1 "pic_sensitive_call_operand" "" )
	    ( match_operand:SI 2 "immediate_operand" "" ))) ]
  "" "" )

( define_insn ""
  [ ( set ( match_operand 0 "" "" )
	  ( call ( match_operand:SI 1 "restricted_memory_operand" "m" )
		 ( match_operand:SI 2 "immediate_operand" "i" ))) ]
  ""
  "*
{
    switch ( INTVAL ( operands[2] ))
    {
    case 0:
	return \"jsr	%f1\";
	
    case 1:
	return \"jsr	%f1\;\"
	       \"move	(r6)-\";
	
    case 2:
	return \"jsr	%f1\;\"
	       \"move	(r6)-\;\"
	       \"move	(r6)-\";
	
    default:
	return \"jsr	%f1\;\"
	       \"move	#%2,n6\;\"
	       \"move	(r6)-n6\";
    }
}" "CCS_SET_CORRECTLY | CALL_VALUE" )

( define_insn ""
  [ ( set ( match_operand 0 "" "" )
	  ( call ( match_operand:SI 1 "register_operand" "A" )
		 ( match_operand:SI 2 "immediate_operand" "i" ))) ]
  "! TARGET_PIC"
  "*
{
    switch ( INTVAL ( operands[2] ))
    {
    case 0:
	return output_pic_dep ( \"%3sr	%f1\", B, J, 3, operands );
	
    case 1:
	return output_pic_dep ( \"%3sr	%f1\;\"
				 \"move	(r6)-\", B, J, 3, operands );
	
    case 2:
	return output_pic_dep ( \"%3sr	%f1\;\"
				 \"move	(r6)-\;\"
				 \"move	(r6)-\", B, J, 3, operands );
	
    default:
	return output_pic_dep ( \"%3sr	%f1\;\"
				 \"move	#%2,n6\;\"
				 \"move	(r6)-n6\", B, J, 3, operands );
    }
}" "CCS_SET_CORRECTLY | CALL_VALUE | BSR_LAST_OP" )

;;  ...........................................................................
;;          NOP

( define_insn "nop"
  [ ( const_int 0 ) ]
  ""
  "*
{
    rtx peek = PREV_INSN ( insn );
    
    while (( peek ) && 
	   (( NOTE == GET_CODE ( peek )) ||
	    (( JUMP_INSN == GET_CODE ( peek )) &&
	     ( PARALLEL == GET_CODE ( PATTERN ( peek ))))))
    {
	peek = PREV_INSN ( peek );
    }
    if (( ! peek ) || ( CODE_LABEL != GET_CODE ( peek )) ||
	( ! LABEL_NUSES ( peek )))
    {
	return \"\";
    }
    
    peek = NEXT_INSN ( insn );
    while (( peek ) && 
	   (( NOTE == GET_CODE ( peek )) ||
	    (( JUMP_INSN == GET_CODE ( peek )) &&
	     ( PARALLEL == GET_CODE ( PATTERN ( peek ))))))
    {
	peek = NEXT_INSN ( peek );
    }
    if (( ! peek ) || 
	( ! LABEL_NUSES ( peek )) ||
	(( CODE_LABEL != GET_CODE ( peek )) && 
	 ( const0_rtx != PATTERN ( peek ))))
    {
	return \"\";
    }

    return \"nop\";
}" "CCS_NOT_AFFECTED" )

;; This insn is needed because jump.c doesn't realize that this is really
;; a nop.

( define_insn "" [ ( set ( pc ) ( pc )) ] "" "" "CCS_NOT_AFFECTED" )

( define_insn "probe" 
  [ ( parallel [ ( const_int 0 ) ] ) ]
  ""
  "*
{
    if ( TARGET_STACK_CHECK )
    {
	return output_pic_dep ( \"%0sr	F__stack_check\", B, J, 0, operands );
    }
    else
    {
	return \"\";
    }
}" )


;;  ...........................................................................
;;          PEEPHOLE OPTIMIZATIONS

;; this sequence can be introduced by the do loop generation code. a 
;; reasonable data flow analysis and optimization phase will (in the future)
;; clean it up.

( define_peephole
  [ ( set ( match_operand:SI 0 "register_operand" "=D" )
	  ( minus:SI ( match_operand:SI 1 "register_operand" "0" )
		     ( match_operand:SI 2 "register_operand" "SD" )))
    ( set ( match_dup 0 )
	  ( plus:SI ( match_dup 1 )
		    ( match_dup 2 ))) ]
  "( ! rtx_equal_p (operands[0], operands[2] ))" "" )

;; ...........................................................................
;; ifcc.u peepholers. these handle adding ifccs where they find a conditional
;; jump around an insn that produces a single alu opcode. currently, addl and
;; addr shapes aren't implemented.

( define_peephole
  [ ( set ( pc ) 
	  ( if_then_else 
	    ( match_operator 4 "cond_operator" [ ( cc0 ) ( const_int 0 ) ] )
	    ( pc ) ( label_ref ( match_operand 5 "" "" ))))
    ( set ( match_operand:SI 0 "register_operand" "" )
	  ( match_operator 3 "alu_two_operand_operator" 
			   [ ( match_operand 1 "register_operand" "" ) 
			     ( match_operand 2 "register_operand" "" ) ] )) ]
  "ifcc_combo_follows_p ( insn, operands[5] )"
  "*return output_ifcc ( insn, operands, 4, FALSE );" )

( define_peephole
  [ ( set ( pc ) 
	  ( if_then_else 
	    ( match_operator 4 "cond_operator" [ ( cc0 ) ( const_int 0 ) ] )
	    ( label_ref ( match_operand 5 "" "" )) ( pc )))
    ( set ( match_operand:SI 0 "register_operand" "" )
	  ( match_operator 3 "alu_two_operand_operator" 
			   [ ( match_operand 1 "register_operand" "" ) 
			     ( match_operand 2 "register_operand" "" ) ] )) ]
  "ifcc_combo_follows_p ( insn, operands[5] )"
  "*return output_ifcc ( insn, operands, 4, TRUE );" )

( define_peephole
  [ ( set ( pc ) 
	  ( if_then_else 
	    ( match_operator 3 "cond_operator" [ ( cc0 ) ( const_int 0 ) ] )
	    ( pc ) ( label_ref ( match_operand 4 "" "" ))))
    ( set ( match_operand:SI 0 "register_operand" "" )
	  ( match_operator 2 "alu_one_operand_operator" 
			   [ ( match_operand 1 "register_operand" "" ) ] )) ]
  "ifcc_combo_follows_p ( insn, operands[4] )"
  "*return output_ifcc ( insn, operands, 3, FALSE );" )

( define_peephole
  [ ( set ( pc ) 
	  ( if_then_else 
	    ( match_operator 3 "cond_operator" [ ( cc0 ) ( const_int 0 ) ] )
	    ( label_ref ( match_operand 4 "" "" )) ( pc )))
    ( set ( match_operand:SI 0 "register_operand" "" )
	  ( match_operator 2 "alu_one_operand_operator" 
			   [ ( match_operand 1 "register_operand" "" ) ] )) ]
  "ifcc_combo_follows_p ( insn, operands[4] )"
  "*return output_ifcc ( insn, operands, 3, TRUE );" )

;; ...........................................................................
;; max peepholers. these handle exploiting the maximum value instruction.

( define_peephole 
  [ ( set ( cc0 ) ( compare ( match_operand:SI 0 "register_operand" "" )
			    ( match_operand:SI 1 "register_operand" "" )))
    ( set ( pc )
	  ( if_then_else
	    ( le ( cc0 ) ( const_int 0 ))
	    ( pc ) ( label_ref ( match_operand 2 "" "" ))))
    ( set ( match_dup 0 ) ( match_dup 1 )) ]
  "max_combo_follows_p ( insn, operands[2] )"
  "*return output_max ( insn );" )

( define_peephole 
  [ ( set ( cc0 ) ( compare ( match_operand:SI 0 "register_operand" "" )
			    ( match_operand:SI 1 "register_operand" "" )))
    ( set ( pc )
	  ( if_then_else
	    ( gt ( cc0 ) ( const_int 0 ))
	    ( label_ref ( match_operand 2 "" "" )) ( pc )))
    ( set ( match_dup 0 ) ( match_dup 1 )) ]
  "max_combo_follows_p ( insn, operands[2] )"
  "*return output_max ( insn );" )

;; ...........................................................................
;; tcc peepholers. these handle exploiting tcc where a conditional 
;; branch jumps around a tfr. 

( define_peephole 
  [ ( set ( pc )
	  ( if_then_else
	    ( match_operator 2 "cond_operator" [ ( cc0 ) ( const_int 0 ) ] )
	    ( pc ) ( label_ref ( match_operand 3 "" "" ))))
    ( set ( match_operand:SI 0 "register_operand" "" )
	  ( match_operand:SI 1 "register_operand" "" )) ]
  "tcc_combo_follows_p ( insn, operands[3] )"
  "*return output_tcc ( insn, operands, FALSE );" )

( define_peephole
  [ ( set ( pc )
	  ( if_then_else
	    ( match_operator 2 "cond_operator" [ ( cc0 ) ( const_int 0 ) ] )
	    ( label_ref ( match_operand 3 "" "" )) ( pc )))
    ( set ( match_operand:SI 0 "register_operand" "" )
	  ( match_operand:SI 1 "register_operand" "" )) ]
  "tcc_combo_follows_p ( insn, operands[3] )"
  "*return output_tcc ( insn, operands, TRUE );" )

;; ...........................................................................
;; jscc/bscc peepholers. these take advantage of some cases where 
;; conditional branches jump around function calls.

( define_peephole
  [ ( set ( pc )
	  ( if_then_else
	    ( match_operator 1 "cond_operator" [ ( cc0 ) ( const_int 0 ) ] )
	    ( pc ) ( label_ref ( match_operand 2 "" "" ))))
    ( call ( match_operand:SI 0 "register_or_restricted_memory_operand" "" )
	   ( const_int 0 )) ]
  "jscc_combo_follows_p ( insn, operands[2] )"
  "*return output_jscc ( insn, operands, FALSE );" )

( define_peephole
  [ ( set ( pc )
	  ( if_then_else
	    ( match_operator 1 "cond_operator" [ ( cc0 ) ( const_int 0 ) ] )
	    ( label_ref ( match_operand 2 "" "" )) ( pc )))
    ( call ( match_operand:SI 0 "register_or_restricted_memory_operand" "" )
	   ( const_int 0 )) ]
  "jscc_combo_follows_p ( insn, operands[2] )"
  "*return output_jscc ( insn, operands, TRUE );" )

( define_peephole
  [ ( set ( pc )
	  ( if_then_else
	    ( match_operator 1 "cond_operator" [ ( cc0 ) ( const_int 0 ) ] )
	    ( pc ) ( label_ref ( match_operand 2 "" "" ))))
    ( set ( match_operand 3 "" "" )
	  ( call 
	    ( match_operand:SI 0 "register_or_restricted_memory_operand" "" )
	    ( const_int 0 ))) ]
  "jscc_combo_follows_p ( insn, operands[2] )"
  "*return output_jscc ( insn, operands, FALSE );" )

( define_peephole
  [ ( set ( pc )
	  ( if_then_else
	    ( match_operator 1 "cond_operator" [ ( cc0 ) ( const_int 0 ) ] )
	    ( label_ref ( match_operand 2 "" "" )) ( pc )))
    ( set ( match_operand 3 "" "" )
	  ( call
	    ( match_operand:SI 0 "register_or_restricted_memory_operand" "" )
	    ( const_int 0 ))) ]
  "jscc_combo_follows_p ( insn, operands[2] )"
  "*return output_jscc ( insn, operands, TRUE );" )

;; ...........................................................................
;; js(clr/set)/bs(clr/set) peepholers. these take advantage of some cases
;; where conditional branches jump around function calls.

( define_peephole
  [ ( set 
      ( pc )
      ( if_then_else
	( ne
	  ( sign_extract
	    ( match_operand:SI 1 "register_or_indirect_memory_operand" "" )
	    ( const_int 1 )
	    ( match_operand:SI 2 "immediate_operand" "" ))
	  ( const_int 0 ))
	( pc ) ( label_ref ( match_operand 3 "" "" ))))
    ( call ( match_operand:SI 0 "direct_memory_operand" "" ) ( const_int 0 )) ]
  "jscc_combo_follows_p ( insn, operands[3] )"
  "*return output_jsbit ( insn, operands, TRUE );" )

( define_peephole
  [ ( set 
      ( pc )
      ( if_then_else
	( eq
	  ( sign_extract
	    ( match_operand:SI 1 "register_or_indirect_memory_operand" "" )
	    ( const_int 1 )
	    ( match_operand:SI 2 "immediate_operand" "" ))
	  ( const_int 0 ))
	( pc ) ( label_ref ( match_operand 3 "" "" ))))
    ( call ( match_operand:SI 0 "direct_memory_operand" "" ) ( const_int 0 )) ]
  "jscc_combo_follows_p ( insn, operands[3] )"
  "*return output_jsbit ( insn, operands, FALSE );" )

( define_peephole
  [ ( set 
      ( pc )
      ( if_then_else
	( ne
	  ( sign_extract
	    ( match_operand:SI 1 "register_or_indirect_memory_operand" "" )
	    ( const_int 1 )
	    ( match_operand:SI 2 "immediate_operand" "" ))
	  ( const_int 0 ))
	( label_ref ( match_operand 3 "" "" )) ( pc )))
    ( call ( match_operand:SI 0 "direct_memory_operand" "" ) ( const_int 0 )) ]
  "jscc_combo_follows_p ( insn, operands[3] )"
  "*return output_jsbit ( insn, operands, FALSE );" )

( define_peephole
  [ ( set 
      ( pc )
      ( if_then_else
	( eq
	  ( sign_extract
	    ( match_operand:SI 1 "register_or_indirect_memory_operand" "" )
	    ( const_int 1 )
	    ( match_operand:SI 2 "immediate_operand" "" ))
	  ( const_int 0 ))
	( label_ref ( match_operand 3 "" "" )) ( pc )))
    ( call ( match_operand:SI 0 "direct_memory_operand" "" ) ( const_int 0 )) ]
  "jscc_combo_follows_p ( insn, operands[3] )"
  "*return output_jsbit ( insn, operands, TRUE );" )

;; ...........................................................................
;; bclr/bset/bchg peepholers convert series of bit-ops on accumulators
;; back into logical instructions.

( define_peephole
  [ ( set ( match_operand:SI 0 "register_operand" "" )
	  ( bitclr:SI ( match_dup 0 )
		      ( match_operand:SI 1 "immediate_operand" "" )))
    ( set ( match_dup 0 )
	  ( bitclr:SI ( match_dup 0 )
		      ( match_operand:SI 2 "immediate_operand" "" )))
    ( set ( match_dup 0 )
	  ( bitclr:SI ( match_dup 0 )
		      ( match_operand:SI 3 "immediate_operand" "" )))
    ( set ( match_dup 0 )
	  ( bitclr:SI ( match_dup 0 )
		      ( match_operand:SI 4 "immediate_operand" "" ))) ]
  "DSP_B_REGNUM >= REGNO ( operands[0] )"
  "*return output_repeated_bitop ( \"*and\", operands, 4 );" )

( define_peephole
  [ ( set ( match_operand:SI 0 "register_operand" "" )
	  ( bitclr:SI ( match_dup 0 )
		      ( match_operand:SI 1 "immediate_operand" "" )))
    ( set ( match_dup 0 )
	  ( bitclr:SI ( match_dup 0 )
		      ( match_operand:SI 2 "immediate_operand" "" )))
    ( set ( match_dup 0 )
	  ( bitclr:SI ( match_dup 0 )
		      ( match_operand:SI 3 "immediate_operand" "" ))) ]
  "DSP_B_REGNUM >= REGNO ( operands[0] )"
  "*return output_repeated_bitop ( \"*and\", operands, 3 );" )

( define_peephole
  [ ( set ( match_operand:SI 0 "register_operand" "" )
	  ( bitset:SI ( match_dup 0 )
		      ( match_operand:SI 1 "immediate_operand" "" )))
    ( set ( match_dup 0 )
	  ( bitset:SI ( match_dup 0 )
		      ( match_operand:SI 2 "immediate_operand" "" )))
    ( set ( match_dup 0 )
	  ( bitset:SI ( match_dup 0 )
		      ( match_operand:SI 3 "immediate_operand" "" )))
    ( set ( match_dup 0 )
	  ( bitset:SI ( match_dup 0 )
		      ( match_operand:SI 4 "immediate_operand" "" ))) ]
  "DSP_B_REGNUM >= REGNO ( operands[0] )"
  "*return output_repeated_bitop ( \"*or\", operands, 4 );" )

( define_peephole
  [ ( set ( match_operand:SI 0 "register_operand" "" )
	  ( bitset:SI ( match_dup 0 )
		      ( match_operand:SI 1 "immediate_operand" "" )))
    ( set ( match_dup 0 )
	  ( bitset:SI ( match_dup 0 )
		      ( match_operand:SI 2 "immediate_operand" "" )))
    ( set ( match_dup 0 )
	  ( bitset:SI ( match_dup 0 )
		      ( match_operand:SI 3 "immediate_operand" "" ))) ]
  "DSP_B_REGNUM >= REGNO ( operands[0] )"
  "*return output_repeated_bitop ( \"*or\", operands, 3 );" )

( define_peephole
  [ ( set ( match_operand:SI 0 "register_operand" "" )
	  ( bitchg:SI ( match_dup 0 )
		      ( match_operand:SI 1 "immediate_operand" "" )))
    ( set ( match_dup 0 )
	  ( bitchg:SI ( match_dup 0 )
		      ( match_operand:SI 2 "immediate_operand" "" )))
    ( set ( match_dup 0 )
	  ( bitchg:SI ( match_dup 0 )
		      ( match_operand:SI 3 "immediate_operand" "" )))
    ( set ( match_dup 0 )
	  ( bitchg:SI ( match_dup 0 )
		      ( match_operand:SI 4 "immediate_operand" "" ))) ]
  "DSP_B_REGNUM >= REGNO ( operands[0] )"
  "*return output_repeated_bitop ( \"*eor\", operands, 4 );" )

( define_peephole
  [ ( set ( match_operand:SI 0 "register_operand" "" )
	  ( bitchg:SI ( match_dup 0 )
		      ( match_operand:SI 1 "immediate_operand" "" )))
    ( set ( match_dup 0 )
	  ( bitchg:SI ( match_dup 0 )
		      ( match_operand:SI 2 "immediate_operand" "" )))
    ( set ( match_dup 0 )
	  ( bitchg:SI ( match_dup 0 )
		      ( match_operand:SI 3 "immediate_operand" "" ))) ]
  "DSP_B_REGNUM >= REGNO ( operands[0] )"
  "*return output_repeated_bitop ( \"*eor\", operands, 3 );" )

;;- Local variables:
;;- mode:emacs-lisp
;;- comment-start: ";;- "
;;- eval: ( set-syntax-table ( copy-sequence ( syntax-table ) ) )
;;- eval: ( modify-syntax-entry ?[ "(]" )
;;- eval: ( modify-syntax-entry ?] ")[" )
;;- eval: ( modify-syntax-entry ?{ "(}" )
;;- eval: ( modify-syntax-entry ?} "){" )
;;- End:

