37642bd20f6213e790d0baba874e4be1e00ef509
[external/binutils.git] / gas / config / tc-ft32.c
1 /* tc-ft32.c -- Assemble code for ft32
2    Copyright (C) 2008-2016 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
27 extern const ft32_opc_info_t ft32_opc_info[128];
28
29 const char comment_chars[]        = "#";
30 const char line_separator_chars[] = ";";
31 const char line_comment_chars[]   = "#";
32
33 static int pending_reloc;
34 static struct hash_control *opcode_hash_control;
35
36 static valueT md_chars_to_number (char * buf, int n);
37
38 const pseudo_typeS md_pseudo_table[] =
39 {
40   {0, 0, 0}
41 };
42
43 const char FLT_CHARS[] = "rRsSfFdDxXpP";
44 const 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
50 void
51 md_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
65 static char *
66 parse_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
77 static int
78 parse_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
115 static int
116 parse_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
130 static int
131 parse_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
189 void
190 md_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
413 const char *
414 md_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 \f
451 const char *md_shortopts = "";
452
453 struct option md_longopts[] =
454 {
455   {NULL, no_argument, NULL, 0}
456 };
457 size_t md_longopts_size = sizeof (md_longopts);
458
459 /* We have no target specific options yet, so these next
460    two functions are empty.  */
461 int
462 md_parse_option (int c ATTRIBUTE_UNUSED, const char *arg ATTRIBUTE_UNUSED)
463 {
464   return 0;
465 }
466
467 void
468 md_show_usage (FILE *stream ATTRIBUTE_UNUSED)
469 {
470 }
471
472 /* Convert from target byte order to host byte order.  */
473
474 static valueT
475 md_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
490 void
491 md_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
557 void
558 md_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.  */
564 arelent *
565 tc_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 }