/* Variables to handle plabels that we discover are necessary at assembly
output time. They are output after the current function. */
-struct defer_plab
+struct deferred_plabel
{
rtx internal_label;
- rtx symbol;
+ char *name;
} *deferred_plabels = 0;
int n_deferred_plabels = 0;
fputs ("\tnop\n", file);
fputs ("\t.EXIT\n\t.PROCEND\n", file);
-
- /* If we have deferred plabels, then we need to switch into the data
- section and align it to a 4 byte boundary before we output the
- deferred plabels. */
- if (n_deferred_plabels)
- {
- data_section ();
- ASM_OUTPUT_ALIGN (file, 2);
- }
-
- /* Now output the deferred plabels. */
- for (i = 0; i < n_deferred_plabels; i++)
- {
- ASM_OUTPUT_INTERNAL_LABEL (file, "L", CODE_LABEL_NUMBER (deferred_plabels[i].internal_label));
- assemble_integer (deferred_plabels[i].symbol, 4, 1);
- }
- n_deferred_plabels = 0;
}
void
output_addr_const (file, x);
}
+void
+output_deferred_plabels (file)
+ FILE *file;
+{
+ int i;
+ /* If we have deferred plabels, then we need to switch into the data
+ section and align it to a 4 byte boundary before we output the
+ deferred plabels. */
+ if (n_deferred_plabels)
+ {
+ data_section ();
+ ASM_OUTPUT_ALIGN (file, 2);
+ }
+
+ /* Now output the deferred plabels. */
+ for (i = 0; i < n_deferred_plabels; i++)
+ {
+ ASM_OUTPUT_INTERNAL_LABEL (file, "L", CODE_LABEL_NUMBER (deferred_plabels[i].internal_label));
+ assemble_integer (gen_rtx (SYMBOL_REF, VOIDmode,
+ deferred_plabels[i].name), 4, 1);
+ }
+}
+
/* HP's millicode routines mean something special to the assembler.
Keep track of which ones we have used. */
return "";
}
+extern struct obstack permanent_obstack;
+extern struct obstack *saveable_obstack;
+extern struct obstack *rtl_obstack;
+extern struct obstack *current_obstack;
+
/* INSN is either a function call. It may have an unconditional jump
in its delay slot.
output_asm_insn ("ldw -12(%%sr0,%%r30),%R1", xoperands);
output_asm_insn ("ldw -16(%%sr0,%%r30),%1", xoperands);
}
-
}
}
/* Don't have to worry about TARGET_PORTABLE_RUNTIME here since
we don't have any direct calls in that case. */
- if (flag_pic)
{
- /* We have to load the address of the function using a procedure
- label (plabel). The LP and RP relocs don't work reliably for PIC,
- so we make a plain 32 bit plabel in the data segment instead. We
- have to defer outputting it of course... Not pretty. */
+ int i;
+ char *name = XSTR (call_dest, 0);
+
+ /* See if we have already put this function on the list
+ of deferred plabels. This list is generally small,
+ so a liner search is not too ugly. If it proves too
+ slow replace it with something faster. */
+ for (i = 0; i < n_deferred_plabels; i++)
+ if (strcmp (name, deferred_plabels[i].name) == 0)
+ break;
+
+ /* If the deferred plabel list is empty, or this entry was
+ not found on the list, create a new entry on the list. */
+ if (deferred_plabels == NULL || i == n_deferred_plabels)
+ {
+ struct obstack *ambient_obstack = current_obstack;
+ struct obstack *ambient_rtl_obstack = rtl_obstack;
+ char *real_name;
+
+ /* Any RTL we create here needs to live until the end of
+ the compilation unit and therefore must live on the
+ permanent obstack. */
+ current_obstack = &permanent_obstack;
+ rtl_obstack = &permanent_obstack;
+
+ if (deferred_plabels == 0)
+ deferred_plabels = (struct deferred_plabel *)
+ xmalloc (1 * sizeof (struct deferred_plabel));
+ else
+ deferred_plabels = (struct deferred_plabel *)
+ xrealloc (deferred_plabels,
+ ((n_deferred_plabels + 1)
+ * sizeof (struct deferred_plabel)));
+
+ i = n_deferred_plabels++;
+ deferred_plabels[i].internal_label = gen_label_rtx ();
+ deferred_plabels[i].name = obstack_alloc (&permanent_obstack,
+ strlen (name) + 1);
+ strcpy (deferred_plabels[i].name, name);
+
+ /* Switch back to normal obstack allocation. */
+ current_obstack = ambient_obstack;
+ rtl_obstack = ambient_rtl_obstack;
+
+ /* Gross. We have just implicitly taken the address of this
+ function, mark it as such. */
+ STRIP_NAME_ENCODING (real_name, name);
+ TREE_SYMBOL_REFERENCED (get_identifier (real_name)) = 1;
+ }
- xoperands[0] = gen_label_rtx ();
- xoperands[1] = gen_label_rtx ();
- output_asm_insn ("addil LT%%%0,%%r19", xoperands);
- output_asm_insn ("ldw RT%%%0(%%r1),%%r22", xoperands);
- output_asm_insn ("ldw 0(0,%%r22),%%r22", xoperands);
+ /* We have to load the address of the function using a procedure
+ label (plabel). Inline plabels can lose for PIC and other
+ cases, so avoid them by creating a 32bit plabel in the data
+ segment. */
+ if (flag_pic)
+ {
+ xoperands[0] = deferred_plabels[i].internal_label;
+ xoperands[1] = gen_label_rtx ();
- if (deferred_plabels == 0)
- deferred_plabels = (struct defer_plab *)
- xmalloc (1 * sizeof (struct defer_plab));
- else
- deferred_plabels = (struct defer_plab *)
- xrealloc (deferred_plabels,
- (n_deferred_plabels + 1) * sizeof (struct defer_plab));
- deferred_plabels[n_deferred_plabels].internal_label = xoperands[0];
- deferred_plabels[n_deferred_plabels].symbol = call_dest;
- n_deferred_plabels++;
+ output_asm_insn ("addil LT%%%0,%%r19", xoperands);
+ output_asm_insn ("ldw RT%%%0(%%r1),%%r22", xoperands);
+ output_asm_insn ("ldw 0(0,%%r22),%%r22", xoperands);
- /* Get our address + 8 into %r1. */
- output_asm_insn ("bl .+8,%%r1", xoperands);
+ /* Get our address + 8 into %r1. */
+ output_asm_insn ("bl .+8,%%r1", xoperands);
- /* Add %r1 to the offset of dyncall from the next insn. */
- output_asm_insn ("addil L%%$$dyncall-%1,%%r1", xoperands);
- ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L",
- CODE_LABEL_NUMBER (xoperands[1]));
- output_asm_insn ("ldo R%%$$dyncall-%1(%%r1),%%r1", xoperands);
+ /* Add %r1 to the offset of dyncall from the next insn. */
+ output_asm_insn ("addil L%%$$dyncall-%1,%%r1", xoperands);
+ ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L",
+ CODE_LABEL_NUMBER (xoperands[1]));
+ output_asm_insn ("ldo R%%$$dyncall-%1(%%r1),%%r1", xoperands);
- /* Get the return address into %r31. */
- output_asm_insn ("blr 0,%%r31", xoperands);
+ /* Get the return address into %r31. */
+ output_asm_insn ("blr 0,%%r31", xoperands);
- /* Branch to our target which is in %r1. */
- output_asm_insn ("bv 0(%%r1)", xoperands);
+ /* Branch to our target which is in %r1. */
+ output_asm_insn ("bv 0(%%r1)", xoperands);
- /* Copy the return address into %r2 also. */
- output_asm_insn ("copy %%r31,%%r2", xoperands);
- }
- else
- {
- /* No PIC stuff to worry about. We can use ldil;ble. */
- xoperands[0] = call_dest;
+ /* Copy the return address into %r2 also. */
+ output_asm_insn ("copy %%r31,%%r2", xoperands);
+ }
+ else
+ {
+ xoperands[0] = deferred_plabels[i].internal_label;
- /* Get the address of our target into %r22. */
- output_asm_insn ("ldil LP%%%0,%%r22", xoperands);
- output_asm_insn ("ldo RP%%%0(%%r22),%%r22", xoperands);
+ /* Get the address of our target into %r22. */
+ output_asm_insn ("addil LR%%%0-$global$,%%r27", xoperands);
+ output_asm_insn ("ldw RR%%%0-$global$(%%r1),%%r22", xoperands);
- /* Get the high part of the address of $dyncall into %r2, then
- add in the low part in the branch instruction. */
- output_asm_insn ("ldil L%%$$dyncall,%%r2", xoperands);
- output_asm_insn ("ble R%%$$dyncall(%%sr4,%%r2)", xoperands);
+ /* Get the high part of the address of $dyncall into %r2, then
+ add in the low part in the branch instruction. */
+ output_asm_insn ("ldil L%%$$dyncall,%%r2", xoperands);
+ output_asm_insn ("ble R%%$$dyncall(%%sr4,%%r2)", xoperands);
- /* Copy the return pointer into both %r31 and %r2. */
- output_asm_insn ("copy %%r31,%%r2", xoperands);
+ /* Copy the return pointer into both %r31 and %r2. */
+ output_asm_insn ("copy %%r31,%%r2", xoperands);
+ }
}
/* If we had a jump in the call's delay slot, output it now. */
return "";
}
-extern struct obstack permanent_obstack;
-extern struct obstack *saveable_obstack;
-
/* In HPUX 8.0's shared library scheme, special relocations are needed
for function labels if they might be passed to a function
in a shared library (because shared libraries don't live in code
[(set_attr "type" "binary,binary")
(set_attr "length" "4,8")])
-;; For function addresses.
-(define_insn ""
- [(set (match_operand:SI 0 "register_operand" "=r")
- (high:SI (match_operand:SI 1 "function_label_operand" "")))]
- "!TARGET_PORTABLE_RUNTIME"
- "ldil LP'%G1,%0"
- [(set_attr "type" "move")
- (set_attr "length" "4")])
-
-;; This version is used only for the portable runtime conventions model
-;; (it does not use/support plabels)
-(define_insn ""
- [(set (match_operand:SI 0 "register_operand" "=r")
- (high:SI (match_operand:SI 1 "function_label_operand" "")))]
- "TARGET_PORTABLE_RUNTIME"
- "ldil L'%G1,%0"
- [(set_attr "type" "move")
- (set_attr "length" "4")])
-
(define_insn ""
[(set (match_operand:SI 0 "register_operand" "=r")
(high:SI (match_operand 1 "" "")))]
[(set_attr "type" "move")
(set_attr "length" "4")])
-;; lo_sum of a function address.
-;;
-;; Note since we are not supporting MPE style external calls we can
-;; use the short ldil;ldo sequence. If one wanted to support
-;; MPE external calls you would want to generate something like
-;; ldil;ldo;extru;ldw;add. See the HP compiler's output for details.
-(define_insn ""
- [(set (match_operand:SI 0 "register_operand" "=r")
- (lo_sum:SI (match_operand:SI 1 "register_operand" "r")
- (match_operand:SI 2 "function_label_operand" "")))]
- "!TARGET_PORTABLE_RUNTIME"
- "ldo RP'%G2(%1),%0"
- [(set_attr "type" "move")
- (set_attr "length" "4")])
-
-;; This version is used only for the portable runtime conventions model
-;; (it does not use/support plabels)
-(define_insn ""
- [(set (match_operand:SI 0 "register_operand" "=r")
- (lo_sum:SI (match_operand:SI 1 "register_operand" "r")
- (match_operand:SI 2 "function_label_operand" "")))]
- "TARGET_PORTABLE_RUNTIME"
- "ldo R'%G2(%1),%0"
- [(set_attr "type" "move")
- (set_attr "length" "4")])
-
(define_insn ""
[(set (match_operand:SI 0 "register_operand" "=r")
(lo_sum:SI (match_operand:SI 1 "register_operand" "r")
(const_int 12)
(const_int 16))))))])
-;; Simply another variant of the dbra pattern. More restrictive
-;; in testing the comparison operator as it must worry about overflow
-;; problems.
-(define_insn ""
- [(set (pc)
- (if_then_else
- (match_operator 2 "eq_neq_comparison_operator"
- [(match_operand:SI 0 "register_operand" "+!r,!*f,!*m")
- (match_operand:SI 5 "const_int_operand" "")])
- (label_ref (match_operand 3 "" ""))
- (pc)))
- (set (match_dup 0)
- (plus:SI (match_dup 0) (match_operand:SI 1 "int5_operand" "L,L,L")))
- (clobber (match_scratch:SI 4 "=X,r,r"))]
- "INTVAL (operands[5]) == - INTVAL (operands[1])"
-"* return output_dbra (operands, insn, which_alternative);"
-;; Do not expect to understand this the first time through.
-[(set_attr "type" "cbranch,multi,multi")
- (set (attr "length")
- (if_then_else (eq_attr "alternative" "0")
-;; Loop counter in register case
-;; Short branch has length of 4
-;; Long branch has length of 8
- (if_then_else (lt (abs (minus (match_dup 3) (plus (pc) (const_int 8))))
- (const_int 8184))
- (const_int 4)
- (const_int 8))
-
-;; Loop counter in FP reg case.
-;; Extra goo to deal with additional reload insns.
- (if_then_else (eq_attr "alternative" "1")
- (if_then_else (lt (match_dup 3) (pc))
- (if_then_else
- (lt (abs (minus (match_dup 3) (plus (pc) (const_int 24))))
- (const_int 8184))
- (const_int 24)
- (const_int 28))
- (if_then_else
- (lt (abs (minus (match_dup 3) (plus (pc) (const_int 8))))
- (const_int 8184))
- (const_int 24)
- (const_int 28)))
-;; Loop counter in memory case.
-;; Extra goo to deal with additional reload insns.
- (if_then_else (lt (match_dup 3) (pc))
- (if_then_else
- (lt (abs (minus (match_dup 3) (plus (pc) (const_int 12))))
- (const_int 8184))
- (const_int 12)
- (const_int 16))
- (if_then_else
- (lt (abs (minus (match_dup 3) (plus (pc) (const_int 8))))
- (const_int 8184))
- (const_int 12)
- (const_int 16))))))])
-
(define_insn ""
[(set (pc)
(if_then_else