OSDN Git Service

* 1750a.md: Don't use hex format for a const_int.
[pf3gnuchains/gcc-fork.git] / gcc / config / 1750a / 1750a.md
index bcfc64e..1ebd02e 100644 (file)
@@ -1,13 +1,14 @@
 ;;- Machine description for GNU compiler
 ;;- MIL-STD-1750A version.
-;; Copyright (C) 1994, 1995 Free Software Foundation, Inc.
-;; Contributed by O.M.Kellogg, DASA (kellogg@space.otn.dasa.de).
+;; Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999,
+;; 2000 Free Software Foundation, Inc.
+;; Contributed by O.M.Kellogg, DASA (oliver.kellogg@space.otn.dasa.de).
 
 ;; This file is part of GNU CC.
 
 ;; GNU CC is free software; you can redistribute it and/or modify
 ;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 1, or (at your option)
+;; the Free Software Foundation; either version 2, or (at your option)
 ;; any later version.
 
 ;; GNU CC is distributed in the hope that it will be useful,
   [(set (match_operand:HI 0 "push_operand" "=<")
         (match_operand:HI 1 "general_operand" "r"))]
   ""
-  "*
-   { 
-        rtx new_operands[2];
-        new_operands[0] = operands[1];
-        new_operands[1] = gen_rtx(CONST_INT,VOIDmode,REGNO(operands[1])+1);
-   } ")
+  "pshm r%1,r%d1")
 
 (define_insn ""
   [(set (match_operand:HF 0 "push_operand" "=<")
         (match_operand:HF 1 "general_operand" "r"))]
   ""
-  "*
-  { 
-        rtx new_operands[2];
-        new_operands[0] = operands[1];
-        new_operands[1] = gen_rtx(CONST_INT,VOIDmode,REGNO(operands[1])+1);
-        output_asm_insn(\"pshm r%0,r%1\",new_operands);
-        return \"\;\";
-   } ")
+  "pshm r%1,r%d1")
 
 (define_insn ""
   [(set (match_operand:TQF 0 "push_operand" "=<")
         (match_operand:TQF 1 "general_operand" "r"))]
   ""
-  "*
-   { 
-        rtx new_operands[2];
-        new_operands[0] = operands[1];
-        new_operands[1] = gen_rtx(CONST_INT,VOIDmode,REGNO(operands[1])+2);
-        output_asm_insn(\"pshm r%0,r%1\",new_operands);
-        return \"\;\";
-   } ")
+  "pshm r%1,r%t1")
 
 ;; stackpop
 (define_insn ""
   [(set (match_operand:HI 0 "general_operand" "=r")
         (match_operand:HI 1 "push_operand" ">"))]
   ""
-  "*
-   { 
-        rtx new_operands[2];
-        new_operands[0] = operands[0];
-        new_operands[1] = gen_rtx(CONST_INT,VOIDmode,REGNO(operands[0])+1);
-        output_asm_insn(\"popm r%0,r%1\",new_operands);
-        return \"\;\";
-   } ")
+  "popm r%1,r%d1")
 
 (define_insn ""
   [(set (match_operand:HF 0 "general_operand" "=r")
         (match_operand:HF 1 "push_operand" ">"))]
   ""
-  "*
-   { 
-        rtx new_operands[2];
-        new_operands[0] = operands[0];
-        new_operands[1] = gen_rtx(CONST_INT,VOIDmode,REGNO(operands[0])+1);
-        output_asm_insn(\"popm r%0,r%1\",new_operands);
-        return \"\;\";
-   } ")
-
+  "popm r%1,r%d1")
+   
 (define_insn ""
   [(set (match_operand:TQF 0 "general_operand" "=r")
         (match_operand:TQF 1 "push_operand" ">"))]
   ""
-  "*
-   { 
-        rtx new_operands[2];
-        new_operands[0] = operands[0];
-        new_operands[1] = gen_rtx(CONST_INT,VOIDmode,REGNO(operands[0])+2);
-        output_asm_insn(\"popm r%0,r%1\",new_operands);
-        return \"\;\";
-   } ")
+  "popm r%1,r%t1")
 
-;; Test operations. These shouldn't really occur for 1750:
-;; all important instructions set the cc's (see NOTICE_UPDATE_CC)
+
+;; Test operations.
 
 (define_insn "tstqi"
   [(set (cc0)
   ""
   "dlr r%0,r%0   ; from tsthi")
 
+; With 1750A floats, testing the most significant word suffices.
+
 (define_insn "tsthf"
   [(set (cc0)
         (match_operand:HF 0 "register_operand" "r"))]
   ""
-  "dlr r%0,r%0   ; from tsthf")
+  "lr r%0,r%0   ; tsthf")
 
-;; This one is happy with "roughly zero" :-)  (should be improved)
 (define_insn "tsttqf"
   [(set (cc0)
         (match_operand:TQF 0 "register_operand" "r"))]
   ""
-  "dlr r%0,r%0   ; from tsttqf")
+  "lr r%0,r%0   ; tsttqf")
 
 
 ;; block move.
 
-; there is a problem with this insn in gcc-2.2.3
-; (clobber (match_dup 2)) does not prevent use of this operand later
-;
 (define_insn "movstrqi"
-  [(set (mem:BLK (match_operand:QI 0 "register_operand" "r"))
-       (mem:BLK (match_operand:QI 1 "register_operand" "r")))
-   (use (match_operand:QI 2 "register_operand" "r"))
-   (use (match_operand:QI 3 "immediate_operand" ""))
+  [(set (match_operand:BLK 0 "mov_memory_operand" "=m")
+       (match_operand:BLK 1 "mov_memory_operand" "m"))
+   (use (match_operand:QI 2 "general_operand" "r"))
+   (match_operand 3 "" "")
    (clobber (match_dup 0))
    (clobber (match_dup 1))
    (clobber (match_dup 2))]
   ""
-  "* return (char *)movcnt_regno_adjust(operands); ")
+  "*
+   {
+     rtx regops[3];
+
+     regops[0] = XEXP (operands[0], 0);
+     regops[1] = XEXP (operands[1], 0);
+     regops[2] = operands[2];
+
+     return movcnt_regno_adjust (regops);
+   } ")
 
 
 ;; compare instructions.
           return \"ucr.m %0,%1\";
         case 4:
           return \"uc.m %0,%1\";
+        default:
+          abort();
         }
      else
        switch (which_alternative)
           return \"cr   r%0,r%1\";
         case 4:
           return \"c    r%0,%1\";
+        default:
+          abort();
         }
    } ")
 
         (compare (match_operand:HI 0 "general_operand" "r,r")
                  (match_operand:HI 1 "general_operand" "r,m")))]
   ""
