mmix.h (MMIX_LAST_STACK_REGISTER_REGNUM): Renamed from MMIX_LAST_REGISTER_FILE_REGNUM.
* config/mmix/mmix.h (MMIX_LAST_STACK_REGISTER_REGNUM): Renamed from MMIX_LAST_REGISTER_FILE_REGNUM. (NO_IMPLICIT_EXTERN_C): Remove cryptic obsolete comment. (struct machine_function): New member highest_saved_stack_register previously static variable in mmix.c. (MACHINE_DEPENDENT_REORG): Define. * config/mmix/mmix.c (highest_saved_stack_register): Deleted. (MMIX_OUTPUT_REGNO): New. (mmix_target_asm_function_prologue): Move calculation of last used saved-stack-register into... (mmix_machine_dependent_reorg): New function. Update to also handle !TARGET_ABI_GNU. (mmix_print_operand): Apply MMIX_OUTPUT_REGNO when emitting register names, simplify somewhat by new variable regno. <case 'p'>: Remove fixed FIXME. Always emit highest used saved register. (mmix_print_operand_address): Apply MMIX_OUTPUT_REGNO when emitting register names. (mmix_asm_output_reg_push, mmix_asm_output_reg_pop): Ditto. (mmix_dbx_register_number): Apply MMIX_OUTPUT_REGNO here too. Remove fixed FIXME. * config/mmix/mmix-protos.h (mmix_machine_dependent_reorg): Declare. * config/mmix/mmix.md ("divmoddi4"): Update head comment. From-SVN: r52966
This commit is contained in:
parent
73985940ad
commit
1f2641b6d2
|
@ -1,3 +1,31 @@
|
|||
2002-04-30 Hans-Peter Nilsson <hp@bitrange.com>
|
||||
|
||||
* config/mmix/mmix.h (MMIX_LAST_STACK_REGISTER_REGNUM): Renamed
|
||||
from MMIX_LAST_REGISTER_FILE_REGNUM.
|
||||
(NO_IMPLICIT_EXTERN_C): Remove cryptic obsolete comment.
|
||||
(struct machine_function): New member highest_saved_stack_register
|
||||
previously static variable in mmix.c.
|
||||
(MACHINE_DEPENDENT_REORG): Define.
|
||||
* config/mmix/mmix.c (highest_saved_stack_register): Deleted.
|
||||
(MMIX_OUTPUT_REGNO): New.
|
||||
(mmix_target_asm_function_prologue): Move calculation of last used
|
||||
saved-stack-register into...
|
||||
(mmix_machine_dependent_reorg): New function. Update to also handle
|
||||
!TARGET_ABI_GNU.
|
||||
(mmix_print_operand): Apply MMIX_OUTPUT_REGNO when emitting
|
||||
register names, simplify somewhat by new variable regno.
|
||||
<case 'p'>: Remove fixed FIXME. Always emit highest used saved
|
||||
register.
|
||||
(mmix_print_operand_address): Apply MMIX_OUTPUT_REGNO when
|
||||
emitting register names.
|
||||
(mmix_asm_output_reg_push, mmix_asm_output_reg_pop): Ditto.
|
||||
(mmix_dbx_register_number): Apply MMIX_OUTPUT_REGNO here too.
|
||||
Remove fixed FIXME.
|
||||
* config/mmix/mmix-protos.h (mmix_machine_dependent_reorg):
|
||||
Declare.
|
||||
|
||||
* config/mmix/mmix.md ("divmoddi4"): Update head comment.
|
||||
|
||||
2002-04-30 Richard Henderson <rth@redhat.com>
|
||||
|
||||
* config/sparc/sparc.c (emit_soft_tfmode_libcall,
|
||||
|
|
|
@ -125,6 +125,7 @@ extern void mmix_print_operand PARAMS ((FILE *, rtx, int));
|
|||
extern void mmix_print_operand_address PARAMS ((FILE *, rtx));
|
||||
extern int mmix_valid_comparison PARAMS ((RTX_CODE, enum machine_mode, rtx));
|
||||
extern rtx mmix_gen_compare_reg PARAMS ((enum rtx_code, rtx, rtx));
|
||||
extern void mmix_machine_dependent_reorg PARAMS ((rtx));
|
||||
#endif /* RTX_CODE */
|
||||
|
||||
extern int mmix_asm_preferred_eh_data_format PARAMS ((int, int));
|
||||
|
|
|
@ -62,6 +62,19 @@ Boston, MA 02111-1307, USA. */
|
|||
|| EH_RETURN_DATA_REGNO (2) == REGNO \
|
||||
|| EH_RETURN_DATA_REGNO (3) == REGNO))
|
||||
|
||||
/* For the default ABI, we rename registers at output-time to fill the gap
|
||||
between the (statically partitioned) saved registers and call-clobbered
|
||||
registers. In effect this makes unused call-saved registers to be used
|
||||
as call-clobbered registers. The benefit comes from keeping the number
|
||||
of local registers (value of rL) low, since there's a cost of
|
||||
increasing rL and clearing unused (unset) registers with lower numbers. */
|
||||
#define MMIX_OUTPUT_REGNO(N) \
|
||||
(TARGET_ABI_GNU \
|
||||
|| (N) < MMIX_RETURN_VALUE_REGNUM \
|
||||
|| (N) > MMIX_LAST_STACK_REGISTER_REGNUM \
|
||||
? (N) : ((N) - MMIX_RETURN_VALUE_REGNUM \
|
||||
+ cfun->machine->highest_saved_stack_register + 1))
|
||||
|
||||
/* The canonical saved comparison operands for non-cc0 machines, set in
|
||||
the compare expander. */
|
||||
rtx mmix_compare_op0;
|
||||
|
@ -74,10 +87,6 @@ const char *mmix_cc1_ignored_option;
|
|||
|
||||
/* Declarations of locals. */
|
||||
|
||||
/* This is used in the prologue for what number to pass in a PUSHJ or
|
||||
PUSHGO insn. */
|
||||
static int mmix_highest_saved_stack_register;
|
||||
|
||||
/* Intermediate for insn output. */
|
||||
static int mmix_output_destination_register;
|
||||
|
||||
|
@ -981,19 +990,50 @@ mmix_target_asm_function_prologue (stream, locals_size)
|
|||
cfa_offset);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* MACHINE_DEPENDENT_REORG.
|
||||
No actual rearrangements done here; just virtually by calculating the
|
||||
highest saved stack register number used to modify the register numbers
|
||||
at output time. */
|
||||
|
||||
void
|
||||
mmix_machine_dependent_reorg (first)
|
||||
rtx first ATTRIBUTE_UNUSED;
|
||||
{
|
||||
int regno;
|
||||
|
||||
/* We put the number of the highest saved register-file register in a
|
||||
location convenient for the call-patterns to output. Note that we
|
||||
don't tell dwarf2 about these registers, since it can't restore them
|
||||
anyway. */
|
||||
for (regno = MMIX_LAST_REGISTER_FILE_REGNUM;
|
||||
for (regno = MMIX_LAST_STACK_REGISTER_REGNUM;
|
||||
regno >= 0;
|
||||
regno--)
|
||||
if ((regs_ever_live[regno] && !call_used_regs[regno])
|
||||
|| (regno == MMIX_FRAME_POINTER_REGNUM && frame_pointer_needed))
|
||||
break;
|
||||
|
||||
mmix_highest_saved_stack_register = regno;
|
||||
/* Regardless of whether they're saved (they might be just read), we
|
||||
mustn't include registers that carry parameters. We could scan the
|
||||
insns to see whether they're actually used (and indeed do other less
|
||||
trivial register usage analysis and transformations), but it seems
|
||||
wasteful to optimize for unused parameter registers. As of
|
||||
2002-04-30, regs_ever_live[n] seems to be set for only-reads too, but
|
||||
that might change. */
|
||||
if (!TARGET_ABI_GNU && regno < current_function_args_info.regs - 1)
|
||||
{
|
||||
regno = current_function_args_info.regs - 1;
|
||||
|
||||
/* We don't want to let this cause us to go over the limit and make
|
||||
incoming parameter registers be misnumbered and treating the last
|
||||
parameter register and incoming return value register call-saved.
|
||||
Stop things at the unmodified scheme. */
|
||||
if (regno > MMIX_RETURN_VALUE_REGNUM - 1)
|
||||
regno = MMIX_RETURN_VALUE_REGNUM - 1;
|
||||
}
|
||||
|
||||
cfun->machine->highest_saved_stack_register = regno;
|
||||
}
|
||||
|
||||
/* TARGET_ASM_FUNCTION_EPILOGUE. */
|
||||
|
@ -2165,6 +2205,7 @@ mmix_print_operand (stream, x, code)
|
|||
/* When we add support for different codes later, we can, when needed,
|
||||
drop through to the main handler with a modified operand. */
|
||||
rtx modified_x = x;
|
||||
int regno = x != NULL_RTX && REG_P (x) ? REGNO (x) : 0;
|
||||
|
||||
switch (code)
|
||||
{
|
||||
|
@ -2189,11 +2230,11 @@ mmix_print_operand (stream, x, code)
|
|||
case 'H':
|
||||
/* Highpart. Must be general register, and not the last one, as
|
||||
that one cannot be part of a consecutive register pair. */
|
||||
if (REGNO (x) > MMIX_LAST_GENERAL_REGISTER - 1)
|
||||
internal_error ("MMIX Internal: Bad register: %d", REGNO (x));
|
||||
if (regno > MMIX_LAST_GENERAL_REGISTER - 1)
|
||||
internal_error ("MMIX Internal: Bad register: %d", regno);
|
||||
|
||||
/* This is big-endian, so the high-part is the first one. */
|
||||
fprintf (stream, "%s", reg_names[REGNO (x)]);
|
||||
fprintf (stream, "%s", reg_names[MMIX_OUTPUT_REGNO (regno)]);
|
||||
return;
|
||||
|
||||
case 'L':
|
||||
|
@ -2213,11 +2254,11 @@ mmix_print_operand (stream, x, code)
|
|||
return;
|
||||
}
|
||||
|
||||
if (REGNO (x) > MMIX_LAST_GENERAL_REGISTER - 1)
|
||||
internal_error ("MMIX Internal: Bad register: %d", REGNO (x));
|
||||
if (regno > MMIX_LAST_GENERAL_REGISTER - 1)
|
||||
internal_error ("MMIX Internal: Bad register: %d", regno);
|
||||
|
||||
/* This is big-endian, so the low-part is + 1. */
|
||||
fprintf (stream, "%s", reg_names[REGNO (x) + 1]);
|
||||
fprintf (stream, "%s", reg_names[MMIX_OUTPUT_REGNO (regno) + 1]);
|
||||
return;
|
||||
|
||||
/* Can't use 'a' because that's a generic modifier for address
|
||||
|
@ -2273,19 +2314,15 @@ mmix_print_operand (stream, x, code)
|
|||
by the prologue. The actual operand contains the number of
|
||||
registers to pass, but we don't use it currently. Anyway, we
|
||||
need to output the number of saved registers here. */
|
||||
if (TARGET_ABI_GNU)
|
||||
fprintf (stream, "%d", mmix_highest_saved_stack_register + 1);
|
||||
else
|
||||
/* FIXME: Get the effect of renaming $16, $17.. to the first
|
||||
unused call-saved reg. */
|
||||
fprintf (stream, "15");
|
||||
fprintf (stream, "%d",
|
||||
cfun->machine->highest_saved_stack_register + 1);
|
||||
return;
|
||||
|
||||
case 'r':
|
||||
/* Store the register to output a constant to. */
|
||||
if (! REG_P (x))
|
||||
fatal_insn ("MMIX Internal: Expected a register, not this", x);
|
||||
mmix_output_destination_register = REGNO (x);
|
||||
mmix_output_destination_register = MMIX_OUTPUT_REGNO (regno);
|
||||
return;
|
||||
|
||||
case 'I':
|
||||
|
@ -2332,9 +2369,10 @@ mmix_print_operand (stream, x, code)
|
|||
switch (GET_CODE (modified_x))
|
||||
{
|
||||
case REG:
|
||||
if (REGNO (modified_x) >= FIRST_PSEUDO_REGISTER)
|
||||
internal_error ("MMIX Internal: Bad register: %d", REGNO (modified_x));
|
||||
fprintf (stream, "%s", reg_names[REGNO (modified_x)]);
|
||||
regno = REGNO (modified_x);
|
||||
if (regno >= FIRST_PSEUDO_REGISTER)
|
||||
internal_error ("MMIX Internal: Bad register: %d", regno);
|
||||
fprintf (stream, "%s", reg_names[MMIX_OUTPUT_REGNO (regno)]);
|
||||
return;
|
||||
|
||||
case MEM:
|
||||
|
@ -2402,7 +2440,7 @@ mmix_print_operand_address (stream, x)
|
|||
{
|
||||
/* I find the generated assembly code harder to read without
|
||||
the ",0". */
|
||||
fprintf (stream, "%s,0",reg_names[REGNO (x)]);
|
||||
fprintf (stream, "%s,0", reg_names[MMIX_OUTPUT_REGNO (REGNO (x))]);
|
||||
return;
|
||||
}
|
||||
else if (GET_CODE (x) == PLUS)
|
||||
|
@ -2420,11 +2458,12 @@ mmix_print_operand_address (stream, x)
|
|||
|
||||
if (REG_P (x1))
|
||||
{
|
||||
fprintf (stream, "%s,", reg_names[REGNO (x1)]);
|
||||
fprintf (stream, "%s,", reg_names[MMIX_OUTPUT_REGNO (REGNO (x1))]);
|
||||
|
||||
if (REG_P (x2))
|
||||
{
|
||||
fprintf (stream, "%s", reg_names[REGNO (x2)]);
|
||||
fprintf (stream, "%s",
|
||||
reg_names[MMIX_OUTPUT_REGNO (REGNO (x2))]);
|
||||
return;
|
||||
}
|
||||
else if (GET_CODE (x2) == CONST_INT
|
||||
|
@ -2455,7 +2494,7 @@ mmix_asm_output_reg_push (stream, regno)
|
|||
fprintf (stream, "\tSUBU %s,%s,8\n\tSTOU %s,%s,0\n",
|
||||
reg_names[MMIX_STACK_POINTER_REGNUM],
|
||||
reg_names[MMIX_STACK_POINTER_REGNUM],
|
||||
reg_names[regno],
|
||||
reg_names[MMIX_OUTPUT_REGNO (regno)],
|
||||
reg_names[MMIX_STACK_POINTER_REGNUM]);
|
||||
}
|
||||
|
||||
|
@ -2467,7 +2506,7 @@ mmix_asm_output_reg_pop (stream, regno)
|
|||
int regno;
|
||||
{
|
||||
fprintf (stream, "\tLDOU %s,%s,0\n\tINCL %s,8\n",
|
||||
reg_names[regno],
|
||||
reg_names[MMIX_OUTPUT_REGNO (regno)],
|
||||
reg_names[MMIX_STACK_POINTER_REGNUM],
|
||||
reg_names[MMIX_STACK_POINTER_REGNUM]);
|
||||
}
|
||||
|
@ -2527,8 +2566,11 @@ int
|
|||
mmix_dbx_register_number (regno)
|
||||
int regno;
|
||||
{
|
||||
/* FIXME: Implement final register renumbering if necessary. (Use
|
||||
target state in cfun). */
|
||||
/* Adjust the register number to the one it will be output as, dammit.
|
||||
It'd be nice if we could check the assumption that we're filling a
|
||||
gap, but every register between the last saved register and parameter
|
||||
registers might be a valid parameter register. */
|
||||
regno = MMIX_OUTPUT_REGNO (regno);
|
||||
|
||||
/* We need to renumber registers to get the number of the return address
|
||||
register in the range 0..255. It is also space-saving if registers
|
||||
|
|
|
@ -49,7 +49,7 @@ Boston, MA 02111-1307, USA. */
|
|||
#define MMIX_HIMULT_REGNUM 258
|
||||
#define MMIX_REMAINDER_REGNUM 260
|
||||
#define MMIX_ARG_POINTER_REGNUM 261
|
||||
#define MMIX_LAST_REGISTER_FILE_REGNUM 31
|
||||
#define MMIX_LAST_STACK_REGISTER_REGNUM 31
|
||||
|
||||
/* Four registers; "ideally, these registers should be call-clobbered", so
|
||||
just grab a bunch of the common clobbered registers. FIXME: Last
|
||||
|
@ -91,6 +91,7 @@ extern struct rtx_def *mmix_compare_op1;
|
|||
struct machine_function
|
||||
{
|
||||
int has_landing_pad;
|
||||
int highest_saved_stack_register;
|
||||
};
|
||||
|
||||
/* For these target macros, there is no generic documentation here. You
|
||||
|
@ -1196,7 +1197,6 @@ const_section () \
|
|||
|
||||
#define FUNCTION_MODE QImode
|
||||
|
||||
/* When in due time we *will* have some specific headers. */
|
||||
#define NO_IMPLICIT_EXTERN_C
|
||||
|
||||
#define HANDLE_SYSV_PRAGMA
|
||||
|
@ -1206,6 +1206,10 @@ const_section () \
|
|||
#define NO_DOLLAR_IN_LABEL
|
||||
#define NO_DOT_IN_LABEL
|
||||
|
||||
/* Calculate the highest used supposed saved stack register. */
|
||||
#define MACHINE_DEPENDENT_REORG(INSN) \
|
||||
mmix_machine_dependent_reorg (INSN)
|
||||
|
||||
#endif /* GCC_MMIX_H */
|
||||
/*
|
||||
* Local variables:
|
||||
|
|
|
@ -241,8 +241,10 @@
|
|||
;; One day we might persuade GCC to expand divisions with constants the
|
||||
;; way MMIX does; giving the remainder the sign of the divisor. But even
|
||||
;; then, it might be good to have an option to divide the way "everybody
|
||||
;; else" does. Perhaps then, this option can be on by default. Until
|
||||
;; then, we do division and modulus in a library function.
|
||||
;; else" does. Perhaps then, this option can be on by default. However,
|
||||
;; it's not likely to happen because major (C, C++, Fortran) language
|
||||
;; standards in effect at 2002-04-29 reportedly demand that the sign of
|
||||
;; the remainder must follow the sign of the dividend.
|
||||
|
||||
(define_insn "divmoddi4"
|
||||
[(set (match_operand:DI 0 "register_operand" "=r")
|
||||
|
|
Loading…
Reference in New Issue