aboutsummaryrefslogtreecommitdiffstats
path: root/gcc-4.8/gcc/config/microblaze/microblaze.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc-4.8/gcc/config/microblaze/microblaze.c')
-rw-r--r--gcc-4.8/gcc/config/microblaze/microblaze.c146
1 files changed, 103 insertions, 43 deletions
diff --git a/gcc-4.8/gcc/config/microblaze/microblaze.c b/gcc-4.8/gcc/config/microblaze/microblaze.c
index c121c2bae..914246bd5 100644
--- a/gcc-4.8/gcc/config/microblaze/microblaze.c
+++ b/gcc-4.8/gcc/config/microblaze/microblaze.c
@@ -1609,21 +1609,28 @@ static int
microblaze_version_to_int (const char *version)
{
const char *p, *v;
- const char *tmpl = "vX.YY.Z";
+ const char *tmpl = "vXX.YY.Z";
int iver = 0;
p = version;
v = tmpl;
- while (*v)
+ while (*p)
{
if (*v == 'X')
{ /* Looking for major */
+ if (*p == '.')
+ {
+ *v++;
+ }
+ else
+ {
if (!(*p >= '0' && *p <= '9'))
return -1;
iver += (int) (*p - '0');
iver *= 10;
}
+ }
else if (*v == 'Y')
{ /* Looking for minor */
if (!(*p >= '0' && *p <= '9'))
@@ -3064,6 +3071,73 @@ expand_pic_symbol_ref (enum machine_mode mode ATTRIBUTE_UNUSED, rtx op)
return result;
}
+static void
+microblaze_asm_output_mi_thunk (FILE *file, tree thunk_fndecl ATTRIBUTE_UNUSED,
+ HOST_WIDE_INT delta, HOST_WIDE_INT vcall_offset,
+ tree function)
+{
+ rtx this_rtx, insn, funexp;
+
+ reload_completed = 1;
+ epilogue_completed = 1;
+
+ /* Mark the end of the (empty) prologue. */
+ emit_note (NOTE_INSN_PROLOGUE_END);
+
+ /* Find the "this" pointer. If the function returns a structure,
+ the structure return pointer is in MB_ABI_FIRST_ARG_REGNUM. */
+ if (aggregate_value_p (TREE_TYPE (TREE_TYPE (function)), function))
+ this_rtx = gen_rtx_REG (Pmode, (MB_ABI_FIRST_ARG_REGNUM + 1));
+ else
+ this_rtx = gen_rtx_REG (Pmode, MB_ABI_FIRST_ARG_REGNUM);
+
+ /* Apply the constant offset, if required. */
+ if (delta)
+ emit_insn (gen_addsi3 (this_rtx, this_rtx, GEN_INT (delta)));
+
+ /* Apply the offset from the vtable, if required. */
+ if (vcall_offset)
+ {
+ rtx vcall_offset_rtx = GEN_INT (vcall_offset);
+ rtx temp1 = gen_rtx_REG (Pmode, MB_ABI_TEMP1_REGNUM);
+
+ emit_move_insn (temp1, gen_rtx_MEM (Pmode, this_rtx));
+
+ rtx loc = gen_rtx_PLUS (Pmode, temp1, vcall_offset_rtx);
+ emit_move_insn (temp1, gen_rtx_MEM (Pmode, loc));
+
+ emit_insn (gen_addsi3 (this_rtx, this_rtx, temp1));
+ }
+
+ /* Generate a tail call to the target function. */
+ if (!TREE_USED (function))
+ {
+ assemble_external (function);
+ TREE_USED (function) = 1;
+ }
+
+ funexp = XEXP (DECL_RTL (function), 0);
+ rtx temp2 = gen_rtx_REG (Pmode, MB_ABI_TEMP2_REGNUM);
+
+ if (flag_pic)
+ emit_move_insn (temp2, expand_pic_symbol_ref (Pmode, funexp));
+ else
+ emit_move_insn (temp2, funexp);
+
+ emit_insn (gen_indirect_jump (temp2));
+
+ /* Run just enough of rest_of_compilation. This sequence was
+ "borrowed" from rs6000.c. */
+ insn = get_insns ();
+ shorten_branches (insn);
+ final_start_function (insn, file, 1);
+ final (insn, file, 1);
+ final_end_function ();
+
+ reload_completed = 0;
+ epilogue_completed = 0;
+}
+
bool
microblaze_expand_move (enum machine_mode mode, rtx operands[])
{
@@ -3234,65 +3308,45 @@ microblaze_trampoline_init (rtx m_tramp, tree fndecl, rtx chain_value)
emit_move_insn (mem, fnaddr);
}
-/* Emit instruction to perform compare.
- cmp is (compare_op op0 op1). */
-static rtx
-microblaze_emit_compare (enum machine_mode mode, rtx cmp, enum rtx_code *cmp_code)
+/* Generate conditional branch -- first, generate test condition,
+ second, generate correct branch instruction. */
+
+void
+microblaze_expand_conditional_branch (enum machine_mode mode, rtx operands[])
{
- rtx cmp_op0 = XEXP (cmp, 0);
- rtx cmp_op1 = XEXP (cmp, 1);
+ enum rtx_code code = GET_CODE (operands[0]);
+ rtx cmp_op0 = operands[1];
+ rtx cmp_op1 = operands[2];
+ rtx label1 = operands[3];
rtx comp_reg = gen_reg_rtx (SImode);
- enum rtx_code code = *cmp_code;
+ rtx condition;
gcc_assert ((GET_CODE (cmp_op0) == REG) || (GET_CODE (cmp_op0) == SUBREG));
/* If comparing against zero, just test source reg. */
if (cmp_op1 == const0_rtx)
- return cmp_op0;
+ {
+ comp_reg = cmp_op0;
+ condition = gen_rtx_fmt_ee (signed_condition (code), SImode, comp_reg, const0_rtx);
+ emit_jump_insn (gen_condjump (condition, label1));
+ }
- if (code == EQ || code == NE)
+ else if (code == EQ || code == NE)
{
/* Use xor for equal/not-equal comparison. */
emit_insn (gen_xorsi3 (comp_reg, cmp_op0, cmp_op1));
+ condition = gen_rtx_fmt_ee (signed_condition (code), SImode, comp_reg, const0_rtx);
+ emit_jump_insn (gen_condjump (condition, label1));
}
- else if (code == GT || code == GTU || code == LE || code == LEU)
- {
- /* MicroBlaze compare is not symmetrical. */
- /* Swap argument order. */
- cmp_op1 = force_reg (mode, cmp_op1);
- if (code == GT || code == LE)
- emit_insn (gen_signed_compare (comp_reg, cmp_op0, cmp_op1));
else
- emit_insn (gen_unsigned_compare (comp_reg, cmp_op0, cmp_op1));
- /* Translate test condition. */
- *cmp_code = swap_condition (code);
- }
- else /* if (code == GE || code == GEU || code == LT || code == LTU) */
{
+ /* Generate compare and branch in single instruction. */
cmp_op1 = force_reg (mode, cmp_op1);
- if (code == GE || code == LT)
- emit_insn (gen_signed_compare (comp_reg, cmp_op1, cmp_op0));
- else
- emit_insn (gen_unsigned_compare (comp_reg, cmp_op1, cmp_op0));
+ condition = gen_rtx_fmt_ee (code, mode, cmp_op0, cmp_op1);
+ emit_jump_insn (gen_branch_compare(condition, cmp_op0, cmp_op1, label1));
}
-
- return comp_reg;
}
-/* Generate conditional branch -- first, generate test condition,
- second, generate correct branch instruction. */
-
-void
-microblaze_expand_conditional_branch (enum machine_mode mode, rtx operands[])
-{
- enum rtx_code code = GET_CODE (operands[0]);
- rtx comp;
- rtx condition;
-
- comp = microblaze_emit_compare (mode, operands[0], &code);
- condition = gen_rtx_fmt_ee (signed_condition (code), SImode, comp, const0_rtx);
- emit_jump_insn (gen_condjump (condition, operands[3]));
-}
void
microblaze_expand_conditional_branch_sf (rtx operands[])
@@ -3501,6 +3555,12 @@ microblaze_legitimate_constant_p (enum machine_mode mode ATTRIBUTE_UNUSED, rtx x
#undef TARGET_SECONDARY_RELOAD
#define TARGET_SECONDARY_RELOAD microblaze_secondary_reload
+#undef TARGET_ASM_OUTPUT_MI_THUNK
+#define TARGET_ASM_OUTPUT_MI_THUNK microblaze_asm_output_mi_thunk
+
+#undef TARGET_ASM_CAN_OUTPUT_MI_THUNK
+#define TARGET_ASM_CAN_OUTPUT_MI_THUNK hook_bool_const_tree_hwi_hwi_const_tree_true
+
#undef TARGET_SCHED_ADJUST_COST
#define TARGET_SCHED_ADJUST_COST microblaze_adjust_cost