i860-protos.h (output_delay_insn): Remove prototype.

2003-08-22  Jason Eckhardt  <jle@rice.edu>

	* config/i860/i860-protos.h (output_delay_insn): Remove prototype.
	(output_delayed_branch): Remove prototype.
	(single_insn_src_p): Remove prototype.
	* config/i860/i860.c (single_insn_src_p): Remove function.
	(output_delayed_branch): Remove function.
	(output_delay_insn): Remove function.
	(va_start): Remove unconditional test and dead code, re-format.
	Fix coding style and spelling problems in various comments.
	* config/i860/i860.md (UNSPECV_BLOCKAGE): Define constant...
	(blockage pattern): ...and use it here.
	(all define_peephole patterns related to delayed branches): Remove.
	Fix coding style and spelling problems in various comments.

From-SVN: r70724
This commit is contained in:
Jason Eckhardt 2003-08-23 02:30:35 +00:00 committed by Jason Eckhardt
parent 8274e603cf
commit 89520fd7cb
4 changed files with 123 additions and 501 deletions

View File

@ -1,3 +1,18 @@
2003-08-22 Jason Eckhardt <jle@rice.edu>
* config/i860/i860-protos.h (output_delay_insn): Remove prototype.
(output_delayed_branch): Remove prototype.
(single_insn_src_p): Remove prototype.
* config/i860/i860.c (single_insn_src_p): Remove function.
(output_delayed_branch): Remove function.
(output_delay_insn): Remove function.
(va_start): Remove unconditional test and dead code, re-format.
Fix coding style and spelling problems in various comments.
* config/i860/i860.md (UNSPECV_BLOCKAGE): Define constant...
(blockage pattern): ...and use it here.
(all define_peephole patterns related to delayed branches): Remove.
Fix coding style and spelling problems in various comments.
2003-08-22 Jason Eckhardt <jle@rice.edu>
* config/i860/i860.c: Replace all occurrences of 'GNU CC' with 'GCC'.

View File

@ -30,14 +30,9 @@ extern const char *output_store (rtx *);
extern const char *output_move_double (rtx *);
extern const char *output_fp_move_double (rtx *);
extern const char *output_block_move (rtx *);
extern const char *output_delay_insn (rtx);
#if 0
extern const char *output_delayed_branch (const char *, rtx *, rtx);
#endif
extern void output_load_address (rtx *);
extern int safe_insn_src_p (rtx, enum machine_mode);
extern int operand_clobbered_before_used_after (rtx, rtx);
extern int single_insn_src_p (rtx, enum machine_mode);
extern int reg_or_0_operand (rtx, enum machine_mode);
extern int arith_operand (rtx, enum machine_mode);
extern int logic_operand (rtx, enum machine_mode);

View File

