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