Home | History | Annotate | Line # | Download | only in config
      1   1.1  christos /* tc-moxie.c -- Assemble code for moxie
      2  1.10  christos    Copyright (C) 2009-2025 Free Software Foundation, Inc.
      3   1.1  christos 
      4   1.1  christos    This file is part of GAS, the GNU Assembler.
      5   1.1  christos 
      6   1.1  christos    GAS is free software; you can redistribute it and/or modify
      7   1.1  christos    it under the terms of the GNU General Public License as published by
      8   1.1  christos    the Free Software Foundation; either version 3, or (at your option)
      9   1.1  christos    any later version.
     10   1.1  christos 
     11   1.1  christos    GAS is distributed in the hope that it will be useful,
     12   1.1  christos    but WITHOUT ANY WARRANTY; without even the implied warranty of
     13   1.1  christos    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     14   1.1  christos    GNU General Public License for more details.
     15   1.1  christos 
     16   1.1  christos    You should have received a copy of the GNU General Public License
     17   1.1  christos    along with GAS; see the file COPYING.  If not, write to
     18   1.1  christos    the Free Software Foundation, 51 Franklin Street - Fifth Floor,
     19   1.1  christos    Boston, MA 02110-1301, USA.  */
     20   1.1  christos 
     21   1.1  christos /* Contributed by Anthony Green <green (at) moxielogic.com>.  */
     22   1.1  christos 
     23   1.1  christos #include "as.h"
     24   1.1  christos #include "safe-ctype.h"
     25   1.1  christos #include "opcode/moxie.h"
     26   1.1  christos #include "elf/moxie.h"
     27   1.1  christos 
     28   1.1  christos extern const moxie_opc_info_t moxie_opc_info[128];
     29   1.1  christos 
     30   1.1  christos const char comment_chars[]        = "#";
     31   1.1  christos const char line_separator_chars[] = ";";
     32   1.1  christos const char line_comment_chars[]   = "#";
     33   1.1  christos 
     34   1.1  christos static int pending_reloc;
     35   1.8  christos static htab_t opcode_hash_control;
     36   1.1  christos 
     37   1.1  christos const pseudo_typeS md_pseudo_table[] =
     38   1.1  christos {
     39   1.1  christos   {0, 0, 0}
     40   1.1  christos };
     41   1.1  christos 
     42   1.1  christos const char FLT_CHARS[] = "rRsSfFdDxXpP";
     43   1.1  christos const char EXP_CHARS[] = "eE";
     44   1.1  christos 
     45   1.3  christos static valueT md_chars_to_number (char * buf, int n);
     46   1.3  christos 
     47   1.3  christos /* Byte order.  */
     48   1.3  christos extern int target_big_endian;
     49   1.1  christos 
     50   1.1  christos void
     51   1.1  christos md_operand (expressionS *op __attribute__((unused)))
     52   1.1  christos {
     53   1.1  christos   /* Empty for now. */
     54   1.1  christos }
     55   1.1  christos 
     56   1.1  christos /* This function is called once, at assembler startup time.  It sets
     57   1.1  christos    up the hash table with all the opcodes in it, and also initializes
     58   1.1  christos    some aliases for compatibility with other assemblers.  */
     59   1.1  christos 
     60   1.1  christos void
     61   1.1  christos md_begin (void)
     62   1.1  christos {
     63   1.1  christos   int count;
     64   1.1  christos   const moxie_opc_info_t *opcode;
     65   1.8  christos   opcode_hash_control = str_htab_create ();
     66   1.1  christos 
     67   1.1  christos   /* Insert names into hash table.  */
     68   1.1  christos   for (count = 0, opcode = moxie_form1_opc_info; count++ < 64; opcode++)
     69   1.8  christos     str_hash_insert (opcode_hash_control, opcode->name, opcode, 0);
     70   1.1  christos 
     71   1.1  christos   for (count = 0, opcode = moxie_form2_opc_info; count++ < 4; opcode++)
     72   1.8  christos     str_hash_insert (opcode_hash_control, opcode->name, opcode, 0);
     73   1.1  christos 
     74   1.1  christos   for (count = 0, opcode = moxie_form3_opc_info; count++ < 10; opcode++)
     75   1.8  christos     str_hash_insert (opcode_hash_control, opcode->name, opcode, 0);
     76   1.3  christos 
     77   1.1  christos   bfd_set_arch_mach (stdoutput, TARGET_ARCH, 0);
     78   1.1  christos }
     79   1.1  christos 
     80   1.1  christos /* Parse an expression and then restore the input line pointer.  */
     81   1.1  christos 
     82   1.1  christos static char *
     83   1.1  christos parse_exp_save_ilp (char *s, expressionS *op)
     84   1.1  christos {
     85   1.1  christos   char *save = input_line_pointer;
     86   1.1  christos 
     87   1.1  christos   input_line_pointer = s;
     88   1.1  christos   expression (op);
     89   1.1  christos   s = input_line_pointer;
     90   1.1  christos   input_line_pointer = save;
     91   1.1  christos   return s;
     92   1.1  christos }
     93   1.1  christos 
     94   1.1  christos static int
     95   1.1  christos parse_register_operand (char **ptr)
     96   1.1  christos {
     97   1.1  christos   int reg;
     98   1.1  christos   char *s = *ptr;
     99   1.1  christos 
    100   1.1  christos   if (*s != '$')
    101   1.1  christos     {
    102   1.1  christos       as_bad (_("expecting register"));
    103   1.1  christos       ignore_rest_of_line ();
    104   1.1  christos       return -1;
    105   1.1  christos     }
    106   1.1  christos   if (s[1] == 'f' && s[2] == 'p')
    107   1.1  christos     {
    108   1.1  christos       *ptr += 3;
    109   1.1  christos       return 0;
    110   1.1  christos     }
    111   1.1  christos   if (s[1] == 's' && s[2] == 'p')
    112   1.1  christos     {
    113   1.1  christos       *ptr += 3;
    114   1.1  christos       return 1;
    115   1.1  christos     }
    116   1.1  christos   if (s[1] == 'r')
    117   1.1  christos     {
    118   1.1  christos       reg = s[2] - '0';
    119   1.1  christos       if ((reg < 0) || (reg > 9))
    120   1.1  christos 	{
    121   1.1  christos 	  as_bad (_("illegal register number"));
    122   1.1  christos 	  ignore_rest_of_line ();
    123   1.1  christos 	  return -1;
    124   1.1  christos 	}
    125   1.1  christos       if (reg == 1)
    126   1.1  christos 	{
    127   1.1  christos 	  int r2 = s[3] - '0';
    128   1.1  christos 	  if ((r2 >= 0) && (r2 <= 3))
    129   1.1  christos 	    {
    130   1.1  christos 	      reg = 10 + r2;
    131   1.1  christos 	      *ptr += 1;
    132   1.1  christos 	    }
    133   1.1  christos 	}
    134   1.1  christos     }
    135   1.1  christos   else
    136   1.1  christos     {
    137   1.1  christos       as_bad (_("illegal register number"));
    138   1.1  christos       ignore_rest_of_line ();
    139   1.1  christos       return -1;
    140   1.1  christos     }
    141   1.1  christos 
    142   1.1  christos   *ptr += 3;
    143   1.1  christos 
    144   1.1  christos   return reg + 2;
    145   1.1  christos }
    146   1.1  christos 
    147   1.1  christos /* This is the guts of the machine-dependent assembler.  STR points to
    148   1.1  christos    a machine dependent instruction.  This function is supposed to emit
    149   1.1  christos    the frags/bytes it assembles to.  */
    150   1.1  christos 
    151   1.1  christos void
    152   1.1  christos md_assemble (char *str)
    153   1.1  christos {
    154   1.1  christos   char *op_start;
    155   1.1  christos   char *op_end;
    156   1.1  christos 
    157   1.1  christos   moxie_opc_info_t *opcode;
    158   1.1  christos   char *p;
    159   1.1  christos   char pend;
    160   1.1  christos 
    161   1.1  christos   unsigned short iword = 0;
    162   1.1  christos 
    163   1.1  christos   int nlen = 0;
    164   1.1  christos 
    165   1.1  christos   /* Drop leading whitespace.  */
    166  1.10  christos   while (is_whitespace (*str))
    167   1.1  christos     str++;
    168   1.1  christos 
    169   1.1  christos   /* Find the op code end.  */
    170   1.1  christos   op_start = str;
    171   1.1  christos   for (op_end = str;
    172  1.10  christos        !is_end_of_stmt (*op_end) && !is_whitespace (*op_end);
    173   1.1  christos        op_end++)
    174   1.1  christos     nlen++;
    175   1.1  christos 
    176   1.1  christos   pend = *op_end;
    177   1.1  christos   *op_end = 0;
    178   1.1  christos 
    179   1.1  christos   if (nlen == 0)
    180   1.1  christos     as_bad (_("can't find opcode "));
    181  1.10  christos   opcode = str_hash_find (opcode_hash_control, op_start);
    182   1.1  christos   *op_end = pend;
    183   1.1  christos 
    184   1.1  christos   if (opcode == NULL)
    185   1.1  christos     {
    186   1.1  christos       as_bad (_("unknown opcode %s"), op_start);
    187   1.1  christos       return;
    188   1.1  christos     }
    189   1.1  christos 
    190   1.1  christos   p = frag_more (2);
    191   1.1  christos 
    192   1.1  christos   switch (opcode->itype)
    193   1.1  christos     {
    194   1.1  christos     case MOXIE_F2_A8V:
    195   1.1  christos       iword = (1<<15) | (opcode->opcode << 12);
    196  1.10  christos       while (is_whitespace (*op_end))
    197   1.1  christos 	op_end++;
    198   1.1  christos       {
    199   1.1  christos 	expressionS arg;
    200   1.1  christos 	int reg;
    201   1.1  christos 	reg = parse_register_operand (&op_end);
    202   1.1  christos 	iword += (reg << 8);
    203   1.1  christos 	if (*op_end != ',')
    204   1.1  christos 	  as_warn (_("expecting comma delimited register operands"));
    205   1.1  christos 	op_end++;
    206   1.1  christos 	op_end = parse_exp_save_ilp (op_end, &arg);
    207   1.1  christos 	fix_new_exp (frag_now,
    208   1.3  christos 		     ((p + (target_big_endian ? 1 : 0)) - frag_now->fr_literal),
    209   1.1  christos 		     1,
    210   1.1  christos 		     &arg,
    211   1.1  christos 		     0,
    212   1.1  christos 		     BFD_RELOC_8);
    213   1.1  christos       }
    214   1.1  christos       break;
    215   1.1  christos     case MOXIE_F1_AB:
    216   1.1  christos       iword = opcode->opcode << 8;
    217  1.10  christos       while (is_whitespace (*op_end))
    218   1.1  christos 	op_end++;
    219   1.1  christos       {
    220   1.1  christos 	int dest, src;
    221   1.1  christos 	dest = parse_register_operand (&op_end);
    222   1.1  christos 	if (*op_end != ',')
    223   1.1  christos 	  as_warn (_("expecting comma delimited register operands"));
    224   1.1  christos 	op_end++;
    225   1.1  christos 	src  = parse_register_operand (&op_end);
    226   1.1  christos 	iword += (dest << 4) + src;
    227  1.10  christos 	while (is_whitespace (*op_end))
    228   1.1  christos 	  op_end++;
    229   1.1  christos 	if (*op_end != 0)
    230   1.1  christos 	  as_warn (_("extra stuff on line ignored"));
    231   1.1  christos       }
    232   1.1  christos       break;
    233   1.1  christos     case MOXIE_F1_A4:
    234   1.1  christos       iword = opcode->opcode << 8;
    235  1.10  christos       while (is_whitespace (*op_end))
    236   1.1  christos 	op_end++;
    237   1.1  christos       {
    238   1.1  christos 	expressionS arg;
    239   1.1  christos 	char *where;
    240   1.1  christos 	int regnum;
    241   1.1  christos 
    242   1.1  christos  	regnum = parse_register_operand (&op_end);
    243  1.10  christos 	while (is_whitespace (*op_end))
    244   1.1  christos 	  op_end++;
    245   1.1  christos 
    246   1.1  christos 	iword += (regnum << 4);
    247   1.1  christos 
    248   1.1  christos 	if (*op_end != ',')
    249   1.1  christos 	  {
    250   1.1  christos 	    as_bad (_("expecting comma delimited operands"));
    251   1.1  christos 	    ignore_rest_of_line ();
    252   1.1  christos 	    return;
    253   1.1  christos 	  }
    254   1.1  christos 	op_end++;
    255   1.1  christos 
    256   1.1  christos 	op_end = parse_exp_save_ilp (op_end, &arg);
    257   1.1  christos 	where = frag_more (4);
    258   1.1  christos 	fix_new_exp (frag_now,
    259   1.1  christos 		     (where - frag_now->fr_literal),
    260   1.1  christos 		     4,
    261   1.1  christos 		     &arg,
    262   1.1  christos 		     0,
    263   1.1  christos 		     BFD_RELOC_32);
    264   1.1  christos       }
    265   1.1  christos       break;
    266   1.1  christos     case MOXIE_F1_M:
    267   1.1  christos     case MOXIE_F1_4:
    268   1.1  christos       iword = opcode->opcode << 8;
    269  1.10  christos       while (is_whitespace (*op_end))
    270   1.1  christos 	op_end++;
    271   1.1  christos       {
    272   1.1  christos 	expressionS arg;
    273   1.1  christos 	char *where;
    274   1.1  christos 
    275   1.1  christos 	op_end = parse_exp_save_ilp (op_end, &arg);
    276   1.1  christos 	where = frag_more (4);
    277   1.1  christos 	fix_new_exp (frag_now,
    278   1.1  christos 		     (where - frag_now->fr_literal),
    279   1.1  christos 		     4,
    280   1.1  christos 		     &arg,
    281   1.1  christos 		     0,
    282   1.1  christos 		     BFD_RELOC_32);
    283   1.1  christos       }
    284   1.1  christos       break;
    285   1.1  christos     case MOXIE_F1_NARG:
    286   1.1  christos       iword = opcode->opcode << 8;
    287  1.10  christos       while (is_whitespace (*op_end))
    288   1.1  christos 	op_end++;
    289   1.1  christos       if (*op_end != 0)
    290   1.1  christos 	as_warn (_("extra stuff on line ignored"));
    291   1.1  christos       break;
    292   1.1  christos     case MOXIE_F1_A:
    293   1.1  christos       iword = opcode->opcode << 8;
    294  1.10  christos       while (is_whitespace (*op_end))
    295   1.1  christos 	op_end++;
    296   1.1  christos       {
    297   1.1  christos 	int reg;
    298   1.1  christos 	reg = parse_register_operand (&op_end);
    299  1.10  christos 	while (is_whitespace (*op_end))
    300   1.1  christos 	  op_end++;
    301   1.1  christos 	if (*op_end != 0)
    302   1.1  christos 	  as_warn (_("extra stuff on line ignored"));
    303   1.1  christos 	iword += (reg << 4);
    304   1.1  christos       }
    305   1.1  christos       break;
    306   1.1  christos     case MOXIE_F1_ABi:
    307   1.1  christos       iword = opcode->opcode << 8;
    308  1.10  christos       while (is_whitespace (*op_end))
    309   1.1  christos 	op_end++;
    310   1.1  christos       {
    311   1.1  christos 	int a, b;
    312   1.1  christos 	a = parse_register_operand (&op_end);
    313   1.1  christos 	if (*op_end != ',')
    314   1.1  christos 	  as_warn (_("expecting comma delimited register operands"));
    315   1.1  christos 	op_end++;
    316   1.1  christos 	if (*op_end != '(')
    317   1.1  christos 	  {
    318   1.1  christos 	    as_bad (_("expecting indirect register `($rA)'"));
    319   1.1  christos 	    ignore_rest_of_line ();
    320   1.1  christos 	    return;
    321   1.1  christos 	  }
    322   1.1  christos 	op_end++;
    323   1.1  christos 	b = parse_register_operand (&op_end);
    324   1.1  christos 	if (*op_end != ')')
    325   1.1  christos 	  {
    326   1.1  christos 	    as_bad (_("missing closing parenthesis"));
    327   1.1  christos 	    ignore_rest_of_line ();
    328   1.1  christos 	    return;
    329   1.1  christos 	  }
    330   1.1  christos 	op_end++;
    331   1.1  christos 	iword += (a << 4) + b;
    332  1.10  christos 	while (is_whitespace (*op_end))
    333   1.1  christos 	  op_end++;
    334   1.1  christos 	if (*op_end != 0)
    335   1.1  christos 	  as_warn (_("extra stuff on line ignored"));
    336   1.1  christos       }
    337   1.1  christos       break;
    338   1.1  christos     case MOXIE_F1_AiB:
    339   1.1  christos       iword = opcode->opcode << 8;
    340  1.10  christos       while (is_whitespace (*op_end))
    341   1.1  christos 	op_end++;
    342   1.1  christos       {
    343   1.1  christos 	int a, b;
    344   1.1  christos 	if (*op_end != '(')
    345   1.1  christos 	  {
    346   1.1  christos 	    as_bad (_("expecting indirect register `($rA)'"));
    347   1.1  christos 	    ignore_rest_of_line ();
    348   1.1  christos 	    return;
    349   1.1  christos 	  }
    350   1.1  christos 	op_end++;
    351   1.1  christos 	a = parse_register_operand (&op_end);
    352   1.1  christos 	if (*op_end != ')')
    353   1.1  christos 	  {
    354   1.1  christos 	    as_bad (_("missing closing parenthesis"));
    355   1.1  christos 	    ignore_rest_of_line ();
    356   1.1  christos 	    return;
    357   1.1  christos 	  }
    358   1.1  christos 	op_end++;
    359   1.1  christos 	if (*op_end != ',')
    360   1.1  christos 	  as_warn (_("expecting comma delimited register operands"));
    361   1.1  christos 	op_end++;
    362   1.1  christos 	b = parse_register_operand (&op_end);
    363   1.1  christos 	iword += (a << 4) + b;
    364  1.10  christos 	while (is_whitespace (*op_end))
    365   1.1  christos 	  op_end++;
    366   1.1  christos 	if (*op_end != 0)
    367   1.1  christos 	  as_warn (_("extra stuff on line ignored"));
    368   1.1  christos       }
    369   1.1  christos       break;
    370   1.1  christos     case MOXIE_F1_4A:
    371   1.1  christos       iword = opcode->opcode << 8;
    372  1.10  christos       while (is_whitespace (*op_end))
    373   1.1  christos 	op_end++;
    374   1.1  christos       {
    375   1.1  christos 	expressionS arg;
    376   1.1  christos 	char *where;
    377   1.1  christos 	int a;
    378   1.1  christos 
    379   1.1  christos 	op_end = parse_exp_save_ilp (op_end, &arg);
    380   1.1  christos 	where = frag_more (4);
    381   1.1  christos 	fix_new_exp (frag_now,
    382   1.1  christos 		     (where - frag_now->fr_literal),
    383   1.1  christos 		     4,
    384   1.1  christos 		     &arg,
    385   1.1  christos 		     0,
    386   1.1  christos 		     BFD_RELOC_32);
    387   1.1  christos 
    388   1.1  christos 	if (*op_end != ',')
    389   1.1  christos 	  {
    390   1.1  christos 	    as_bad (_("expecting comma delimited operands"));
    391   1.1  christos 	    ignore_rest_of_line ();
    392   1.1  christos 	    return;
    393   1.1  christos 	  }
    394   1.1  christos 	op_end++;
    395   1.1  christos 
    396   1.1  christos  	a = parse_register_operand (&op_end);
    397  1.10  christos 	while (is_whitespace (*op_end))
    398   1.1  christos 	  op_end++;
    399   1.1  christos 	if (*op_end != 0)
    400   1.1  christos 	  as_warn (_("extra stuff on line ignored"));
    401   1.1  christos 
    402   1.1  christos 	iword += (a << 4);
    403   1.1  christos       }
    404   1.1  christos       break;
    405   1.3  christos     case MOXIE_F1_ABi2:
    406   1.1  christos       iword = opcode->opcode << 8;
    407  1.10  christos       while (is_whitespace (*op_end))
    408   1.1  christos 	op_end++;
    409   1.1  christos       {
    410   1.1  christos 	expressionS arg;
    411   1.1  christos 	char *offset;
    412   1.1  christos 	int a, b;
    413   1.1  christos 
    414   1.1  christos  	a = parse_register_operand (&op_end);
    415  1.10  christos 	while (is_whitespace (*op_end))
    416   1.1  christos 	  op_end++;
    417   1.1  christos 
    418   1.1  christos 	if (*op_end != ',')
    419   1.1  christos 	  {
    420   1.1  christos 	    as_bad (_("expecting comma delimited operands"));
    421   1.1  christos 	    ignore_rest_of_line ();
    422   1.1  christos 	    return;
    423   1.1  christos 	  }
    424   1.1  christos 	op_end++;
    425   1.1  christos 
    426   1.1  christos 	op_end = parse_exp_save_ilp (op_end, &arg);
    427   1.3  christos 	offset = frag_more (2);
    428   1.1  christos 	fix_new_exp (frag_now,
    429   1.1  christos 		     (offset - frag_now->fr_literal),
    430   1.3  christos 		     2,
    431   1.1  christos 		     &arg,
    432   1.1  christos 		     0,
    433   1.3  christos 		     BFD_RELOC_16);
    434   1.1  christos 
    435   1.1  christos 	if (*op_end != '(')
    436   1.1  christos 	  {
    437   1.1  christos 	    as_bad (_("expecting indirect register `($rX)'"));
    438   1.1  christos 	    ignore_rest_of_line ();
    439   1.1  christos 	    return;
    440   1.1  christos 	  }
    441   1.1  christos 	op_end++;
    442   1.1  christos 	b = parse_register_operand (&op_end);
    443   1.1  christos 	if (*op_end != ')')
    444   1.1  christos 	  {
    445   1.1  christos 	    as_bad (_("missing closing parenthesis"));
    446   1.1  christos 	    ignore_rest_of_line ();
    447   1.1  christos 	    return;
    448   1.1  christos 	  }
    449   1.1  christos 	op_end++;
    450   1.1  christos 
    451  1.10  christos 	while (is_whitespace (*op_end))
    452   1.1  christos 	  op_end++;
    453   1.1  christos 	if (*op_end != 0)
    454   1.1  christos 	  as_warn (_("extra stuff on line ignored"));
    455   1.1  christos 
    456   1.1  christos 	iword += (a << 4) + b;
    457   1.1  christos       }
    458   1.1  christos       break;
    459   1.3  christos     case MOXIE_F1_AiB2:
    460   1.1  christos       iword = opcode->opcode << 8;
    461  1.10  christos       while (is_whitespace (*op_end))
    462   1.1  christos 	op_end++;
    463   1.1  christos       {
    464   1.1  christos 	expressionS arg;
    465   1.1  christos 	char *offset;
    466   1.1  christos 	int a, b;
    467   1.1  christos 
    468   1.1  christos 	op_end = parse_exp_save_ilp (op_end, &arg);
    469   1.3  christos 	offset = frag_more (2);
    470   1.1  christos 	fix_new_exp (frag_now,
    471   1.1  christos 		     (offset - frag_now->fr_literal),
    472   1.3  christos 		     2,
    473   1.1  christos 		     &arg,
    474   1.1  christos 		     0,
    475   1.3  christos 		     BFD_RELOC_16);
    476   1.1  christos 
    477   1.1  christos 	if (*op_end != '(')
    478   1.1  christos 	  {
    479   1.1  christos 	    as_bad (_("expecting indirect register `($rX)'"));
    480   1.1  christos 	    ignore_rest_of_line ();
    481   1.1  christos 	    return;
    482   1.1  christos 	  }
    483   1.1  christos 	op_end++;
    484   1.1  christos 	a = parse_register_operand (&op_end);
    485   1.1  christos 	if (*op_end != ')')
    486   1.1  christos 	  {
    487   1.1  christos 	    as_bad (_("missing closing parenthesis"));
    488   1.1  christos 	    ignore_rest_of_line ();
    489   1.1  christos 	    return;
    490   1.1  christos 	  }
    491   1.1  christos 	op_end++;
    492   1.1  christos 
    493   1.1  christos 	if (*op_end != ',')
    494   1.1  christos 	  {
    495   1.1  christos 	    as_bad (_("expecting comma delimited operands"));
    496   1.1  christos 	    ignore_rest_of_line ();
    497   1.1  christos 	    return;
    498   1.1  christos 	  }
    499   1.1  christos 	op_end++;
    500   1.1  christos 
    501   1.1  christos  	b = parse_register_operand (&op_end);
    502  1.10  christos 	while (is_whitespace (*op_end))
    503   1.1  christos 	  op_end++;
    504   1.1  christos 	if (*op_end != 0)
    505   1.1  christos 	  as_warn (_("extra stuff on line ignored"));
    506   1.1  christos 
    507   1.1  christos 	iword += (a << 4) + b;
    508   1.1  christos       }
    509   1.1  christos       break;
    510   1.1  christos     case MOXIE_F2_NARG:
    511   1.1  christos       iword = opcode->opcode << 12;
    512  1.10  christos       while (is_whitespace (*op_end))
    513   1.1  christos 	op_end++;
    514   1.1  christos       if (*op_end != 0)
    515   1.1  christos 	as_warn (_("extra stuff on line ignored"));
    516   1.1  christos       break;
    517   1.1  christos     case MOXIE_F3_PCREL:
    518   1.1  christos       iword = (3<<14) | (opcode->opcode << 10);
    519  1.10  christos       while (is_whitespace (*op_end))
    520   1.1  christos 	op_end++;
    521   1.1  christos       {
    522   1.1  christos 	expressionS arg;
    523   1.1  christos 
    524   1.1  christos 	op_end = parse_exp_save_ilp (op_end, &arg);
    525   1.1  christos 	fix_new_exp (frag_now,
    526   1.1  christos 		     (p - frag_now->fr_literal),
    527   1.1  christos 		     2,
    528   1.1  christos 		     &arg,
    529   1.8  christos 		     true,
    530   1.1  christos 		     BFD_RELOC_MOXIE_10_PCREL);
    531   1.1  christos       }
    532   1.1  christos       break;
    533   1.6  christos     case MOXIE_BAD:
    534   1.6  christos       iword = 0;
    535  1.10  christos       while (is_whitespace (*op_end))
    536   1.6  christos 	op_end++;
    537   1.6  christos       if (*op_end != 0)
    538   1.6  christos 	as_warn (_("extra stuff on line ignored"));
    539   1.6  christos       break;
    540   1.1  christos     default:
    541   1.1  christos       abort ();
    542   1.1  christos     }
    543   1.1  christos 
    544   1.1  christos   md_number_to_chars (p, iword, 2);
    545   1.5  christos   dwarf2_emit_insn (2);
    546   1.1  christos 
    547  1.10  christos   while (is_whitespace (*op_end))
    548   1.1  christos     op_end++;
    549   1.1  christos 
    550   1.1  christos   if (*op_end != 0)
    551   1.1  christos     as_warn (_("extra stuff on line ignored"));
    552   1.1  christos 
    553   1.1  christos   if (pending_reloc)
    554   1.1  christos     as_bad (_("Something forgot to clean up\n"));
    555   1.1  christos }
    556   1.1  christos 
    557   1.1  christos /* Turn a string in input_line_pointer into a floating point constant
    558   1.1  christos    of type type, and store the appropriate bytes in *LITP.  The number
    559   1.1  christos    of LITTLENUMS emitted is stored in *SIZEP .  An error message is
    560   1.1  christos    returned, or NULL on OK.  */
    561   1.1  christos 
    562   1.5  christos const char *
    563   1.1  christos md_atof (int type, char *litP, int *sizeP)
    564   1.1  christos {
    565   1.1  christos   int prec;
    566   1.1  christos   LITTLENUM_TYPE words[4];
    567   1.1  christos   char *t;
    568   1.1  christos   int i;
    569   1.1  christos 
    570   1.1  christos   switch (type)
    571   1.1  christos     {
    572   1.1  christos     case 'f':
    573   1.1  christos       prec = 2;
    574   1.1  christos       break;
    575   1.1  christos 
    576   1.1  christos     case 'd':
    577   1.1  christos       prec = 4;
    578   1.1  christos       break;
    579   1.1  christos 
    580   1.1  christos     default:
    581   1.1  christos       *sizeP = 0;
    582   1.1  christos       return _("bad call to md_atof");
    583   1.1  christos     }
    584   1.1  christos 
    585   1.1  christos   t = atof_ieee (input_line_pointer, type, words);
    586   1.1  christos   if (t)
    587   1.1  christos     input_line_pointer = t;
    588   1.1  christos 
    589   1.1  christos   *sizeP = prec * 2;
    590   1.1  christos 
    591   1.1  christos   for (i = prec - 1; i >= 0; i--)
    592   1.1  christos     {
    593  1.10  christos       md_number_to_chars (litP, words[i], 2);
    594   1.1  christos       litP += 2;
    595   1.1  christos     }
    596   1.1  christos 
    597   1.1  christos   return NULL;
    598   1.1  christos }
    599   1.3  christos 
    600   1.3  christos enum options
    601   1.3  christos {
    602   1.3  christos   OPTION_EB = OPTION_MD_BASE,
    603   1.3  christos   OPTION_EL,
    604   1.3  christos };
    605   1.1  christos 
    606  1.10  christos const struct option md_longopts[] =
    607   1.1  christos {
    608   1.3  christos   { "EB",          no_argument, NULL, OPTION_EB},
    609   1.3  christos   { "EL",          no_argument, NULL, OPTION_EL},
    610   1.3  christos   { NULL,          no_argument, NULL, 0}
    611   1.1  christos };
    612   1.3  christos 
    613  1.10  christos const size_t md_longopts_size = sizeof (md_longopts);
    614   1.3  christos 
    615  1.10  christos const char md_shortopts[] = "";
    617   1.1  christos 
    618   1.5  christos int
    619   1.1  christos md_parse_option (int c ATTRIBUTE_UNUSED, const char *arg ATTRIBUTE_UNUSED)
    620   1.3  christos {
    621   1.3  christos   switch (c)
    622   1.3  christos     {
    623   1.3  christos     case OPTION_EB:
    624   1.3  christos       target_big_endian = 1;
    625   1.3  christos       break;
    626   1.3  christos     case OPTION_EL:
    627   1.3  christos       target_big_endian = 0;
    628   1.3  christos       break;
    629   1.3  christos     default:
    630   1.3  christos       return 0;
    631   1.3  christos     }
    632   1.3  christos 
    633   1.1  christos   return 1;
    634   1.1  christos }
    635   1.1  christos 
    636   1.1  christos void
    637   1.1  christos md_show_usage (FILE *stream ATTRIBUTE_UNUSED)
    638   1.3  christos {
    639   1.3  christos   fprintf (stream, _("\
    640   1.3  christos   -EB                     assemble for a big endian system (default)\n\
    641   1.1  christos   -EL                     assemble for a little endian system\n"));
    642   1.1  christos }
    643   1.1  christos 
    644   1.1  christos /* Apply a fixup to the object file.  */
    645   1.1  christos 
    646   1.3  christos void
    647   1.1  christos md_apply_fix (fixS *fixP ATTRIBUTE_UNUSED,
    648   1.1  christos 	      valueT * valP ATTRIBUTE_UNUSED, segT seg ATTRIBUTE_UNUSED)
    649   1.1  christos {
    650   1.1  christos   char *buf = fixP->fx_where + fixP->fx_frag->fr_literal;
    651   1.1  christos   long val = *valP;
    652   1.1  christos   long newval;
    653   1.1  christos   long max, min;
    654   1.1  christos 
    655   1.1  christos   max = min = 0;
    656   1.1  christos   switch (fixP->fx_r_type)
    657   1.1  christos     {
    658   1.3  christos     case BFD_RELOC_32:
    659   1.3  christos       if (target_big_endian)
    660   1.3  christos 	{
    661   1.3  christos 	  buf[0] = val >> 24;
    662   1.3  christos 	  buf[1] = val >> 16;
    663   1.3  christos 	  buf[2] = val >> 8;
    664   1.3  christos 	  buf[3] = val >> 0;
    665   1.3  christos 	}
    666   1.3  christos       else
    667   1.3  christos 	{
    668   1.3  christos 	  buf[3] = val >> 24;
    669   1.3  christos 	  buf[2] = val >> 16;
    670   1.3  christos 	  buf[1] = val >> 8;
    671   1.3  christos 	  buf[0] = val >> 0;
    672   1.3  christos 	}
    673   1.1  christos       buf += 4;
    674   1.1  christos       break;
    675   1.1  christos 
    676   1.3  christos     case BFD_RELOC_16:
    677   1.3  christos       if (target_big_endian)
    678   1.3  christos 	{
    679   1.3  christos 	  buf[0] = val >> 8;
    680   1.3  christos 	  buf[1] = val >> 0;
    681   1.3  christos 	}
    682   1.3  christos       else
    683   1.3  christos 	{
    684   1.3  christos 	  buf[1] = val >> 8;
    685   1.3  christos 	  buf[0] = val >> 0;
    686   1.3  christos 	}
    687   1.1  christos       buf += 2;
    688   1.1  christos       break;
    689   1.1  christos 
    690   1.1  christos     case BFD_RELOC_8:
    691   1.1  christos       *buf++ = val;
    692   1.1  christos       break;
    693   1.1  christos 
    694   1.1  christos     case BFD_RELOC_MOXIE_10_PCREL:
    695   1.1  christos       if (!val)
    696   1.1  christos 	break;
    697   1.1  christos       if (val < -1024 || val > 1022)
    698   1.1  christos 	as_bad_where (fixP->fx_file, fixP->fx_line,
    699   1.1  christos                       _("pcrel too far BFD_RELOC_MOXIE_10"));
    700   1.1  christos       /* 11 bit offset even numbered, so we remove right bit.  */
    701   1.1  christos       val >>= 1;
    702   1.1  christos       newval = md_chars_to_number (buf, 2);
    703   1.1  christos       newval |= val & 0x03ff;
    704   1.1  christos       md_number_to_chars (buf, newval, 2);
    705   1.1  christos       break;
    706   1.1  christos 
    707   1.1  christos     default:
    708   1.1  christos       abort ();
    709   1.1  christos     }
    710   1.1  christos 
    711   1.1  christos   if (max != 0 && (val < min || val > max))
    712   1.1  christos     as_bad_where (fixP->fx_file, fixP->fx_line, _("offset out of range"));
    713   1.1  christos 
    714   1.1  christos   if (fixP->fx_addsy == NULL && fixP->fx_pcrel == 0)
    715   1.1  christos     fixP->fx_done = 1;
    716   1.1  christos }
    717   1.3  christos 
    718   1.1  christos /* Put number into target byte order.  */
    719   1.1  christos 
    720   1.3  christos void
    721   1.1  christos md_number_to_chars (char * ptr, valueT use, int nbytes)
    722   1.3  christos {
    723   1.3  christos   if (target_big_endian)
    724   1.3  christos     number_to_chars_bigendian (ptr, use, nbytes);
    725   1.3  christos   else
    726   1.1  christos     number_to_chars_littleendian (ptr, use, nbytes);
    727   1.1  christos }
    728   1.1  christos 
    729   1.1  christos /* Convert from target byte order to host byte order.  */
    730   1.3  christos 
    731   1.3  christos static valueT
    732   1.1  christos md_chars_to_number (char * buf, int n)
    733   1.3  christos {
    734   1.1  christos   valueT result = 0;
    735   1.3  christos 
    736   1.3  christos   if (target_big_endian)
    737   1.3  christos     {
    738   1.3  christos       while (n--)
    739   1.3  christos 	{
    740  1.10  christos 	  result <<= 8;
    741   1.3  christos 	  result |= (*buf++ & 255);
    742   1.3  christos 	}
    743   1.3  christos     }
    744   1.1  christos   else
    745   1.3  christos     {
    746   1.3  christos       while (n--)
    747   1.3  christos 	{
    748  1.10  christos 	  result <<= 8;
    749   1.3  christos 	  result |= (buf[n] & 255);
    750   1.1  christos 	}
    751   1.1  christos     }
    752   1.3  christos 
    753   1.1  christos   return result;
    754   1.1  christos }
    755   1.1  christos 
    756   1.1  christos /* Generate a machine-dependent relocation.  */
    757   1.1  christos arelent *
    758   1.1  christos tc_gen_reloc (asection *section ATTRIBUTE_UNUSED, fixS *fixP)
    759   1.1  christos {
    760   1.1  christos   arelent *relP;
    761   1.1  christos   bfd_reloc_code_real_type code;
    762   1.1  christos 
    763   1.1  christos   switch (fixP->fx_r_type)
    764   1.1  christos     {
    765   1.1  christos     case BFD_RELOC_32:
    766   1.1  christos       code = fixP->fx_r_type;
    767   1.1  christos       break;
    768   1.1  christos     case BFD_RELOC_MOXIE_10_PCREL:
    769   1.1  christos       code = fixP->fx_r_type;
    770   1.1  christos       break;
    771   1.1  christos     default:
    772   1.1  christos       as_bad_where (fixP->fx_file, fixP->fx_line,
    773   1.1  christos 		    _("Semantics error.  This type of operand can not be relocated, it must be an assembly-time constant"));
    774   1.1  christos       return 0;
    775   1.1  christos     }
    776  1.10  christos 
    777  1.10  christos   relP = notes_alloc (sizeof (arelent));
    778   1.1  christos   relP->sym_ptr_ptr = notes_alloc (sizeof (asymbol *));
    779   1.1  christos   *relP->sym_ptr_ptr = symbol_get_bfdsym (fixP->fx_addsy);
    780   1.1  christos   relP->address = fixP->fx_frag->fr_address + fixP->fx_where;
    781   1.1  christos 
    782   1.1  christos   relP->addend = fixP->fx_offset;
    783   1.1  christos 
    784   1.1  christos   /* This is the standard place for KLUDGEs to work around bugs in
    785   1.1  christos      bfd_install_relocation (first such note in the documentation
    786   1.1  christos      appears with binutils-2.8).
    787   1.1  christos 
    788   1.1  christos      That function bfd_install_relocation does the wrong thing with
    789   1.1  christos      putting stuff into the addend of a reloc (it should stay out) for a
    790   1.1  christos      weak symbol.  The really bad thing is that it adds the
    791   1.1  christos      "segment-relative offset" of the symbol into the reloc.  In this
    792   1.1  christos      case, the reloc should instead be relative to the symbol with no
    793   1.1  christos      other offset than the assembly code shows; and since the symbol is
    794   1.1  christos      weak, any local definition should be ignored until link time (or
    795   1.1  christos      thereafter).
    796   1.1  christos      To wit:  weaksym+42  should be weaksym+42 in the reloc,
    797   1.1  christos      not weaksym+(offset_from_segment_of_local_weaksym_definition)
    798   1.1  christos 
    799   1.1  christos      To "work around" this, we subtract the segment-relative offset of
    800   1.1  christos      "known" weak symbols.  This evens out the extra offset.
    801   1.1  christos 
    802   1.1  christos      That happens for a.out but not for ELF, since for ELF,
    803   1.1  christos      bfd_install_relocation uses the "special function" field of the
    804   1.1  christos      howto, and does not execute the code that needs to be undone.  */
    805   1.1  christos 
    806   1.1  christos   if (OUTPUT_FLAVOR == bfd_target_aout_flavour
    807   1.1  christos       && fixP->fx_addsy && S_IS_WEAK (fixP->fx_addsy)
    808   1.1  christos       && ! bfd_is_und_section (S_GET_SEGMENT (fixP->fx_addsy)))
    809   1.1  christos     {
    810   1.1  christos       relP->addend -= S_GET_VALUE (fixP->fx_addsy);
    811   1.1  christos     }
    812   1.1  christos 
    813   1.1  christos   relP->howto = bfd_reloc_type_lookup (stdoutput, code);
    814   1.1  christos   if (! relP->howto)
    815   1.1  christos     {
    816   1.1  christos       const char *name;
    817   1.1  christos 
    818   1.1  christos       name = S_GET_NAME (fixP->fx_addsy);
    819   1.1  christos       if (name == NULL)
    820   1.1  christos 	name = _("<unknown>");
    821   1.1  christos       as_fatal (_("Cannot generate relocation type for symbol %s, code %s"),
    822   1.1  christos 		name, bfd_get_reloc_code_name (code));
    823   1.1  christos     }
    824   1.1  christos 
    825   1.1  christos   return relP;
    826   1.1  christos }
    827   1.1  christos 
    828   1.1  christos /* Decide from what point a pc-relative relocation is relative to,
    829   1.1  christos    relative to the pc-relative fixup.  Er, relatively speaking.  */
    830   1.1  christos long
    831   1.1  christos md_pcrel_from (fixS *fixP)
    832   1.1  christos {
    833   1.1  christos   valueT addr = fixP->fx_where + fixP->fx_frag->fr_address;
    834   1.1  christos 
    835   1.1  christos   switch (fixP->fx_r_type)
    836   1.1  christos     {
    837   1.1  christos     case BFD_RELOC_32:
    838   1.1  christos       return addr + 4;
    839   1.3  christos     case BFD_RELOC_MOXIE_10_PCREL:
    840   1.3  christos       /* Offset is from the end of the instruction.  */
    841   1.1  christos       return addr + 2;
    842   1.1  christos     default:
    843   1.1  christos       abort ();
    844   1.1  christos       return addr;
    845   1.1  christos     }
    846                 }
    847