;; GCC machine description for Intel 80386.
;; Copyright (C) 1988 Free Software Foundation, Inc.
;; Mostly by William Schelter.

;; This file is part of GNU CC.

;; GNU CC is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY.  No author or distributor
;; accepts responsibility to anyone for the consequences of using it
;; or for whether it serves any particular purpose or works at all,
;; unless he says so in writing.  Refer to the GNU CC General Public
;; License for full details.

;; Everyone is granted permission to copy, modify and redistribute
;; GNU CC, but only under the conditions described in the
;; GNU CC General Public License.   A copy of this license is
;; supposed to have been given to you along with GNU CC so you
;; can know your rights and responsibilities.  It should be in a
;; file named COPYING.  Among other things, the copyright notice
;; and this notice must be preserved on all copies.


;;- instruction definitions

;;- @@The original PO technology requires these to be ordered by speed,
;;- @@    so that assigner will pick the fastest.

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

;;- When naming insn's (operand 0 of define_insn) be careful about using
;;- names from other targets machine descriptions.

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

;;- Operand classes for the register allocator:
;;- 'a' for eax
;;- 'd' for edx
;;- 'c' for ecx
;;- 'b' for ebx
;;- 'S' for SIREGS (esi)
;;- 'D' for DIREGS (edi)
;;- 'f' for anything in FLOAT_REGS
;;- 'r' any (non-floating-point) register

;; the special asm out single letter directives following a '%' are:
;; 'z' mov%z1 would be movl, movw, or movb depending on the mode of operands[1]
;; 's' output a '*'
;; 'w' If the operand is a REG, it uses the mode size to determine the
;;      printing of the reg



