OSDN Git Service

* rs6000.c (print_operand, case 'T'): New case.
authordje <dje@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 25 Jul 2000 18:46:54 +0000 (18:46 +0000)
committerdje <dje@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 25 Jul 2000 18:46:54 +0000 (18:46 +0000)
* rs6000.md (call_indirect_aix32): Convert to expander of
scheduled instructions.
(call_indirect_aix64): Likewise.
(call_value_indirect_aix{32,64}): Likewise.
(call, call_value): Invoke expanders for AIX.  Fall through to
matchers for SysV.
(call_indirect_nonlocal_aix{32,64}): New patterns (ctr and lr).
(call_value_indirect_nonlocal_aix{32,64}): New patterns.
(call_nonlocal_aix32): Remove CALL_LONG alternative.  Operand 1
only "g" constraint.
(call_nonlocal_aix64): Likewise.
(call_value_nonlocal_aix{32,64}): Likewise.
(call_nonlocal_sysv): New pattern for ctr, lr, and symbolic
operands.
(call_value_nonlocal_sysv): New pattern.
(indirect_jump{si,di}): Use new 'T' modifier.
(tablejump{si,di} matchers): Likewise.
(return_internal_{si,di}): Likewise.
(return_eh_{si,di}): Likewise.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@35246 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/config/rs6000/rs6000.c
gcc/config/rs6000/rs6000.md

index f8c0441..d391b95 100644 (file)
@@ -1,3 +1,27 @@
+2000-07-25  David Edelsohn  <edelsohn@gnu.org>
+
+       * rs6000.c (print_operand, case 'T'): New case.
+
+       * rs6000.md (call_indirect_aix32): Convert to expander of
+       scheduled instructions.
+       (call_indirect_aix64): Likewise.
+       (call_value_indirect_aix{32,64}): Likewise.
+       (call, call_value): Invoke expanders for AIX.  Fall through to
+       matchers for SysV.
+       (call_indirect_nonlocal_aix{32,64}): New patterns (ctr and lr).
+       (call_value_indirect_nonlocal_aix{32,64}): New patterns.
+       (call_nonlocal_aix32): Remove CALL_LONG alternative.  Operand 1
+       only "g" constraint.
+       (call_nonlocal_aix64): Likewise.
+       (call_value_nonlocal_aix{32,64}): Likewise.
+       (call_nonlocal_sysv): New pattern for ctr, lr, and symbolic
+       operands.
+       (call_value_nonlocal_sysv): New pattern.
+       (indirect_jump{si,di}): Use new 'T' modifier.
+       (tablejump{si,di} matchers): Likewise.
+       (return_internal_{si,di}): Likewise.
+       (return_eh_{si,di}): Likewise.
+
 2000-07-24  Richard Henderson  <rth@cygnus.com>
 
        * config/ia64/ia64.c (ia64_print_operand): Handle "%,".
index 5c41141..623a47d 100644 (file)
@@ -3984,6 +3984,7 @@ print_operand (file, x, code)
           mask begins at 63 - i from left */
          if (i > 63)
            output_operand_lossage ("%%S computed all 1's mask");
+
          fprintf (file, "%d", 63 - i);
          return;
        }
@@ -4010,10 +4011,23 @@ print_operand (file, x, code)
           mask ends at 62 - i from left */
          if (i > 62)
            output_operand_lossage ("%%S computed all 0's mask");
+
          fprintf (file, "%d", 62 - i);
          return;
        }
 
+    case 'T':
+      /* Print the symbolic name of a branch target register.  */
+      if (GET_CODE (x) != REG || (REGNO (x) != LINK_REGISTER_REGNUM
+                                 && REGNO (x) != COUNT_REGISTER_REGNUM))
+       output_operand_lossage ("invalid %%T value");
+
+      if (REGNO (x) == LINK_REGISTER_REGNUM)
+       fputs (TARGET_NEW_MNEMONICS ? "lr" : "r", file);
+      else
+       fputs ("ctr", file);
+      return;
+
     case 'u':
       /* High-order 16 bits of constant for use in unsigned operand.  */
       if (! INT_P (x))
index 4dfe6ba..52ef798 100644 (file)
@@ -9298,122 +9298,96 @@ operands[2] = GEN_INT (INTVAL (operands[1]) >> 32);
 ;; pointer to its TOC, and whose third word contains a value to place in the
 ;; static chain register (r11).  Note that if we load the static chain, our
 ;; "trampoline" need not have any executable code.
