blob: e7872d54e820d586c7f4e100af3acba2ad2e7b6a [file] [log] [blame]
From 8660e76d664ee4b42a83a4c15344b072d3c879df Mon Sep 17 00:00:00 2001
From: Nagaraju Mekala <nmekala@xilix.com>
Date: Fri, 27 Jul 2018 15:23:41 +0530
Subject: [PATCH 35/58] Intial commit for 64bit-MB sources.
Need to cleanup the code later.
---
gcc/config/microblaze/constraints.md | 2 +-
gcc/config/microblaze/microblaze-c.c | 6 +
gcc/config/microblaze/microblaze.c | 218 ++++++---
gcc/config/microblaze/microblaze.h | 63 ++-
gcc/config/microblaze/microblaze.md | 606 ++++++++++++++++++------
gcc/config/microblaze/t-microblaze | 7 +-
libgcc/config/microblaze/crti.S | 4 +-
libgcc/config/microblaze/crtn.S | 4 +-
libgcc/config/microblaze/divdi3.S | 98 ++++
libgcc/config/microblaze/divdi3_table.c | 62 +++
libgcc/config/microblaze/moddi3.S | 97 ++++
libgcc/config/microblaze/muldi3.S | 73 +++
libgcc/config/microblaze/t-microblaze | 11 +-
libgcc/config/microblaze/udivdi3.S | 107 +++++
libgcc/config/microblaze/umoddi3.S | 110 +++++
15 files changed, 1232 insertions(+), 236 deletions(-)
create mode 100644 libgcc/config/microblaze/divdi3.S
create mode 100644 libgcc/config/microblaze/divdi3_table.c
create mode 100644 libgcc/config/microblaze/moddi3.S
create mode 100644 libgcc/config/microblaze/muldi3.S
create mode 100644 libgcc/config/microblaze/udivdi3.S
create mode 100644 libgcc/config/microblaze/umoddi3.S
diff --git a/gcc/config/microblaze/constraints.md b/gcc/config/microblaze/constraints.md
index f636b035280..c2b0a21c53b 100644
--- a/gcc/config/microblaze/constraints.md
+++ b/gcc/config/microblaze/constraints.md
@@ -55,7 +55,7 @@
(define_constraint "K"
"A constant in the range 0xffffff8000000000L to 0x0000007fffffffffL (inclusive)."
(and (match_code "const_int")
- (match_test "ival > (long)0xffffff8000000000L && ival < (long)0x0000007fffffffffL")))
+ (match_test "ival > (long)-549755813888 && ival < (long)549755813887")))
;; Define floating point constraints
diff --git a/gcc/config/microblaze/microblaze-c.c b/gcc/config/microblaze/microblaze-c.c
index d8c88e510e5..dbcd21fc6ee 100644
--- a/gcc/config/microblaze/microblaze-c.c
+++ b/gcc/config/microblaze/microblaze-c.c
@@ -100,4 +100,10 @@ microblaze_cpp_define (cpp_reader *pfile)
builtin_define ("HAVE_HW_FPU_SQRT");
builtin_define ("__HAVE_HW_FPU_SQRT__");
}
+ if (TARGET_MB_64)
+ {
+ builtin_define ("__arch64__");
+ builtin_define ("__microblaze64__");
+ builtin_define ("__MICROBLAZE64__");
+ }
}
diff --git a/gcc/config/microblaze/microblaze.c b/gcc/config/microblaze/microblaze.c
index 8a3ccae558a..3ecda553fe6 100644
--- a/gcc/config/microblaze/microblaze.c
+++ b/gcc/config/microblaze/microblaze.c
@@ -383,10 +383,10 @@ simple_memory_operand (rtx op, machine_mode mode ATTRIBUTE_UNUSED)
{
return 1;
}
- else if (GET_CODE (plus0) == REG && GET_CODE (plus1) == REG)
+ /*else if (GET_CODE (plus0) == REG && GET_CODE (plus1) == REG)
{
return 1;
- }
+ }*/
else
return 0;
@@ -434,7 +434,7 @@ double_memory_operand (rtx op, machine_mode mode)
return 1;
return memory_address_p ((GET_MODE_CLASS (mode) == MODE_INT
- ? E_SImode : E_SFmode),
+ ? Pmode : E_SFmode),
plus_constant (Pmode, addr, 4));
}
@@ -681,7 +681,7 @@ microblaze_legitimize_tls_address(rtx x, rtx reg)
/* Load the addend. */
addend = gen_rtx_UNSPEC (Pmode, gen_rtvec (2, x, GEN_INT (TLS_DTPREL)),
UNSPEC_TLS);
- addend = force_reg (SImode, gen_rtx_CONST (SImode, addend));
+ addend = force_reg (Pmode, gen_rtx_CONST (Pmode, addend));
dest = gen_rtx_PLUS (Pmode, dest, addend);
break;
@@ -699,7 +699,7 @@ microblaze_classify_unspec (struct microblaze_address_info *info, rtx x)
if (XINT (x, 1) == UNSPEC_GOTOFF)
{
- info->regA = gen_rtx_REG (SImode, PIC_OFFSET_TABLE_REGNUM);
+ info->regA = gen_rtx_REG (Pmode, PIC_OFFSET_TABLE_REGNUM);
info->type = ADDRESS_GOTOFF;
}
else if (XINT (x, 1) == UNSPEC_PLT)
@@ -1302,8 +1302,16 @@ microblaze_block_move_loop (rtx dest, rtx src, HOST_WIDE_INT length)
emit_move_insn (dest_reg, plus_constant (Pmode, dest_reg, MAX_MOVE_BYTES));
/* Emit the test & branch. */
- emit_insn (gen_cbranchsi4 (gen_rtx_NE (SImode, src_reg, final_src),
+
+ if (TARGET_MB_64) {
+ emit_insn (gen_cbranchdi4 (gen_rtx_NE (Pmode, src_reg, final_src),
+ src_reg, final_src, label));
+ }
+ else {
+ emit_insn (gen_cbranchsi4 (gen_rtx_NE (Pmode, src_reg, final_src),
src_reg, final_src, label));
+
+ }
/* Mop up any left-over bytes. */
if (leftover)
@@ -1633,14 +1641,20 @@ microblaze_function_arg_advance (cumulative_args_t cum_v,
break;
case E_DFmode:
- cum->arg_words += 2;
+ if (TARGET_MB_64)
+ cum->arg_words++;
+ else
+ cum->arg_words += 2;
if (!cum->gp_reg_found && cum->arg_number <= 2)
cum->fp_code += 2 << ((cum->arg_number - 1) * 2);
break;
case E_DImode:
cum->gp_reg_found = 1;
- cum->arg_words += 2;
+ if (TARGET_MB_64)
+ cum->arg_words++;
+ else
+ cum->arg_words += 2;
break;
case E_QImode:
@@ -2285,7 +2299,7 @@ compute_frame_size (HOST_WIDE_INT size)
if (regno != MB_ABI_SUB_RETURN_ADDR_REGNUM)
/* Don't account for link register. It is accounted specially below. */
- gp_reg_size += GET_MODE_SIZE (SImode);
+ gp_reg_size += GET_MODE_SIZE (Pmode);
mask |= (1L << (regno - GP_REG_FIRST));
}
@@ -2554,7 +2568,7 @@ print_operand (FILE * file, rtx op, int letter)
if ((letter == 'M' && !WORDS_BIG_ENDIAN)
|| (letter == 'L' && WORDS_BIG_ENDIAN) || letter == 'D')
- regnum++;
+ regnum++;
fprintf (file, "%s", reg_names[regnum]);
}
@@ -2580,6 +2594,7 @@ print_operand (FILE * file, rtx op, int letter)
else if (letter == 'h' || letter == 'j')
{
long val[2];
+ int val1[2];
long l[2];
if (code == CONST_DOUBLE)
{
@@ -2592,12 +2607,12 @@ print_operand (FILE * file, rtx op, int letter)
val[0] = l[WORDS_BIG_ENDIAN != 0];
}
}
- else if (code == CONST_INT)
+ else if (code == CONST_INT || code == CONST)// || code == SYMBOL_REF ||code == LABEL_REF)
{
- val[0] = (INTVAL (op) & 0xffffffff00000000LL) >> 32;
- val[1] = INTVAL (op) & 0x00000000ffffffffLL;
+ val1[0] = (INTVAL (op) & 0xffffffff00000000LL) >> 32;
+ val1[1] = INTVAL (op) & 0x00000000ffffffffLL;
}
- fprintf (file, "0x%8.8lx", (letter == 'h') ? val[0] : val[1]);
+ fprintf (file, "0x%8.8lx", (letter == 'h') ? val1[0] : val1[1]);
}
else if (code == CONST_DOUBLE)
{
@@ -2791,7 +2806,10 @@ microblaze_asm_constructor (rtx symbol ATTRIBUTE_UNUSED, int priority)
switch_to_section (get_section (section, 0, NULL));
assemble_align (POINTER_SIZE);
- fputs ("\t.word\t", asm_out_file);
+ if (TARGET_MB_64)
+ fputs ("\t.dword\t", asm_out_file);
+ else
+ fputs ("\t.word\t", asm_out_file);
output_addr_const (asm_out_file, symbol);
fputs ("\n", asm_out_file);
}
@@ -2814,7 +2832,10 @@ microblaze_asm_destructor (rtx symbol, int priority)
switch_to_section (get_section (section, 0, NULL));
assemble_align (POINTER_SIZE);
- fputs ("\t.word\t", asm_out_file);
+ if (TARGET_MB_64)
+ fputs ("\t.dword\t", asm_out_file);
+ else
+ fputs ("\t.word\t", asm_out_file);
output_addr_const (asm_out_file, symbol);
fputs ("\n", asm_out_file);
}
@@ -2880,7 +2901,7 @@ save_restore_insns (int prologue)
/* For interrupt_handlers, need to save/restore the MSR. */
if (microblaze_is_interrupt_variant ())
{
- isr_mem_rtx = gen_rtx_MEM (SImode,
+ isr_mem_rtx = gen_rtx_MEM (Pmode,
gen_rtx_PLUS (Pmode, base_reg_rtx,
GEN_INT (current_frame_info.
gp_offset -
@@ -2888,8 +2909,8 @@ save_restore_insns (int prologue)
/* Do not optimize in flow analysis. */
MEM_VOLATILE_P (isr_mem_rtx) = 1;
- isr_reg_rtx = gen_rtx_REG (SImode, MB_ABI_MSR_SAVE_REG);
- isr_msr_rtx = gen_rtx_REG (SImode, ST_REG);
+ isr_reg_rtx = gen_rtx_REG (Pmode, MB_ABI_MSR_SAVE_REG);
+ isr_msr_rtx = gen_rtx_REG (Pmode, ST_REG);
}
if (microblaze_is_interrupt_variant () && !prologue)
@@ -2897,8 +2918,8 @@ save_restore_insns (int prologue)
emit_move_insn (isr_reg_rtx, isr_mem_rtx);
emit_move_insn (isr_msr_rtx, isr_reg_rtx);
/* Do not optimize in flow analysis. */
- emit_insn (gen_rtx_USE (SImode, isr_reg_rtx));
- emit_insn (gen_rtx_USE (SImode, isr_msr_rtx));
+ emit_insn (gen_rtx_USE (Pmode, isr_reg_rtx));
+ emit_insn (gen_rtx_USE (Pmode, isr_msr_rtx));
}
for (regno = GP_REG_FIRST; regno <= GP_REG_LAST; regno++)
@@ -2909,9 +2930,9 @@ save_restore_insns (int prologue)
/* Don't handle here. Already handled as the first register. */
continue;
- reg_rtx = gen_rtx_REG (SImode, regno);
+ reg_rtx = gen_rtx_REG (Pmode, regno);
insn = gen_rtx_PLUS (Pmode, base_reg_rtx, GEN_INT (gp_offset));
- mem_rtx = gen_rtx_MEM (SImode, insn);
+ mem_rtx = gen_rtx_MEM (Pmode, insn);
if (microblaze_is_interrupt_variant () || save_volatiles)
/* Do not optimize in flow analysis. */
MEM_VOLATILE_P (mem_rtx) = 1;
@@ -2926,7 +2947,7 @@ save_restore_insns (int prologue)
insn = emit_move_insn (reg_rtx, mem_rtx);
}
- gp_offset += GET_MODE_SIZE (SImode);
+ gp_offset += GET_MODE_SIZE (Pmode);
}
}
@@ -2936,8 +2957,8 @@ save_restore_insns (int prologue)
emit_move_insn (isr_mem_rtx, isr_reg_rtx);
/* Do not optimize in flow analysis. */
- emit_insn (gen_rtx_USE (SImode, isr_reg_rtx));
- emit_insn (gen_rtx_USE (SImode, isr_msr_rtx));
+ emit_insn (gen_rtx_USE (Pmode, isr_reg_rtx));
+ emit_insn (gen_rtx_USE (Pmode, isr_msr_rtx));
}
/* Done saving and restoring */
@@ -3027,7 +3048,10 @@ microblaze_elf_asm_cdtor (rtx symbol, int priority, bool is_ctor)
switch_to_section (s);
assemble_align (POINTER_SIZE);
- fputs ("\t.word\t", asm_out_file);
+ if (TARGET_MB_64)
+ fputs ("\t.dword\t", asm_out_file);
+ else
+ fputs ("\t.word\t", asm_out_file);
output_addr_const (asm_out_file, symbol);
fputs ("\n", asm_out_file);
}
@@ -3171,10 +3195,10 @@ microblaze_expand_prologue (void)
{
if (offset != 0)
ptr = gen_rtx_PLUS (Pmode, stack_pointer_rtx, GEN_INT (offset));
- emit_move_insn (gen_rtx_MEM (SImode, ptr),
- gen_rtx_REG (SImode, regno));
+ emit_move_insn (gen_rtx_MEM (Pmode, ptr),
+ gen_rtx_REG (Pmode, regno));
- offset += GET_MODE_SIZE (SImode);
+ offset += GET_MODE_SIZE (Pmode);
}
}
@@ -3183,15 +3207,23 @@ microblaze_expand_prologue (void)
rtx fsiz_rtx = GEN_INT (fsiz);
rtx_insn *insn = NULL;
- insn = emit_insn (gen_subsi3 (stack_pointer_rtx, stack_pointer_rtx,
+ if (TARGET_MB_64)
+ {
+
+ insn = emit_insn (gen_subdi3 (stack_pointer_rtx, stack_pointer_rtx,
fsiz_rtx));
+ }
+ else {
+ insn = emit_insn (gen_subsi3 (stack_pointer_rtx, stack_pointer_rtx,
+ fsiz_rtx));
+ }
if (insn)
RTX_FRAME_RELATED_P (insn) = 1;
/* Handle SUB_RETURN_ADDR_REGNUM specially at first. */
if (!crtl->is_leaf || interrupt_handler)
{
- mem_rtx = gen_rtx_MEM (SImode,
+ mem_rtx = gen_rtx_MEM (Pmode,
gen_rtx_PLUS (Pmode, stack_pointer_rtx,
const0_rtx));
@@ -3199,7 +3231,7 @@ microblaze_expand_prologue (void)
/* Do not optimize in flow analysis. */
MEM_VOLATILE_P (mem_rtx) = 1;
- reg_rtx = gen_rtx_REG (SImode, MB_ABI_SUB_RETURN_ADDR_REGNUM);
+ reg_rtx = gen_rtx_REG (Pmode, MB_ABI_SUB_RETURN_ADDR_REGNUM);
insn = emit_move_insn (mem_rtx, reg_rtx);
RTX_FRAME_RELATED_P (insn) = 1;
}
@@ -3309,12 +3341,12 @@ microblaze_expand_epilogue (void)
if (!crtl->is_leaf || interrupt_handler)
{
mem_rtx =
- gen_rtx_MEM (SImode,
+ gen_rtx_MEM (Pmode,
gen_rtx_PLUS (Pmode, stack_pointer_rtx, const0_rtx));
if (interrupt_handler)
/* Do not optimize in flow analysis. */
MEM_VOLATILE_P (mem_rtx) = 1;
- reg_rtx = gen_rtx_REG (SImode, MB_ABI_SUB_RETURN_ADDR_REGNUM);
+ reg_rtx = gen_rtx_REG (Pmode, MB_ABI_SUB_RETURN_ADDR_REGNUM);
emit_move_insn (reg_rtx, mem_rtx);
}
@@ -3330,15 +3362,25 @@ microblaze_expand_epilogue (void)
/* _restore_ registers for epilogue. */
save_restore_insns (0);
emit_insn (gen_blockage ());
- emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx, fsiz_rtx));
+ if (TARGET_MB_64)
+ emit_insn (gen_adddi3 (stack_pointer_rtx, stack_pointer_rtx, fsiz_rtx));
+ else
+ emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx, fsiz_rtx));
}
if (crtl->calls_eh_return)
- emit_insn (gen_addsi3 (stack_pointer_rtx,
+ if (TARGET_MB_64) {
+ emit_insn (gen_adddi3 (stack_pointer_rtx,
stack_pointer_rtx,
- gen_raw_REG (SImode,
+ gen_raw_REG (Pmode,
MB_EH_STACKADJ_REGNUM)));
-
+ }
+ else {
+ emit_insn (gen_addsi3 (stack_pointer_rtx,
+ stack_pointer_rtx,
+ gen_raw_REG (Pmode,
+ MB_EH_STACKADJ_REGNUM)));
+ }
emit_jump_insn (gen_return_internal (gen_rtx_REG (Pmode, GP_REG_FIRST +
MB_ABI_SUB_RETURN_ADDR_REGNUM)));
}
@@ -3505,9 +3547,14 @@ microblaze_asm_output_mi_thunk (FILE *file, tree thunk_fndecl ATTRIBUTE_UNUSED,
else
this_rtx = gen_rtx_REG (Pmode, MB_ABI_FIRST_ARG_REGNUM);
- /* Apply the constant offset, if required. */
+ /* Apply the constant offset, if required. */
if (delta)
- emit_insn (gen_addsi3 (this_rtx, this_rtx, GEN_INT (delta)));
+ {
+ if (TARGET_MB_64)
+ emit_insn (gen_adddi3 (this_rtx, this_rtx, GEN_INT (delta)));
+ else
+ emit_insn (gen_addsi3 (this_rtx, this_rtx, GEN_INT (delta)));
+ }
/* Apply the offset from the vtable, if required. */
if (vcall_offset)
@@ -3520,7 +3567,10 @@ microblaze_asm_output_mi_thunk (FILE *file, tree thunk_fndecl ATTRIBUTE_UNUSED,
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));
+ if (TARGET_MB_64)
+ emit_insn (gen_adddi3 (this_rtx, this_rtx, temp1));
+ else
+ emit_insn (gen_addsi3 (this_rtx, this_rtx, temp1));
}
/* Generate a tail call to the target function. */
@@ -3696,7 +3746,7 @@ microblaze_eh_return (rtx op0)
/* Queue an .ident string in the queue of top-level asm statements.
If the string size is below the threshold, put it into .sdata2.
If the front-end is done, we must be being called from toplev.c.
- In that case, do nothing. */
+ In that case, do nothing. */
void
microblaze_asm_output_ident (const char *string)
{
@@ -3751,9 +3801,9 @@ microblaze_trampoline_init (rtx m_tramp, tree fndecl, rtx chain_value)
emit_block_move (m_tramp, assemble_trampoline_template (),
GEN_INT (6*UNITS_PER_WORD), BLOCK_OP_NORMAL);
- mem = adjust_address (m_tramp, SImode, 16);
+ mem = adjust_address (m_tramp, Pmode, 16);
emit_move_insn (mem, chain_value);
- mem = adjust_address (m_tramp, SImode, 20);
+ mem = adjust_address (m_tramp, Pmode, 20);
emit_move_insn (mem, fnaddr);
}
@@ -3777,7 +3827,7 @@ microblaze_expand_conditional_branch (machine_mode mode, rtx operands[])
{
comp_reg = cmp_op0;
condition = gen_rtx_fmt_ee (signed_condition (code), mode, comp_reg, const0_rtx);
- if (mode == SImode)
+ if (mode == Pmode)
emit_jump_insn (gen_condjump (condition, label1));
else
emit_jump_insn (gen_long_condjump (condition, label1));
@@ -3896,7 +3946,7 @@ microblaze_expand_conditional_branch_sf (rtx operands[])
rtx comp_reg = gen_reg_rtx (SImode);
emit_insn (gen_cstoresf4 (comp_reg, operands[0], cmp_op0, cmp_op1));
- condition = gen_rtx_NE (SImode, comp_reg, const0_rtx);
+ condition = gen_rtx_NE (Pmode, comp_reg, const0_rtx);
emit_jump_insn (gen_condjump (condition, operands[3]));
}
@@ -3906,10 +3956,10 @@ microblaze_expand_conditional_branch_df (rtx operands[])
rtx condition;
rtx cmp_op0 = XEXP (operands[0], 0);
rtx cmp_op1 = XEXP (operands[0], 1);
- rtx comp_reg = gen_reg_rtx (DImode);
+ rtx comp_reg = gen_reg_rtx (Pmode);
emit_insn (gen_cstoredf4 (comp_reg, operands[0], cmp_op0, cmp_op1));
- condition = gen_rtx_NE (DImode, comp_reg, const0_rtx);
+ condition = gen_rtx_NE (Pmode, comp_reg, const0_rtx);
emit_jump_insn (gen_long_condjump (condition, operands[3]));
}
@@ -3930,8 +3980,8 @@ microblaze_expand_divide (rtx operands[])
{
/* Table lookup software divides. Works for all (nr/dr) where (0 <= nr,dr <= 15). */
- rtx regt1 = gen_reg_rtx (SImode);
- rtx reg18 = gen_rtx_REG (SImode, R_TMP);
+ rtx regt1 = gen_reg_rtx (Pmode);
+ rtx reg18 = gen_rtx_REG (Pmode, R_TMP);
rtx regqi = gen_reg_rtx (QImode);
rtx_code_label *div_label = gen_label_rtx ();
rtx_code_label *div_end_label = gen_label_rtx ();
@@ -3939,17 +3989,31 @@ microblaze_expand_divide (rtx operands[])
rtx mem_rtx;
rtx ret;
rtx_insn *jump, *cjump, *insn;
-
- insn = emit_insn (gen_iorsi3 (regt1, operands[1], operands[2]));
- cjump = emit_jump_insn_after (gen_cbranchsi4 (
- gen_rtx_GTU (SImode, regt1, GEN_INT (15)),
+
+ if (TARGET_MB_64) {
+ insn = emit_insn (gen_iordi3 (regt1, operands[1], operands[2]));
+ cjump = emit_jump_insn_after (gen_cbranchdi4 (
+ gen_rtx_GTU (Pmode, regt1, GEN_INT (15)),
+ regt1, GEN_INT (15), div_label), insn);
+ }
+ else {
+ insn = emit_insn (gen_iorsi3 (regt1, operands[1], operands[2]));
+ cjump = emit_jump_insn_after (gen_cbranchsi4 (
+ gen_rtx_GTU (Pmode, regt1, GEN_INT (15)),
regt1, GEN_INT (15), div_label), insn);
+ }
LABEL_NUSES (div_label) = 1;
JUMP_LABEL (cjump) = div_label;
- emit_insn (gen_rtx_CLOBBER (SImode, reg18));
+ emit_insn (gen_rtx_CLOBBER (Pmode, reg18));
- emit_insn (gen_ashlsi3_bshift (regt1, operands[1], GEN_INT(4)));
- emit_insn (gen_addsi3 (regt1, regt1, operands[2]));
+ if (TARGET_MB_64) {
+ emit_insn (gen_ashldi3_long (regt1, operands[1], GEN_INT(4)));
+ emit_insn (gen_adddi3 (regt1, regt1, operands[2]));
+ }
+ else {
+ emit_insn (gen_ashlsi3_bshift (regt1, operands[1], GEN_INT(4)));
+ emit_insn (gen_addsi3 (regt1, regt1, operands[2]));
+ }
mem_rtx = gen_rtx_MEM (QImode,
gen_rtx_PLUS (QImode, regt1, div_table_rtx));
@@ -4096,7 +4160,7 @@ insert_wic_for_ilb_runout (rtx_insn *first)
{
insn =
emit_insn_before (gen_iprefetch
- (gen_int_mode (addr_offset, SImode)),
+ (gen_int_mode (addr_offset, Pmode)),
before_4);
recog_memoized (insn);
INSN_LOCATION (insn) = INSN_LOCATION (before_4);
@@ -4106,7 +4170,27 @@ insert_wic_for_ilb_runout (rtx_insn *first)
}
}
}
-
+
+/* Set the names for various arithmetic operations according to the
+ * MICROBLAZE ABI. */
+static void
+microblaze_init_libfuncs (void)
+{
+ set_optab_libfunc (smod_optab, SImode, "__modsi3");
+ set_optab_libfunc (sdiv_optab, SImode, "__divsi3");
+ set_optab_libfunc (smul_optab, SImode, "__mulsi3");
+ set_optab_libfunc (umod_optab, SImode, "__umodsi3");
+ set_optab_libfunc (udiv_optab, SImode, "__udivsi3");
+
+ if (TARGET_MB_64)
+ {
+ set_optab_libfunc (smod_optab, DImode, "__moddi3");
+ set_optab_libfunc (sdiv_optab, DImode, "__divdi3");
+ set_optab_libfunc (smul_optab, DImode, "__muldi3");
+ set_optab_libfunc (umod_optab, DImode, "__umoddi3");
+ set_optab_libfunc (udiv_optab, DImode, "__udivdi3");
+ }
+}
/* Insert instruction prefetch instruction at the fall
through path of the function call. */
@@ -4259,6 +4343,17 @@ microblaze_starting_frame_offset (void)
#undef TARGET_LRA_P
#define TARGET_LRA_P hook_bool_void_false
+#ifdef TARGET_MB_64
+#undef TARGET_ASM_ALIGNED_DI_OP
+#define TARGET_ASM_ALIGNED_DI_OP "\t.dword\t"
+
+#undef TARGET_ASM_ALIGNED_HI_OP
+#define TARGET_ASM_ALIGNED_HI_OP "\t.hword\t"
+
+#undef TARGET_ASM_ALIGNED_SI_OP
+#define TARGET_ASM_ALIGNED_SI_OP "\t.word\t"
+#endif
+
#undef TARGET_FRAME_POINTER_REQUIRED
#define TARGET_FRAME_POINTER_REQUIRED microblaze_frame_pointer_required
@@ -4268,6 +4363,9 @@ microblaze_starting_frame_offset (void)
#undef TARGET_TRAMPOLINE_INIT
#define TARGET_TRAMPOLINE_INIT microblaze_trampoline_init
+#undef TARGET_INIT_LIBFUNCS
+#define TARGET_INIT_LIBFUNCS microblaze_init_libfuncs
+
#undef TARGET_PROMOTE_FUNCTION_MODE
#define TARGET_PROMOTE_FUNCTION_MODE default_promote_function_mode_always_promote
diff --git a/gcc/config/microblaze/microblaze.h b/gcc/config/microblaze/microblaze.h
index 4931895e650..1f6e2059545 100644
--- a/gcc/config/microblaze/microblaze.h
+++ b/gcc/config/microblaze/microblaze.h
@@ -173,7 +173,6 @@ extern enum pipeline_type microblaze_pipe;
/* Generate DWARF exception handling info. */
#define DWARF2_UNWIND_INFO 1
-
/* Don't generate .loc operations. */
#define DWARF2_ASM_LINE_DEBUG_INFO 0
@@ -206,38 +205,51 @@ extern enum pipeline_type microblaze_pipe;
((flag_pic || GLOBAL) ? DW_EH_PE_aligned : DW_EH_PE_absptr)
/* Use DWARF 2 debugging information by default. */
-#define DWARF2_DEBUGGING_INFO
+#define DWARF2_DEBUGGING_INFO 1
#define PREFERRED_DEBUGGING_TYPE DWARF2_DEBUG
+#define DWARF2_ADDR_SIZE 4
/* Target machine storage layout */
#define BITS_BIG_ENDIAN 0
#define BYTES_BIG_ENDIAN (TARGET_LITTLE_ENDIAN == 0)
#define WORDS_BIG_ENDIAN (BYTES_BIG_ENDIAN)
-#define BITS_PER_WORD 32
-#define UNITS_PER_WORD 4
+//#define BITS_PER_WORD 64
+//Revisit
+#define MAX_BITS_PER_WORD 64
+#define UNITS_PER_WORD (TARGET_MB_64 ? 8 : 4)
+//#define MIN_UNITS_PER_WORD (TARGET_MB_64 ? 8 : 4)
+//#define UNITS_PER_WORD 4
#define MIN_UNITS_PER_WORD 4
#define INT_TYPE_SIZE 32
#define SHORT_TYPE_SIZE 16
-#define LONG_TYPE_SIZE 64
+#define LONG_TYPE_SIZE (TARGET_MB_64 ? 64 : 32)
#define LONG_LONG_TYPE_SIZE 64
#define FLOAT_TYPE_SIZE 32
#define DOUBLE_TYPE_SIZE 64
#define LONG_DOUBLE_TYPE_SIZE 64
-#define POINTER_SIZE 32
-#define PARM_BOUNDARY 32
-#define FUNCTION_BOUNDARY 32
-#define EMPTY_FIELD_BOUNDARY 32
+#define POINTER_SIZE (TARGET_MB_64 ? 64 : 32)
+//#define WIDEST_HARDWARE_FP_SIZE 64
+//#define POINTERS_EXTEND_UNSIGNED 1
+#define PARM_BOUNDARY (TARGET_MB_64 ? 64 : 32)
+#define FUNCTION_BOUNDARY (TARGET_MB_64 ? 64 : 32)
+#define EMPTY_FIELD_BOUNDARY (TARGET_MB_64 ? 64 : 32)
#define STRUCTURE_SIZE_BOUNDARY 8
-#define BIGGEST_ALIGNMENT 32
+#define BIGGEST_ALIGNMENT (TARGET_MB_64 ? 64 : 32)
#define STRICT_ALIGNMENT 1
#define PCC_BITFIELD_TYPE_MATTERS 1
+//#define MAX_FIXED_MODE_SIZE GET_MODE_BITSIZE (TARGET_MB_64 ? TImode : DImode)
#undef SIZE_TYPE
-#define SIZE_TYPE "unsigned int"
+#define SIZE_TYPE (TARGET_MB_64 ? "long unsigned int" : "unsigned int")
#undef PTRDIFF_TYPE
-#define PTRDIFF_TYPE "int"
+#define PTRDIFF_TYPE (TARGET_MB_64 ? "long int" : "int")
+
+/*#undef INTPTR_TYPE
+#define INTPTR_TYPE (TARGET_MB_64 ? "long int" : "int")*/
+#undef UINTPTR_TYPE
+#define UINTPTR_TYPE (TARGET_MB_64 ? "long unsigned int" : "unsigned int")
#define DATA_ALIGNMENT(TYPE, ALIGN) \
((((ALIGN) < BITS_PER_WORD) \
@@ -253,12 +265,12 @@ extern enum pipeline_type microblaze_pipe;
#define WORD_REGISTER_OPERATIONS 1
#define LOAD_EXTEND_OP(MODE) ZERO_EXTEND
-
+/*
#define PROMOTE_MODE(MODE, UNSIGNEDP, TYPE) \
if (GET_MODE_CLASS (MODE) == MODE_INT \
- && GET_MODE_SIZE (MODE) < 4) \
- (MODE) = SImode;
-
+ && GET_MODE_SIZE (MODE) < (TARGET_MB_64 ? 8 : 4)) \
+ (MODE) = TARGET_MB_64 ? DImode : SImode;
+*/
/* Standard register usage. */
/* On the MicroBlaze, we have 32 integer registers */
@@ -438,13 +450,16 @@ extern struct microblaze_frame_info current_frame_info;
#define FIRST_PARM_OFFSET(FNDECL) (UNITS_PER_WORD)
#define ARG_POINTER_CFA_OFFSET(FNDECL) 0
+#define DWARF_CIE_DATA_ALIGNMENT -1
#define REG_PARM_STACK_SPACE(FNDECL) microblaze_reg_parm_stack_space(FNDECL)
#define OUTGOING_REG_PARM_STACK_SPACE(FNTYPE) 1
-#define STACK_BOUNDARY 32
+#define STACK_BOUNDARY (TARGET_MB_64 ? 64 : 32)
+#define PREFERRED_STACK_BOUNDARY (TARGET_MB_64 ? 64 : 32)
+
#define NUM_OF_ARGS 6
#define GP_RETURN (GP_REG_FIRST + MB_ABI_INT_RETURN_VAL_REGNUM)
@@ -455,12 +470,15 @@ extern struct microblaze_frame_info current_frame_info;
#define MAX_ARGS_IN_REGISTERS MB_ABI_MAX_ARG_REGS
#define LIBCALL_VALUE(MODE) \
+ gen_rtx_REG (MODE,GP_RETURN)
+
+/*#define LIBCALL_VALUE(MODE) \
gen_rtx_REG ( \
((GET_MODE_CLASS (MODE) != MODE_INT \
|| GET_MODE_SIZE (MODE) >= 4) \
? (MODE) \
: SImode), GP_RETURN)
-
+*/
/* 1 if N is a possible register number for a function value.
On the MicroBlaze, R2 R3 are the only register thus used.
Currently, R2 are only implemented here (C has no complex type) */
@@ -500,7 +518,7 @@ typedef struct microblaze_args
/* 4 insns + 2 words of data. */
#define TRAMPOLINE_SIZE (6 * 4)
-#define TRAMPOLINE_ALIGNMENT 32
+#define TRAMPOLINE_ALIGNMENT 64
#define REGNO_OK_FOR_BASE_P(regno) microblaze_regno_ok_for_base_p ((regno), 1)
@@ -529,13 +547,13 @@ typedef struct microblaze_args
addresses which require two reload registers. */
#define LEGITIMATE_PIC_OPERAND_P(X) microblaze_legitimate_pic_operand (X)
-#define CASE_VECTOR_MODE (SImode)
+#define CASE_VECTOR_MODE (TARGET_MB_64? DImode:SImode)
#ifndef DEFAULT_SIGNED_CHAR
#define DEFAULT_SIGNED_CHAR 1
#endif
-#define MOVE_MAX 4
+#define MOVE_MAX (TARGET_MB_64 ? 8 : 4)
#define MAX_MOVE_MAX 8
#define SLOW_BYTE_ACCESS 1
@@ -545,7 +563,7 @@ typedef struct microblaze_args
#define SHIFT_COUNT_TRUNCATED 1
-#define Pmode SImode
+#define Pmode (TARGET_MB_64? DImode:SImode)
#define FUNCTION_MODE SImode
@@ -707,6 +725,7 @@ do { \
#undef TARGET_ASM_OUTPUT_IDENT
#define TARGET_ASM_OUTPUT_IDENT microblaze_asm_output_ident
+//#define TARGET_ASM_OUTPUT_IDENT default_asm_output_ident_directive
/* Default to -G 8 */
#ifndef MICROBLAZE_DEFAULT_GVALUE
diff --git a/gcc/config/microblaze/microblaze.md b/gcc/config/microblaze/microblaze.md
index bcf2b9244f8..bef750c026a 100644
--- a/gcc/config/microblaze/microblaze.md
+++ b/gcc/config/microblaze/microblaze.md
@@ -26,6 +26,7 @@
;; Constants
;;----------------------------------------------------
(define_constants [
+ (R_Z 0) ;; For reg r0
(R_SP 1) ;; Stack pointer reg
(R_SR 15) ;; Sub-routine return addr reg
(R_IR 14) ;; Interrupt return addr reg
@@ -541,6 +542,7 @@
;; Add 2 SImode integers [ src1 = reg ; src2 = arith ; dest = reg ]
;; Leave carry as is
+
(define_insn "addsi3"
[(set (match_operand:SI 0 "register_operand" "=d,d,d")
(plus:SI (match_operand:SI 1 "reg_or_0_operand" "%dJ,dJ,dJ")
@@ -562,23 +564,38 @@
;; Adding 2 DI operands in register or reg/imm
-(define_insn "adddi3_long"
+(define_expand "adddi3"
+ [(set (match_operand:DI 0 "register_operand" "")
+ (plus:DI (match_operand:DI 1 "register_operand" "")
+ (match_operand:DI 2 "arith_plus_operand" "")))]
+""
+{
+ if (TARGET_MB_64)
+ {
+ if (GET_CODE (operands[2]) == CONST_INT &&
+ INTVAL(operands[2]) < (long)-549755813888 &&
+ INTVAL(operands[2]) > (long)549755813887)
+ FAIL;
+ }
+})
+
+(define_insn "*adddi3_long"
[(set (match_operand:DI 0 "register_operand" "=d,d")
- (plus:DI (match_operand:DI 1 "reg_or_0_operand" "%dJ,dJ")
+ (plus:DI (match_operand:DI 1 "register_operand" "%d,d")
(match_operand:DI 2 "arith_plus_operand" "d,K")))]
"TARGET_MB_64"
"@
- addlk\t%0,%z1,%2
- addlik\t%0,%z1,%2"
- [(set_attr "type" "arith,arith")
- (set_attr "mode" "DI,DI")
+ addlk\t%0,%1,%2
+ addlik\t%0,%1,%2 #N10"
+ [(set_attr "type" "darith,no_delay_arith")
+ (set_attr "mode" "DI")
(set_attr "length" "4,4")])
-(define_insn "adddi3"
+(define_insn "*adddi3_all"
[(set (match_operand:DI 0 "register_operand" "=d,d")
(plus:DI (match_operand:DI 1 "register_operand" "%d,d")
(match_operand:DI 2 "arith_operand" "d,i")))]
- ""
+ "!TARGET_MB_64"
"@
add\t%L0,%L1,%L2\;addc\t%M0,%M1,%M2
addi\t%L0,%L1,%j2\;addic\t%M0,%M1,%h2"
@@ -605,7 +622,7 @@
(define_insn "iprefetch"
[(unspec [(match_operand:SI 0 "const_int_operand" "n")] UNSPEC_IPREFETCH)
(clobber (mem:BLK (scratch)))]
- "TARGET_PREFETCH"
+ "TARGET_PREFETCH && !TARGET_MB_64"
{
operands[2] = gen_rtx_REG (SImode, MB_ABI_ASM_TEMP_REGNUM);
return "mfs\t%2,rpc\n\twic\t%2,r0";
@@ -618,23 +635,33 @@
;; Double Precision Subtraction
;;----------------------------------------------------------------
-(define_insn "subdi3_long"
- [(set (match_operand:DI 0 "register_operand" "=d,d")
- (minus:DI (match_operand:DI 1 "register_operand" "d,d")
- (match_operand:DI 2 "register_operand" "d,n")))]
+(define_expand "subdi3"
+ [(set (match_operand:DI 0 "register_operand" "")
+ (minus:DI (match_operand:DI 1 "register_operand" "")
+ (match_operand:DI 2 "arith_operand" "")))]
+""
+"
+{
+}")
+
+(define_insn "subsidi3"
+ [(set (match_operand:DI 0 "register_operand" "=d,d,d")
+ (minus:DI (match_operand:DI 1 "register_operand" "d,d,d")
+ (match_operand:DI 2 "arith_operand" "d,K,n")))]
"TARGET_MB_64"
"@
rsubl\t%0,%2,%1
- addlik\t%0,%z1,-%2"
- [(set_attr "type" "darith")
- (set_attr "mode" "DI,DI")
- (set_attr "length" "4,4")])
+ addik\t%0,%z1,-%2
+ addik\t%0,%z1,-%2"
+ [(set_attr "type" "arith,no_delay_arith,no_delay_arith")
+ (set_attr "mode" "DI")
+ (set_attr "length" "4,4,4")])
-(define_insn "subdi3"
+(define_insn "subdi3_small"
[(set (match_operand:DI 0 "register_operand" "=&d")
(minus:DI (match_operand:DI 1 "register_operand" "d")
(match_operand:DI 2 "register_operand" "d")))]
- ""
+ "!TARGET_MB_64"
"rsub\t%L0,%L2,%L1\;rsubc\t%M0,%M2,%M1"
[(set_attr "type" "darith")
(set_attr "mode" "DI")
@@ -663,7 +690,7 @@
(mult:DI
(sign_extend:DI (match_operand:SI 1 "register_operand" "d"))
(sign_extend:DI (match_operand:SI 2 "register_operand" "d"))))]
- "!TARGET_SOFT_MUL && TARGET_MULTIPLY_HIGH"
+ "!TARGET_SOFT_MUL && TARGET_MULTIPLY_HIGH && !TARGET_MB_64"
"mul\t%L0,%1,%2\;mulh\t%M0,%1,%2"
[(set_attr "type" "no_delay_arith")
(set_attr "mode" "DI")
@@ -674,7 +701,7 @@
(mult:DI
(zero_extend:DI (match_operand:SI 1 "register_operand" "d"))
(zero_extend:DI (match_operand:SI 2 "register_operand" "d"))))]
- "!TARGET_SOFT_MUL && TARGET_MULTIPLY_HIGH"
+ "!TARGET_SOFT_MUL && TARGET_MULTIPLY_HIGH && !TARGET_MB_64"
"mul\t%L0,%1,%2\;mulhu\t%M0,%1,%2"
[(set_attr "type" "no_delay_arith")
(set_attr "mode" "DI")
@@ -685,7 +712,7 @@
(mult:DI
(zero_extend:DI (match_operand:SI 1 "register_operand" "d"))
(sign_extend:DI (match_operand:SI 2 "register_operand" "d"))))]
- "!TARGET_SOFT_MUL && TARGET_MULTIPLY_HIGH"
+ "!TARGET_SOFT_MUL && TARGET_MULTIPLY_HIGH && !TARGET_MB_64"
"mul\t%L0,%1,%2\;mulhsu\t%M0,%2,%1"
[(set_attr "type" "no_delay_arith")
(set_attr "mode" "DI")
@@ -789,7 +816,7 @@
(match_operand:SI 4 "arith_operand")])
(label_ref (match_operand 5))
(pc)))]
- "TARGET_HARD_FLOAT"
+ "TARGET_HARD_FLOAT && !TARGET_MB_64"
[(set (match_dup 1) (match_dup 3))]
{
@@ -819,6 +846,15 @@
(set_attr "mode" "SI")
(set_attr "length" "4")])
+(define_insn "negsi_long"
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (neg:SI (match_operand:DI 1 "register_operand" "d")))]
+ ""
+ "rsubk\t%0,%1,r0"
+ [(set_attr "type" "arith")
+ (set_attr "mode" "SI")
+ (set_attr "length" "4")])
+
(define_insn "negdi2_long"
[(set (match_operand:DI 0 "register_operand" "=d")
(neg:DI (match_operand:DI 1 "register_operand" "d")))]
@@ -847,16 +883,24 @@
(set_attr "mode" "SI")
(set_attr "length" "4")])
-(define_insn "one_cmpldi2_long"
+(define_expand "one_cmpldi2"
+ [(set (match_operand:DI 0 "register_operand" "")
+ (not:DI (match_operand:DI 1 "register_operand" "")))]
+ ""
+ "
+{
+}")
+
+(define_insn ""
[(set (match_operand:DI 0 "register_operand" "=d")
- (not:DI (match_operand:DI 1 "register_operand" "d")))]
+ (not:DI (match_operand:DI 1 "arith_operand" "d")))]
"TARGET_MB_64"
"xorli\t%0,%1,-1"
- [(set_attr "type" "arith")
+ [(set_attr "type" "no_delay_arith")
(set_attr "mode" "DI")
(set_attr "length" "4")])
-(define_insn "*one_cmpldi2"
+(define_insn ""
[(set (match_operand:DI 0 "register_operand" "=d")
(not:DI (match_operand:DI 1 "register_operand" "d")))]
""
@@ -871,7 +915,8 @@
(not:DI (match_operand:DI 1 "register_operand" "")))]
"reload_completed
&& GET_CODE (operands[0]) == REG && GP_REG_P (REGNO (operands[0]))
- && GET_CODE (operands[1]) == REG && GP_REG_P (REGNO (operands[1]))"
+ && GET_CODE (operands[1]) == REG && GP_REG_P (REGNO (operands[1]))
+ && !TARGET_MB_64"
[(set (subreg:SI (match_dup 0) 0) (not:SI (subreg:SI (match_dup 1) 0)))
(set (subreg:SI (match_dup 0) 4) (not:SI (subreg:SI (match_dup 1) 4)))]
@@ -883,18 +928,17 @@
;;----------------------------------------------------------------
(define_insn "anddi3"
- [(set (match_operand:DI 0 "register_operand" "=d,d")
- (and:DI (match_operand:DI 1 "arith_operand" "d,d")
- (match_operand:DI 2 "arith_operand" "d,K")))]
+ [(set (match_operand:DI 0 "register_operand" "=d,d,d")
+ (and:DI (match_operand:DI 1 "arith_operand" "d,d,d")
+ (match_operand:DI 2 "arith_operand" "d,K,I")))]
"TARGET_MB_64"
"@
andl\t%0,%1,%2
- andli\t%0,%1,%2 #andl1"
- ;; andli\t%0,%1,%2 #andl3
- ;; andli\t%0,%1,%2 #andl2
- [(set_attr "type" "arith,arith")
- (set_attr "mode" "DI,DI")
- (set_attr "length" "4,4")])
+ andli\t%0,%1,%2 #andl2
+ andli\t%0,%1,%2 #andl3"
+ [(set_attr "type" "arith,no_delay_arith,no_delay_arith")
+ (set_attr "mode" "DI,DI,DI")
+ (set_attr "length" "4,4,4")])
(define_insn "andsi3"
[(set (match_operand:SI 0 "register_operand" "=d,d,d,d")
@@ -919,7 +963,7 @@
"@
orl\t%0,%1,%2
orli\t%0,%1,%2 #andl1"
- [(set_attr "type" "arith,arith")
+ [(set_attr "type" "arith,no_delay_arith")
(set_attr "mode" "DI,DI")
(set_attr "length" "4,4")])
@@ -945,7 +989,7 @@
"@
xorl\t%0,%1,%2
xorli\t%0,%1,%2 #andl1"
- [(set_attr "type" "arith,arith")
+ [(set_attr "type" "arith,no_delay_arith")
(set_attr "mode" "DI,DI")
(set_attr "length" "4,4")])
@@ -1018,26 +1062,6 @@
(set_attr "mode" "SI")
(set_attr "length" "4")])
-;;(define_expand "extendqidi2"
-;; [(set (match_operand:DI 0 "register_operand" "=d")
-;; (sign_extend:DI (match_operand:QI 1 "general_operand" "d")))]
-;; "TARGET_MB_64"
-;; {
-;; if (GET_CODE (operands[1]) != REG)
-;; FAIL;
-;; }
-;;)
-
-
-;;(define_insn "extendqidi2"
-;; [(set (match_operand:DI 0 "register_operand" "=d")
-;; (sign_extend:DI (match_operand:QI 1 "register_operand" "d")))]
-;; "TARGET_MB_64"
-;; "sextl8\t%0,%1"
-;; [(set_attr "type" "arith")
-;; (set_attr "mode" "DI")
-;; (set_attr "length" "4")])
-
(define_insn "extendhisi2"
[(set (match_operand:SI 0 "register_operand" "=d")
(sign_extend:SI (match_operand:HI 1 "register_operand" "d")))]
@@ -1060,6 +1084,27 @@
;; Those for integer source operand are ordered
;; widest source type first.
+(define_insn "extendsidi2_long"
+ [(set (match_operand:DI 0 "register_operand" "=d,d,d")
+ (sign_extend:DI (match_operand:SI 1 "nonimmediate_operand" "d,R,m")))]
+ "TARGET_MB_64"
+ {
+ switch (which_alternative)
+ {
+ case 0:
+ return "sextl32\t%0,%1";
+ case 1:
+ case 2:
+ {
+ output_asm_insn ("ll%i1\t%0,%1", operands);
+ return "sextl32\t%0,%0";
+ }
+ }
+ }
+ [(set_attr "type" "multi,multi,multi")
+ (set_attr "mode" "DI")
+ (set_attr "length" "4,8,8")])
+
(define_insn "extendsidi2"
[(set (match_operand:DI 0 "register_operand" "=d,d,d")
(sign_extend:DI (match_operand:SI 1 "nonimmediate_operand" "d,R,m")))]
@@ -1090,68 +1135,117 @@
;; Unlike most other insns, the move insns can't be split with
;; different predicates, because register spilling and other parts of
;; the compiler, have memoized the insn number already.
+;; //}
(define_expand "movdi"
[(set (match_operand:DI 0 "nonimmediate_operand" "")
(match_operand:DI 1 "general_operand" ""))]
""
{
- /* If operands[1] is a constant address illegal for pic, then we need to
- handle it just like microblaze_legitimize_address does. */
- if (flag_pic && pic_address_needs_scratch (operands[1]))
+ if (TARGET_MB_64)
+ {
+ if (microblaze_expand_move (DImode, operands)) DONE;
+ }
+ else
{
+ /* If operands[1] is a constant address illegal for pic, then we need to
+ handle it just like microblaze_legitimize_address does. */
+ if (flag_pic && pic_address_needs_scratch (operands[1]))
+ {
rtx temp = force_reg (DImode, XEXP (XEXP (operands[1], 0), 0));
rtx temp2 = XEXP (XEXP (operands[1], 0), 1);
emit_move_insn (operands[0], gen_rtx_PLUS (DImode, temp, temp2));
DONE;
- }
-
-
- if ((reload_in_progress | reload_completed) == 0
- && !register_operand (operands[0], DImode)
- && !register_operand (operands[1], DImode)
- && (((GET_CODE (operands[1]) != CONST_INT || INTVAL (operands[1]) != 0)
- && operands[1] != CONST0_RTX (DImode))))
- {
+ }
- rtx temp = force_reg (DImode, operands[1]);
- emit_move_insn (operands[0], temp);
- DONE;
+ if ((reload_in_progress | reload_completed) == 0
+ && !register_operand (operands[0], DImode)
+ && !register_operand (operands[1], DImode)
+ && (((GET_CODE (operands[1]) != CONST_INT || INTVAL (operands[1]) != 0)
+ && operands[1] != CONST0_RTX (DImode))))
+ {
+ rtx temp = force_reg (DImode, operands[1]);
+ emit_move_insn (operands[0], temp);
+ DONE;
+ }
}
}
)
+;; Added for status registers
+(define_insn "movdi_status"
+ [(set (match_operand:DI 0 "register_operand" "=d,d,z")
+ (match_operand:DI 1 "register_operand" "z,d,d"))]
+ "microblaze_is_interrupt_variant () && TARGET_MB_64"
+ "@
+ mfs\t%0,%1 #mfs
+ addlk\t%0,%1,r0 #add movdi
+ mts\t%0,%1 #mts"
+ [(set_attr "type" "move")
+ (set_attr "mode" "DI")
+ (set_attr "length" "12")])
-(define_insn "*movdi_internal_64"
- [(set (match_operand:DI 0 "nonimmediate_operand" "=d,d,d,d,d,R,o")
- (match_operand:DI 1 "general_operand" " d,K,J,R,o,d,d"))]
- "TARGET_MB_64 && (INTVAL(operands[1]) < 0x7fffffffff) && (INTVAL(operands[1]) > 0xffffff8000000000)"
+;; This move will be not be moved to delay slot.
+(define_insn "*movdi_internal3"
+ [(set (match_operand:DI 0 "nonimmediate_operand" "=d,d,d")
+ (match_operand:DI 1 "immediate_operand" "J,I,Mnis"))]
+ "TARGET_MB_64 && (register_operand (operands[0], DImode) &&
+ (GET_CODE (operands[1]) == CONST_INT &&
+ (INTVAL (operands[1]) <= (long)549755813887 && INTVAL (operands[1]) >= (long)-549755813888)))"
+ "@
+ addlk\t%0,r0,r0\t
+ addlik\t%0,r0,%1\t #N1 %X1
+ addlik\t%0,r0,%1\t #N2 %X1"
+ [(set_attr "type" "arith,no_delay_arith,no_delay_arith")
+ (set_attr "mode" "DI")
+ (set_attr "length" "4")])
+
+;; This move may be used for PLT label operand
+(define_insn "*movdi_internal5_pltop"
+ [(set (match_operand:DI 0 "register_operand" "=d,d")
+ (match_operand:DI 1 "call_insn_operand" ""))]
+ "TARGET_MB_64 && (register_operand (operands[0], Pmode) &&
+ PLT_ADDR_P (operands[1]))"
+ {
+ gcc_unreachable ();
+ }
+ [(set_attr "type" "load")
+ (set_attr "mode" "DI")
+ (set_attr "length" "4")])
+
+(define_insn "*movdi_internal2"
+ [(set (match_operand:DI 0 "nonimmediate_operand" "=d,d,d, d,d,R,m")
+ (match_operand:DI 1 "move_src_operand" " d,I,Mnis,R,m,dJ,dJ"))]
+ "TARGET_MB_64"
{
switch (which_alternative)
{
case 0:
- return "addlk\t%0,%1";
- case 1:
- return "addlik\t%0,r0,%1";
- case 2:
- return "addlk\t%0,r0,r0";
- case 3:
- case 4:
- return "lli\t%0,%1";
- case 5:
- case 6:
- return "sli\t%1,%0";
- }
- return "unreachable";
- }
- [(set_attr "type" "no_delay_move,no_delay_arith,no_delay_arith,no_delay_load,no_delay_load,no_delay_store,no_delay_store")
+ return "addlk\t%0,%1,r0";
+ case 1:
+ case 2:
+ if (GET_CODE (operands[1]) == CONST_INT &&
+ (INTVAL (operands[1]) > (long)549755813887 || INTVAL (operands[1]) < (long)-549755813888))
+ return "addlik\t%0,r0,%h1\n\tbsllli\t%0,%0,32\n\taddlik\t%0,%0,%j1 #li => la";
+ else
+ return "addlik\t%0,r0,%1";
+ case 3:
+ case 4:
+ return "ll%i1\t%0,%1";
+ case 5:
+ case 6:
+ return "sl%i0\t%z1,%0";
+ }
+ }
+ [(set_attr "type" "load,no_delay_load,no_delay_load,no_delay_load,no_delay_load,no_delay_store,no_delay_store")
(set_attr "mode" "DI")
- (set_attr "length" "8,8,8,8,12,8,12")])
+ (set_attr "length" "4,4,12,4,8,4,8")])
+
(define_insn "*movdi_internal"
[(set (match_operand:DI 0 "nonimmediate_operand" "=d,d,d,d,d,R,o")
(match_operand:DI 1 "general_operand" " d,i,J,R,o,d,d"))]
- ""
+ "!TARGET_MB_64"
{
switch (which_alternative)
{
@@ -1183,7 +1277,8 @@
"reload_completed
&& GET_CODE (operands[0]) == REG && GP_REG_P (REGNO (operands[0]))
&& GET_CODE (operands[1]) == REG && GP_REG_P (REGNO (operands[1]))
- && (REGNO(operands[0]) == (REGNO(operands[1]) + 1))"
+ && (REGNO(operands[0]) == (REGNO(operands[1]) + 1))
+ && !(TARGET_MB_64)"
[(set (subreg:SI (match_dup 0) 4) (subreg:SI (match_dup 1) 4))
(set (subreg:SI (match_dup 0) 0) (subreg:SI (match_dup 1) 0))]
@@ -1195,12 +1290,22 @@
"reload_completed
&& GET_CODE (operands[0]) == REG && GP_REG_P (REGNO (operands[0]))
&& GET_CODE (operands[1]) == REG && GP_REG_P (REGNO (operands[1]))
- && (REGNO (operands[0]) != (REGNO (operands[1]) + 1))"
+ && (REGNO (operands[0]) != (REGNO (operands[1]) + 1))
+ && !(TARGET_MB_64)"
[(set (subreg:SI (match_dup 0) 0) (subreg:SI (match_dup 1) 0))
(set (subreg:SI (match_dup 0) 4) (subreg:SI (match_dup 1) 4))]
"")
+(define_insn "movdi_long_int"
+ [(set (match_operand:DI 0 "nonimmediate_operand" "=d")
+ (match_operand:DI 1 "general_operand" "i"))]
+ ""
+ "addlik\t%0,r0,%h1\n\tbsllli\t%0,%0,32\n\taddlik\t%0,%0,%j1 #li => la";
+ [(set_attr "type" "no_delay_arith")
+ (set_attr "mode" "DI")
+ (set_attr "length" "12")])
+
;; Unlike most other insns, the move insns can't be split with
;; different predicates, because register spilling and other parts of
;; the compiler, have memoized the insn number already.
@@ -1272,6 +1377,8 @@
(set_attr "length" "4,4,8,4,8,4,8")])
+
+
;; 16-bit Integer moves
;; Unlike most other insns, the move insns can't be split with
@@ -1304,8 +1411,8 @@
"@
addik\t%0,r0,%1\t# %X1
addk\t%0,%1,r0
- lhui\t%0,%1
- lhui\t%0,%1
+ lhu%i1\t%0,%1
+ lhu%i1\t%0,%1
sh%i0\t%z1,%0
sh%i0\t%z1,%0"
[(set_attr "type" "arith,move,load,no_delay_load,store,no_delay_store")
@@ -1348,7 +1455,7 @@
lbu%i1\t%0,%1
lbu%i1\t%0,%1
sb%i0\t%z1,%0
- sbi\t%z1,%0"
+ sb%i0\t%z1,%0"
[(set_attr "type" "arith,arith,move,load,no_delay_load,store,no_delay_store")
(set_attr "mode" "QI")
(set_attr "length" "4,4,8,4,8,4,8")])
@@ -1421,7 +1528,7 @@
addik\t%0,r0,%F1
lw%i1\t%0,%1
sw%i0\t%z1,%0
- swi\t%z1,%0"
+ sw%i0\t%z1,%0"
[(set_attr "type" "move,no_delay_load,load,no_delay_load,no_delay_load,store,no_delay_store")
(set_attr "mode" "SF")
(set_attr "length" "4,4,4,4,4,4,4")])
@@ -1460,6 +1567,33 @@
;; movdf_internal
;; Applies to both TARGET_SOFT_FLOAT and TARGET_HARD_FLOAT
;;
+(define_insn "*movdf_internal_64"
+ [(set (match_operand:DF 0 "nonimmediate_operand" "=d,d,d,d,d,m")
+ (match_operand:DF 1 "general_operand" "d,dG,m,F,T,d"))]
+ "TARGET_MB_64"
+ {
+ switch (which_alternative)
+ {
+ case 0:
+ return "addlk\t%0,%1,r0";
+ case 1:
+ return "addlk\t%0,r0,r0";
+ case 2:
+ case 4:
+ return "ll%i1\t%0,%1";
+ case 3:
+ {
+ return "addlik\t%0,r0,%h1 \n\tbsllli\t%0,%0,32\n\taddlik\t%0,%0,%j1 #Xfer Lo";
+ }
+ case 5:
+ return "sl%i0\t%1,%0";
+ }
+ gcc_unreachable ();
+ }
+ [(set_attr "type" "no_delay_move,no_delay_move,no_delay_load,no_delay_load,no_delay_load,no_delay_store")
+ (set_attr "mode" "DF")
+ (set_attr "length" "4,4,4,16,4,4")])
+
(define_insn "*movdf_internal"
[(set (match_operand:DF 0 "nonimmediate_operand" "=d,d,d,d,o")
(match_operand:DF 1 "general_operand" "dG,o,F,T,d"))]
@@ -1494,7 +1628,8 @@
"reload_completed
&& GET_CODE (operands[0]) == REG && GP_REG_P (REGNO (operands[0]))
&& GET_CODE (operands[1]) == REG && GP_REG_P (REGNO (operands[1]))
- && (REGNO (operands[0]) == (REGNO (operands[1]) + 1))"
+ && (REGNO (operands[0]) == (REGNO (operands[1]) + 1))
+ && !TARGET_MB_64"
[(set (subreg:SI (match_dup 0) 4) (subreg:SI (match_dup 1) 4))
(set (subreg:SI (match_dup 0) 0) (subreg:SI (match_dup 1) 0))]
"")
@@ -1505,7 +1640,8 @@
"reload_completed
&& GET_CODE (operands[0]) == REG && GP_REG_P (REGNO (operands[0]))
&& GET_CODE (operands[1]) == REG && GP_REG_P (REGNO (operands[1]))
- && (REGNO (operands[0]) != (REGNO (operands[1]) + 1))"
+ && (REGNO (operands[0]) != (REGNO (operands[1]) + 1))
+ && !TARGET_MB_64"
[(set (subreg:SI (match_dup 0) 0) (subreg:SI (match_dup 1) 0))
(set (subreg:SI (match_dup 0) 4) (subreg:SI (match_dup 1) 4))]
"")
@@ -2005,6 +2141,31 @@ else
"
)
+
+(define_insn "seq_internal_pat_long"
+ [(set (match_operand:DI 0 "register_operand" "=d")
+ (eq:DI
+ (match_operand:DI 1 "register_operand" "d")
+ (match_operand:DI 2 "register_operand" "d")))]
+ "TARGET_MB_64"
+ "pcmpleq\t%0,%1,%2"
+ [(set_attr "type" "arith")
+ (set_attr "mode" "DI")
+ (set_attr "length" "4")]
+)
+
+(define_insn "sne_internal_pat_long"
+ [(set (match_operand:DI 0 "register_operand" "=d")
+ (ne:DI
+ (match_operand:DI 1 "register_operand" "d")
+ (match_operand:DI 2 "register_operand" "d")))]
+ "TARGET_MB_64"
+ "pcmplne\t%0,%1,%2"
+ [(set_attr "type" "arith")
+ (set_attr "mode" "DI")
+ (set_attr "length" "4")]
+)
+
(define_insn "seq_internal_pat"
[(set (match_operand:SI 0 "register_operand" "=d")
(eq:SI
@@ -2065,8 +2226,8 @@ else
(define_expand "cbranchsi4"
[(set (pc)
(if_then_else (match_operator 0 "ordered_comparison_operator"
- [(match_operand:SI 1 "register_operand")
- (match_operand:SI 2 "arith_operand" "I,i")])
+ [(match_operand 1 "register_operand")
+ (match_operand 2 "arith_operand" "I,i")])
(label_ref (match_operand 3 ""))
(pc)))]
""
@@ -2078,13 +2239,13 @@ else
(define_expand "cbranchsi4_reg"
[(set (pc)
(if_then_else (match_operator 0 "ordered_comparison_operator"
- [(match_operand:SI 1 "register_operand")
- (match_operand:SI 2 "register_operand")])
+ [(match_operand 1 "register_operand")
+ (match_operand 2 "register_operand")])
(label_ref (match_operand 3 ""))
(pc)))]
""
{
- microblaze_expand_conditional_branch_reg (SImode, operands);
+ microblaze_expand_conditional_branch_reg (Pmode, operands);
DONE;
})
@@ -2109,6 +2270,26 @@ else
(label_ref (match_operand 1))
(pc)))])
+(define_insn "branch_zero64"
+ [(set (pc)
+ (if_then_else (match_operator 0 "ordered_comparison_operator"
+ [(match_operand 1 "register_operand" "d")
+ (const_int 0)])
+ (match_operand 2 "pc_or_label_operand" "")
+ (match_operand 3 "pc_or_label_operand" "")))
+ ]
+ "TARGET_MB_64"
+ {
+ if (operands[3] == pc_rtx)
+ return "bea%C0i%?\t%z1,%2";
+ else
+ return "bea%N0i%?\t%z1,%3";
+ }
+ [(set_attr "type" "branch")
+ (set_attr "mode" "none")
+ (set_attr "length" "4")]
+)
+
(define_insn "branch_zero"
[(set (pc)
(if_then_else (match_operator:SI 0 "ordered_comparison_operator"
@@ -2129,6 +2310,47 @@ else
(set_attr "length" "4")]
)
+(define_insn "branch_compare64"
+ [(set (pc)
+ (if_then_else (match_operator 0 "cmp_op"
+ [(match_operand 1 "register_operand" "d")
+ (match_operand 2 "register_operand" "d")
+ ])
+ (label_ref (match_operand 3))
+ (pc)))
+ (clobber(reg:SI R_TMP))]
+ "TARGET_MB_64"
+ {
+ operands[4] = gen_rtx_REG (SImode, MB_ABI_ASM_TEMP_REGNUM);
+ enum rtx_code code = GET_CODE (operands[0]);
+
+ if (code == GT || code == LE)
+ {
+ output_asm_insn ("cmp\tr18,%z1,%z2", operands);
+ code = swap_condition (code);
+ }
+ else if (code == GTU || code == LEU)
+ {
+ output_asm_insn ("cmpu\tr18,%z1,%z2", operands);
+ code = swap_condition (code);
+ }
+ else if (code == GE || code == LT)
+ {
+ output_asm_insn ("cmp\tr18,%z2,%z1", operands);
+ }
+ else if (code == GEU || code == LTU)
+ {
+ output_asm_insn ("cmpu\tr18,%z2,%z1", operands);
+ }
+
+ operands[0] = gen_rtx_fmt_ee (signed_condition (code), SImode, operands[4], const0_rtx);
+ return "bea%C0i%?\tr18,%3";
+ }
+ [(set_attr "type" "branch")
+ (set_attr "mode" "none")
+ (set_attr "length" "12")]
+)
+
(define_insn "branch_compare"
[(set (pc)
(if_then_else (match_operator:SI 0 "cmp_op"
@@ -2312,7 +2534,7 @@ else
;; Indirect jumps. Jump to register values. Assuming absolute jumps
(define_insn "indirect_jump_internal1"
- [(set (pc) (match_operand:SI 0 "register_operand" "d"))]
+ [(set (pc) (match_operand 0 "register_operand" "d"))]
""
"bra%?\t%0"
[(set_attr "type" "jump")
@@ -2325,7 +2547,7 @@ else
(use (label_ref (match_operand 1 "" "")))]
""
{
- gcc_assert (GET_MODE (operands[0]) == Pmode);
+ //gcc_assert (GET_MODE (operands[0]) == Pmode);
if (!flag_pic || TARGET_PIC_DATA_TEXT_REL)
emit_jump_insn (gen_tablejump_internal1 (operands[0], operands[1]));
@@ -2337,7 +2559,7 @@ else
(define_insn "tablejump_internal1"
[(set (pc)
- (match_operand:SI 0 "register_operand" "d"))
+ (match_operand 0 "register_operand" "d"))
(use (label_ref (match_operand 1 "" "")))]
""
"bra%?\t%0 "
@@ -2347,9 +2569,9 @@ else
(define_expand "tablejump_internal3"
[(parallel [(set (pc)
- (plus:SI (match_operand:SI 0 "register_operand" "d")
- (label_ref:SI (match_operand:SI 1 "" ""))))
- (use (label_ref:SI (match_dup 1)))])]
+ (plus (match_operand 0 "register_operand" "d")
+ (label_ref (match_operand:SI 1 "" ""))))
+ (use (label_ref (match_dup 1)))])]
""
""
)
@@ -2410,7 +2632,7 @@ else
(minus (reg 1) (match_operand 1 "register_operand" "")))
(set (reg 1)
(minus (reg 1) (match_dup 1)))]
- ""
+ "!TARGET_MB_64"
{
rtx retaddr = gen_rtx_MEM (Pmode, stack_pointer_rtx);
rtx reg = gen_reg_rtx (Pmode);
@@ -2435,7 +2657,7 @@ else
(define_expand "save_stack_block"
[(match_operand 0 "register_operand" "")
(match_operand 1 "register_operand" "")]
- ""
+ "!TARGET_MB_64"
{
emit_move_insn (operands[0], operands[1]);
DONE;
@@ -2445,7 +2667,7 @@ else
(define_expand "restore_stack_block"
[(match_operand 0 "register_operand" "")
(match_operand 1 "register_operand" "")]
- ""
+ "!TARGET_MB_64"
{
rtx retaddr = gen_rtx_MEM (Pmode, stack_pointer_rtx);
rtx rtmp = gen_rtx_REG (SImode, R_TMP);
@@ -2492,7 +2714,7 @@ else
(define_insn "<optab>_internal"
[(any_return)
- (use (match_operand:SI 0 "register_operand" ""))]
+ (use (match_operand 0 "register_operand" ""))]
""
{
if (microblaze_is_break_handler ())
@@ -2525,7 +2747,7 @@ else
(define_expand "call"
[(parallel [(call (match_operand 0 "memory_operand" "m")
(match_operand 1 "" "i"))
- (clobber (reg:SI R_SR))
+ (clobber (reg R_SR))
(use (match_operand 2 "" ""))
(use (match_operand 3 "" ""))])]
""
@@ -2546,12 +2768,12 @@ else
if (GET_CODE (XEXP (operands[0], 0)) == UNSPEC)
emit_call_insn (gen_call_internal_plt0 (operands[0], operands[1],
- gen_rtx_REG (SImode,
+ gen_rtx_REG (Pmode,
GP_REG_FIRST + MB_ABI_SUB_RETURN_ADDR_REGNUM),
pic_offset_table_rtx));
else
emit_call_insn (gen_call_internal0 (operands[0], operands[1],
- gen_rtx_REG (SImode,
+ gen_rtx_REG (Pmode,
GP_REG_FIRST + MB_ABI_SUB_RETURN_ADDR_REGNUM)));
DONE;
@@ -2561,7 +2783,7 @@ else
(define_expand "call_internal0"
[(parallel [(call (match_operand 0 "" "")
(match_operand 1 "" ""))
- (clobber (match_operand:SI 2 "" ""))])]
+ (clobber (match_operand 2 "" ""))])]
""
{
}
@@ -2570,18 +2792,34 @@ else
(define_expand "call_internal_plt0"
[(parallel [(call (match_operand 0 "" "")
(match_operand 1 "" ""))
- (clobber (match_operand:SI 2 "" ""))
- (use (match_operand:SI 3 "" ""))])]
+ (clobber (match_operand 2 "" ""))
+ (use (match_operand 3 "" ""))])]
""
{
}
)
+(define_insn "call_internal_plt_64"
+ [(call (mem (match_operand 0 "call_insn_plt_operand" ""))
+ (match_operand 1 "" "i"))
+ (clobber (reg R_SR))
+ (use (reg R_GOT))]
+ "flag_pic && TARGET_MB_64"
+ {
+ register rtx target2 = gen_rtx_REG (Pmode,
+ GP_REG_FIRST + MB_ABI_SUB_RETURN_ADDR_REGNUM);
+ gen_rtx_CLOBBER (VOIDmode, target2);
+ return "brealid\tr15,%0\;%#";
+ }
+ [(set_attr "type" "call")
+ (set_attr "mode" "none")
+ (set_attr "length" "4")])
+
(define_insn "call_internal_plt"
- [(call (mem (match_operand:SI 0 "call_insn_plt_operand" ""))
- (match_operand:SI 1 "" "i"))
- (clobber (reg:SI R_SR))
- (use (reg:SI R_GOT))]
+ [(call (mem (match_operand 0 "call_insn_plt_operand" ""))
+ (match_operand 1 "" "i"))
+ (clobber (reg R_SR))
+ (use (reg R_GOT))]
"flag_pic"
{
register rtx target2 = gen_rtx_REG (Pmode,
@@ -2593,10 +2831,41 @@ else
(set_attr "mode" "none")
(set_attr "length" "4")])
+(define_insn "call_internal1_64"
+ [(call (mem (match_operand:VOID 0 "call_insn_simple_operand" "ri"))
+ (match_operand 1 "" "i"))
+ (clobber (reg R_SR))]
+ "TARGET_MB_64"
+ {
+ register rtx target = operands[0];
+ register rtx target2 = gen_rtx_REG (Pmode,
+ GP_REG_FIRST + MB_ABI_SUB_RETURN_ADDR_REGNUM);
+ if (GET_CODE (target) == SYMBOL_REF) {
+ if (microblaze_break_function_p (SYMBOL_REF_DECL (target))) {
+ gen_rtx_CLOBBER (VOIDmode, target2);
+ return "breaki\tr16,%0\;%#";
+ }
+ else {
+ gen_rtx_CLOBBER (VOIDmode, target2);
+ return "brealid\tr15,%0\;%#";
+ }
+ } else if (GET_CODE (target) == CONST_INT)
+ return "la\t%@,r0,%0\;brald\tr15,%@\;%#";
+ else if (GET_CODE (target) == REG)
+ return "brald\tr15,%0\;%#";
+ else {
+ fprintf (stderr,"Unsupported call insn\n");
+ return NULL;
+ }
+ }
+ [(set_attr "type" "call")
+ (set_attr "mode" "none")
+ (set_attr "length" "4")])
+
(define_insn "call_internal1"
[(call (mem (match_operand:VOID 0 "call_insn_simple_operand" "ri"))
- (match_operand:SI 1 "" "i"))
- (clobber (reg:SI R_SR))]
+ (match_operand 1 "" "i"))
+ (clobber (reg R_SR))]
""
{
register rtx target = operands[0];
@@ -2630,7 +2899,7 @@ else
[(parallel [(set (match_operand 0 "register_operand" "=d")
(call (match_operand 1 "memory_operand" "m")
(match_operand 2 "" "i")))
- (clobber (reg:SI R_SR))
+ (clobber (reg R_SR))
(use (match_operand 3 "" ""))])] ;; next_arg_reg
""
{
@@ -2651,13 +2920,13 @@ else
if (GET_CODE (XEXP (operands[1], 0)) == UNSPEC)
emit_call_insn (gen_call_value_intern_plt0 (operands[0], operands[1],
operands[2],
- gen_rtx_REG (SImode,
+ gen_rtx_REG (Pmode,
GP_REG_FIRST + MB_ABI_SUB_RETURN_ADDR_REGNUM),
pic_offset_table_rtx));
else
emit_call_insn (gen_call_value_internal (operands[0], operands[1],
operands[2],
- gen_rtx_REG (SImode,
+ gen_rtx_REG (Pmode,
GP_REG_FIRST + MB_ABI_SUB_RETURN_ADDR_REGNUM)));
DONE;
@@ -2669,7 +2938,7 @@ else
[(parallel [(set (match_operand 0 "" "")
(call (match_operand 1 "" "")
(match_operand 2 "" "")))
- (clobber (match_operand:SI 3 "" ""))
+ (clobber (match_operand 3 "" ""))
])]
""
{}
@@ -2679,18 +2948,35 @@ else
[(parallel[(set (match_operand 0 "" "")
(call (match_operand 1 "" "")
(match_operand 2 "" "")))
- (clobber (match_operand:SI 3 "" ""))
- (use (match_operand:SI 4 "" ""))])]
+ (clobber (match_operand 3 "" ""))
+ (use (match_operand 4 "" ""))])]
"flag_pic"
{}
)
+(define_insn "call_value_intern_plt_64"
+ [(set (match_operand:VOID 0 "register_operand" "=d")
+ (call (mem (match_operand 1 "call_insn_plt_operand" ""))
+ (match_operand 2 "" "i")))
+ (clobber (match_operand 3 "register_operand" "=d"))
+ (use (match_operand 4 "register_operand"))]
+ "flag_pic && TARGET_MB_64"
+ {
+ register rtx target2=gen_rtx_REG (Pmode,GP_REG_FIRST + MB_ABI_SUB_RETURN_ADDR_REGNUM);
+
+ gen_rtx_CLOBBER (VOIDmode,target2);
+ return "brealid\tr15,%1\;%#";
+ }
+ [(set_attr "type" "call")
+ (set_attr "mode" "none")
+ (set_attr "length" "4")])
+
(define_insn "call_value_intern_plt"
[(set (match_operand:VOID 0 "register_operand" "=d")
- (call (mem (match_operand:SI 1 "call_insn_plt_operand" ""))
- (match_operand:SI 2 "" "i")))
- (clobber (match_operand:SI 3 "register_operand" "=d"))
- (use (match_operand:SI 4 "register_operand"))]
+ (call (mem (match_operand 1 "call_insn_plt_operand" ""))
+ (match_operand 2 "" "i")))
+ (clobber (match_operand 3 "register_operand" "=d"))
+ (use (match_operand 4 "register_operand"))]
"flag_pic"
{
register rtx target2=gen_rtx_REG (Pmode,GP_REG_FIRST + MB_ABI_SUB_RETURN_ADDR_REGNUM);
@@ -2702,11 +2988,46 @@ else
(set_attr "mode" "none")
(set_attr "length" "4")])
+(define_insn "call_value_intern_64"
+ [(set (match_operand:VOID 0 "register_operand" "=d")
+ (call (mem (match_operand:VOID 1 "call_insn_operand" "ri"))
+ (match_operand 2 "" "i")))
+ (clobber (match_operand 3 "register_operand" "=d"))]
+ "TARGET_MB_64"
+ {
+ register rtx target = operands[1];
+ register rtx target2=gen_rtx_REG (Pmode,GP_REG_FIRST + MB_ABI_SUB_RETURN_ADDR_REGNUM);
+
+ if (GET_CODE (target) == SYMBOL_REF)
+ {
+ gen_rtx_CLOBBER (VOIDmode,target2);
+ if (microblaze_break_function_p (SYMBOL_REF_DECL (target)))
+ return "breaki\tr16,%1\;%#";
+ else if (SYMBOL_REF_FLAGS (target) & SYMBOL_FLAG_FUNCTION)
+ {
+ return "brealid\tr15,%1\;%#";
+ }
+ else
+ {
+ return "bralid\tr15,%1\;%#";
+ }
+ }
+ else if (GET_CODE (target) == CONST_INT)
+ return "la\t%@,r0,%1\;brald\tr15,%@\;%#";
+ else if (GET_CODE (target) == REG)
+ return "brald\tr15,%1\;%#";
+ else
+ return "Unsupported call insn\n";
+ }
+ [(set_attr "type" "call")
+ (set_attr "mode" "none")
+ (set_attr "length" "4")])
+
(define_insn "call_value_intern"
[(set (match_operand:VOID 0 "register_operand" "=d")
(call (mem (match_operand:VOID 1 "call_insn_operand" "ri"))
- (match_operand:SI 2 "" "i")))
- (clobber (match_operand:SI 3 "register_operand" "=d"))]
+ (match_operand 2 "" "i")))
+ (clobber (match_operand 3 "register_operand" "=d"))]
""
{
register rtx target = operands[1];
@@ -2880,7 +3201,6 @@ else
;;if (!register_operand (operands[0], VOIDmode))
;; FAIL;
-
emit_insn (gen_insv_32 (operands[0], operands[1],
operands[2], operands[3]));
DONE;
diff --git a/gcc/config/microblaze/t-microblaze b/gcc/config/microblaze/t-microblaze
index 7671f63c5b5..9fc80b142ce 100644
--- a/gcc/config/microblaze/t-microblaze
+++ b/gcc/config/microblaze/t-microblaze
@@ -2,10 +2,11 @@ MULTILIB_OPTIONS = mxl-barrel-shift mno-xl-soft-mul mxl-multiply-high mlittle-en
MULTILIB_DIRNAMES = bs m mh le m64
MULTILIB_EXCEPTIONS = *mxl-barrel-shift/mxl-multiply-high mxl-multiply-high
MULTILIB_EXCEPTIONS += *mxl-barrel-shift/mxl-multiply-high/mlittle-endian
-MULTILIB_EXCEPTIONS += *mxl-barrel-shift/mxl-multiply-high/m64
+MULTILIB_EXCEPTIONS += *mxl-barrel-shift/mxl-multiply-high/mlittle-endian/m64
+MULTILIB_EXCEPTIONS += *mxl-barrel-shift/mxl-multiply-high/m64 mxl-multiply-high
MULTILIB_EXCEPTIONS += mxl-multiply-high/mlittle-endian
-#MULTILIB_EXCEPTIONS += mxl-multiply-high/m64
-#MULTILIB_EXCEPTIONS += *mxl-multiply-high/mlittle-endian/m64
+MULTILIB_EXCEPTIONS += mxl-multiply-high/m64
+MULTILIB_EXCEPTIONS += *mxl-multiply-high/mlittle-endian/m64
# Extra files
microblaze-c.o: $(srcdir)/config/microblaze/microblaze-c.c \
diff --git a/libgcc/config/microblaze/crti.S b/libgcc/config/microblaze/crti.S
index d0146083db6..005825f1ec5 100644
--- a/libgcc/config/microblaze/crti.S
+++ b/libgcc/config/microblaze/crti.S
@@ -40,7 +40,7 @@
.align 2
__init:
- addik r1, r1, -8
+ addik r1, r1, -16
sw r15, r0, r1
la r11, r0, _stack
mts rshr, r11
@@ -51,5 +51,5 @@ __init:
.global __fini
.align 2
__fini:
- addik r1, r1, -8
+ addik r1, r1, -16
sw r15, r0, r1
diff --git a/libgcc/config/microblaze/crtn.S b/libgcc/config/microblaze/crtn.S
index 2fff5ac04c7..5705eff9a4a 100644
--- a/libgcc/config/microblaze/crtn.S
+++ b/libgcc/config/microblaze/crtn.S
@@ -33,9 +33,9 @@
.section .init, "ax"
lw r15, r0, r1
rtsd r15, 8
- addik r1, r1, 8
+ addik r1, r1, 16
.section .fini, "ax"
lw r15, r0, r1
rtsd r15, 8
- addik r1, r1, 8
+ addik r1, r1, 16
diff --git a/libgcc/config/microblaze/divdi3.S b/libgcc/config/microblaze/divdi3.S
new file mode 100644
index 00000000000..d37bf5165c6
--- /dev/null
+++ b/libgcc/config/microblaze/divdi3.S
@@ -0,0 +1,98 @@
+###################################-
+#
+# Copyright (C) 2009-2017 Free Software Foundation, Inc.
+#
+# Contributed by Michael Eager <eager@eagercon.com>.
+#
+# This file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the
+# Free Software Foundation; either version 3, or (at your option) any
+# later version.
+#
+# GCC is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+# License for more details.
+#
+# Under Section 7 of GPL version 3, you are granted additional
+# permissions described in the GCC Runtime Library Exception, version
+# 3.1, as published by the Free Software Foundation.
+#
+# You should have received a copy of the GNU General Public License and
+# a copy of the GCC Runtime Library Exception along with this program;
+# see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+# <http://www.gnu.org/licenses/>.
+#
+# divdi3.S
+#
+# Divide operation for 32 bit integers.
+# Input : Dividend in Reg r5
+# Divisor in Reg r6
+# Output: Result in Reg r3
+#
+#######################################
+
+#ifdef __arch64__
+ .globl __divdi3
+ .ent __divdi3
+ .type __divdi3,@function
+__divdi3:
+ .frame r1,0,r15
+
+ ADDLIK r1,r1,-32
+ SLI r28,r1,0
+ SLI r29,r1,8
+ SLI r30,r1,16
+ SLI r31,r1,24
+
+ BEALEQI r6,$LaDiv_By_Zero # Div_by_Zero # Division Error
+ BEALEQI r5,$LaResult_Is_Zero # Result is Zero
+ XORL r28,r5,r6 # Get the sign of the result
+ BEALGEI r5,$LaR5_Pos
+ RSUBLI r5,r5,0 # Make r5 positive
+$LaR5_Pos:
+ BEALGEI r6,$LaR6_Pos
+ RSUBLI r6,r6,0 # Make r6 positive
+$LaR6_Pos:
+ ADDLIK r30,r0,0 # Clear mod
+ ADDLIK r3,r0,0 # clear div
+ ADDLIK r29,r0,64 # Initialize the loop count
+
+ # First part try to find the first '1' in the r5
+$LaDIV0:
+ BEALLTI r5,$LaDIV2 # This traps r5 == 0x80000000
+$LaDIV1:
+ ADDL r5,r5,r5 # left shift logical r5
+ ADDLIK r29,r29,-1
+ BEALGTI r5,$LaDIV1
+$LaDIV2:
+ ADDL r5,r5,r5 # left shift logical r5 get the '1' into the Carry
+ ADDLC r30,r30,r30 # Move that bit into the Mod register
+ RSUBL r31,r6,r30 # Try to subtract (r30 a r6)
+ BEALLTI r31,$LaMOD_TOO_SMALL
+ ORL r30,r0,r31 # Move the r31 to mod since the result was positive
+ ADDLIK r3,r3,1
+$LaMOD_TOO_SMALL:
+ ADDLIK r29,r29,-1
+ BEALEQi r29,$LaLOOP_END
+ ADDL r3,r3,r3 # Shift in the '1' into div
+ BREAI $LaDIV2 # Div2
+$LaLOOP_END:
+ BEALGEI r28,$LaRETURN_HERE
+ RSUBLI r3,r3,0 # Negate the result
+ BREAI $LaRETURN_HERE
+$LaDiv_By_Zero:
+$LaResult_Is_Zero:
+ ORL r3,r0,r0 # set result to 0
+$LaRETURN_HERE:
+# Restore values of CSRs and that of r3 and the divisor and the dividend
+ LLI r28,r1,0
+ LLI r29,r1,8
+ LLI r30,r1,16
+ LLI r31,r1,24
+ ADDLIK r1,r1,32
+ RTSD r15,8
+ nop
+.end __divdi3
+ .size __divdi3, . - __divdi3
+#endif
diff --git a/libgcc/config/microblaze/divdi3_table.c b/libgcc/config/microblaze/divdi3_table.c
new file mode 100644
index 00000000000..80962597ea5
--- /dev/null
+++ b/libgcc/config/microblaze/divdi3_table.c
@@ -0,0 +1,62 @@
+/* Table for software lookup divide for Xilinx MicroBlaze.
+
+ Copyright (C) 2009-2017 Free Software Foundation, Inc.
+
+ Contributed by Michael Eager <eager@eagercon.com>.
+
+ This file is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by the
+ Free Software Foundation; either version 3, or (at your option) any
+ later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+ License for more details.
+
+ Under Section 7 of GPL version 3, you are granted additional
+ permissions described in the GCC Runtime Library Exception, version
+ 3.1, as published by the Free Software Foundation.
+
+ You should have received a copy of the GNU General Public License and
+ a copy of the GCC Runtime Library Exception along with this program;
+ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+
+unsigned char _divdi3_table[] =
+{
+ 0, 0/1, 0/2, 0/3, 0/4, 0/5, 0/6, 0/7,
+ 0/8, 0/9, 0/10, 0/11, 0/12, 0/13, 0/14, 0/15,
+ 0, 1/1, 1/2, 1/3, 1/4, 1/5, 1/6, 1/7,
+ 1/8, 1/9, 1/10, 1/11, 1/12, 1/13, 1/14, 1/15,
+ 0, 2/1, 2/2, 2/3, 2/4, 2/5, 2/6, 2/7,
+ 2/8, 2/9, 2/10, 2/11, 2/12, 2/13, 2/14, 2/15,
+ 0, 3/1, 3/2, 3/3, 3/4, 3/5, 3/6, 3/7,
+ 3/8, 3/9, 3/10, 3/11, 3/12, 3/13, 3/14, 3/15,
+ 0, 4/1, 4/2, 4/3, 4/4, 4/5, 4/6, 4/7,
+ 4/8, 4/9, 4/10, 4/11, 4/12, 4/13, 4/14, 4/15,
+ 0, 5/1, 5/2, 5/3, 5/4, 5/5, 5/6, 5/7,
+ 5/8, 5/9, 5/10, 5/11, 5/12, 5/13, 5/14, 5/15,
+ 0, 6/1, 6/2, 6/3, 6/4, 6/5, 6/6, 6/7,
+ 6/8, 6/9, 6/10, 6/11, 6/12, 6/13, 6/14, 6/15,
+ 0, 7/1, 7/2, 7/3, 7/4, 7/5, 7/6, 7/7,
+ 7/8, 7/9, 7/10, 7/11, 7/12, 7/13, 7/14, 7/15,
+ 0, 8/1, 8/2, 8/3, 8/4, 8/5, 8/6, 8/7,
+ 8/8, 8/9, 8/10, 8/11, 8/12, 8/13, 8/14, 8/15,
+ 0, 9/1, 9/2, 9/3, 9/4, 9/5, 9/6, 9/7,
+ 9/8, 9/9, 9/10, 9/11, 9/12, 9/13, 9/14, 9/15,
+ 0, 10/1, 10/2, 10/3, 10/4, 10/5, 10/6, 10/7,
+ 10/8, 10/9, 10/10, 10/11, 10/12, 10/13, 10/14, 10/15,
+ 0, 11/1, 11/2, 11/3, 11/4, 11/5, 11/6, 11/7,
+ 11/8, 11/9, 11/10, 11/11, 11/12, 11/13, 11/14, 11/15,
+ 0, 12/1, 12/2, 12/3, 12/4, 12/5, 12/6, 12/7,
+ 12/8, 12/9, 12/10, 12/11, 12/12, 12/13, 12/14, 12/15,
+ 0, 13/1, 13/2, 13/3, 13/4, 13/5, 13/6, 13/7,
+ 13/8, 13/9, 13/10, 13/11, 13/12, 13/13, 13/14, 13/15,
+ 0, 14/1, 14/2, 14/3, 14/4, 14/5, 14/6, 14/7,
+ 14/8, 14/9, 14/10, 14/11, 14/12, 14/13, 14/14, 14/15,
+ 0, 15/1, 15/2, 15/3, 15/4, 15/5, 15/6, 15/7,
+ 15/8, 15/9, 15/10, 15/11, 15/12, 15/13, 15/14, 15/15,
+};
+
diff --git a/libgcc/config/microblaze/moddi3.S b/libgcc/config/microblaze/moddi3.S
new file mode 100644
index 00000000000..5d3f7c03fc8
--- /dev/null
+++ b/libgcc/config/microblaze/moddi3.S
@@ -0,0 +1,97 @@
+###################################
+#
+# Copyright (C) 2009-2017 Free Software Foundation, Inc.
+#
+# Contributed by Michael Eager <eager@eagercon.com>.
+#
+# This file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the
+# Free Software Foundation; either version 3, or (at your option) any
+# later version.
+#
+# GCC is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+# License for more details.
+#
+# Under Section 7 of GPL version 3, you are granted additional
+# permissions described in the GCC Runtime Library Exception, version
+# 3.1, as published by the Free Software Foundation.
+#
+# You should have received a copy of the GNU General Public License and
+# a copy of the GCC Runtime Library Exception along with this program;
+# see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+# <http://www.gnu.org/licenses/>.
+#
+# moddi3.S
+#
+# modulo operation for 32 bit integers.
+# Input : op1 in Reg r5
+# op2 in Reg r6
+# Output: op1 mod op2 in Reg r3
+#
+#######################################
+
+#ifdef __arch64__
+ .globl __moddi3
+ .ent __moddi3
+ .type __moddi3,@function
+__moddi3:
+ .frame r1,0,r15
+
+ addlik r1,r1,-32
+ sli r28,r1,0
+ sli r29,r1,8
+ sli r30,r1,16
+ sli r31,r1,32
+
+ BEALEQI r6,$LaDiv_By_Zero # Div_by_Zero # Division Error
+ BEALEQI r5,$LaResult_Is_Zero # Result is Zero
+ ADDL r28,r5,r0 # Get the sign of the result [ Depends only on the first arg]
+ BEALGEI r5,$LaR5_Pos
+ RSUBLI r5,r5,0 # Make r5 positive
+$LaR5_Pos:
+ BEALGEI r6,$LaR6_Pos
+ RSUBLI r6,r6,0 # Make r6 positive
+$LaR6_Pos:
+ ADDLIK r3,r0,0 # Clear mod
+ ADDLIK r30,r0,0 # clear div
+ ADDLIK r29,r0,64 # Initialize the loop count
+ BEALLTI r5,$LaDIV2 # If r5 is still negative (0x80000000), skip
+ # the first bit search.
+ # First part try to find the first '1' in the r5
+$LaDIV1:
+ ADDL r5,r5,r5 # left shift logical r5
+ ADDLIK r29,r29,-1
+ BEALGEI r5,$LaDIV1 #
+$LaDIV2:
+ ADDL r5,r5,r5 # left shift logical r5 get the '1' into the Carry
+ ADDLC r3,r3,r3 # Move that bit into the Mod register
+ rSUBL r31,r6,r3 # Try to subtract (r30 a r6)
+ BEALLTi r31,$LaMOD_TOO_SMALL
+ ORL r3,r0,r31 # Move the r31 to mod since the result was positive
+ ADDLIK r30,r30,1
+$LaMOD_TOO_SMALL:
+ ADDLIK r29,r29,-1
+ BEALEQi r29,$LaLOOP_END
+ ADDL r30,r30,r30 # Shift in the '1' into div
+ BREAI $LaDIV2 # Div2
+$LaLOOP_END:
+ BEALGEI r28,$LaRETURN_HERE
+ rsubli r3,r3,0 # Negate the result
+ BREAI $LaRETURN_HERE
+$LaDiv_By_Zero:
+$LaResult_Is_Zero:
+ orl r3,r0,r0 # set result to 0 [Both mod as well as div are 0]
+$LaRETURN_HERE:
+# Restore values of CSRs and that of r3 and the divisor and the dividend
+ lli r28,r1,0
+ lli r29,r1,8
+ lli r30,r1,16
+ lli r31,r1,24
+ addlik r1,r1,32
+ rtsd r15,8
+ nop
+ .end __moddi3
+ .size __moddi3, . - __moddi3
+#endif
diff --git a/libgcc/config/microblaze/muldi3.S b/libgcc/config/microblaze/muldi3.S
new file mode 100644
index 00000000000..567784197d3
--- /dev/null
+++ b/libgcc/config/microblaze/muldi3.S
@@ -0,0 +1,73 @@
+/*###################################-*-asm*-
+#
+# Copyright (C) 2009-2017 Free Software Foundation, Inc.
+#
+# Contributed by Michael Eager <eager@eagercon.com>.
+#
+# This file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the
+# Free Software Foundation; either version 3, or (at your option) any
+# later version.
+#
+# GCC is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+# License for more details.
+#
+# Under Section 7 of GPL version 3, you are granted additional
+# permissions described in the GCC Runtime Library Exception, version
+# 3.1, as published by the Free Software Foundation.
+#
+# You should have received a copy of the GNU General Public License and
+# a copy of the GCC Runtime Library Exception along with this program;
+# see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+# <http://www.gnu.org/licenses/>.
+#
+# muldi3.S
+#
+# Multiply operation for 32 bit integers.
+# Input : Operand1 in Reg r5
+# Operand2 in Reg r6
+# Output: Result [op1 * op2] in Reg r3
+#
+#######################################*/
+
+#ifdef __arch64__
+ .globl __muldi3
+ .ent __muldi3
+ .type __muldi3,@function
+__muldi3:
+ .frame r1,0,r15
+ addl r3,r0,r0
+ BEALEQI r5,$L_Result_Is_Zero # Multiply by Zero
+ BEALEQI r6,$L_Result_Is_Zero # Multiply by Zero
+ XORL r4,r5,r6 # Get the sign of the result
+ BEALGEI r5,$L_R5_Pos
+ RSUBLI r5,r5,0 # Make r5 positive
+$L_R5_Pos:
+ BEALGEI r6,$L_R6_Pos
+ RSUBLI r6,r6,0 # Make r6 positive
+$L_R6_Pos:
+ breai $L1
+$L2:
+ addl r5,r5,r5
+$L1:
+ srll r6,r6
+ addlc r7,r0,r0
+ bealeqi r7,$L2
+ addl r3,r3,r5
+ bealnei r6,$L2
+ beallti r4,$L_NegateResult
+ rtsd r15,8
+ nop
+$L_NegateResult:
+ rsubl r3,r3,r0
+ rtsd r15,8
+ nop
+$L_Result_Is_Zero:
+ addli r3,r0,0
+ rtsd r15,8
+ nop
+ .end __muldi3
+ .size __muldi3, . - __muldi3
+#endif
diff --git a/libgcc/config/microblaze/t-microblaze b/libgcc/config/microblaze/t-microblaze
index 8d954a49575..35021b24b7d 100644
--- a/libgcc/config/microblaze/t-microblaze
+++ b/libgcc/config/microblaze/t-microblaze
@@ -1,11 +1,16 @@
-LIB2FUNCS_EXCLUDE += _divsi3 _modsi3 _mulsi3 _udivsi3 _umodsi3
+LIB2FUNCS_EXCLUDE += _divsi3 _modsi3 _mulsi3 _udivsi3 _umodsi3 \
+ _divdi3 _moddi3 _muldi3 _udivdi3 _umoddi3
LIB2ADD += \
$(srcdir)/config/microblaze/divsi3.S \
+ $(srcdir)/config/microblaze/divdi3.S \
$(srcdir)/config/microblaze/modsi3.S \
- $(srcdir)/config/microblaze/muldi3_hard.S \
+ $(srcdir)/config/microblaze/moddi3.S \
$(srcdir)/config/microblaze/mulsi3.S \
+ $(srcdir)/config/microblaze/muldi3.S \
$(srcdir)/config/microblaze/stack_overflow_exit.S \
$(srcdir)/config/microblaze/udivsi3.S \
+ $(srcdir)/config/microblaze/udivdi3.S \
$(srcdir)/config/microblaze/umodsi3.S \
- $(srcdir)/config/microblaze/divsi3_table.c
+ $(srcdir)/config/microblaze/umoddi3.S \
+ $(srcdir)/config/microblaze/divsi3_table.c \
diff --git a/libgcc/config/microblaze/udivdi3.S b/libgcc/config/microblaze/udivdi3.S
new file mode 100644
index 00000000000..c210fbc7128
--- /dev/null
+++ b/libgcc/config/microblaze/udivdi3.S
@@ -0,0 +1,107 @@
+###################################-
+#
+# Copyright (C) 2009-2017 Free Software Foundation, Inc.
+#
+# Contributed by Michael Eager <eager@eagercon.com>.
+#
+# This file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the
+# Free Software Foundation; either version 3, or (at your option) any
+# later version.
+#
+# GCC is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+# License for more details.
+#
+# Under Section 7 of GPL version 3, you are granted additional
+# permissions described in the GCC Runtime Library Exception, version
+# 3.1, as published by the Free Software Foundation.
+#
+# You should have received a copy of the GNU General Public License and
+# a copy of the GCC Runtime Library Exception along with this program;
+# see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+# <http://www.gnu.org/licenses/>.
+#
+# udivdi3.S
+#
+# Unsigned divide operation.
+# Input : Divisor in Reg r5
+# Dividend in Reg r6
+# Output: Result in Reg r3
+#
+#######################################
+
+#ifdef __arch64__
+ .globl __udivdi3
+ .ent __udivdi3
+ .type __udivdi3,@function
+__udivdi3:
+ .frame r1,0,r15
+
+ ADDlIK r1,r1,-24
+ SLI r29,r1,0
+ SLI r30,r1,8
+ SLI r31,r1,16
+
+ BEALEQI r6,$LaDiv_By_Zero # Div_by_Zero # Division Error
+ ADDLIK r30,r0,0 # Clear mod
+ BEALEQI r5,$LaResult_Is_Zero # Result is Zero
+ ADDLIK r29,r0,64 # Initialize the loop count
+
+ # Check if r6 and r5 are equal # if yes, return 1
+ RSUBL r18,r5,r6
+ ADDLIK r3,r0,1
+ BEALEQI r18,$LaRETURN_HERE
+
+ # Check if (uns)r6 is greater than (uns)r5. In that case, just return 0
+ XORL r18,r5,r6
+ ADDL r3,r0,r0 # We would anyways clear r3
+ BEALGEI r18,$LRSUBL
+ BEALLTI r6,$LaRETURN_HERE # r6[bit 31 = 1] hence is greater
+ BREAI $LCheckr6
+$LRSUBL:
+ RSUBL r18,r6,r5 # MICROBLAZEcmp
+ BEALLTI r18,$LaRETURN_HERE
+
+ # If r6 [bit 31] is set, then return result as 1
+$LCheckr6:
+ BEALGTI r6,$LaDIV0
+ ADDLIK r3,r0,1
+ BREAI $LaRETURN_HERE
+
+ # First part try to find the first '1' in the r5
+$LaDIV0:
+ BEALLTI r5,$LaDIV2
+$LaDIV1:
+ ADDL r5,r5,r5 # left shift logical r5
+ ADDLIK r29,r29,-1
+ BEALGTI r5,$LaDIV1
+$LaDIV2:
+ ADDL r5,r5,r5 # left shift logical r5 get the '1' into the Carry
+ ADDLC r30,r30,r30 # Move that bit into the Mod register
+ RSUBL r31,r6,r30 # Try to subtract (r30 a r6)
+ BEALLTI r31,$LaMOD_TOO_SMALL
+ ORL r30,r0,r31 # Move the r31 to mod since the result was positive
+ ADDLIK r3,r3,1
+$LaMOD_TOO_SMALL:
+ ADDLIK r29,r29,-1
+ BEALEQi r29,$LaLOOP_END
+ ADDL r3,r3,r3 # Shift in the '1' into div
+ BREAI $LaDIV2 # Div2
+$LaLOOP_END:
+ BREAI $LaRETURN_HERE
+$LaDiv_By_Zero:
+$LaResult_Is_Zero:
+ ORL r3,r0,r0 # set result to 0
+$LaRETURN_HERE:
+ # Restore values of CSRs and that of r3 and the divisor and the dividend
+ LLI r29,r1,0
+ LLI r30,r1,8
+ LLI r31,r1,16
+ ADDLIK r1,r1,24
+ RTSD r15,8
+ NOP
+ .end __udivdi3
+ .size __udivdi3, . - __udivdi3
+#endif
diff --git a/libgcc/config/microblaze/umoddi3.S b/libgcc/config/microblaze/umoddi3.S
new file mode 100644
index 00000000000..7f5cd23f9a1
--- /dev/null
+++ b/libgcc/config/microblaze/umoddi3.S
@@ -0,0 +1,110 @@
+###################################
+#
+# Copyright (C) 2009-2017 Free Software Foundation, Inc.
+#
+# Contributed by Michael Eager <eager@eagercon.com>.
+#
+# This file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the
+# Free Software Foundation; either version 3, or (at your option) any
+# later version.
+#
+# GCC is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+# License for more details.
+#
+# Under Section 7 of GPL version 3, you are granted additional
+# permissions described in the GCC Runtime Library Exception, version
+# 3.1, as published by the Free Software Foundation.
+#
+# You should have received a copy of the GNU General Public License and
+# a copy of the GCC Runtime Library Exception along with this program;
+# see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+# <http://www.gnu.org/licenses/>.
+#
+# umoddi3.S
+#
+# Unsigned modulo operation for 32 bit integers.
+# Input : op1 in Reg r5
+# op2 in Reg r6
+# Output: op1 mod op2 in Reg r3
+#
+#######################################
+
+#ifdef __arch64__
+ .globl __umoddi3
+ .ent __umoddi3
+ .type __umoddi3,@function
+__umoddi3:
+ .frame r1,0,r15
+
+ addlik r1,r1,-24
+ sli r29,r1,0
+ sli r30,r1,8
+ sli r31,r1,16
+
+ BEALEQI r6,$LaDiv_By_Zero # Div_by_Zero # Division Error
+ ADDLIK r3,r0,0 # Clear div
+ BEALEQI r5,$LaResult_Is_Zero # Result is Zero
+ ADDLIK r30,r0,0 # clear mod
+ ADDLIK r29,r0,64 # Initialize the loop count
+
+# Check if r6 and r5 are equal # if yes, return 0
+ rsubl r18,r5,r6
+ bealeqi r18,$LaRETURN_HERE
+
+# Check if (uns)r6 is greater than (uns)r5. In that case, just return r5
+ xorl r18,r5,r6
+ addlik r3,r5,0
+ bealgei r18,$LRSUB
+ beallti r6,$LaRETURN_HERE
+ breai $LCheckr6
+$LRSUB:
+ rsubl r18,r5,r6 # MICROBLAZEcmp
+ bealgti r18,$LaRETURN_HERE
+
+# If r6 [bit 31] is set, then return result as r5-r6
+$LCheckr6:
+ addlik r3,r0,0
+ bealgti r6,$LaDIV0
+ addlik r18,r0,0x7fffffff
+ andl r5,r5,r18
+ andl r6,r6,r18
+ breaid $LaRETURN_HERE
+ rsubl r3,r6,r5
+# First part: try to find the first '1' in the r5
+$LaDIV0:
+ BEALLTI r5,$LaDIV2
+$LaDIV1:
+ ADDL r5,r5,r5 # left shift logical r5
+ ADDLIK r29,r29,-1
+ BEALGEI r5,$LaDIV1 #
+$LaDIV2:
+ ADDL r5,r5,r5 # left shift logical r5 get the '1' into the Carry
+ ADDLC r3,r3,r3 # Move that bit into the Mod register
+ rSUBL r31,r6,r3 # Try to subtract (r3 a r6)
+ BEALLTi r31,$LaMOD_TOO_SMALL
+ ORL r3,r0,r31 # Move the r31 to mod since the result was positive
+ ADDLIK r30,r30,1
+$LaMOD_TOO_SMALL:
+ ADDLIK r29,r29,-1
+ BEALEQi r29,$LaLOOP_END
+ ADDL r30,r30,r30 # Shift in the '1' into div
+ BREAI $LaDIV2 # Div2
+$LaLOOP_END:
+ BREAI $LaRETURN_HERE
+$LaDiv_By_Zero:
+$LaResult_Is_Zero:
+ orl r3,r0,r0 # set result to 0
+$LaRETURN_HERE:
+# Restore values of CSRs and that of r3 and the divisor and the dividend
+ lli r29,r1,0
+ lli r30,r1,8
+ lli r31,r1,16
+ addlik r1,r1,24
+ rtsd r15,8
+ nop
+.end __umoddi3
+ .size __umoddi3, . - __umoddi3
+#endif
--
2.17.1