@ -1,4 +1,4 @@
/* Subroutines for insn-output.c for Intel 860
/* Subroutines for insn-output.c for Intel i860
Copyright (C) 1989, 1991, 1997, 1998, 1999, 2000, 2001, 2002, 2003
Free Software Foundation, Inc.
Derived from sparc.c.
@ -67,7 +67,7 @@ safe_insn_src_p (rtx op, enum machine_mode mode)
{
/* Just experimenting. */
/* No floating point src is safe if it contains an arithmetic
/* No floating point source is safe if it contains an arithmetic
operation, since that operation may trap. */
switch (GET_CODE (op))
{
@ -122,7 +122,7 @@ safe_insn_src_p (rtx op, enum machine_mode mode)
/* Return 1 if REG is clobbered in IN.
Return 2 if REG is used in IN.
Return 3 if REG is both used and clobbered in IN.
Return 0 if neither. */
Return 0 if none of the above. */
static int
reg_clobbered_p (rtx reg, rtx in)
@ -246,7 +246,7 @@ operand_clobbered_before_used_after (rtx op, rtx after)
}
/* In both of these cases, the first insn executed
for this op will be a orh whatever%h,%?r0,%?r31,
for this op will be a orh whatever%h,%r0,%r31,
which is tolerable. */
if (GET_CODE (op) == MEM)
return (CONSTANT_ADDRESS_P (XEXP (op, 0)));
@ -254,102 +254,6 @@ operand_clobbered_before_used_after (rtx op, rtx after)
return 0;
}
/* Return non-zero if this pattern, as a source to a "SET",
is known to yield an instruction of unit size. */
int
single_insn_src_p (rtx op, enum machine_mode mode)
{
switch (GET_CODE (op))
{
case CONST_INT:
/* This is not always a single insn src, technically,
but output_delayed_branch knows how to deal with it. */
return 1;
case SYMBOL_REF:
case CONST:
/* This is not a single insn src, technically,
but output_delayed_branch knows how to deal with it. */
return 1;
case REG:
return 1;
case MEM:
return 1;
/* We never need to negate or complement constants. */
case NEG:
return (mode != DFmode);
case NOT:
case ZERO_EXTEND:
return 1;
case PLUS:
case MINUS:
/* Detect cases that require multiple instructions. */
if (CONSTANT_P (XEXP (op, 1))
&& !(GET_CODE (XEXP (op, 1)) == CONST_INT
&& SMALL_INT (XEXP (op, 1))))
return 0;
case EQ:
case NE:
case LT:
case GT:
case LE:
case GE:
case LTU:
case GTU:
case LEU:
case GEU:
/* Not doing floating point, since they probably
take longer than the branch slot they might fill. */
return (mode != SFmode && mode != DFmode);
case AND:
if (GET_CODE (XEXP (op, 1)) == NOT)
{
rtx arg = XEXP (XEXP (op, 1), 0);
if (CONSTANT_P (arg)
&& !(GET_CODE (arg) == CONST_INT
&& (SMALL_INT (arg)
|| (INTVAL (arg) & 0xffff) == 0)))
return 0;
}
case IOR:
case XOR:
/* Both small and round numbers take one instruction;
others take two. */
if (CONSTANT_P (XEXP (op, 1))
&& !(GET_CODE (XEXP (op, 1)) == CONST_INT
&& (SMALL_INT (XEXP (op, 1))
|| (INTVAL (XEXP (op, 1)) & 0xffff) == 0)))
return 0;
case ASHIFT:
case ASHIFTRT:
case LSHIFTRT:
return 1;
case SUBREG:
if (SUBREG_BYTE (op) != 0)
return 0;
return single_insn_src_p (SUBREG_REG (op), mode);
/* Not doing floating point, since they probably
take longer than the branch slot they might fill. */
case FLOAT_EXTEND:
case FLOAT_TRUNCATE:
case FLOAT:
case FIX:
case UNSIGNED_FLOAT:
case UNSIGNED_FIX:
return 0;
default:
return 0;
}
}
/* Return non-zero only if OP is a register of mode MODE,
or const0_rtx. */
@ -581,7 +485,7 @@ output_move_double (rtx *operands)
if (optype0 == RNDOP || optype1 == RNDOP)
abort ();
/* If an operand is an unoffsettable memory ref, find a register
/* If an operand is an unoffsettable memory reference, find a register
we can increment temporarily to make it refer to the second word. */
if (optype0 == MEMOP)
@ -630,7 +534,7 @@ output_move_double (rtx *operands)
such overlap can't happen in memory unless the user explicitly
sets it up, and that is an undefined circumstance."
but it happens on the sparc when loading parameter registers,
But it happens on the sparc when loading parameter registers,
so I am going to define that circumstance, and make it work
as expected. */
@ -811,7 +715,7 @@ find_addr_reg (rtx addr)
/* Return a template for a load instruction with mode MODE and
arguments from the string ARGS.
This string is in static storage. */
This string is in static storage. */
static const char *
load_opcode (enum machine_mode mode, const char *args, rtx reg)
@ -1289,198 +1193,13 @@ output_block_move (rtx *operands)
return "";
}
#if 0
/* Output a delayed branch insn with the delay insn in its
branch slot. The delayed branch insn template is in TEMPLATE,
with operands OPERANDS. The insn in its delay slot is INSN.
As a special case, since we know that all memory transfers are via
ld/st insns, if we see a (MEM (SYMBOL_REF ...)) we divide the memory
reference around the branch as
orh ha%x,%?r0,%?r31
b ...
ld/st l%x(%?r31),...
As another special case, we handle loading (SYMBOL_REF ...) and
other large constants around branches as well:
orh h%x,%?r0,%0
b ...
or l%x,%0,%1
*/
/* ??? Disabled because this re-recognition is incomplete and causes
constrain_operands to segfault. Anyone who cares should fix up
the code to use the DBR pass. */
const char *
output_delayed_branch (const char *template, rtx *operands, rtx insn)
{
rtx src = XVECEXP (PATTERN (insn), 0, 1);
rtx dest = XVECEXP (PATTERN (insn), 0, 0);
/* See if we are doing some branch together with setting some register
to some 32-bit value which does (or may) have some of the high-order
16 bits set. If so, we need to set the register in two stages. One
stage must be done before the branch, and the other one can be done
in the delay slot. */
if ( (GET_CODE (src) == CONST_INT
&& ((unsigned) INTVAL (src) & (unsigned) 0xffff0000) != (unsigned) 0)
|| (GET_CODE (src) == SYMBOL_REF)
|| (GET_CODE (src) == LABEL_REF)
|| (GET_CODE (src) == CONST))
{
rtx xoperands[2];
xoperands[0] = dest;
xoperands[1] = src;
CC_STATUS_PARTIAL_INIT;
/* Output the `orh' insn. */
output_asm_insn ("orh %H1,%?r0,%0", xoperands);
/* Output the branch instruction next. */
output_asm_insn (template, operands);
/* Now output the `or' insn. */
output_asm_insn ("or %L1,%0,%0", xoperands);
}
else if ((GET_CODE (src) == MEM
&& CONSTANT_ADDRESS_P (XEXP (src, 0)))
|| (GET_CODE (dest) == MEM
&& CONSTANT_ADDRESS_P (XEXP (dest, 0))))
{
rtx xoperands[2];
const char *split_template;
xoperands[0] = dest;
xoperands[1] = src;
/* Output the `orh' insn. */
if (GET_CODE (src) == MEM)
{
if (! ((cc_prev_status.flags & CC_KNOW_HI_R31)
&& (cc_prev_status.flags & CC_HI_R31_ADJ)
&& cc_prev_status.mdep == XEXP (operands[1], 0)))
{
CC_STATUS_INIT;
output_asm_insn ("orh %h1,%?r0,%?r31", xoperands);
}
split_template = load_opcode (GET_MODE (dest),
"%L1(%?r31),%0", dest);
}
else
{
if (! ((cc_prev_status.flags & CC_KNOW_HI_R31)
&& (cc_prev_status.flags & CC_HI_R31_ADJ)
&& cc_prev_status.mdep == XEXP (operands[0], 0)))
{
CC_STATUS_INIT;
output_asm_insn ("orh %h0,%?r0,%?r31", xoperands);
}
split_template = store_opcode (GET_MODE (dest),
"%r1,%L0(%?r31)", src);
}
/* Output the branch instruction next. */
output_asm_insn (template, operands);
/* Now output the load or store.
No need to do a CC_STATUS_INIT, because we are branching anyway. */
output_asm_insn (split_template, xoperands);
}
else
{
int insn_code_number;
rtx pat = gen_rtx_SET (VOIDmode, dest, src);
rtx delay_insn = gen_rtx_INSN (VOIDmode, 0, 0, 0, pat, -1, 0, 0);
int i;
/* Output the branch instruction first. */
output_asm_insn (template, operands);
/* Now recognize the insn which we put in its delay slot.
We must do this after outputting the branch insn,
since operands may just be a pointer to `recog_data.operand'. */
INSN_CODE (delay_insn) = insn_code_number
= recog (pat, delay_insn, NULL);
if (insn_code_number == -1)
abort ();
for (i = 0; i < insn_data[insn_code_number].n_operands; i++)
{
if (GET_CODE (recog_data.operand[i]) == SUBREG)
alter_subreg (&recog_data.operand[i]);
}
insn_extract (delay_insn);
if (! constrain_operands (1))
fatal_insn_not_found (delay_insn);
template = get_insn_template (insn_code_number, delay_insn);
output_asm_insn (template, recog_data.operand);
}
CC_STATUS_INIT;
return "";
}
/* Output a newly constructed insn DELAY_INSN. */
const char *
output_delay_insn (rtx delay_insn)
{
const char *template;
int insn_code_number;
int i;
/* Now recognize the insn which we put in its delay slot.
We must do this after outputting the branch insn,
since operands may just be a pointer to `recog_data.operand'. */
insn_code_number = recog_memoized (delay_insn);
if (insn_code_number == -1)
abort ();
/* Extract the operands of this delay insn. */
INSN_CODE (delay_insn) = insn_code_number;
insn_extract (delay_insn);
/* It is possible that this insn has not been properly scanned by final
yet. If this insn's operands don't appear in the peephole's
actual operands, then they won't be fixed up by final, so we
make sure they get fixed up here. -- This is a kludge. */
for (i = 0; i < insn_data[insn_code_number].n_operands; i++)
{
if (GET_CODE (recog_data.operand[i]) == SUBREG)
alter_subreg (&recog_data.operand[i]);
}
if (! constrain_operands (1))
abort ();
cc_prev_status = cc_status;
/* Update `cc_status' for this instruction.
The instruction's output routine may change it further.
If the output routine for a jump insn needs to depend
on the cc status, it should look at cc_prev_status. */
NOTICE_UPDATE_CC (PATTERN (delay_insn), delay_insn);
/* Now get the template for what this insn would
have been, without the branch. */
template = get_insn_template (insn_code_number, delay_insn);
output_asm_insn (template, recog_data.operand);
return "";
}
#endif
/* Special routine to convert an SFmode value represented as a
CONST_DOUBLE into its equivalent unsigned long bit pattern.
We convert the value from a double precision floating-point
value to single precision first, and thence to a bit-wise
equivalent unsigned long value. This routine is used when
generating an immediate move of an SFmode value directly
into a general register because the svr4 assembler doesn't
into a general register because the SVR4 assembler doesn't
grok floating literals in instruction operand contexts. */
unsigned long
@ -1515,18 +1234,18 @@ sfmode_constant_to_ulong (rtx x)
part of each frame always includes at least 2 words (8 bytes)
to hold the saved frame pointer and the saved return address.
The svr4 ABI for the i860 now requires that the values of the
The SVR4 ABI for the i860 now requires that the values of the
stack pointer and frame pointer registers be kept aligned to
16-byte boundaries at all times. We obey that restriction here.
The svr4 ABI for the i860 is entirely vague when it comes to specifying
The SVR4 ABI for the i860 is entirely vague when it comes to specifying
exactly where the "preserved" registers should be saved. The native
svr4 C compiler I now have doesn't help to clarify the requirements
SVR4 C compiler I now have doesn't help to clarify the requirements
very much because it is plainly out-of-date and non-ABI-compliant
(in at least one important way, i.e. how it generates function
epilogues).
The native svr4 C compiler saves the "preserved" registers (i.e.
The native SVR4 C compiler saves the "preserved" registers (i.e.
r4-r15 and f2-f7) in the lower part of a frame (i.e. at negative
offsets from the frame pointer).
@ -1563,7 +1282,7 @@ sfmode_constant_to_ulong (rtx x)
frame, so that we can decide at the very last minute how much (or how
little) space we must allocate for this purpose.
To satisfy the needs of the svr4 ABI "tdesc" scheme, preserved
To satisfy the needs of the SVR4 ABI "tdesc" scheme, preserved
registers must always be saved so that the saved values of registers
with higher numbers are at higher addresses. We obey that restriction
here.
@ -1571,13 +1290,13 @@ sfmode_constant_to_ulong (rtx x)
There are two somewhat different ways that you can generate prologues
here... i.e. pedantically ABI-compliant, and the "other" way. The
"other" way is more consistent with what is currently generated by the
"native" svr4 C compiler for the i860. That's important if you want
to use the current (as of 8/91) incarnation of svr4 SDB for the i860.
"native" SVR4 C compiler for the i860. That's important if you want
to use the current (as of 8/91) incarnation of SVR4 SDB for the i860.
The SVR4 SDB for the i860 insists on having function prologues be
non-ABI-compliant!
To get fully ABI-compliant prologues, define I860_STRICT_ABI_PROLOGUES
in the i860svr4.h file. (By default this is *not* defined).
in the i860/sysv4.h file. (By default this is *not* defined).
The differences between the ABI-compliant and non-ABI-compliant prologues
are that (a) the ABI version seems to require the use of *signed*
@ -1589,8 +1308,7 @@ sfmode_constant_to_ulong (rtx x)
thing that is supposed to happen in the prologue is getting the frame
pointer set to its new value (but only after everything else has
already been properly setup). We do that here, but only if the symbol
I860_STRICT_ABI_PROLOGUES is defined.
*/
I860_STRICT_ABI_PROLOGUES is defined. */
#ifndef STACK_ALIGNMENT
#define STACK_ALIGNMENT 16
@ -1623,17 +1341,17 @@ i860_output_function_prologue (FILE *asm_file, HOST_WIDE_INT local_bytes)
preserved_reg_bytes += 4;
}
/* Round-up the frame_lower_bytes so that it's a multiple of 16. */
/* Round-up the frame_lower_bytes so that it's a multiple of 16. */
frame_lower_bytes = (local_bytes + STACK_ALIGNMENT - 1) & -STACK_ALIGNMENT;
/* The upper part of each frame will contain the saved fp,
the saved r1, and stack slots for all of the other "preserved"
registers that we find we will need to save & restore. */
registers that we find we will need to save & restore. */
frame_upper_bytes = must_preserve_bytes + preserved_reg_bytes;
/* Round-up the frame_upper_bytes so that it's a multiple of 16. */
/* Round-up the frame_upper_bytes so that it's a multiple of 16. */
frame_upper_bytes
= (frame_upper_bytes + STACK_ALIGNMENT - 1) & -STACK_ALIGNMENT;
@ -1650,8 +1368,8 @@ i860_output_function_prologue (FILE *asm_file, HOST_WIDE_INT local_bytes)
if (total_fsize > 0x7fff)
{
/* Adjust the stack pointer. The ABI sez to do this using `adds',
but the native C compiler on svr4 uses `addu'. */
/* Adjust the stack pointer. The ABI specifies using `adds' for
this, but the native C compiler on SVR4 uses `addu'. */
fprintf (asm_file, "\taddu -" HOST_WIDE_INT_PRINT_DEC ",%ssp,%ssp\n",
frame_upper_bytes, i860_reg_prefix, i860_reg_prefix);
@ -1661,9 +1379,9 @@ i860_output_function_prologue (FILE *asm_file, HOST_WIDE_INT local_bytes)
fprintf (asm_file, "\tst.l %sfp,0(%ssp)\n",
i860_reg_prefix, i860_reg_prefix);
/* Setup the new frame pointer. The ABI sez to do this after
preserving registers (using adds), but that's not what the
native C compiler on svr4 does. */
/* Setup the new frame pointer. The ABI specifies that this is to
be done after preserving registers (using `adds'), but that's not
what the native C compiler on SVR4 does. */
fprintf (asm_file, "\taddu 0,%ssp,%sfp\n",
i860_reg_prefix, i860_reg_prefix);
@ -1676,14 +1394,15 @@ i860_output_function_prologue (FILE *asm_file, HOST_WIDE_INT local_bytes)
frame_lower_bytes & 0xffff, i860_reg_prefix, i860_reg_prefix);
/* Now re-adjust the stack pointer using the value in r31.
The ABI sez to do this with `subs' but SDB may prefer `subu'. */
The ABI specifies that this is done with `subs' but SDB may
prefer `subu'. */
fprintf (asm_file, "\tsubu %ssp,%sr31,%ssp\n",
i860_reg_prefix, i860_reg_prefix, i860_reg_prefix);
/* Preserve registers. The ABI sez to do this before setting
up the new frame pointer, but that's not what the native
C compiler on svr4 does. */
/* Preserve registers. The ABI specifies that this is to be done
before setting up the new frame pointer, but that's not what the
native C compiler on SVR4 does. */
for (i = 1; i < 32; i++)
if (regs_ever_live[i] && ! call_used_regs[i])
@ -1707,8 +1426,8 @@ i860_output_function_prologue (FILE *asm_file, HOST_WIDE_INT local_bytes)
}
else
{
/* Adjust the stack pointer. The ABI sez to do this using `adds',
but the native C compiler on svr4 uses `addu'. */
/* Adjust the stack pointer. The ABI specifies using `adds' for this,
but the native C compiler on SVR4 uses `addu'. */
fprintf (asm_file, "\taddu -" HOST_WIDE_INT_PRINT_DEC ",%ssp,%ssp\n",
total_fsize, i860_reg_prefix, i860_reg_prefix);
@ -1718,17 +1437,17 @@ i860_output_function_prologue (FILE *asm_file, HOST_WIDE_INT local_bytes)
fprintf (asm_file, "\tst.l %sfp," HOST_WIDE_INT_PRINT_DEC "(%ssp)\n",
i860_reg_prefix, frame_lower_bytes, i860_reg_prefix);
/* Setup the new frame pointer. The ABI sez to do this after
preserving registers and after saving the return address,
(and its saz to do this using adds), but that's not what the
native C compiler on svr4 does. */
/* Setup the new frame pointer. The ABI specifies that this is to be
done after preserving registers and after saving the return address,
(and to do it using `adds'), but that's not what the native C
compiler on SVR4 does. */
fprintf (asm_file, "\taddu " HOST_WIDE_INT_PRINT_DEC ",%ssp,%sfp\n",
frame_lower_bytes, i860_reg_prefix, i860_reg_prefix);
/* Preserve registers. The ABI sez to do this before setting
up the new frame pointer, but that's not what the native
compiler on svr4 does. */
/* Preserve registers. The ABI specifies that this is to be done
before setting up the new frame pointer, but that's not what the
native compiler on SVR4 does. */
for (i = 1; i < 32; i++)
if (regs_ever_live[i] && ! call_used_regs[i])
@ -1744,9 +1463,9 @@ i860_output_function_prologue (FILE *asm_file, HOST_WIDE_INT local_bytes)
must_preserve_bytes + (4 * preserved_so_far++),
i860_reg_prefix);
/* Save the return address. The ABI sez to do this earlier,
and also via an offset from %sp, but the native C compiler
on svr4 does it later (i.e. now) and uses an offset from
/* Save the return address. The ABI specifies that this is to be
done earlier, and also via an offset from %sp, but the native C
compiler on SVR4 does it later (i.e. now) and uses an offset from
%fp. */
if (must_preserve_r1)
@ -1896,12 +1615,11 @@ i860_output_function_prologue (FILE *asm_file, HOST_WIDE_INT local_bytes)
the frame pointer register is never less than the value in the stack
pointer register. It's not clear why this relationship needs to be
maintained at all times, but maintaining it only costs one extra
instruction, so what the hell.
*/
instruction, so what the hell. */
/* This corresponds to a version 4 TDESC structure. Lower numbered
versions successively omit the last word of the structure. We
don't try to handle version 5 here. */
don't try to handle version 5 here. */
typedef struct TDESC_flags {
int version:4;
@ -1940,7 +1658,7 @@ i860_output_function_epilogue (FILE *asm_file, HOST_WIDE_INT local_bytes)
flags->reg_packing = 1;
flags->iregs = 8; /* old fp always gets saved */
/* Round-up the frame_lower_bytes so that it's a multiple of 16. */
/* Round-up the frame_lower_bytes so that it's a multiple of 16. */
frame_lower_bytes = (local_bytes + STACK_ALIGNMENT - 1) & -STACK_ALIGNMENT;
@ -1955,11 +1673,11 @@ i860_output_function_epilogue (FILE *asm_file, HOST_WIDE_INT local_bytes)
/* The upper part of each frame will contain only saved fp,
the saved r1, and stack slots for all of the other "preserved"
registers that we find we will need to save & restore. */
registers that we find we will need to save & restore. */
frame_upper_bytes = must_preserve_bytes + preserved_reg_bytes;
/* Round-up frame_upper_bytes so that t is a multiple of 16. */
/* Round-up frame_upper_bytes so that t is a multiple of 16. */
frame_upper_bytes
= (frame_upper_bytes + STACK_ALIGNMENT - 1) & -STACK_ALIGNMENT;
@ -2013,12 +1731,12 @@ i860_output_function_epilogue (FILE *asm_file, HOST_WIDE_INT local_bytes)
fprintf (asm_file, "\tbri %sr1\n\tmov %sr31,%ssp\n",
i860_reg_prefix, i860_reg_prefix, i860_reg_prefix);
#ifdef OUTPUT_TDESC /* Output an ABI-compliant TDESC entry */
#ifdef OUTPUT_TDESC /* Output an ABI-compliant TDESC entry. */
if (! frame_lower_bytes) {
flags->version--;
if (! frame_upper_bytes) {
flags->version--;
if (restored_so_far == int_restored) /* No FP saves */
if (restored_so_far == int_restored) /* No FP saves. */
flags->version--;
}
}
@ -2110,64 +1828,54 @@ void
i860_va_start (tree valist, rtx nextarg)
{
tree saveregs, t;
tree field_ireg_used, field_freg_used, field_reg_base, field_mem_ptr;
tree ireg_used, freg_used, reg_base, mem_ptr;
saveregs = make_tree (build_pointer_type (va_list_type_node),
expand_builtin_saveregs ());
saveregs = build1 (INDIRECT_REF, va_list_type_node, saveregs);
if (1 /* stdarg_p */)
{
tree field_ireg_used, field_freg_used, field_reg_base, field_mem_ptr;
tree ireg_used, freg_used, reg_base, mem_ptr;
#ifdef I860_SVR4_VA_LIST
field_ireg_used = TYPE_FIELDS (va_list_type_node);
field_freg_used = TREE_CHAIN (field_ireg_used);
field_reg_base = TREE_CHAIN (field_freg_used);
field_mem_ptr = TREE_CHAIN (field_reg_base);
field_ireg_used = TYPE_FIELDS (va_list_type_node);
field_freg_used = TREE_CHAIN (field_ireg_used);
field_reg_base = TREE_CHAIN (field_freg_used);
field_mem_ptr = TREE_CHAIN (field_reg_base);
#else
field_reg_base = TYPE_FIELDS (va_list_type_node);
field_mem_ptr = TREE_CHAIN (field_reg_base);
field_ireg_used = TREE_CHAIN (field_mem_ptr);
field_freg_used = TREE_CHAIN (field_ireg_used);
field_reg_base = TYPE_FIELDS (va_list_type_node);
field_mem_ptr = TREE_CHAIN (field_reg_base);
field_ireg_used = TREE_CHAIN (field_mem_ptr);
field_freg_used = TREE_CHAIN (field_ireg_used);
#endif
ireg_used = build (COMPONENT_REF, TREE_TYPE (field_ireg_used),
valist, field_ireg_used);
freg_used = build (COMPONENT_REF, TREE_TYPE (field_freg_used),
valist, field_freg_used);
reg_base = build (COMPONENT_REF, TREE_TYPE (field_reg_base),
valist, field_reg_base);
mem_ptr = build (COMPONENT_REF, TREE_TYPE (field_mem_ptr),
valist, field_mem_ptr);
ireg_used = build (COMPONENT_REF, TREE_TYPE (field_ireg_used),
valist, field_ireg_used);
freg_used = build (COMPONENT_REF, TREE_TYPE (field_freg_used),
valist, field_freg_used);
reg_base = build (COMPONENT_REF, TREE_TYPE (field_reg_base),
valist, field_reg_base);
mem_ptr = build (COMPONENT_REF, TREE_TYPE (field_mem_ptr),
valist, field_mem_ptr);
t = build_int_2 (current_function_args_info.ints / UNITS_PER_WORD, 0);
t = build (MODIFY_EXPR, TREE_TYPE (ireg_used), ireg_used, t);
TREE_SIDE_EFFECTS (t) = 1;
expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
t = build_int_2 (current_function_args_info.ints / UNITS_PER_WORD, 0);
t = build (MODIFY_EXPR, TREE_TYPE (ireg_used), ireg_used, t);
TREE_SIDE_EFFECTS (t) = 1;
expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
t = build_int_2 (ROUNDUP ((current_function_args_info.floats / UNITS_PER_WORD), 8), 0);
t = build (MODIFY_EXPR, TREE_TYPE (freg_used), freg_used, t);
TREE_SIDE_EFFECTS (t) = 1;
expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
t = build_int_2 (ROUNDUP ((current_function_args_info.floats / UNITS_PER_WORD), 8), 0);
t = build (MODIFY_EXPR, TREE_TYPE (freg_used), freg_used, t);
TREE_SIDE_EFFECTS (t) = 1;
expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
t = build (COMPONENT_REF, TREE_TYPE (field_reg_base),
saveregs, field_reg_base);
t = build (MODIFY_EXPR, TREE_TYPE (reg_base), reg_base, t);
TREE_SIDE_EFFECTS (t) = 1;
expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
t = build (COMPONENT_REF, TREE_TYPE (field_reg_base),
saveregs, field_reg_base);
t = build (MODIFY_EXPR, TREE_TYPE (reg_base), reg_base, t);
TREE_SIDE_EFFECTS (t) = 1;
expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
t = make_tree (ptr_type_node, nextarg);
t = build (MODIFY_EXPR, TREE_TYPE (mem_ptr), mem_ptr, t);
TREE_SIDE_EFFECTS (t) = 1;
expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
}
else
{
t = build (MODIFY_EXPR, va_list_type_node, valist, saveregs);
TREE_SIDE_EFFECTS (t) = 1;
expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
}
t = make_tree (ptr_type_node, nextarg);
t = build (MODIFY_EXPR, TREE_TYPE (mem_ptr), mem_ptr, t);
TREE_SIDE_EFFECTS (t) = 1;
expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
}
#define NUM_PARM_FREGS 8

View File

@ -1,4 +1,4 @@
;;- Machine description for Intel 860 chip for GNU C compiler
;; GCC Machine description for the Intel i860 microprocessor
;; Copyright (C) 1989, 1990, 1997, 1998, 1999, 2000, 2003
;; Free Software Foundation, Inc.
@ -25,6 +25,15 @@
;;- cpp macro #define NOTICE_UPDATE_CC in file tm.h handles condition code
;;- updates for most instructions.
;;
;; UNSPEC_VOLATILE usage
;;
(define_constants
[; Blockage
(UNSPECV_BLOCKAGE 0)
])
;;- Operand classes for the register allocator:
/* Bit-test instructions. */
@ -307,8 +316,7 @@
return \"pfgt.ss %r0,%r1,%?f0\";
}")
;; NOTE: The pfle opcode doesn't do what you think it does. It is
;; bass-ackwards. It *clears* the CC flag if the first operand is
;; NOTE: The pfle opcode *clears* the CC flag if the first operand is
;; less than or equal to the second. Thus, we have to set CC_NEGATED
;; for the following two patterns.
@ -385,8 +393,7 @@
return \"pfgt.dd %r0,%r1,%?f0\";
}")
;; NOTE: The pfle opcode doesn't do what you think it does. It is
;; bass-ackwards. It *clears* the CC flag if the first operand is
;; NOTE: The pfle opcode *clears* the CC flag if the first operand is
;; less than or equal to the second. Thus, we have to set CC_NEGATED
;; for the following two patterns.
@ -878,7 +885,7 @@
;; Move instructions
;; Note that source operands for `mov' pseudo-instructions are no longer
;; allowed (by the svr4 assembler) to be "big" things, i.e. constants that
;; allowed (by the SVR4 assembler) to be "big" things, i.e. constants that
;; won't fit in 16-bits. (This includes any sort of a relocatable address
;; also.) Thus, we must use an explicit orh/or pair of instructions if
;; the source operand is something "big".
@ -1086,7 +1093,7 @@
&& CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))
return output_load (operands);
/* ??? How can we have a DFmode arg here with DImode above? */
/* ??? How can we have a DFmode arg here with DImode above? */
if (FP_REG_P (operands[0]) && operands[1] == CONST0_RTX (DFmode))
return \"fmov.dd %?f0,%0\";
@ -1520,9 +1527,9 @@
return \"and 128,%0,%?r0\";
}")
;; next two patterns are good for bitfields coming from memory
;; The next two patterns are good for bitfields coming from memory
;; (via pseudo-register) or from a register, though this optimization
;; is only good for values contained wholly within the bottom 13 bits
;; is only good for values contained wholly within the bottom 13 bits.
(define_insn ""
[(set (cc0)
(eq
@ -1573,7 +1580,7 @@
;; Note that among the fix-to-float insns
;; the ones that start with SImode come first.
;; That is so that an operand that is a CONST_INT
;; (and therefore lacks a specific machine mode).
;; (and therefore lacks a specific machine mode)
;; will be recognized as SImode (which is always valid)
;; rather than as QImode or HImode.
@ -1999,8 +2006,7 @@ fmul.ss %1,%0,%4\;fmul.ss %3,%4,%0\";
;; Shift instructions
;; Optimized special case of shifting.
;; Must precede the general case.
;; Optimized special case of shifting, which must precede the general case.
(define_insn ""
[(set (match_operand:SI 0 "register_operand" "=r")
@ -2020,7 +2026,7 @@ fmul.ss %1,%0,%4\;fmul.ss %3,%4,%0\";
}")
;;- arithmetic shift instructions
;;- Arithmetic shift instructions.
(define_insn "ashlsi3"
[(set (match_operand:SI 0 "register_operand" "=r")
(ashift:SI (match_operand:SI 1 "register_operand" "r")
@ -2071,7 +2077,7 @@ fmul.ss %1,%0,%4\;fmul.ss %3,%4,%0\";
return \"shr %2,%1,%0\";
}")
;; Unconditional and other jump instructions
;; Unconditional and other jump instructions.
(define_insn "jump"
[(set (pc) (label_ref (match_operand 0 "" "")))]
@ -2081,41 +2087,12 @@ fmul.ss %1,%0,%4\;fmul.ss %3,%4,%0\";
return \"br %l0\;nop\";
}")
;; Here are two simple peepholes which fill the delay slot of
;; an unconditional branch.
;
;; ??? All disabled, because output_delayed_branch is a crock
;; that will reliably segfault. This should be using the dbr
;; pass in any case. Anyone who cares is welcome to fix it.
;
;(define_peephole
; [(set (match_operand:SI 0 "register_operand" "=rf")
; (match_operand:SI 1 "single_insn_src_p" "gfG"))
; (set (pc) (label_ref (match_operand 2 "" "")))]
; ""
; "* return output_delayed_branch (\"br %l2\", operands, insn);")
;
;(define_peephole
; [(set (match_operand:SI 0 "memory_operand" "=m")
; (match_operand:SI 1 "reg_or_0_operand" "rfJ"))
; (set (pc) (label_ref (match_operand 2 "" "")))]
; ""
; "* return output_delayed_branch (\"br %l2\", operands, insn);")
(define_insn "tablejump"
[(set (pc) (match_operand:SI 0 "register_operand" "r"))
(use (label_ref (match_operand 1 "" "")))]
""
"bri %0\;nop")
;(define_peephole
; [(set (match_operand:SI 0 "memory_operand" "=m")
; (match_operand:SI 1 "reg_or_0_operand" "rfJ"))
; (set (pc) (match_operand:SI 2 "register_operand" "r"))
; (use (label_ref (match_operand 3 "" "")))]
; ""
; "* return output_delayed_branch (\"bri %2\", operands, insn);")
;;- jump to subroutine
(define_expand "call"
[(call (match_operand:SI 0 "memory_operand" "m")
@ -2137,7 +2114,7 @@ fmul.ss %1,%0,%4\;fmul.ss %3,%4,%0\";
}
}")
;;- jump to subroutine
;;- Jump to subroutine.
(define_insn ""
[(call (match_operand:SI 0 "call_insn_operand" "m")
(match_operand 1 "" "i"))]
@ -2153,38 +2130,6 @@ fmul.ss %1,%0,%4\;fmul.ss %3,%4,%0\";
return \"call %0\;nop\";
}")
;(define_peephole
; [(set (match_operand:SI 0 "register_operand" "=rf")
; (match_operand:SI 1 "single_insn_src_p" "gfG"))
; (call (match_operand:SI 2 "memory_operand" "m")
; (match_operand 3 "" "i"))]
; ;;- Don't use operand 1 for most machines.
; "! reg_mentioned_p (operands[0], operands[2])"
; "*
;{
; /* strip the MEM. */
; operands[2] = XEXP (operands[2], 0);
; if (GET_CODE (operands[2]) == REG)
; return output_delayed_branch (\"calli %2\", operands, insn);
; return output_delayed_branch (\"call %2\", operands, insn);
;}")
;(define_peephole
; [(set (match_operand:SI 0 "memory_operand" "=m")
; (match_operand:SI 1 "reg_or_0_operand" "rfJ"))
; (call (match_operand:SI 2 "call_insn_operand" "m")
; (match_operand 3 "" "i"))]
; ;;- Don't use operand 1 for most machines.
; ""
; "*
;{
; /* strip the MEM. */
; operands[2] = XEXP (operands[2], 0);
; if (GET_CODE (operands[2]) == REG)
; return output_delayed_branch (\"calli %2\", operands, insn);
; return output_delayed_branch (\"call %2\", operands, insn);
;}")
(define_expand "call_value"
[(set (match_operand 0 "register_operand" "=rf")
(call (match_operand:SI 1 "memory_operand" "m")
@ -2214,7 +2159,7 @@ fmul.ss %1,%0,%4\;fmul.ss %3,%4,%0\";
""
"*
{
/* strip the MEM. */
/* Strip the MEM. */
operands[1] = XEXP (operands[1], 0);
CC_STATUS_INIT;
if (GET_CODE (operands[1]) == REG)
@ -2222,40 +2167,6 @@ fmul.ss %1,%0,%4\;fmul.ss %3,%4,%0\";
return \"call %1\;nop\";
}")
;(define_peephole
; [(set (match_operand:SI 0 "register_operand" "=rf")
; (match_operand:SI 1 "single_insn_src_p" "gfG"))
; (set (match_operand 2 "" "=rf")
; (call (match_operand:SI 3 "call_insn_operand" "m")
; (match_operand 4 "" "i")))]
; ;;- Don't use operand 4 for most machines.
; "! reg_mentioned_p (operands[0], operands[3])"
; "*
;{
; /* strip the MEM. */
; operands[3] = XEXP (operands[3], 0);
; if (GET_CODE (operands[3]) == REG)
; return output_delayed_branch (\"calli %3\", operands, insn);
; return output_delayed_branch (\"call %3\", operands, insn);
;}")
;(define_peephole
; [(set (match_operand:SI 0 "memory_operand" "=m")
; (match_operand:SI 1 "reg_or_0_operand" "rJf"))
; (set (match_operand 2 "" "=rf")
; (call (match_operand:SI 3 "call_insn_operand" "m")
; (match_operand 4 "" "i")))]
; ;;- Don't use operand 4 for most machines.
; ""
; "*
;{
; /* strip the MEM. */
; operands[3] = XEXP (operands[3], 0);
; if (GET_CODE (operands[3]) == REG)
; return output_delayed_branch (\"calli %3\", operands, insn);
; return output_delayed_branch (\"call %3\", operands, insn);
;}")
;; Call subroutine returning any type.
(define_expand "untyped_call"
@ -2289,7 +2200,7 @@ fmul.ss %1,%0,%4\;fmul.ss %3,%4,%0\";
;; all of memory. This blocks insns from being moved across this point.
(define_insn "blockage"
[(unspec_volatile [(const_int 0)] 0)]
[(unspec_volatile [(const_int 0)] UNSPECV_BLOCKAGE)]
""
"")
@ -2317,11 +2228,4 @@ fmul.ss %1,%0,%4\;fmul.ss %3,%4,%0\";
CC_STATUS_INIT;
return \"orh %H2,%?r0,%?r31\;or %L2,%?r31,%?r31\;ld.l %?r31(%1),%0\";
}")
;(define_peephole
; [(set (match_operand:SI 0 "register_operand" "=rf")
; (match_operand:SI 1 "single_insn_src_p" "gfG"))
; (set (pc) (match_operand:SI 2 "register_operand" "r"))
; (use (label_ref (match_operand 3 "" "")))]
; "REGNO (operands[0]) != REGNO (operands[2])"
; "* return output_delayed_branch (\"bri %2\", operands, insn);")