toolchain-mipsel/patches/010_binutils-2.13.2.1-broad...

334 lines
12 KiB
Diff

diff -uNrbB binutils-2.13.2.1/gas/as.c binutils/gas/as.c
--- binutils-2.13.2.1/gas/as.c 2002-12-20 22:19:05.000000000 +0100
+++ binutils/gas/as.c 2004-03-31 22:47:52.000000000 +0200
@@ -212,6 +212,7 @@
#else
fprintf (stderr, _("GNU assembler version %s (%s)"), VERSION, TARGET_ALIAS);
#endif
+ fprintf (stderr, _(" with Broadcom modifications"));
fprintf (stderr, "\n");
}
@@ -529,10 +530,11 @@
case OPTION_VERSION:
/* This output is intended to follow the GNU standards document. */
#ifdef BFD_ASSEMBLER
- printf (_("GNU assembler %s\n"), BFD_VERSION_STRING);
+ printf (_("GNU assembler %s"), BFD_VERSION_STRING);
#else
- printf (_("GNU assembler %s\n"), VERSION);
+ printf (_("GNU assembler %s"), VERSION);
#endif
+ printf (_(" with Broadcom modifications\n"));
printf (_("Copyright 2002 Free Software Foundation, Inc.\n"));
printf (_("\
This program is free software; you may redistribute it under the terms of\n\
diff -uNrbB binutils-2.13.2.1/gas/config/tc-mips.c binutils/gas/config/tc-mips.c
--- binutils-2.13.2.1/gas/config/tc-mips.c 2002-11-05 23:03:40.000000000 +0100
+++ binutils/gas/config/tc-mips.c 2004-03-31 22:47:54.000000000 +0200
@@ -106,6 +106,13 @@
extern int target_big_endian;
+/* WA_BCM4710A0 */
+#if BCM4710A0
+static int wa_bcm4710a0 = 1;
+#else
+#define wa_bcm4710a0 0
+#endif
+
/* The name of the readonly data section. */
#define RDATA_SECTION_NAME (OUTPUT_FLAVOR == bfd_target_aout_flavour \
? ".data" \
@@ -2130,6 +2137,8 @@
|| (pinfo & INSN_COND_BRANCH_DELAY))
{
if (mips_optimize < 2
+ /* WA_BCM4710A0: Shortcut the whole conditional and always add nops */
+ || wa_bcm4710a0 == 1
/* If we have seen .set volatile or .set nomove, don't
optimize. */
|| mips_opts.nomove != 0
@@ -2342,6 +2351,11 @@
instruction at the destination, put it in the delay
slot, and bump the destination address. */
emit_nop ();
+
+ /* WA_BCM4710A0: Add another nop */
+ if (wa_bcm4710a0)
+ emit_nop ();
+
/* Update the previous insn information. */
prev_prev_insn = *ip;
prev_insn.insn_mo = &dummy_opcode;
@@ -2456,6 +2470,11 @@
into the delay slot, and increment the branch to jump to
the next instruction. */
emit_nop ();
+
+ /* WA_BCM4710A0: Add another nop */
+ if (wa_bcm4710a0)
+ emit_nop ();
+
/* Update the previous insn information. */
prev_prev_insn = *ip;
prev_insn.insn_mo = &dummy_opcode;
@@ -2500,6 +2519,167 @@
}
else if (place == NULL)
{
+ if(wa_bcm4710a0) {
+ /* We took care above of adding noops when reordering, now
+ need to do the same when not reordering. Unless this
+ is already a nop.
+ This means swapping the insn in the delay slot with the
+ jump and adding the nops. */
+
+#define MIPS_INSN_MOVE 0x00000021
+#define MIPS_INSN_MOVE2 0x00000025
+#define GLIBC_SET_GP 0x04100000
+
+ if (prev_pinfo & (INSN_UNCOND_BRANCH_DELAY | INSN_COND_BRANCH_DELAY | INSN_COND_BRANCH_LIKELY)) {
+
+ /* Special case for glibc SET_GP macro */
+ if (prev_insn.insn_opcode == GLIBC_SET_GP) {
+ as_warn (_("bcm4710a0: NOT adding nop to glibc SET_GP macro (0x%lx %s)"),
+ prev_insn.insn_opcode, prev_insn.insn_mo->name);
+ goto skip_nop;
+ }
+
+ /* If it is a nop or just a move, let it go. XXX: we should add a flag to
+ pinfo to let us know which insn's are ok, i.e. they don't
+ cause any stalls. */
+ if ((ip->insn_opcode != 0)
+ && ((ip->insn_opcode & ip->insn_mo->mask) != MIPS_INSN_MOVE)
+ && ((ip->insn_opcode & ip->insn_mo->mask) != MIPS_INSN_MOVE2)) {
+
+ int wreg = 0, wrsh = 0, rs = 0, rt = 0;
+ unsigned long wrmsk = 0, temp;
+ char *prev_f;
+
+ /* Bad case: we cannot move a trap */
+ if (pinfo & INSN_TRAP) {
+ as_warn (_("bcm4710a0: Current insn (%s) is a trap, cannot swap with %s"),
+ ip->insn_mo->name, prev_insn.insn_mo->name);
+ goto skip_swap;
+ }
+
+ /* Another bad case: we cannot move stuff after a branch likely */
+ if (pinfo & INSN_COND_BRANCH_LIKELY) {
+ as_warn (_("bcm4710a0: Current insn (%s) cannot be swaped with branch likely %s"),
+ ip->insn_mo->name, prev_insn.insn_mo->name);
+ goto skip_swap;
+ }
+ /* Also, we cannot move if there is a cc conflict */
+ if ((pinfo & INSN_WRITE_COND_CODE) && (prev_pinfo & INSN_READ_COND_CODE)) {
+ as_warn (_("bcm4710a0: Current insn (%s) writes CC, cannot swap with %s which reads CC"),
+ ip->insn_mo->name, prev_insn.insn_mo->name);
+ goto skip_swap;
+ }
+
+ /* or a hi conflict */
+ if ((pinfo & INSN_WRITE_HI) && (prev_pinfo & INSN_READ_HI)) {
+ as_warn (_("bcm4710a0: Current insn (%s) writes HI, cannot swap with %s which reads HI"),
+ ip->insn_mo->name, prev_insn.insn_mo->name);
+ goto skip_swap;
+ }
+
+ /* or a lo conflict */
+ if ((pinfo & INSN_WRITE_LO) && (prev_pinfo & INSN_READ_LO)) {
+ as_warn (_("bcm4710a0: Current insn (%s) writes LO, cannot swap with %s which reads LO"),
+ ip->insn_mo->name, prev_insn.insn_mo->name);
+ goto skip_swap;
+ }
+
+ /* Which register if any is modified by the current insn? */
+ if (pinfo & INSN_WRITE_GPR_D) {
+ wreg = (ip->insn_opcode >> OP_SH_RD) & OP_MASK_RD;
+ wrsh = OP_SH_RD;
+ wrmsk = OP_MASK_RD;
+ } else if (pinfo & INSN_WRITE_GPR_T) {
+ wreg = (ip->insn_opcode >> OP_SH_RT) & OP_MASK_RT;
+ wrsh = OP_SH_RT;
+ wrmsk = OP_MASK_RT;
+ } else if (pinfo & INSN_WRITE_GPR_31)
+ wreg = RA;
+
+ if (wreg) {
+ /* Is that reg used by the previous insn? */
+ if (prev_pinfo & INSN_READ_GPR_S)
+ rs = (prev_insn.insn_opcode >> OP_SH_RS) & OP_MASK_RS;
+ if (prev_pinfo & INSN_READ_GPR_T)
+ rt = (prev_insn.insn_opcode >> OP_SH_RT) & OP_MASK_RT;
+ if ((wreg != rs) && (wreg != rt)) {
+ /* Nope, We *can* do the swap */
+ wreg = 0;
+ } else {
+ /* Cannot swap without some more surgery,
+ but do not swap at all if it is $at */
+ if (wreg == AT) {
+ as_warn (_("bcm4710a0: Current insn (%s) uses reg%d, cannot swap with %s"),
+ ip->insn_mo->name, wreg, prev_insn.insn_mo->name);
+ goto skip_swap;
+ }
+ /* or if $at is not avaliable */
+ if (mips_opts.noat) {
+ as_warn (_("bcm4710a0: .set noat in effect, cannot swap %s with %s"),
+ ip->insn_mo->name, prev_insn.insn_mo->name);
+ goto skip_swap;
+ }
+ }
+ }
+
+ /* Swap the previous insn (a jump) and the current one */
+ assert (prev_insn_frag != NULL);
+ prev_f = prev_insn_frag->fr_literal + prev_insn_where;
+ memcpy (&temp, f, 4);
+ if (wreg) {
+ /* Modify the instruction to use at */
+ temp = (temp & ~(wrmsk << wrsh)) | (AT << wrsh);
+ }
+ memcpy (f, prev_f, 4);
+ memcpy (prev_f, &temp, 4);
+ if (prev_insn_fixp[0]) {
+ prev_insn_fixp[0]->fx_frag = frag_now;
+ prev_insn_fixp[0]->fx_where = f - frag_now->fr_literal;
+ }
+ if (prev_insn_fixp[1]) {
+ prev_insn_fixp[1]->fx_frag = frag_now;
+ prev_insn_fixp[1]->fx_where = f - frag_now->fr_literal;
+ }
+ if (prev_insn_fixp[2]) {
+ prev_insn_fixp[2]->fx_frag = frag_now;
+ prev_insn_fixp[2]->fx_where = f - frag_now->fr_literal;
+ }
+ if (fixp[0]) {
+ fixp[0]->fx_frag = prev_insn_frag;
+ fixp[0]->fx_where = prev_insn_where;
+ }
+ if (fixp[1]) {
+ fixp[1]->fx_frag = prev_insn_frag;
+ fixp[1]->fx_where = prev_insn_where;
+ }
+ if (fixp[2]) {
+ fixp[2]->fx_frag = prev_insn_frag;
+ fixp[2]->fx_where = prev_insn_where;
+ }
+ /* Now put a nop or move after the jump ... */
+ if (wreg) {
+ /* A move if we modified the insn we moved. */
+ md_number_to_chars (frag_more (4),
+ (MIPS_INSN_MOVE | (wreg << OP_SH_RD) | (AT << OP_SH_RS)),
+ 4);
+ } else {
+ emit_nop ();
+ }
+ }
+skip_swap:
+ /* And another nop */
+ emit_nop ();
+ }
+skip_nop:
+ /* Remember stuff that is not normally remembered in the not-reordering
+ case so we can swap with next insn */
+ prev_insn_fixp[0] = fixp[0];
+ prev_insn_fixp[1] = fixp[1];
+ prev_insn_fixp[2] = fixp[2];
+ prev_insn_frag = frag_now;
+ prev_insn_where = f - frag_now->fr_literal;
+ }
+
/* We need to record a bit of information even when we are not
reordering, in order to determine the base address for mips16
PC relative relocs. */
@@ -10003,8 +10183,14 @@
{"mdmx", no_argument, NULL, OPTION_MDMX},
#define OPTION_NO_MDMX (OPTION_MD_BASE + 36)
{"no-mdmx", no_argument, NULL, OPTION_NO_MDMX},
+#define OPTION_M4710A0 (OPTION_MD_BASE + 37)
+ {"m4710a0", no_argument, NULL, OPTION_M4710A0},
+#define OPTION_NO_M4710A0 (OPTION_MD_BASE + 38)
+ {"no-m4710a0", no_argument, NULL, OPTION_NO_M4710A0},
+ {"mno-4710a0", no_argument, NULL, OPTION_NO_M4710A0},
+ {"m4710a0kern", no_argument, NULL, OPTION_NO_M4710A0},
#ifdef OBJ_ELF
-#define OPTION_ELF_BASE (OPTION_MD_BASE + 37)
+#define OPTION_ELF_BASE (OPTION_MD_BASE + 39)
#define OPTION_CALL_SHARED (OPTION_ELF_BASE + 0)
{"KPIC", no_argument, NULL, OPTION_CALL_SHARED},
{"call_shared", no_argument, NULL, OPTION_CALL_SHARED},
@@ -10213,6 +10399,16 @@
case OPTION_NO_M3900:
break;
+#if BCM4710A0
+ case OPTION_M4710A0:
+ wa_bcm4710a0 = 1;
+ break;
+
+ case OPTION_NO_M4710A0:
+ wa_bcm4710a0 = 0;
+ break;
+#endif
+
case OPTION_MDMX:
mips_opts.ase_mdmx = 1;
break;
diff -uNrbB binutils-2.13.2.1/gas/config.in binutils/gas/config.in
--- binutils-2.13.2.1/gas/config.in 2002-07-14 03:14:19.000000000 +0200
+++ binutils/gas/config.in 2004-03-31 22:47:52.000000000 +0200
@@ -271,3 +271,5 @@
/* Define if errno is not declared in system header files. */
#undef NEED_DECLARATION_ERRNO
+/* Define to 1 for BCM4710A0 compiler workarounds */
+#undef BCM4710A0
diff -uNrbB binutils-2.13.2.1/gas/configure binutils/gas/configure
--- binutils-2.13.2.1/gas/configure 2002-10-30 18:07:37.000000000 +0100
+++ binutils/gas/configure 2004-03-31 22:47:52.000000000 +0200
@@ -32,6 +32,8 @@
ac_help="$ac_help
--enable-build-warnings Enable build-time compiler warnings if gcc is used"
ac_help="$ac_help
+ --with-bcm4710a0 enable BCM4710A0 compiler workarounds"
+ac_help="$ac_help
--disable-nls do not use Native Language Support"
ac_help="$ac_help
--with-included-gettext use the GNU gettext library included here"
@@ -2936,6 +2938,18 @@
;;
esac
+# Enable BCM4710A0 compiler workarounds
+# Check whether --with-bcm4710a0 or --without-bcm4710a0 was given.
+if test "${with_bcm4710a0+set}" = set; then
+ withval="$with_bcm4710a0"
+ case "${withval}" in
+ yes) cat >> confdefs.h <<\EOF
+#define BCM4710A0 1
+EOF
+ ;;
+esac
+fi
+
# Getting this done right is going to be a bitch. Each configuration specified
# with --enable-targets=... should be checked for environment, format, cpu, and
# bfd_gas setting.
diff -uNrbB binutils-2.13.2.1/gas/configure.in binutils/gas/configure.in
--- binutils-2.13.2.1/gas/configure.in 2002-10-30 18:07:32.000000000 +0100
+++ binutils/gas/configure.in 2004-03-31 22:47:52.000000000 +0200
@@ -762,6 +762,13 @@
;;
esac
+# With BCM4710A0 compiler workarounds
+AC_ARG_WITH(bcm4710a0,
+[ --with-bcm4710a0 enable BCM4710A0 compiler workarounds],
+[case "${withval}" in
+ yes) AC_DEFINE(BCM4710A0, 1, [BCM4710A0 support?]) ;;
+esac])
+
# Getting this done right is going to be a bitch. Each configuration specified
# with --enable-targets=... should be checked for environment, format, cpu, and
# bfd_gas setting.