Add new binutils target: moxie
[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_4:
263       iword = opcode->opcode << 8;
264       while (ISSPACE (*op_end))
265         op_end++;
266       {
267         expressionS arg;
268         char *where;
269
270         op_end = parse_exp_save_ilp (op_end, &arg);
271         where = frag_more (4);
272         fix_new_exp (frag_now,
273                      (where - frag_now->fr_literal),
274                      4,
275                      &arg,
276                      0,
277                      BFD_RELOC_32);
278       }
279       break;
280     case MOXIE_F1_NARG:
281       iword = opcode->opcode << 8;
282       while (ISSPACE (*op_end))
283         op_end++;
284       if (*op_end != 0)
285         as_warn ("extra stuff on line ignored");
286       break;
287     case MOXIE_F1_A:
288       iword = opcode->opcode << 8;
289       while (ISSPACE (*op_end))
290         op_end++;
291       {
292         int reg;
293         reg = parse_register_operand (&op_end);
294         while (ISSPACE (*op_end))
295           op_end++;
296         if (*op_end != 0)
297           as_warn ("extra stuff on line ignored");
298         iword += (reg << 4);
299       }
300       break;
301     case MOXIE_F1_ABi:
302       iword = opcode->opcode << 8;
303       while (ISSPACE (*op_end))
304         op_end++;
305       {
306         int a, b;
307         a = parse_register_operand (&op_end);
308         if (*op_end != ',')
309           as_warn ("expecting comma delimeted register operands");
310         op_end++;
311         if (*op_end != '(')
312           {
313             as_bad ("expecting indirect register `($rA)'");
314             ignore_rest_of_line ();
315             return;
316           }
317         op_end++;
318         b = parse_register_operand (&op_end);
319         if (*op_end != ')')
320           {
321             as_bad ("missing closing parenthesis");
322             ignore_rest_of_line ();
323             return;
324           }
325         op_end++;
326         iword += (a << 4) + b;
327         while (ISSPACE (*op_end))
328           op_end++;
329         if (*op_end != 0)
330           as_warn ("extra stuff on line ignored");
331       }
332       break;
333     case MOXIE_F1_AiB:
334       iword = opcode->opcode << 8;
335       while (ISSPACE (*op_end))
336         op_end++;
337       {
338         int a, b;
339         if (*op_end != '(')
340           {
341             as_bad ("expecting indirect register `($rA)'");
342             ignore_rest_of_line ();
343             return;
344           }
345         op_end++;
346         a = parse_register_operand (&op_end);
347         if (*op_end != ')')
348           {
349             as_bad ("missing closing parenthesis");
350             ignore_rest_of_line ();
351             return;
352           }
353         op_end++;
354         if (*op_end != ',')
355           as_warn ("expecting comma delimeted register operands");
356         op_end++;
357         b = parse_register_operand (&op_end);
358         iword += (a << 4) + b;
359         while (ISSPACE (*op_end))
360           op_end++;
361         if (*op_end != 0)
362           as_warn ("extra stuff on line ignored");
363       }
364       break;
365     case MOXIE_F1_4A:
366       iword = opcode->opcode << 8;
367       while (ISSPACE (*op_end))
368         op_end++;
369       {
370         expressionS arg;
371         char *where;
372         int a;
373
374         op_end = parse_exp_save_ilp (op_end, &arg);
375         where = frag_more (4);
376         fix_new_exp (frag_now,
377                      (where - frag_now->fr_literal),
378                      4,
379                      &arg,
380                      0,
381                      BFD_RELOC_32);
382
383         if (*op_end != ',')
384           {
385             as_bad ("expecting comma delimited operands");
386             ignore_rest_of_line ();
387             return;
388           }
389         op_end++;
390
391         a = parse_register_operand (&op_end);
392         while (ISSPACE (*op_end))
393           op_end++;
394         if (*op_end != 0)
395           as_warn ("extra stuff on line ignored");
396
397         iword += (a << 4);
398       }
399       break;
400     case MOXIE_F1_ABi4:
401       iword = opcode->opcode << 8;
402       while (ISSPACE (*op_end))
403         op_end++;
404       {
405         expressionS arg;
406         char *offset;
407         int a, b;
408
409         a = parse_register_operand (&op_end);
410         while (ISSPACE (*op_end))
411           op_end++;
412
413         if (*op_end != ',')
414           {
415             as_bad ("expecting comma delimited operands");
416             ignore_rest_of_line ();
417             return;
418           }
419         op_end++;
420
421         op_end = parse_exp_save_ilp (op_end, &arg);
422         offset = frag_more (4);
423         fix_new_exp (frag_now,
424                      (offset - frag_now->fr_literal),
425                      4,
426                      &arg,
427                      0,
428                      BFD_RELOC_32);
429
430         if (*op_end != '(')
431           {
432             as_bad ("expecting indirect register `($rX)'");
433             ignore_rest_of_line ();
434             return;
435           }
436         op_end++;
437         b = parse_register_operand (&op_end);
438         if (*op_end != ')')
439           {
440             as_bad ("missing closing parenthesis");
441             ignore_rest_of_line ();
442             return;
443           }
444         op_end++;
445
446         while (ISSPACE (*op_end))
447           op_end++;
448         if (*op_end != 0)
449           as_warn ("extra stuff on line ignored");
450
451         iword += (a << 4) + b;
452       }
453       break;
454     case MOXIE_F1_AiB4:
455       iword = opcode->opcode << 8;
456       while (ISSPACE (*op_end))
457         op_end++;
458       {
459         expressionS arg;
460         char *offset;
461         int a, b;
462
463         op_end = parse_exp_save_ilp (op_end, &arg);
464         offset = frag_more (4);
465         fix_new_exp (frag_now,
466                      (offset - frag_now->fr_literal),
467                      4,
468                      &arg,
469                      0,
470                      BFD_RELOC_32);
471
472         if (*op_end != '(')
473           {
474             as_bad ("expecting indirect register `($rX)'");
475             ignore_rest_of_line ();
476             return;
477           }
478         op_end++;
479         a = parse_register_operand (&op_end);
480         if (*op_end != ')')
481           {
482             as_bad ("missing closing parenthesis");
483             ignore_rest_of_line ();
484             return;
485           }
486         op_end++;
487
488         if (*op_end != ',')
489           {
490             as_bad ("expecting comma delimited operands");
491             ignore_rest_of_line ();
492             return;
493           }
494         op_end++;
495
496         b = parse_register_operand (&op_end);
497         while (ISSPACE (*op_end))
498           op_end++;
499
500         while (ISSPACE (*op_end))
501           op_end++;
502         if (*op_end != 0)
503           as_warn ("extra stuff on line ignored");
504
505         iword += (a << 4) + b;
506       }
507       break;
508     case MOXIE_F2_NARG:
509       iword = opcode->opcode << 12;
510       while (ISSPACE (*op_end))
511         op_end++;
512       if (*op_end != 0)
513         as_warn ("extra stuff on line ignored");
514       break;
515     default:
516       abort();
517     }
518
519   md_number_to_chars (p, iword, 2);
520
521   while (ISSPACE (*op_end))
522     op_end++;
523
524   if (*op_end != 0)
525     as_warn ("extra stuff on line ignored");
526
527   if (pending_reloc)
528     as_bad ("Something forgot to clean up\n");
529 }
530
531 /* Turn a string in input_line_pointer into a floating point constant
532    of type type, and store the appropriate bytes in *LITP.  The number
533    of LITTLENUMS emitted is stored in *SIZEP .  An error message is
534    returned, or NULL on OK.  */
535
536 char *
537 md_atof (int type, char *litP, int *sizeP)
538 {
539   int prec;
540   LITTLENUM_TYPE words[4];
541   char *t;
542   int i;
543
544   switch (type)
545     {
546     case 'f':
547       prec = 2;
548       break;
549
550     case 'd':
551       prec = 4;
552       break;
553
554     default:
555       *sizeP = 0;
556       return _("bad call to md_atof");
557     }
558
559   t = atof_ieee (input_line_pointer, type, words);
560   if (t)
561     input_line_pointer = t;
562
563   *sizeP = prec * 2;
564
565   for (i = prec - 1; i >= 0; i--)
566     {
567       md_number_to_chars (litP, (valueT) words[i], 2);
568       litP += 2;
569     }
570
571   return NULL;
572 }
573 \f
574 const char *md_shortopts = "";
575
576 struct option md_longopts[] =
577 {
578   {NULL, no_argument, NULL, 0}
579 };
580 size_t md_longopts_size = sizeof (md_longopts);
581
582 /* We have no target specific options yet, so these next
583    two functions are empty.  */
584 int
585 md_parse_option (int c ATTRIBUTE_UNUSED, char *arg ATTRIBUTE_UNUSED)
586 {
587   return 0;
588 }
589
590 void
591 md_show_usage (FILE *stream ATTRIBUTE_UNUSED)
592 {
593 }
594
595 /* Apply a fixup to the object file.  */
596
597 void
598 md_apply_fix (fixS *fixP ATTRIBUTE_UNUSED, valueT * valP ATTRIBUTE_UNUSED, segT seg ATTRIBUTE_UNUSED)
599 {
600   char *buf = fixP->fx_where + fixP->fx_frag->fr_literal;
601   long val = *valP;
602   long max, min;
603   int shift;
604
605   max = min = 0;
606   shift = 0;
607   switch (fixP->fx_r_type)
608     {
609     case BFD_RELOC_32:
610       *buf++ = val >> 24;
611       *buf++ = val >> 16;
612       *buf++ = val >> 8;
613       *buf++ = val >> 0;
614       break;
615
616     case BFD_RELOC_16:
617       *buf++ = val >> 8;
618       *buf++ = val >> 0;
619       break;
620
621     case BFD_RELOC_8:
622       *buf++ = val;
623       break;
624
625     default:
626       abort ();
627     }
628
629   if (max != 0 && (val < min || val > max))
630     as_bad_where (fixP->fx_file, fixP->fx_line, _("offset out of range"));
631
632   if (fixP->fx_addsy == NULL && fixP->fx_pcrel == 0)
633     fixP->fx_done = 1;
634 }
635
636 /* Put number into target byte order (big endian).  */
637
638 void
639 md_number_to_chars (char *ptr, valueT use, int nbytes)
640 {
641   number_to_chars_bigendian (ptr, use, nbytes);
642 }
643
644 /* Generate a machine-dependent relocation.  */
645 arelent *
646 tc_gen_reloc (asection *section ATTRIBUTE_UNUSED, fixS *fixP)
647 {
648   arelent *relP;
649   bfd_reloc_code_real_type code;
650
651   switch (fixP->fx_r_type)
652     {
653     case BFD_RELOC_32:
654       code = fixP->fx_r_type;
655       break;
656     default:
657       as_bad_where (fixP->fx_file, fixP->fx_line,
658                     _("Semantics error.  This type of operand can not be relocated, it must be an assembly-time constant"));
659       return 0;
660     }
661
662   relP = xmalloc (sizeof (arelent));
663   assert (relP != 0);
664   relP->sym_ptr_ptr = xmalloc (sizeof (asymbol *));
665   *relP->sym_ptr_ptr = symbol_get_bfdsym (fixP->fx_addsy);
666   relP->address = fixP->fx_frag->fr_address + fixP->fx_where;
667
668   relP->addend = fixP->fx_offset;
669
670   /* This is the standard place for KLUDGEs to work around bugs in
671      bfd_install_relocation (first such note in the documentation
672      appears with binutils-2.8).
673
674      That function bfd_install_relocation does the wrong thing with
675      putting stuff into the addend of a reloc (it should stay out) for a
676      weak symbol.  The really bad thing is that it adds the
677      "segment-relative offset" of the symbol into the reloc.  In this
678      case, the reloc should instead be relative to the symbol with no
679      other offset than the assembly code shows; and since the symbol is
680      weak, any local definition should be ignored until link time (or
681      thereafter).
682      To wit:  weaksym+42  should be weaksym+42 in the reloc,
683      not weaksym+(offset_from_segment_of_local_weaksym_definition)
684
685      To "work around" this, we subtract the segment-relative offset of
686      "known" weak symbols.  This evens out the extra offset.
687
688      That happens for a.out but not for ELF, since for ELF,
689      bfd_install_relocation uses the "special function" field of the
690      howto, and does not execute the code that needs to be undone.  */
691
692   if (OUTPUT_FLAVOR == bfd_target_aout_flavour
693       && fixP->fx_addsy && S_IS_WEAK (fixP->fx_addsy)
694       && ! bfd_is_und_section (S_GET_SEGMENT (fixP->fx_addsy)))
695     {
696       relP->addend -= S_GET_VALUE (fixP->fx_addsy);
697     }
698
699   relP->howto = bfd_reloc_type_lookup (stdoutput, code);
700   if (! relP->howto)
701     {
702       const char *name;
703
704       name = S_GET_NAME (fixP->fx_addsy);
705       if (name == NULL)
706         name = _("<unknown>");
707       as_fatal (_("Cannot generate relocation type for symbol %s, code %s"),
708                 name, bfd_get_reloc_code_name (code));
709     }
710
711   return relP;
712 }
713
714 /* Decide from what point a pc-relative relocation is relative to,
715    relative to the pc-relative fixup.  Er, relatively speaking.  */
716 long
717 md_pcrel_from (fixS *fixP)
718 {
719   valueT addr = fixP->fx_where + fixP->fx_frag->fr_address;
720
721   fprintf (stderr, "md_pcrel_from 0x%d\n", fixP->fx_r_type);
722
723   switch (fixP->fx_r_type)
724     {
725     case BFD_RELOC_32:
726       return addr + 4;
727     default:
728       abort ();
729       return addr;
730     }
731 }