mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-03-24 16:30:53 +08:00
Add ms2 support
Add ms2 support * config/ms1/ms1.md (UNSPEC_BLOCKAGE, UNSPEC_EI, UNSPEC_DI): New constants. (call,load,store): New insn types. (mem_access, branch_access): Adjust reservation conditions. (define_delay): Adjust condition. (decrement_and_branch_until_zero): Allow for ms2. Set branch type. (*decrement_and_rbanch_until_zero_no_clobber): Allow for ms2. (*movqi_internal,*movsi_internal,*movsf_internal): Use load,store insn type. (call_internal, call_value_internal, return_internal, return_interrupt_internal, eh_return_internal, indirect_jump, tablejump): Set call insn type. (blockage, ei, di): Use appropriate unspec const. * config/ms1/ms1.c (ms1_flag_delayed_branch): New. (ms1_get_attr_type): Adjust to give load & store types. (ms1_final_prescan_insn): Adjust for new insn types. Don't look backwards past a barrier. (ms1_override_options): Accept ms2 arch. Copy and reset delayed branch scheduling. (struct branch_info, struct label_info): New. (ms1_labels): New. (ms1_add_branches, ms1_check_delay_slot, ms1_reorg_hazard): New. (ms1_machine_reorg): New. (TARGET_MACHINE_DEPENDENT_REORG): Override. * config/ms1/crtn.asm: Add nop for ms2 JAL hazard. * config/ms1/ms1.h (processor_type): Add PROCESSOR_MS2. (ASM_SPEC, LIB_SPEC, STARTFILE_SPEC, ENDFILE_SPEC): Add ms2. (TARGET_MS2): New. From-SVN: r106680
This commit is contained in:
parent
456b8ce5db
commit
1508cc4663
@ -1,3 +1,36 @@
|
||||
2005-11-09 Nathan Sidwell <nathan@codesourcery.com>
|
||||
|
||||
Add ms2 support
|
||||
* config/ms1/ms1.md (UNSPEC_BLOCKAGE, UNSPEC_EI, UNSPEC_DI): New
|
||||
constants.
|
||||
(call,load,store): New insn types.
|
||||
(mem_access, branch_access): Adjust reservation conditions.
|
||||
(define_delay): Adjust condition.
|
||||
(decrement_and_branch_until_zero): Allow for ms2. Set branch
|
||||
type.
|
||||
(*decrement_and_rbanch_until_zero_no_clobber): Allow for ms2.
|
||||
(*movqi_internal,*movsi_internal,*movsf_internal): Use load,store
|
||||
insn type.
|
||||
(call_internal, call_value_internal, return_internal,
|
||||
return_interrupt_internal, eh_return_internal, indirect_jump,
|
||||
tablejump): Set call insn type.
|
||||
(blockage, ei, di): Use appropriate unspec const.
|
||||
* config/ms1/ms1.c (ms1_flag_delayed_branch): New.
|
||||
(ms1_get_attr_type): Adjust to give load & store types.
|
||||
(ms1_final_prescan_insn): Adjust for new insn types. Don't look
|
||||
backwards past a barrier.
|
||||
(ms1_override_options): Accept ms2 arch. Copy and reset delayed
|
||||
branch scheduling.
|
||||
(struct branch_info, struct label_info): New.
|
||||
(ms1_labels): New.
|
||||
(ms1_add_branches, ms1_check_delay_slot, ms1_reorg_hazard): New.
|
||||
(ms1_machine_reorg): New.
|
||||
(TARGET_MACHINE_DEPENDENT_REORG): Override.
|
||||
* config/ms1/crtn.asm: Add nop for ms2 JAL hazard.
|
||||
* config/ms1/ms1.h (processor_type): Add PROCESSOR_MS2.
|
||||
(ASM_SPEC, LIB_SPEC, STARTFILE_SPEC, ENDFILE_SPEC): Add ms2.
|
||||
(TARGET_MS2): New.
|
||||
|
||||
2005-11-09 Per Bothner <per@bothner.com>
|
||||
Uros Bizjak <uros@kss-loka.si>
|
||||
|
||||
|
@ -42,6 +42,7 @@
|
||||
.align 4
|
||||
ldw r14, sp, #0
|
||||
addi sp, sp, #4
|
||||
nop
|
||||
jal r0, r14
|
||||
or r0, r0, r0
|
||||
|
||||
@ -50,5 +51,6 @@
|
||||
|
||||
ldw r14, sp, #0
|
||||
addi sp, sp, #4
|
||||
nop
|
||||
jal r0, r14
|
||||
or r0, r0, r0
|
||||
|
@ -84,6 +84,8 @@ struct ms1_frame_info zero_frame_info;
|
||||
/* ms1 doesn't have unsigned compares need a library call for this. */
|
||||
struct rtx_def * ms1_ucmpsi3_libcall;
|
||||
|
||||
static int ms1_flag_delayed_branch;
|
||||
|
||||
|
||||
static rtx
|
||||
ms1_struct_value_rtx (tree fndecl ATTRIBUTE_UNUSED,
|
||||
@ -125,13 +127,6 @@ ms1_asm_output_opcode (FILE *f ATTRIBUTE_UNUSED, const char *ptr)
|
||||
return ptr;
|
||||
}
|
||||
|
||||
/* Return TRUE if INSN is a memory load. */
|
||||
static bool
|
||||
ms1_memory_load (rtx insn)
|
||||
{
|
||||
return ((GET_CODE (insn) == SET) && (GET_CODE (XEXP (insn,1)) == MEM));
|
||||
}
|
||||
|
||||
/* Given an insn, return whether it's a memory operation or a branch
|
||||
operation, otherwise return TYPE_ARITH. */
|
||||
static enum attr_type
|
||||
@ -139,18 +134,24 @@ ms1_get_attr_type (rtx complete_insn)
|
||||
{
|
||||
rtx insn = PATTERN (complete_insn);
|
||||
|
||||
if ((GET_CODE (insn) == SET)
|
||||
&& ((GET_CODE (XEXP (insn, 0)) == MEM)
|
||||
|| (GET_CODE (XEXP (insn, 1)) == MEM)))
|
||||
return TYPE_MEM;
|
||||
|
||||
else if (((GET_CODE (insn) == SET) && (XEXP (insn, 0) == pc_rtx))
|
||||
|| (GET_CODE (complete_insn) == JUMP_INSN)
|
||||
|| (GET_CODE (complete_insn) == CALL_INSN))
|
||||
if (JUMP_P (complete_insn))
|
||||
return TYPE_BRANCH;
|
||||
if (CALL_P (complete_insn))
|
||||
return TYPE_BRANCH;
|
||||
|
||||
else
|
||||
if (GET_CODE (insn) != SET)
|
||||
return TYPE_ARITH;
|
||||
|
||||
if (SET_DEST (insn) == pc_rtx)
|
||||
return TYPE_BRANCH;
|
||||
|
||||
if (GET_CODE (SET_DEST (insn)) == MEM)
|
||||
return TYPE_STORE;
|
||||
|
||||
if (GET_CODE (SET_SRC (insn)) == MEM)
|
||||
return TYPE_LOAD;
|
||||
|
||||
return TYPE_ARITH;
|
||||
}
|
||||
|
||||
/* A helper routine for insn_dependent_p called through note_stores. */
|
||||
@ -212,35 +213,48 @@ ms1_final_prescan_insn (rtx insn,
|
||||
int noperands ATTRIBUTE_UNUSED)
|
||||
{
|
||||
rtx prev_i;
|
||||
enum attr_type prev_attr;
|
||||
|
||||
ms1_nops_required = 0;
|
||||
ms1_nop_reasons = "";
|
||||
|
||||
/* ms2 constraints are dealt with in reorg. */
|
||||
if (ms1_cpu == PROCESSOR_MS2)
|
||||
return;
|
||||
|
||||
/* Only worry about real instructions. */
|
||||
if (! INSN_P (insn))
|
||||
return;
|
||||
|
||||
/* Find the previous real instructions. */
|
||||
prev_i = PREV_INSN (insn);
|
||||
while (prev_i != NULL
|
||||
for (prev_i = PREV_INSN (insn);
|
||||
prev_i != NULL
|
||||
&& (! INSN_P (prev_i)
|
||||
|| GET_CODE (PATTERN (prev_i)) == USE
|
||||
|| GET_CODE (PATTERN (prev_i)) == CLOBBER))
|
||||
prev_i = PREV_INSN (prev_i);
|
||||
|
||||
|| GET_CODE (PATTERN (prev_i)) == CLOBBER);
|
||||
prev_i = PREV_INSN (prev_i))
|
||||
{
|
||||
/* If we meet a barrier, there is no flow through here. */
|
||||
if (BARRIER_P (prev_i))
|
||||
return;
|
||||
}
|
||||
|
||||
/* If there isn't one then there is nothing that we need do. */
|
||||
if (prev_i == NULL || ! INSN_P (prev_i))
|
||||
return;
|
||||
|
||||
prev_attr = ms1_get_attr_type (prev_i);
|
||||
|
||||
/* Delayed branch slots already taken care of by delay branch scheduling. */
|
||||
if (ms1_get_attr_type (prev_i) == TYPE_BRANCH)
|
||||
if (prev_attr == TYPE_BRANCH)
|
||||
return;
|
||||
|
||||
switch (ms1_get_attr_type (insn))
|
||||
{
|
||||
case TYPE_MEM:
|
||||
case TYPE_LOAD:
|
||||
case TYPE_STORE:
|
||||
/* Avoid consecutive memory operation. */
|
||||
if (ms1_get_attr_type (prev_i) == TYPE_MEM
|
||||
if ((prev_attr == TYPE_LOAD || prev_attr == TYPE_STORE)
|
||||
&& ms1_cpu == PROCESSOR_MS1_64_001)
|
||||
{
|
||||
ms1_nops_required = 1;
|
||||
@ -252,7 +266,7 @@ ms1_final_prescan_insn (rtx insn,
|
||||
case TYPE_COMPLEX:
|
||||
/* One cycle of delay is required between load
|
||||
and the dependent arithmetic instruction. */
|
||||
if (ms1_memory_load (PATTERN (prev_i))
|
||||
if (prev_attr == TYPE_LOAD
|
||||
&& insn_true_dependent_p (prev_i, insn))
|
||||
{
|
||||
ms1_nops_required = 1;
|
||||
@ -263,7 +277,7 @@ ms1_final_prescan_insn (rtx insn,
|
||||
case TYPE_BRANCH:
|
||||
if (insn_dependent_p (prev_i, insn))
|
||||
{
|
||||
if (ms1_get_attr_type (prev_i) == TYPE_ARITH
|
||||
if (prev_attr == TYPE_ARITH
|
||||
&& ms1_cpu == PROCESSOR_MS1_64_001)
|
||||
{
|
||||
/* One cycle of delay between arith
|
||||
@ -271,7 +285,7 @@ ms1_final_prescan_insn (rtx insn,
|
||||
ms1_nops_required = 1;
|
||||
ms1_nop_reasons = "arith->branch dependency delay";
|
||||
}
|
||||
else if (ms1_memory_load (PATTERN (prev_i)))
|
||||
else if (prev_attr == TYPE_LOAD)
|
||||
{
|
||||
/* Two cycles of delay are required
|
||||
between load and dependent branch. */
|
||||
@ -790,10 +804,9 @@ ms1_override_options (void)
|
||||
else if (!strcasecmp (ms1_cpu_string, "MS1-16-002"))
|
||||
ms1_cpu = PROCESSOR_MS1_16_002;
|
||||
else if (!strcasecmp (ms1_cpu_string, "MS1-16-003"))
|
||||
{
|
||||
ms1_cpu = PROCESSOR_MS1_16_003;
|
||||
target_flags |= MASK_MUL;
|
||||
}
|
||||
ms1_cpu = PROCESSOR_MS1_16_003;
|
||||
else if (!strcasecmp (ms1_cpu_string, "MS2"))
|
||||
ms1_cpu = PROCESSOR_MS2;
|
||||
else
|
||||
error ("bad value (%s) for -march= switch", ms1_cpu_string);
|
||||
}
|
||||
@ -806,6 +819,10 @@ ms1_override_options (void)
|
||||
flag_gcse = 0;
|
||||
}
|
||||
|
||||
/* We do delayed branch filling in machine dependent reorg */
|
||||
ms1_flag_delayed_branch = flag_delayed_branch;
|
||||
flag_delayed_branch = 0;
|
||||
|
||||
init_machine_status = ms1_init_machine_status;
|
||||
}
|
||||
|
||||
@ -1631,6 +1648,315 @@ ms1_pass_in_stack (enum machine_mode mode ATTRIBUTE_UNUSED, tree type)
|
||||
|| TREE_ADDRESSABLE (type))));
|
||||
}
|
||||
|
||||
|
||||
/* Structures to hold branch information during reorg. */
|
||||
typedef struct branch_info
|
||||
{
|
||||
rtx insn; /* The branch insn. */
|
||||
|
||||
struct branch_info *next;
|
||||
} branch_info;
|
||||
|
||||
typedef struct label_info
|
||||
{
|
||||
rtx label; /* The label. */
|
||||
branch_info *branches; /* branches to this label. */
|
||||
struct label_info *next;
|
||||
} label_info;
|
||||
|
||||
/* Chain of labels found in current function, used during reorg. */
|
||||
static label_info *ms1_labels;
|
||||
|
||||
/* If *X is a label, add INSN to the list of branches for that
|
||||
label. */
|
||||
|
||||
static int
|
||||
ms1_add_branches (rtx *x, void *insn)
|
||||
{
|
||||
if (GET_CODE (*x) == LABEL_REF)
|
||||
{
|
||||
branch_info *branch = xmalloc (sizeof (*branch));
|
||||
rtx label = XEXP (*x, 0);
|
||||
label_info *info;
|
||||
|
||||
for (info = ms1_labels; info; info = info->next)
|
||||
if (info->label == label)
|
||||
break;
|
||||
|
||||
if (!info)
|
||||
{
|
||||
info = xmalloc (sizeof (*info));
|
||||
info->next = ms1_labels;
|
||||
ms1_labels = info;
|
||||
|
||||
info->label = label;
|
||||
info->branches = NULL;
|
||||
}
|
||||
|
||||
branch->next = info->branches;
|
||||
info->branches = branch;
|
||||
branch->insn = insn;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* If BRANCH has a filled delay slot, check if INSN is dependent upon
|
||||
it. If so, undo the delay slot fill. Returns the next insn, if
|
||||
we patch out the branch. Returns the branch insn, if we cannot
|
||||
patch out the branch (due to anti-dependency in the delay slot).
|
||||
In that case, the caller must insert nops at the branch target. */
|
||||
|
||||
static rtx
|
||||
ms1_check_delay_slot (rtx branch, rtx insn)
|
||||
{
|
||||
rtx slot;
|
||||
rtx tmp;
|
||||
rtx p;
|
||||
rtx jmp;
|
||||
|
||||
gcc_assert (GET_CODE (PATTERN (branch)) == SEQUENCE);
|
||||
if (INSN_DELETED_P (branch))
|
||||
return NULL_RTX;
|
||||
slot = XVECEXP (PATTERN (branch), 0, 1);
|
||||
|
||||
tmp = PATTERN (insn);
|
||||
note_stores (PATTERN (slot), insn_dependent_p_1, &tmp);
|
||||
if (tmp)
|
||||
/* Not dependent. */
|
||||
return NULL_RTX;
|
||||
|
||||
/* Undo the delay slot. */
|
||||
jmp = XVECEXP (PATTERN (branch), 0, 0);
|
||||
|
||||
tmp = PATTERN (jmp);
|
||||
note_stores (PATTERN (slot), insn_dependent_p_1, &tmp);
|
||||
if (!tmp)
|
||||
/* Anti dependent. */
|
||||
return branch;
|
||||
|
||||
p = PREV_INSN (branch);
|
||||
NEXT_INSN (p) = slot;
|
||||
PREV_INSN (slot) = p;
|
||||
NEXT_INSN (slot) = jmp;
|
||||
PREV_INSN (jmp) = slot;
|
||||
NEXT_INSN (jmp) = branch;
|
||||
PREV_INSN (branch) = jmp;
|
||||
XVECEXP (PATTERN (branch), 0, 0) = NULL_RTX;
|
||||
XVECEXP (PATTERN (branch), 0, 1) = NULL_RTX;
|
||||
delete_insn (branch);
|
||||
return jmp;
|
||||
}
|
||||
|
||||
/* Insert nops to satisfy pipeline constraints. We only deal with ms2
|
||||
constraints here. Earlier CPUs are dealt with by inserting nops with
|
||||
final_prescan (but that can lead to inferior code, and is
|
||||
impractical with ms2's JAL hazard).
|
||||
|
||||
ms2 dynamic constraints
|
||||
1) a load and a following use must be separated by one insn
|
||||
2) an insn and a following dependent call must be separated by two insns
|
||||
|
||||
only arith insns are placed in delay slots so #1 cannot happen with
|
||||
a load in a delay slot. #2 can happen with an arith insn in the
|
||||
delay slot. */
|
||||
|
||||
static void
|
||||
ms1_reorg_hazard (void)
|
||||
{
|
||||
rtx insn, next;
|
||||
|
||||
/* Find all the branches */
|
||||
for (insn = get_insns ();
|
||||
insn;
|
||||
insn = NEXT_INSN (insn))
|
||||
{
|
||||
rtx jmp;
|
||||
|
||||
if (!INSN_P (insn))
|
||||
continue;
|
||||
|
||||
jmp = PATTERN (insn);
|
||||
|
||||
if (GET_CODE (jmp) != SEQUENCE)
|
||||
/* If it's not got a filled delay slot, then it can't
|
||||
conflict. */
|
||||
continue;
|
||||
|
||||
jmp = XVECEXP (jmp, 0, 0);
|
||||
|
||||
if (recog_memoized (jmp) == CODE_FOR_tablejump)
|
||||
for (jmp = XEXP (XEXP (XVECEXP (PATTERN (jmp), 0, 1), 0), 0);
|
||||
!JUMP_TABLE_DATA_P (jmp);
|
||||
jmp = NEXT_INSN (jmp))
|
||||
continue;
|
||||
|
||||
for_each_rtx (&PATTERN (jmp), ms1_add_branches, insn);
|
||||
}
|
||||
|
||||
/* Now scan for dependencies. */
|
||||
for (insn = get_insns ();
|
||||
insn && !INSN_P (insn);
|
||||
insn = NEXT_INSN (insn))
|
||||
continue;
|
||||
|
||||
for (;
|
||||
insn;
|
||||
insn = next)
|
||||
{
|
||||
rtx jmp, tmp;
|
||||
enum attr_type attr;
|
||||
|
||||
gcc_assert (INSN_P (insn) && !INSN_DELETED_P (insn));
|
||||
for (next = NEXT_INSN (insn);
|
||||
next && !INSN_P (next);
|
||||
next = NEXT_INSN (next))
|
||||
continue;
|
||||
|
||||
jmp = insn;
|
||||
if (GET_CODE (PATTERN (insn)) == SEQUENCE)
|
||||
jmp = XVECEXP (PATTERN (insn), 0, 0);
|
||||
|
||||
attr = recog_memoized (jmp) >= 0 ? get_attr_type (jmp) : TYPE_UNKNOWN;
|
||||
|
||||
if (next && attr == TYPE_LOAD)
|
||||
{
|
||||
/* A load. See if NEXT is dependent, and if so insert a
|
||||
nop. */
|
||||
|
||||
tmp = PATTERN (next);
|
||||
if (GET_CODE (tmp) == SEQUENCE)
|
||||
tmp = PATTERN (XVECEXP (tmp, 0, 0));
|
||||
note_stores (PATTERN (insn), insn_dependent_p_1, &tmp);
|
||||
if (!tmp)
|
||||
emit_insn_after (gen_nop (), insn);
|
||||
}
|
||||
|
||||
if (attr == TYPE_CALL)
|
||||
{
|
||||
/* A call. Make sure we're not dependent on either of the
|
||||
previous two dynamic instructions. */
|
||||
int nops = 0;
|
||||
int count;
|
||||
rtx prev = insn;
|
||||
rtx rescan = NULL_RTX;
|
||||
|
||||
for (count = 2; count && !nops;)
|
||||
{
|
||||
int type;
|
||||
|
||||
prev = PREV_INSN (prev);
|
||||
if (!prev)
|
||||
{
|
||||
/* If we reach the start of the function, we must
|
||||
presume the caller set the address in the delay
|
||||
slot of the call instruction. */
|
||||
nops = count;
|
||||
break;
|
||||
}
|
||||
|
||||
if (BARRIER_P (prev))
|
||||
break;
|
||||
if (LABEL_P (prev))
|
||||
{
|
||||
/* Look at branches to this label. */
|
||||
label_info *label;
|
||||
branch_info *branch;
|
||||
|
||||
for (label = ms1_labels;
|
||||
label;
|
||||
label = label->next)
|
||||
if (label->label == prev)
|
||||
{
|
||||
for (branch = label->branches;
|
||||
branch;
|
||||
branch = branch->next)
|
||||
{
|
||||
tmp = ms1_check_delay_slot (branch->insn, jmp);
|
||||
|
||||
if (tmp == branch->insn)
|
||||
{
|
||||
nops = count;
|
||||
break;
|
||||
}
|
||||
|
||||
if (tmp && branch->insn == next)
|
||||
rescan = tmp;
|
||||
}
|
||||
break;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (!INSN_P (prev))
|
||||
continue;
|
||||
|
||||
if (GET_CODE (PATTERN (prev)) == SEQUENCE)
|
||||
{
|
||||
/* Look at the delay slot. */
|
||||
tmp = ms1_check_delay_slot (prev, jmp);
|
||||
if (tmp == prev)
|
||||
nops = count;
|
||||
break;
|
||||
}
|
||||
|
||||
type = (INSN_CODE (prev) >= 0 ? get_attr_type (prev)
|
||||
: TYPE_COMPLEX);
|
||||
if (type == TYPE_CALL || type == TYPE_BRANCH)
|
||||
break;
|
||||
|
||||
if (type == TYPE_LOAD
|
||||
|| type == TYPE_ARITH
|
||||
|| type == TYPE_COMPLEX)
|
||||
{
|
||||
tmp = PATTERN (jmp);
|
||||
note_stores (PATTERN (prev), insn_dependent_p_1, &tmp);
|
||||
if (!tmp)
|
||||
{
|
||||
nops = count;
|
||||
break;
|
||||
}
|
||||
}
|
||||
count -= INSN_CODE (prev) >= 0;
|
||||
}
|
||||
|
||||
if (rescan)
|
||||
for (next = NEXT_INSN (rescan);
|
||||
next && !INSN_P (next);
|
||||
next = NEXT_INSN (next))
|
||||
continue;
|
||||
while (nops--)
|
||||
emit_insn_before (gen_nop (), insn);
|
||||
}
|
||||
}
|
||||
|
||||
/* Free the data structures. */
|
||||
while (ms1_labels)
|
||||
{
|
||||
label_info *label = ms1_labels;
|
||||
branch_info *branch, *next;
|
||||
|
||||
ms1_labels = label->next;
|
||||
for (branch = label->branches; branch; branch = next)
|
||||
{
|
||||
next = branch->next;
|
||||
free (branch);
|
||||
}
|
||||
free (label);
|
||||
}
|
||||
}
|
||||
|
||||
/* Fixup the looping instructions, do delayed branch scheduling, fixup
|
||||
scheduling hazards. */
|
||||
|
||||
static void
|
||||
ms1_machine_reorg (void)
|
||||
{
|
||||
if (ms1_flag_delayed_branch)
|
||||
dbr_schedule (get_insns (), dump_file);
|
||||
|
||||
if (ms1_cpu == PROCESSOR_MS2)
|
||||
ms1_reorg_hazard ();
|
||||
}
|
||||
|
||||
/* Initialize the GCC target structure. */
|
||||
const struct attribute_spec ms1_attribute_table[];
|
||||
|
||||
@ -1646,6 +1972,8 @@ const struct attribute_spec ms1_attribute_table[];
|
||||
#define TARGET_MUST_PASS_IN_STACK ms1_pass_in_stack
|
||||
#undef TARGET_ARG_PARTIAL_BYTES
|
||||
#define TARGET_ARG_PARTIAL_BYTES ms1_arg_partial_bytes
|
||||
#undef TARGET_MACHINE_DEPENDENT_REORG
|
||||
#define TARGET_MACHINE_DEPENDENT_REORG ms1_machine_reorg
|
||||
|
||||
struct gcc_target targetm = TARGET_INITIALIZER;
|
||||
|
||||
|
@ -25,7 +25,8 @@ enum processor_type
|
||||
{
|
||||
PROCESSOR_MS1_64_001,
|
||||
PROCESSOR_MS1_16_002,
|
||||
PROCESSOR_MS1_16_003
|
||||
PROCESSOR_MS1_16_003,
|
||||
PROCESSOR_MS2
|
||||
};
|
||||
|
||||
enum epilogue_type
|
||||
@ -40,7 +41,7 @@ extern enum processor_type ms1_cpu;
|
||||
/* A C string constant that tells the GCC driver program options to pass to
|
||||
the assembler. */
|
||||
#undef ASM_SPEC
|
||||
#define ASM_SPEC "%{march=ms1-16-002: -march=ms1-16-002} %{march=ms1-16-003: -march=ms1-16-003} %{!march=*: -march=ms1-16-002}"
|
||||
#define ASM_SPEC "%{march=ms1-16-002: -march=ms1-16-002} %{march=ms1-16-003: -march=ms1-16-003} %{march=ms2: -march=ms2} %{!march=*: -march=ms1-16-002}"
|
||||
|
||||
/* A string to pass to at the end of the command given to the linker. */
|
||||
#undef LIB_SPEC
|
||||
@ -51,7 +52,9 @@ march=MS1-64-001:-T 64-001.ld%s; \
|
||||
march=ms1-16-002:-T 16-002.ld%s; \
|
||||
march=MS1-16-002:-T 16-002.ld%s; \
|
||||
march=ms1-16-003:-T 16-003.ld%s; \
|
||||
march=MS1-16-003:-T 16-003.ld%s}"
|
||||
march=MS1-16-003:-T 16-003.ld%s; \
|
||||
march=ms2:-T ms2.ld%s; \
|
||||
march=MS2:-T ms2.ld%s}"
|
||||
|
||||
/* A string to pass at the very beginning of the command given to the
|
||||
linker. */
|
||||
@ -62,7 +65,9 @@ march=MS1-64-001:%{!mno-crt0:crt0-64-001.o%s} startup-64-001.o%s; \
|
||||
march=ms1-16-002:%{!mno-crt0:crt0-16-002.o%s} startup-16-002.o%s; \
|
||||
march=MS1-16-002:%{!mno-crt0:crt0-16-002.o%s} startup-16-002.o%s; \
|
||||
march=ms1-16-003:%{!mno-crt0:crt0-16-003.o%s} startup-16-003.o%s; \
|
||||
march=MS1-16-003:%{!mno-crt0:crt0-16-003.o%s} startup-16-003.o%s} \
|
||||
march=MS1-16-003:%{!mno-crt0:crt0-16-003.o%s} startup-16-003.o%s; \
|
||||
march=ms2:%{!mno-crt0:crt0-ms2.o%s} startup-ms2.o%s; \
|
||||
march=MS2:%{!mno-crt0:crt0-ms2.o%s} startup-ms2.o%s} \
|
||||
crti.o%s crtbegin.o%s"
|
||||
|
||||
/* A string to pass at the end of the command given to the linker. */
|
||||
@ -73,7 +78,9 @@ march=MS1-64-001:exit-64-001.o%s; \
|
||||
march=ms1-16-002:exit-16-002.o%s; \
|
||||
march=MS1-16-002:exit-16-002.o%s; \
|
||||
march=ms1-16-003:exit-16-003.o%s; \
|
||||
march=MS1-16-003:exit-16-003.o%s} \
|
||||
march=MS1-16-003:exit-16-003.o%s; \
|
||||
march=ms2:exit-ms2.o%s; \
|
||||
march=MS2:exit-ms2.o%s} \
|
||||
crtend.o%s crtn.o%s"
|
||||
|
||||
/* Run-time target specifications. */
|
||||
@ -89,6 +96,7 @@ march=MS1-16-003:exit-16-003.o%s} \
|
||||
#define TARGET_MS1_64_001 (ms1_cpu == PROCESSOR_MS1_64_001)
|
||||
#define TARGET_MS1_16_002 (ms1_cpu == PROCESSOR_MS1_16_002)
|
||||
#define TARGET_MS1_16_003 (ms1_cpu == PROCESSOR_MS1_16_003)
|
||||
#define TARGET_MS2 (ms1_cpu == PROCESSOR_MS2)
|
||||
|
||||
#define TARGET_VERSION fprintf (stderr, " (ms1)");
|
||||
|
||||
|
@ -19,8 +19,16 @@
|
||||
;; Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
;; 02110-1301, USA.
|
||||
|
||||
;; UNSPECs
|
||||
(define_constants
|
||||
[
|
||||
(UNSPEC_BLOCKAGE 0)
|
||||
(UNSPEC_EI 1)
|
||||
(UNSPEC_DI 2)
|
||||
])
|
||||
|
||||
;; Attributes
|
||||
(define_attr "type" "branch,mem,io,arith,complex,unknown"
|
||||
(define_attr "type" "branch,call,load,store,io,arith,complex,unknown"
|
||||
(const_string "unknown") )
|
||||
|
||||
;; If the attribute takes numeric values, no `enum' type will be defined and
|
||||
@ -36,7 +44,7 @@
|
||||
(define_cpu_unit "branch_unit" "other")
|
||||
|
||||
(define_insn_reservation "mem_access" 2
|
||||
(eq_attr "type" "mem")
|
||||
(ior (eq_attr "type" "load") (eq_attr "type" "store"))
|
||||
"decode_unit+memory_unit*2")
|
||||
|
||||
(define_insn_reservation "io_access" 2
|
||||
@ -44,7 +52,8 @@
|
||||
"decode_unit+memory_unit*2")
|
||||
|
||||
(define_insn_reservation "branch_access" 2
|
||||
(eq_attr "type" "branch")
|
||||
(ior (eq_attr "type" "branch")
|
||||
(eq_attr "type" "call"))
|
||||
"decode_unit+branch_unit*2")
|
||||
|
||||
(define_insn_reservation "arith_access" 1
|
||||
@ -64,7 +73,8 @@
|
||||
;; the destination of the branch. Thus, only type that will be acceptable
|
||||
;; (safe) is the arith type.
|
||||
|
||||
(define_delay (eq_attr "type" "branch")
|
||||
(define_delay (ior (eq_attr "type" "branch")
|
||||
(eq_attr "type" "call"))
|
||||
[(eq_attr "type" "arith") (nil) (nil)])
|
||||
|
||||
|
||||
@ -79,7 +89,7 @@
|
||||
(plus:SI (match_dup 0)
|
||||
(const_int -1)))
|
||||
(clobber (match_scratch:SI 2 "=X,r"))]
|
||||
"TARGET_MS1_16_003"
|
||||
"TARGET_MS1_16_003 || TARGET_MS2"
|
||||
"@
|
||||
dbnz\t%0, %l1%#
|
||||
#"
|
||||
@ -98,9 +108,10 @@
|
||||
(set (match_dup 0)
|
||||
(plus:SI (match_dup 0)
|
||||
(const_int -1)))]
|
||||
"TARGET_MS1_16_003"
|
||||
"TARGET_MS1_16_003 || TARGET_MS2"
|
||||
"dbnz\t%0, %l1%#"
|
||||
[(set_attr "length" "4")]
|
||||
[(set_attr "length" "4")
|
||||
(set_attr "type" "branch")]
|
||||
)
|
||||
|
||||
;; Split the above to handle the case where operand 0 is in memory
|
||||
@ -116,7 +127,7 @@
|
||||
(plus:SI (match_dup 0)
|
||||
(const_int -1)))
|
||||
(clobber (match_scratch:SI 2 ""))]
|
||||
"TARGET_MS1_16_003"
|
||||
"TARGET_MS1_16_003 || TARGET_MS2"
|
||||
[(set (match_dup 2) (match_dup 0))
|
||||
(set (match_dup 2) (plus:SI (match_dup 2) (const_int -1)))
|
||||
(set (match_dup 0) (match_dup 2))
|
||||
@ -143,7 +154,7 @@
|
||||
(label_ref (match_operand 2 "" ""))
|
||||
(pc)))
|
||||
]
|
||||
"TARGET_MS1_16_003"
|
||||
"TARGET_MS1_16_003 || TARGET_MS2"
|
||||
[(parallel [(set (pc)
|
||||
(if_then_else
|
||||
(ne (match_dup 0) (const_int 0))
|
||||
@ -308,7 +319,7 @@
|
||||
stb %1, %0
|
||||
addi %0, r0, %1"
|
||||
[(set_attr "length" "4,4,4,4")
|
||||
(set_attr "type" "arith,mem,mem,arith")])
|
||||
(set_attr "type" "arith,load,store,arith")])
|
||||
|
||||
(define_insn "*movqi_internal_nobyte"
|
||||
[(set (match_operand:QI 0 "register_operand" "=r,r")
|
||||
@ -566,7 +577,7 @@
|
||||
nori %0, r0, %N1
|
||||
ldui %0, %H1\;addui %0, %0, %L1"
|
||||
[(set_attr "length" "4,4,4,4,4,4,4,8")
|
||||
(set_attr "type" "arith,mem,mem,arith,arith,arith,arith,complex")]
|
||||
(set_attr "type" "arith,load,store,arith,arith,arith,arith,complex")]
|
||||
)
|
||||
|
||||
;; Floating Point Moves
|
||||
@ -641,7 +652,7 @@
|
||||
ldw %0, %1
|
||||
stw %1, %0"
|
||||
[(set_attr "length" "4,4,4")
|
||||
(set_attr "type" "arith,mem,mem")]
|
||||
(set_attr "type" "arith,load,store")]
|
||||
)
|
||||
|
||||
(define_expand "movdf"
|
||||
@ -1269,7 +1280,7 @@
|
||||
""
|
||||
"jal r14, %0%#"
|
||||
[(set_attr "length" "4")
|
||||
(set_attr "type" "branch")])
|
||||
(set_attr "type" "call")])
|
||||
|
||||
(define_expand "call_value"
|
||||
[(parallel [(set (match_operand 0 "register_operand" "")
|
||||
@ -1292,7 +1303,7 @@
|
||||
""
|
||||
"jal r14, %1%#"
|
||||
[(set_attr "length" "4")
|
||||
(set_attr "type" "branch")])
|
||||
(set_attr "type" "call")])
|
||||
|
||||
;; Subroutine return
|
||||
(define_insn "return_internal"
|
||||
@ -1302,7 +1313,7 @@
|
||||
""
|
||||
"jal r0, r14%#"
|
||||
[(set_attr "length" "4")
|
||||
(set_attr "type" "branch")])
|
||||
(set_attr "type" "call")])
|
||||
|
||||
;; Interrupt return
|
||||
(define_insn "return_interrupt_internal"
|
||||
@ -1312,7 +1323,7 @@
|
||||
""
|
||||
"reti r15%#"
|
||||
[(set_attr "length" "4")
|
||||
(set_attr "type" "branch")])
|
||||
(set_attr "type" "call")])
|
||||
|
||||
;; Subroutine return
|
||||
(define_insn "eh_return_internal"
|
||||
@ -1324,7 +1335,7 @@
|
||||
""
|
||||
"jal r0, r11%#"
|
||||
[(set_attr "length" "4")
|
||||
(set_attr "type" "branch")])
|
||||
(set_attr "type" "call")])
|
||||
|
||||
|
||||
;; Normal unconditional jump
|
||||
@ -1341,7 +1352,7 @@
|
||||
""
|
||||
"jal r0,%0%#"
|
||||
[(set_attr "length" "4")
|
||||
(set_attr "type" "branch")])
|
||||
(set_attr "type" "call")])
|
||||
|
||||
(define_insn "tablejump"
|
||||
[(set (pc) (match_operand:SI 0 "register_operand" "r"))
|
||||
@ -1349,7 +1360,7 @@
|
||||
""
|
||||
"jal r0, %0%#"
|
||||
[(set_attr "length" "4")
|
||||
(set_attr "type" "branch")])
|
||||
(set_attr "type" "call")])
|
||||
|
||||
|
||||
(define_expand "prologue"
|
||||
@ -1412,7 +1423,7 @@
|
||||
;; Pseudo instruction that prevents the scheduler from moving code above this
|
||||
;; point.
|
||||
(define_insn "blockage"
|
||||
[(unspec_volatile [(const_int 0)] 0)]
|
||||
[(unspec_volatile [(const_int 0)] UNSPEC_BLOCKAGE)]
|
||||
""
|
||||
""
|
||||
[(set_attr "length" "0")])
|
||||
@ -1442,14 +1453,14 @@
|
||||
|
||||
;; Enable interrupts template
|
||||
(define_insn "ei"
|
||||
[(unspec_volatile [(const_int 0)] 1)]
|
||||
[(unspec_volatile [(const_int 0)] UNSPEC_EI)]
|
||||
""
|
||||
"ei"
|
||||
[(set_attr "length" "4")])
|
||||
|
||||
;; Enable interrupts template
|
||||
(define_insn "di"
|
||||
[(unspec_volatile [(const_int 0)] 2)]
|
||||
[(unspec_volatile [(const_int 0)] UNSPEC_DI)]
|
||||
""
|
||||
"di"
|
||||
[(set_attr "length" "4")])
|
||||
|
Loading…
x
Reference in New Issue
Block a user