aboutsummaryrefslogtreecommitdiff
path: root/gas/config
diff options
context:
space:
mode:
authorMaciej W. Rozycki <macro@linux-mips.org>2011-02-28 15:52:26 +0000
committerMaciej W. Rozycki <macro@linux-mips.org>2011-02-28 15:52:26 +0000
commit66b3e8dabc2c61facd835c97aa64dccde687d85d (patch)
tree2d58ff5d8e586239a86936496658fe08c418638f /gas/config
parentce70d90a3e5e00fd49b46164a43e3dfbcf1cf404 (diff)
downloadgdb-66b3e8dabc2c61facd835c97aa64dccde687d85d.zip
gdb-66b3e8dabc2c61facd835c97aa64dccde687d85d.tar.gz
gdb-66b3e8dabc2c61facd835c97aa64dccde687d85d.tar.bz2
gas/
* config/tc-mips.c (RELAX_BRANCH_ENCODE): Encode the temporary register to use. (RELAX_BRANCH_UNCOND): Adjust accordingly. (RELAX_BRANCH_LIKELY): Likewise. (RELAX_BRANCH_LINK): Likewise. (RELAX_BRANCH_TOOFAR): Likewise. (RELAX_BRANCH_AT): New macro. (append_insn): Encode the temporary register to use in standard MIPS branch relaxation. (relaxed_branch_length): Update according to changes to RELAX_BRANCH_ENCODE. (md_convert_frag): Use the encoded register as the temporary. gas/testsuite/ * gas/mips/relax-at.d: New test for branch relaxation with .set at. * gas/mips/relax.s: Update to support the new test. * gas/mips/relax.l: Update accordingly. * gas/mips/relax.d: Update for multi-arch invocation. * gas/mips/mips.exp: Run the new test. Adjust to run "relax" across all applicable architectures.
Diffstat (limited to 'gas/config')
-rw-r--r--gas/config/tc-mips.c43
1 files changed, 26 insertions, 17 deletions
diff --git a/gas/config/tc-mips.c b/gas/config/tc-mips.c
index 897ed0f..9450ddd 100644
--- a/gas/config/tc-mips.c
+++ b/gas/config/tc-mips.c
@@ -918,18 +918,20 @@ static int mips_relax_branch;
but it's not clear that it would actually improve performance. */
-#define RELAX_BRANCH_ENCODE(uncond, likely, link, toofar) \
- ((relax_substateT) \
- (0xc0000000 \
- | ((toofar) ? 1 : 0) \
- | ((link) ? 2 : 0) \
- | ((likely) ? 4 : 0) \
- | ((uncond) ? 8 : 0)))
+#define RELAX_BRANCH_ENCODE(at, uncond, likely, link, toofar) \
+ ((relax_substateT) \
+ (0xc0000000 \
+ | ((at) & 0x1f) \
+ | ((toofar) ? 0x20 : 0) \
+ | ((link) ? 0x40 : 0) \
+ | ((likely) ? 0x80 : 0) \
+ | ((uncond) ? 0x100 : 0)))
#define RELAX_BRANCH_P(i) (((i) & 0xf0000000) == 0xc0000000)
-#define RELAX_BRANCH_UNCOND(i) (((i) & 8) != 0)
-#define RELAX_BRANCH_LIKELY(i) (((i) & 4) != 0)
-#define RELAX_BRANCH_LINK(i) (((i) & 2) != 0)
-#define RELAX_BRANCH_TOOFAR(i) (((i) & 1) != 0)
+#define RELAX_BRANCH_UNCOND(i) (((i) & 0x100) != 0)
+#define RELAX_BRANCH_LIKELY(i) (((i) & 0x80) != 0)
+#define RELAX_BRANCH_LINK(i) (((i) & 0x40) != 0)
+#define RELAX_BRANCH_TOOFAR(i) (((i) & 0x20) != 0)
+#define RELAX_BRANCH_AT(i) ((i) & 0x1f)
/* For mips16 code, we use an entirely different form of relaxation.
mips16 supports two versions of most instructions which take
@@ -2940,7 +2942,8 @@ append_insn (struct mips_cl_insn *ip, expressionS *address_expr,
: (pinfo & INSN_COND_BRANCH_LIKELY) ? 1
: 0)), 4,
RELAX_BRANCH_ENCODE
- (pinfo & INSN_UNCOND_BRANCH_DELAY,
+ (AT,
+ pinfo & INSN_UNCOND_BRANCH_DELAY,
pinfo & INSN_COND_BRANCH_LIKELY,
pinfo & INSN_WRITE_GPR_31,
0),
@@ -14145,7 +14148,8 @@ relaxed_branch_length (fragS *fragp, asection *sec, int update)
if (fragp && update && toofar != RELAX_BRANCH_TOOFAR (fragp->fr_subtype))
fragp->fr_subtype
- = RELAX_BRANCH_ENCODE (RELAX_BRANCH_UNCOND (fragp->fr_subtype),
+ = RELAX_BRANCH_ENCODE (RELAX_BRANCH_AT (fragp->fr_subtype),
+ RELAX_BRANCH_UNCOND (fragp->fr_subtype),
RELAX_BRANCH_LIKELY (fragp->fr_subtype),
RELAX_BRANCH_LINK (fragp->fr_subtype),
toofar);
@@ -14555,8 +14559,11 @@ md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED, segT asec, fragS *fragp)
}
else
{
+ unsigned long at = RELAX_BRANCH_AT (fragp->fr_subtype);
+
/* lw/ld $at, <sym>($gp) R_MIPS_GOT16 */
- insn = HAVE_64BIT_ADDRESSES ? 0xdf810000 : 0x8f810000;
+ insn = HAVE_64BIT_ADDRESSES ? 0xdf800000 : 0x8f800000;
+ insn |= at << OP_SH_RT;
exp.X_op = O_symbol;
exp.X_add_symbol = fragp->fr_symbol;
exp.X_add_number = fragp->fr_offset;
@@ -14583,7 +14590,8 @@ md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED, segT asec, fragS *fragp)
}
/* d/addiu $at, $at, <sym> R_MIPS_LO16 */
- insn = HAVE_64BIT_ADDRESSES ? 0x64210000 : 0x24210000;
+ insn = HAVE_64BIT_ADDRESSES ? 0x64000000 : 0x24000000;
+ insn |= at << OP_SH_RS | at << OP_SH_RT;
fixp = fix_new_exp (fragp, buf - (bfd_byte *)fragp->fr_literal,
4, &exp, FALSE, BFD_RELOC_LO16);
@@ -14595,9 +14603,10 @@ md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED, segT asec, fragS *fragp)
/* j(al)r $at. */
if (RELAX_BRANCH_LINK (fragp->fr_subtype))
- insn = 0x0020f809;
+ insn = 0x0000f809;
else
- insn = 0x00200008;
+ insn = 0x00000008;
+ insn |= at << OP_SH_RS;
md_number_to_chars ((char *) buf, insn, 4);
buf += 4;