-  "@
-    dcr r%0,r%1
-    dc  r%0,%1 ")
+  "*
+   {
+     if (next_cc_user_is_unsigned (insn))
+       {
+         if (which_alternative == 0)
+          return \"ducr.m %0,%1\";
+        return \"duc.m %0,%1\";
+       }
+     else
+       {
+         if (which_alternative == 0)
+           return \"dcr r%0,r%1\";
+         return \"dc  r%0,%1\";
+       }
+   } ")
 
 (define_insn "cmphf"
  [(set (cc0)
 
 (define_insn "trunchiqi2"
   [(set (match_operand:QI 0 "register_operand" "=r")
-        (truncate:QI
-         (match_operand:HI 1 "register_operand" "r")))]
+        (truncate:QI (match_operand:HI 1 "register_operand" "r")))]
   ""
-  "*
-     {
-        REGNO(operands[1]) += 1;
-        return \"lr r%0,r%1  ;trunchiqi2\";
-     } ")
+  "lr  r%0,r%d1")
 
-;; zero extension instructions
 
-(define_insn "zero_extendqihi2"
-  [(set (match_operand:HI 0 "register_operand" "=r,r,r")
-        (zero_extend:HI (match_operand:QI 1 "general_operand" "r,m,i")))]
-  ""
-  "*
-      {
-        output_asm_insn(\"xorr r%0,r%0   ;zero_extendqihi2\",operands);
-        REGNO(operands[0]) += 1;
-        switch (which_alternative)
-          {
-            case 0:
-              return \"lr  r%0,r%1\";
-            case 1:
-              return \"l   r%0,%1\";
-            case 2:
-              return \"lim r%0,%1\";
-          }
-      } ")
+;; zero extension instructions: not defined, GCC can synthesize
 
 ;; sign extension instructions
 
 (define_insn "extendqihi2"
-  [(set (match_operand:HI 0 "register_operand" "=r,r,r")
-        (sign_extend:HI (match_operand:QI 1 "general_operand" "r,m,i")) )]
+  [(set (match_operand:HI 0 "register_operand" "=r,r")
+        (sign_extend:HI (match_operand:QI 1 "general_operand" "r,m")) )]
   ""
-  "@
-    lr  r%0,r%1 ;extendqihi2\;dsra r%0,16
-    l   r%0,%1  ;extendqihi2\;dsra r%0,16
-    lim r%0,%1  ;extendqihi2\;dsra r%0,16 ")
+  "*
+    if (which_alternative == 0)
+      {
+        if (REGNO (operands [0]) != REGNO (operands [1]))
+          output_asm_insn (\"lr r%0,r%1\", operands);
+      }
+    else
+      output_asm_insn (\"l  r%0,%1\", operands);
+    return \"dsra r%0,16  ;extendqihi2\";
+  ")
 
 
 ;; Conversions between float and double.
 ; 1750 HF-to-TQF extend: just append 16 bits (least signif.) with all bits zero
 (define_insn "extendhftqf2"
   [(set (match_operand:TQF 0 "register_operand" "=r,r")
-        (float_extend:TQF
-         (match_operand:HF 1 "general_operand" "r,m")))]
+        (float_extend:TQF (match_operand:HF 1 "general_operand" "r,m")))]
   ""
   "*
+    output_asm_insn(\"xorr r%t0,r%t0   ;extendhftqf2\", operands);
+    if (which_alternative == 0)
       {
-        REGNO(operands[0]) += 2;
-        output_asm_insn(\"xorr r%0,r%0   ;extendhftqf2\",operands);
-        REGNO(operands[0]) -= 2;
-        if (which_alternative == 0)
+        if (REGNO (operands[1]) != REGNO (operands[0]))
           return \"dlr r%0,r%1\";
         else
-          return \"dl  r%0,%1\";
-      } ")
+          return \";\";
+      }
+    else
+      return \"dl  r%0,%1\";
+   ")
 
 ; 1750 TQF-to-HF truncate is a no-op: just leave away the least signif. 16 bits
 (define_insn "trunctqfhf2"
 
 ;; 16-bit moves
 
+; memory indirect to reg
+(define_insn ""
+  [(set (match_operand:QI 0 "register_operand" "=r")
+        (mem:QI (match_operand 1 "memory_operand"  "m")))]
+  ""
+  "li   r%0,%1")
+
+; reg/const to memory indirect
+(define_insn ""
+  [(set (mem:QI (match_operand 0 "memory_operand" "=m,m"))
+        (match_operand:QI 1 "nonmemory_operand"  "r,K"))]
+  ""
+  "@
+     sti  r%1,%0
+     stci %1,%0")
+
+; general case
 (define_insn "movqi"
-  [(set (match_operand:QI 0 "general_operand" "=r,r,r,r,r,r,r,m,m")
-        (match_operand:QI 1 "general_operand"  "O,I,J,M,i,r,m,r,K"))]
+  [(set (match_operand:QI 0 "general_operand" "=r,r,r,r,r,r,m,m")
+        (match_operand:QI 1 "general_operand"  "O,I,J,i,r,m,r,K"))]
   ""
   "@
      xorr r%0,r%0
      lisp r%0,%1
      lisn r%0,%J1
-     lim  r%0,%1  ; 'M' constraint
-     lim  r%0,%1  ; 'i' constraint
+     lim  r%0,%1
      lr   r%0,r%1
      l    r%0,%1
      st   r%1,%0
 
 ;; 32-bit moves
 
-;; Set HIreg to constant
+; memory indirect to reg
 (define_insn ""
   [(set (match_operand:HI 0 "register_operand" "=r")
-        (match_operand    1 "immediate_operand" "i"))]
+        (mem:HI (match_operand 1 "memory_operand"  "m")))]
   ""
-  "*
-    if (GET_CODE(operands[1]) == CONST_INT)
-      {
-        int val = INTVAL(operands[1]);
-        if (val >= 0)
-          {
-            if (val <= 65535)
-              {
-                output_asm_insn(\"xorr   r%0,r%0 ;movhi cst->reg\",operands);
-                operands[0] = gen_rtx(REG,QImode,REGNO(operands[0]) + 1);
-                if (val == 0)
-                  return \"xorr r%0,r%0\";
-                else if (val <= 16)
-                  return \"lisp r%0,%1\";
-                else
-                  return \"lim  r%0,%1\";
-              }
-          }
-        else if (val >= -16)
-          return \"lisn r%0,%J1\;dsra r%0,16 ;movhi cst\";
-        INTVAL(operands[1]) >>= 16;
-        output_asm_insn(\"lim r%0,%1 ;movhi cst->reg\",operands);
-        REGNO(operands[0]) += 1;
-        INTVAL(operands[1]) = val & 0xFFFF;
-        return \"lim r%0,%1\";
-      }
-    return \"lim r%0,%1\;dsra r%0,16 ;movhi cst\";
-  ")
+  "dli  r%0,%1")
 
-(define_insn "movhi"
-  [(set (match_operand:HI 0 "general_operand" "=r,r,m")
-        (match_operand:HI 1 "general_operand"  "r,m,r"))]
+; reg to memory indirect
+(define_insn ""
+  [(set (mem:HI (match_operand 0 "memory_operand" "=m"))
+        (match_operand:HI 1 "register_operand"  "r"))]
   ""
-  "@
-    dlr r%0,r%1
-    dl  r%0,%1
-    dst r%1,%0 ")
+  "dsti r%1,%0")
 
+; general case
+(define_insn ""
+  [(set (match_operand:HI 0 "general_operand" "=r,r,r,r,r,m,m")
+        (match_operand:HI 1 "general_operand"  "O,I,J,r,m,r,K"))]
+  ""
+  "@
+    xorr r%0,r%0\;xorr r%d0,r%d0
+    xorr r%0,r%0\;lisp r%d0,%1
+    lisn r%0,1  \;lisn r%d0,%J1
+    dlr  r%0,r%1
+    dl   r%0,%1
+    dst  r%1,%0
+    stc  0,%0   \;stc  %1,%A0 ")
+
+(define_expand "movhi"
+  [(set (match_operand:HI 0 "general_operand" "=g")
+        (match_operand:HI 1 "general_operand"  "g"))]
+  ""
+  "
+   {
+     rtx op1 = operands[1];
+     if (GET_CODE (operands[0]) == MEM)
+       {
+         if (GET_CODE (op1) == MEM
+            || (GET_CODE (op1) == CONST_INT
+                && (INTVAL (op1) < 0 || INTVAL (op1) > 15)))
+          operands[1] = force_reg (HImode, operands[1]);
+       }
+     else if (GET_CODE (op1) == CONST_INT
+             && (INTVAL (op1) < -16 || INTVAL (op1) > 16))
+       operands[1] = force_const_mem (HImode, operands[1]);
+   }")
 
-;; Single-Float moves are *same* as HImode moves:
 
-;(define_insn "movhf"
-;  [(set (match_operand:HF 0 "general_operand" "=r,r,r,m")
-;        (match_operand:HF 1 "general_operand"  "F,r,m,r"))]
-;  ""
-;  "@
-;    %D1\;dl r%0,%F1
-;    dlr r%0,r%1
-;    dl  r%0,%1
-;    dst r%1,%0 ")
+;; Single-Float moves
 
-(define_insn "movhf"
-  [(set (match_operand:HF 0 "general_operand" "=r,r,m")
-        (match_operand:HF 1 "general_operand"  "r,m,r"))]
+(define_insn ""
+  [(set (match_operand:HF 0 "general_operand" "=r,r,m,m")
+        (match_operand:HF 1 "general_operand"  "r,m,r,G"))]
   ""
   "@
-    dlr r%0,r%1
-    dl  r%0,%1
-    dst r%1,%0 ")
+    dlr  r%0,r%1
+    dl   r%0,%1
+    dst  r%1,%0
+    stc  0,%0   \;stc 0,%A0 ")
+
+(define_expand "movhf"
+  [(set (match_operand:HF 0 "general_operand" "")
+        (match_operand:HF 1 "general_operand" ""))]
+  ""
+  "
+   {
+     enum rtx_code op1code = GET_CODE (operands[1]);
+     if (GET_CODE (operands[0]) == MEM)
+       {
+         if (op1code == MEM || (op1code == CONST_DOUBLE
+             && !rtx_equal_p (operands[1], CONST0_RTX (HFmode))))
+          operands[1] = force_reg (HFmode, operands[1]);
+       }
+     else if (op1code == CONST_DOUBLE)
+       operands[1] = force_const_mem (HFmode, operands[1]);
+   }")
 
 
 ;; Longfloat moves
 
-;(define_insn "movtqf"
-;  [(set (match_operand:TQF 0 "general_operand" "=r,r,r,m")
-;        (match_operand:TQF 1 "general_operand"  "F,r,m,r"))]
-;  ""
-;  "@
-;    %E1\;efl r%0,%G1
-;    eflr.m %0,%1
-;    efl  r%0,%1
-;    efst r%1,%0 ")
-
-(define_insn "movtqf"
+(define_insn ""
   [(set (match_operand:TQF 0 "general_operand" "=r,r,m")
         (match_operand:TQF 1 "general_operand"  "r,m,r"))]
   ""
     efl  r%0,%1
     efst r%1,%0 ")
 
+(define_expand "movtqf"
+  [(set (match_operand:TQF 0 "general_operand" "")
+        (match_operand:TQF 1 "general_operand" ""))]
+  ""
+  "
+   {
+     enum rtx_code op1code = GET_CODE (operands[1]);
+     if (GET_CODE (operands[0]) == MEM)
+       {
+         if (op1code == MEM || op1code == CONST_DOUBLE)
+          operands[1] = force_reg (TQFmode, operands[1]);
+       }
+     else if (op1code == CONST_DOUBLE)
+       operands[1] = force_const_mem (TQFmode, operands[1]);
+   }")
+
 
 ;; add instructions 
 
 ;; single integer
 
-;; Use "LIM Ra,sym,Rb" for adding a symbol value to a register and
-;; transferring the result to a different register.
-;(define_insn ""
-;  [(set (match_operand:QI 0 "register_operand" "=r")
-;        (plus:QI (match_operand:QI 1 "register_operand" "b")
-;                 (match_operand:QI 2 "immediate_operand"  "i")))]
-;   "REGNO(operands[0]) != REGNO(operands[1])"
-;   "lim r%0,%2,r%1 ;md special addqi")
-
 (define_insn "addqi3"
   [(set (match_operand:QI 0 "general_operand" "=r,r,r,r,r,m,m")
         (plus:QI (match_operand:QI 1 "general_operand" "%0,0,0,0,0,0,0")
           return \"incm %2,%0\";
         case 6:
           return \"decm %J2,%0\";
+       default:
+         abort();
       } ")
 
 ;; double integer
 (define_insn "addhf3"
   [(set (match_operand:HF 0 "register_operand" "=r,r")
         (plus:HF (match_operand:HF 1 "register_operand" "%0,0")
-                 (match_operand:HF 2 "general_operand" "m,r")))]
+                 (match_operand:HF 2 "general_operand" "r,m")))]
   ""
   "@
-    fa  r%0,%2
-    far r%0,r%2 ")
+    far r%0,r%2
+    fa  r%0,%2 ")
 
 (define_insn "addtqf3"
   [(set (match_operand:TQF 0 "register_operand" "=r,r")
         (plus:TQF (match_operand:TQF 1 "register_operand" "%0,0")
-                 (match_operand:TQF 2 "general_operand" "m,r")))]
+                 (match_operand:TQF 2 "general_operand" "r,m")))]
   ""
   "@
-    efa  r%0,%2
-    efar r%0,r%2 ")
+    efar r%0,r%2
+    efa  r%0,%2 ")
 
 
 ;; subtract instructions
 ; 32-bit product
 (define_insn "mulqihi3"
   [(set (match_operand:HI 0 "register_operand" "=r,r,r")
-        (mult:HI (match_operand:QI 1 "register_operand" "%0,0,0")
-                 (match_operand:QI 2 "general_operand" "M,r,m")))]
+    (mult:HI (sign_extend:HI (match_operand:QI 1 "register_operand" "%r,r,r"))
+             (sign_extend:HI (match_operand:QI 2 "general_operand" "r,m,i"))))]
   ""
-  "@
-    mim r%0,%1
-    mr  r%0,r%2
-    m   r%0,%2 ")
+  "*
+    if (REGNO (operands[1]) != REGNO (operands[0]))
+      output_asm_insn (\"lr r%0,r%1\", operands);
+
+    switch (which_alternative)
+      {
+      case 0:
+        return \"mr  r%0,r%2\";
+      case 1:
+        return \"m   r%0,%2\";
+      case 2:
+        return \"mim r%0,%2\";
+      default:
+        abort();
+      }
+  ")
+
 
 (define_insn "mulhi3"
   [(set (match_operand:HI 0 "register_operand" "=r,r")
   ""
   "*
    {
-     char *istr;
+     const char *istr;
      switch(which_alternative)
        {
        case 0:
          istr = \"disp\";
          break;
        case 1:
-         INTVAL(operands[2]) = - INTVAL(operands[2]); /* to be corrected */
-         istr = \"disn\";
+        {
+          rtx new_opnds[4];
+          new_opnds[0] = operands[0];
+          new_opnds[1] = operands[1];
+          new_opnds[2] = GEN_INT (-INTVAL(operands[2]));
+          new_opnds[3] = operands[3];
+           istr = \"disn\";
+          return mod_regno_adjust (istr, new_opnds);
+        }
          break;
        case 2:
          istr = \"dvim\";
          istr = \"dv  \";
          break;
       }
-      return (char *)mod_regno_adjust(istr,operands);
+      return mod_regno_adjust (istr, operands);
      }")
 
 ;; Division for other types is straightforward.
         (neg:TQF (match_operand:TQF 1 "register_operand" "r")))]
   ""
   "
-   emit_insn(gen_rtx(SET,VOIDmode,operands[0],CONST0_RTX(TQFmode)));
-   emit_insn(gen_rtx(SET,VOIDmode,operands[0],
-             gen_rtx(MINUS,TQFmode,operands[0],operands[1])));
+   emit_insn (gen_rtx_SET (VOIDmode, operands[0], CONST0_RTX (TQFmode)));
+   emit_insn (gen_rtx_SET (VOIDmode, operands[0],
+                          gen_rtx_MINUS (TQFmode, operands[0], operands[1])));
    DONE;
   ")
 
 
 ;; bit-logical instructions
 
+;; Set Bit
+(define_insn ""
+  [(set (match_operand:QI 0 "general_operand" "=r,m")
+        (ior:QI  (match_operand:QI 1 "general_operand" "0,0")
+                 (match_operand:QI 2 "const_int_operand" "i,i")))]
+  "one_bit_set_p (INTVAL (operands [2]))"
+  "@
+    sbr    %b2,r%0
+    sb     %b2,%0")
+
+;; Reset Bit
+(define_insn ""
+  [(set (match_operand:QI 0 "general_operand" "=r,m")
+        (and:QI  (match_operand:QI 1 "general_operand" "0,0")
+                 (match_operand:QI 2 "const_int_operand" "i,i")))]
+  "one_bit_set_p ((~INTVAL (operands [2])) & 0xffff)"
+  "@
+    rbr    %B2,r%0
+    rb     %B2,%0")
+
+;; Set Variable Bit
+(define_insn ""
+  [(set (match_operand:QI 0 "register_operand" "=r")
+        (ior:QI  (match_operand:QI 1 "register_operand" "0")
+                 (lshiftrt:QI (const_int 32768)
+                      (match_operand:QI 2 "register_operand" "r"))))]
+  ""
+  "svbr   r%2,%r0")
+
+;; Reset Variable Bit
+(define_insn ""
+  [(set (match_operand:QI 0 "general_operand" "=r")
+        (and:QI  (match_operand:QI 1 "general_operand" "0")
+            (not:QI (lshiftrt:QI (const_int 32768)
+                        (match_operand:QI 2 "register_operand" "r")))))]
+  ""
+  "rvbr   r%2,%r0")
+
+
 ;; AND
 
 (define_insn "andqi3"
 (define_insn "iorqi3"
   [(set (match_operand:QI 0 "general_operand" "=r,r,r")
         (ior:QI  (match_operand:QI 1 "general_operand" "%0,0,0")
-                (match_operand:QI 2 "general_operand" "M,r,m")))]
+                 (match_operand:QI 2 "general_operand" "M,r,m")))]
   ""
   "@
     orim r%0,%2
 
 ; (What to the 1750 is logical-shift-left, GCC likes to call "arithmetic")
 (define_insn "ashlqi3"
-  [(set (match_operand:QI 0 "register_operand" "=r,r,r")
-        (ashift:QI (match_operand:QI 1 "register_operand" "0,0,0")
-                   (match_operand:QI 2 "general_operand" "O,I,r")))]
+  [(set (match_operand:QI 0 "register_operand" "=r,r")
+        (ashift:QI (match_operand:QI 1 "register_operand" "0,0")
+                   (match_operand:QI 2 "nonmemory_operand" "I,r")))]
   ""
   "@
-    ; optimized away an SLL r%0,0
     sll r%0,%2
     slr r%0,r%2 ")
 
 (define_insn "ashlhi3"
   [(set (match_operand:HI 0 "register_operand" "=r,r")
         (ashift:HI (match_operand:HI 1 "register_operand" "0,0")
-                   (match_operand:QI 2 "general_operand" "L,r")))]
+                   (match_operand:QI 2 "nonmemory_operand" "L,r")))]
   ""                        ; the 'L' constraint is a slight imprecise...
-  "@
-     dsll r%0,%2
-     dslr r%0,r%2 ")
+  "*
+    if (which_alternative == 1)
+      return \"dslr r%0,r%2\";
+    else if (INTVAL(operands[2]) <= 16)
+      return \"dsll r%0,%2\";
+    else
+      {
+        output_asm_insn (\"dsll r%0,16  ; ashlhi3 shiftcnt > 16\", operands);
+        return \"sll r%0,%w2\";
+      }
+  ")
 
-(define_insn "lshrqi3"
-  [(set (match_operand:QI 0 "register_operand" "=r,r")
-        (lshiftrt:QI (match_operand:QI 1 "register_operand" "0,0")
-                     (match_operand:QI 2 "general_operand" "I,r")))]
+
+;; Right shift by a variable shiftcount works by negating the shift count,
+;; then emitting a right shift with the shift count negated.  This means
+;; that all actual shift counts in the RTL will be positive.  This 
+;; prevents converting shifts to ZERO_EXTRACTs with negative positions,
+;; which isn't valid.
+(define_expand "lshrqi3"
+  [(set (match_operand:QI 0 "register_operand" "=r")
+       (lshiftrt:QI (match_operand:QI 1 "register_operand" "0")
+                    (match_operand:QI 2 "nonmemory_operand" "g")))]
   ""
-  "@
-    srl r%0,%2
-    neg r%2,r%2\;slr    r%0,r%2 ")
+  "
+{
+  if (GET_CODE (operands[2]) != CONST_INT)
+    operands[2] = gen_rtx_NEG (QImode, negate_rtx (QImode, operands[2]));
+}")
 
-(define_insn "lshrhi3"
-  [(set (match_operand:HI 0 "register_operand" "=r,r")
-        (lshiftrt:HI (match_operand:HI 1 "register_operand" "0,0")
-                     (match_operand:QI 2 "general_operand" "L,r")))]
-  ""                        ; the 'L' constraint is a slight imprecise...
-  "@
-    dsrl r%0,%2
-    neg  r%2,r%2\;dslr   r%0,r%2 ")
+(define_insn ""
+  [(set (match_operand:QI 0 "register_operand" "=r")
+       (lshiftrt:QI (match_operand:QI 1 "register_operand" "0")
+                    (match_operand:QI 2 "immediate_operand" "I")))]
+  ""
+  "srl r%0,%2")
 
-(define_insn "ashrqi3"
-  [(set (match_operand:QI 0 "register_operand" "=r,r")
-        (ashiftrt:QI (match_operand:QI 1 "register_operand" "0,0")
-                     (match_operand:QI 2 "general_operand" "I,r")))]
+(define_insn ""
+  [(set (match_operand:QI 0 "register_operand" "=r")
+       (lshiftrt:QI (match_operand:QI 1 "register_operand" "0")
+                    (neg:QI (match_operand:QI 2 "register_operand" "r"))))]
   ""
-  "@
-     sra r%0,%2
-     neg r%2,r%2\;sar    r%0,r%2 ")
+  "slr r%0,r%2 ")
 
-(define_insn "ashrhi3"
-  [(set (match_operand:HI 0 "register_operand" "=r,r")
-        (ashiftrt:HI (match_operand:HI 1 "register_operand" "0,0")
-                     (match_operand:QI 2 "general_operand" "I,r")))]
+;; Same thing for HImode.
+
+(define_expand "lshrhi3"
+  [(set (match_operand:HI 0 "register_operand" "=r")
+       (lshiftrt:HI (match_operand:HI 1 "register_operand" "0")
+                    (match_operand:QI 2 "nonmemory_operand" "g")))]
   ""
-  "@
-     dsra r%0,%2
-     neg  r%2,r%2\;dsar   r%0,r%2 ")
+  "
+  {
+    if (GET_CODE (operands[2]) != CONST_INT)
+      operands[2] = gen_rtx_NEG (QImode, negate_rtx (QImode, operands[2]));
+  }")
+
+(define_insn ""
+  [(set (match_operand:HI 0 "register_operand" "=r")
+       (lshiftrt:HI (match_operand:HI 1 "register_operand" "0")
+                    (match_operand:QI 2 "immediate_operand" "L")))]
+  ""
+  "*
+    if (INTVAL (operands[2]) <= 16)
+      return \"dsrl r%0,%2\";
+    output_asm_insn (\"dsrl r%0,16  ; lshrhi3 shiftcount > 16\", operands);
+    return \"srl  r%d0,%w2\";
+  ")
+
+(define_insn ""
+  [(set (match_operand:HI 0 "register_operand" "=r")
+       (lshiftrt:HI (match_operand:HI 1 "register_operand" "0")
+                    (neg:QI (match_operand:QI 2 "register_operand" "r"))))]
+  ""
+  "dslr r%0,r%2 ")
+
+;; Same applies for arithmetic shift right.
+(define_expand "ashrqi3"
+  [(set (match_operand:QI 0 "register_operand" "=r")
+       (ashiftrt:QI (match_operand:QI 1 "register_operand" "0")
+                    (match_operand:QI 2 "nonmemory_operand" "g")))]
+  ""
+  "
+  {
+    if (GET_CODE (operands[2]) != CONST_INT)
+      operands[2] = gen_rtx_NEG (QImode, negate_rtx (QImode, operands[2]));
+  }")
+
+(define_insn ""
+  [(set (match_operand:QI 0 "register_operand" "=r")
+       (ashiftrt:QI (match_operand:QI 1 "register_operand" "0")
+                    (match_operand:QI 2 "immediate_operand" "I")))]
+  ""
+  "sra r%0,%2")
+
+(define_insn ""
+  [(set (match_operand:QI 0 "register_operand" "=r")
+       (ashiftrt:QI (match_operand:QI 1 "register_operand" "0")
+                    (neg:QI (match_operand:QI 2 "register_operand" "r"))))]
+  ""
+  "sar r%0,r%2 ")
+
+;; HImode arithmetic shift right.
+(define_expand "ashrhi3"
+  [(set (match_operand:HI 0 "register_operand" "=r")
+       (ashiftrt:HI (match_operand:HI 1 "register_operand" "0")
+                    (match_operand:QI 2 "nonmemory_operand" "g")))]
+  ""
+  "
+  {
+    if (GET_CODE (operands[2]) != CONST_INT)
+      operands[2] = gen_rtx_NEG (QImode, negate_rtx (QImode, operands[2]));
+  }")
+
+(define_insn ""
+  [(set (match_operand:HI 0 "register_operand" "=r")
+       (ashiftrt:HI (match_operand:HI 1 "register_operand" "0")
+                    (match_operand:QI 2 "immediate_operand" "L")))]
+  ""
+  "*
+    if (INTVAL (operands[2]) <= 16)
+      return \"dsra r%0,%2\";
+    output_asm_insn (\"dsra r%0,16  ; ashrhi3 shiftcount > 16\", operands);
+    return \"sra  r%d0,%w2\";
+  ")
+
+(define_insn ""
+  [(set (match_operand:HI 0 "register_operand" "=r")
+       (ashiftrt:HI (match_operand:HI 1 "register_operand" "0")
+                    (neg:QI (match_operand:QI 2 "register_operand" "r"))))]
+  ""
+  "dsar r%0,r%2 ")
 
 
 ;; rotate instructions
 (define_insn "rotlqi3"
   [(set (match_operand:QI 0 "register_operand" "=r,r")
         (rotate:QI (match_operand:QI 1 "register_operand" "0,0")
-                   (match_operand:QI 2 "general_operand" "I,r")))]
+                   (match_operand:QI 2 "nonmemory_operand" "I,r")))]
   ""
   "@
     slc r%0,%2
 (define_insn "rotlhi3"
   [(set (match_operand:HI 0 "register_operand" "=r,r")
         (rotate:HI (match_operand:HI 1 "register_operand" "0,0")
-                   (match_operand:QI 2 "general_operand" "I,r")))]
+                   (match_operand:QI 2 "nonmemory_operand" "I,r")))]
   ""
   "@
     dslc r%0,%2
 (define_insn "rotrhi3"
   [(set (match_operand:HI 0 "register_operand" "=r")
         (rotatert:HI (match_operand:HI 1 "register_operand" "0")
-                     (match_operand:QI 2 "general_operand" "r")))]
+                     (match_operand:QI 2 "nonmemory_operand" "r")))]
   ""
   "neg  r%2,r%2\;dscr r%0,r%2 ")
 
                       (label_ref (match_operand 0 "" ""))
                       (pc)))]
   ""
-  "* return (char *)branch_or_jump(\"ez\",CODE_LABEL_NUMBER(operands[0]));
+  "* return branch_or_jump (\"ez\", CODE_LABEL_NUMBER (operands[0]));
   ")
 
 (define_insn "bne"
                       (label_ref (match_operand 0 "" ""))
                       (pc)))]
   ""
-  "* return (char *)branch_or_jump(\"nz\",CODE_LABEL_NUMBER(operands[0]));
+  "* return branch_or_jump (\"nz\", CODE_LABEL_NUMBER (operands[0]));
   ")
 
 (define_insn "bgt"
                       (label_ref (match_operand 0 "" ""))
                       (pc)))]
   ""
-  "* return (char *)branch_or_jump(\"gt\",CODE_LABEL_NUMBER(operands[0]));
+  "* return branch_or_jump (\"gt\", CODE_LABEL_NUMBER (operands[0]));
   ")
 
 (define_insn "blt"
                       (label_ref (match_operand 0 "" ""))
                       (pc)))]
   ""
-  "* return (char *)branch_or_jump(\"lt\",CODE_LABEL_NUMBER(operands[0]));
+  "* return branch_or_jump (\"lt\", CODE_LABEL_NUMBER (operands[0]));
   ")
 
 (define_insn "bge"
                       (label_ref (match_operand 0 "" ""))
                       (pc)))]
   ""
-  "* return (char *)branch_or_jump(\"ge\",CODE_LABEL_NUMBER(operands[0]));
+  "* return branch_or_jump (\"ge\", CODE_LABEL_NUMBER (operands[0]));
   ")
 
 (define_insn "ble"
                       (label_ref (match_operand 0 "" ""))
                       (pc)))]
   ""
-  "* return (char *)branch_or_jump(\"le\",CODE_LABEL_NUMBER(operands[0]));
+  "* return branch_or_jump (\"le\", CODE_LABEL_NUMBER (operands[0]));
   ")
 
 
                       (pc)
                       (label_ref (match_operand 0 "" ""))))]
   ""
-  "* return (char *)branch_or_jump(\"nz\",CODE_LABEL_NUMBER(operands[0]));
+  "* return branch_or_jump (\"nz\", CODE_LABEL_NUMBER (operands[0]));
   ")
 
 (define_insn ""
                       (pc)
                       (label_ref (match_operand 0 "" ""))))]
   ""
-  "* return (char *)branch_or_jump(\"ez\",CODE_LABEL_NUMBER(operands[0]));
+  "* return branch_or_jump (\"ez\", CODE_LABEL_NUMBER (operands[0]));
   ")
 
 (define_insn ""
                       (pc)
                       (label_ref (match_operand 0 "" ""))))]
   ""
-  "* return (char *)branch_or_jump(\"le\",CODE_LABEL_NUMBER(operands[0]));
+  "* return branch_or_jump (\"le\", CODE_LABEL_NUMBER (operands[0]));
   ")
 
 (define_insn ""
                       (pc)
                       (label_ref (match_operand 0 "" ""))))]
   ""
-  "* return (char *)branch_or_jump(\"ge\",CODE_LABEL_NUMBER(operands[0]));
+  "* return branch_or_jump (\"ge\", CODE_LABEL_NUMBER (operands[0]));
   ")
 
 (define_insn ""
                       (pc)
                       (label_ref (match_operand 0 "" ""))))]
   ""
-  "* return (char *)branch_or_jump(\"lt\",CODE_LABEL_NUMBER(operands[0]));
+  "* return branch_or_jump (\"lt\", CODE_LABEL_NUMBER (operands[0]));
   ")
 
 (define_insn ""
                       (pc)
                       (label_ref (match_operand 0 "" ""))))]
   ""