(define_insn ""
  [(set (match_operand:DI 0 "push_operand" "=<")
	(match_operand:DI 1 "general_operand" "r"))]
  ""
  "*
{
  return output_move_double (operands);
}")

(define_insn "tstsi"
  [(set (cc0)
	(match_operand:SI 0 "general_operand" "rm"))]
  ""
  "*
{
  operands[1] = const0_rtx;
  return AS2 (cmp%L,%1,%0);
}")

(define_insn "tsthi"
  [(set (cc0)
	(match_operand:HI 0 "general_operand" "rm"))]
  ""
  "*
{
  operands[1] = const0_rtx;
  return AS2 (cmp%W,%1,%0);
}")

(define_insn "tstqi"
  [(set (cc0)
	(match_operand:QI 0 "general_operand" "rm"))]
  ""
  "*
{
  operands[1] = const0_rtx;
  return AS2 (cmp%B,%1,%0);
}")

(define_insn "tstsf"
  [(set (cc0)
	(match_operand:SF 0 "general_operand" "rm,f"))
   (clobber (reg:HI 0))]
  "TARGET_80387"
  "*
{
  rtx xops[1];
  if (!FP_REG_P (operands[0]))
    fp_push_sf (operands[0]);
/*  fp_pop_level--; */
  xops[0] = FP_TOP;
  cc_status.flags |= CC_IN_80387;
  output_asm_insn (\"ftst\;fstp %0(0)\;fstsw %Rax\;sahf\", xops);
  RETCOM (testsf);
}")

(define_insn "tstdf"
  [(set (cc0)
	(match_operand:DF 0 "general_operand" "rm,f"))
   (clobber (reg:HI 0))
   ]
  "TARGET_80387"
  "*
{
  rtx xops[1];
  if (!FP_REG_P (operands[0]))
    fp_push_df (operands[0]);
/*  fp_pop_level--; */
  xops[0] = FP_TOP;
  cc_status.flags |= CC_IN_80387;
  output_asm_insn (\"ftst\;fstp %0(0)\;fstsw %Rax\;sahf\", xops);
  RETCOM (testdf);
}")

;;- compare instructions

(define_insn "cmpsi"
  [(set (cc0)
	(minus (match_operand:SI 0 "general_operand" "mr,ri")
	       (match_operand:SI 1 "general_operand" "ri,mr")))]
  ""
  "*
{
  if (REG_P (operands[1])
      || (!REG_P (operands[0]) && GET_CODE (operands[0]) != MEM))
    {
      cc_status.flags |= CC_REVERSED;
      return AS2 (cmp%L,%0,%1);
    }
  return AS2 (cmp%L,%1,%0);
}")

(define_insn "cmphi"
  [(set (cc0)
	(minus (match_operand:HI 0 "general_operand" "mr,ri")
	       (match_operand:HI 1 "general_operand" "ri,mr")))]
  ""
  "*
{
  if (REG_P (operands[1])
      || (!REG_P (operands[0]) && GET_CODE (operands[0]) != MEM))
    {
      cc_status.flags |= CC_REVERSED;
      return AS2 (cmp%W,%0,%1);
    }
  return AS2 (cmp%W,%1,%0);
}")

(define_insn "cmpqi"
  [(set (cc0)
	(minus (match_operand:QI 0 "general_operand" "qn,mq")
	       (match_operand:QI 1 "general_operand" "qm,nq")))]
  ""
  "*
{
  if (REG_P (operands[1])
      || (!REG_P (operands[0]) && GET_CODE (operands[0]) != MEM))
    {
      cc_status.flags |= CC_REVERSED;
      return AS2 (cmp%B,%0,%1);
    }
  return AS2 (cmp%B,%1,%0);
}")

(define_insn "cmpdf"
  [(set (cc0)
	(minus (match_operand:DF 0 "general_operand" "m,f*r,m,f,r,!*r")
	       (match_operand:DF 1 "general_operand" "m,m,f*r,r,f,*r")))
      (clobber (reg:SI 0))]
  "TARGET_80387"
  "*
{
  if (FP_REG_P (operands[0]))
    {
      rtx tem = operands[1];
      operands[1] = operands[0];
      operands[0] = tem;
      cc_status.flags |= CC_REVERSED;
    }
  if (! FP_REG_P (operands[1]))
    output_movdf (FP_TOP, operands[1]);
  output_movdf (FP_TOP, operands[0]);
/*  fp_pop_level--;
  fp_pop_level--; */
  cc_status.flags |= CC_IN_80387;
  return \"fcompp\;fstsw %Rax\;sahf\";
}")

(define_insn "cmpsf"
  [(set (cc0)
	(minus (match_operand:SF 0 "general_operand" "m,f*r,m,f,r,!*r")
	       (match_operand:SF 1 "general_operand" "m,m,f*r,r,f,*r")))
   (clobber (reg:SI 0))]
  "TARGET_80387"
  "*
{
  if (FP_REG_P (operands[0]))
    {
      rtx tem = operands[1];
      operands[1] = operands[0];
      operands[0] = tem;
      cc_status.flags |= CC_REVERSED;
    }
  if (! FP_REG_P (operands[1]))
    output_movsf (FP_TOP, operands[1]);
  output_movsf (FP_TOP, operands[0]);
/*  fp_pop_level--;
  fp_pop_level--; */
  cc_status.flags |= CC_IN_80387;
  return \"fcompp\;fstsw %Rax\;sahf\";
}")

;; logical compare
(define_insn ""
  [(set (cc0)
	(and:SI (match_operand:SI 0 "general_operand" "rm,ri")
		(match_operand:SI 1 "general_operand" "ri,rm")))]
  ""
  "*
{
  if (GET_CODE (operands[1]) == CONST_INT || GET_CODE (operands[0]) == MEM)
    return AS2 (test%L,%1,%0);
  return AS2 (test%L,%0,%1);
}")

(define_insn ""
  [(set (cc0)
	(and:HI (match_operand:HI 0 "general_operand" "rm,ri")
		(match_operand:HI 1 "general_operand" "ri,rm")))]
  ""
  "*
{
  if (GET_CODE (operands[1]) == CONST_INT || GET_CODE (operands[0]) == MEM)
    return AS2 (test%W,%1,%0);
  return AS2 (test%W,%0,%1);
}")

(define_insn ""
  [(set (cc0)
	(and:QI (match_operand:QI 0 "general_operand" "qm,qi")
		(match_operand:QI 1 "general_operand" "qi,qm")))]
  ""
  "*
{
  if (GET_CODE (operands[1]) == CONST_INT || GET_CODE (operands[0]) == MEM)
    return AS2 (test%B,%1,%0);
  return AS2 (test%B,%0,%1);
}")

;;- move instructions

(define_insn ""
  [(set (match_operand:SI 0 "push_operand" "=<")
	(match_operand:SI 1 "general_operand" "g"))]
  ""
  "push%L %1")

;; General case of fullword move.
(define_insn "movsi"
  [(set (match_operand:SI 0 "general_operand" "=g,r")
	(match_operand:SI 1 "general_operand" "ri,m"))]
  ""
  "*
{
  rtx link;
  if (operands[1] == const0_rtx && REG_P (operands[0]))
    return \"xor%L %0,%0\";
  if (operands[1] == const1_rtx
      && (link = find_reg_note (insn, REG_WAS_0, 0))
      /* Make sure the insn that stored the 0 is still present.  */
      && ! XEXP (link, 0)->volatil
      && GET_CODE (XEXP (link, 0)) != NOTE
      /* Make sure cross jumping didn't happen here.  */
      && no_labels_between_p (XEXP (link, 0), insn))
    /* Fastest way to change a 0 to a 1.  */
    return \"inc%L %0\";
  return \"mov%L %1,%0\";
}")

(define_insn ""
  [(set (match_operand:HI 0 "push_operand" "=<")
	(match_operand:HI 1 "general_operand" "g"))]
  ""
  "push%W %1")

(define_insn "movhi"
  [(set (match_operand:HI 0 "general_operand" "=g,r")
	(match_operand:HI 1 "general_operand" "ri,m"))]
  ""
  "*
{
  rtx link;
  if (operands[1] == const0_rtx && REG_P (operands[0]))
    return \"xor%W %0,%0\";
  if (operands[1] == const1_rtx
      && (link = find_reg_note (insn, REG_WAS_0, 0))
      /* Make sure the insn that stored the 0 is still present.  */
      && ! XEXP (link, 0)->volatil
      && GET_CODE (XEXP (link, 0)) != NOTE
      /* Make sure cross jumping didn't happen here.  */
      && no_labels_between_p (XEXP (link, 0), insn))
    /* Fastest way to change a 0 to a 1.  */
    return \"inc%W %0\";
  return \"mov%W %1,%0\";
}")

(define_insn "movqi"
  [(set (match_operand:QI 0 "general_operand" "=q,*r,m")
	(match_operand:QI 1 "general_operand" "*g,q,qi"))]
  ""
  "*
{
  rtx link;
  if (operands[1] == const0_rtx && REG_P (operands[0]))
    return \"xor%B %0,%0\";
  if (operands[1] == const1_rtx
      && (link = find_reg_note (insn, REG_WAS_0, 0))
      /* Make sure the insn that stored the 0 is still present.  */
      && ! XEXP (link, 0)->volatil
      && GET_CODE (XEXP (link, 0)) != NOTE
      /* Make sure cross jumping didn't happen here.  */
      && no_labels_between_p (XEXP (link, 0), insn))
    /* Fastest way to change a 0 to a 1.  */
    return \"inc%B %0\";
  /* If mov%B isn't allowed for one of these regs, use mov%W.  */
  if (NON_QI_REG_P (operands[0]) || NON_QI_REG_P (operands[1]))
    return (AS2 (mov%W,%w1,%w0));
  return (AS2 (mov%B,%1,%0));
}")

; I suspect nothing can ever match this ???
;(define_insn ""
;  [(set (match_operand:SF 0 "general_operand" "rm")
;	(match_operand:SF 1 "general_operand" "f"))
;   (clobber (reg:SF 8))]
;  ""
;  "*
;{
;  output_asm_insn ("???", operands);
;  fpop_sf (operands[0]);
;  RETCOM (movsf_clobber);
;}")

(define_insn ""
  [(set (match_operand:SF 0 "push_operand" "=<,<")
	(match_operand:SF 1 "general_operand" "gF,f"))]
  ""
  "*
{
  if (FP_REG_P (operands[1]))
    {
      rtx xops[3];
      xops[0] = AT_SP (SFmode);
      xops[1] = gen_rtx (CONST_INT, VOIDmode, 4);
      xops[2] = stack_pointer_rtx;
/*      fp_pop_level--; */
      output_asm_insn (AS2 (sub%L,%1,%2), xops);
      output_asm_insn (\"fstp%S %0\", xops);
      RET;
    }
  return \"push%L %1\";
}")

(define_insn "movsf"
  [(set (match_operand:SF 0 "general_operand" "=mf,rmf,!rm")
	(match_operand:SF 1 "general_operand" "m,rf,F"))]
  ""
  "*
{
  if (FP_REG_P (operands[1])
      && !FP_REG_P (operands[0])
      && !top_dead_p (insn))
    fp_store_sf (operands[0]);
  else
    output_movsf (operands[0], operands[1]);
  RETCOM (movsf);
}")

;;should change to handle the memory operands[1] without doing df push..
(define_insn ""
  [(set (match_operand:DF 0 "push_operand" "=<,<")
	(match_operand:DF 1 "general_operand" "gF,f"))]
  ""
  "*
{
  if (FP_REG_P (operands[1]))
    {
      rtx xops[3];
      xops[0] = AT_SP (DFmode);
      xops[1] = gen_rtx (CONST_INT, VOIDmode, 8);
      xops[2] = stack_pointer_rtx;
/*      fp_pop_level--; */
      output_asm_insn (AS2 (sub%L,%1,%2), xops);
      output_asm_insn (\"fstp%Q %0\", xops);
      RETCOM (pushdf);
    }
  else
    return output_move_double (operands);
}")

(define_insn "movdf"
  [(set (match_operand:DF 0 "general_operand" "=&rmf,rmf,!rm")
	(match_operand:DF 1 "general_operand" "m,fr,F"))]
  ""
  "*
{
  if (FP_REG_P (operands[1])
      && ! FP_REG_P (operands[0])
      && ! top_dead_p (insn))
    fp_store_df (operands[0]);
  else
    output_movdf (operands[0], operands[1]);
  RETCOM (movdf);
}")

(define_insn "movdi"
  [(set (match_operand:DI 0 "general_operand" "=&r,rm")
	(match_operand:DI 1 "general_operand" "m,ri"))]
  ""
  "*
{
   return output_move_double (operands);
}")

;; These go after the move instructions
;; because the move instructions are better (require no spilling)
;; when they can apply.  But these go before the add and subtract insns
;; because it is often shorter to use these when both apply.

; ??? Why is this pattern desirable?
(define_insn ""
  [(set (match_operand:SI 0 "push_operand" "=<")
	(plus:SI (match_operand:SI 1 "general_operand" "%r")
		 (match_operand:SI 2 "general_operand" "ri")))]
  ""
  "*
{
  rtx xops[4];
  xops[0] = operands[0];
  xops[1] = operands[1];
  xops[2] = operands[2];
  xops[3] = gen_rtx (MEM, SImode, stack_pointer_rtx);
  output_asm_insn (\"push%z1 %1\", xops);
  output_asm_insn (AS2 (add%z3,%2,%3), xops);
  RET;
}")

(define_insn ""
  [(set (match_operand:SI 0 "general_operand" "=g")
	(plus:SI (match_operand:SI 1 "general_operand" "0")
		 (const_int 1)))]
  ""
  "inc%L %0")

(define_insn ""
  [(set (match_operand:SI 0 "general_operand" "=g")
	(plus:SI (match_operand:SI 1 "general_operand" "0")
		 (const_int -1)))]
  ""
  "dec%L %0")

(define_insn ""
  [(set (match_operand:SI 0 "general_operand" "=g")
	(minus:SI (match_operand:SI 1 "general_operand" "0")
		  (const_int 1)))]
  ""
  "dec%L %0")

(define_insn ""
  [(set (match_operand:SI 0 "register_operand" "=r")
        (match_operand:QI 1 "address_operand" "p"))]
  ""
  "lea%L %a1,%0")

;;- conversion instructions
;;- NONE

;;- truncation instructions
(define_insn "truncsiqi2"
  [(set (match_operand:QI 0 "general_operand" "=rm,r")
	(truncate:QI
	 (match_operand:SI 1 "general_operand" "ri,m")))]
  ""
  "mov%B %1,%0")

(define_insn "trunchiqi2"
  [(set (match_operand:QI 0 "general_operand" "=rm,r")
	(truncate:QI
	 (match_operand:HI 1 "general_operand" "ri,m")))]
  ""
  "mov%B %1,%0")

(define_insn "truncsihi2"
  [(set (match_operand:HI 0 "general_operand" "=rm,r")
	(truncate:HI
	 (match_operand:SI 1 "general_operand" "ri,m")))]
  ""
  "mov%W %1,%0")

;;- zero extension instructions
;; Note that the one starting from HImode comes before those for QImode
;; so that a constant operand will match HImode, not QImode.

(define_insn "zero_extendhisi2"
  [(set (match_operand:SI 0 "general_operand" "=r")
	(zero_extend:SI
	 (match_operand:HI 1 "general_operand" "rm")))]
  ""
  "movz%W%L %1,%0")

(define_insn "zero_extendqihi2"
  [(set (match_operand:HI 0 "general_operand" "=r")
	(zero_extend:HI
	 (match_operand:QI 1 "general_operand" "qm")))]
  ""
  "movz%B%W %1,%0")

(define_insn "zero_extendqisi2"
  [(set (match_operand:SI 0 "general_operand" "=r")
	(zero_extend:SI
	 (match_operand:QI 1 "general_operand" "qm")))]
  ""
  "movz%B%L %1,%0")

;;- sign extension instructions
;; Note that the one starting from HImode comes before those for QImode
;; so that a constant operand will match HImode, not QImode.

/*
(define_insn "extendsidi2"
  [(set (match_operand:DI 0 "general_operand" "=a")
	(sign_extend:DI
	 (match_operand:SI 1 "general_operand" "a")))]
  ""
  "clq")
*/

(define_insn "extendhisi2"
  [(set (match_operand:SI 0 "general_operand" "=r")
	(sign_extend:SI
	 (match_operand:HI 1 "general_operand" "rm")))]
  ""
  "movs%W%L %1,%0")

(define_insn "extendqihi2"
  [(set (match_operand:HI 0 "general_operand" "=r")
	(sign_extend:HI
	 (match_operand:QI 1 "general_operand" "qm")))]
  ""
  "movs%B%W %1,%0")

(define_insn "extendqisi2"
  [(set (match_operand:SI 0 "general_operand" "=r")
	(sign_extend:SI
	 (match_operand:QI 1 "general_operand" "qm")))]
  ""
 "movs%B%L %1,%0"
 )

;; Conversions between float and double.

(define_insn "extendsfdf2"
  [(set (match_operand:DF 0 "general_operand" "=fm,fm,fm")
	(float_extend:DF
	 (match_operand:SF 1 "general_operand" "m,f,!*r")))]
  "TARGET_80387"
  "*
{
  if (FP_REG_P (operands[0]))
    {
      output_movsf (operands[0], operands[1]);
      RET;
    }
  if (FP_REG_P (operands[1]))
    {
      if (top_dead_p (insn))
        fp_pop_df (operands[0]);
      else
        fp_store_df (operands[0]);
      RET;
    }
  output_movsf (FP_TOP, operands[1]);
  fp_pop_df (operands[0]);
  RETCOM (extendsfdf2);
}")

;; This cannot output into an f-reg because there is no way to be
;; sure of truncating in that case.
(define_insn "truncdfsf2"
  [(set (match_operand:SF 0 "general_operand" "=m,!*r")
	(float_truncate:SF
	 (match_operand:DF 1 "general_operand" "f,f")))]
  "TARGET_80387"
  "*
{
  fp_pop_sf (operands[0]);
  RETCOM (truncdfsf2);
}")

;; Conversion between fixed point and floating point.
;; Note that among the fix-to-float insns
;; the ones that start with SImode come first.
;; That is so that an operand that is a CONST_INT
;; (and therefore lacks a specific machine mode).
;; will be recognized as SImode (which is always valid)
;; rather than as QImode or HImode. The 80387 would not know
;; what to do with the smaller sizes anyway. (I think).

(define_insn "floatsisf2"
  [(set (match_operand:SF 0 "general_operand" "=fm,fm")
	(float:SF (match_operand:SI 1 "general_operand" "m,!*r")))]
  "TARGET_80387"
  "*
{
/*  fp_pop_level++; */

  if (GET_CODE (operands[1]) != MEM)
    {
      rtx xops[2];
      output_asm_insn (\"push%L %1\", operands);
      operands[1] = AT_SP (SImode);
      output_asm_insn (\"fild%L %1\", operands);
      xops[0] = stack_pointer_rtx;
      xops[1] = gen_rtx (CONST_INT, VOIDmode, 4);
      output_asm_insn (AS2 (add%L,%1,%0), xops);
    }
  else
    output_asm_insn (\"fild%L %1\", operands);

  if (! FP_REG_P (operands[0]))
    {
/*      fp_pop_level--; */
      return \"fstp%S %0\";
    }
  RET;
}")

(define_insn "floatsidf2"
  [(set (match_operand:DF 0 "general_operand" "=fm,fm")
	(float:DF (match_operand:SI 1 "general_operand" "m,!*r")))]
  "TARGET_80387"
  "*
{
/*  fp_pop_level++; */
  if (GET_CODE (operands[1]) != MEM)
    {
      rtx xops[2];
      output_asm_insn (\"push%L %1\", operands);
      operands[1] = AT_SP (SImode);
      output_asm_insn (\"fild%L %1\", operands);
      xops[0] = stack_pointer_rtx;
      xops[1] = gen_rtx (CONST_INT, VOIDmode, 4);
      output_asm_insn (AS2 (add%L,%1,%0), xops);
    }
  else
    output_asm_insn (\"fild%L %1\", operands);
  if (! FP_REG_P (operands[0]))
    {
/*      fp_pop_level--; */
      return \"fstp%Q %0\";
    }
  RET;
}")

;; Convert a float to a float whose value is an integer.
;; This is the first stage of converting it to an integer type.

;; On the 387  truncating doub to an short integer shor can be performed:

;	fstcw	-4(%esp)  ;save cw
;	movw	-4(%esp),%ax
;	orw	$0x0c00,%ax  ;set rounding to chop towards zero
;	movw	%ax,-2(%esp) ;
;	fldcw	-2(%esp)     ;
;	fldl	doubl
;	fistpl	-12(%esp)    ;store the round value
;	fldcw	-4(%esp)     ;restore cw
;	movl	-12(%esp),%eax
;	movw	%ax,shor     ; move the result into shor.

;; but it is probably better to have a call, rather than waste this
;; space.  The last instruction would have been a movl if were
;; going to an int instead of a short.
;; For the moment we will go with the soft float for these.

/* These are incorrect since they don't set the rounding bits of CW flag.
   The proper way to do that is to make the function prologue save the CW
   and also construct the alternate CW value needed for these insns.
   Then these insns can output two fldcw's, referring to fixed places in
   the stack frame.

;; Convert a float whose value is an integer
;; to an actual integer.  Second stage of converting float to integer type.

(define_insn "fix_truncsfqi2"
  [(set (match_operand:QI 0 "general_operand" "=m,?*q")
	(fix:QI (fix:SF (match_operand:SF 1 "general_operand" "f,f"))))]
  "TARGET_80387"
  "*
{
  fp_pop_int (operands[0]);
  RET;
}")

(define_insn "fix_truncsfhi2"
  [(set (match_operand:HI 0 "general_operand" "=m,?*r")
	(fix:HI (fix:SF (match_operand:SF 1 "general_operand" "f,f"))))]
  "TARGET_80387"
  "*
{
  fp_pop_int (operands[0]);
  RET;
}")

(define_insn "fix_truncsfsi2"
  [(set (match_operand:SI 0 "general_operand" "=m,?*r")
	(fix:SI (fix:SF (match_operand:SF 1 "general_operand" "f,f"))))]
  "TARGET_80387"
  "*
{
  fp_pop_int (operands[0]);
  RET;
}")

(define_insn "fix_truncdfqi2"
  [(set (match_operand:QI 0 "general_operand" "=m,?*q")
	(fix:QI (fix:DF (match_operand:DF 1 "general_operand" "f,f"))))]

  "TARGET_80387"
 "*
{
  fp_pop_int (operands[0]);
  RET;
}")


(define_insn "fix_truncdfhi2"
  [(set (match_operand:HI 0 "general_operand" "=m,?*r")
	(fix:HI (fix:DF (match_operand:DF 1 "general_operand" "f,f"))))]
  "TARGET_80387"
  "*
{
  fp_pop_int (operands[0]);
  RET;
}")


(define_insn "fix_truncdfsi2"
  [(set (match_operand:SI 0 "general_operand" "=m,?*r")
	(fix:SI (fix:DF (match_operand:DF 1 "general_operand" "f,f"))))]
  "TARGET_80387"
  "*
{
  fp_pop_int (operands[0]);
  RET;
}")
*/


;;- add instructions
;;moved incl to above leal

(define_insn "addsi3"
  [(set (match_operand:SI 0 "general_operand" "=rm,r")
	(plus:SI (match_operand:SI 1 "general_operand" "%0,0")
		 (match_operand:SI 2 "general_operand" "ri,rm")))]
  ""
  "add%L %2,%0")

(define_insn ""
  [(set (match_operand:HI 0 "general_operand" "=g")
	(plus:HI (match_operand:HI 1 "general_operand" "0")
		 (const_int 1)))]
  ""
  "inc%W %0")

(define_insn "addhi3"
  [(set (match_operand:HI 0 "general_operand" "=rm,r")
	(plus:HI (match_operand:HI 1 "general_operand" "%0,0")
		 (match_operand:HI 2 "general_operand" "ri,rm")))]
  ""
  "add%W %2,%0")

(define_insn ""
  [(set (match_operand:QI 0 "general_operand" "=qm")
	(plus:QI (match_operand:QI 1 "general_operand" "0")
		 (const_int 1)))]
  ""
  "inc%B %0")

(define_insn "addqi3"
  [(set (match_operand:QI 0 "general_operand" "=m,q")
	(plus:QI (match_operand:QI 1 "general_operand" "%0,0")
		 (match_operand:QI 2 "general_operand" "qn,qmn")))]
  ""
  "add%B %2,%0")

;;had "fmF,m"

(define_insn "adddf3"
  [(set (match_operand:DF 0 "general_operand" "=f,m,f")
	(plus:DF (match_operand:DF 1 "general_operand" "%0,0,0)")
		 (match_operand:DF 2 "general_operand" "m,!f,!*r")))]
  "TARGET_80387"
  "*FP_CALL (\"fadd%z0 %0\", \"fadd%z0 %0\", 2)")

(define_insn "addsf3"
  [(set (match_operand:SF 0 "general_operand" "=f,m,f")
	(plus:SF (match_operand:SF 1 "general_operand" "%0,0,0")
		 (match_operand:SF 2 "general_operand" "m,!f,!*r")))]
  "TARGET_80387"
  "*FP_CALL (\"fadd%z0 %0\", \"fadd%z0 %0\", 2)")

;;- subtract instructions

;;moved decl above leal

(define_insn "subsi3"
  [(set (match_operand:SI 0 "general_operand" "=rm,r")
	(minus:SI (match_operand:SI 1 "general_operand" "0,0")
		  (match_operand:SI 2 "general_operand" "ri,rm")))]
  ""
  "sub%L %2,%0")

(define_insn ""
  [(set (match_operand:HI 0 "general_operand" "=g")
	(minus:HI (match_operand:HI 1 "general_operand" "0")
		  (const_int 1)))]
  ""
  "dec%W %0")

(define_insn "subhi3"
  [(set (match_operand:HI 0 "general_operand" "=rm,r")
	(minus:HI (match_operand:HI 1 "general_operand" "0,0")
		  (match_operand:HI 2 "general_operand" "ri,rm")))]
  ""
  "sub%W %2,%0")

(define_insn ""
  [(set (match_operand:QI 0 "general_operand" "=qm")
	(minus:QI (match_operand:QI 1 "general_operand" "0")
		  (const_int 1)))]
  ""
  "dec%B %0")

(define_insn "subqi3"
  [(set (match_operand:QI 0 "general_operand" "=m,q")
	(minus:QI (match_operand:QI 1 "general_operand" "0,0")
		  (match_operand:QI 2 "general_operand" "qn,qmn")))]
  ""
  "sub%B %2,%0")

(define_insn "subdf3"
  [(set (match_operand:DF 0 "general_operand" "=f,m,f,f")
	(minus:DF (match_operand:DF 1 "general_operand" "0,0,0,m")
		  (match_operand:DF 2 "general_operand" "m,!f,!*r,*0")))]
  "TARGET_80387"
  "*FP_CALL (\"fsub%z0 %0\", \"fsubr%z0 %0\", 2)")


(define_insn "subsf3"
  [(set (match_operand:SF 0 "general_operand" "=f,m,f,f")
	(minus:SF (match_operand:SF 1 "general_operand" "0,0,0,m")
		  (match_operand:SF 2 "general_operand" "m,!f,!*r,*0")))]
  "TARGET_80387"
  "*FP_CALL (\"fsub%z0 %0\", \"fsubr%z0 %0\", 2)")

;;- multiply instructions

(define_insn "mulhi3"
  [(set (match_operand:HI 0 "general_operand" "=r")
	(mult:SI (match_operand:HI 1 "general_operand" "%0")
		 (match_operand:HI 2 "general_operand" "g")))]
  ""
  "imul%W %2,%0")

(define_insn "mulsi3"
  [(set (match_operand:SI 0 "general_operand" "=r,r")
	(mult:SI (match_operand:SI 1 "general_operand" "%0,rm")
		 (match_operand:SI 2 "general_operand" "g,i")))]
  ""
  "*
{
  if (rtx_equal_p (operands[0], operands[1])
      && (GET_CODE (operands[2]) == MEM
	  || GET_CODE (operands[2]) == REG))
    /* Assembler has weird restrictions.  */
    return AS2 (imul%L,%2,%0);
  return AS3 (imul%L,%2,%1,%0);
}")

(define_insn "umulqihi3"
  [(set (match_operand:HI 0 "general_operand" "=a")
	(umult:HI (match_operand:QI "general_operand" "%a")
		  (match_operand:QI "general_operand" "rm")))]
  ""
  "mul%B %2,%0")

(define_insn "umulhi3"
  [(set (match_operand:HI 0 "general_operand" "=a")
	(umult:SI (match_operand:HI 1 "general_operand" "%a")
		  (match_operand:HI 2 "general_operand" "rm")))
   (clobber (reg:HI 1))]
  ""
  "mul%W %2,%0")

(define_insn "umulsi3"
  [(set (match_operand:SI 0 "general_operand" "=a")
	(umult:SI (match_operand:SI 1 "general_operand" "%a")
		  (match_operand:SI 2 "general_operand" "rm")))
   (clobber (reg:SI 1))]
  ""
  "mul%L %2,%0")

(define_insn "muldf3"
  [(set (match_operand:DF 0 "general_operand" "=f,m,f")
	(mult:DF (match_operand:DF 1 "general_operand" "%0,0,0")
		 (match_operand:DF 2 "general_operand" "m,!f,!*r")))]
  "TARGET_80387"
   "*FP_CALL (\"fmul%z0 %0\", \"fmul%z0 %0\", 2)
")

(define_insn "mulsf3"
  [(set (match_operand:SF 0 "general_operand" "=f,m,f")
	(mult:SF (match_operand:SF 1 "general_operand" "%0,0,0")
		 (match_operand:SF 2 "general_operand" "m,!f,!*r")))]
  "TARGET_80387"
  "*FP_CALL (\"fmul%z0 %0\", \"fmul%z0 %0\", 2)
")

;;- divide instructions
(define_insn "divdf3"
  [(set (match_operand:DF 0 "general_operand" "=f,m,f,f")
	(div:DF (match_operand:DF 1 "general_operand" "0,0,0,m")
		(match_operand:DF 2 "general_operand" "m,!f,!*r,*0")))]
  "TARGET_80387"
  "*FP_CALL (\"fdiv%z0 %0\", \"fdivr%z0 %0\", 2)
")

(define_insn "divsf3"
  [(set (match_operand:SF 0 "general_operand" "=f,m,f,f")
	(div:SF (match_operand:SF 1 "general_operand" "0,0,0,m")
		(match_operand:SF 2 "general_operand" "m,!f,!*r,*0")))]
  "TARGET_80387"
  "*FP_CALL (\"fdiv%z0 %0\", \"fdivr%z0 %0\", 2)
")

;; Remainder instructions.

(define_insn "divmodsi4"
  [(set (match_operand:SI 0 "general_operand" "=a")
	(div:SI (match_operand:SI 1 "general_operand" "0")
		(match_operand:SI 2 "general_operand" "rm")))
   (set (match_operand:SI 3 "general_operand" "=&d")
	(mod:SI (match_dup 1) (match_dup 2)))]
  ""
  "cltd\;idiv%L %2")

(define_insn "udivmodsi4"
  [(set (match_operand:SI 0 "general_operand" "=a")
	(udiv:SI (match_operand:SI 1 "general_operand" "0")
		(match_operand:SI 2 "general_operand" "rm")))
   (set (match_operand:SI 3 "general_operand" "=&d")
	(umod:SI (match_dup 1) (match_dup 2)))]
  ""
  "xor%L %3,%3\;div%L %2")

/*
;;this should be a valid double division which we may want to add

(define_insn ""
  [(set (match_operand:SI 0 "general_operand" "=a")
	(udiv:DI (match_operand:DI 1 "general_operand" "a")
		(match_operand:SI 2 "general_operand" "rm")))
   (set (match_operand:SI 3 "general_operand" "=d")
	(umod:SI (match_dup 1) (match_dup 2)))]
  ""
  "div%L %2,%0")
*/

;;- and instructions

;; The `r' in `rm' for operand 3 looks redundant, but it causes
;; optional reloads to be generated if op 3 is a pseudo in a stack slot.

(define_insn "andsi3"
  [(set (match_operand:SI 0 "general_operand" "=rm,r")
	(and:SI (match_operand:SI 1 "general_operand" "%0,0")
		(match_operand:SI 2 "general_operand" "ri,rm")))]
  ""
  "and%L %2,%0")

(define_insn "andhi3"
  [(set (match_operand:HI 0 "general_operand" "=rm,r")
	(and:HI (match_operand:HI 1 "general_operand" "%0,0")
		(match_operand:HI 2 "general_operand" "ri,rm")))]
  ""
  "and%W %2,%0")

(define_insn "andqi3"
  [(set (match_operand:QI 0 "general_operand" "=m,q")
	(and:QI (match_operand:QI 1 "general_operand" "%0,0")
		(match_operand:QI 2 "general_operand" "qn,qmn")))]
  ""
  "and%B %2,%0")

/* I am nervous about these two.. add them later..
;I presume this means that we have something in say op0= eax which is small
;and we want to and it with memory so we can do this by just an
;andb m,%al  and have success.
(define_insn ""
  [(set (match_operand:SI 0 "general_operand" "=r")
	(and:SI (zero_extend:SI (match_operand:HI 1 "general_operand" "rm"))
		(match_operand:SI 2 "general_operand" "0")))]
  "GET_CODE (operands[2]) == CONST_INT
   && (unsigned int) INTVAL (operands[2]) < (1 << GET_MODE_BITSIZE (HImode))"
  "and%W %1,%0")

(define_insn ""
  [(set (match_operand:SI 0 "general_operand" "=q")
	(and:SI (zero_extend:SI (match_operand:QI 1 "general_operand" "qm"))
		(match_operand:SI 2 "general_operand" "0")))]
  "GET_CODE (operands[2]) == CONST_INT
   && (unsigned int) INTVAL (operands[2]) < (1 << GET_MODE_BITSIZE (QImode))"
  "and%L %1,%0")

*/



;;- Bit set (inclusive or) instructions

(define_insn "iorsi3"
  [(set (match_operand:SI 0 "general_operand" "=rm,r")
	(ior:SI (match_operand:SI 1 "general_operand" "%0,0")
		(match_operand:SI 2 "general_operand" "ri,rm")))]
  ""
  "or%L %2,%0")

(define_insn "iorhi3"
  [(set (match_operand:HI 0 "general_operand" "=rm,r")
	(ior:HI (match_operand:HI 1 "general_operand" "%0,0")
		(match_operand:HI 2 "general_operand" "ri,rm")))]
  ""
  "or%W %2,%0")

(define_insn "iorqi3"
  [(set (match_operand:QI 0 "general_operand" "=m,q")
	(ior:QI (match_operand:QI 1 "general_operand" "%0,0")
		(match_operand:QI 2 "general_operand" "qn,qmn")))]
  ""
  "or%B %2,%0")

;;- xor instructions

(define_insn "xorsi3"
  [(set (match_operand:SI 0 "general_operand" "=rm,r")
	(xor:SI (match_operand:SI 1 "general_operand" "%0,0")
		(match_operand:SI 2 "general_operand" "ri,rm")))]
  ""
  "xor%L %2,%0")

(define_insn "xorhi3"
  [(set (match_operand:HI 0 "general_operand" "=rm,r")
	(xor:HI (match_operand:HI 1 "general_operand" "%0,0")
		(match_operand:HI 2 "general_operand" "ri,rm")))]
  ""
  "xor%W %2,%0")

(define_insn "xorqi3"
  [(set (match_operand:QI 0 "general_operand" "=qm")
	(xor:QI (match_operand:QI 1 "general_operand" "%0")
		(match_operand:QI 2 "general_operand" "qn")))]
  ""
  "xor%B %2,%0")

;;- negation instructions
(define_insn "negsi2"
  [(set (match_operand:SI 0 "general_operand" "=rm")
	(neg:SI (match_operand:SI 1 "general_operand" "0")))]
  ""
  "neg%L %0")

(define_insn "neghi2"
  [(set (match_operand:HI 0 "general_operand" "=rm")
	(neg:HI (match_operand:HI 1 "general_operand" "0")))]
  ""
  "neg%W %0")

(define_insn "negqi2"
  [(set (match_operand:QI 0 "general_operand" "=qm")
	(neg:QI (match_operand:QI 1 "general_operand" "0")))]
  ""
  "neg%B %0")

(define_insn "negsf2"
  [(set (match_operand:SF 0 "general_operand" "=f,!m")
	(neg:SF (match_operand:SF 1 "general_operand" "0,0")))]
  "TARGET_80387"
  "*FP_CALL1 (\"fchs\")")

(define_insn "negdf2"
  [(set (match_operand:DF 0 "general_operand" "=f,!m")
	(neg:DF (match_operand:DF 1 "general_operand" "0,0")))]
  "TARGET_80387"
  "*FP_CALL1 (\"fchs\")")

;; Absolute value instructions

(define_insn "abssf2"
  [(set (match_operand:SF 0 "general_operand" "=f,!m")
	(abs:SF (match_operand:SF 1 "general_operand" "0,0")))]
  "TARGET_80387"
  "*FP_CALL1 (\"fabs\")")

(define_insn "absdf2"
  [(set (match_operand:DF 0 "general_operand" "=f,!m")
	(abs:DF (match_operand:DF 1 "general_operand" "0,0")))]
  "TARGET_80387"
  "*FP_CALL1 (\"fabs\")")

;;- one complement instructions
(define_insn "one_cmplsi2"
  [(set (match_operand:SI 0 "general_operand" "=rm")
	(not:SI (match_operand:SI 1 "general_operand" "0")))]
  ""
  "not%L %0")

(define_insn "one_cmplhi2"
  [(set (match_operand:HI 0 "general_operand" "=rm")
	(not:HI (match_operand:HI 1 "general_operand" "0")))]
  ""
  "not%W %0")

(define_insn "one_cmplqi2"
  [(set (match_operand:QI 0 "general_operand" "=qm")
	(not:QI (match_operand:QI 1 "general_operand" "0")))]
  ""
  "not%B %0")

;;- arithmetic shift instructions

(define_insn "ashlsi3"
  [(set (match_operand:SI 0 "general_operand" "=rm")
	(ashift:SI (match_operand:SI 1 "general_operand" "0")
		   (match_operand:SI 2 "general_operand" "cI")))]
  ""
  "*
{
  if (REG_P (operands[2]))
    return AS2 (sal%L,%Rcl,%0);
  else
    return AS2 (sal%L,%2,%1);
}")

(define_insn "ashlhi3"
  [(set (match_operand:HI 0 "general_operand" "=rm")
	(ashift:HI (match_operand:HI 1 "general_operand" "0")
		   (match_operand:HI 2 "general_operand" "cI")))]
  ""
  "*
{
  if (REG_P (operands[2]))
    return AS2 (sal%W,%Rcl,%0);
  else
    return AS2 (sal%W,%2,%1);
}")

(define_insn "ashlqi3"
  [(set (match_operand:QI 0 "general_operand" "=qm")
	(ashift:QI (match_operand:QI 1 "general_operand" "0")
		   (match_operand:QI 2 "general_operand" "cI")))]
  ""
  "*
{
  if (REG_P (operands[2]))
    return AS2 (sal%B,%Rcl,%0);
  else
    return AS2 (sal%B,%2,%1);
}")

(define_insn "ashrsi3"
  [(set (match_operand:SI 0 "general_operand" "=rm")
	(ashiftrt:SI (match_operand:SI 1 "general_operand" "0")
		     (match_operand:SI 2 "general_operand" "cI")))]
  ""
  "*
{
  if (REG_P (operands[2]))
    return AS2 (sar%L,%Rcl,%0);
  else
    return AS2 (sar%L,%2,%0);
}")

(define_insn "ashrhi3"
  [(set (match_operand:HI 0 "general_operand" "=rm")
	(ashiftrt:HI (match_operand:HI 1 "general_operand" "0")
		     (match_operand:HI 2 "general_operand" "cI")))]
  ""
  "*
{
  if (REG_P (operands[2]))
    return AS2 (sar%W,%Rcl,%0);
  else
    return AS2 (sar%W,%2,%0);
}")

(define_insn "ashrqi3"
  [(set (match_operand:QI 0 "general_operand" "=qm")
	(ashiftrt:QI (match_operand:QI 1 "general_operand" "0")
		     (match_operand:QI 2 "general_operand" "cI")))]
  ""
  "*
{
  if (REG_P (operands[2]))
    return AS2 (sar%B,%Rcl,%0);
  return
    AS2 (sar%B,%2,%1);
}")

;;- logical shift instructions

(define_insn "lshlsi3"
  [(set (match_operand:SI 0 "general_operand" "=rm")
	(lshift:SI (match_operand:SI 1 "general_operand" "0")
		   (match_operand:SI 2 "general_operand" "cI")))]
  ""
  "*
{
  if (REG_P (operands[2]))
    return AS2 (shl%L,%Rcl,%0);
  else
    return AS2 (shl%L,%2,%1);
}")

(define_insn "lshlhi3"
  [(set (match_operand:HI 0 "general_operand" "=rm")
	(lshift:HI (match_operand:HI 1 "general_operand" "0")
		   (match_operand:HI 2 "general_operand" "cI")))]
  ""
  "*
{
  if (REG_P (operands[2]))
    return AS2 (shl%W,%Rcl,%0);
  else
    return AS2 (shl%W,%2,%1);
}")

(define_insn "lshlqi3"
  [(set (match_operand:QI 0 "general_operand" "=qm")
	(lshift:QI (match_operand:QI 1 "general_operand" "0")
		   (match_operand:QI 2 "general_operand" "cI")))]
  ""
  "*
{
  if (REG_P (operands[2]))
    return AS2 (shl%B,%Rcl,%0);
  else
    return AS2 (shl%B,%2,%1);
}")

(define_insn "lshrsi3"
  [(set (match_operand:SI 0 "general_operand" "=rm")
	(lshiftrt:SI (match_operand:SI 1 "general_operand" "0")
		     (match_operand:SI 2 "general_operand" "cI")))]
  ""
  "*
{
  if (REG_P (operands[2]))
    return AS2 (shr%L,%Rcl,%0);
  else
    return AS2 (shr%L,%2,%1);
}")

(define_insn "lshrhi3"
  [(set (match_operand:HI 0 "general_operand" "=rm")
	(lshiftrt:HI (match_operand:HI 1 "general_operand" "0")
		     (match_operand:HI 2 "general_operand" "cI")))]
  ""
  "*
{
  if (REG_P (operands[2]))
    return AS2 (shr%W,%%cl,%0);
  else
    return AS2 (shr%W,%2,%1);
}")

(define_insn "lshrqi3"
  [(set (match_operand:QI 0 "general_operand" "=qm")
	(lshiftrt:QI (match_operand:QI 1 "general_operand" "0")
		     (match_operand:QI 2 "general_operand" "cI")))]
  ""
  "*
{
  if (REG_P (operands[2]))
    return AS2 (shr%B,%%cl,%0);
  else
    return AS2 (shr%B,%2,%1);
}")

;;- rotate instructions

(define_insn "rotlsi3"
  [(set (match_operand:SI 0 "general_operand" "=rm")
	(rotate:SI (match_operand:SI 1 "general_operand" "0")
		   (match_operand:SI 2 "general_operand" "cI")))]
  ""
  "*
{
  if (REG_P (operands[2]))
    return AS2 (rol%L,%%cl,%0);
  else
    return AS2 (rol%L,%2,%1);
}")

(define_insn "rotlhi3"
  [(set (match_operand:HI 0 "general_operand" "=rm")
	(rotate:HI (match_operand:HI 1 "general_operand" "0")
		   (match_operand:HI 2 "general_operand" "cI")))]
  ""
  "*
{
  if (REG_P (operands[2]))
    return AS2 (rol%W,%%cl,%0);
  else
    return AS2 (rol%W,%2,%1);
}")

(define_insn "rotlqi3"
  [(set (match_operand:QI 0 "general_operand" "=qm")
	(rotate:QI (match_operand:QI 1 "general_operand" "0")
		   (match_operand:QI 2 "general_operand" "cI")))]
  ""
  "*
{
  if (REG_P (operands[2]))
    return AS2 (rol%B,%%cl,%0);
  else
    return AS2 (rol%B,%2,%1);
}")

(define_insn "rotrsi3"
  [(set (match_operand:SI 0 "general_operand" "=rm")
	(rotatert:SI (match_operand:SI 1 "general_operand" "0")
		     (match_operand:SI 2 "general_operand" "cI")))]
  ""
  "*
{
  if (REG_P (operands[2]))
    return AS2 (ror%L,%%cl,%0);
  else
    return AS2 (ror%L,%2,%1);
}")

(define_insn "rotrhi3"
  [(set (match_operand:HI 0 "general_operand" "=rm")
	(rotatert:HI (match_operand:HI 1 "general_operand" "0")
		     (match_operand:HI 2 "general_operand" "cI")))]
  ""
  "*
{
  if (REG_P (operands[2]))
    return AS2 (ror%W,%%cl,%0);
  else
    return AS2 (ror%W,%2,%1);
}")

(define_insn "rotrqi3"
  [(set (match_operand:QI 0 "general_operand" "=qm")
	(rotatert:QI (match_operand:QI 1 "general_operand" "0")
		     (match_operand:QI 2 "general_operand" "cI")))]
  ""
  "*
{
  if (REG_P (operands[2]))
    return AS2 (ror%B,%%cl,%0);
  else
    return AS2 (ror%B,%2,%1);
}")

;;the seq ops are moved to md.old

;; Basic conditional jump instructions.

;; ??? The third operand of OUTPUT_JUMP is incorrect, in each case.
;; It is supposed to ignore the overflow flag.
;; It isn't obvious how to do this in certain cases.

(define_insn "beq"
  [(set (pc)
	(if_then_else (eq (cc0)
			  (const_int 0))
		      (label_ref (match_operand 0 "" ""))
		      (pc)))]
  ""
  "je %l0")

(define_insn "bne"
  [(set (pc)
	(if_then_else (ne (cc0)
			  (const_int 0))
		      (label_ref (match_operand 0 "" ""))
		      (pc)))]
  ""
  "jne %l0")

(define_insn "bgt"
  [(set (pc)
	(if_then_else (gt (cc0)
			  (const_int 0))
		      (label_ref (match_operand 0 "" ""))
		      (pc)))]
  ""
  "*OUTPUT_JUMP (\"jg %l0\", \"ja %l0\", \"jg %l0\")")

(define_insn "bgtu"
  [(set (pc)
	(if_then_else (gtu (cc0)
			   (const_int 0))
		      (label_ref (match_operand 0 "" ""))
		      (pc)))]
  ""
  "ja %l0")

(define_insn "blt"
  [(set (pc)
	(if_then_else (lt (cc0)
			  (const_int 0))
		      (label_ref (match_operand 0 "" ""))
		      (pc)))]
  ""
  "*OUTPUT_JUMP (\"jl %l0\", \"jb %l0\", \"jl %l0\")")

(define_insn "bltu"
  [(set (pc)
	(if_then_else (ltu (cc0)
			   (const_int 0))
		      (label_ref (match_operand 0 "" ""))
		      (pc)))]
  ""
  "jb %l0")

(define_insn "bge"
  [(set (pc)
	(if_then_else (ge (cc0)
			  (const_int 0))
		      (label_ref (match_operand 0 "" ""))
		      (pc)))]
  ""
  "*OUTPUT_JUMP (\"jge %l0\", \"jae %l0\", \"jge %l0\")")

(define_insn "bgeu"
  [(set (pc)
	(if_then_else (geu (cc0)
			   (const_int 0))
		      (label_ref (match_operand 0 "" ""))
		      (pc)))]
  ""
  "jae %l0")

(define_insn "ble"
  [(set (pc)
	(if_then_else (le (cc0)
			  (const_int 0))
		      (label_ref (match_operand 0 "" ""))
		      (pc)))]
  ""
  "*OUTPUT_JUMP (\"jle %l0\", \"jbe %l0\", \"jle %l0\") ")

(define_insn "bleu"
  [(set (pc)
	(if_then_else (leu (cc0)
			   (const_int 0))
		      (label_ref (match_operand 0 "" ""))
		      (pc)))]
  ""
  "jbe %l0")

;; Negated conditional jump instructions.

(define_insn ""
  [(set (pc)
	(if_then_else (eq (cc0)
			  (const_int 0))
		      (pc)
		      (label_ref (match_operand 0 "" ""))))]
  ""
  "jne %l0")

(define_insn ""
  [(set (pc)
	(if_then_else (ne (cc0)
			  (const_int 0))
		      (pc)
		      (label_ref (match_operand 0 "" ""))))]
  ""
  "je %l0")

(define_insn ""
  [(set (pc)
	(if_then_else (gt (cc0)
			  (const_int 0))
		      (pc)
		      (label_ref (match_operand 0 "" ""))))]
  ""
  "*OUTPUT_JUMP (\"jle %l0\", \"jbe %l0\", \"jle %l0\") ")

(define_insn ""
  [(set (pc)
	(if_then_else (gtu (cc0)
			   (const_int 0))
		      (pc)
		      (label_ref (match_operand 0 "" ""))))]
  ""
  "jbe %l0")

(define_insn ""
  [(set (pc)
	(if_then_else (lt (cc0)
			  (const_int 0))
		      (pc)
		      (label_ref (match_operand 0 "" ""))))]
  ""
  "*OUTPUT_JUMP (\"jge %l0\", \"jae %l0\", \"jge %l0\")
")

(define_insn ""
  [(set (pc)
	(if_then_else (ltu (cc0)
			   (const_int 0))
		      (pc)
		      (label_ref (match_operand 0 "" ""))))]
  ""
  "jae %l0")

(define_insn ""
  [(set (pc)
	(if_then_else (ge (cc0)
			  (const_int 0))
		      (pc)
		      (label_ref (match_operand 0 "" ""))))]
  ""
  "*OUTPUT_JUMP (\"jl %l0\", \"jb %l0\", \"jl %l0\")")

(define_insn ""
  [(set (pc)
	(if_then_else (geu (cc0)
			   (const_int 0))
		      (pc)
		      (label_ref (match_operand 0 "" ""))))]
  ""
  "jb %l0")

(define_insn ""
  [(set (pc)
	(if_then_else (le (cc0)
			  (const_int 0))
		      (pc)
		      (label_ref (match_operand 0 "" ""))))]
  ""
  "*OUTPUT_JUMP (\"jg %l0\", \"ja %l0\", \"jg %l0\")")

(define_insn ""
  [(set (pc)
	(if_then_else (leu (cc0)
			   (const_int 0))
		      (pc)
		      (label_ref (match_operand 0 "" ""))))]
  ""
  "ja %l0")

;; Unconditional and other jump instructions
(define_insn "jump"
  [(set (pc)
	(label_ref (match_operand 0 "" "")))]
  ""
  "jmp %l0")

(define_insn "tablejump"
  [(set (pc) (match_operand:SI 0 "general_operand" "rm"))
   (use (label_ref (match_operand 1 "" "")))]
  ""
  "*
{
  CC_STATUS_INIT;

  return \"jmp %*%0\";
}")

/*
(define_insn ""
  [(set (pc)
	(if_then_else
	 (ne (minus (minus:HI (match_operand:HI 0 "general_operand" "c")
			      (const_int 1))
		    (const_int -1))
	     (const_int 0))
	 (label_ref (match_operand 1 "" "g"))
	 (pc)))
   (set (match_dup 0)
	(minus:HI (match_dup 0)
		  (const_int 1)))]
  ""
  "loop %l1")

(define_insn ""
  [(set (pc)
	(if_then_else
	 (ne (minus (const_int -1)
		    (minus:SI (match_operand:SI 0 "general_operand" "c")
			      (const_int 1)))
	     (const_int 0))
	 (label_ref (match_operand 1 "" "g"))
	 (pc)))
   (set (match_dup 0)
	(minus:SI (match_dup 0)
		  (const_int 1)))]
  ""
  "loop %l1")
*/

;; Call subroutine returning no value.
(define_insn "call"
  [(call (match_operand:QI 0 "indirect_operand" "m")
	 (match_operand:SI 1 "general_operand" "g"))]
  ;; Operand 1 not really used on the m68000.
  ""
  "*
{
  if (GET_CODE (operands[0]) == MEM
      && ! CONSTANT_ADDRESS_P (XEXP (operands[0], 0)))
    {
      operands[0] = XEXP (operands[0], 0);
      return \"call %*%0\";
    }
  else
    return \"call %0\";
}")

;; Call subroutine, returning value in operand 0
;; (which must be a hard register).
(define_insn "call_value"
  [(set (match_operand 0 "" "rf")
	(call (match_operand:QI 1 "indirect_operand" "m")
	      (match_operand:SI 2 "general_operand" "g")))]
  ;; Operand 2 not really used on the m68000.
  ""
  "*
{
  if (GET_CODE (operands[1]) == MEM
      && ! CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))
    {
      operands[1] = XEXP (operands[1], 0);
      return \"call %*%1\";
    }
  else
    output_asm_insn (\"call %1\", operands);

  if (GET_MODE (operands[0]) == DFmode
      || GET_MODE (operands[0]) == SFmode)
    {
/*      fp_pop_level++; */
      /* pop if reg dead */
      if (!FP_REG_P (operands[0]))
	abort ();
      if (top_dead_p (insn))
	{
	  POP_ONE_FP;
	}
    }
  RET;
}")

(define_insn "return"
  [(return)]
  "0"
  "ret")


;;- 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:
