1/* tc-ft32.c -- Assemble code for ft32
2   Copyright (C) 2008-2017 Free Software Foundation, Inc.
3
4   This file is part of GAS, the GNU Assembler.
5
6   GAS is free software; you can redistribute it and/or modify
7   it under the terms of the GNU General Public License as published by
8   the Free Software Foundation; either version 3, or (at your option)
9   any later version.
10
11   GAS is distributed in the hope that it will be useful,
12   but WITHOUT ANY WARRANTY; without even the implied warranty of
13   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14   GNU General Public License for more details.
15
16   You should have received a copy of the GNU General Public License
17   along with GAS; see the file COPYING.  If not, write to
18   the Free Software Foundation, 51 Franklin Street - Fifth Floor,
19   Boston, MA 02110-1301, USA.  */
20
21/* Contributed by Anthony Green <green@spindazzle.org>.  */
22
23#include "as.h"
24#include "safe-ctype.h"
25#include "opcode/ft32.h"
26
27extern const ft32_opc_info_t ft32_opc_info[128];
28
29const char comment_chars[]        = "#";
30const char line_separator_chars[] = ";";
31const char line_comment_chars[]   = "#";
32
33static int pending_reloc;
34static struct hash_control *opcode_hash_control;
35
36static valueT md_chars_to_number (char * buf, int n);
37
38const pseudo_typeS md_pseudo_table[] =
39{
40  {0, 0, 0}
41};
42
43const char FLT_CHARS[] = "rRsSfFdDxXpP";
44const char EXP_CHARS[] = "eE";
45
46/* This function is called once, at assembler startup time.  It sets
47   up the hash table with all the opcodes in it, and also initializes
48   some aliases for compatibility with other assemblers.  */
49
50void
51md_begin (void)
52{
53  const ft32_opc_info_t *opcode;
54  opcode_hash_control = hash_new ();
55
56  /* Insert names into hash table.  */
57  for (opcode = ft32_opc_info; opcode->name; opcode++)
58    hash_insert (opcode_hash_control, opcode->name, (char *) opcode);
59
60  bfd_set_arch_mach (stdoutput, TARGET_ARCH, 0);
61}
62
63/* Parse an expression and then restore the input line pointer.  */
64
65static char *
66parse_exp_save_ilp (char *s, expressionS *op)
67{
68  char *save = input_line_pointer;
69
70  input_line_pointer = s;
71  expression (op);
72  s = input_line_pointer;
73  input_line_pointer = save;
74  return s;
75}
76
77static int
78parse_condition (char **ptr)
79{
80  char *s = *ptr;
81  static const struct {
82    const char *name;
83    int bits;
84  } ccs[] = {
85    { "gt,"   , (2 << FT32_FLD_CR_BIT) | (5 << FT32_FLD_CB_BIT) | (1 << FT32_FLD_CV_BIT)},
86    { "gte,"  , (2 << FT32_FLD_CR_BIT) | (4 << FT32_FLD_CB_BIT) | (1 << FT32_FLD_CV_BIT)},
87    { "lt,"   , (2 << FT32_FLD_CR_BIT) | (4 << FT32_FLD_CB_BIT) | (0 << FT32_FLD_CV_BIT)},
88    { "lte,"  , (2 << FT32_FLD_CR_BIT) | (5 << FT32_FLD_CB_BIT) | (0 << FT32_FLD_CV_BIT)},
89    { "a,"    , (2 << FT32_FLD_CR_BIT) | (6 << FT32_FLD_CB_BIT) | (1 << FT32_FLD_CV_BIT)},
90    { "ae,"   , (2 << FT32_FLD_CR_BIT) | (1 << FT32_FLD_CB_BIT) | (0 << FT32_FLD_CV_BIT)},
91    { "be,"   , (2 << FT32_FLD_CR_BIT) | (6 << FT32_FLD_CB_BIT) | (0 << FT32_FLD_CV_BIT)},
92    { "b,"    , (2 << FT32_FLD_CR_BIT) | (1 << FT32_FLD_CB_BIT) | (1 << FT32_FLD_CV_BIT)},
93    { "nz,"   , (2 << FT32_FLD_CR_BIT) | (0 << FT32_FLD_CB_BIT) | (0 << FT32_FLD_CV_BIT)},
94    { "z,"    , (2 << FT32_FLD_CR_BIT) | (0 << FT32_FLD_CB_BIT) | (1 << FT32_FLD_CV_BIT)},
95    { "nc,"   , (2 << FT32_FLD_CR_BIT) | (1 << FT32_FLD_CB_BIT) | (0 << FT32_FLD_CV_BIT)},
96    { "c,"    , (2 << FT32_FLD_CR_BIT) | (1 << FT32_FLD_CB_BIT) | (1 << FT32_FLD_CV_BIT)},
97    { "no,"   , (2 << FT32_FLD_CR_BIT) | (2 << FT32_FLD_CB_BIT) | (0 << FT32_FLD_CV_BIT)},
98    { "o,"    , (2 << FT32_FLD_CR_BIT) | (2 << FT32_FLD_CB_BIT) | (1 << FT32_FLD_CV_BIT)},
99    { "ns,"   , (2 << FT32_FLD_CR_BIT) | (3 << FT32_FLD_CB_BIT) | (0 << FT32_FLD_CV_BIT)},
100    { "s,"    , (2 << FT32_FLD_CR_BIT) | (3 << FT32_FLD_CB_BIT) | (1 << FT32_FLD_CV_BIT)},
101    { NULL, 0}
102  }, *pc;
103
104  for (pc = ccs; pc->name; pc++)
105    {
106      if (memcmp(pc->name, s, strlen(pc->name)) == 0)
107        {
108          *ptr += strlen(pc->name) - 1;
109          return pc->bits;
110        }
111    }
112  return -1;
113}
114
115static int
116parse_decimal (char **ptr)
117{
118  int r = 0;
119  char *s = *ptr;
120
121  while (('0' <= *s) && (*s <= '9'))
122    {
123      r *= 10;
124      r += (*s++ - '0');
125    }
126  *ptr = s;
127  return r;
128}
129
130static int
131parse_register_operand (char **ptr)
132{
133  int reg;
134  char *s = *ptr;
135
136  if (*s != '$')
137    {
138      as_bad (_("expecting register"));
139      ignore_rest_of_line ();
140      return -1;
141    }
142  if ((s[1] == 's') && (s[2] == 'p'))
143    {
144      reg = 31;
145    }
146  else if ((s[1] == 'c') && (s[2] == 'c'))
147    {
148      reg = 30;
149    }
150  else if ((s[1] == 'f') && (s[2] == 'p'))
151    {
152      reg = 29;
153    }
154  else if (s[1] == 'r')
155    {
156      reg = s[2] - '0';
157      if ((reg < 0) || (reg > 9))
158	{
159	  as_bad (_("illegal register number"));
160	  ignore_rest_of_line ();
161	  return -1;
162	}
163      if ((reg == 1) || (reg == 2) || (reg == 3))
164	{
165	  int r2 = s[3] - '0';
166	  if ((r2 >= 0) && (r2 <= 9))
167	    {
168	      reg = (reg * 10) + r2;
169	      *ptr += 1;
170	    }
171	}
172    }
173  else
174    {
175      as_bad (_("illegal register number"));
176      ignore_rest_of_line ();
177      return -1;
178    }
179
180  *ptr += 3;
181
182  return reg;
183}
184
185/* This is the guts of the machine-dependent assembler.  STR points to
186   a machine dependent instruction.  This function is supposed to emit
187   the frags/bytes it assembles to.  */
188
189void
190md_assemble (char *str)
191{
192  char *op_start;
193  char *op_end;
194
195  ft32_opc_info_t *opcode;
196  char *output;
197  int idx = 0;
198  char pend;
199
200  int nlen = 0;
201
202  unsigned int b;
203  int f;
204
205  expressionS arg;
206
207  /* Drop leading whitespace.  */
208  while (*str == ' ')
209    str++;
210
211  /* Find the op code end.  */
212  op_start = str;
213  for (op_end = str;
214       *op_end && !is_end_of_line[*op_end & 0xff] && *op_end != ' ' && *op_end != '.';
215       op_end++)
216    nlen++;
217
218  pend = *op_end;
219  *op_end = 0;
220
221  if (nlen == 0)
222    as_bad (_("can't find opcode "));
223
224  opcode = (ft32_opc_info_t *) hash_find (opcode_hash_control, op_start);
225  *op_end = pend;
226
227  if (opcode == NULL)
228    {
229      as_bad (_("unknown opcode %s"), op_start);
230      return;
231    }
232
233  b = opcode->bits;
234  f = opcode->fields;
235
236  if (opcode->dw)
237    {
238      int dw;
239      if (*op_end == '.')
240        {
241          switch (op_end[1])
242            {
243              case 'b':
244                dw = 0;
245                break;
246              case 's':
247                dw = 1;
248                break;
249              case 'l':
250                dw = 2;
251                break;
252              default:
253                as_bad (_("unknown width specifier '.%c'"), op_end[1]);
254                return;
255            }
256          op_end += 2;
257        }
258      else
259        {
260          dw = 2; /* default is ".l" */
261        }
262      b |= dw << FT32_FLD_DW_BIT;
263    }
264
265  while (ISSPACE (*op_end))
266    op_end++;
267
268  output = frag_more (4);
269
270  while (f)
271    {
272      int lobit = f & -f;
273      if (f & lobit)
274        {
275          switch (lobit)
276          {
277          case  FT32_FLD_CBCRCV:
278            b |= parse_condition( &op_end);
279            break;
280          case  FT32_FLD_CB:
281            b |= parse_decimal (&op_end) << FT32_FLD_CB_BIT;
282            break;
283          case  FT32_FLD_R_D:
284            b |= parse_register_operand (&op_end) << FT32_FLD_R_D_BIT;
285            break;
286          case  FT32_FLD_CR:
287            b |= (parse_register_operand (&op_end) - 28) << FT32_FLD_CR_BIT;
288            break;
289          case  FT32_FLD_CV:
290            b |= parse_decimal (&op_end) << FT32_FLD_CV_BIT;
291            break;
292          case  FT32_FLD_R_1:
293            b |= parse_register_operand (&op_end) << FT32_FLD_R_1_BIT;
294            break;
295          case  FT32_FLD_RIMM:
296            if (*op_end == '$')
297              {
298                b |= parse_register_operand (&op_end) << FT32_FLD_RIMM_BIT;
299              }
300            else
301              {
302                b |= 0x400 << FT32_FLD_RIMM_BIT;
303                op_end = parse_exp_save_ilp (op_end, &arg);
304                fix_new_exp (frag_now,
305                             (output - frag_now->fr_literal),
306                             2,
307                             &arg,
308                             0,
309                             BFD_RELOC_FT32_10);
310              }
311            break;
312          case  FT32_FLD_R_2:
313            b |= parse_register_operand (&op_end) << FT32_FLD_R_2_BIT;
314            break;
315          case  FT32_FLD_K20:
316            op_end = parse_exp_save_ilp (op_end, &arg);
317            fix_new_exp (frag_now,
318                         (output - frag_now->fr_literal),
319                         3,
320                         &arg,
321                         0,
322                         BFD_RELOC_FT32_20);
323            break;
324          case  FT32_FLD_PA:
325            op_end = parse_exp_save_ilp (op_end, &arg);
326            fix_new_exp (frag_now,
327                         (output - frag_now->fr_literal),
328                         3,
329                         &arg,
330                         0,
331                         BFD_RELOC_FT32_18);
332            break;
333          case  FT32_FLD_AA:
334            op_end = parse_exp_save_ilp (op_end, &arg);
335            fix_new_exp (frag_now,
336                         (output - frag_now->fr_literal),
337                         3,
338                         &arg,
339                         0,
340                         BFD_RELOC_FT32_17);
341            break;
342          case  FT32_FLD_K16:
343            op_end = parse_exp_save_ilp (op_end, &arg);
344            fix_new_exp (frag_now,
345                         (output - frag_now->fr_literal),
346                         2,
347                         &arg,
348                         0,
349                         BFD_RELOC_16);
350            break;
351          case  FT32_FLD_K8:
352            op_end = parse_exp_save_ilp (op_end, &arg);
353            fix_new_exp (frag_now,
354                         (output - frag_now->fr_literal),
355                         1,
356                         &arg,
357                         0,
358                         BFD_RELOC_8);
359            break;
360          case  FT32_FLD_R_D_POST:
361            b |= parse_register_operand (&op_end) << FT32_FLD_R_D_BIT;
362            break;
363          case  FT32_FLD_R_1_POST:
364            b |= parse_register_operand (&op_end) << FT32_FLD_R_1_BIT;
365            break;
366          default:
367            as_bad (_("internal error in argument parsing"));
368            break;
369          }
370          f &= ~lobit;
371          if (f)
372            {
373              while (ISSPACE (*op_end))
374                op_end++;
375
376              if (*op_end != ',')
377                {
378                  as_bad (_("expected comma separator"));
379                  ignore_rest_of_line ();
380                }
381
382              op_end++;
383              while (ISSPACE (*op_end))
384                op_end++;
385            }
386        }
387    }
388  if (*op_end != 0)
389    as_warn (_("extra stuff on line ignored"));
390
391  output[idx++] = 0xff & (b >> 0);
392  output[idx++] = 0xff & (b >> 8);
393  output[idx++] = 0xff & (b >> 16);
394  output[idx++] = 0xff & (b >> 24);
395
396  dwarf2_emit_insn (4);
397
398  while (ISSPACE (*op_end))
399    op_end++;
400
401  if (*op_end != 0)
402    as_warn ("extra stuff on line ignored");
403
404  if (pending_reloc)
405    as_bad ("Something forgot to clean up\n");
406}
407
408/* Turn a string in input_line_pointer into a floating point constant
409   of type type, and store the appropriate bytes in *LITP.  The number
410   of LITTLENUMS emitted is stored in *SIZEP .  An error message is
411   returned, or NULL on OK.  */
412
413const char *
414md_atof (int type, char *litP, int *sizeP)
415{
416  int prec;
417  LITTLENUM_TYPE words[4];
418  char *t;
419  int i;
420
421  switch (type)
422    {
423    case 'f':
424      prec = 2;
425      break;
426
427    case 'd':
428      prec = 4;
429      break;
430
431    default:
432      *sizeP = 0;
433      return _("bad call to md_atof");
434    }
435
436  t = atof_ieee (input_line_pointer, type, words);
437  if (t)
438    input_line_pointer = t;
439
440  *sizeP = prec * 2;
441
442  for (i = prec - 1; i >= 0; i--)
443    {
444      md_number_to_chars (litP, (valueT) words[i], 2);
445      litP += 2;
446    }
447
448  return NULL;
449}
450
451const char *md_shortopts = "";
452
453struct option md_longopts[] =
454{
455  {NULL, no_argument, NULL, 0}
456};
457size_t md_longopts_size = sizeof (md_longopts);
458
459/* We have no target specific options yet, so these next
460   two functions are empty.  */
461int
462md_parse_option (int c ATTRIBUTE_UNUSED, const char *arg ATTRIBUTE_UNUSED)
463{
464  return 0;
465}
466
467void
468md_show_usage (FILE *stream ATTRIBUTE_UNUSED)
469{
470}
471
472/* Convert from target byte order to host byte order.  */
473
474static valueT
475md_chars_to_number (char * buf, int n)
476{
477  valueT result = 0;
478  unsigned char * where = (unsigned char *) buf;
479
480  while (n--)
481    {
482      result <<= 8;
483      result |= (where[n] & 255);
484    }
485
486  return result;
487}
488/* Apply a fixup to the object file.  */
489
490void
491md_apply_fix (fixS *fixP ATTRIBUTE_UNUSED,
492	      valueT * valP ATTRIBUTE_UNUSED, segT seg ATTRIBUTE_UNUSED)
493{
494  char *buf = fixP->fx_where + fixP->fx_frag->fr_literal;
495  long val = *valP;
496  long newval;
497
498  switch (fixP->fx_r_type)
499    {
500    case BFD_RELOC_32:
501      buf[3] = val >> 24;
502      buf[2] = val >> 16;
503      buf[1] = val >> 8;
504      buf[0] = val >> 0;
505      break;
506
507    case BFD_RELOC_16:
508      buf[1] = val >> 8;
509      buf[0] = val >> 0;
510      break;
511
512    case BFD_RELOC_8:
513      *buf = val;
514      break;
515
516    case BFD_RELOC_FT32_10:
517      if (!val)
518	break;
519      newval = md_chars_to_number (buf, 2);
520      newval |= (val & ((1 << 10) - 1)) << FT32_FLD_RIMM_BIT;
521      md_number_to_chars (buf, newval, 2);
522      break;
523
524    case BFD_RELOC_FT32_20:
525      if (!val)
526	break;
527      newval = md_chars_to_number (buf, 3);
528      newval |= val & ((1 << 20) - 1);
529      md_number_to_chars (buf, newval, 3);
530      break;
531
532    case BFD_RELOC_FT32_17:
533      if (!val)
534	break;
535      newval = md_chars_to_number (buf, 3);
536      newval |= val & ((1 << 17) - 1);
537      md_number_to_chars (buf, newval, 3);
538      break;
539
540    case BFD_RELOC_FT32_18:
541      if (!val)
542	break;
543      newval = md_chars_to_number (buf, 4);
544      newval |= (val >> 2) & ((1 << 18) - 1);
545      md_number_to_chars (buf, newval, 4);
546      break;
547
548    default:
549      abort ();
550    }
551
552  if (fixP->fx_addsy == NULL && fixP->fx_pcrel == 0)
553    fixP->fx_done = 1;
554  // printf("fx_addsy=%p fixP->fx_pcrel=%d fx_done=%d\n", fixP->fx_addsy, fixP->fx_pcrel, fixP->fx_done);
555}
556
557void
558md_number_to_chars (char *ptr, valueT use, int nbytes)
559{
560  number_to_chars_littleendian (ptr, use, nbytes);
561}
562
563/* Generate a machine-dependent relocation.  */
564arelent *
565tc_gen_reloc (asection *section ATTRIBUTE_UNUSED, fixS *fixP)
566{
567  arelent *relP;
568  bfd_reloc_code_real_type code;
569
570  switch (fixP->fx_r_type)
571    {
572    case BFD_RELOC_32:
573    case BFD_RELOC_16:
574    case BFD_RELOC_8:
575    case BFD_RELOC_FT32_10:
576    case BFD_RELOC_FT32_20:
577    case BFD_RELOC_FT32_17:
578    case BFD_RELOC_FT32_18:
579      code = fixP->fx_r_type;
580      break;
581    default:
582      as_bad_where (fixP->fx_file, fixP->fx_line,
583		    _("Semantics error.  This type of operand can not be relocated, it must be an assembly-time constant"));
584      return 0;
585    }
586
587  relP = XNEW (arelent);
588  gas_assert (relP != 0);
589  relP->sym_ptr_ptr = XNEW (asymbol *);
590  *relP->sym_ptr_ptr = symbol_get_bfdsym (fixP->fx_addsy);
591  relP->address = fixP->fx_frag->fr_address + fixP->fx_where;
592
593  relP->addend = fixP->fx_offset;
594
595  relP->howto = bfd_reloc_type_lookup (stdoutput, code);
596  if (! relP->howto)
597    {
598      const char *name;
599
600      name = S_GET_NAME (fixP->fx_addsy);
601      if (name == NULL)
602	name = _("<unknown>");
603      as_fatal (_("Cannot generate relocation type for symbol %s, code %s"),
604		name, bfd_get_reloc_code_name (code));
605    }
606
607  return relP;
608}
609