-;;
-;; operands[0] is a register pointing to the 3 word descriptor (aka, the function address)
-;; operands[1] is the stack size to clean up
-;; operands[2] is the value FUNCTION_ARG returns for the VOID argument (must be 0 for AIX)
-;; operands[3] is location to store the TOC
-;; operands[4] is the TOC register
-;; operands[5] is the static chain register
-;;
-;; We do not break this into separate insns, so that the scheduler will not try
-;; to move the load of the new TOC before any loads from the TOC.
-
-(define_insn "call_indirect_aix32"
-  [(call (mem:SI (match_operand:SI 0 "gpc_reg_operand" "b"))
-        (match_operand 1 "const_int_operand" "n"))
-   (use (match_operand 2 "const_int_operand" "n"))
-   (use (match_operand 3 "offsettable_mem_operand" "o"))
-   (use (match_operand 4 "gpc_reg_operand" "r"))
-   (clobber (match_operand 5 "gpc_reg_operand" "=r"))
-   (clobber (match_scratch:SI 6 "=&r"))
-   (clobber (match_scratch:SI 7 "=l"))]
-  "DEFAULT_ABI == ABI_AIX
-   && (INTVAL (operands[2]) == CALL_NORMAL || (INTVAL (operands[2]) & CALL_LONG) != 0)"
-  "{st|stw} %4,%3\;{l|lwz} %6,0(%0)\;{l|lwz} %4,4(%0)\;mt%7 %6\;{l|lwz} %5,8(%0)\;{brl|blrl}\;{l|lwz} %4,%3"
-  [(set_attr "type" "load")
-   (set_attr "length" "28")])
-
-(define_insn "call_indirect_aix64"
-  [(call (mem:SI (match_operand:DI 0 "gpc_reg_operand" "b"))
-        (match_operand 1 "const_int_operand" "n"))
-   (use (match_operand 2 "const_int_operand" "n"))
-   (use (match_operand 3 "offsettable_mem_operand" "o"))
-   (use (match_operand 4 "gpc_reg_operand" "r"))
-   (clobber (match_operand 5 "gpc_reg_operand" "=r"))
-   (clobber (match_scratch:SI 6 "=&r"))
-   (clobber (match_scratch:SI 7 "=l"))]
-  "TARGET_64BIT && DEFAULT_ABI == ABI_AIX
-   && (INTVAL (operands[2]) == CALL_NORMAL || (INTVAL (operands[2]) & CALL_LONG) != 0)"
-  "std %4,%3\;ld %6,0(%0)\;ld %4,8(%0)\;mt%7 %6\;ld %5,16(%0)\;blrl\;ld %4,%3"
-  [(set_attr "type" "load")
-   (set_attr "length" "28")])
-
-(define_insn "call_value_indirect_aix32"
-  [(set (match_operand 0 "" "")
-       (call (mem:SI (match_operand:SI 1 "gpc_reg_operand" "b"))
-             (match_operand 2 "const_int_operand" "n")))
-   (use (match_operand 3 "const_int_operand" "n"))
-   (use (match_operand 4 "offsettable_mem_operand" "o"))
-   (use (match_operand 5 "gpc_reg_operand" "r"))
-   (clobber (match_operand 6 "gpc_reg_operand" "=r"))
-   (clobber (match_scratch:SI 7 "=&r"))
-   (clobber (match_scratch:SI 8 "=l"))]
-  "DEFAULT_ABI == ABI_AIX
-   && (INTVAL (operands[3]) == CALL_NORMAL || (INTVAL (operands[3]) & CALL_LONG) != 0)"
-  "{st|stw} %5,%4\;{l|lwz} %7,0(%1)\;{l|lwz} %5,4(%1)\;mt%8 %7\;{l|lwz} %6,8(%1)\;{brl|blrl}\;{l|lwz} %5,%4"
-  [(set_attr "type" "load")
-   (set_attr "length" "28")])
-
-(define_insn "call_value_indirect_aix64"
-  [(set (match_operand 0 "" "")
-       (call (mem:SI (match_operand:DI 1 "gpc_reg_operand" "b"))
-             (match_operand 2 "const_int_operand" "n")))
-   (use (match_operand 3 "const_int_operand" "n"))
-   (use (match_operand 4 "offsettable_mem_operand" "o"))
-   (use (match_operand 5 "gpc_reg_operand" "r"))
-   (clobber (match_operand 6 "gpc_reg_operand" "=r"))
-   (clobber (match_scratch:SI 7 "=&r"))
-   (clobber (match_scratch:SI 8 "=l"))]
-  "TARGET_64BIT && DEFAULT_ABI == ABI_AIX
-   && (INTVAL (operands[3]) == CALL_NORMAL || (INTVAL (operands[3]) & CALL_LONG) != 0)"
-  "std %5,%4\;ld %7,0(%1)\;ld %5,8(%1)\;mt%8 %7\;ld %6,16(%1)\;blrl\;ld %5,%4"
-  [(set_attr "type" "load")
-   (set_attr "length" "28")])
-
-;; A function pointer under System V is just a normal pointer
-;; operands[0] is the function pointer
-;; operands[1] is the stack size to clean up
-;; operands[2] is the value FUNCTION_ARG returns for the VOID argument which indicates how to set cr1
-
-(define_insn "call_indirect_sysv"
-  [(call (mem:SI (match_operand:SI 0 "register_operand" "l,l"))
-        (match_operand 1 "const_int_operand" "n,n"))
-   (use (match_operand 2 "const_int_operand" "O,n"))
-   (clobber (match_scratch:SI 3 "=l,l"))]
-  "DEFAULT_ABI == ABI_V4 || DEFAULT_ABI == ABI_SOLARIS || DEFAULT_ABI == ABI_AIX_NODESC"
-  "*
-{
-  if (INTVAL (operands[2]) & CALL_V4_SET_FP_ARGS)
-    output_asm_insn (\"crxor 6,6,6\", operands);
-
-  else if (INTVAL (operands[2]) & CALL_V4_CLEAR_FP_ARGS)
-    output_asm_insn (\"creqv 6,6,6\", operands);
 
-  return \"{brl|blrl}\";
-}"
-  [(set_attr "type" "jmpreg")
-   (set_attr "length" "4,8")])
+(define_expand "call_indirect_aix32"
+  [(set (match_dup 2)
+       (mem:SI (match_operand:SI 0 "gpc_reg_operand" "")))
+   (set (mem:SI (plus:SI (reg:SI 1) (const_int 20)))
+       (reg:SI 2))
+   (set (reg:SI 2)
+       (mem:SI (plus:SI (match_dup 0)
+                        (const_int 4))))
+   (set (reg:SI 11)
+       (mem:SI (plus:SI (match_dup 0)
+                        (const_int 8))))
+   (parallel [(call (mem:SI (match_dup 2))
+                   (match_operand 1 "" ""))
+             (use (reg:SI 2))
+             (use (reg:SI 11))
+             (set (reg:SI 2)
+                  (mem:SI (plus:SI (reg:SI 1) (const_int 20))))
+             (clobber (scratch:SI))])]
+  "TARGET_32BIT"
+  "
+{ operands[2] = gen_reg_rtx (SImode); }")
 
-(define_insn "call_value_indirect_sysv"
-  [(set (match_operand 0 "register_operand" "=fg,fg")
-       (call (mem:SI (match_operand:SI 1 "register_operand" "l,l"))
-             (match_operand 2 "const_int_operand" "n,n")))
-   (use (match_operand 3 "const_int_operand" "O,n"))
-   (clobber (match_scratch:SI 4 "=l,l"))]
-  "DEFAULT_ABI == ABI_V4 || DEFAULT_ABI == ABI_SOLARIS || DEFAULT_ABI == ABI_AIX_NODESC"
-  "*
-{
-  if (INTVAL (operands[3]) & CALL_V4_SET_FP_ARGS)
-    output_asm_insn (\"crxor 6,6,6\", operands);
+(define_expand "call_indirect_aix64"
+  [(set (match_dup 2)
+       (mem:DI (match_operand:DI 0 "gpc_reg_operand" "")))
+   (set (mem:DI (plus:DI (reg:DI 1) (const_int 40)))
+       (reg:DI 2))
+   (set (reg:DI 2)
+       (mem:DI (plus:DI (match_dup 0)
+                        (const_int 8))))
+   (set (reg:DI 11)
+       (mem:DI (plus:DI (match_dup 0)
+                        (const_int 16))))
+   (parallel [(call (mem:SI (match_dup 2))
+                   (match_operand 1 "" ""))
+             (use (reg:DI 2))
+             (use (reg:DI 11))
+             (set (reg:DI 2)
+                  (mem:DI (plus:DI (reg:DI 1) (const_int 40))))
+             (clobber (scratch:SI))])]
+  "TARGET_64BIT"
+  "
+{ operands[2] = gen_reg_rtx (DImode); }")
 
-  else if (INTVAL (operands[3]) & CALL_V4_CLEAR_FP_ARGS)
-    output_asm_insn (\"creqv 6,6,6\", operands);
+(define_expand "call_value_indirect_aix32"
+  [(set (match_dup 3)
+       (mem:SI (match_operand:SI 1 "gpc_reg_operand" "")))
+   (set (mem:SI (plus:SI (reg:SI 1) (const_int 20)))
+       (reg:SI 2))
+   (set (reg:SI 2)
+       (mem:SI (plus:SI (match_dup 1)
+                        (const_int 4))))
+   (set (reg:SI 11)
+       (mem:SI (plus:SI (match_dup 1)
+                        (const_int 8))))
+   (parallel [(set (match_operand 0 "" "")
+                  (call (mem:SI (match_dup 3))
+                        (match_operand 2 "" "")))
+             (use (reg:SI 2))
+             (use (reg:SI 11))
+             (set (reg:SI 2)
+                  (mem:SI (plus:SI (reg:SI 1) (const_int 20))))
+             (clobber (scratch:SI))])]
+  "TARGET_32BIT"
+  "
+{ operands[3] = gen_reg_rtx (SImode); }")
 
-  return \"{brl|blrl}\";
-}"
-  [(set_attr "type" "jmpreg")
-   (set_attr "length" "4,8")])
+(define_expand "call_value_indirect_aix64"
+  [(set (match_dup 3)
+       (mem:DI (match_operand:DI 1 "gpc_reg_operand" "")))
+   (set (mem:DI (plus:DI (reg:DI 1) (const_int 40)))
+       (reg:DI 2))
+   (set (reg:DI 2)
+       (mem:DI (plus:DI (match_dup 1)
+                        (const_int 8))))
+   (set (reg:DI 11)
+       (mem:DI (plus:DI (match_dup 1)
+                        (const_int 16))))
+   (parallel [(set (match_operand 0 "" "")
+                  (call (mem:SI (match_dup 3))
+                        (match_operand 2 "" "")))
+             (use (reg:DI 2))
+             (use (reg:DI 11))
+             (set (reg:DI 2)
+                  (mem:DI (plus:DI (reg:DI 1) (const_int 40))))
+             (clobber (scratch:SI))])]
+  "TARGET_64BIT"
+  "
+{ operands[3] = gen_reg_rtx (DImode); }")
 
 ;; Now the definitions for the call and call_value insns
 (define_expand "call"
@@ -9435,31 +9409,26 @@ operands[2] = GEN_INT (INTVAL (operands[1]) >> 32);
       if (INTVAL (operands[2]) & CALL_LONG)
        operands[0] = rs6000_longcall_ref (operands[0]);
 
-      if (DEFAULT_ABI == ABI_V4 || DEFAULT_ABI == ABI_AIX_NODESC || DEFAULT_ABI == ABI_SOLARIS)
-       emit_call_insn (gen_call_indirect_sysv (force_reg (Pmode, operands[0]),
-                                               operands[1], operands[2]));
-      else
-       {
-         rtx toc_reg = gen_rtx_REG (Pmode, 2);
-         rtx toc_addr = RS6000_SAVE_TOC;
+      if (DEFAULT_ABI == ABI_V4
+          || DEFAULT_ABI == ABI_AIX_NODESC
+         || DEFAULT_ABI == ABI_SOLARIS)
+       operands[0] = force_reg (Pmode, operands[0]);
 
-         if (DEFAULT_ABI == ABI_AIX)
-           {
-             /* AIX function pointers are really pointers to a three word
-                area.  */
-             rtx static_chain = gen_rtx_REG (Pmode, STATIC_CHAIN_REGNUM);
-             emit_call_insn (TARGET_32BIT
-                             ? gen_call_indirect_aix32 (force_reg (Pmode, operands[0]),
-                                                        operands[1], operands[2],
-                                                        toc_addr, toc_reg, static_chain)
-                             : gen_call_indirect_aix64 (force_reg (Pmode, operands[0]),
-                                                        operands[1], operands[2],
-                                                        toc_addr, toc_reg, static_chain));
-           }
-         else
-           abort ();
+      else if (DEFAULT_ABI == ABI_AIX)
+       {
+         /* AIX function pointers are really pointers to a three word
+            area.  */
+         emit_call_insn (TARGET_32BIT
+                         ? gen_call_indirect_aix32 (force_reg (SImode,
+                                                               operands[0]),
+                                                    operands[1])
+                         : gen_call_indirect_aix64 (force_reg (DImode,
+                                                               operands[0]),
+                                                    operands[1]));
+         DONE;
        }
-      DONE;
+      else
+       abort ();
     }
 }")
 
@@ -9483,33 +9452,28 @@ operands[2] = GEN_INT (INTVAL (operands[1]) >> 32);
       if (INTVAL (operands[3]) & CALL_LONG)
        operands[1] = rs6000_longcall_ref (operands[1]);
 
-      if (DEFAULT_ABI == ABI_V4 || DEFAULT_ABI == ABI_AIX_NODESC || DEFAULT_ABI == ABI_SOLARIS)
-       emit_call_insn (gen_call_value_indirect_sysv (operands[0], operands[1],
-                                                     operands[2], operands[3]));
-      else
-       {
-         rtx toc_reg = gen_rtx_REG (Pmode, 2);
-         rtx toc_addr = RS6000_SAVE_TOC;
+      if (DEFAULT_ABI == ABI_V4
+         || DEFAULT_ABI == ABI_AIX_NODESC
+         || DEFAULT_ABI == ABI_SOLARIS)
+       operands[0] = force_reg (Pmode, operands[0]);
 
-         if (DEFAULT_ABI == ABI_AIX)
-           {
-             /* AIX function pointers are really pointers to a three word
-                area.  */
-             rtx static_chain = gen_rtx_REG (Pmode, STATIC_CHAIN_REGNUM);
-             emit_call_insn (TARGET_32BIT
-                             ? gen_call_value_indirect_aix32 (operands[0],
-                                                              force_reg (Pmode, operands[1]),
-                                                              operands[2], operands[3],
-                                                              toc_addr, toc_reg, static_chain)
-                             : gen_call_value_indirect_aix64 (operands[0],
-                                                              force_reg (Pmode, operands[1]),
-                                                              operands[2], operands[3],
-                                                              toc_addr, toc_reg, static_chain));
-           }
-         else
-           abort ();
+      else if (DEFAULT_ABI == ABI_AIX)
+       {
+         /* AIX function pointers are really pointers to a three word
+            area.  */
+         emit_call_insn (TARGET_32BIT
+                         ? gen_call_value_indirect_aix32 (operands[0],
+                                                          force_reg (SImode,
+                                                                     operands[1]),
+                                                          operands[2])
+                         : gen_call_value_indirect_aix64 (operands[0],
+                                                          force_reg (DImode,
+                                                                     operands[1]),
+                                                          operands[2]));
+         DONE;
        }
-      DONE;
+      else
+       abort ();
     }
 }")
 
@@ -9557,7 +9521,7 @@ operands[2] = GEN_INT (INTVAL (operands[1]) >> 32);
   [(set_attr "type" "branch")
    (set_attr "length" "4,8")])
 
-(define_insn "*ret_call_local32"
+(define_insn "*call_value_local32"
   [(set (match_operand 0 "" "=fg,fg")
        (call (mem:SI (match_operand:SI 1 "current_file_function_operand" "s,s"))
              (match_operand 2 "" "g,g")))
@@ -9578,7 +9542,7 @@ operands[2] = GEN_INT (INTVAL (operands[1]) >> 32);
    (set_attr "length" "4,8")])
 
 
-(define_insn "*ret_call_local64"
+(define_insn "*call_value_local64"
   [(set (match_operand 0 "" "=fg,fg")
        (call (mem:SI (match_operand:DI 1 "current_file_function_operand" "s,s"))
              (match_operand 2 "" "g,g")))
@@ -9605,154 +9569,178 @@ operands[2] = GEN_INT (INTVAL (operands[1]) >> 32);
 ;; variable argument function.  It is > 0 if FP registers were passed
 ;; and < 0 if they were not.
 
+(define_insn "*call_indirect_nonlocal_aix32"
+  [(call (mem:SI (match_operand:SI 0 "register_operand" "cl"))
+        (match_operand 1 "" "g"))
+   (use (reg:SI 2))
+   (use (reg:SI 11))
+   (set (reg:SI 2)
+       (mem:SI (plus:SI (reg:SI 1) (const_int 20))))
+   (clobber (match_scratch:SI 3 "=l"))]
+  "TARGET_32BIT && DEFAULT_ABI == ABI_AIX"
+  "b%T0l\;{l|lwz} 2,20(1)"
+  [(set_attr "type" "jmpreg")
+   (set_attr "length" "8")])
+
 (define_insn "*call_nonlocal_aix32"
-  [(call (mem:SI (match_operand:SI 0 "call_operand" "s,s"))
-        (match_operand 1 "" "fg,fg"))
-   (use (match_operand:SI 2 "immediate_operand" "O,n"))
-   (clobber (match_scratch:SI 3 "=l,l"))]
-  "DEFAULT_ABI == ABI_AIX
+  [(call (mem:SI (match_operand:SI 0 "call_operand" "s"))
+        (match_operand 1 "" "g"))
+   (use (match_operand:SI 2 "immediate_operand" "O"))
+   (clobber (match_scratch:SI 3 "=l"))]
+  "TARGET_32BIT
+   && DEFAULT_ABI == ABI_AIX
    && (INTVAL (operands[2]) & CALL_LONG) == 0"
-  "*
-{
-  /* Indirect calls should go through call_indirect */
-  if (GET_CODE (operands[0]) == REG)
-    abort ();
-
-  if (INTVAL (operands[2]) & CALL_V4_SET_FP_ARGS)
-    output_asm_insn (\"crxor 6,6,6\", operands);
-
-  else if (INTVAL (operands[2]) & CALL_V4_CLEAR_FP_ARGS)
-    output_asm_insn (\"creqv 6,6,6\", operands);
-
-  return \"bl %z0\;%.\";
-}"
+  "bl %z0\;%."
   [(set_attr "type" "branch")
-   (set_attr "length" "8,12")])
+   (set_attr "length" "8")])
+
+(define_insn "*call_indirect_nonlocal_aix64"
+  [(call (mem:SI (match_operand:DI 0 "register_operand" "cl"))
+        (match_operand 1 "" "g"))
+   (use (reg:DI 2))
+   (use (reg:DI 11))
+   (set (reg:DI 2)
+       (mem:DI (plus:DI (reg:DI 1) (const_int 40))))
+   (clobber (match_scratch:SI 3 "=l"))]
+  "TARGET_64BIT && DEFAULT_ABI == ABI_AIX"
+  "b%T0l\;ld 2,40(1)"
+  [(set_attr "type" "jmpreg")
+   (set_attr "length" "8")])
 
 (define_insn "*call_nonlocal_aix64"
-  [(call (mem:SI (match_operand:DI 0 "call_operand" "s,s"))
-        (match_operand 1 "" "fg,fg"))
-   (use (match_operand:SI 2 "immediate_operand" "O,n"))
-   (clobber (match_scratch:SI 3 "=l,l"))]
+  [(call (mem:SI (match_operand:DI 0 "call_operand" "s"))
+        (match_operand 1 "" "g"))
+   (use (match_operand:SI 2 "immediate_operand" "O"))
+   (clobber (match_scratch:SI 3 "=l"))]
   "TARGET_64BIT 
    && DEFAULT_ABI == ABI_AIX
    && (INTVAL (operands[2]) & CALL_LONG) == 0"
-  "*
-{
-  /* Indirect calls should go through call_indirect */
-  if (GET_CODE (operands[0]) == REG)
-    abort ();
-
-  if (INTVAL (operands[2]) & CALL_V4_SET_FP_ARGS)
-    output_asm_insn (\"crxor 6,6,6\", operands);
-
-  else if (INTVAL (operands[2]) & CALL_V4_CLEAR_FP_ARGS)
-    output_asm_insn (\"creqv 6,6,6\", operands);
-
-  return \"bl %z0\;%.\";
-}"
+  "bl %z0\;%."
   [(set_attr "type" "branch")
-   (set_attr "length" "8,12")])
-
-(define_insn "*call_nonlocal_sysv"
-  [(call (mem:SI (match_operand:SI 0 "call_operand" "s,s"))
-        (match_operand 1 "" "fg,fg"))
-   (use (match_operand:SI 2 "immediate_operand" "O,n"))
-   (clobber (match_scratch:SI 3 "=l,l"))]
-  "(DEFAULT_ABI == ABI_AIX_NODESC || DEFAULT_ABI == ABI_V4 || DEFAULT_ABI == ABI_SOLARIS)
-   && (INTVAL (operands[2]) & CALL_LONG) == 0"
-  "*
-{
-  /* Indirect calls should go through call_indirect */
-  if (GET_CODE (operands[0]) == REG)
-    abort ();
-
-  if (INTVAL (operands[2]) & CALL_V4_SET_FP_ARGS)
-    output_asm_insn (\"crxor 6,6,6\", operands);
-
-  else if (INTVAL (operands[2]) & CALL_V4_CLEAR_FP_ARGS)
-    output_asm_insn (\"creqv 6,6,6\", operands);
+   (set_attr "length" "8")])
 
-  return (DEFAULT_ABI == ABI_V4 && flag_pic) ? \"bl %z0@plt\" : \"bl %z0\";
-}"
-  [(set_attr "type" "branch")
-   (set_attr "length" "4,8")])
+(define_insn "*call_value_indirect_nonlocal_aix32"
+  [(set (match_operand 0 "" "=fg")
+       (call (mem:SI (match_operand:SI 1 "register_operand" "cl"))
+             (match_operand 2 "" "g")))
+   (use (reg:SI 2))
+   (use (reg:SI 11))
+   (set (reg:SI 2)
+       (mem:SI (plus:SI (reg:SI 1) (const_int 20))))
+   (clobber (match_scratch:SI 3 "=l"))]
+  "TARGET_32BIT && DEFAULT_ABI == ABI_AIX"
+  "b%T1l\;{l|lwz} 2,20(1)"
+  [(set_attr "type" "jmpreg")
+   (set_attr "length" "8")])
 
-(define_insn "*ret_call_nonlocal_aix32"
-  [(set (match_operand 0 "" "=fg,fg")
-       (call (mem:SI (match_operand:SI 1 "call_operand" "s,s"))
-             (match_operand 2 "" "fg,fg")))
-   (use (match_operand:SI 3 "immediate_operand" "O,n"))
-   (clobber (match_scratch:SI 4 "=l,l"))]
-  "DEFAULT_ABI == ABI_AIX
+(define_insn "*call_value_nonlocal_aix32"
+  [(set (match_operand 0 "" "=fg")
+       (call (mem:SI (match_operand:SI 1 "call_operand" "s"))
+             (match_operand 2 "" "g")))
+   (use (match_operand:SI 3 "immediate_operand" "O"))
+   (clobber (match_scratch:SI 4 "=l"))]
+  "TARGET_32BIT
+   && DEFAULT_ABI == ABI_AIX
    && (INTVAL (operands[3]) & CALL_LONG) == 0"
-  "*
-{
-  /* This should be handled by call_value_indirect */
-  if (GET_CODE (operands[1]) == REG)
-    abort ();
-
-  if (INTVAL (operands[3]) & CALL_V4_SET_FP_ARGS)
-    output_asm_insn (\"crxor 6,6,6\", operands);
-
-  else if (INTVAL (operands[3]) & CALL_V4_CLEAR_FP_ARGS)
-    output_asm_insn (\"creqv 6,6,6\", operands);
-
-  return \"bl %z1\;%.\";
-}"
+  "bl %z1\;%."
   [(set_attr "type" "branch")
-   (set_attr "length" "8,12")])
+   (set_attr "length" "8")])
 
-(define_insn "*ret_call_nonlocal_aix64"
-  [(set (match_operand 0 "" "=fg,fg")
-       (call (mem:SI (match_operand:DI 1 "call_operand" "s,s"))
-             (match_operand 2 "" "fg,fg")))
-   (use (match_operand:SI 3 "immediate_operand" "O,n"))
-   (clobber (match_scratch:SI 4 "=l,l"))]
+(define_insn "*call_value_indirect_nonlocal_aix64"
+  [(set (match_operand 0 "" "=fg")
+       (call (mem:SI (match_operand:DI 1 "register_operand" "cl"))
+             (match_operand 2 "" "g")))
+   (use (reg:DI 2))
+   (use (reg:DI 11))
+   (set (reg:DI 2)
+       (mem:DI (plus:DI (reg:DI 1) (const_int 40))))
+   (clobber (match_scratch:SI 3 "=l"))]
+  "TARGET_64BIT && DEFAULT_ABI == ABI_AIX"
+  "b%T1l\;ld 2,40(1)"
+  [(set_attr "type" "jmpreg")
+   (set_attr "length" "8")])
+
+(define_insn "*call_value_nonlocal_aix64"
+  [(set (match_operand 0 "" "=fg")
+       (call (mem:SI (match_operand:DI 1 "call_operand" "s"))
+             (match_operand 2 "" "g")))
+   (use (match_operand:SI 3 "immediate_operand" "O"))
+   (clobber (match_scratch:SI 4 "=l"))]
   "TARGET_64BIT 
    && DEFAULT_ABI == ABI_AIX
    && (INTVAL (operands[3]) & CALL_LONG) == 0"
+  "bl %z1\;%."
+  [(set_attr "type" "branch")
+   (set_attr "length" "8")])
+
+;; A function pointer under System V is just a normal pointer
+;; operands[0] is the function pointer
+;; operands[1] is the stack size to clean up
+;; operands[2] is the value FUNCTION_ARG returns for the VOID argument
+;; which indicates how to set cr1
+
+(define_insn "*call_nonlocal_sysv"
+  [(call (mem:SI (match_operand:SI 0 "call_operand" "cl,cl,s,s"))
+        (match_operand 1 "" "g,g,g,g"))
+   (use (match_operand:SI 2 "immediate_operand" "O,n,O,n"))
+   (clobber (match_scratch:SI 3 "=l,l,l,l"))]
+  "DEFAULT_ABI == ABI_AIX_NODESC
+   || DEFAULT_ABI == ABI_V4
+   || DEFAULT_ABI == ABI_SOLARIS"
   "*
 {
-  /* This should be handled by call_value_indirect */
-  if (GET_CODE (operands[1]) == REG)
-    abort ();
-
-  if (INTVAL (operands[3]) & CALL_V4_SET_FP_ARGS)
+  if (INTVAL (operands[2]) & CALL_V4_SET_FP_ARGS)
     output_asm_insn (\"crxor 6,6,6\", operands);
 
-  else if (INTVAL (operands[3]) & CALL_V4_CLEAR_FP_ARGS)
+  else if (INTVAL (operands[2]) & CALL_V4_CLEAR_FP_ARGS)
     output_asm_insn (\"creqv 6,6,6\", operands);
 
-  return \"bl %z1\;%.\";
+  switch (which_alternative)
+    {
+    default:
+      abort ();
+    case 0:
+    case 1:
+      return \"b%T0l\";
+    case 2:
+    case 3:
+      return (DEFAULT_ABI == ABI_V4 && flag_pic) ? \"bl %z0@plt\" : \"bl %z0\";
+    }
 }"
-  [(set_attr "type" "branch")
-   (set_attr "length" "8,12")])
-
-(define_insn "*ret_call_nonlocal_sysv"
-  [(set (match_operand 0 "" "=fg,fg")
-       (call (mem:SI (match_operand:SI 1 "call_operand" "s,s"))
-             (match_operand 2 "" "fg,fg")))
-   (use (match_operand:SI 3 "immediate_operand" "O,n"))
-   (clobber (match_scratch:SI 4 "=l,l"))]
-  "(DEFAULT_ABI == ABI_AIX_NODESC || DEFAULT_ABI == ABI_V4 || DEFAULT_ABI == ABI_SOLARIS)
-   && (INTVAL (operands[3]) & CALL_LONG) == 0"
+  [(set_attr "type" "jmpreg,jmpreg,branch,branch")
+   (set_attr "length" "4,8,4,8")])
+
+(define_insn "*call_value_nonlocal_sysv"
+  [(set (match_operand 0 "" "=fg,fg,fg,fg")
+       (call (mem:SI (match_operand:SI 1 "call_operand" "cl,cl,s,s"))
+             (match_operand 2 "" "g,g,g,g")))
+   (use (match_operand:SI 3 "immediate_operand" "O,n,O,n"))
+   (clobber (match_scratch:SI 4 "=l,l,l,l"))]
+  "DEFAULT_ABI == ABI_AIX_NODESC
+   || DEFAULT_ABI == ABI_V4
+   || DEFAULT_ABI == ABI_SOLARIS"
   "*
 {
-  /* This should be handled by call_value_indirect */
-  if (GET_CODE (operands[1]) == REG)
-    abort ();
-
   if (INTVAL (operands[3]) & CALL_V4_SET_FP_ARGS)
     output_asm_insn (\"crxor 6,6,6\", operands);
 
   else if (INTVAL (operands[3]) & CALL_V4_CLEAR_FP_ARGS)
     output_asm_insn (\"creqv 6,6,6\", operands);
 
-  return (DEFAULT_ABI == ABI_V4 && flag_pic) ? \"bl %z1@plt\" : \"bl %z1\";
+  switch (which_alternative)
+    {
+    default:
+      abort ();
+    case 0:
+    case 1:
+      return \"b%T1l\";
+    case 2:
+    case 3:
+      return (DEFAULT_ABI == ABI_V4 && flag_pic) ? \"bl %z1@plt\" : \"bl %z1\";
+    }
 }"
-  [(set_attr "type" "branch")
-   (set_attr "length" "4,8")])
+  [(set_attr "type" "jmpreg,jmpreg,branch,branch")
+   (set_attr "length" "4,8,4,8")])
 
 ;; Call subroutine returning any type.
 (define_expand "untyped_call"
@@ -13226,19 +13214,15 @@ operands[2] = GEN_INT (INTVAL (operands[1]) >> 32);
 }")
 
 (define_insn "indirect_jumpsi"
-  [(set (pc) (match_operand:SI 0 "register_operand" "c,l"))]
+  [(set (pc) (match_operand:SI 0 "register_operand" "cl"))]
   "TARGET_32BIT"
-  "@
-   bctr
-   {br|blr}"
+  "b%T0"
   [(set_attr "type" "jmpreg")])
 
 (define_insn "indirect_jumpdi"
-  [(set (pc) (match_operand:DI 0 "register_operand" "c,l"))]
+  [(set (pc) (match_operand:DI 0 "register_operand" "cl"))]
   "TARGET_64BIT"
-  "@
-   bctr
-   {br|blr}"
+  "b%T0"
   [(set_attr "type" "jmpreg")])
 
 ;; Table jump for switch statements:
@@ -13285,22 +13269,18 @@ operands[2] = GEN_INT (INTVAL (operands[1]) >> 32);
 
 (define_insn ""
   [(set (pc)
-       (match_operand:SI 0 "register_operand" "c,l"))
+       (match_operand:SI 0 "register_operand" "cl"))
    (use (label_ref (match_operand 1 "" "")))]
   "TARGET_32BIT"
-  "@
-   bctr
-   {br|blr}"
+  "b%T0"
   [(set_attr "type" "jmpreg")])
 
 (define_insn ""
   [(set (pc)
-       (match_operand:DI 0 "register_operand" "c,l"))
+       (match_operand:DI 0 "register_operand" "cl"))
    (use (label_ref (match_operand 1 "" "")))]
   "TARGET_64BIT"
-  "@
-   bctr
-   {br|blr}"
+  "b%T0"
   [(set_attr "type" "jmpreg")])
 
 (define_insn "nop"
@@ -13898,21 +13878,17 @@ operands[2] = GEN_INT (INTVAL (operands[1]) >> 32);
  "{lm|lmw} %1,%2")
  
 (define_insn "*return_internal_si"
-  [(use (match_operand:SI 0 "register_operand" "l,c"))
+  [(use (match_operand:SI 0 "register_operand" "lc"))
    (return)]
   "TARGET_32BIT"
-  "@
-   {br|blr}
-   bctr"
+  "b%T0"
   [(set_attr "type" "jmpreg")])
 
 (define_insn "*return_internal_di"
-  [(use (match_operand:DI 0 "register_operand" "l,c"))
+  [(use (match_operand:DI 0 "register_operand" "lc"))
    (return)]
   "TARGET_64BIT"
-  "@
-   {br|blr}
-   bctr"
+  "b%T0"
   [(set_attr "type" "jmpreg")])
 
 ; FIXME: This would probably be somewhat simpler if the Cygnus sibcall
@@ -14037,23 +14013,19 @@ operands[2] = GEN_INT (INTVAL (operands[1]) >> 32);
 
 
 (define_insn "return_eh_si"
-  [(use (match_operand:SI 0 "register_operand" "l,c"))
+  [(use (match_operand:SI 0 "register_operand" "lc"))
    (return)
    (use (reg:SI 2))
    (use (reg:SI 3))]
   "TARGET_32BIT"
-  "@
-   {br|blr}
-   bctr"
+  "b%T0"
   [(set_attr "type" "jmpreg")])
 
 (define_insn "return_eh_di"
-  [(use (match_operand:DI 0 "register_operand" "l,c"))
+  [(use (match_operand:DI 0 "register_operand" "lc"))
    (return)
    (use (reg:DI 2))
    (use (reg:DI 3))]
   "TARGET_64BIT"
-  "@
-   {br|blr}
-   bctr"
+  "b%T0"
   [(set_attr "type" "jmpreg")])