Home | History | Annotate | Line # | Download | only in config
tc-spu.c revision 1.1.1.4
      1      1.1     skrll /* spu.c -- Assembler for the IBM Synergistic Processing Unit (SPU)
      2      1.1     skrll 
      3  1.1.1.4  christos    Copyright (C) 2006-2016 Free Software Foundation, Inc.
      4      1.1     skrll 
      5      1.1     skrll    This file is part of GAS, the GNU Assembler.
      6      1.1     skrll 
      7      1.1     skrll    GAS is free software; you can redistribute it and/or modify
      8      1.1     skrll    it under the terms of the GNU General Public License as published by
      9      1.1     skrll    the Free Software Foundation; either version 3, or (at your option)
     10      1.1     skrll    any later version.
     11      1.1     skrll 
     12      1.1     skrll    GAS is distributed in the hope that it will be useful,
     13      1.1     skrll    but WITHOUT ANY WARRANTY; without even the implied warranty of
     14      1.1     skrll    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     15      1.1     skrll    GNU General Public License for more details.
     16      1.1     skrll 
     17      1.1     skrll    You should have received a copy of the GNU General Public License
     18      1.1     skrll    along with GAS; see the file COPYING.  If not, write to the Free
     19      1.1     skrll    Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
     20      1.1     skrll    02110-1301, USA.  */
     21      1.1     skrll 
     22      1.1     skrll #include "as.h"
     23      1.1     skrll #include "safe-ctype.h"
     24      1.1     skrll #include "subsegs.h"
     25  1.1.1.3  christos #include "dwarf2dbg.h"
     26      1.1     skrll 
     27      1.1     skrll const struct spu_opcode spu_opcodes[] = {
     28      1.1     skrll #define APUOP(TAG,MACFORMAT,OPCODE,MNEMONIC,ASMFORMAT,DEP,PIPE) \
     29  1.1.1.4  christos 	{ MACFORMAT, (OPCODE ## u) << (32-11), MNEMONIC, ASMFORMAT },
     30      1.1     skrll #define APUOPFB(TAG,MACFORMAT,OPCODE,FB,MNEMONIC,ASMFORMAT,DEP,PIPE) \
     31      1.1     skrll 	{ MACFORMAT, ((OPCODE) << (32-11)) | ((FB) << (32-18)), MNEMONIC, ASMFORMAT },
     32      1.1     skrll #include "opcode/spu-insns.h"
     33      1.1     skrll #undef APUOP
     34      1.1     skrll #undef APUOPFB
     35      1.1     skrll };
     36      1.1     skrll 
     37      1.1     skrll static const int spu_num_opcodes =
     38      1.1     skrll   sizeof (spu_opcodes) / sizeof (spu_opcodes[0]);
     39      1.1     skrll 
     40      1.1     skrll #define MAX_RELOCS 2
     41      1.1     skrll 
     42      1.1     skrll struct spu_insn
     43      1.1     skrll {
     44      1.1     skrll   unsigned int opcode;
     45      1.1     skrll   expressionS exp[MAX_RELOCS];
     46      1.1     skrll   int reloc_arg[MAX_RELOCS];
     47      1.1     skrll   bfd_reloc_code_real_type reloc[MAX_RELOCS];
     48      1.1     skrll   enum spu_insns tag;
     49      1.1     skrll };
     50      1.1     skrll 
     51      1.1     skrll static const char *get_imm (const char *param, struct spu_insn *insn, int arg);
     52      1.1     skrll static const char *get_reg (const char *param, struct spu_insn *insn, int arg,
     53      1.1     skrll 			    int accept_expr);
     54      1.1     skrll static int calcop (struct spu_opcode *format, const char *param,
     55      1.1     skrll 		   struct spu_insn *insn);
     56  1.1.1.2  christos static void spu_brinfo (int);
     57      1.1     skrll static void spu_cons (int);
     58      1.1     skrll 
     59      1.1     skrll extern char *myname;
     60      1.1     skrll static struct hash_control *op_hash = NULL;
     61      1.1     skrll 
     62      1.1     skrll /* These bits should be turned off in the first address of every segment */
     63      1.1     skrll int md_seg_align = 7;
     64      1.1     skrll 
     65      1.1     skrll /* These chars start a comment anywhere in a source file (except inside
     66      1.1     skrll    another comment */
     67      1.1     skrll const char comment_chars[] = "#";
     68      1.1     skrll 
     69      1.1     skrll /* These chars only start a comment at the beginning of a line.  */
     70      1.1     skrll const char line_comment_chars[] = "#";
     71      1.1     skrll 
     72      1.1     skrll /* gods own line continuation char */
     73      1.1     skrll const char line_separator_chars[] = ";";
     74      1.1     skrll 
     75      1.1     skrll /* Chars that can be used to separate mant from exp in floating point nums */
     76      1.1     skrll const char EXP_CHARS[] = "eE";
     77      1.1     skrll 
     78      1.1     skrll /* Chars that mean this number is a floating point constant */
     79      1.1     skrll /* as in 0f123.456 */
     80      1.1     skrll /* or    0H1.234E-12 (see exp chars above) */
     81      1.1     skrll const char FLT_CHARS[] = "dDfF";
     82      1.1     skrll 
     83      1.1     skrll const pseudo_typeS md_pseudo_table[] =
     84      1.1     skrll {
     85      1.1     skrll   {"align", s_align_ptwo, 4},
     86  1.1.1.2  christos   {"brinfo", spu_brinfo, 0},
     87      1.1     skrll   {"bss", s_lcomm_bytes, 1},
     88      1.1     skrll   {"def", s_set, 0},
     89      1.1     skrll   {"dfloat", float_cons, 'd'},
     90      1.1     skrll   {"ffloat", float_cons, 'f'},
     91      1.1     skrll   {"global", s_globl, 0},
     92      1.1     skrll   {"half", cons, 2},
     93      1.1     skrll   {"int", spu_cons, 4},
     94      1.1     skrll   {"long", spu_cons, 4},
     95      1.1     skrll   {"quad", spu_cons, 8},
     96      1.1     skrll   {"string", stringer, 8 + 1},
     97      1.1     skrll   {"word", spu_cons, 4},
     98      1.1     skrll   /* Force set to be treated as an instruction.  */
     99      1.1     skrll   {"set", NULL, 0},
    100      1.1     skrll   {".set", s_set, 0},
    101      1.1     skrll   /* Likewise for eqv.  */
    102      1.1     skrll   {"eqv", NULL, 0},
    103      1.1     skrll   {".eqv", s_set, -1},
    104      1.1     skrll   {0,0,0}
    105      1.1     skrll };
    106      1.1     skrll 
    107  1.1.1.2  christos /* Bits plugged into branch instruction offset field.  */
    108  1.1.1.2  christos unsigned int brinfo;
    109  1.1.1.2  christos 
    110      1.1     skrll void
    111      1.1     skrll md_begin (void)
    112      1.1     skrll {
    113      1.1     skrll   const char *retval = NULL;
    114      1.1     skrll   int i;
    115      1.1     skrll 
    116      1.1     skrll   /* initialize hash table */
    117      1.1     skrll 
    118      1.1     skrll   op_hash = hash_new ();
    119      1.1     skrll 
    120      1.1     skrll   /* loop until you see the end of the list */
    121      1.1     skrll 
    122      1.1     skrll   for (i = 0; i < spu_num_opcodes; i++)
    123      1.1     skrll     {
    124      1.1     skrll       /* hash each mnemonic and record its position */
    125      1.1     skrll 
    126      1.1     skrll       retval = hash_insert (op_hash, spu_opcodes[i].mnemonic,
    127      1.1     skrll 			    (void *) &spu_opcodes[i]);
    128      1.1     skrll 
    129      1.1     skrll       if (retval != NULL && strcmp (retval, "exists") != 0)
    130      1.1     skrll 	as_fatal (_("Can't hash instruction '%s':%s"),
    131      1.1     skrll 		  spu_opcodes[i].mnemonic, retval);
    132      1.1     skrll     }
    133      1.1     skrll }
    134      1.1     skrll 
    135      1.1     skrll const char *md_shortopts = "";
    137      1.1     skrll struct option md_longopts[] = {
    138      1.1     skrll #define OPTION_APUASM (OPTION_MD_BASE)
    139      1.1     skrll   {"apuasm", no_argument, NULL, OPTION_APUASM},
    140      1.1     skrll #define OPTION_DD2 (OPTION_MD_BASE+1)
    141      1.1     skrll   {"mdd2.0", no_argument, NULL, OPTION_DD2},
    142      1.1     skrll #define OPTION_DD1 (OPTION_MD_BASE+2)
    143      1.1     skrll   {"mdd1.0", no_argument, NULL, OPTION_DD1},
    144      1.1     skrll #define OPTION_DD3 (OPTION_MD_BASE+3)
    145      1.1     skrll   {"mdd3.0", no_argument, NULL, OPTION_DD3},
    146      1.1     skrll   { NULL, no_argument, NULL, 0 }
    147      1.1     skrll };
    148      1.1     skrll size_t md_longopts_size = sizeof (md_longopts);
    149      1.1     skrll 
    150      1.1     skrll /* When set (by -apuasm) our assembler emulates the behaviour of apuasm.
    151      1.1     skrll  * e.g. don't add bias to float conversion and don't right shift
    152      1.1     skrll  * immediate values. */
    153      1.1     skrll static int emulate_apuasm;
    154      1.1     skrll 
    155      1.1     skrll /* Use the dd2.0 instructions set.  The only differences are some new
    156      1.1     skrll  * register names and the orx insn */
    157      1.1     skrll static int use_dd2 = 1;
    158      1.1     skrll 
    159  1.1.1.4  christos int
    160      1.1     skrll md_parse_option (int c, const char *arg ATTRIBUTE_UNUSED)
    161      1.1     skrll {
    162      1.1     skrll   switch (c)
    163      1.1     skrll     {
    164      1.1     skrll     case OPTION_APUASM:
    165      1.1     skrll       emulate_apuasm = 1;
    166      1.1     skrll       break;
    167      1.1     skrll     case OPTION_DD3:
    168      1.1     skrll       use_dd2 = 1;
    169      1.1     skrll       break;
    170      1.1     skrll     case OPTION_DD2:
    171      1.1     skrll       use_dd2 = 1;
    172      1.1     skrll       break;
    173      1.1     skrll     case OPTION_DD1:
    174      1.1     skrll       use_dd2 = 0;
    175      1.1     skrll       break;
    176      1.1     skrll     default:
    177      1.1     skrll       return 0;
    178      1.1     skrll     }
    179      1.1     skrll   return 1;
    180      1.1     skrll }
    181      1.1     skrll 
    182      1.1     skrll void
    183      1.1     skrll md_show_usage (FILE *stream)
    184      1.1     skrll {
    185      1.1     skrll   fputs (_("\
    186      1.1     skrll SPU options:\n\
    187      1.1     skrll   --apuasm		  emulate behaviour of apuasm\n"),
    188      1.1     skrll 	stream);
    189      1.1     skrll }
    190      1.1     skrll 
    191      1.1     skrll 
    193      1.1     skrll struct arg_encode {
    194      1.1     skrll   int size;
    195      1.1     skrll   int pos;
    196      1.1     skrll   int rshift;
    197      1.1     skrll   int lo, hi;
    198      1.1     skrll   int wlo, whi;
    199      1.1     skrll   bfd_reloc_code_real_type reloc;
    200      1.1     skrll };
    201      1.1     skrll 
    202      1.1     skrll static struct arg_encode arg_encode[A_MAX] = {
    203      1.1     skrll   {  7,  0, 0,       0,    127,    0,   -1,  0 }, /* A_T */
    204      1.1     skrll   {  7,  7, 0,       0,    127,    0,   -1,  0 }, /* A_A */
    205      1.1     skrll   {  7, 14, 0,       0,    127,    0,   -1,  0 }, /* A_B */
    206      1.1     skrll   {  7, 21, 0,       0,    127,    0,   -1,  0 }, /* A_C */
    207      1.1     skrll   {  7,  7, 0,       0,    127,    0,   -1,  0 }, /* A_S */
    208      1.1     skrll   {  7,  7, 0,       0,    127,    0,   -1,  0 }, /* A_H */
    209      1.1     skrll   {  0,  0, 0,       0,     -1,    0,   -1,  0 }, /* A_P */
    210      1.1     skrll   {  7, 14, 0,       0,     -1,    0,   -1,  BFD_RELOC_SPU_IMM7 }, /* A_S3 */
    211      1.1     skrll   {  7, 14, 0,     -32,     31,  -31,    0,  BFD_RELOC_SPU_IMM7 }, /* A_S6 */
    212      1.1     skrll   {  7, 14, 0,       0,     -1,    0,   -1,  BFD_RELOC_SPU_IMM7 }, /* A_S7N */
    213      1.1     skrll   {  7, 14, 0,     -64,     63,  -63,    0,  BFD_RELOC_SPU_IMM7 }, /* A_S7 */
    214      1.1     skrll   {  8, 14, 0,       0,    127,    0,   -1,  BFD_RELOC_SPU_IMM8 }, /* A_U7A */
    215      1.1     skrll   {  8, 14, 0,       0,    127,    0,   -1,  BFD_RELOC_SPU_IMM8 }, /* A_U7B */
    216      1.1     skrll   { 10, 14, 0,    -512,    511, -128,  255,  BFD_RELOC_SPU_IMM10 }, /* A_S10B */
    217      1.1     skrll   { 10, 14, 0,    -512,    511,    0,   -1,  BFD_RELOC_SPU_IMM10 }, /* A_S10 */
    218      1.1     skrll   {  2, 23, 9,   -1024,   1023,    0,   -1,  BFD_RELOC_SPU_PCREL9a }, /* A_S11 */
    219      1.1     skrll   {  2, 14, 9,   -1024,   1023,    0,   -1,  BFD_RELOC_SPU_PCREL9b }, /* A_S11I */
    220      1.1     skrll   { 10, 14, 4,   -8192,   8191,    0,   -1,  BFD_RELOC_SPU_IMM10W }, /* A_S14 */
    221      1.1     skrll   { 16,  7, 0,  -32768,  32767,    0,   -1,  BFD_RELOC_SPU_IMM16 }, /* A_S16 */
    222      1.1     skrll   { 16,  7, 2, -131072, 262143,    0,   -1,  BFD_RELOC_SPU_IMM16W }, /* A_S18 */
    223      1.1     skrll   { 16,  7, 2, -262144, 262143,    0,   -1,  BFD_RELOC_SPU_PCREL16 }, /* A_R18 */
    224      1.1     skrll   {  7, 14, 0,       0,     -1,    0,   -1,  BFD_RELOC_SPU_IMM7 }, /* A_U3 */
    225      1.1     skrll   {  7, 14, 0,       0,    127,    0,   31,  BFD_RELOC_SPU_IMM7 }, /* A_U5 */
    226      1.1     skrll   {  7, 14, 0,       0,    127,    0,   63,  BFD_RELOC_SPU_IMM7 }, /* A_U6 */
    227      1.1     skrll   {  7, 14, 0,       0,     -1,    0,   -1,  BFD_RELOC_SPU_IMM7 }, /* A_U7 */
    228      1.1     skrll   { 14,  0, 0,       0,  16383,    0,   -1,  0 }, /* A_U14 */
    229      1.1     skrll   { 16,  7, 0,  -32768,  65535,    0,   -1,  BFD_RELOC_SPU_IMM16 }, /* A_X16 */
    230      1.1     skrll   { 18,  7, 0,       0, 262143,    0,   -1,  BFD_RELOC_SPU_IMM18 }, /* A_U18 */
    231      1.1     skrll };
    232      1.1     skrll 
    233      1.1     skrll /* Some flags for handling errors.  This is very hackish and added after
    234      1.1     skrll  * the fact. */
    235      1.1     skrll static int syntax_error_arg;
    236      1.1     skrll static const char *syntax_error_param;
    237      1.1     skrll static int syntax_reg;
    238      1.1     skrll 
    239      1.1     skrll static char *
    240      1.1     skrll insn_fmt_string (struct spu_opcode *format)
    241      1.1     skrll {
    242      1.1     skrll   static char buf[64];
    243      1.1     skrll   int len = 0;
    244      1.1     skrll   int i;
    245      1.1     skrll 
    246      1.1     skrll   len += sprintf (&buf[len], "%s\t", format->mnemonic);
    247      1.1     skrll   for (i = 1; i <= format->arg[0]; i++)
    248  1.1.1.4  christos     {
    249  1.1.1.3  christos       int arg = format->arg[i];
    250      1.1     skrll       const char *exp;
    251      1.1     skrll       if (i > 1 && arg != A_P && format->arg[i-1] != A_P)
    252      1.1     skrll 	buf[len++] =  ',';
    253      1.1     skrll       if (arg == A_P)
    254      1.1     skrll 	exp = "(";
    255  1.1.1.3  christos       else if (arg < A_P)
    256      1.1     skrll 	exp = i == syntax_error_arg ? "REG" : "reg";
    257      1.1     skrll       else
    258  1.1.1.3  christos 	exp = i == syntax_error_arg ? "IMM" : "imm";
    259      1.1     skrll       len += sprintf (&buf[len], "%s", exp);
    260      1.1     skrll       if (i > 1 && format->arg[i-1] == A_P)
    261      1.1     skrll 	buf[len++] =  ')';
    262      1.1     skrll     }
    263      1.1     skrll   buf[len] = 0;
    264      1.1     skrll   return buf;
    265      1.1     skrll }
    266      1.1     skrll 
    267      1.1     skrll void
    268      1.1     skrll md_assemble (char *op)
    269      1.1     skrll {
    270      1.1     skrll   char *param, *thisfrag;
    271      1.1     skrll   char c;
    272      1.1     skrll   struct spu_opcode *format;
    273      1.1     skrll   struct spu_insn insn;
    274  1.1.1.2  christos   int i;
    275      1.1     skrll 
    276      1.1     skrll   gas_assert (op);
    277      1.1     skrll 
    278      1.1     skrll   /* skip over instruction to find parameters */
    279      1.1     skrll 
    280      1.1     skrll   for (param = op; *param != 0 && !ISSPACE (*param); param++)
    281      1.1     skrll     ;
    282      1.1     skrll   c = *param;
    283      1.1     skrll   *param = 0;
    284      1.1     skrll 
    285      1.1     skrll   if (c != 0 && c != '\n')
    286      1.1     skrll     param++;
    287      1.1     skrll 
    288      1.1     skrll   /* try to find the instruction in the hash table */
    289      1.1     skrll 
    290      1.1     skrll   if ((format = (struct spu_opcode *) hash_find (op_hash, op)) == NULL)
    291      1.1     skrll     {
    292      1.1     skrll       as_bad (_("Invalid mnemonic '%s'"), op);
    293      1.1     skrll       return;
    294      1.1     skrll     }
    295      1.1     skrll 
    296      1.1     skrll   if (!use_dd2 && strcmp (format->mnemonic, "orx") == 0)
    297      1.1     skrll     {
    298      1.1     skrll       as_bad (_("'%s' is only available in DD2.0 or higher."), op);
    299      1.1     skrll       return;
    300      1.1     skrll     }
    301      1.1     skrll 
    302      1.1     skrll   while (1)
    303      1.1     skrll     {
    304      1.1     skrll       /* try parsing this instruction into insn */
    305      1.1     skrll       for (i = 0; i < MAX_RELOCS; i++)
    306      1.1     skrll 	{
    307      1.1     skrll 	  insn.exp[i].X_add_symbol = 0;
    308      1.1     skrll 	  insn.exp[i].X_op_symbol = 0;
    309      1.1     skrll 	  insn.exp[i].X_add_number = 0;
    310      1.1     skrll 	  insn.exp[i].X_op = O_illegal;
    311      1.1     skrll 	  insn.reloc_arg[i] = -1;
    312      1.1     skrll 	  insn.reloc[i] = BFD_RELOC_NONE;
    313      1.1     skrll 	}
    314      1.1     skrll       insn.opcode = format->opcode;
    315      1.1     skrll       insn.tag = (enum spu_insns) (format - spu_opcodes);
    316      1.1     skrll 
    317      1.1     skrll       syntax_error_arg = 0;
    318      1.1     skrll       syntax_error_param = 0;
    319      1.1     skrll       syntax_reg = 0;
    320      1.1     skrll       if (calcop (format, param, &insn))
    321      1.1     skrll 	break;
    322      1.1     skrll 
    323      1.1     skrll       /* if it doesn't parse try the next instruction */
    324      1.1     skrll       if (!strcmp (format[0].mnemonic, format[1].mnemonic))
    325      1.1     skrll 	format++;
    326      1.1     skrll       else
    327      1.1     skrll 	{
    328      1.1     skrll 	  int parg = format[0].arg[syntax_error_arg-1];
    329      1.1     skrll 
    330      1.1     skrll 	  as_fatal (_("Error in argument %d.  Expecting:  \"%s\""),
    331      1.1     skrll 		    syntax_error_arg - (parg == A_P),
    332      1.1     skrll 		    insn_fmt_string (format));
    333      1.1     skrll 	  return;
    334      1.1     skrll 	}
    335      1.1     skrll     }
    336      1.1     skrll 
    337      1.1     skrll   if ((syntax_reg & 4)
    338      1.1     skrll       && ! (insn.tag == M_RDCH
    339      1.1     skrll 	    || insn.tag == M_RCHCNT
    340      1.1     skrll 	    || insn.tag == M_WRCH))
    341      1.1     skrll     as_warn (_("Mixing register syntax, with and without '$'."));
    342      1.1     skrll   if (syntax_error_param)
    343      1.1     skrll     {
    344      1.1     skrll       const char *d = syntax_error_param;
    345      1.1     skrll       while (*d != '$')
    346      1.1     skrll 	d--;
    347      1.1     skrll       as_warn (_("Treating '%-*s' as a symbol."), (int)(syntax_error_param - d), d);
    348  1.1.1.2  christos     }
    349  1.1.1.2  christos 
    350  1.1.1.2  christos   if (brinfo != 0
    351  1.1.1.2  christos       && (insn.tag <= M_BRASL
    352  1.1.1.2  christos 	  || (insn.tag >= M_BRZ && insn.tag <= M_BRHNZ))
    353  1.1.1.2  christos       && (insn.opcode & 0x7ff80) == 0
    354  1.1.1.2  christos       && (insn.reloc_arg[0] == A_R18
    355  1.1.1.2  christos 	  || insn.reloc_arg[0] == A_S18
    356  1.1.1.2  christos 	  || insn.reloc_arg[1] == A_R18
    357  1.1.1.2  christos 	  || insn.reloc_arg[1] == A_S18))
    358      1.1     skrll     insn.opcode |= brinfo << 7;
    359      1.1     skrll 
    360      1.1     skrll   /* grow the current frag and plop in the opcode */
    361      1.1     skrll 
    362      1.1     skrll   thisfrag = frag_more (4);
    363      1.1     skrll   md_number_to_chars (thisfrag, insn.opcode, 4);
    364      1.1     skrll 
    365      1.1     skrll   /* if this instruction requires labels mark it for later */
    366  1.1.1.3  christos 
    367      1.1     skrll   for (i = 0; i < MAX_RELOCS; i++)
    368      1.1     skrll     if (insn.reloc_arg[i] >= 0)
    369      1.1     skrll       {
    370      1.1     skrll         fixS *fixP;
    371      1.1     skrll         bfd_reloc_code_real_type reloc = insn.reloc[i];
    372      1.1     skrll 	int pcrel = 0;
    373      1.1     skrll 
    374      1.1     skrll 	if (reloc == BFD_RELOC_SPU_PCREL9a
    375      1.1     skrll 	    || reloc == BFD_RELOC_SPU_PCREL9b
    376      1.1     skrll 	    || reloc == BFD_RELOC_SPU_PCREL16)
    377      1.1     skrll 	  pcrel = 1;
    378      1.1     skrll 	fixP = fix_new_exp (frag_now,
    379      1.1     skrll 			    thisfrag - frag_now->fr_literal,
    380      1.1     skrll 			    4,
    381      1.1     skrll 			    &insn.exp[i],
    382      1.1     skrll 			    pcrel,
    383      1.1     skrll 			    reloc);
    384      1.1     skrll 	fixP->tc_fix_data.arg_format = insn.reloc_arg[i];
    385      1.1     skrll 	fixP->tc_fix_data.insn_tag = insn.tag;
    386  1.1.1.2  christos       }
    387  1.1.1.2  christos   dwarf2_emit_insn (4);
    388  1.1.1.2  christos 
    389      1.1     skrll   /* .brinfo lasts exactly one instruction.  */
    390      1.1     skrll   brinfo = 0;
    391      1.1     skrll }
    392      1.1     skrll 
    393      1.1     skrll static int
    394      1.1     skrll calcop (struct spu_opcode *format, const char *param, struct spu_insn *insn)
    395      1.1     skrll {
    396      1.1     skrll   int i;
    397      1.1     skrll   int paren = 0;
    398      1.1     skrll   int arg;
    399      1.1     skrll 
    400      1.1     skrll   for (i = 1; i <= format->arg[0]; i++)
    401      1.1     skrll     {
    402      1.1     skrll       arg = format->arg[i];
    403      1.1     skrll       syntax_error_arg = i;
    404      1.1     skrll 
    405      1.1     skrll       while (ISSPACE (*param))
    406      1.1     skrll         param++;
    407      1.1     skrll       if (*param == 0 || *param == ',')
    408      1.1     skrll 	return 0;
    409      1.1     skrll       if (arg < A_P)
    410      1.1     skrll         param = get_reg (param, insn, arg, 1);
    411      1.1     skrll       else if (arg > A_P)
    412      1.1     skrll         param = get_imm (param, insn, arg);
    413      1.1     skrll       else if (arg == A_P)
    414      1.1     skrll 	{
    415      1.1     skrll 	  paren++;
    416      1.1     skrll 	  if ('(' != *param++)
    417      1.1     skrll 	    return 0;
    418      1.1     skrll 	}
    419      1.1     skrll 
    420      1.1     skrll       if (!param)
    421      1.1     skrll 	return 0;
    422      1.1     skrll 
    423      1.1     skrll       while (ISSPACE (*param))
    424      1.1     skrll         param++;
    425      1.1     skrll 
    426      1.1     skrll       if (arg != A_P && paren)
    427      1.1     skrll 	{
    428      1.1     skrll 	  paren--;
    429      1.1     skrll 	  if (')' != *param++)
    430      1.1     skrll 	    return 0;
    431      1.1     skrll 	}
    432      1.1     skrll       else if (i < format->arg[0]
    433      1.1     skrll 	       && format->arg[i] != A_P
    434      1.1     skrll 	       && format->arg[i+1] != A_P)
    435      1.1     skrll 	{
    436      1.1     skrll 	  if (',' != *param++)
    437      1.1     skrll 	    {
    438      1.1     skrll 	      syntax_error_arg++;
    439      1.1     skrll 	      return 0;
    440      1.1     skrll 	    }
    441      1.1     skrll 	}
    442      1.1     skrll     }
    443      1.1     skrll   while (ISSPACE (*param))
    444      1.1     skrll     param++;
    445      1.1     skrll   return !paren && (*param == 0 || *param == '\n');
    446      1.1     skrll }
    447      1.1     skrll 
    448      1.1     skrll struct reg_name {
    449      1.1     skrll     unsigned int regno;
    450      1.1     skrll     unsigned int length;
    451      1.1     skrll     char name[32];
    452      1.1     skrll };
    453      1.1     skrll 
    454      1.1     skrll #define REG_NAME(NO,NM) { NO, sizeof (NM) - 1, NM }
    455      1.1     skrll 
    456      1.1     skrll static struct reg_name reg_name[] = {
    457      1.1     skrll   REG_NAME (0, "lr"),  /* link register */
    458      1.1     skrll   REG_NAME (1, "sp"),  /* stack pointer */
    459      1.1     skrll   REG_NAME (0, "rp"),  /* link register */
    460      1.1     skrll   REG_NAME (127, "fp"),  /* frame pointer */
    461      1.1     skrll };
    462      1.1     skrll 
    463      1.1     skrll static struct reg_name sp_reg_name[] = {
    464      1.1     skrll };
    465      1.1     skrll 
    466      1.1     skrll static struct reg_name ch_reg_name[] = {
    467      1.1     skrll   REG_NAME (  0, "SPU_RdEventStat"),
    468      1.1     skrll   REG_NAME (  1, "SPU_WrEventMask"),
    469      1.1     skrll   REG_NAME (  2, "SPU_WrEventAck"),
    470      1.1     skrll   REG_NAME (  3, "SPU_RdSigNotify1"),
    471      1.1     skrll   REG_NAME (  4, "SPU_RdSigNotify2"),
    472      1.1     skrll   REG_NAME (  7, "SPU_WrDec"),
    473      1.1     skrll   REG_NAME (  8, "SPU_RdDec"),
    474      1.1     skrll   REG_NAME ( 11, "SPU_RdEventMask"), /* DD2.0 only */
    475      1.1     skrll   REG_NAME ( 13, "SPU_RdMachStat"),
    476      1.1     skrll   REG_NAME ( 14, "SPU_WrSRR0"),
    477      1.1     skrll   REG_NAME ( 15, "SPU_RdSRR0"),
    478      1.1     skrll   REG_NAME ( 28, "SPU_WrOutMbox"),
    479      1.1     skrll   REG_NAME ( 29, "SPU_RdInMbox"),
    480      1.1     skrll   REG_NAME ( 30, "SPU_WrOutIntrMbox"),
    481      1.1     skrll   REG_NAME (  9, "MFC_WrMSSyncReq"),
    482      1.1     skrll   REG_NAME ( 12, "MFC_RdTagMask"),   /* DD2.0 only */
    483      1.1     skrll   REG_NAME ( 16, "MFC_LSA"),
    484      1.1     skrll   REG_NAME ( 17, "MFC_EAH"),
    485      1.1     skrll   REG_NAME ( 18, "MFC_EAL"),
    486      1.1     skrll   REG_NAME ( 19, "MFC_Size"),
    487      1.1     skrll   REG_NAME ( 20, "MFC_TagID"),
    488      1.1     skrll   REG_NAME ( 21, "MFC_Cmd"),
    489      1.1     skrll   REG_NAME ( 22, "MFC_WrTagMask"),
    490      1.1     skrll   REG_NAME ( 23, "MFC_WrTagUpdate"),
    491      1.1     skrll   REG_NAME ( 24, "MFC_RdTagStat"),
    492      1.1     skrll   REG_NAME ( 25, "MFC_RdListStallStat"),
    493      1.1     skrll   REG_NAME ( 26, "MFC_WrListStallAck"),
    494      1.1     skrll   REG_NAME ( 27, "MFC_RdAtomicStat"),
    495      1.1     skrll };
    496      1.1     skrll #undef REG_NAME
    497      1.1     skrll 
    498      1.1     skrll static const char *
    499      1.1     skrll get_reg (const char *param, struct spu_insn *insn, int arg, int accept_expr)
    500      1.1     skrll {
    501      1.1     skrll   unsigned regno;
    502      1.1     skrll   int saw_prefix = 0;
    503      1.1     skrll 
    504      1.1     skrll   if (*param == '$')
    505      1.1     skrll     {
    506      1.1     skrll       saw_prefix = 1;
    507  1.1.1.3  christos       param++;
    508      1.1     skrll     }
    509      1.1     skrll 
    510      1.1     skrll   if (arg == A_H) /* Channel */
    511      1.1     skrll     {
    512      1.1     skrll       if ((param[0] == 'c' || param[0] == 'C')
    513      1.1     skrll 	  && (param[1] == 'h' || param[1] == 'H')
    514      1.1     skrll 	  && ISDIGIT (param[2]))
    515      1.1     skrll         param += 2;
    516      1.1     skrll     }
    517      1.1     skrll   else if (arg == A_S) /* Special purpose register */
    518      1.1     skrll     {
    519      1.1     skrll       if ((param[0] == 's' || param[0] == 'S')
    520      1.1     skrll 	  && (param[1] == 'p' || param[1] == 'P')
    521      1.1     skrll 	  && ISDIGIT (param[2]))
    522      1.1     skrll         param += 2;
    523      1.1     skrll     }
    524      1.1     skrll 
    525      1.1     skrll   if (ISDIGIT (*param))
    526      1.1     skrll     {
    527      1.1     skrll       regno = 0;
    528      1.1     skrll       while (ISDIGIT (*param))
    529      1.1     skrll 	regno = regno * 10 + *param++ - '0';
    530      1.1     skrll     }
    531      1.1     skrll   else
    532      1.1     skrll     {
    533      1.1     skrll       struct reg_name *rn;
    534      1.1     skrll       unsigned int i, n, l = 0;
    535      1.1     skrll 
    536      1.1     skrll       if (arg == A_H) /* Channel */
    537      1.1     skrll 	{
    538      1.1     skrll 	  rn = ch_reg_name;
    539      1.1     skrll 	  n = sizeof (ch_reg_name) / sizeof (*ch_reg_name);
    540      1.1     skrll 	}
    541      1.1     skrll       else if (arg == A_S) /* Special purpose register */
    542      1.1     skrll 	{
    543      1.1     skrll 	  rn = sp_reg_name;
    544      1.1     skrll 	  n = sizeof (sp_reg_name) / sizeof (*sp_reg_name);
    545      1.1     skrll 	}
    546      1.1     skrll       else
    547      1.1     skrll 	{
    548      1.1     skrll 	  rn = reg_name;
    549      1.1     skrll 	  n = sizeof (reg_name) / sizeof (*reg_name);
    550      1.1     skrll 	}
    551      1.1     skrll       regno = 128;
    552      1.1     skrll       for (i = 0; i < n; i++)
    553      1.1     skrll 	if (rn[i].length > l
    554      1.1     skrll 	    && 0 == strncasecmp (param, rn[i].name, rn[i].length))
    555      1.1     skrll           {
    556      1.1     skrll 	    l = rn[i].length;
    557      1.1     skrll             regno = rn[i].regno;
    558      1.1     skrll           }
    559      1.1     skrll       param += l;
    560      1.1     skrll     }
    561      1.1     skrll 
    562      1.1     skrll   if (!use_dd2
    563      1.1     skrll       && arg == A_H)
    564      1.1     skrll     {
    565      1.1     skrll       if (regno == 11)
    566      1.1     skrll 	as_bad (_("'SPU_RdEventMask' (channel 11) is only available in DD2.0 or higher."));
    567      1.1     skrll       else if (regno == 12)
    568      1.1     skrll 	as_bad (_("'MFC_RdTagMask' (channel 12) is only available in DD2.0 or higher."));
    569      1.1     skrll     }
    570      1.1     skrll 
    571      1.1     skrll   if (regno < 128)
    572      1.1     skrll     {
    573      1.1     skrll       insn->opcode |= regno << arg_encode[arg].pos;
    574      1.1     skrll       if ((!saw_prefix && syntax_reg == 1)
    575      1.1     skrll 	  || (saw_prefix && syntax_reg == 2))
    576      1.1     skrll 	syntax_reg |= 4;
    577      1.1     skrll       syntax_reg |= saw_prefix ? 1 : 2;
    578      1.1     skrll       return param;
    579      1.1     skrll     }
    580      1.1     skrll 
    581      1.1     skrll   if (accept_expr)
    582      1.1     skrll     {
    583      1.1     skrll       char *save_ptr;
    584      1.1     skrll       expressionS ex;
    585      1.1     skrll       save_ptr = input_line_pointer;
    586      1.1     skrll       input_line_pointer = (char *)param;
    587      1.1     skrll       expression (&ex);
    588      1.1     skrll       param = input_line_pointer;
    589      1.1     skrll       input_line_pointer = save_ptr;
    590      1.1     skrll       if (ex.X_op == O_register || ex.X_op == O_constant)
    591      1.1     skrll 	{
    592      1.1     skrll 	  insn->opcode |= ex.X_add_number << arg_encode[arg].pos;
    593      1.1     skrll 	  return param;
    594      1.1     skrll 	}
    595      1.1     skrll     }
    596      1.1     skrll   return 0;
    597      1.1     skrll }
    598      1.1     skrll 
    599      1.1     skrll static const char *
    600      1.1     skrll get_imm (const char *param, struct spu_insn *insn, int arg)
    601      1.1     skrll {
    602      1.1     skrll   int val;
    603      1.1     skrll   char *save_ptr;
    604      1.1     skrll   int low = 0, high = 0;
    605      1.1     skrll   int reloc_i = insn->reloc_arg[0] >= 0 ? 1 : 0;
    606      1.1     skrll 
    607      1.1     skrll   if (strncasecmp (param, "%lo(", 4) == 0)
    608      1.1     skrll     {
    609      1.1     skrll       param += 3;
    610      1.1     skrll       low = 1;
    611      1.1     skrll       as_warn (_("Using old style, %%lo(expr), please change to PPC style, expr@l."));
    612      1.1     skrll     }
    613      1.1     skrll   else if (strncasecmp (param, "%hi(", 4) == 0)
    614      1.1     skrll     {
    615      1.1     skrll       param += 3;
    616      1.1     skrll       high = 1;
    617      1.1     skrll       as_warn (_("Using old style, %%hi(expr), please change to PPC style, expr@h."));
    618      1.1     skrll     }
    619      1.1     skrll   else if (strncasecmp (param, "%pic(", 5) == 0)
    620      1.1     skrll     {
    621      1.1     skrll       /* Currently we expect %pic(expr) == expr, so do nothing here.
    622      1.1     skrll 	 i.e. for code loaded at address 0 $toc will be 0.  */
    623  1.1.1.3  christos       param += 4;
    624      1.1     skrll     }
    625      1.1     skrll 
    626      1.1     skrll   if (*param == '$')
    627      1.1     skrll     {
    628      1.1     skrll       /* Symbols can start with $, but if this symbol matches a register
    629      1.1     skrll 	 name, it's probably a mistake.  The only way to avoid this
    630      1.1     skrll 	 warning is to rename the symbol.  */
    631      1.1     skrll       struct spu_insn tmp_insn;
    632      1.1     skrll       const char *np = get_reg (param, &tmp_insn, arg, 0);
    633      1.1     skrll 
    634      1.1     skrll       if (np)
    635  1.1.1.3  christos 	syntax_error_param = np;
    636      1.1     skrll     }
    637      1.1     skrll 
    638      1.1     skrll   save_ptr = input_line_pointer;
    639      1.1     skrll   input_line_pointer = (char *) param;
    640      1.1     skrll   expression (&insn->exp[reloc_i]);
    641      1.1     skrll   param = input_line_pointer;
    642      1.1     skrll   input_line_pointer = save_ptr;
    643      1.1     skrll 
    644      1.1     skrll   /* Similar to ppc_elf_suffix in tc-ppc.c.  We have so few cases to
    645      1.1     skrll      handle we do it inlined here. */
    646      1.1     skrll   if (param[0] == '@' && !ISALNUM (param[2]) && param[2] != '@')
    647      1.1     skrll     {
    648      1.1     skrll       if (param[1] == 'h' || param[1] == 'H')
    649      1.1     skrll 	{
    650      1.1     skrll 	  high = 1;
    651      1.1     skrll 	  param += 2;
    652      1.1     skrll 	}
    653      1.1     skrll       else if (param[1] == 'l' || param[1] == 'L')
    654      1.1     skrll 	{
    655      1.1     skrll 	  low = 1;
    656      1.1     skrll 	  param += 2;
    657      1.1     skrll 	}
    658      1.1     skrll     }
    659      1.1     skrll 
    660      1.1     skrll   if (insn->exp[reloc_i].X_op == O_constant)
    661      1.1     skrll     {
    662      1.1     skrll       val = insn->exp[reloc_i].X_add_number;
    663      1.1     skrll 
    664  1.1.1.3  christos       if (emulate_apuasm)
    665      1.1     skrll 	{
    666      1.1     skrll 	  /* Convert the value to a format we expect. */
    667      1.1     skrll           val <<= arg_encode[arg].rshift;
    668      1.1     skrll 	  if (arg == A_U7A)
    669  1.1.1.3  christos 	    val = 173 - val;
    670      1.1     skrll 	  else if (arg == A_U7B)
    671      1.1     skrll 	    val = 155 - val;
    672      1.1     skrll 	}
    673      1.1     skrll 
    674      1.1     skrll       if (high)
    675      1.1     skrll 	val = val >> 16;
    676      1.1     skrll       else if (low)
    677      1.1     skrll 	val = val & 0xffff;
    678      1.1     skrll 
    679      1.1     skrll       /* Warn about out of range expressions. */
    680      1.1     skrll       {
    681      1.1     skrll 	int hi = arg_encode[arg].hi;
    682      1.1     skrll 	int lo = arg_encode[arg].lo;
    683      1.1     skrll 	int whi = arg_encode[arg].whi;
    684      1.1     skrll 	int wlo = arg_encode[arg].wlo;
    685      1.1     skrll 
    686      1.1     skrll 	if (hi > lo && (val < lo || val > hi))
    687      1.1     skrll 	  as_fatal (_("Constant expression %d out of range, [%d, %d]."),
    688      1.1     skrll 		    val, lo, hi);
    689      1.1     skrll 	else if (whi > wlo && (val < wlo || val > whi))
    690      1.1     skrll 	  as_warn (_("Constant expression %d out of range, [%d, %d]."),
    691      1.1     skrll 		   val, wlo, whi);
    692      1.1     skrll       }
    693      1.1     skrll 
    694      1.1     skrll       if (arg == A_U7A)
    695  1.1.1.3  christos         val = 173 - val;
    696      1.1     skrll       else if (arg == A_U7B)
    697      1.1     skrll         val = 155 - val;
    698      1.1     skrll 
    699      1.1     skrll       /* Branch hints have a split encoding.  Do the bottom part. */
    700      1.1     skrll       if (arg == A_S11 || arg == A_S11I)
    701      1.1     skrll 	insn->opcode |= ((val >> 2) & 0x7f);
    702      1.1     skrll 
    703      1.1     skrll       insn->opcode |= (((val >> arg_encode[arg].rshift)
    704      1.1     skrll 			& ((1 << arg_encode[arg].size) - 1))
    705      1.1     skrll 		       << arg_encode[arg].pos);
    706      1.1     skrll     }
    707      1.1     skrll   else
    708      1.1     skrll     {
    709      1.1     skrll       insn->reloc_arg[reloc_i] = arg;
    710      1.1     skrll       if (high)
    711      1.1     skrll 	insn->reloc[reloc_i] = BFD_RELOC_SPU_HI16;
    712      1.1     skrll       else if (low)
    713      1.1     skrll 	insn->reloc[reloc_i] = BFD_RELOC_SPU_LO16;
    714      1.1     skrll       else
    715      1.1     skrll 	insn->reloc[reloc_i] = arg_encode[arg].reloc;
    716      1.1     skrll     }
    717      1.1     skrll 
    718      1.1     skrll   return param;
    719  1.1.1.4  christos }
    720      1.1     skrll 
    721      1.1     skrll const char *
    722      1.1     skrll md_atof (int type, char *litP, int *sizeP)
    723      1.1     skrll {
    724      1.1     skrll   return ieee_md_atof (type, litP, sizeP, TRUE);
    725      1.1     skrll }
    726      1.1     skrll 
    727      1.1     skrll #ifndef WORKING_DOT_WORD
    728      1.1     skrll int md_short_jump_size = 4;
    729      1.1     skrll 
    730      1.1     skrll void
    731      1.1     skrll md_create_short_jump (char *ptr,
    732      1.1     skrll 		      addressT from_addr ATTRIBUTE_UNUSED,
    733      1.1     skrll 		      addressT to_addr ATTRIBUTE_UNUSED,
    734      1.1     skrll 		      fragS *frag,
    735      1.1     skrll 		      symbolS *to_symbol)
    736      1.1     skrll {
    737      1.1     skrll   ptr[0] = (char) 0xc0;
    738      1.1     skrll   ptr[1] = 0x00;
    739      1.1     skrll   ptr[2] = 0x00;
    740      1.1     skrll   ptr[3] = 0x00;
    741      1.1     skrll   fix_new (frag,
    742      1.1     skrll 	   ptr - frag->fr_literal,
    743      1.1     skrll 	   4,
    744      1.1     skrll 	   to_symbol,
    745      1.1     skrll 	   (offsetT) 0,
    746      1.1     skrll 	   0,
    747      1.1     skrll 	   BFD_RELOC_SPU_PCREL16);
    748      1.1     skrll }
    749      1.1     skrll 
    750      1.1     skrll int md_long_jump_size = 4;
    751      1.1     skrll 
    752      1.1     skrll void
    753      1.1     skrll md_create_long_jump (char *ptr,
    754      1.1     skrll 		     addressT from_addr ATTRIBUTE_UNUSED,
    755      1.1     skrll 		     addressT to_addr ATTRIBUTE_UNUSED,
    756      1.1     skrll 		     fragS *frag,
    757      1.1     skrll 		     symbolS *to_symbol)
    758      1.1     skrll {
    759      1.1     skrll   ptr[0] = (char) 0xc0;
    760      1.1     skrll   ptr[1] = 0x00;
    761      1.1     skrll   ptr[2] = 0x00;
    762      1.1     skrll   ptr[3] = 0x00;
    763      1.1     skrll   fix_new (frag,
    764      1.1     skrll 	   ptr - frag->fr_literal,
    765      1.1     skrll 	   4,
    766      1.1     skrll 	   to_symbol,
    767      1.1     skrll 	   (offsetT) 0,
    768      1.1     skrll 	   0,
    769      1.1     skrll 	   BFD_RELOC_SPU_PCREL16);
    770      1.1     skrll }
    771  1.1.1.2  christos #endif
    772  1.1.1.2  christos 
    773  1.1.1.2  christos /* Handle .brinfo <priority>,<lrlive>.  */
    774  1.1.1.2  christos static void
    775  1.1.1.2  christos spu_brinfo (int ignore ATTRIBUTE_UNUSED)
    776  1.1.1.2  christos {
    777  1.1.1.2  christos   addressT priority;
    778  1.1.1.2  christos   addressT lrlive;
    779  1.1.1.2  christos 
    780  1.1.1.2  christos   priority = get_absolute_expression ();
    781  1.1.1.2  christos   SKIP_WHITESPACE ();
    782  1.1.1.2  christos 
    783  1.1.1.2  christos   lrlive = 0;
    784  1.1.1.2  christos   if (*input_line_pointer == ',')
    785  1.1.1.2  christos     {
    786  1.1.1.2  christos       ++input_line_pointer;
    787  1.1.1.2  christos       lrlive = get_absolute_expression ();
    788  1.1.1.2  christos     }
    789  1.1.1.2  christos 
    790  1.1.1.2  christos   if (priority > 0x1fff)
    791  1.1.1.2  christos     {
    792  1.1.1.2  christos       as_bad (_("invalid priority '%lu'"), (unsigned long) priority);
    793  1.1.1.2  christos       priority = 0;
    794  1.1.1.2  christos     }
    795  1.1.1.2  christos 
    796  1.1.1.2  christos   if (lrlive > 7)
    797  1.1.1.2  christos     {
    798  1.1.1.2  christos       as_bad (_("invalid lrlive '%lu'"), (unsigned long) lrlive);
    799  1.1.1.2  christos       lrlive = 0;
    800  1.1.1.2  christos     }
    801  1.1.1.2  christos 
    802  1.1.1.2  christos   brinfo = (lrlive << 13) | priority;
    803  1.1.1.2  christos   demand_empty_rest_of_line ();
    804      1.1     skrll }
    805      1.1     skrll 
    806      1.1     skrll /* Support @ppu on symbols referenced in .int/.long/.word/.quad.  */
    807      1.1     skrll static void
    808      1.1     skrll spu_cons (int nbytes)
    809      1.1     skrll {
    810      1.1     skrll   expressionS exp;
    811      1.1     skrll 
    812      1.1     skrll   if (is_it_end_of_statement ())
    813      1.1     skrll     {
    814      1.1     skrll       demand_empty_rest_of_line ();
    815      1.1     skrll       return;
    816      1.1     skrll     }
    817      1.1     skrll 
    818      1.1     skrll   do
    819      1.1     skrll     {
    820      1.1     skrll       deferred_expression (&exp);
    821      1.1     skrll       if ((exp.X_op == O_symbol
    822      1.1     skrll 	   || exp.X_op == O_constant)
    823      1.1     skrll 	  && strncasecmp (input_line_pointer, "@ppu", 4) == 0)
    824      1.1     skrll 	{
    825      1.1     skrll 	  char *p = frag_more (nbytes);
    826      1.1     skrll 	  enum bfd_reloc_code_real reloc;
    827      1.1     skrll 
    828      1.1     skrll 	  /* Check for identifier@suffix+constant.  */
    829      1.1     skrll 	  input_line_pointer += 4;
    830      1.1     skrll 	  if (*input_line_pointer == '-' || *input_line_pointer == '+')
    831      1.1     skrll 	    {
    832      1.1     skrll 	      expressionS new_exp;
    833      1.1     skrll 
    834      1.1     skrll 	      expression (&new_exp);
    835      1.1     skrll 	      if (new_exp.X_op == O_constant)
    836      1.1     skrll 		exp.X_add_number += new_exp.X_add_number;
    837      1.1     skrll 	    }
    838      1.1     skrll 
    839      1.1     skrll 	  reloc = nbytes == 4 ? BFD_RELOC_SPU_PPU32 : BFD_RELOC_SPU_PPU64;
    840      1.1     skrll 	  fix_new_exp (frag_now, p - frag_now->fr_literal, nbytes,
    841      1.1     skrll 		       &exp, 0, reloc);
    842      1.1     skrll 	}
    843      1.1     skrll       else
    844      1.1     skrll 	emit_expr (&exp, nbytes);
    845      1.1     skrll     }
    846      1.1     skrll   while (*input_line_pointer++ == ',');
    847      1.1     skrll 
    848      1.1     skrll   /* Put terminator back into stream.  */
    849      1.1     skrll   input_line_pointer--;
    850      1.1     skrll   demand_empty_rest_of_line ();
    851      1.1     skrll }
    852      1.1     skrll 
    853      1.1     skrll int
    854      1.1     skrll md_estimate_size_before_relax (fragS *fragP ATTRIBUTE_UNUSED,
    855      1.1     skrll 			       segT segment_type ATTRIBUTE_UNUSED)
    856      1.1     skrll {
    857      1.1     skrll   as_fatal (_("Relaxation should never occur"));
    858      1.1     skrll   return -1;
    859      1.1     skrll }
    860      1.1     skrll 
    861      1.1     skrll /* If while processing a fixup, a reloc really needs to be created,
    862      1.1     skrll    then it is done here.  */
    863      1.1     skrll 
    864      1.1     skrll arelent *
    865      1.1     skrll tc_gen_reloc (asection *seg ATTRIBUTE_UNUSED, fixS *fixp)
    866  1.1.1.4  christos {
    867  1.1.1.4  christos   arelent *reloc;
    868      1.1     skrll   reloc = XNEW (arelent);
    869      1.1     skrll   reloc->sym_ptr_ptr = XNEW (asymbol *);
    870      1.1     skrll   if (fixp->fx_addsy)
    871      1.1     skrll     *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
    872      1.1     skrll   else if (fixp->fx_subsy)
    873      1.1     skrll     *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_subsy);
    874      1.1     skrll   else
    875      1.1     skrll     abort ();
    876      1.1     skrll   reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
    877      1.1     skrll   reloc->howto = bfd_reloc_type_lookup (stdoutput, fixp->fx_r_type);
    878      1.1     skrll   if (reloc->howto == (reloc_howto_type *) NULL)
    879      1.1     skrll     {
    880      1.1     skrll       as_bad_where (fixp->fx_file, fixp->fx_line,
    881      1.1     skrll 		    _("reloc %d not supported by object file format"),
    882      1.1     skrll 		    (int) fixp->fx_r_type);
    883      1.1     skrll       return NULL;
    884      1.1     skrll     }
    885      1.1     skrll   reloc->addend = fixp->fx_addnumber;
    886      1.1     skrll   return reloc;
    887      1.1     skrll }
    888      1.1     skrll 
    889      1.1     skrll /* Round up a section's size to the appropriate boundary.  */
    890      1.1     skrll 
    891      1.1     skrll valueT
    892      1.1     skrll md_section_align (segT seg, valueT size)
    893      1.1     skrll {
    894      1.1     skrll   int align = bfd_get_section_alignment (stdoutput, seg);
    895      1.1     skrll   valueT mask = ((valueT) 1 << align) - 1;
    896      1.1     skrll 
    897      1.1     skrll   return (size + mask) & ~mask;
    898      1.1     skrll }
    899      1.1     skrll 
    900      1.1     skrll /* Where a PC relative offset is calculated from.  On the spu they
    901      1.1     skrll    are calculated from the beginning of the branch instruction.  */
    902      1.1     skrll 
    903      1.1     skrll long
    904      1.1     skrll md_pcrel_from (fixS *fixp)
    905      1.1     skrll {
    906      1.1     skrll   return fixp->fx_frag->fr_address + fixp->fx_where;
    907      1.1     skrll }
    908      1.1     skrll 
    909      1.1     skrll /* Fill in rs_align_code fragments.  */
    910      1.1     skrll 
    911      1.1     skrll void
    912      1.1     skrll spu_handle_align (fragS *fragp)
    913      1.1     skrll {
    914      1.1     skrll   static const unsigned char nop_pattern[8] = {
    915      1.1     skrll     0x40, 0x20, 0x00, 0x00, /* even nop */
    916      1.1     skrll     0x00, 0x20, 0x00, 0x00, /* odd  nop */
    917      1.1     skrll   };
    918      1.1     skrll 
    919      1.1     skrll   int bytes;
    920      1.1     skrll   char *p;
    921      1.1     skrll 
    922      1.1     skrll   if (fragp->fr_type != rs_align_code)
    923      1.1     skrll     return;
    924      1.1     skrll 
    925      1.1     skrll   bytes = fragp->fr_next->fr_address - fragp->fr_address - fragp->fr_fix;
    926      1.1     skrll   p = fragp->fr_literal + fragp->fr_fix;
    927      1.1     skrll 
    928      1.1     skrll   if (bytes & 3)
    929      1.1     skrll     {
    930      1.1     skrll       int fix = bytes & 3;
    931      1.1     skrll       memset (p, 0, fix);
    932      1.1     skrll       p += fix;
    933      1.1     skrll       bytes -= fix;
    934      1.1     skrll       fragp->fr_fix += fix;
    935      1.1     skrll     }
    936      1.1     skrll   if (bytes & 4)
    937      1.1     skrll     {
    938      1.1     skrll       memcpy (p, &nop_pattern[4], 4);
    939      1.1     skrll       p += 4;
    940      1.1     skrll       bytes -= 4;
    941      1.1     skrll       fragp->fr_fix += 4;
    942      1.1     skrll     }
    943      1.1     skrll 
    944      1.1     skrll   memcpy (p, nop_pattern, 8);
    945      1.1     skrll   fragp->fr_var = 8;
    946      1.1     skrll }
    947      1.1     skrll 
    948      1.1     skrll void
    949      1.1     skrll md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
    950  1.1.1.2  christos {
    951      1.1     skrll   unsigned int res;
    952      1.1     skrll   unsigned int mask;
    953      1.1     skrll   valueT val = *valP;
    954      1.1     skrll   char *place = fixP->fx_where + fixP->fx_frag->fr_literal;
    955      1.1     skrll 
    956      1.1     skrll   if (fixP->fx_subsy != (symbolS *) NULL)
    957      1.1     skrll     {
    958      1.1     skrll       /* We can't actually support subtracting a symbol.  */
    959      1.1     skrll       as_bad_where (fixP->fx_file, fixP->fx_line, _("expression too complex"));
    960      1.1     skrll     }
    961      1.1     skrll 
    962      1.1     skrll   if (fixP->fx_addsy != NULL)
    963      1.1     skrll     {
    964      1.1     skrll       if (fixP->fx_pcrel)
    965      1.1     skrll 	{
    966      1.1     skrll 	  /* Hack around bfd_install_relocation brain damage.  */
    967      1.1     skrll 	  val += fixP->fx_frag->fr_address + fixP->fx_where;
    968      1.1     skrll 
    969      1.1     skrll 	  switch (fixP->fx_r_type)
    970      1.1     skrll 	    {
    971      1.1     skrll 	    case BFD_RELOC_32:
    972      1.1     skrll 	      fixP->fx_r_type = BFD_RELOC_32_PCREL;
    973      1.1     skrll 	      break;
    974      1.1     skrll 
    975      1.1     skrll 	    case BFD_RELOC_SPU_PCREL16:
    976      1.1     skrll 	    case BFD_RELOC_SPU_PCREL9a:
    977      1.1     skrll 	    case BFD_RELOC_SPU_PCREL9b:
    978      1.1     skrll 	    case BFD_RELOC_32_PCREL:
    979      1.1     skrll 	      break;
    980      1.1     skrll 
    981      1.1     skrll 	    default:
    982      1.1     skrll 	      as_bad_where (fixP->fx_file, fixP->fx_line,
    983      1.1     skrll 			    _("expression too complex"));
    984      1.1     skrll 	      break;
    985      1.1     skrll 	    }
    986      1.1     skrll 	}
    987      1.1     skrll     }
    988      1.1     skrll 
    989      1.1     skrll   fixP->fx_addnumber = val;
    990  1.1.1.2  christos 
    991  1.1.1.2  christos   if (fixP->fx_r_type == BFD_RELOC_SPU_PPU32
    992      1.1     skrll       || fixP->fx_r_type == BFD_RELOC_SPU_PPU64
    993      1.1     skrll       || fixP->fx_r_type == BFD_RELOC_SPU_ADD_PIC)
    994      1.1     skrll     return;
    995      1.1     skrll 
    996      1.1     skrll   if (fixP->fx_addsy == NULL && fixP->fx_pcrel == 0)
    997      1.1     skrll     {
    998  1.1.1.2  christos       fixP->fx_done = 1;
    999      1.1     skrll       res = 0;
   1000      1.1     skrll       mask = 0;
   1001      1.1     skrll       if (fixP->tc_fix_data.arg_format > A_P)
   1002      1.1     skrll 	{
   1003      1.1     skrll 	  int hi = arg_encode[fixP->tc_fix_data.arg_format].hi;
   1004      1.1     skrll 	  int lo = arg_encode[fixP->tc_fix_data.arg_format].lo;
   1005  1.1.1.2  christos 	  if (hi > lo && ((offsetT) val < lo || (offsetT) val > hi))
   1006      1.1     skrll 	    as_bad_where (fixP->fx_file, fixP->fx_line,
   1007      1.1     skrll 			  _("Relocation doesn't fit. (relocation value = 0x%lx)"),
   1008      1.1     skrll 			  (long) val);
   1009      1.1     skrll 	}
   1010  1.1.1.2  christos 
   1011  1.1.1.2  christos       switch (fixP->fx_r_type)
   1012      1.1     skrll 	{
   1013      1.1     skrll 	case BFD_RELOC_8:
   1014      1.1     skrll 	  md_number_to_chars (place, val, 1);
   1015  1.1.1.2  christos 	  return;
   1016      1.1     skrll 
   1017      1.1     skrll 	case BFD_RELOC_16:
   1018      1.1     skrll 	  md_number_to_chars (place, val, 2);
   1019  1.1.1.2  christos 	  return;
   1020      1.1     skrll 
   1021      1.1     skrll 	case BFD_RELOC_32:
   1022      1.1     skrll 	case BFD_RELOC_32_PCREL:
   1023      1.1     skrll 	  md_number_to_chars (place, val, 4);
   1024  1.1.1.2  christos 	  return;
   1025      1.1     skrll 
   1026      1.1     skrll 	case BFD_RELOC_64:
   1027      1.1     skrll 	  md_number_to_chars (place, val, 8);
   1028  1.1.1.2  christos 	  return;
   1029  1.1.1.2  christos 
   1030  1.1.1.2  christos 	case BFD_RELOC_SPU_IMM7:
   1031  1.1.1.2  christos 	  res = val << 14;
   1032  1.1.1.2  christos 	  mask = 0x7f << 14;
   1033  1.1.1.2  christos 	  break;
   1034  1.1.1.2  christos 
   1035  1.1.1.2  christos 	case BFD_RELOC_SPU_IMM8:
   1036  1.1.1.2  christos 	  res = val << 14;
   1037  1.1.1.2  christos 	  mask = 0xff << 14;
   1038  1.1.1.2  christos 	  break;
   1039  1.1.1.2  christos 
   1040  1.1.1.2  christos 	case BFD_RELOC_SPU_IMM10:
   1041  1.1.1.2  christos 	  res = val << 14;
   1042  1.1.1.2  christos 	  mask = 0x3ff << 14;
   1043  1.1.1.2  christos 	  break;
   1044  1.1.1.2  christos 
   1045  1.1.1.2  christos 	case BFD_RELOC_SPU_IMM10W:
   1046  1.1.1.2  christos 	  res = val << 10;
   1047  1.1.1.2  christos 	  mask = 0x3ff0 << 10;
   1048  1.1.1.2  christos 	  break;
   1049  1.1.1.2  christos 
   1050  1.1.1.2  christos 	case BFD_RELOC_SPU_IMM16:
   1051  1.1.1.2  christos 	  res = val << 7;
   1052  1.1.1.2  christos 	  mask = 0xffff << 7;
   1053  1.1.1.2  christos 	  break;
   1054  1.1.1.2  christos 
   1055  1.1.1.2  christos 	case BFD_RELOC_SPU_IMM16W:
   1056  1.1.1.2  christos 	  res = val << 5;
   1057  1.1.1.2  christos 	  mask = 0x3fffc << 5;
   1058  1.1.1.2  christos 	  break;
   1059  1.1.1.2  christos 
   1060  1.1.1.2  christos 	case BFD_RELOC_SPU_IMM18:
   1061  1.1.1.2  christos 	  res = val << 7;
   1062  1.1.1.2  christos 	  mask = 0x3ffff << 7;
   1063  1.1.1.2  christos 	  break;
   1064  1.1.1.2  christos 
   1065  1.1.1.2  christos 	case BFD_RELOC_SPU_PCREL9a:
   1066  1.1.1.2  christos 	  res = ((val & 0x1fc) >> 2) | ((val & 0x600) << 14);
   1067  1.1.1.2  christos 	  mask = (0x1fc >> 2) | (0x600 << 14);
   1068  1.1.1.2  christos 	  break;
   1069  1.1.1.2  christos 
   1070  1.1.1.2  christos 	case BFD_RELOC_SPU_PCREL9b:
   1071  1.1.1.2  christos 	  res = ((val & 0x1fc) >> 2) | ((val & 0x600) << 5);
   1072  1.1.1.2  christos 	  mask = (0x1fc >> 2) | (0x600 << 5);
   1073  1.1.1.2  christos 	  break;
   1074  1.1.1.2  christos 
   1075  1.1.1.2  christos 	case BFD_RELOC_SPU_PCREL16:
   1076  1.1.1.2  christos 	  res = val << 5;
   1077      1.1     skrll 	  mask = 0x3fffc << 5;
   1078      1.1     skrll 	  break;
   1079  1.1.1.2  christos 
   1080  1.1.1.2  christos 	case BFD_RELOC_SPU_HI16:
   1081      1.1     skrll 	  res = val >> 9;
   1082      1.1     skrll 	  mask = 0xffff << 7;
   1083      1.1     skrll 	  break;
   1084  1.1.1.2  christos 
   1085  1.1.1.2  christos 	case BFD_RELOC_SPU_LO16:
   1086      1.1     skrll 	  res = val << 7;
   1087      1.1     skrll 	  mask = 0xffff << 7;
   1088  1.1.1.2  christos 	  break;
   1089  1.1.1.2  christos 
   1090  1.1.1.2  christos 	default:
   1091  1.1.1.2  christos 	  as_bad_where (fixP->fx_file, fixP->fx_line,
   1092  1.1.1.2  christos 			_("reloc %d not supported by object file format"),
   1093  1.1.1.2  christos 			(int) fixP->fx_r_type);
   1094  1.1.1.2  christos 	}
   1095  1.1.1.2  christos 
   1096  1.1.1.2  christos       res &= mask;
   1097  1.1.1.2  christos       place[0] = (place[0] & (~mask >> 24)) | ((res >> 24) & 0xff);
   1098  1.1.1.2  christos       place[1] = (place[1] & (~mask >> 16)) | ((res >> 16) & 0xff);
   1099      1.1     skrll       place[2] = (place[2] & (~mask >> 8)) | ((res >> 8) & 0xff);
   1100      1.1     skrll       place[3] = (place[3] & ~mask) | (res & 0xff);
   1101                        }
   1102                    }
   1103