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