-  "* return (char *)branch_or_jump(\"gt\",CODE_LABEL_NUMBER(operands[0]));
+  "* return branch_or_jump (\"gt\", CODE_LABEL_NUMBER (operands[0]));
   ")
 
 
 ;; Call subroutine, returning value in operand 0
 ;; (which must be a hard register).
 (define_insn "call_value"
-  [(set (match_operand 0 "register_operand" "r")
+  [(set (match_operand 0 "register_operand" "=r")
         (call (match_operand:QI 1 "memory_operand" "m")
               (match_operand:QI 2 "general_operand" "g")))]
   ;; Operand 2 not really used for 1750.
   ""
   "ANYCALL %0")
 
-
-; (define_insn "return"
-;   [(return)]
-;   ""
-;   "*
-;    { 
-;         rtx oprnd = gen_rtx(CONST_INT,VOIDmode,get_frame_size());
-;         output_asm_insn(\"ret.m  %0\",&oprnd);
-;         return \"\;\";
-;    } ")
-
 (define_insn "indirect_jump"
   [(set (pc) (match_operand:QI 0 "address_operand" "p"))]
   ""
   "INTVAL(operands[2]) == -1"
   "soj r%0,%3")
 
-;; Load Base
+;; Combine a Load Register with subsequent increment/decrement into a LIM
 (define_peephole 
   [(set (match_operand:QI 0 "register_operand" "=r")
-        (mem:QI (plus:QI (match_operand:QI 1 "register_operand" "x")
-                         (match_operand:QI 2 "immediate_operand" "L"))))
-   ]
-  "REGNO(operands[0]) == 2 && REGNO(operands[1]) >= 12
-    && INTVAL(operands[2]) <= 255"
-  "lb r%1,%2")
-
-;; Double Load Base
-(define_peephole 
-  [(set (match_operand:HI 0 "register_operand" "=r")
-        (mem:HI (plus:QI (match_operand:QI 1 "register_operand" "x")
-                         (match_operand:QI 2 "immediate_operand" "L"))))
-   ]
-  "REGNO(operands[0]) == 0 && REGNO(operands[1]) >= 12
-    && INTVAL(operands[2]) <= 255"
-  "dlb r%1,%2")
-
-(define_peephole 
-  [(set (match_operand:HF 0 "register_operand" "=r")
-        (mem:HF (plus:QI (match_operand:QI 1 "register_operand" "x")
-                         (match_operand:QI 2 "immediate_operand" "L"))))
-   ]
-  "REGNO(operands[0]) == 0 && REGNO(operands[1]) >= 12
-    && INTVAL(operands[2]) <= 255"
-  "dlb r%1,%2")
-
-;; Store Base
-(define_peephole 
-  [(set (mem:QI (plus:QI (match_operand:QI 0 "register_operand" "x")
-                         (match_operand:QI 1 "immediate_operand" "L")))
-       (match_operand:QI 2 "register_operand" "r"))
-   ]
-  "REGNO(operands[2]) == 2 && REGNO(operands[0]) >= 12
-    && INTVAL(operands[1]) <= 255"
-  "stb r%0,%1")
-
-;; Double Store Base
-(define_peephole 
-  [(set (mem:HI (plus:QI (match_operand:QI 0 "register_operand" "x")
-                         (match_operand:QI 1 "immediate_operand" "L")))
-       (match_operand:HI 2 "register_operand" "r"))
-   ]
-  "REGNO(operands[2]) == 0 && REGNO(operands[0]) >= 12
-    && INTVAL(operands[1]) <= 255"
-  "dstb r%0,%1")
-
-(define_peephole 
-  [(set (mem:HF (plus:QI (match_operand:QI 0 "register_operand" "x")
-                         (match_operand:QI 1 "immediate_operand" "L")))
-       (match_operand:HF 2 "register_operand" "r"))
-   ]
-  "REGNO(operands[2]) == 0 && REGNO(operands[0]) >= 12
-    && INTVAL(operands[1]) <= 255"
-  "dstb r%0,%1")
+        (match_operand:QI 1 "register_operand" "b"))
+   (set (match_dup 0)
+        (plus:QI (match_dup 0)
+                 (match_operand:QI 2 "immediate_operand" "i")))]
+  "REGNO(operands[1]) > 0"
+  "lim r%0,%2,r%1  ; LR,inc/dec peephole")
 
 ;; Eliminate the redundant load in a store/load sequence
 (define_peephole 
   [(set (mem:QI (plus:QI (match_operand:QI 0 "register_operand" "r")
-                         (match_operand:QI 1 "immediate_operand" "i")))
+                         (match_operand:QI 1 "immediate_operand" "i")))
        (match_operand:QI 2 "register_operand" "r"))
    (set (match_operand:QI 3 "register_operand" "=r")
-       (mem:QI (plus:QI (match_operand:QI 4 "register_operand" "r")
-                        (match_operand:QI 5 "immediate_operand" "i"))))
+       (mem:QI (plus:QI (match_dup 0)
+                        (match_dup 1))))
    ]
-  "REGNO(operands[2]) == REGNO(operands[3]) &&
-   REGNO(operands[0]) == REGNO(operands[4]) &&
-   INTVAL(operands[1]) == INTVAL(operands[5])"
+  "REGNO(operands[2]) == REGNO(operands[3])"
   "st r%2,%1,r%0  ; eliminated previous redundant load")
 
 ;;;End.
-