mn10300.h (PREDICATE_CODES): Define.

* config/mn10300/mn10300.h (PREDICATE_CODES): Define.
2001-05-01  Alexandre Oliva  <aoliva@redhat.com>
* config/mn10300/mn10300.md (sqrtsf2): flag_fast_math was renamed
to flag_unsafe_math_optimizations.
2001-04-14  Alexandre Oliva  <aoliva@redhat.com>
* config/mn10300/mn10300.c (expand_prologue): Mark
FP-register-saving insns as frame-related.
2001-02-13  Alexandre Oliva  <aoliva@redhat.com>
* config/mn10300/mn10300.c
(mn10300_get_live_callee_saved_regs): Don't search past
LAST_EXTENDED_REGNUM.
(mn10300_gen_multiple_store, store_multiple_operation): Likewise.
* config/mn10300/mn10300.md: Remove excessive line breaks from
`@' output patterns that were accounted as additional
alternatives.
* config/mn10300/mn10300.md, config/mn10300/mn10300.c:
Re-introduce changes accidentally removed in Richard Sandiford's
2000-12-05's patch.
* config/mn10300/t-mn10300 (MULTILIB_OPTIONS, MULTILIB_DIRNAMES):
Re-instate am33-2 lost in merge from net GCC.
2000-08-26  Alexandre Oliva  <aoliva@redhat.com>
* config/mn10300/mn10300.h (DBX_REGISTER_NUMBER): Added
floating-point registers.
2000-08-07  Alexandre Oliva  <aoliva@redhat.com>
* config/mn10300/mn10300.md (movdf): Revert some am33-specific
pessimizations that had gone in on 2000-05-08.
2000-06-28  Graham Stott  <grahams@cygnus.co.uk>
* config/mn10300/mn10300.h (REG_CLASS_CONTENTS): Fix typo.
2000-06-22  Graham Stott  <grahams@cygnus.co.uk>
* config/mn10300/mn10300.md (movqi): Use nonimmediate_operand for
operand 0.
* (movhi): Likewise.
* (movsi): Likewise.
* (movsf): Likewise.
* (movdi): Likewise.
* (movdf): Likewise.
Wed May 24 13:16:09 2000  Alexandre Oliva  <aoliva@cygnus.com>
* config/mn10300/mn10300.c (fp_regs_to_save): New function.
(can_use_return_insn, initial_offset): Add fp_regs_to_save.
(expand_prologue, expand_epilogue): Save and restore FP regs.
2000-05-20  Alexandre Oliva  <aoliva@cygnus.com>
* config/mn10300/mn10300.md (movdi, movdf): 64-bit clean-up.
2000-05-13  Alexandre Oliva  <aoliva@cygnus.com>
* config/mn10300/mn10300.md (abssf2, negsf2, rsqrtsf2, addsf3,
subsf3, mulsf3, divsf3, fmaddsf4, fmsubsf4, fnmaddsf4, fnmsubsf4):
Do not clobber cc0.
2000-05-12  Alexandre Oliva  <aoliva@cygnus.com>
* config/mn10300/mn10300.md (abssf2, negsf2, rsqrtsf2):
Discourage the two-argument, longer opcodes.
(addsf3, subsf3, mulsf3, divsf3): Likewise for three-argument
ones.
* config/mn10300/mn10300.h (struct mn10300_cc_status_mdep): New.
(CC_STATUS_MDEP, CC_STATUS_MDEP_INIT): Define.
* config/mn10300/mn10300.md (cmpsf): New pattern.
(branch): Test mdep.fpCC and output fbCC.
* config/mn10300/mn10300.c (print_operand): Output conditions.
(notice_cc_update): Recognize fcmp and set mdep.fpCC.
2000-05-10  Alexandre Oliva  <aoliva@cygnus.com>
* config/mn10300/mn10300.md (movsf, movdf, addsf3, subsf3,
mulsf3, divsf3): Use the `F' constraint for FP values.
* config/mn10300/mn10300.c (const_1f_operand): New function.
* config/mn10300/mn10300-protos.h (const_1f_operand): Declare.
* config/mn10300/mn10300.md (sqrtsf2): New expand.
(rsqrtsf2): New insn.
2000-05-09  Alexandre Oliva  <aoliva@cygnus.com>
* config/mn10300/mn10300.md (movdf): Oops, I missed it in my
previous check-in.
2000-05-08  Alexandre Oliva  <aoliva@cygnus.com>
* config/mn10300/mn10300.md (abssf2, negdf2): On
TARGET_AM33_2, expand to...
(abssf2_am33_2, negdf2_am33_2): New insns.
(addsf3, subsf3, mulsf3, divsf3): Likewise.
(fmaddsf4, fmsubsf4, fnmaddsf4, fnmsubsf4): Likewise.
* config/mn10300/mn10300.md (movqi, movhi, movsi, movsf,
movdi, movdf): Added FP regs.
* invoke.texi (-mam33-2, -mno-am33-2): Document.
2000-04-29  Alexandre Oliva  <aoliva@cygnus.com>
* config/mn10300/mn10300.h (FIRST_FP_REGNUM, LAST_FP_REGNUM):
New macros.
(REGNO_AM33_2_FP_P): Renamed to...
(REGNO_FP_P): Redefine in terms of FIRST_* and LAST_*.
(CONDITIONAL_REGISTER_USAGE, REGNO_REG_CLASS): Likewise.
2000-04-27  Alexandre Oliva  <aoliva@cygnus.com>
* config/mn10300/mn10300.h (REG_CLASS_CONTENTS): Remove FP
regs from GENERAL_REGS.
2000-04-27  Alexandre Oliva  <aoliva@cygnus.com>
* config/mn10300/mn10300.h (REGNO_AM33_2_FP_P): New macro.
* config/mn10300/mn10300.c (mn10300_address_cost): Added FP_REGS.
* config/mn10300/mn10300.h (REGISTER_MOVE_COST): Added FP_REGS.
2000-04-23  Alexandre Oliva  <aoliva@cygnus.com>
* config/mn10300/mn10300.h (CLASS_CANNOT_CHANGE_SIZE): Defined
as FP_REGS.
2000-04-21  Alexandre Oliva  <aoliva@cygnus.com>
* config/mn10300/mn10300.h (OK_FOR_Q): New macro.
(EXTRA_CONSTRAINT): Added OK_FOR_Q.
* config/mn10300/mn10300.c (secondary_reload_class): Adjust.
* config/mn10300/mn10300.c (print_operand): Support `D' for doubles.
* config/mn10300/mn10300.h (FIRST_PSEUDO_REGISTER): Adjust.
(FIXED_REGISTERS, CALL_USED_REGISTERS, REG_ALLOC_ORDER): Added
AM33/2.0 floating-point registers.
(CONDITIONAL_REGISTER_USAGE): Adjust.
(enum reg_class, REG_CLASS_NAMES): Added FP_REGS and FP_ACC_REGS.
(REG_CLASS_CONTENTS, REGNO_REG_CLASS): Adjust.
(REG_CLASS_FROM_LETTER): Added `f' and `A'.
(REGISTER_NAMES, ADDITIONAL_REGISTER_NAMES): Adjust.
* config/mn10300/t-mn10300 (MULTILIB_OPTIONS): Added am33-2.
(MULTILIB_DIRNAMES): Likewise.
* config/mn10300/mn10300.h (CPP_SPEC): Define `__AM33__=2' and
`__AM33_2__' when `-mam33-2' is given.
(TARGET_AM33_2): Define.
(TARGET_SWITCHES): Adjust.
* config/mn10300/mn10300.c (asm_file_start): Print `.am33_2'
when appropriate.

From-SVN: r69167
This commit is contained in:
Alexandre Oliva 2003-07-10 02:56:29 +00:00 committed by Alexandre Oliva
parent 2ff167186b
commit 18e9d2f9e3
6 changed files with 977 additions and 61 deletions

View File

@ -1,3 +1,119 @@
2003-07-09 Alexandre Oliva <aoliva@redhat.com>
* config/mn10300/mn10300.h (PREDICATE_CODES): Define.
2001-05-01 Alexandre Oliva <aoliva@redhat.com>
* config/mn10300/mn10300.md (sqrtsf2): flag_fast_math was renamed
to flag_unsafe_math_optimizations.
2001-04-14 Alexandre Oliva <aoliva@redhat.com>
* config/mn10300/mn10300.c (expand_prologue): Mark
FP-register-saving insns as frame-related.
2001-02-13 Alexandre Oliva <aoliva@redhat.com>
* config/mn10300/mn10300.c
(mn10300_get_live_callee_saved_regs): Don't search past
LAST_EXTENDED_REGNUM.
(mn10300_gen_multiple_store, store_multiple_operation): Likewise.
* config/mn10300/mn10300.md: Remove excessive line breaks from
`@' output patterns that were accounted as additional
alternatives.
* config/mn10300/mn10300.md, config/mn10300/mn10300.c:
Re-introduce changes accidentally removed in Richard Sandiford's
2000-12-05's patch.
* config/mn10300/t-mn10300 (MULTILIB_OPTIONS, MULTILIB_DIRNAMES):
Re-instate am33-2 lost in merge from net GCC.
2000-08-26 Alexandre Oliva <aoliva@redhat.com>
* config/mn10300/mn10300.h (DBX_REGISTER_NUMBER): Added
floating-point registers.
2000-08-07 Alexandre Oliva <aoliva@redhat.com>
* config/mn10300/mn10300.md (movdf): Revert some am33-specific
pessimizations that had gone in on 2000-05-08.
2000-06-28 Graham Stott <grahams@cygnus.co.uk>
* config/mn10300/mn10300.h (REG_CLASS_CONTENTS): Fix typo.
2000-06-22 Graham Stott <grahams@cygnus.co.uk>
* config/mn10300/mn10300.md (movqi): Use nonimmediate_operand for
operand 0.
* (movhi): Likewise.
* (movsi): Likewise.
* (movsf): Likewise.
* (movdi): Likewise.
* (movdf): Likewise.
Wed May 24 13:16:09 2000 Alexandre Oliva <aoliva@cygnus.com>
* config/mn10300/mn10300.c (fp_regs_to_save): New function.
(can_use_return_insn, initial_offset): Add fp_regs_to_save.
(expand_prologue, expand_epilogue): Save and restore FP regs.
2000-05-20 Alexandre Oliva <aoliva@cygnus.com>
* config/mn10300/mn10300.md (movdi, movdf): 64-bit clean-up.
2000-05-13 Alexandre Oliva <aoliva@cygnus.com>
* config/mn10300/mn10300.md (abssf2, negsf2, rsqrtsf2, addsf3,
subsf3, mulsf3, divsf3, fmaddsf4, fmsubsf4, fnmaddsf4, fnmsubsf4):
Do not clobber cc0.
2000-05-12 Alexandre Oliva <aoliva@cygnus.com>
* config/mn10300/mn10300.md (abssf2, negsf2, rsqrtsf2):
Discourage the two-argument, longer opcodes.
(addsf3, subsf3, mulsf3, divsf3): Likewise for three-argument
ones.
* config/mn10300/mn10300.h (struct mn10300_cc_status_mdep): New.
(CC_STATUS_MDEP, CC_STATUS_MDEP_INIT): Define.
* config/mn10300/mn10300.md (cmpsf): New pattern.
(branch): Test mdep.fpCC and output fbCC.
* config/mn10300/mn10300.c (print_operand): Output conditions.
(notice_cc_update): Recognize fcmp and set mdep.fpCC.
2000-05-10 Alexandre Oliva <aoliva@cygnus.com>
* config/mn10300/mn10300.md (movsf, movdf, addsf3, subsf3,
mulsf3, divsf3): Use the `F' constraint for FP values.
* config/mn10300/mn10300.c (const_1f_operand): New function.
* config/mn10300/mn10300-protos.h (const_1f_operand): Declare.
* config/mn10300/mn10300.md (sqrtsf2): New expand.
(rsqrtsf2): New insn.
2000-05-09 Alexandre Oliva <aoliva@cygnus.com>
* config/mn10300/mn10300.md (movdf): Oops, I missed it in my
previous check-in.
2000-05-08 Alexandre Oliva <aoliva@cygnus.com>
* config/mn10300/mn10300.md (abssf2, negdf2): On
TARGET_AM33_2, expand to...
(abssf2_am33_2, negdf2_am33_2): New insns.
(addsf3, subsf3, mulsf3, divsf3): Likewise.
(fmaddsf4, fmsubsf4, fnmaddsf4, fnmsubsf4): Likewise.
* config/mn10300/mn10300.md (movqi, movhi, movsi, movsf,
movdi, movdf): Added FP regs.
* invoke.texi (-mam33-2, -mno-am33-2): Document.
2000-04-29 Alexandre Oliva <aoliva@cygnus.com>
* config/mn10300/mn10300.h (FIRST_FP_REGNUM, LAST_FP_REGNUM):
New macros.
(REGNO_AM33_2_FP_P): Renamed to...
(REGNO_FP_P): Redefine in terms of FIRST_* and LAST_*.
(CONDITIONAL_REGISTER_USAGE, REGNO_REG_CLASS): Likewise.
2000-04-27 Alexandre Oliva <aoliva@cygnus.com>
* config/mn10300/mn10300.h (REG_CLASS_CONTENTS): Remove FP
regs from GENERAL_REGS.
2000-04-27 Alexandre Oliva <aoliva@cygnus.com>
* config/mn10300/mn10300.h (REGNO_AM33_2_FP_P): New macro.
* config/mn10300/mn10300.c (mn10300_address_cost): Added FP_REGS.
* config/mn10300/mn10300.h (REGISTER_MOVE_COST): Added FP_REGS.
2000-04-23 Alexandre Oliva <aoliva@cygnus.com>
* config/mn10300/mn10300.h (CLASS_CANNOT_CHANGE_SIZE): Defined
as FP_REGS.
2000-04-21 Alexandre Oliva <aoliva@cygnus.com>
* config/mn10300/mn10300.h (OK_FOR_Q): New macro.
(EXTRA_CONSTRAINT): Added OK_FOR_Q.
* config/mn10300/mn10300.c (secondary_reload_class): Adjust.
* config/mn10300/mn10300.c (print_operand): Support `D' for doubles.
* config/mn10300/mn10300.h (FIRST_PSEUDO_REGISTER): Adjust.
(FIXED_REGISTERS, CALL_USED_REGISTERS, REG_ALLOC_ORDER): Added
AM33/2.0 floating-point registers.
(CONDITIONAL_REGISTER_USAGE): Adjust.
(enum reg_class, REG_CLASS_NAMES): Added FP_REGS and FP_ACC_REGS.
(REG_CLASS_CONTENTS, REGNO_REG_CLASS): Adjust.
(REG_CLASS_FROM_LETTER): Added `f' and `A'.
(REGISTER_NAMES, ADDITIONAL_REGISTER_NAMES): Adjust.
* config/mn10300/t-mn10300 (MULTILIB_OPTIONS): Added am33-2.
(MULTILIB_DIRNAMES): Likewise.
* config/mn10300/mn10300.h (CPP_SPEC): Define `__AM33__=2' and
`__AM33_2__' when `-mam33-2' is given.
(TARGET_AM33_2): Define.
(TARGET_SWITCHES): Adjust.
* config/mn10300/mn10300.c (asm_file_start): Print `.am33_2'
when appropriate.
2003-07-09 Matt Kraai <kraai@alumni.cmu.edu>
* doc/install.texi: Add missing @.

View File

@ -82,7 +82,9 @@ mn10300_file_start ()
{
default_file_start ();
if (TARGET_AM33)
if (TARGET_AM33_2)
fprintf (asm_out_file, "\t.am33_2\n");
else if (TARGET_AM33)
fprintf (asm_out_file, "\t.am33\n");
}
@ -100,6 +102,58 @@ print_operand (file, x, code)
{
case 'b':
case 'B':
if (cc_status.mdep.fpCC)
{
switch (code == 'b' ? GET_CODE (x)
: reverse_condition_maybe_unordered (GET_CODE (x)))
{
case NE:
fprintf (file, "ne");
break;
case EQ:
fprintf (file, "eq");
break;
case GE:
fprintf (file, "ge");
break;
case GT:
fprintf (file, "gt");
break;
case LE:
fprintf (file, "le");
break;
case LT:
fprintf (file, "lt");
break;
case ORDERED:
fprintf (file, "lge");
break;
case UNORDERED:
fprintf (file, "uo");
break;
case LTGT:
fprintf (file, "lg");
break;
case UNEQ:
fprintf (file, "ue");
break;
case UNGE:
fprintf (file, "uge");
break;
case UNGT:
fprintf (file, "ug");
break;
case UNLE:
fprintf (file, "ule");
break;
case UNLT:
fprintf (file, "ul");
break;
default:
abort ();
}
break;
}
/* These are normal and reversed branches. */
switch (code == 'b' ? GET_CODE (x) : reverse_condition (GET_CODE (x)))
{
@ -151,6 +205,24 @@ print_operand (file, x, code)
print_operand (file, x, 0);
break;
case 'D':
switch (GET_CODE (x))
{
case MEM:
fputc ('(', file);
output_address (XEXP (x, 0));
fputc (')', file);
break;
case REG:
fprintf (file, "fd%d", REGNO (x) - 18);
break;
default:
abort ();
}
break;
/* These are the least significant word in a 64bit value. */
case 'L':
switch (GET_CODE (x))
@ -388,6 +460,22 @@ print_operand_address (file, addr)
}
}
/* Count the number of FP registers that have to be saved. */
static int
fp_regs_to_save ()
{
int i, n = 0;
if (! TARGET_AM33_2)
return 0;
for (i = FIRST_FP_REGNUM; i <= LAST_FP_REGNUM; ++i)
if (regs_ever_live[i] && ! call_used_regs[i])
++n;
return n;
}
/* Print a set of registers in the format required by "movm" and "ret".
Register K is saved if bit K of MASK is set. The data and address
registers can be stored individually, but the extended registers cannot.
@ -446,6 +534,7 @@ can_use_return_insn ()
&& !regs_ever_live[15]
&& !regs_ever_live[16]
&& !regs_ever_live[17]
&& fp_regs_to_save () == 0
&& !frame_pointer_needed);
}
@ -460,7 +549,7 @@ mn10300_get_live_callee_saved_regs ()
int i;
mask = 0;
for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
for (i = 0; i <= LAST_EXTENDED_REGNUM; i++)
if (regs_ever_live[i] && ! call_used_regs[i])
mask |= (1 << i);
if ((mask & 0x3c000) != 0)
@ -501,7 +590,7 @@ mn10300_gen_multiple_store (mask)
/* Count how many registers need to be saved. */
count = 0;
for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
for (i = 0; i <= LAST_EXTENDED_REGNUM; i++)
if ((mask & (1 << i)) != 0)
count += 1;
@ -519,7 +608,7 @@ mn10300_gen_multiple_store (mask)
/* Create each store. */
pari = 1;
for (i = FIRST_PSEUDO_REGISTER - 1; i >= 0; i--)
for (i = LAST_EXTENDED_REGNUM; i >= 0; i--)
if ((mask & (1 << i)) != 0)
{
rtx address = gen_rtx_PLUS (SImode,
@ -549,6 +638,240 @@ expand_prologue ()
/* If we use any of the callee-saved registers, save them now. */
mn10300_gen_multiple_store (mn10300_get_live_callee_saved_regs ());
if (TARGET_AM33_2 && fp_regs_to_save ())
{
int num_regs_to_save = fp_regs_to_save (), i;
HOST_WIDE_INT xsize;
enum { save_sp_merge,
save_sp_no_merge,
save_sp_partial_merge,
save_a0_merge,
save_a0_no_merge } strategy;
unsigned int strategy_size = (unsigned)-1, this_strategy_size;
rtx reg;
rtx insn;
/* We have several different strategies to save FP registers.
We can store them using SP offsets, which is beneficial if
there are just a few registers to save, or we can use `a0' in
post-increment mode (`a0' is the only call-clobbered address
register that is never used to pass information to a
function). Furthermore, if we don't need a frame pointer, we
can merge the two SP adds into a single one, but this isn't
always beneficial; sometimes we can just split the two adds
so that we don't exceed a 16-bit constant size. The code
below will select which strategy to use, so as to generate
smallest code. Ties are broken in favor or shorter sequences
(in terms of number of instructions). */
#define SIZE_ADD_AX(S) ((((S) >= (1 << 15)) || ((S) < -(1 << 15))) ? 6 \
: (((S) >= (1 << 7)) || ((S) < -(1 << 7))) ? 4 : 2)
#define SIZE_ADD_SP(S) ((((S) >= (1 << 15)) || ((S) < -(1 << 15))) ? 6 \
: (((S) >= (1 << 7)) || ((S) < -(1 << 7))) ? 4 : 3)
#define SIZE_FMOV_LIMIT(S,N,L,SIZE1,SIZE2,ELSE) \
(((S) >= (L)) ? (SIZE1) * (N) \
: ((S) + 4 * (N) >= (L)) ? (((L) - (S)) / 4 * (SIZE2) \
+ ((S) + 4 * (N) - (L)) / 4 * (SIZE1)) \
: (ELSE))
#define SIZE_FMOV_SP_(S,N) \
(SIZE_FMOV_LIMIT ((S), (N), (1 << 24), 7, 6, \
SIZE_FMOV_LIMIT ((S), (N), (1 << 8), 6, 4, \
(S) ? 4 * (N) : 3 + 4 * ((N) - 1))))
#define SIZE_FMOV_SP(S,N) (SIZE_FMOV_SP_ ((unsigned HOST_WIDE_INT)(S), (N)))
/* Consider alternative save_sp_merge only if we don't need the
frame pointer and size is non-zero. */
if (! frame_pointer_needed && size)
{
/* Insn: add -(size + 4 * num_regs_to_save), sp. */
this_strategy_size = SIZE_ADD_SP (-(size + 4 * num_regs_to_save));
/* Insn: fmov fs#, (##, sp), for each fs# to be saved. */
this_strategy_size += SIZE_FMOV_SP (size, num_regs_to_save);
if (this_strategy_size < strategy_size)
{
strategy = save_sp_merge;
strategy_size = this_strategy_size;
}
}
/* Consider alternative save_sp_no_merge unconditionally. */
/* Insn: add -4 * num_regs_to_save, sp. */
this_strategy_size = SIZE_ADD_SP (-4 * num_regs_to_save);
/* Insn: fmov fs#, (##, sp), for each fs# to be saved. */
this_strategy_size += SIZE_FMOV_SP (0, num_regs_to_save);
if (size)
{
/* Insn: add -size, sp. */
this_strategy_size += SIZE_ADD_SP (-size);
}
if (this_strategy_size < strategy_size)
{
strategy = save_sp_no_merge;
strategy_size = this_strategy_size;
}
/* Consider alternative save_sp_partial_merge only if we don't
need a frame pointer and size is reasonably large. */
if (! frame_pointer_needed && size + 4 * num_regs_to_save > 128)
{
/* Insn: add -128, sp. */
this_strategy_size = SIZE_ADD_SP (-128);
/* Insn: fmov fs#, (##, sp), for each fs# to be saved. */
this_strategy_size += SIZE_FMOV_SP (128 - 4 * num_regs_to_save,
num_regs_to_save);
if (size)
{
/* Insn: add 128-size, sp. */
this_strategy_size += SIZE_ADD_SP (128 - size);
}
if (this_strategy_size < strategy_size)
{
strategy = save_sp_partial_merge;
strategy_size = this_strategy_size;
}
}
/* Consider alternative save_a0_merge only if we don't need a
frame pointer, size is non-zero and the user hasn't
changed the calling conventions of a0. */
if (! frame_pointer_needed && size
&& call_used_regs[FIRST_ADDRESS_REGNUM]
&& ! fixed_regs[FIRST_ADDRESS_REGNUM])
{
/* Insn: add -(size + 4 * num_regs_to_save), sp. */
this_strategy_size = SIZE_ADD_SP (-(size + 4 * num_regs_to_save));
/* Insn: mov sp, a0. */
this_strategy_size++;
if (size)
{
/* Insn: add size, a0. */
this_strategy_size += SIZE_ADD_AX (size);
}
/* Insn: fmov fs#, (a0+), for each fs# to be saved. */
this_strategy_size += 3 * num_regs_to_save;
if (this_strategy_size < strategy_size)
{
strategy = save_a0_merge;
strategy_size = this_strategy_size;
}
}
/* Consider alternative save_a0_no_merge if the user hasn't
changed the calling conventions of a0. */
if (call_used_regs[FIRST_ADDRESS_REGNUM]
&& ! fixed_regs[FIRST_ADDRESS_REGNUM])
{
/* Insn: add -4 * num_regs_to_save, sp. */
this_strategy_size = SIZE_ADD_SP (-4 * num_regs_to_save);
/* Insn: mov sp, a0. */
this_strategy_size++;
/* Insn: fmov fs#, (a0+), for each fs# to be saved. */
this_strategy_size += 3 * num_regs_to_save;
if (size)
{
/* Insn: add -size, sp. */
this_strategy_size += SIZE_ADD_SP (-size);
}
if (this_strategy_size < strategy_size)
{
strategy = save_a0_no_merge;
strategy_size = this_strategy_size;
}
}
/* Emit the initial SP add, common to all strategies. */
switch (strategy)
{
case save_sp_no_merge:
case save_a0_no_merge:
emit_insn (gen_addsi3 (stack_pointer_rtx,
stack_pointer_rtx,
GEN_INT (-4 * num_regs_to_save)));
xsize = 0;
break;
case save_sp_partial_merge:
emit_insn (gen_addsi3 (stack_pointer_rtx,
stack_pointer_rtx,
GEN_INT (-128)));
xsize = 128 - 4 * num_regs_to_save;
size -= xsize;
break;
case save_sp_merge:
case save_a0_merge:
emit_insn (gen_addsi3 (stack_pointer_rtx,
stack_pointer_rtx,
GEN_INT (-(size + 4 * num_regs_to_save))));
/* We'll have to adjust FP register saves according to the
frame size. */
xsize = size;
/* Since we've already created the stack frame, don't do it
again at the end of the function. */
size = 0;
break;
default:
abort ();
}
/* Now prepare register a0, if we have decided to use it. */
switch (strategy)
{
case save_sp_merge:
case save_sp_no_merge:
case save_sp_partial_merge:
reg = 0;
break;
case save_a0_merge:
case save_a0_no_merge:
reg = gen_rtx_REG (SImode, FIRST_ADDRESS_REGNUM);
emit_insn (gen_movsi (reg, stack_pointer_rtx));
if (xsize)
emit_insn (gen_addsi3 (reg, reg, GEN_INT (xsize)));
reg = gen_rtx_POST_INC (SImode, reg);
break;
default:
abort ();
}
/* Now actually save the FP registers. */
for (i = FIRST_FP_REGNUM; i <= LAST_FP_REGNUM; ++i)
if (regs_ever_live[i] && ! call_used_regs[i])
{
rtx addr;
if (reg)
addr = reg;
else
{
/* If we aren't using `a0', use an SP offset. */
if (xsize)
{
addr = gen_rtx_PLUS (SImode,
stack_pointer_rtx,
GEN_INT (xsize));
}
else
addr = stack_pointer_rtx;
xsize += 4;
}
insn = emit_insn (gen_movsi (gen_rtx_MEM (SImode, addr),
gen_rtx_REG (SImode, i)));
RTX_FRAME_RELATED_P (insn) = 1;
}
}
/* Now put the frame pointer into the frame pointer register. */
if (frame_pointer_needed)
emit_move_insn (frame_pointer_rtx, stack_pointer_rtx);
@ -569,6 +892,193 @@ expand_epilogue ()
size = get_frame_size () + current_function_outgoing_args_size;
size += (current_function_outgoing_args_size ? 4 : 0);
if (TARGET_AM33_2 && fp_regs_to_save ())
{
int num_regs_to_save = fp_regs_to_save (), i;
rtx reg = 0;
/* We have several options to restore FP registers. We could
load them from SP offsets, but, if there are enough FP
registers to restore, we win if we use a post-increment
addressing mode. */
/* If we have a frame pointer, it's the best option, because we
already know it has the value we want. */
if (frame_pointer_needed)
reg = gen_rtx_REG (SImode, FRAME_POINTER_REGNUM);
/* Otherwise, we may use `a1', since it's call-clobbered and
it's never used for return values. But only do so if it's
smaller than using SP offsets. */
else
{
enum { restore_sp_post_adjust,
restore_sp_pre_adjust,
restore_sp_partial_adjust,
restore_a1 } strategy;
unsigned int this_strategy_size, strategy_size = (unsigned)-1;
/* Consider using sp offsets before adjusting sp. */
/* Insn: fmov (##,sp),fs#, for each fs# to be restored. */
this_strategy_size = SIZE_FMOV_SP (size, num_regs_to_save);
/* If size is too large, we'll have to adjust SP with an
add. */
if (size + 4 * num_regs_to_save + REG_SAVE_BYTES > 255)
{
/* Insn: add size + 4 * num_regs_to_save, sp. */
this_strategy_size += SIZE_ADD_SP (size + 4 * num_regs_to_save);
}
/* If we don't have to restore any non-FP registers,
we'll be able to save one byte by using rets. */
if (! REG_SAVE_BYTES)
this_strategy_size--;
if (this_strategy_size < strategy_size)
{
strategy = restore_sp_post_adjust;
strategy_size = this_strategy_size;
}
/* Consider using sp offsets after adjusting sp. */
/* Insn: add size, sp. */
this_strategy_size = SIZE_ADD_SP (size);
/* Insn: fmov (##,sp),fs#, for each fs# to be restored. */
this_strategy_size += SIZE_FMOV_SP (0, num_regs_to_save);
/* We're going to use ret to release the FP registers
save area, so, no savings. */
if (this_strategy_size < strategy_size)
{
strategy = restore_sp_pre_adjust;
strategy_size = this_strategy_size;
}
/* Consider using sp offsets after partially adjusting sp.
When size is close to 32Kb, we may be able to adjust SP
with an imm16 add instruction while still using fmov
(d8,sp). */
if (size + 4 * num_regs_to_save + REG_SAVE_BYTES > 255)
{
/* Insn: add size + 4 * num_regs_to_save
+ REG_SAVE_BYTES - 252,sp. */
this_strategy_size = SIZE_ADD_SP (size + 4 * num_regs_to_save
+ REG_SAVE_BYTES - 252);
/* Insn: fmov (##,sp),fs#, fo each fs# to be restored. */
this_strategy_size += SIZE_FMOV_SP (252 - REG_SAVE_BYTES
- 4 * num_regs_to_save,
num_regs_to_save);
/* We're going to use ret to release the FP registers
save area, so, no savings. */
if (this_strategy_size < strategy_size)
{
strategy = restore_sp_partial_adjust;
strategy_size = this_strategy_size;
}
}
/* Consider using a1 in post-increment mode, as long as the
user hasn't changed the calling conventions of a1. */
if (call_used_regs[FIRST_ADDRESS_REGNUM+1]
&& ! fixed_regs[FIRST_ADDRESS_REGNUM+1])
{
/* Insn: mov sp,a1. */
this_strategy_size = 1;
if (size)
{
/* Insn: add size,a1. */
this_strategy_size += SIZE_ADD_AX (size);
}
/* Insn: fmov (a1+),fs#, for each fs# to be restored. */
this_strategy_size += 3 * num_regs_to_save;
/* If size is large enough, we may be able to save a
couple of bytes. */
if (size + 4 * num_regs_to_save + REG_SAVE_BYTES > 255)
{
/* Insn: mov a1,sp. */
this_strategy_size += 2;
}
/* If we don't have to restore any non-FP registers,
we'll be able to save one byte by using rets. */
if (! REG_SAVE_BYTES)
this_strategy_size--;
if (this_strategy_size < strategy_size)
{
strategy = restore_a1;
strategy_size = this_strategy_size;
}
}
switch (strategy)
{
case restore_sp_post_adjust:
break;
case restore_sp_pre_adjust:
emit_insn (gen_addsi3 (stack_pointer_rtx,
stack_pointer_rtx,
GEN_INT (size)));
size = 0;
break;
case restore_sp_partial_adjust:
emit_insn (gen_addsi3 (stack_pointer_rtx,
stack_pointer_rtx,
GEN_INT (size + 4 * num_regs_to_save
+ REG_SAVE_BYTES - 252)));
size = 252 - REG_SAVE_BYTES - 4 * num_regs_to_save;
break;
case restore_a1:
reg = gen_rtx_REG (SImode, FIRST_ADDRESS_REGNUM + 1);
emit_insn (gen_movsi (reg, stack_pointer_rtx));
if (size)
emit_insn (gen_addsi3 (reg, reg, GEN_INT (size)));
break;
default:
abort ();
}
}
/* Adjust the selected register, if any, for post-increment. */
if (reg)
reg = gen_rtx_POST_INC (SImode, reg);
for (i = FIRST_FP_REGNUM; i <= LAST_FP_REGNUM; ++i)
if (regs_ever_live[i] && ! call_used_regs[i])
{
rtx addr;
if (reg)
addr = reg;
else if (size)
{
/* If we aren't using a post-increment register, use an
SP offset. */
addr = gen_rtx_PLUS (SImode,
stack_pointer_rtx,
GEN_INT (size));
}
else
addr = stack_pointer_rtx;
size += 4;
emit_insn (gen_movsi (gen_rtx_REG (SImode, i),
gen_rtx_MEM (SImode, addr)));
}
/* If we were using the restore_a1 strategy and the number of
bytes to be released won't fit in the `ret' byte, copy `a1'
to `sp', to avoid having to use `add' to adjust it. */
if (! frame_pointer_needed && reg && size + REG_SAVE_BYTES > 255)
{
emit_move_insn (stack_pointer_rtx, XEXP (reg, 0));
size = 0;
}
}
/* Maybe cut back the stack, except for the register save area.
If the frame pointer exists, then use the frame pointer to
@ -649,6 +1159,9 @@ notice_update_cc (body, insn)
/* The insn is a compare instruction. */
CC_STATUS_INIT;
cc_status.value1 = SET_SRC (body);
if (GET_CODE (cc_status.value1) == COMPARE
&& GET_MODE (XEXP (cc_status.value1, 0)) == SFmode)
cc_status.mdep.fpCC = 1;
break;
case CC_INVERT:
@ -714,7 +1227,7 @@ store_multiple_operation (op, mode)
LAST keeps track of the smallest-numbered register stored so far.
MASK is the set of stored registers. */
last = FIRST_PSEUDO_REGISTER;
last = LAST_EXTENDED_REGNUM + 1;
mask = 0;
for (i = 1; i < count; i++)
{
@ -810,6 +1323,14 @@ secondary_reload_class (class, mode, in)
return DATA_REGS;
}
if (TARGET_AM33_2 && class == FP_REGS
&& GET_CODE (in) == MEM && ! OK_FOR_Q (in))
{
if (TARGET_AM33)
return DATA_OR_EXTENDED_REGS;
return DATA_REGS;
}
/* Otherwise assume no secondary reloads are needed. */
return NO_REGS;
}
@ -826,8 +1347,10 @@ initial_offset (from, to)
|| regs_ever_live[6] || regs_ever_live[7]
|| regs_ever_live[14] || regs_ever_live[15]
|| regs_ever_live[16] || regs_ever_live[17]
|| fp_regs_to_save ()
|| frame_pointer_needed)
return REG_SAVE_BYTES;
return REG_SAVE_BYTES
+ 4 * fp_regs_to_save ();
else
return 0;
}
@ -841,8 +1364,10 @@ initial_offset (from, to)
|| regs_ever_live[6] || regs_ever_live[7]
|| regs_ever_live[14] || regs_ever_live[15]
|| regs_ever_live[16] || regs_ever_live[17]
|| fp_regs_to_save ()
|| frame_pointer_needed)
return (get_frame_size () + REG_SAVE_BYTES
+ 4 * fp_regs_to_save ()
+ (current_function_outgoing_args_size
? current_function_outgoing_args_size + 4 : 0));
else
@ -1155,6 +1680,15 @@ const_8bit_operand (op, mode)
&& INTVAL (op) < 256);
}
/* Return true if the operand is the 1.0f constant. */
int
const_1f_operand (op, mode)
register rtx op;
enum machine_mode mode ATTRIBUTE_UNUSED;
{
return (op == CONST1_RTX (SFmode));
}
/* Similarly, but when using a zero_extract pattern for a btst where
the source operand might end up in memory. */
int
@ -1271,6 +1805,7 @@ mn10300_address_cost_1 (x, unsig)
case DATA_REGS:
case EXTENDED_REGS:
case FP_REGS:
return 3;
case NO_REGS:

