alpha.c (alpha_return_addr_rtx): New variable.
* alpha.c (alpha_return_addr_rtx): New variable. (alpha_save_machine_status): New; save it. (alpha_restore_machine_status): New; restore it. (alpha_init_expanders): New; clear it. (alpha_return_addr): New; set it. (alpha_ra_ever_killed): New; if alpha_return_addr_rtx, regs_ever_live is overly conservative, so search the insns explicitly. (alpha_sa_mask [VMS]): Check alpha_ra_ever_killed. (alpha_sa_size [VMS && !VMS]): Likewise. * alpha.h (RETURN_ADDR_RTX): Call alpha_return_addr. (INIT_EXPANDERS): New definition. * alpha.c: Move REG_PV, REG_RA somewhere more visible in the file. (output_prolog [!VMS]): Use them. * alpha.c (output_prolog [!VMS]): Move gp detection to ... (alpha_does_function_need_gp): ... a new function. Refine the CALL_INSN test to just TYPE_JSR. * alpha.md (most call insns): Fix some jsr/ibr type transpositions. From-SVN: r15936
This commit is contained in:
parent
bda2ffefc8
commit
9ecc37f0e2
@ -1,3 +1,25 @@
|
||||
Thu Oct 16 11:20:30 1997 Richard Henderson <rth@cygnus.com>
|
||||
|
||||
* alpha.c (alpha_return_addr_rtx): New variable.
|
||||
(alpha_save_machine_status): New; save it.
|
||||
(alpha_restore_machine_status): New; restore it.
|
||||
(alpha_init_expanders): New; clear it.
|
||||
(alpha_return_addr): New; set it.
|
||||
(alpha_ra_ever_killed): New; if alpha_return_addr_rtx, regs_ever_live
|
||||
is overly conservative, so search the insns explicitly.
|
||||
(alpha_sa_mask [VMS]): Check alpha_ra_ever_killed.
|
||||
(alpha_sa_size [VMS && !VMS]): Likewise.
|
||||
* alpha.h (RETURN_ADDR_RTX): Call alpha_return_addr.
|
||||
(INIT_EXPANDERS): New definition.
|
||||
|
||||
* alpha.c: Move REG_PV, REG_RA somewhere more visible in the file.
|
||||
(output_prolog [!VMS]): Use them.
|
||||
|
||||
* alpha.c (output_prolog [!VMS]): Move gp detection to ...
|
||||
(alpha_does_function_need_gp): ... a new function. Refine the
|
||||
CALL_INSN test to just TYPE_JSR.
|
||||
* alpha.md (most call insns): Fix some jsr/ibr type transpositions.
|
||||
|
||||
Thu Oct 16 09:36:47 1997 Jeffrey A Law (law@cygnus.com)
|
||||
|
||||
* version.c: Bump for snapshot.
|
||||
|
@ -37,8 +37,15 @@ Boston, MA 02111-1307, USA. */
|
||||
#include "expr.h"
|
||||
#include "obstack.h"
|
||||
#include "tree.h"
|
||||
#include "except.h"
|
||||
#include "function.h"
|
||||
|
||||
/* External data. */
|
||||
extern char *version_string;
|
||||
extern int rtx_equal_function_value_matters;
|
||||
|
||||
/* Specify which cpu to schedule for. */
|
||||
|
||||
enum processor_type alpha_cpu;
|
||||
|
||||
/* Specify how accurate floating-point traps need to be. */
|
||||
@ -54,6 +61,7 @@ enum alpha_fp_rounding_mode alpha_fprm;
|
||||
enum alpha_fp_trap_mode alpha_fptm;
|
||||
|
||||
/* Strings decoded into the above options. */
|
||||
|
||||
char *alpha_cpu_string; /* -mcpu=ev[4|5] */
|
||||
char *alpha_tp_string; /* -mtrap-precision=[p|s|i] */
|
||||
char *alpha_fprm_string; /* -mfp-rounding-mode=[n|m|c|d] */
|
||||
@ -79,8 +87,9 @@ static int inside_function = FALSE;
|
||||
|
||||
int alpha_function_needs_gp;
|
||||
|
||||
extern char *version_string;
|
||||
extern int rtx_equal_function_value_matters;
|
||||
/* If non-null, this rtx holds the return address for the function. */
|
||||
|
||||
static rtx alpha_return_addr_rtx;
|
||||
|
||||
/* Declarations of static functions. */
|
||||
static void alpha_set_memflags_1 PROTO((rtx, int, int, int));
|
||||
@ -91,10 +100,16 @@ static void add_long_const PROTO((FILE *, HOST_WIDE_INT, int, int, int));
|
||||
/* Compute the size of the save area in the stack. */
|
||||
static void alpha_sa_mask PROTO((unsigned long *imaskP,
|
||||
unsigned long *fmaskP));
|
||||
|
||||
/* Strip type information. */
|
||||
#define CURRENT_FUNCTION_ARGS_INFO \
|
||||
(TARGET_OPEN_VMS ? current_function_args_info & 0xff \
|
||||
: current_function_args_info)
|
||||
|
||||
/* Some helpful register info. */
|
||||
#define REG_PV 27
|
||||
#define REG_RA 26
|
||||
|
||||
|
||||
/* Parse target option strings. */
|
||||
|
||||
@ -1269,6 +1284,87 @@ alpha_adjust_cost (insn, link, dep_insn, cost)
|
||||
/* Otherwise, return the default cost. */
|
||||
return cost;
|
||||
}
|
||||
|
||||
/* Functions to save and restore alpha_return_addr_rtx. */
|
||||
|
||||
struct machine_function
|
||||
{
|
||||
rtx ra_rtx;
|
||||
};
|
||||
|
||||
static void
|
||||
alpha_save_machine_status (p)
|
||||
struct function *p;
|
||||
{
|
||||
struct machine_function *machine =
|
||||
(struct machine_function *) xmalloc (sizeof (struct machine_function));
|
||||
|
||||
p->machine = machine;
|
||||
machine->ra_rtx = alpha_return_addr_rtx;
|
||||
}
|
||||
|
||||
static void
|
||||
alpha_restore_machine_status (p)
|
||||
struct function *p;
|
||||
{
|
||||
struct machine_function *machine = p->machine;
|
||||
|
||||
alpha_return_addr_rtx = machine->ra_rtx;
|
||||
|
||||
free (machine);
|
||||
p->machine = (struct machine_function *)0;
|
||||
}
|
||||
|
||||
/* Do anything needed before RTL is emitted for each function. */
|
||||
|
||||
void
|
||||
alpha_init_expanders ()
|
||||
{
|
||||
alpha_return_addr_rtx = NULL_RTX;
|
||||
|
||||
/* Arrange to save and restore machine status around nested functions. */
|
||||
save_machine_status = alpha_save_machine_status;
|
||||
restore_machine_status = alpha_restore_machine_status;
|
||||
}
|
||||
|
||||
/* Start the ball rolling with RETURN_ADDR_RTX. */
|
||||
|
||||
rtx
|
||||
alpha_return_addr (count, frame)
|
||||
int count;
|
||||
rtx frame;
|
||||
{
|
||||
rtx init, first;
|
||||
|
||||
if (count != 0)
|
||||
return const0_rtx;
|
||||
|
||||
if (alpha_return_addr_rtx)
|
||||
return alpha_return_addr_rtx;
|
||||
|
||||
/* No rtx yet. Invent one, and initialize it from $26 in the prologue. */
|
||||
alpha_return_addr_rtx = gen_reg_rtx (Pmode);
|
||||
init = gen_rtx (SET, Pmode, alpha_return_addr_rtx, gen_rtx (REG, Pmode, 26));
|
||||
|
||||
/* Emit the insn to the prologue with the other argument copies. */
|
||||
push_topmost_sequence ();
|
||||
emit_insn_after (init, get_insns ());
|
||||
pop_topmost_sequence ();
|
||||
|
||||
return alpha_return_addr_rtx;
|
||||
}
|
||||
|
||||
static int
|
||||
alpha_ra_ever_killed ()
|
||||
{
|
||||
rtx i, ra;
|
||||
|
||||
if (!alpha_return_addr_rtx)
|
||||
return regs_ever_live[REG_RA];
|
||||
|
||||
return reg_set_between_p (gen_rtx (REG, REG_RA), get_insns(), NULL_RTX);
|
||||
}
|
||||
|
||||
|
||||
/* Print an operand. Recognize special options, documented below. */
|
||||
|
||||
@ -1661,9 +1757,6 @@ alpha_builtin_saveregs (arglist)
|
||||
|
||||
#if OPEN_VMS
|
||||
|
||||
#define REG_PV 27
|
||||
#define REG_RA 26
|
||||
|
||||
/* These variables are used for communication between the following functions.
|
||||
They indicate various things about the current function being compiled
|
||||
that are used to tell what kind of prologue, epilogue and procedure
|
||||
@ -1700,13 +1793,16 @@ alpha_sa_mask (imaskP, fmaskP)
|
||||
/* One for every register we have to save. */
|
||||
|
||||
for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
|
||||
if (! fixed_regs[i] && ! call_used_regs[i] && regs_ever_live[i])
|
||||
if (! fixed_regs[i] && ! call_used_regs[i]
|
||||
&& regs_ever_live[i] && i != REG_RA)
|
||||
{
|
||||
if (i < 32)
|
||||
imask |= (1L << i);
|
||||
else
|
||||
fmask |= (1L << (i - 32));
|
||||
}
|
||||
if (alpha_ra_ever_killed ())
|
||||
imask |= (1L << REG_RA);
|
||||
|
||||
*imaskP = imask;
|
||||
*fmaskP = fmask;
|
||||
@ -1724,13 +1820,14 @@ alpha_sa_size ()
|
||||
/* One for every register we have to save. */
|
||||
|
||||
for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
|
||||
if (! fixed_regs[i] && ! call_used_regs[i] && regs_ever_live[i])
|
||||
if (! fixed_regs[i] && ! call_used_regs[i]
|
||||
&& regs_ever_live[i] && i != REG_RA)
|
||||
sa_size++;
|
||||
|
||||
/* Start by assuming we can use a register procedure if we don't make any
|
||||
calls (REG_RA not used) or need to save any registers and a stack
|
||||
procedure if we do. */
|
||||
is_stack_procedure = regs_ever_live[REG_RA] || sa_size != 0;
|
||||
is_stack_procedure = sa_size != 0 || alpha_ra_ever_killed ();
|
||||
|
||||
/* Decide whether to refer to objects off our PV via FP or PV.
|
||||
If we need need FP for something else or if we receive a nonlocal
|
||||
@ -1788,12 +1885,13 @@ alpha_sa_size ()
|
||||
int i;
|
||||
|
||||
for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
|
||||
if (! fixed_regs[i] && ! call_used_regs[i] && regs_ever_live[i])
|
||||
if (! fixed_regs[i] && ! call_used_regs[i]
|
||||
&& regs_ever_live[i] && i != REG_RA)
|
||||
size++;
|
||||
|
||||
/* If some registers were saved but not reg 26, reg 26 must also
|
||||
be saved, so leave space for it. */
|
||||
if (size != 0 && ! regs_ever_live[26])
|
||||
if (size != 0 || alpha_ra_ever_killed ())
|
||||
size++;
|
||||
|
||||
/* Our size must be even (multiple of 16 bytes). */
|
||||
@ -2333,6 +2431,37 @@ output_epilog (file, size)
|
||||
|
||||
#else /* !OPEN_VMS */
|
||||
|
||||
static int
|
||||
alpha_does_function_need_gp ()
|
||||
{
|
||||
rtx insn;
|
||||
|
||||
/* We never need a GP for Windows/NT. */
|
||||
if (TARGET_WINDOWS_NT)
|
||||
return 0;
|
||||
|
||||
#ifdef TARGET_PROFILING_NEEDS_GP
|
||||
if (profile_flag)
|
||||
return 1;
|
||||
#endif
|
||||
|
||||
/* If we need a GP (we have a LDSYM insn or a CALL_INSN), load it first.
|
||||
Even if we are a static function, we still need to do this in case
|
||||
our address is taken and passed to something like qsort. */
|
||||
|
||||
for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
|
||||
if (GET_RTX_CLASS (GET_CODE (insn)) == 'i'
|
||||
&& GET_CODE (PATTERN (insn)) != USE
|
||||
&& GET_CODE (PATTERN (insn)) != CLOBBER)
|
||||
{
|
||||
enum attr_type type = get_attr_type (insn);
|
||||
if (type == TYPE_LDSYM || type == TYPE_JSR)
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
output_prolog (file, size)
|
||||
FILE *file;
|
||||
@ -2348,7 +2477,6 @@ output_prolog (file, size)
|
||||
HOST_WIDE_INT start_reg_offset = reg_offset;
|
||||
HOST_WIDE_INT actual_start_reg_offset = start_reg_offset;
|
||||
int int_reg_save_area_size = 0;
|
||||
rtx insn;
|
||||
unsigned reg_mask = 0;
|
||||
int i, sa_reg;
|
||||
|
||||
@ -2393,30 +2521,7 @@ output_prolog (file, size)
|
||||
alpha_auto_offset = -frame_size + current_function_pretend_args_size;
|
||||
alpha_arg_offset = -frame_size + 48;
|
||||
|
||||
/* If we need a GP (we have a LDSYM insn or a CALL_INSN), load it first.
|
||||
Even if we are a static function, we still need to do this in case
|
||||
our address is taken and passed to something like qsort.
|
||||
|
||||
We never need a GP for Windows/NT. */
|
||||
|
||||
alpha_function_needs_gp = 0;
|
||||
|
||||
#ifdef TARGET_PROFILING_NEEDS_GP
|
||||
if (profile_flag)
|
||||
alpha_function_needs_gp = 1;
|
||||
#endif
|
||||
|
||||
for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
|
||||
if ((GET_CODE (insn) == CALL_INSN)
|
||||
|| (GET_RTX_CLASS (GET_CODE (insn)) == 'i'
|
||||
&& GET_CODE (PATTERN (insn)) != USE
|
||||
&& GET_CODE (PATTERN (insn)) != CLOBBER
|
||||
&& (get_attr_type (insn) == TYPE_LDSYM
|
||||
|| get_attr_type (insn) == TYPE_ISUBR)))
|
||||
{
|
||||
alpha_function_needs_gp = 1;
|
||||
break;
|
||||
}
|
||||
alpha_function_needs_gp = alpha_does_function_need_gp ();
|
||||
|
||||
if (TARGET_WINDOWS_NT == 0)
|
||||
{
|
||||
@ -2515,10 +2620,10 @@ output_prolog (file, size)
|
||||
sa_reg = 24;
|
||||
}
|
||||
|
||||
/* Save register 26 if any other register needs to be saved. */
|
||||
/* Save register RA if any other register needs to be saved. */
|
||||
if (sa_size != 0)
|
||||
{
|
||||
reg_mask |= 1 << 26;
|
||||
reg_mask |= 1 << REG_RA;
|
||||
fprintf (file, "\tstq $26,%d($%d)\n", reg_offset, sa_reg);
|
||||
reg_offset += 8;
|
||||
int_reg_save_area_size += 8;
|
||||
@ -2526,7 +2631,8 @@ output_prolog (file, size)
|
||||
|
||||
/* Now save any other used integer registers required to be saved. */
|
||||
for (i = 0; i < 32; i++)
|
||||
if (! fixed_regs[i] && ! call_used_regs[i] && regs_ever_live[i] && i != 26)
|
||||
if (! fixed_regs[i] && ! call_used_regs[i]
|
||||
&& regs_ever_live[i] && i != REG_RA)
|
||||
{
|
||||
reg_mask |= 1 << i;
|
||||
fprintf (file, "\tstq $%d,%d($%d)\n", i, reg_offset, sa_reg);
|
||||
|
@ -1255,16 +1255,17 @@ __enable_execute_stack (addr) \
|
||||
/* A C expression whose value is RTL representing the value of the return
|
||||
address for the frame COUNT steps up from the current frame.
|
||||
FRAMEADDR is the frame pointer of the COUNT frame, or the frame pointer of
|
||||
the COUNT-1 frame if RETURN_ADDR_IN_PREVIOUS_FRAME} is defined.
|
||||
the COUNT-1 frame if RETURN_ADDR_IN_PREVIOUS_FRAME} is defined. */
|
||||
|
||||
This definition for Alpha is broken, but is put in at the request of
|
||||
Mike Stump. */
|
||||
#define RETURN_ADDR_RTX alpha_return_addr
|
||||
extern struct rtx_def *alpha_return_addr ();
|
||||
|
||||
/* Initialize data used by insn expanders. This is called from insn_emit,
|
||||
once for every function before code is generated. */
|
||||
|
||||
#define INIT_EXPANDERS alpha_init_expanders ()
|
||||
extern void alpha_init_expanders ();
|
||||
|
||||
#define RETURN_ADDR_RTX(COUNT, FRAME) \
|
||||
((COUNT == 0 && alpha_sa_size () == 0 && 0 /* not right. */) \
|
||||
? gen_rtx (REG, Pmode, 26) \
|
||||
: gen_rtx (MEM, Pmode, \
|
||||
memory_address (Pmode, FRAME)))
|
||||
|
||||
/* Addressing modes, and classification of registers for them. */
|
||||
|
||||
|
@ -33,7 +33,7 @@
|
||||
;; separately.
|
||||
|
||||
(define_attr "type"
|
||||
"ld,st,ibr,fbr,jsr,iadd,ilog,shift,cmov,icmp,imull,imulq,imulh,fadd,fmul,fcpys,fdivs,fdivt,ldsym,isubr,misc"
|
||||
"ld,st,ibr,fbr,jsr,iadd,ilog,shift,cmov,icmp,imull,imulq,imulh,fadd,fmul,fcpys,fdivs,fdivt,ldsym,misc"
|
||||
(const_string "iadd"))
|
||||
|
||||
;; The TRAP_TYPE attribute marks instructions that may generate traps
|
||||
@ -744,7 +744,7 @@
|
||||
; (clobber (reg:DI 28))]
|
||||
; "!TARGET_OPEN_VMS"
|
||||
; "%E1 $24,$25,$27"
|
||||
; [(set_attr "type" "isubr")])
|
||||
; [(set_attr "type" "jsr")])
|
||||
|
||||
(define_insn ""
|
||||
[(set (reg:DI 27)
|
||||
@ -754,7 +754,7 @@
|
||||
(clobber (reg:DI 28))]
|
||||
"!TARGET_OPEN_VMS"
|
||||
"%E1 $24,$25,$27"
|
||||
[(set_attr "type" "isubr")])
|
||||
[(set_attr "type" "jsr")])
|
||||
|
||||
;; Next are the basic logical operations. These only exist in DImode.
|
||||
|
||||
@ -3289,7 +3289,7 @@
|
||||
jsr $26,($27),0\;ldgp $29,0($26)
|
||||
bsr $26,%0..ng
|
||||
jsr $26,%0\;ldgp $29,0($26)"
|
||||
[(set_attr "type" "jsr,jsr,ibr")])
|
||||
[(set_attr "type" "jsr,ibr,jsr")])
|
||||
|
||||
(define_insn ""
|
||||
[(call (mem:DI (match_operand:DI 0 "call_operand" "r,i"))
|
||||
@ -3299,7 +3299,7 @@
|
||||
"@
|
||||
jsr $26,(%0)
|
||||
bsr $26,%0"
|
||||
[(set_attr "type" "jsr")])
|
||||
[(set_attr "type" "jsr,ibr")])
|
||||
|
||||
(define_insn ""
|
||||
[(call (mem:DI (match_operand:DI 0 "call_operand" "r,i"))
|
||||
@ -3325,7 +3325,7 @@
|
||||
jsr $26,($27),0\;ldgp $29,0($26)
|
||||
bsr $26,%1..ng
|
||||
jsr $26,%1\;ldgp $29,0($26)"
|
||||
[(set_attr "type" "jsr,jsr,ibr")])
|
||||
[(set_attr "type" "jsr,ibr,jsr")])
|
||||
|
||||
(define_insn ""
|
||||
[(set (match_operand 0 "register_operand" "=rf,rf")
|
||||
@ -3336,7 +3336,7 @@
|
||||
"@
|
||||
jsr $26,(%1)
|
||||
bsr $26,%1"
|
||||
[(set_attr "type" "jsr")])
|
||||
[(set_attr "type" "jsr,ibr")])
|
||||
|
||||
(define_insn ""
|
||||
[(set (match_operand 0 "register_operand" "")
|
||||
@ -3568,11 +3568,15 @@
|
||||
|
||||
;; Cache flush. Used by INITIALIZE_TRAMPOLINE. 0x86 is PAL_imb, but we don't
|
||||
;; want to have to include pal.h in our .s file.
|
||||
;;
|
||||
;; Technically the type for call_pal is jsr, but we use that for determining
|
||||
;; if we need a GP. Use ibr instead since it has the same scheduling
|
||||
;; characteristics.
|
||||
(define_insn ""
|
||||
[(unspec_volatile [(const_int 0)] 0)]
|
||||
""
|
||||
"call_pal 0x86"
|
||||
[(set_attr "type" "isubr")])
|
||||
[(set_attr "type" "ibr")])
|
||||
|
||||
;; Finally, we have the basic data motion insns. The byte and word insns
|
||||
;; are done via define_expand. Start with the floating-point insns, since
|
||||
|
Loading…
x
Reference in New Issue
Block a user