The attached change adds mi_thunk support for vcalls on hppa.  Tested on 
hppa-unknown-linux-gnu,
hppa2.0w-hp-hpux11.11 and hppa64-hp-hpux11.11.  Committed to trunk and gcc-10.

Dave
-- 
John David Anglin  dave.ang...@bell.net

Add mi_thunk support for vcalls on hppa.

gcc/ChangeLog:

        PR target/85074
        * config/pa/pa.c (TARGET_ASM_CAN_OUTPUT_MI_THUNK): Define as
        hook_bool_const_tree_hwi_hwi_const_tree_true.
        (pa_asm_output_mi_thunk): Add support for nonzero vcall_offset.

diff --git a/gcc/config/pa/pa.c b/gcc/config/pa/pa.c
index 3921b5c98de..d7fcd11e504 100644
--- a/gcc/config/pa/pa.c
+++ b/gcc/config/pa/pa.c
@@ -293,7 +293,7 @@ static size_t n_deferred_plabels = 0;
 #undef TARGET_ASM_OUTPUT_MI_THUNK
 #define TARGET_ASM_OUTPUT_MI_THUNK pa_asm_output_mi_thunk
 #undef TARGET_ASM_CAN_OUTPUT_MI_THUNK
-#define TARGET_ASM_CAN_OUTPUT_MI_THUNK default_can_output_mi_thunk_no_vcall
+#define TARGET_ASM_CAN_OUTPUT_MI_THUNK 
hook_bool_const_tree_hwi_hwi_const_tree_true

 #undef TARGET_ASM_FILE_END
 #define TARGET_ASM_FILE_END pa_file_end
@@ -8461,12 +8461,15 @@ pa_is_function_label_plus_const (rtx op)
          && GET_CODE (XEXP (op, 1)) == CONST_INT);
 }

-/* Output assembly code for a thunk to FUNCTION.  */
+/* Output the assembler code for a thunk function.  THUNK_DECL is the
+   declaration for the thunk function itself, FUNCTION is the decl for
+   the target function.  DELTA is an immediate constant offset to be
+   added to THIS.  If VCALL_OFFSET is nonzero, the word at
+   *(*this + vcall_offset) should be added to THIS.  */

 static void
 pa_asm_output_mi_thunk (FILE *file, tree thunk_fndecl, HOST_WIDE_INT delta,
-                       HOST_WIDE_INT vcall_offset ATTRIBUTE_UNUSED,
-                       tree function)
+                       HOST_WIDE_INT vcall_offset, tree function)
 {
   const char *fnname = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (thunk_fndecl));
   static unsigned int current_thunk_number;
@@ -8482,201 +8485,386 @@ pa_asm_output_mi_thunk (FILE *file, tree 
thunk_fndecl, HOST_WIDE_INT delta,
   assemble_start_function (thunk_fndecl, fnname);
   final_start_function (emit_barrier (), file, 1);

-  /* Output the thunk.  We know that the function is in the same
-     translation unit (i.e., the same space) as the thunk, and that
-     thunks are output after their method.  Thus, we don't need an
-     external branch to reach the function.  With SOM and GAS,
-     functions and thunks are effectively in different sections.
-     Thus, we can always use a IA-relative branch and the linker
-     will add a long branch stub if necessary.
-
-     However, we have to be careful when generating PIC code on the
-     SOM port to ensure that the sequence does not transfer to an
-     import stub for the target function as this could clobber the
-     return value saved at SP-24.  This would also apply to the
-     32-bit linux port if the multi-space model is implemented.  */
-  if ((!TARGET_LONG_CALLS && TARGET_SOM && !TARGET_PORTABLE_RUNTIME
-       && !(flag_pic && TREE_PUBLIC (function))
-       && (TARGET_GAS || last_address < 262132))
-      || (!TARGET_LONG_CALLS && !TARGET_SOM && !TARGET_PORTABLE_RUNTIME
-         && ((targetm_common.have_named_sections
-              && DECL_SECTION_NAME (thunk_fndecl) != NULL
-              /* The GNU 64-bit linker has rather poor stub management.
-                 So, we use a long branch from thunks that aren't in
-                 the same section as the target function.  */
-              && ((!TARGET_64BIT
-                   && (DECL_SECTION_NAME (thunk_fndecl)
-                       != DECL_SECTION_NAME (function)))
-                  || ((DECL_SECTION_NAME (thunk_fndecl)
-                       == DECL_SECTION_NAME (function))
-                      && last_address < 262132)))
-             /* In this case, we need to be able to reach the start of
-                the stub table even though the function is likely closer
-                and can be jumped to directly.  */
-             || (targetm_common.have_named_sections
-                 && DECL_SECTION_NAME (thunk_fndecl) == NULL
-                 && DECL_SECTION_NAME (function) == NULL
-                 && total_code_bytes < MAX_PCREL17F_OFFSET)
-             /* Likewise.  */
-             || (!targetm_common.have_named_sections
-                 && total_code_bytes < MAX_PCREL17F_OFFSET))))
-    {
-      if (!val_14)
-       output_asm_insn ("addil L'%2,%%r26", xoperands);
-
-      output_asm_insn ("b %0", xoperands);
-
-      if (val_14)
-       {
-         output_asm_insn ("ldo %2(%%r26),%%r26", xoperands);
-         nbytes += 8;
+  if (!vcall_offset)
+    {
+      /* Output the thunk.  We know that the function is in the same
+        translation unit (i.e., the same space) as the thunk, and that
+        thunks are output after their method.  Thus, we don't need an
+        external branch to reach the function.  With SOM and GAS,
+        functions and thunks are effectively in different sections.
+        Thus, we can always use a IA-relative branch and the linker
+        will add a long branch stub if necessary.
+
+        However, we have to be careful when generating PIC code on the
+        SOM port to ensure that the sequence does not transfer to an
+        import stub for the target function as this could clobber the
+        return value saved at SP-24.  This would also apply to the
+       32-bit linux port if the multi-space model is implemented.  */
+      if ((!TARGET_LONG_CALLS && TARGET_SOM && !TARGET_PORTABLE_RUNTIME
+          && !(flag_pic && TREE_PUBLIC (function))
+          && (TARGET_GAS || last_address < 262132))
+         || (!TARGET_LONG_CALLS && !TARGET_SOM && !TARGET_PORTABLE_RUNTIME
+             && ((targetm_common.have_named_sections
+                  && DECL_SECTION_NAME (thunk_fndecl) != NULL
+                  /* The GNU 64-bit linker has rather poor stub management.
+                     So, we use a long branch from thunks that aren't in
+                     the same section as the target function.  */
+                   && ((!TARGET_64BIT
+                        && (DECL_SECTION_NAME (thunk_fndecl)
+                            != DECL_SECTION_NAME (function)))
+                       || ((DECL_SECTION_NAME (thunk_fndecl)
+                            == DECL_SECTION_NAME (function))
+                           && last_address < 262132)))
+                 /* In this case, we need to be able to reach the start of
+                    the stub table even though the function is likely closer
+                    and can be jumped to directly.  */
+                 || (targetm_common.have_named_sections
+                     && DECL_SECTION_NAME (thunk_fndecl) == NULL
+                     && DECL_SECTION_NAME (function) == NULL
+                     && total_code_bytes < MAX_PCREL17F_OFFSET)
+                 /* Likewise.  */
+                 || (!targetm_common.have_named_sections
+                     && total_code_bytes < MAX_PCREL17F_OFFSET))))
+       {
+         if (!val_14)
+           output_asm_insn ("addil L'%2,%%r26", xoperands);
+
+         output_asm_insn ("b %0", xoperands);
+
+         if (val_14)
+           {
+             output_asm_insn ("ldo %2(%%r26),%%r26", xoperands);
+             nbytes += 8;
+           }
+         else
+           {
+             output_asm_insn ("ldo R'%2(%%r1),%%r26", xoperands);
+             nbytes += 12;
+           }
        }
-      else
+      else if (TARGET_64BIT)
        {
-         output_asm_insn ("ldo R'%2(%%r1),%%r26", xoperands);
-         nbytes += 12;
-       }
-    }
-  else if (TARGET_64BIT)
-    {
-      rtx xop[4];
+         rtx xop[4];
+
+         /* We only have one call-clobbered scratch register, so we can't
+            make use of the delay slot if delta doesn't fit in 14 bits.  */
+         if (!val_14)
+           {
+             output_asm_insn ("addil L'%2,%%r26", xoperands);
+             output_asm_insn ("ldo R'%2(%%r1),%%r26", xoperands);
+           }
+
+         /* Load function address into %r1.  */
+         xop[0] = xoperands[0];
+         xop[1] = gen_rtx_REG (Pmode, 1);
+         xop[2] = xop[1];
+         pa_output_pic_pcrel_sequence (xop);

-      /* We only have one call-clobbered scratch register, so we can't
-         make use of the delay slot if delta doesn't fit in 14 bits.  */
-      if (!val_14)
+         if (val_14)
+           {
+             output_asm_insn ("bv %%r0(%%r1)", xoperands);
+             output_asm_insn ("ldo %2(%%r26),%%r26", xoperands);
+             nbytes += 20;
+           }
+         else
+           {
+             output_asm_insn ("bv,n %%r0(%%r1)", xoperands);
+             nbytes += 24;
+           }
+       }
+      else if (TARGET_PORTABLE_RUNTIME)
        {
-         output_asm_insn ("addil L'%2,%%r26", xoperands);
-         output_asm_insn ("ldo R'%2(%%r1),%%r26", xoperands);
+         output_asm_insn ("ldil L'%0,%%r1", xoperands);
+         output_asm_insn ("ldo R'%0(%%r1),%%r22", xoperands);
+
+         if (!val_14)
+           output_asm_insn ("ldil L'%2,%%r26", xoperands);
+
+         output_asm_insn ("bv %%r0(%%r22)", xoperands);
+
+         if (val_14)
+           {
+             output_asm_insn ("ldo %2(%%r26),%%r26", xoperands);
+             nbytes += 16;
+           }
+         else
+           {
+             output_asm_insn ("ldo R'%2(%%r26),%%r26", xoperands);
+             nbytes += 20;
+           }
        }
+      else if (TARGET_SOM && flag_pic && TREE_PUBLIC (function))
+       {
+         /* The function is accessible from outside this module.  The only
+            way to avoid an import stub between the thunk and function is to
+            call the function directly with an indirect sequence similar to
+            that used by $$dyncall.  This is possible because $$dyncall acts
+            as the import stub in an indirect call.  */
+         ASM_GENERATE_INTERNAL_LABEL (label, "LTHN", current_thunk_number);
+         xoperands[3] = gen_rtx_SYMBOL_REF (Pmode, label);
+         output_asm_insn ("addil LT'%3,%%r19", xoperands);
+         output_asm_insn ("ldw RT'%3(%%r1),%%r22", xoperands);
+         output_asm_insn ("ldw 0(%%sr0,%%r22),%%r22", xoperands);
+         output_asm_insn ("bb,>=,n %%r22,30,.+16", xoperands);
+         output_asm_insn ("depi 0,31,2,%%r22", xoperands);
+         output_asm_insn ("ldw 4(%%sr0,%%r22),%%r19", xoperands);
+         output_asm_insn ("ldw 0(%%sr0,%%r22),%%r22", xoperands);
+
+         if (!val_14)
+           {
+             output_asm_insn ("addil L'%2,%%r26", xoperands);
+             nbytes += 4;
+           }

-      /* Load function address into %r1.  */
-      xop[0] = xoperands[0];
-      xop[1] = gen_rtx_REG (Pmode, 1);
-      xop[2] = xop[1];
-      pa_output_pic_pcrel_sequence (xop);
+         if (TARGET_PA_20)
+           {
+             output_asm_insn ("bve (%%r22)", xoperands);
+             nbytes += 36;
+           }
+         else if (TARGET_NO_SPACE_REGS)
+           {
+             output_asm_insn ("be 0(%%sr4,%%r22)", xoperands);
+             nbytes += 36;
+           }
+         else
+           {
+             output_asm_insn ("ldsid (%%sr0,%%r22),%%r21", xoperands);
+             output_asm_insn ("mtsp %%r21,%%sr0", xoperands);
+             output_asm_insn ("be 0(%%sr0,%%r22)", xoperands);
+             nbytes += 44;
+           }

-      if (val_14)
-       {
-         output_asm_insn ("bv %%r0(%%r1)", xoperands);
-         output_asm_insn ("ldo %2(%%r26),%%r26", xoperands);
-         nbytes += 20;
+         if (val_14)
+           output_asm_insn ("ldo %2(%%r26),%%r26", xoperands);
+         else
+           output_asm_insn ("ldo R'%2(%%r1),%%r26", xoperands);
        }
-      else
+      else if (flag_pic)
        {
-         output_asm_insn ("bv,n %%r0(%%r1)", xoperands);
-         nbytes += 24;
-       }
-    }
-  else if (TARGET_PORTABLE_RUNTIME)
-    {
-      output_asm_insn ("ldil L'%0,%%r1", xoperands);
-      output_asm_insn ("ldo R'%0(%%r1),%%r22", xoperands);
+         rtx xop[4];

-      if (!val_14)
-       output_asm_insn ("ldil L'%2,%%r26", xoperands);
+         /* Load function address into %r22.  */
+         xop[0] = xoperands[0];
+         xop[1] = gen_rtx_REG (Pmode, 1);
+         xop[2] = gen_rtx_REG (Pmode, 22);
+         pa_output_pic_pcrel_sequence (xop);

-      output_asm_insn ("bv %%r0(%%r22)", xoperands);
+         if (!val_14)
+           output_asm_insn ("addil L'%2,%%r26", xoperands);

-      if (val_14)
-       {
-         output_asm_insn ("ldo %2(%%r26),%%r26", xoperands);
-         nbytes += 16;
+         output_asm_insn ("bv %%r0(%%r22)", xoperands);
+
+         if (val_14)
+           {
+             output_asm_insn ("ldo %2(%%r26),%%r26", xoperands);
+             nbytes += 20;
+           }
+         else
+           {
+             output_asm_insn ("ldo R'%2(%%r1),%%r26", xoperands);
+             nbytes += 24;
+           }
        }
       else
        {
-         output_asm_insn ("ldo R'%2(%%r26),%%r26", xoperands);
-         nbytes += 20;
+         if (!val_14)
+           output_asm_insn ("addil L'%2,%%r26", xoperands);
+
+         output_asm_insn ("ldil L'%0,%%r22", xoperands);
+         output_asm_insn ("be R'%0(%%sr4,%%r22)", xoperands);
+
+         if (val_14)
+           {
+             output_asm_insn ("ldo %2(%%r26),%%r26", xoperands);
+             nbytes += 12;
+           }
+         else
+           {
+             output_asm_insn ("ldo R'%2(%%r1),%%r26", xoperands);
+             nbytes += 16;
+           }
        }
     }
-  else if (TARGET_SOM && flag_pic && TREE_PUBLIC (function))
+  else
     {
-      /* The function is accessible from outside this module.  The only
-        way to avoid an import stub between the thunk and function is to
-        call the function directly with an indirect sequence similar to
-        that used by $$dyncall.  This is possible because $$dyncall acts
-        as the import stub in an indirect call.  */
-      ASM_GENERATE_INTERNAL_LABEL (label, "LTHN", current_thunk_number);
-      xoperands[3] = gen_rtx_SYMBOL_REF (Pmode, label);
-      output_asm_insn ("addil LT'%3,%%r19", xoperands);
-      output_asm_insn ("ldw RT'%3(%%r1),%%r22", xoperands);
-      output_asm_insn ("ldw 0(%%sr0,%%r22),%%r22", xoperands);
-      output_asm_insn ("bb,>=,n %%r22,30,.+16", xoperands);
-      output_asm_insn ("depi 0,31,2,%%r22", xoperands);
-      output_asm_insn ("ldw 4(%%sr0,%%r22),%%r19", xoperands);
-      output_asm_insn ("ldw 0(%%sr0,%%r22),%%r22", xoperands);
+      rtx xop[4];

-      if (!val_14)
+      /* Add DELTA to THIS.  */
+      if (val_14)
        {
-         output_asm_insn ("addil L'%2,%%r26", xoperands);
+         output_asm_insn ("ldo %2(%%r26),%%r26", xoperands);
          nbytes += 4;
        }
-
-      if (TARGET_PA_20)
+      else
        {
-         output_asm_insn ("bve (%%r22)", xoperands);
-         nbytes += 36;
+         output_asm_insn ("addil L'%2,%%r26", xoperands);
+         output_asm_insn ("ldo R'%2(%%r1),%%r26", xoperands);
+         nbytes += 8;
        }
-      else if (TARGET_NO_SPACE_REGS)
+
+      if (TARGET_64BIT)
        {
-         output_asm_insn ("be 0(%%sr4,%%r22)", xoperands);
-         nbytes += 36;
+         /* Load *(THIS + DELTA) to %r1.  */
+         output_asm_insn ("ldd 0(%%r26),%%r1", xoperands);
+
+         val_14 = VAL_14_BITS_P (vcall_offset);
+         xoperands[2] = GEN_INT (vcall_offset);
+
+         /* Load  *(*(THIS + DELTA) + VCALL_OFFSET) to %r1.  */
+         if (val_14)
+           {
+             output_asm_insn ("ldd %2(%%r1),%%r1", xoperands);
+             nbytes += 8;
+           }
+         else
+           {
+             output_asm_insn ("addil L'%2,%%r1", xoperands);
+             output_asm_insn ("ldd R'%2(%%r1),%%r1", xoperands);
+             nbytes += 12;
+           }
        }
       else
        {
-         output_asm_insn ("ldsid (%%sr0,%%r22),%%r21", xoperands);
-         output_asm_insn ("mtsp %%r21,%%sr0", xoperands);
-         output_asm_insn ("be 0(%%sr0,%%r22)", xoperands);
-         nbytes += 44;
-       }
+         /* Load *(THIS + DELTA) to %r1.  */
+         output_asm_insn ("ldw 0(%%r26),%%r1", xoperands);

-      if (val_14)
-       output_asm_insn ("ldo %2(%%r26),%%r26", xoperands);
-      else
-       output_asm_insn ("ldo R'%2(%%r1),%%r26", xoperands);
-    }
-  else if (flag_pic)
-    {
-      rtx xop[4];
-
-      /* Load function address into %r22.  */
-      xop[0] = xoperands[0];
-      xop[1] = gen_rtx_REG (Pmode, 1);
-      xop[2] = gen_rtx_REG (Pmode, 22);
-      pa_output_pic_pcrel_sequence (xop);
+         val_14 = VAL_14_BITS_P (vcall_offset);
+         xoperands[2] = GEN_INT (vcall_offset);

-      if (!val_14)
-       output_asm_insn ("addil L'%2,%%r26", xoperands);
-
-      output_asm_insn ("bv %%r0(%%r22)", xoperands);
+         /* Load  *(*(THIS + DELTA) + VCALL_OFFSET) to %r1.  */
+         if (val_14)
+           {
+             output_asm_insn ("ldw %2(%%r1),%%r1", xoperands);
+             nbytes += 8;
+           }
+         else
+           {
+             output_asm_insn ("addil L'%2,%%r1", xoperands);
+             output_asm_insn ("ldw R'%2(%%r1),%%r1", xoperands);
+             nbytes += 12;
+           }
+       }

-      if (val_14)
+      /* Branch to FUNCTION and add %r1 to THIS in delay slot if possible.  */
+      if ((!TARGET_LONG_CALLS && TARGET_SOM && !TARGET_PORTABLE_RUNTIME
+          && !(flag_pic && TREE_PUBLIC (function))
+          && (TARGET_GAS || last_address < 262132))
+         || (!TARGET_LONG_CALLS && !TARGET_SOM && !TARGET_PORTABLE_RUNTIME
+             && ((targetm_common.have_named_sections
+                  && DECL_SECTION_NAME (thunk_fndecl) != NULL
+                  /* The GNU 64-bit linker has rather poor stub management.
+                     So, we use a long branch from thunks that aren't in
+                     the same section as the target function.  */
+                   && ((!TARGET_64BIT
+                        && (DECL_SECTION_NAME (thunk_fndecl)
+                            != DECL_SECTION_NAME (function)))
+                       || ((DECL_SECTION_NAME (thunk_fndecl)
+                            == DECL_SECTION_NAME (function))
+                           && last_address < 262132)))
+                 /* In this case, we need to be able to reach the start of
+                    the stub table even though the function is likely closer
+                    and can be jumped to directly.  */
+                 || (targetm_common.have_named_sections
+                     && DECL_SECTION_NAME (thunk_fndecl) == NULL
+                     && DECL_SECTION_NAME (function) == NULL
+                     && total_code_bytes < MAX_PCREL17F_OFFSET)
+                 /* Likewise.  */
+                 || (!targetm_common.have_named_sections
+                     && total_code_bytes < MAX_PCREL17F_OFFSET))))
        {
-         output_asm_insn ("ldo %2(%%r26),%%r26", xoperands);
-         nbytes += 20;
+         nbytes += 4;
+         output_asm_insn ("b %0", xoperands);
+
+         /* Add *(*(THIS + DELTA) + VCALL_OFFSET) to THIS.  */
+         output_asm_insn ("addl %%r1,%%r26,%%r26", xoperands);
        }
-      else
+      else if (TARGET_64BIT)
        {
-         output_asm_insn ("ldo R'%2(%%r1),%%r26", xoperands);
-         nbytes += 24;
-       }
-    }
-  else
-    {
-      if (!val_14)
-       output_asm_insn ("addil L'%2,%%r26", xoperands);
+         /* Add *(*(THIS + DELTA) + VCALL_OFFSET) to THIS.  */
+         output_asm_insn ("addl %%r1,%%r26,%%r26", xoperands);

-      output_asm_insn ("ldil L'%0,%%r22", xoperands);
-      output_asm_insn ("be R'%0(%%sr4,%%r22)", xoperands);
+         /* Load function address into %r1.  */
+         nbytes += 16;
+         xop[0] = xoperands[0];
+         xop[1] = gen_rtx_REG (Pmode, 1);
+         xop[2] = xop[1];
+         pa_output_pic_pcrel_sequence (xop);

-      if (val_14)
+         output_asm_insn ("bv,n %%r0(%%r1)", xoperands);
+       }
+      else if (TARGET_PORTABLE_RUNTIME)
        {
-         output_asm_insn ("ldo %2(%%r26),%%r26", xoperands);
+         /* Load function address into %r22.  */
          nbytes += 12;
+         output_asm_insn ("ldil L'%0,%%r22", xoperands);
+         output_asm_insn ("ldo R'%0(%%r22),%%r22", xoperands);
+
+         output_asm_insn ("bv %%r0(%%r22)", xoperands);
+
+         /* Add *(*(THIS + DELTA) + VCALL_OFFSET) to THIS.  */
+         output_asm_insn ("addl %%r1,%%r26,%%r26", xoperands);
+       }
+      else if (TARGET_SOM && flag_pic && TREE_PUBLIC (function))
+       {
+         /* Add *(*(THIS + DELTA) + VCALL_OFFSET) to THIS.  */
+         output_asm_insn ("addl %%r1,%%r26,%%r26", xoperands);
+
+         /* The function is accessible from outside this module.  The only
+            way to avoid an import stub between the thunk and function is to
+            call the function directly with an indirect sequence similar to
+            that used by $$dyncall.  This is possible because $$dyncall acts
+            as the import stub in an indirect call.  */
+         ASM_GENERATE_INTERNAL_LABEL (label, "LTHN", current_thunk_number);
+         xoperands[3] = gen_rtx_SYMBOL_REF (Pmode, label);
+         output_asm_insn ("addil LT'%3,%%r19", xoperands);
+         output_asm_insn ("ldw RT'%3(%%r1),%%r22", xoperands);
+         output_asm_insn ("ldw 0(%%sr0,%%r22),%%r22", xoperands);
+         output_asm_insn ("bb,>=,n %%r22,30,.+16", xoperands);
+         output_asm_insn ("depi 0,31,2,%%r22", xoperands);
+         output_asm_insn ("ldw 4(%%sr0,%%r22),%%r19", xoperands);
+         output_asm_insn ("ldw 0(%%sr0,%%r22),%%r22", xoperands);
+
+         if (TARGET_PA_20)
+           {
+             output_asm_insn ("bve,n (%%r22)", xoperands);
+             nbytes += 32;
+           }
+         else if (TARGET_NO_SPACE_REGS)
+           {
+             output_asm_insn ("be,n 0(%%sr4,%%r22)", xoperands);
+             nbytes += 32;
+           }
+         else
+           {
+             output_asm_insn ("ldsid (%%sr0,%%r22),%%r21", xoperands);
+             output_asm_insn ("mtsp %%r21,%%sr0", xoperands);
+             output_asm_insn ("be,n 0(%%sr0,%%r22)", xoperands);
+             nbytes += 40;
+           }
        }
-      else
+      else if (flag_pic)
        {
-         output_asm_insn ("ldo R'%2(%%r1),%%r26", xoperands);
+         /* Add *(*(THIS + DELTA) + VCALL_OFFSET) to THIS.  */
+         output_asm_insn ("addl %%r1,%%r26,%%r26", xoperands);
+
+         /* Load function address into %r1.  */
          nbytes += 16;
+         xop[0] = xoperands[0];
+         xop[1] = gen_rtx_REG (Pmode, 1);
+         xop[2] = xop[1];
+         pa_output_pic_pcrel_sequence (xop);
+
+         output_asm_insn ("bv,n %%r0(%%r1)", xoperands);
+       }
+      else
+       {
+         /* Load function address into %r22.  */
+         nbytes += 8;
+         output_asm_insn ("ldil L'%0,%%r22", xoperands);
+         output_asm_insn ("be R'%0(%%sr4,%%r22)", xoperands);
+
+         /* Add *(*(THIS + DELTA) + VCALL_OFFSET) to THIS.  */
+         output_asm_insn ("addl %%r1,%%r26,%%r26", xoperands);
        }
     }


Reply via email to