View File

@ -1,6 +1,6 @@
/* Definitions of target machine for GNU compiler.
Matsushita MN10300 series
Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002
Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
Free Software Foundation, Inc.
Contributed by Jeff Law (law@cygnus.com).
@ -40,7 +40,7 @@ Boston, MA 02111-1307, USA. */
} \
while (0)
#define CPP_SPEC "%{mam33:-D__AM33__}"
#define CPP_SPEC "%{mam33:-D__AM33__} %{mam33-2:-D__AM33__=2 -D__AM33_2__}"
/* Run-time compilation parameters selecting different hardware subsets. */
@ -60,6 +60,9 @@ extern int target_flags;
/* Generate code for the AM33 processor. */
#define TARGET_AM33 (target_flags & 0x2)
/* Generate code for the AM33/2.0 processor. */
#define TARGET_AM33_2 (target_flags & 0x4)
#define TARGET_SWITCHES \
{{ "mult-bug", 0x1, N_("Work around hardware multiply bug")}, \
{ "no-mult-bug", -0x1, N_("Do not work around hardware multiply bug")},\
@ -67,6 +70,9 @@ extern int target_flags;
{ "am33", -(0x1), ""},\
{ "no-am33", -0x2, ""}, \
{ "no-crt0", 0, N_("No default crt0.o") }, \
{ "am33-2", 0x6, N_("Target the AM33/2.0 processor")}, \
{ "am33-2", -(0x1), ""},\
{ "no-am33-2", -0x4, ""}, \
{ "relax", 0, N_("Enable linker relaxations") }, \
{ "", TARGET_DEFAULT, NULL}}
@ -131,7 +137,7 @@ extern int target_flags;
All registers that the compiler knows about must be given numbers,
even those that are not normally considered general registers. */
#define FIRST_PSEUDO_REGISTER 18
#define FIRST_PSEUDO_REGISTER 50
/* Specify machine-specific register numbers. */
#define FIRST_DATA_REGNUM 0
@ -140,6 +146,8 @@ extern int target_flags;
#define LAST_ADDRESS_REGNUM 8
#define FIRST_EXTENDED_REGNUM 10
#define LAST_EXTENDED_REGNUM 17
#define FIRST_FP_REGNUM 18
#define LAST_FP_REGNUM 49
/* Specify the registers used for certain standard purposes.
The values of these macros are register numbers. */
@ -162,7 +170,10 @@ extern int target_flags;
and are not available for the register allocator. */
#define FIXED_REGISTERS \
{ 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0}
{ 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0 \
, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 \
, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 \
}
/* 1 for registers not available across function calls.
These must include the FIXED_REGISTERS and also any
@ -173,10 +184,16 @@ extern int target_flags;
like. */
#define CALL_USED_REGISTERS \
{ 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0}
{ 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0 \
, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 \
, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 \
}
#define REG_ALLOC_ORDER \
{ 0, 1, 4, 5, 2, 3, 6, 7, 10, 11, 12, 13, 14, 15, 16, 17, 8, 9}
{ 0, 1, 4, 5, 2, 3, 6, 7, 10, 11, 12, 13, 14, 15, 16, 17, 8, 9 \
, 42, 43, 44, 45, 46, 47, 48, 49, 34, 35, 36, 37, 38, 39, 40, 41 \
, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33 \
}
#define CONDITIONAL_REGISTER_USAGE \
{ \
@ -188,6 +205,13 @@ extern int target_flags;
i <= LAST_EXTENDED_REGNUM; i++) \
fixed_regs[i] = call_used_regs[i] = 1; \
} \
if (!TARGET_AM33_2) \
{ \
for (i = FIRST_FP_REGNUM; \
i <= LAST_FP_REGNUM; \
i++) \
fixed_regs[i] = call_used_regs[i] = 1; \
} \
}
/* Return number of consecutive hard regs needed starting at reg REGNO
@ -247,6 +271,7 @@ enum reg_class {
DATA_OR_ADDRESS_REGS, SP_OR_ADDRESS_REGS,
EXTENDED_REGS, DATA_OR_EXTENDED_REGS, ADDRESS_OR_EXTENDED_REGS,
SP_OR_EXTENDED_REGS, SP_OR_ADDRESS_OR_EXTENDED_REGS,
FP_REGS, FP_ACC_REGS,
GENERAL_REGS, ALL_REGS, LIM_REG_CLASSES
};
@ -260,6 +285,7 @@ enum reg_class {
"EXTENDED_REGS", \
"DATA_OR_EXTENDED_REGS", "ADDRESS_OR_EXTENDED_REGS", \
"SP_OR_EXTENDED_REGS", "SP_OR_ADDRESS_OR_EXTENDED_REGS", \
"FP_REGS", "FP_ACC_REGS", \
"GENERAL_REGS", "ALL_REGS", "LIM_REGS" }
/* Define which registers fit in which classes.
@ -267,19 +293,21 @@ enum reg_class {
of length N_REG_CLASSES. */
#define REG_CLASS_CONTENTS \
{ {0}, /* No regs */ \
{0x0000f}, /* DATA_REGS */ \
{0x001f0}, /* ADDRESS_REGS */ \
{0x00200}, /* SP_REGS */ \
{0x001ff}, /* DATA_OR_ADDRESS_REGS */\
{0x003f0}, /* SP_OR_ADDRESS_REGS */\
{0x3fc00}, /* EXTENDED_REGS */ \
{0x3fc0f}, /* DATA_OR_EXTENDED_REGS */ \
{0x3fdf0}, /* ADDRESS_OR_EXTENDED_REGS */ \
{0x3fe00}, /* SP_OR_EXTENDED_REGS */ \
{0x3fff0}, /* SP_OR_ADDRESS_OR_EXTENDED_REGS */ \
{0x3fdff}, /* GENERAL_REGS */ \
{0x3ffff}, /* ALL_REGS */ \
{ { 0, 0 }, /* No regs */ \
{ 0x0000f, 0 }, /* DATA_REGS */ \
{ 0x001f0, 0 }, /* ADDRESS_REGS */ \
{ 0x00200, 0 }, /* SP_REGS */ \
{ 0x001ff, 0 }, /* DATA_OR_ADDRESS_REGS */\
{ 0x003f0, 0 }, /* SP_OR_ADDRESS_REGS */\
{ 0x3fc00, 0 }, /* EXTENDED_REGS */ \
{ 0x3fc0f, 0 }, /* DATA_OR_EXTENDED_REGS */ \
{ 0x3fdf0, 0 }, /* ADDRESS_OR_EXTENDED_REGS */ \
{ 0x3fe00, 0 }, /* SP_OR_EXTENDED_REGS */ \
{ 0x3fff0, 0 }, /* SP_OR_ADDRESS_OR_EXTENDED_REGS */ \
{ 0xfffc0000, 0x3ffff }, /* FP_REGS */ \
{ 0x03fc0000, 0 }, /* FP_ACC_REGS */ \
{ 0x3fdff, 0 }, /* GENERAL_REGS */ \
{ 0xffffffff, 0x3ffff } /* ALL_REGS */ \
}
/* The same information, inverted:
@ -292,6 +320,7 @@ enum reg_class {
(REGNO) <= LAST_ADDRESS_REGNUM ? ADDRESS_REGS : \
(REGNO) == STACK_POINTER_REGNUM ? SP_REGS : \
(REGNO) <= LAST_EXTENDED_REGNUM ? EXTENDED_REGS : \
(REGNO) <= LAST_FP_REGNUM ? FP_REGS : \
NO_REGS)
/* The class value for index registers, and the one for base regs. */
@ -306,6 +335,9 @@ enum reg_class {
(C) == 'y' ? SP_REGS : \
! TARGET_AM33 ? NO_REGS : \
(C) == 'x' ? EXTENDED_REGS : \
! TARGET_AM33_2 ? NO_REGS : \
(C) == 'f' ? FP_REGS : \
(C) == 'A' ? FP_ACC_REGS : \
NO_REGS)
/* Macros to check register numbers against specific register classes. */
@ -350,6 +382,8 @@ enum reg_class {
#define REGNO_AM33_P(regno) \
(REGNO_DATA_P ((regno)) || REGNO_ADDRESS_P ((regno)) \
|| REGNO_EXTENDED_P ((regno)))
#define REGNO_FP_P(regno) \
REGNO_IN_RANGE_P ((regno), FIRST_FP_REGNUM, LAST_FP_REGNUM)
#define REGNO_OK_FOR_BASE_P(regno) \
(REGNO_SP_P ((regno)) \
@ -397,6 +431,11 @@ enum reg_class {
#define CLASS_MAX_NREGS(CLASS, MODE) \
((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
/* A class that contains registers which the compiler must always
access in a mode that is the same size as the mode in which it
loaded the register. */
#define CLASS_CANNOT_CHANGE_SIZE FP_REGS
/* The letters I, J, K, L, M, N, O, P in a register constraint string
can be used to stand for particular ranges of immediate operands.
This macro defines what the ranges are.
@ -669,6 +708,9 @@ struct cum_arg {int nbytes; };
/* Extra constraints. */
#define OK_FOR_Q(OP) \
(GET_CODE (OP) == MEM && ! CONSTANT_ADDRESS_P (XEXP (OP, 0)))
#define OK_FOR_R(OP) \
(GET_CODE (OP) == MEM \
&& GET_MODE (OP) == QImode \
@ -692,6 +734,7 @@ struct cum_arg {int nbytes; };
#define EXTRA_CONSTRAINT(OP, C) \
((C) == 'R' ? OK_FOR_R (OP) \
: (C) == 'Q' ? OK_FOR_Q (OP) \
: (C) == 'S' ? GET_CODE (OP) == SYMBOL_REF \
: (C) == 'T' ? OK_FOR_T (OP) \
: 0)
@ -814,6 +857,7 @@ struct cum_arg {int nbytes; };
! TARGET_AM33 ? 6 : \
(CLASS1 == SP_REGS || CLASS2 == SP_REGS) ? 6 : \
(CLASS1 == CLASS2 && CLASS1 == EXTENDED_REGS) ? 6 : \
(CLASS1 == FP_REGS || CLASS2 == FP_REGS) ? 6 : \
(CLASS1 == EXTENDED_REGS || CLASS2 == EXTENDED_REGS) ? 4 : \
4)
@ -885,6 +929,10 @@ struct cum_arg {int nbytes; };
#define REGISTER_NAMES \
{ "d0", "d1", "d2", "d3", "a0", "a1", "a2", "a3", "ap", "sp", \
"r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7" \
, "fs0", "fs1", "fs2", "fs3", "fs4", "fs5", "fs6", "fs7" \
, "fs8", "fs9", "fs10", "fs11", "fs12", "fs13", "fs14", "fs15" \
, "fs16", "fs17", "fs18", "fs19", "fs20", "fs21", "fs22", "fs23" \
, "fs24", "fs25", "fs26", "fs27", "fs28", "fs29", "fs30", "fs31" \
}
#define ADDITIONAL_REGISTER_NAMES \
@ -892,6 +940,10 @@ struct cum_arg {int nbytes; };
{"r12", 0}, {"r13", 1}, {"r14", 2}, {"r15", 3}, \
{"e0", 10}, {"e1", 11}, {"e2", 12}, {"e3", 13}, \
{"e4", 14}, {"e5", 15}, {"e6", 16}, {"e7", 17} \
, {"fd0", 18}, {"fd2", 20}, {"fd4", 22}, {"fd6", 24} \
, {"fd8", 26}, {"fd10", 28}, {"fd12", 30}, {"fd14", 32} \
, {"fd16", 34}, {"fd18", 36}, {"fd20", 38}, {"fd22", 40} \
, {"fd24", 42}, {"fd26", 44}, {"fd28", 46}, {"fd30", 48} \
}
/* Print an instruction operand X on file FILE.
@ -994,3 +1046,15 @@ struct cum_arg {int nbytes; };
#define FILE_ASM_OP "\t.file\n"
#define PREDICATE_CODES \
{"const_1f_operand", {CONST_INT, CONST_DOUBLE}},
typedef struct mn10300_cc_status_mdep
{
int fpCC;
}
cc_status_mdep;
#define CC_STATUS_MDEP cc_status_mdep
#define CC_STATUS_MDEP_INIT (cc_status.mdep.fpCC = 0)

View File

@ -57,8 +57,8 @@
}")
(define_insn ""
[(set (match_operand:QI 0 "nonimmediate_operand" "=d*x*a,d*x,d*x*a,d*x*a,m")
(match_operand:QI 1 "general_operand" "0,I,d*xai,m,d*xa"))]
[(set (match_operand:QI 0 "nonimmediate_operand" "=d*x*a*f,d*x,d*x*a,d*x*a,m,*f,d*x*a")
(match_operand:QI 1 "general_operand" "0,I,d*xai,m,d*xa,d*xa*f,*f"))]
"TARGET_AM33
&& (register_operand (operands[0], QImode)
|| register_operand (operands[1], QImode))"
@ -93,11 +93,14 @@
case 3:
case 4:
return \"movbu %1,%0\";
case 5:
case 6:
return \"fmov %1,%0\";
default:
abort ();
}
}"
[(set_attr "cc" "none,clobber,none_0hit,none_0hit,none_0hit")])
[(set_attr "cc" "none,clobber,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit")])
(define_insn ""
[(set (match_operand:QI 0 "nonimmediate_operand" "=d*a,d,d*a,d,m")
@ -147,8 +150,8 @@
}")
(define_insn ""
[(set (match_operand:HI 0 "nonimmediate_operand" "=d*x*a,d*x,d*x*a,d*x*a,m")
(match_operand:HI 1 "general_operand" "0,I,d*x*ai,m,d*x*a"))]
[(set (match_operand:HI 0 "nonimmediate_operand" "=d*x*a*f,d*x,d*x*a,d*x*a,m,*f,d*x*a")
(match_operand:HI 1 "general_operand" "0,I,d*x*ai,m,d*x*a,d*x*a*f,*f"))]
"TARGET_AM33
&& (register_operand (operands[0], HImode)
|| register_operand (operands[1], HImode))"
@ -183,11 +186,14 @@
case 3:
case 4:
return \"movhu %1,%0\";
case 5:
case 6:
return \"fmov %1,%0\";
default:
abort ();
}
}"
[(set_attr "cc" "none,clobber,none_0hit,none_0hit,none_0hit")])
[(set_attr "cc" "none,clobber,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit")])
(define_insn ""
[(set (match_operand:HI 0 "nonimmediate_operand" "=d*a,d,d*a,d,m")
@ -277,9 +283,9 @@
(define_insn ""
[(set (match_operand:SI 0 "nonimmediate_operand"
"=dx,ax,dx,a,dxm,dxm,axm,axm,dx,dx,ax,ax,axR,!*y")
"=dx,ax,dx,a,dxm,dxm,axm,axm,dx,dx,ax,ax,axR,!*y,*f,*f,dxaQ")
(match_operand:SI 1 "general_operand"
"0,0,I,I,dx,ax,dx,ax,dixm,aixm,dixm,aixm,!*y,axR"))]
"0,0,I,I,dx,ax,dx,ax,dixm,aixm,dixm,aixm,!*y,axR,0,dxaQi*f,*f"))]
"register_operand (operands[0], SImode)
|| register_operand (operands[1], SImode)"
"*
@ -321,11 +327,16 @@
return \"movu %1,%0\";
}
return \"mov %1,%0\";
case 14:
return \"nop\";
case 15:
case 16:
return \"fmov %1,%0\";
default:
abort ();
}
}"
[(set_attr "cc" "none,none,clobber,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit")])
[(set_attr "cc" "none,none,clobber,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none,none_0hit,none_0hit")])
(define_expand "movsf"
[(set (match_operand:SF 0 "general_operand" "")
@ -340,8 +351,8 @@
}")
(define_insn ""
[(set (match_operand:SF 0 "nonimmediate_operand" "=dx,ax,dx,a,daxm,dax")
(match_operand:SF 1 "general_operand" "0,0,G,G,dax,daxFm"))]
[(set (match_operand:SF 0 "nonimmediate_operand" "=f,dx,ax,dx,a,f,dxaQ,daxm,dax")
(match_operand:SF 1 "general_operand" "0,0,0,G,G,fdxaQF,f,dax,daxFm"))]
"register_operand (operands[0], SFmode)
|| register_operand (operands[1], SFmode)"
"*
@ -350,12 +361,17 @@
{
case 0:
case 1:
return \"nop\";
case 2:
return \"clr %0\";
return \"nop\";
case 3:
case 4:
return \"clr %0\";
/* case 4: below */
case 5:
case 6:
return \"fmov %1, %0\";
case 4:
case 7:
case 8:
if (REGNO_REG_CLASS (true_regnum (operands[0])) == EXTENDED_REGS
&& GET_CODE (operands[1]) == CONST_INT)
{
@ -370,7 +386,7 @@
abort ();
}
}"
[(set_attr "cc" "none,none,clobber,none_0hit,none_0hit,none_0hit")])
[(set_attr "cc" "none,none,none,clobber,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit")])
(define_expand "movdi"
[(set (match_operand:DI 0 "general_operand" "")
@ -386,9 +402,9 @@
(define_insn ""
[(set (match_operand:DI 0 "nonimmediate_operand"
"=dx,ax,dx,a,dxm,dxm,axm,axm,dx,dx,ax,ax")
"=dx,ax,dx,a,dxm,dxm,axm,axm,dx,dx,ax,ax,*f,*f,*f,dxa,*f,Q")
(match_operand:DI 1 "general_operand"
"0,0,I,I,dx,ax,dx,ax,dxim,axim,dxim,axim"))]
"0,0,I,I,dx,ax,dx,ax,dxim,axim,dxim,axim,0,*f,dxai,*f,Q,*f"))]
"register_operand (operands[0], DImode)
|| register_operand (operands[1], DImode)"
"*
@ -516,6 +532,26 @@
output_asm_insn (\"mov %H1,%H0\", operands);
return \"\";
}
case 12:
return \"nop\";
case 13:
case 14:
case 15:
return \"fmov %L1, %L0\;fmov %H1, %H0\";
case 16:
if (GET_CODE (operands[1]) == MEM
&& GET_CODE (XEXP (operands[1], 0)) == CONST_INT
&& (INTVAL (XEXP (operands[1], 0)) & 7) == 0)
return \"fmov %D1, %D0\";
else
return \"fmov %L1, %L0\;fmov %H1, %H0\";
case 17:
if (GET_CODE (operands[0]) == MEM
&& GET_CODE (XEXP (operands[0], 0)) == CONST_INT
&& (INTVAL (XEXP (operands[0], 0)) & 7) == 0)
return \"fmov %D1, %D0\";
else
return \"fmov %L1, %L0\;fmov %H1, %H0\";
default:
abort ();
}
@ -523,8 +559,9 @@
[(set (attr "cc")
(cond
[
(lt (symbol_ref "which_alternative") (const_int 2)
) (const_string "none")
(ior (lt (symbol_ref "which_alternative") (const_int 2))
(eq (symbol_ref "which_alternative") (const_int 12))
) (const_string "none")
(eq (symbol_ref "which_alternative") (const_int 2)
) (const_string "clobber")
(eq (symbol_ref "which_alternative") (const_int 3)
@ -555,9 +592,9 @@
(define_insn ""
[(set (match_operand:DF 0 "nonimmediate_operand"
"=dx,ax,dx,a,dxm,dxm,axm,axm,dx,dx,ax,ax")
"=f,dx,ax,dx,f,f,dxa,f,Q,a,dxm,dxm,axm,axm,dx,dx,ax,ax")
(match_operand:DF 1 "general_operand"
"0,0,G,G,dx,ax,dx,ax,dxFm,axFm,dxFm,axFm"))]
"0,0,0,G,f,dxaF,f,Q,f,G,dx,ax,dx,ax,dxFm,axFm,dxFm,axFm"))]
"register_operand (operands[0], DFmode)
|| register_operand (operands[1], DFmode)"
"*
@ -569,24 +606,46 @@
{
case 0:
case 1:
case 2:
return \"nop\";
case 2:
case 3:
return \"clr %L0\;clr %H0\";
case 3:
case 4:
case 5:
case 6:
return \"fmov %L1, %L0\;fmov %H1, %H0\";
case 7:
if (GET_CODE (operands[1]) == MEM
&& GET_CODE (XEXP (operands[1], 0)) == CONST_INT
&& (INTVAL (XEXP (operands[1], 0)) & 7) == 0)
return \"fmov %D1, %D0\";
else
return \"fmov %L1, %L0\;fmov %H1, %H0\";
case 8:
if (GET_CODE (operands[0]) == MEM
&& GET_CODE (XEXP (operands[0], 0)) == CONST_INT
&& (INTVAL (XEXP (operands[0], 0)) & 7) == 0)
return \"fmov %D1, %D0\";
else
return \"fmov %L1, %L0\;fmov %H1, %H0\";
case 9:
if (rtx_equal_p (operands[0], operands[1]))
return \"sub %L1,%L0\;mov %L0,%H0\";
else
return \"mov %1,%L0\;mov %L0,%H0\";
case 4:
case 5:
case 6:
case 7:
case 8:
case 9:
case 10:
case 11:
case 12:
case 13:
case 14:
case 15:
case 16:
case 17:
if (GET_CODE (operands[1]) == CONST_INT)
{
rtx low, high;
@ -692,17 +751,17 @@
[(set (attr "cc")
(cond
[
(lt (symbol_ref "which_alternative") (const_int 2)
(lt (symbol_ref "which_alternative") (const_int 3)
) (const_string "none")
(eq (symbol_ref "which_alternative") (const_int 2)
) (const_string "clobber")
(eq (symbol_ref "which_alternative") (const_int 3)
) (const_string "clobber")
(eq (symbol_ref "which_alternative") (const_int 9)
) (if_then_else
(ne (symbol_ref "rtx_equal_p (operands[0], operands[1])")
(const_int 0)) (const_string "clobber")
(const_string "none_0hit"))
(ior (eq (symbol_ref "which_alternative") (const_int 8))
(eq (symbol_ref "which_alternative") (const_int 9))
(ior (eq (symbol_ref "which_alternative") (const_int 14))
(eq (symbol_ref "which_alternative") (const_int 15))
) (if_then_else
(ne (symbol_ref "mn10300_wide_const_load_uses_clr
(operands)")
@ -773,6 +832,14 @@
btst 0,d0
cmp %1,%0"
[(set_attr "cc" "compare,compare")])
(define_insn "cmpsf"
[(set (cc0)
(compare (match_operand:SF 0 "register_operand" "f,f")
(match_operand:SF 1 "nonmemory_operand" "f,F")))]
"TARGET_AM33_2"
"fcmp %1,%0"
[(set_attr "cc" "compare,compare")])
;; ----------------------------------------------------------------------
;; ADD INSTRUCTIONS
@ -1551,6 +1618,8 @@
""
"*
{
if (cc_status.mdep.fpCC)
return \"fb%b1 %0\";
if ((cc_status.flags & CC_OVERFLOW_UNUSABLE) != 0
&& (GET_CODE (operands[1]) == GT
|| GET_CODE (operands[1]) == GE
@ -1570,6 +1639,8 @@
""
"*
{
if (cc_status.mdep.fpCC)
return \"fb%B1 %0\";
if ((cc_status.flags & CC_OVERFLOW_UNUSABLE) != 0
&& (GET_CODE (operands[1]) == GT
|| GET_CODE (operands[1]) == GE
@ -1996,6 +2067,12 @@
rtx result;
rtx target;
if (TARGET_AM33_2)
{
emit_insn (gen_abssf2_am33_2 (operands[0], operands[1]));
DONE;
}
target = operand_subword_force (operands[0], 0, SFmode);
result = expand_binop (SImode, and_optab,
operand_subword_force (operands[1], 0, SFmode),
@ -2012,6 +2089,15 @@
}")
(define_insn "abssf2_am33_2"
[(set (match_operand:SF 0 "register_operand" "=f,f")
(abs:SF (match_operand:SF 1 "register_operand" "0,?f")))]
"TARGET_AM33_2"
"@
fabs %0
fabs %1, %0"
[(set_attr "cc" "none_0hit")])
(define_expand "negdf2"
[(set (match_operand:DF 0 "register_operand" "")
(neg:DF (match_operand:DF 1 "register_operand" "")))]
@ -2052,6 +2138,12 @@
rtx result;
rtx target;
if (TARGET_AM33_2)
{
emit_insn (gen_negsf2_am33_2 (operands[0], operands[1]));
DONE;
}
target = operand_subword_force (operands[0], 0, SFmode);
result = expand_binop (SImode, xor_optab,
operand_subword_force (operands[1], 0, SFmode),
@ -2068,6 +2160,114 @@
DONE;
}")
(define_insn "negsf2_am33_2"
[(set (match_operand:SF 0 "register_operand" "=f,f")
(neg:SF (match_operand:SF 1 "register_operand" "0,?f")))]
"TARGET_AM33_2"
"@
fneg %0
fneg %1, %0"
[(set_attr "cc" "none_0hit")])
(define_expand "sqrtsf2"
[(set (match_operand:SF 0 "register_operand" "")
(sqrt:SF (match_operand:SF 1 "register_operand" "")))]
"TARGET_AM33_2 && flag_unsafe_math_optimizations"
"
{
rtx scratch = gen_reg_rtx (SFmode);
emit_insn (gen_rsqrtsf2 (scratch, operands[1], CONST1_RTX (SFmode)));
emit_insn (gen_divsf3 (operands[0], force_reg (SFmode, CONST1_RTX (SFmode)),
scratch));
DONE;
}")
(define_insn "rsqrtsf2"
[(set (match_operand:SF 0 "register_operand" "=f,f")
(div:SF (match_operand:SF 2 "const_1f_operand" "F,F")
(sqrt:SF (match_operand:SF 1 "register_operand" "0,?f"))))]
"TARGET_AM33_2"
"@
frsqrt %0
frsqrt %1, %0"
[(set_attr "cc" "none_0hit")])
(define_insn "addsf3"
[(set (match_operand:SF 0 "register_operand" "=f,f")
(plus:SF (match_operand:SF 1 "register_operand" "%0,f")
(match_operand:SF 2 "general_operand" "f,?fF")))]
"TARGET_AM33_2"
"@
fadd %2, %0
fadd %2, %1, %0"
[(set_attr "cc" "none_0hit")])
(define_insn "subsf3"
[(set (match_operand:SF 0 "register_operand" "=f,f")
(minus:SF (match_operand:SF 1 "register_operand" "0,f")
(match_operand:SF 2 "general_operand" "f,?fF")))]
"TARGET_AM33_2"
"@
fsub %2, %0
fsub %2, %1, %0"
[(set_attr "cc" "none_0hit")])
(define_insn "mulsf3"
[(set (match_operand:SF 0 "register_operand" "=f,f")
(mult:SF (match_operand:SF 1 "register_operand" "%0,f")
(match_operand:SF 2 "general_operand" "f,?fF")))]
"TARGET_AM33_2"
"@
fmul %2, %0
fmul %2, %1, %0"
[(set_attr "cc" "none_0hit")])
(define_insn "divsf3"
[(set (match_operand:SF 0 "register_operand" "=f,f")
(div:SF (match_operand:SF 1 "register_operand" "0,f")
(match_operand:SF 2 "general_operand" "f,?fF")))]
"TARGET_AM33_2"
"@
fdiv %2, %0
fdiv %2, %1, %0"
[(set_attr "cc" "none_0hit")])
(define_insn "fmaddsf4"
[(set (match_operand:SF 0 "register_operand" "=A")
(plus:SF (mult:SF (match_operand:SF 1 "register_operand" "%f")
(match_operand:SF 2 "register_operand" "f"))
(match_operand:SF 3 "register_operand" "f")))]
"TARGET_AM33_2"
"fmadd %1, %2, %3, %0"
[(set_attr "cc" "none_0hit")])
(define_insn "fmsubsf4"
[(set (match_operand:SF 0 "register_operand" "=A")
(minus:SF (mult:SF (match_operand:SF 1 "register_operand" "%f")
(match_operand:SF 2 "register_operand" "f"))
(match_operand:SF 3 "register_operand" "f")))]
"TARGET_AM33_2"
"fmsub %1, %2, %3, %0"
[(set_attr "cc" "none_0hit")])
(define_insn "fnmaddsf4"
[(set (match_operand:SF 0 "register_operand" "=A")
(minus:SF (match_operand:SF 3 "register_operand" "f")
(mult:SF (match_operand:SF 1 "register_operand" "%f")
(match_operand:SF 2 "register_operand" "f"))))]
"TARGET_AM33_2"
"fnmadd %1, %2, %3, %0"
[(set_attr "cc" "none_0hit")])
(define_insn "fnmsubsf4"
[(set (match_operand:SF 0 "register_operand" "=A")
(minus:SF (neg:SF (mult:SF (match_operand:SF 1 "register_operand" "%f")
(match_operand:SF 2 "register_operand" "f")))
(match_operand:SF 3 "register_operand" "f")))]
"TARGET_AM33_2"
"fnmsub %1, %2, %3, %0"
[(set_attr "cc" "none_0hit")])
;; ----------------------------------------------------------------------
;; PROLOGUE/EPILOGUE

View File

@ -10,8 +10,8 @@ fp-bit.c: $(srcdir)/config/fp-bit.c
echo '#define FLOAT' > fp-bit.c
cat $(srcdir)/config/fp-bit.c >> fp-bit.c
MULTILIB_OPTIONS = mam33
MULTILIB_DIRNAMES = am33
MULTILIB_OPTIONS = mam33/mam33-2
MULTILIB_DIRNAMES = am33 am33-2
LIBGCC = stmp-multilib
INSTALL_LIBGCC = install-multilib

View File

@ -386,6 +386,7 @@ in the following sections.
@emph{MN10300 Options}
@gccoptlist{-mmult-bug -mno-mult-bug @gol
-mam33 -mno-am33 @gol
-mam33-2 -mno-am33-2 @gol
-mno-crt0 -mrelax}
@emph{M32R/D Options}