Commit 359255a9 by Jeff Law

pa.md (alternate dbra pattern): Remove incorrect pattern.

        * pa.md (alternate dbra pattern): Remove incorrect pattern.

        * pa.c (struct defer_plab): Renamed to struct deferred_plabel.
        Remove "symbol" field and replace with "name" field.
        (output_function_epilogue): Don't output deferred plabels here.
        (output_deferred_labels): New function.  Output them here instead.
        (output_call): Rewrite long call support.
        * pa.h (ASM_FILE_END): Define.
        (LEGITIMATE_CONSTANT_P): Never accept a function_label_operand.
        * pa.md (HIGH and LO_SUM of function address): Remove patterns.

From-SVN: r14171
parent 6c48ca54
...@@ -70,10 +70,10 @@ unsigned int total_code_bytes; ...@@ -70,10 +70,10 @@ unsigned int total_code_bytes;
/* Variables to handle plabels that we discover are necessary at assembly /* Variables to handle plabels that we discover are necessary at assembly
output time. They are output after the current function. */ output time. They are output after the current function. */
struct defer_plab struct deferred_plabel
{ {
rtx internal_label; rtx internal_label;
rtx symbol; char *name;
} *deferred_plabels = 0; } *deferred_plabels = 0;
int n_deferred_plabels = 0; int n_deferred_plabels = 0;
...@@ -2898,23 +2898,6 @@ output_function_epilogue (file, size) ...@@ -2898,23 +2898,6 @@ output_function_epilogue (file, size)
fputs ("\tnop\n", file); fputs ("\tnop\n", file);
fputs ("\t.EXIT\n\t.PROCEND\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 void
...@@ -3900,6 +3883,29 @@ output_global_address (file, x, round_constant) ...@@ -3900,6 +3883,29 @@ output_global_address (file, x, round_constant)
output_addr_const (file, x); 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. /* HP's millicode routines mean something special to the assembler.
Keep track of which ones we have used. */ Keep track of which ones we have used. */
...@@ -5039,6 +5045,11 @@ output_millicode_call (insn, call_dest) ...@@ -5039,6 +5045,11 @@ output_millicode_call (insn, call_dest)
return ""; 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 /* INSN is either a function call. It may have an unconditional jump
in its delay slot. in its delay slot.
...@@ -5128,70 +5139,109 @@ output_call (insn, call_dest) ...@@ -5128,70 +5139,109 @@ output_call (insn, call_dest)
output_asm_insn ("ldw -12(%%sr0,%%r30),%R1", xoperands); output_asm_insn ("ldw -12(%%sr0,%%r30),%R1", xoperands);
output_asm_insn ("ldw -16(%%sr0,%%r30),%1", xoperands); output_asm_insn ("ldw -16(%%sr0,%%r30),%1", xoperands);
} }
} }
} }
/* Don't have to worry about TARGET_PORTABLE_RUNTIME here since /* Don't have to worry about TARGET_PORTABLE_RUNTIME here since
we don't have any direct calls in that case. */ 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 int i;
label (plabel). The LP and RP relocs don't work reliably for PIC, char *name = XSTR (call_dest, 0);
so we make a plain 32 bit plabel in the data segment instead. We
have to defer outputting it of course... Not pretty. */ /* 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 (); /* We have to load the address of the function using a procedure
xoperands[1] = gen_label_rtx (); label (plabel). Inline plabels can lose for PIC and other
output_asm_insn ("addil LT%%%0,%%r19", xoperands); cases, so avoid them by creating a 32bit plabel in the data
output_asm_insn ("ldw RT%%%0(%%r1),%%r22", xoperands); segment. */
output_asm_insn ("ldw 0(0,%%r22),%%r22", xoperands); if (flag_pic)
{
xoperands[0] = deferred_plabels[i].internal_label;
xoperands[1] = gen_label_rtx ();
if (deferred_plabels == 0) output_asm_insn ("addil LT%%%0,%%r19", xoperands);
deferred_plabels = (struct defer_plab *) output_asm_insn ("ldw RT%%%0(%%r1),%%r22", xoperands);
xmalloc (1 * sizeof (struct defer_plab)); output_asm_insn ("ldw 0(0,%%r22),%%r22", xoperands);
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++;
/* Get our address + 8 into %r1. */ /* Get our address + 8 into %r1. */
output_asm_insn ("bl .+8,%%r1", xoperands); output_asm_insn ("bl .+8,%%r1", xoperands);
/* Add %r1 to the offset of dyncall from the next insn. */ /* Add %r1 to the offset of dyncall from the next insn. */
output_asm_insn ("addil L%%$$dyncall-%1,%%r1", xoperands); output_asm_insn ("addil L%%$$dyncall-%1,%%r1", xoperands);
ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L", ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L",
CODE_LABEL_NUMBER (xoperands[1])); CODE_LABEL_NUMBER (xoperands[1]));
output_asm_insn ("ldo R%%$$dyncall-%1(%%r1),%%r1", xoperands); output_asm_insn ("ldo R%%$$dyncall-%1(%%r1),%%r1", xoperands);
/* Get the return address into %r31. */ /* Get the return address into %r31. */
output_asm_insn ("blr 0,%%r31", xoperands); output_asm_insn ("blr 0,%%r31", xoperands);
/* Branch to our target which is in %r1. */ /* Branch to our target which is in %r1. */
output_asm_insn ("bv 0(%%r1)", xoperands); output_asm_insn ("bv 0(%%r1)", xoperands);
/* Copy the return address into %r2 also. */ /* Copy the return address into %r2 also. */
output_asm_insn ("copy %%r31,%%r2", xoperands); output_asm_insn ("copy %%r31,%%r2", xoperands);
} }
else else
{ {
/* No PIC stuff to worry about. We can use ldil;ble. */ xoperands[0] = deferred_plabels[i].internal_label;
xoperands[0] = call_dest;
/* Get the address of our target into %r22. */ /* Get the address of our target into %r22. */
output_asm_insn ("ldil LP%%%0,%%r22", xoperands); output_asm_insn ("addil LR%%%0-$global$,%%r27", xoperands);
output_asm_insn ("ldo RP%%%0(%%r22),%%r22", xoperands); output_asm_insn ("ldw RR%%%0-$global$(%%r1),%%r22", xoperands);
/* Get the high part of the address of $dyncall into %r2, then /* Get the high part of the address of $dyncall into %r2, then
add in the low part in the branch instruction. */ add in the low part in the branch instruction. */
output_asm_insn ("ldil L%%$$dyncall,%%r2", xoperands); output_asm_insn ("ldil L%%$$dyncall,%%r2", xoperands);
output_asm_insn ("ble R%%$$dyncall(%%sr4,%%r2)", xoperands); output_asm_insn ("ble R%%$$dyncall(%%sr4,%%r2)", xoperands);
/* Copy the return pointer into both %r31 and %r2. */ /* Copy the return pointer into both %r31 and %r2. */
output_asm_insn ("copy %%r31,%%r2", xoperands); output_asm_insn ("copy %%r31,%%r2", xoperands);
}
} }
/* If we had a jump in the call's delay slot, output it now. */ /* If we had a jump in the call's delay slot, output it now. */
...@@ -5244,9 +5294,6 @@ output_call (insn, call_dest) ...@@ -5244,9 +5294,6 @@ output_call (insn, call_dest)
return ""; return "";
} }
extern struct obstack permanent_obstack;
extern struct obstack *saveable_obstack;
/* In HPUX 8.0's shared library scheme, special relocations are needed /* In HPUX 8.0's shared library scheme, special relocations are needed
for function labels if they might be passed to a function for function labels if they might be passed to a function
in a shared library (because shared libraries don't live in code in a shared library (because shared libraries don't live in code
......
...@@ -1376,7 +1376,7 @@ extern struct rtx_def *hppa_builtin_saveregs (); ...@@ -1376,7 +1376,7 @@ extern struct rtx_def *hppa_builtin_saveregs ();
#define LEGITIMATE_CONSTANT_P(X) \ #define LEGITIMATE_CONSTANT_P(X) \
((GET_MODE_CLASS (GET_MODE (X)) != MODE_FLOAT \ ((GET_MODE_CLASS (GET_MODE (X)) != MODE_FLOAT \
|| (X) == CONST0_RTX (GET_MODE (X))) \ || (X) == CONST0_RTX (GET_MODE (X))) \
&& !(flag_pic && function_label_operand (X, VOIDmode))) && !function_label_operand (X, VOIDmode))
/* Subroutine for EXTRA_CONSTRAINT. /* Subroutine for EXTRA_CONSTRAINT.
...@@ -1931,6 +1931,8 @@ do { fputs ("\t.SPACE $PRIVATE$\n\ ...@@ -1931,6 +1931,8 @@ do { fputs ("\t.SPACE $PRIVATE$\n\
output_file_directive ((FILE), main_input_filename); \ output_file_directive ((FILE), main_input_filename); \
} while (0) } while (0)
#define ASM_FILE_END(FILE) output_deferred_plabels (FILE)
/* Output to assembler file text saying following lines /* Output to assembler file text saying following lines
may contain character constants, extra white space, comments, etc. */ may contain character constants, extra white space, comments, etc. */
......
...@@ -1585,25 +1585,6 @@ ...@@ -1585,25 +1585,6 @@
[(set_attr "type" "binary,binary") [(set_attr "type" "binary,binary")
(set_attr "length" "4,8")]) (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 "" (define_insn ""
[(set (match_operand:SI 0 "register_operand" "=r") [(set (match_operand:SI 0 "register_operand" "=r")
(high:SI (match_operand 1 "" "")))] (high:SI (match_operand 1 "" "")))]
...@@ -1619,32 +1600,6 @@ ...@@ -1619,32 +1600,6 @@
[(set_attr "type" "move") [(set_attr "type" "move")
(set_attr "length" "4")]) (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 "" (define_insn ""
[(set (match_operand:SI 0 "register_operand" "=r") [(set (match_operand:SI 0 "register_operand" "=r")
(lo_sum:SI (match_operand:SI 1 "register_operand" "r") (lo_sum:SI (match_operand:SI 1 "register_operand" "r")
...@@ -4578,62 +4533,6 @@ ...@@ -4578,62 +4533,6 @@
(const_int 12) (const_int 12)
(const_int 16))))))]) (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 "" (define_insn ""
[(set (pc) [(set (pc)
(if_then_else (if_then_else
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment