85722b3a5fa2782bd801a0845ded29b4fe2e3e4d
[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     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   while (ISSPACE (*op_end))
397     op_end++;
398
399   if (*op_end != 0)
400     as_warn ("extra stuff on line ignored");
401
402   if (pending_reloc)
403     as_bad ("Something forgot to clean up\n");
404 }
405
406 /* Turn a string in input_line_pointer into a floating point constant
407    of type type, and store the appropriate bytes in *LITP.  The number
408    of LITTLENUMS emitted is stored in *SIZEP .  An error message is
409    returned, or NULL on OK.  */
410
411 char *
412 md_atof (int type, char *litP, int *sizeP)
413 {
414   int prec;
415   LITTLENUM_TYPE words[4];
416   char *t;
417   int i;
418
419   switch (type)
420     {
421     case 'f':
422       prec = 2;
423       break;
424
425     case 'd':
426       prec = 4;
427       break;
428
429     default:
430       *sizeP = 0;
431       return _("bad call to md_atof");
432     }
433
434   t = atof_ieee (input_line_pointer, type, words);
435   if (t)
436     input_line_pointer = t;
437
438   *sizeP = prec * 2;
439
440   for (i = prec - 1; i >= 0; i--)
441     {
442       md_number_to_chars (litP, (valueT) words[i], 2);
443       litP += 2;
444     }
445
446   return NULL;
447 }
448 \f
449 const char *md_shortopts = "";
450
451 struct option md_longopts[] =
452 {
453   {NULL, no_argument, NULL, 0}
454 };
455 size_t md_longopts_size = sizeof (md_longopts);
456
457 /* We have no target specific options yet, so these next
458    two functions are empty.  */
459 int
460 md_parse_option (int c ATTRIBUTE_UNUSED, char *arg ATTRIBUTE_UNUSED)
461 {
462   return 0;
463 }
464
465 void
466 md_show_usage (FILE *stream ATTRIBUTE_UNUSED)
467 {
468 }
469
470 /* Convert from target byte order to host byte order.  */
471
472 static valueT
473 md_chars_to_number (char * buf, int n)
474 {
475   valueT result = 0;
476   unsigned char * where = (unsigned char *) buf;
477
478   while (n--)
479     {
480       result <<= 8;
481       result |= (where[n] & 255);
482     }
483
484   return result;
485 }
486 /* Apply a fixup to the object file.  */
487
488 void
489 md_apply_fix (fixS *fixP ATTRIBUTE_UNUSED,
490               valueT * valP ATTRIBUTE_UNUSED, segT seg ATTRIBUTE_UNUSED)
491 {
492   char *buf = fixP->fx_where + fixP->fx_frag->fr_literal;
493   long val = *valP;
494   long newval;
495
496   switch (fixP->fx_r_type)
497     {
498     case BFD_RELOC_32:
499       buf[3] = val >> 24;
500       buf[2] = val >> 16;
501       buf[1] = val >> 8;
502       buf[0] = val >> 0;
503       break;
504
505     case BFD_RELOC_16:
506       buf[1] = val >> 8;
507       buf[0] = val >> 0;
508       break;
509
510     case BFD_RELOC_8:
511       *buf = val;
512       break;
513
514     case BFD_RELOC_FT32_10:
515       if (!val)
516         break;
517       newval = md_chars_to_number (buf, 2);
518       newval |= (val & ((1 << 10) - 1)) << FT32_FLD_RIMM_BIT;
519       md_number_to_chars (buf, newval, 2);
520       break;
521
522     case BFD_RELOC_FT32_20:
523       if (!val)
524         break;
525       newval = md_chars_to_number (buf, 3);
526       newval |= val & ((1 << 20) - 1);
527       md_number_to_chars (buf, newval, 3);
528       break;
529
530     case BFD_RELOC_FT32_17:
531       if (!val)
532         break;
533       newval = md_chars_to_number (buf, 3);
534       newval |= val & ((1 << 17) - 1);
535       md_number_to_chars (buf, newval, 3);
536       break;
537
538     case BFD_RELOC_FT32_18:
539       if (!val)
540         break;
541       newval = md_chars_to_number (buf, 4);
542       newval |= (val >> 2) & ((1 << 18) - 1);
543       md_number_to_chars (buf, newval, 4);
544       break;
545
546     default:
547       abort ();
548     }
549
550   if (fixP->fx_addsy == NULL && fixP->fx_pcrel == 0)
551     fixP->fx_done = 1;
552   // printf("fx_addsy=%p fixP->fx_pcrel=%d fx_done=%d\n", fixP->fx_addsy, fixP->fx_pcrel, fixP->fx_done);
553 }
554
555 void
556 md_number_to_chars (char *ptr, valueT use, int nbytes)
557 {
558   number_to_chars_littleendian (ptr, use, nbytes);
559 }
560
561 /* Generate a machine-dependent relocation.  */
562 arelent *
563 tc_gen_reloc (asection *section ATTRIBUTE_UNUSED, fixS *fixP)
564 {
565   arelent *relP;
566   bfd_reloc_code_real_type code;
567
568   switch (fixP->fx_r_type)
569     {
570     case BFD_RELOC_32:
571     case BFD_RELOC_16:
572     case BFD_RELOC_8:
573     case BFD_RELOC_FT32_10:
574     case BFD_RELOC_FT32_20:
575     case BFD_RELOC_FT32_17:
576     case BFD_RELOC_FT32_18:
577       code = fixP->fx_r_type;
578       break;
579     default:
580       as_bad_where (fixP->fx_file, fixP->fx_line,
581                     _("Semantics error.  This type of operand can not be relocated, it must be an assembly-time constant"));
582       return 0;
583     }
584
585   relP = xmalloc (sizeof (arelent));
586   gas_assert (relP != 0);
587   relP->sym_ptr_ptr = xmalloc (sizeof (asymbol *));
588   *relP->sym_ptr_ptr = symbol_get_bfdsym (fixP->fx_addsy);
589   relP->address = fixP->fx_frag->fr_address + fixP->fx_where;
590
591   relP->addend = fixP->fx_offset;
592
593   relP->howto = bfd_reloc_type_lookup (stdoutput, code);
594   if (! relP->howto)
595     {
596       const char *name;
597
598       name = S_GET_NAME (fixP->fx_addsy);
599       if (name == NULL)
600         name = _("<unknown>");
601       as_fatal (_("Cannot generate relocation type for symbol %s, code %s"),
602                 name, bfd_get_reloc_code_name (code));
603     }
604
605   return relP;
606 }