aboutsummaryrefslogtreecommitdiff
path: root/gas
diff options
context:
space:
mode:
Diffstat (limited to 'gas')
-rw-r--r--gas/ChangeLog9
-rw-r--r--gas/config/tc-spu.c165
2 files changed, 123 insertions, 51 deletions
diff --git a/gas/ChangeLog b/gas/ChangeLog
index e544b76..819600f 100644
--- a/gas/ChangeLog
+++ b/gas/ChangeLog
@@ -1,3 +1,12 @@
+2009-01-12 Alan Modra <amodra@bigpond.net.au>
+
+ * config/tc-spu.c (md_pseudo_table): Add "brinfo".
+ (brinfo): New var.
+ (md_assemble): Poke brinfo into branch instructions.
+ (spu_brinfo): New function.
+ (md_apply_fix): Don't assume insn fields start off at zero, mask
+ them to remove possible brinfo.
+
2009-01-10 H.J. Lu <hongjiu.lu@intel.com>
* doc/c-i386.texi: Reformat.
diff --git a/gas/config/tc-spu.c b/gas/config/tc-spu.c
index e159e34..0b40a56 100644
--- a/gas/config/tc-spu.c
+++ b/gas/config/tc-spu.c
@@ -1,6 +1,6 @@
/* spu.c -- Assembler for the IBM Synergistic Processing Unit (SPU)
- Copyright 2006, 2007, 2008 Free Software Foundation, Inc.
+ Copyright 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
This file is part of GAS, the GNU Assembler.
@@ -53,6 +53,7 @@ static const char *get_reg (const char *param, struct spu_insn *insn, int arg,
int accept_expr);
static int calcop (struct spu_opcode *format, const char *param,
struct spu_insn *insn);
+static void spu_brinfo (int);
static void spu_cons (int);
extern char *myname;
@@ -82,6 +83,7 @@ const char FLT_CHARS[] = "dDfF";
const pseudo_typeS md_pseudo_table[] =
{
{"align", s_align_ptwo, 4},
+ {"brinfo", spu_brinfo, 0},
{"bss", s_lcomm_bytes, 1},
{"def", s_set, 0},
{"dfloat", float_cons, 'd'},
@@ -104,6 +106,9 @@ const pseudo_typeS md_pseudo_table[] =
{0,0,0}
};
+/* Bits plugged into branch instruction offset field. */
+unsigned int brinfo;
+
void
md_begin (void)
{
@@ -342,6 +347,16 @@ md_assemble (char *op)
as_warn (_("Treating '%-*s' as a symbol."), (int)(syntax_error_param - d), d);
}
+ if (brinfo != 0
+ && (insn.tag <= M_BRASL
+ || (insn.tag >= M_BRZ && insn.tag <= M_BRHNZ))
+ && (insn.opcode & 0x7ff80) == 0
+ && (insn.reloc_arg[0] == A_R18
+ || insn.reloc_arg[0] == A_S18
+ || insn.reloc_arg[1] == A_R18
+ || insn.reloc_arg[1] == A_S18))
+ insn.opcode |= brinfo << 7;
+
/* grow the current frag and plop in the opcode */
thisfrag = frag_more (4);
@@ -370,6 +385,9 @@ md_assemble (char *op)
fixP->tc_fix_data.insn_tag = insn.tag;
}
dwarf2_emit_insn (4);
+
+ /* .brinfo lasts exactly one instruction. */
+ brinfo = 0;
}
static int
@@ -752,6 +770,39 @@ md_create_long_jump (char *ptr,
}
#endif
+/* Handle .brinfo <priority>,<lrlive>. */
+static void
+spu_brinfo (int ignore ATTRIBUTE_UNUSED)
+{
+ addressT priority;
+ addressT lrlive;
+
+ priority = get_absolute_expression ();
+ SKIP_WHITESPACE ();
+
+ lrlive = 0;
+ if (*input_line_pointer == ',')
+ {
+ ++input_line_pointer;
+ lrlive = get_absolute_expression ();
+ }
+
+ if (priority > 0x1fff)
+ {
+ as_bad (_("invalid priority '%lu'"), (unsigned long) priority);
+ priority = 0;
+ }
+
+ if (lrlive > 7)
+ {
+ as_bad (_("invalid lrlive '%lu'"), (unsigned long) lrlive);
+ lrlive = 0;
+ }
+
+ brinfo = (lrlive << 13) | priority;
+ demand_empty_rest_of_line ();
+}
+
/* Support @ppu on symbols referenced in .int/.long/.word/.quad. */
static void
spu_cons (int nbytes)
@@ -898,6 +949,7 @@ void
md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
{
unsigned int res;
+ unsigned int mask;
valueT val = *valP;
char *place = fixP->fx_where + fixP->fx_frag->fr_literal;
@@ -944,6 +996,7 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
{
fixP->fx_done = 1;
res = 0;
+ mask = 0;
if (fixP->tc_fix_data.arg_format > A_P)
{
int hi = arg_encode[fixP->tc_fix_data.arg_format].hi;
@@ -955,84 +1008,94 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
}
switch (fixP->fx_r_type)
- {
- case BFD_RELOC_8:
+ {
+ case BFD_RELOC_8:
md_number_to_chars (place, val, 1);
return;
- case BFD_RELOC_16:
+ case BFD_RELOC_16:
md_number_to_chars (place, val, 2);
return;
- case BFD_RELOC_32:
+ case BFD_RELOC_32:
case BFD_RELOC_32_PCREL:
md_number_to_chars (place, val, 4);
return;
- case BFD_RELOC_64:
+ case BFD_RELOC_64:
md_number_to_chars (place, val, 8);
return;
- case BFD_RELOC_SPU_IMM7:
- res = (val & 0x7f) << 14;
- break;
+ case BFD_RELOC_SPU_IMM7:
+ res = val << 14;
+ mask = 0x7f << 14;
+ break;
- case BFD_RELOC_SPU_IMM8:
- res = (val & 0xff) << 14;
- break;
+ case BFD_RELOC_SPU_IMM8:
+ res = val << 14;
+ mask = 0xff << 14;
+ break;
- case BFD_RELOC_SPU_IMM10:
- res = (val & 0x3ff) << 14;
- break;
+ case BFD_RELOC_SPU_IMM10:
+ res = val << 14;
+ mask = 0x3ff << 14;
+ break;
- case BFD_RELOC_SPU_IMM10W:
- res = (val & 0x3ff0) << 10;
- break;
+ case BFD_RELOC_SPU_IMM10W:
+ res = val << 10;
+ mask = 0x3ff0 << 10;
+ break;
- case BFD_RELOC_SPU_IMM16:
- res = (val & 0xffff) << 7;
- break;
+ case BFD_RELOC_SPU_IMM16:
+ res = val << 7;
+ mask = 0xffff << 7;
+ break;
- case BFD_RELOC_SPU_IMM16W:
- res = (val & 0x3fffc) << 5;
- break;
+ case BFD_RELOC_SPU_IMM16W:
+ res = val << 5;
+ mask = 0x3fffc << 5;
+ break;
- case BFD_RELOC_SPU_IMM18:
- res = (val & 0x3ffff) << 7;
- break;
+ case BFD_RELOC_SPU_IMM18:
+ res = val << 7;
+ mask = 0x3ffff << 7;
+ break;
- case BFD_RELOC_SPU_PCREL9a:
- res = ((val & 0x1fc) >> 2) | ((val & 0x600) << 14);
- break;
+ case BFD_RELOC_SPU_PCREL9a:
+ res = ((val & 0x1fc) >> 2) | ((val & 0x600) << 14);
+ mask = (0x1fc >> 2) | (0x600 << 14);
+ break;
- case BFD_RELOC_SPU_PCREL9b:
- res = ((val & 0x1fc) >> 2) | ((val & 0x600) << 5);
- break;
+ case BFD_RELOC_SPU_PCREL9b:
+ res = ((val & 0x1fc) >> 2) | ((val & 0x600) << 5);
+ mask = (0x1fc >> 2) | (0x600 << 5);
+ break;
- case BFD_RELOC_SPU_PCREL16:
- res = (val & 0x3fffc) << 5;
- break;
+ case BFD_RELOC_SPU_PCREL16:
+ res = val << 5;
+ mask = 0x3fffc << 5;
+ break;
case BFD_RELOC_SPU_HI16:
- res = (val >> 9) & 0x7fff80;
+ res = val >> 9;
+ mask = 0xffff << 7;
break;
case BFD_RELOC_SPU_LO16:
- res = (val << 7) & 0x7fff80;
+ res = val << 7;
+ mask = 0xffff << 7;
break;
- default:
- as_bad_where (fixP->fx_file, fixP->fx_line,
- _("reloc %d not supported by object file format"),
- (int) fixP->fx_r_type);
- }
-
- if (res != 0)
- {
- place[0] |= (res >> 24) & 0xff;
- place[1] |= (res >> 16) & 0xff;
- place[2] |= (res >> 8) & 0xff;
- place[3] |= (res) & 0xff;
- }
+ default:
+ as_bad_where (fixP->fx_file, fixP->fx_line,
+ _("reloc %d not supported by object file format"),
+ (int) fixP->fx_r_type);
+ }
+
+ res &= mask;
+ place[0] = (place[0] & (~mask >> 24)) | ((res >> 24) & 0xff);
+ place[1] = (place[1] & (~mask >> 16)) | ((res >> 16) & 0xff);
+ place[2] = (place[2] & (~mask >> 8)) | ((res >> 8) & 0xff);
+ place[3] = (place[3] & ~mask) | (res & 0xff);
}
}