PR gas/12848
[binutils.git] / gas / config / tc-moxie.c
blob2fffc6594c8c8831125cbdf67b6ee29ad0c9a9d1
1 /* tc-moxie.c -- Assemble code for moxie
2 Copyright 2009
3 Free Software Foundation, Inc.
5 This file is part of GAS, the GNU Assembler.
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.
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.
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. */
22 /* Contributed by Anthony Green <green@moxielogic.com>. */
24 #include "as.h"
25 #include "safe-ctype.h"
26 #include "opcode/moxie.h"
27 #include "elf/moxie.h"
29 extern const moxie_opc_info_t moxie_opc_info[128];
31 const char comment_chars[] = "#";
32 const char line_separator_chars[] = ";";
33 const char line_comment_chars[] = "#";
35 static int pending_reloc;
36 static struct hash_control *opcode_hash_control;
38 const pseudo_typeS md_pseudo_table[] =
40 {0, 0, 0}
43 const char FLT_CHARS[] = "rRsSfFdDxXpP";
44 const char EXP_CHARS[] = "eE";
46 static int md_chars_to_number (char *val, int n);
48 void
49 md_operand (expressionS *op __attribute__((unused)))
51 /* Empty for now. */
54 /* This function is called once, at assembler startup time. It sets
55 up the hash table with all the opcodes in it, and also initializes
56 some aliases for compatibility with other assemblers. */
58 void
59 md_begin (void)
61 int count;
62 const moxie_opc_info_t *opcode;
63 opcode_hash_control = hash_new ();
65 /* Insert names into hash table. */
66 for (count = 0, opcode = moxie_form1_opc_info; count++ < 64; opcode++)
67 hash_insert (opcode_hash_control, opcode->name, (char *) opcode);
69 for (count = 0, opcode = moxie_form2_opc_info; count++ < 4; opcode++)
70 hash_insert (opcode_hash_control, opcode->name, (char *) opcode);
72 for (count = 0, opcode = moxie_form3_opc_info; count++ < 10; opcode++)
73 hash_insert (opcode_hash_control, opcode->name, (char *) opcode);
75 bfd_set_arch_mach (stdoutput, TARGET_ARCH, 0);
78 /* Parse an expression and then restore the input line pointer. */
80 static char *
81 parse_exp_save_ilp (char *s, expressionS *op)
83 char *save = input_line_pointer;
85 input_line_pointer = s;
86 expression (op);
87 s = input_line_pointer;
88 input_line_pointer = save;
89 return s;
92 static int
93 parse_register_operand (char **ptr)
95 int reg;
96 char *s = *ptr;
98 if (*s != '$')
100 as_bad (_("expecting register"));
101 ignore_rest_of_line ();
102 return -1;
104 if (s[1] == 'f' && s[2] == 'p')
106 *ptr += 3;
107 return 0;
109 if (s[1] == 's' && s[2] == 'p')
111 *ptr += 3;
112 return 1;
114 if (s[1] == 'r')
116 reg = s[2] - '0';
117 if ((reg < 0) || (reg > 9))
119 as_bad (_("illegal register number"));
120 ignore_rest_of_line ();
121 return -1;
123 if (reg == 1)
125 int r2 = s[3] - '0';
126 if ((r2 >= 0) && (r2 <= 3))
128 reg = 10 + r2;
129 *ptr += 1;
133 else
135 as_bad (_("illegal register number"));
136 ignore_rest_of_line ();
137 return -1;
140 *ptr += 3;
142 return reg + 2;
145 /* This is the guts of the machine-dependent assembler. STR points to
146 a machine dependent instruction. This function is supposed to emit
147 the frags/bytes it assembles to. */
149 void
150 md_assemble (char *str)
152 char *op_start;
153 char *op_end;
155 moxie_opc_info_t *opcode;
156 char *p;
157 char pend;
159 unsigned short iword = 0;
161 int nlen = 0;
163 /* Drop leading whitespace. */
164 while (*str == ' ')
165 str++;
167 /* Find the op code end. */
168 op_start = str;
169 for (op_end = str;
170 *op_end && !is_end_of_line[*op_end & 0xff] && *op_end != ' ';
171 op_end++)
172 nlen++;
174 pend = *op_end;
175 *op_end = 0;
177 if (nlen == 0)
178 as_bad (_("can't find opcode "));
179 opcode = (moxie_opc_info_t *) hash_find (opcode_hash_control, op_start);
180 *op_end = pend;
182 if (opcode == NULL)
184 as_bad (_("unknown opcode %s"), op_start);
185 return;
188 p = frag_more (2);
190 switch (opcode->itype)
192 case MOXIE_F2_A8V:
193 iword = (1<<15) | (opcode->opcode << 12);
194 while (ISSPACE (*op_end))
195 op_end++;
197 expressionS arg;
198 int reg;
199 reg = parse_register_operand (&op_end);
200 iword += (reg << 8);
201 if (*op_end != ',')
202 as_warn (_("expecting comma delimited register operands"));
203 op_end++;
204 op_end = parse_exp_save_ilp (op_end, &arg);
205 fix_new_exp (frag_now,
206 ((p+1) - frag_now->fr_literal),
208 &arg,
210 BFD_RELOC_8);
212 break;
213 case MOXIE_F1_AB:
214 iword = opcode->opcode << 8;
215 while (ISSPACE (*op_end))
216 op_end++;
218 int dest, src;
219 dest = parse_register_operand (&op_end);
220 if (*op_end != ',')
221 as_warn (_("expecting comma delimited register operands"));
222 op_end++;
223 src = parse_register_operand (&op_end);
224 iword += (dest << 4) + src;
225 while (ISSPACE (*op_end))
226 op_end++;
227 if (*op_end != 0)
228 as_warn (_("extra stuff on line ignored"));
230 break;
231 case MOXIE_F1_A4:
232 iword = opcode->opcode << 8;
233 while (ISSPACE (*op_end))
234 op_end++;
236 expressionS arg;
237 char *where;
238 int regnum;
240 regnum = parse_register_operand (&op_end);
241 while (ISSPACE (*op_end))
242 op_end++;
244 iword += (regnum << 4);
246 if (*op_end != ',')
248 as_bad (_("expecting comma delimited operands"));
249 ignore_rest_of_line ();
250 return;
252 op_end++;
254 op_end = parse_exp_save_ilp (op_end, &arg);
255 where = frag_more (4);
256 fix_new_exp (frag_now,
257 (where - frag_now->fr_literal),
259 &arg,
261 BFD_RELOC_32);
263 break;
264 case MOXIE_F1_M:
265 case MOXIE_F1_4:
266 iword = opcode->opcode << 8;
267 while (ISSPACE (*op_end))
268 op_end++;
270 expressionS arg;
271 char *where;
273 op_end = parse_exp_save_ilp (op_end, &arg);
274 where = frag_more (4);
275 fix_new_exp (frag_now,
276 (where - frag_now->fr_literal),
278 &arg,
280 BFD_RELOC_32);
282 break;
283 case MOXIE_F1_NARG:
284 iword = opcode->opcode << 8;
285 while (ISSPACE (*op_end))
286 op_end++;
287 if (*op_end != 0)
288 as_warn (_("extra stuff on line ignored"));
289 break;
290 case MOXIE_F1_A:
291 iword = opcode->opcode << 8;
292 while (ISSPACE (*op_end))
293 op_end++;
295 int reg;
296 reg = parse_register_operand (&op_end);
297 while (ISSPACE (*op_end))
298 op_end++;
299 if (*op_end != 0)
300 as_warn (_("extra stuff on line ignored"));
301 iword += (reg << 4);
303 break;
304 case MOXIE_F1_ABi:
305 iword = opcode->opcode << 8;
306 while (ISSPACE (*op_end))
307 op_end++;
309 int a, b;
310 a = parse_register_operand (&op_end);
311 if (*op_end != ',')
312 as_warn (_("expecting comma delimited register operands"));
313 op_end++;
314 if (*op_end != '(')
316 as_bad (_("expecting indirect register `($rA)'"));
317 ignore_rest_of_line ();
318 return;
320 op_end++;
321 b = parse_register_operand (&op_end);
322 if (*op_end != ')')
324 as_bad (_("missing closing parenthesis"));
325 ignore_rest_of_line ();
326 return;
328 op_end++;
329 iword += (a << 4) + b;
330 while (ISSPACE (*op_end))
331 op_end++;
332 if (*op_end != 0)
333 as_warn (_("extra stuff on line ignored"));
335 break;
336 case MOXIE_F1_AiB:
337 iword = opcode->opcode << 8;
338 while (ISSPACE (*op_end))
339 op_end++;
341 int a, b;
342 if (*op_end != '(')
344 as_bad (_("expecting indirect register `($rA)'"));
345 ignore_rest_of_line ();
346 return;
348 op_end++;
349 a = parse_register_operand (&op_end);
350 if (*op_end != ')')
352 as_bad (_("missing closing parenthesis"));
353 ignore_rest_of_line ();
354 return;
356 op_end++;
357 if (*op_end != ',')
358 as_warn (_("expecting comma delimited register operands"));
359 op_end++;
360 b = parse_register_operand (&op_end);
361 iword += (a << 4) + b;
362 while (ISSPACE (*op_end))
363 op_end++;
364 if (*op_end != 0)
365 as_warn (_("extra stuff on line ignored"));
367 break;
368 case MOXIE_F1_4A:
369 iword = opcode->opcode << 8;
370 while (ISSPACE (*op_end))
371 op_end++;
373 expressionS arg;
374 char *where;
375 int a;
377 op_end = parse_exp_save_ilp (op_end, &arg);
378 where = frag_more (4);
379 fix_new_exp (frag_now,
380 (where - frag_now->fr_literal),
382 &arg,
384 BFD_RELOC_32);
386 if (*op_end != ',')
388 as_bad (_("expecting comma delimited operands"));
389 ignore_rest_of_line ();
390 return;
392 op_end++;
394 a = parse_register_operand (&op_end);
395 while (ISSPACE (*op_end))
396 op_end++;
397 if (*op_end != 0)
398 as_warn (_("extra stuff on line ignored"));
400 iword += (a << 4);
402 break;
403 case MOXIE_F1_ABi4:
404 iword = opcode->opcode << 8;
405 while (ISSPACE (*op_end))
406 op_end++;
408 expressionS arg;
409 char *offset;
410 int a, b;
412 a = parse_register_operand (&op_end);
413 while (ISSPACE (*op_end))
414 op_end++;
416 if (*op_end != ',')
418 as_bad (_("expecting comma delimited operands"));
419 ignore_rest_of_line ();
420 return;
422 op_end++;
424 op_end = parse_exp_save_ilp (op_end, &arg);
425 offset = frag_more (4);
426 fix_new_exp (frag_now,
427 (offset - frag_now->fr_literal),
429 &arg,
431 BFD_RELOC_32);
433 if (*op_end != '(')
435 as_bad (_("expecting indirect register `($rX)'"));
436 ignore_rest_of_line ();
437 return;
439 op_end++;
440 b = parse_register_operand (&op_end);
441 if (*op_end != ')')
443 as_bad (_("missing closing parenthesis"));
444 ignore_rest_of_line ();
445 return;
447 op_end++;
449 while (ISSPACE (*op_end))
450 op_end++;
451 if (*op_end != 0)
452 as_warn (_("extra stuff on line ignored"));
454 iword += (a << 4) + b;
456 break;
457 case MOXIE_F1_AiB4:
458 iword = opcode->opcode << 8;
459 while (ISSPACE (*op_end))
460 op_end++;
462 expressionS arg;
463 char *offset;
464 int a, b;
466 op_end = parse_exp_save_ilp (op_end, &arg);
467 offset = frag_more (4);
468 fix_new_exp (frag_now,
469 (offset - frag_now->fr_literal),
471 &arg,
473 BFD_RELOC_32);
475 if (*op_end != '(')
477 as_bad (_("expecting indirect register `($rX)'"));
478 ignore_rest_of_line ();
479 return;
481 op_end++;
482 a = parse_register_operand (&op_end);
483 if (*op_end != ')')
485 as_bad (_("missing closing parenthesis"));
486 ignore_rest_of_line ();
487 return;
489 op_end++;
491 if (*op_end != ',')
493 as_bad (_("expecting comma delimited operands"));
494 ignore_rest_of_line ();
495 return;
497 op_end++;
499 b = parse_register_operand (&op_end);
500 while (ISSPACE (*op_end))
501 op_end++;
503 while (ISSPACE (*op_end))
504 op_end++;
505 if (*op_end != 0)
506 as_warn (_("extra stuff on line ignored"));
508 iword += (a << 4) + b;
510 break;
511 case MOXIE_F2_NARG:
512 iword = opcode->opcode << 12;
513 while (ISSPACE (*op_end))
514 op_end++;
515 if (*op_end != 0)
516 as_warn (_("extra stuff on line ignored"));
517 break;
518 case MOXIE_F3_PCREL:
519 iword = (3<<14) | (opcode->opcode << 10);
520 while (ISSPACE (*op_end))
521 op_end++;
523 expressionS arg;
525 op_end = parse_exp_save_ilp (op_end, &arg);
526 fix_new_exp (frag_now,
527 (p - frag_now->fr_literal),
529 &arg,
530 TRUE,
531 BFD_RELOC_MOXIE_10_PCREL);
533 break;
534 default:
535 abort ();
538 md_number_to_chars (p, iword, 2);
540 while (ISSPACE (*op_end))
541 op_end++;
543 if (*op_end != 0)
544 as_warn (_("extra stuff on line ignored"));
546 if (pending_reloc)
547 as_bad (_("Something forgot to clean up\n"));
550 /* Turn a string in input_line_pointer into a floating point constant
551 of type type, and store the appropriate bytes in *LITP. The number
552 of LITTLENUMS emitted is stored in *SIZEP . An error message is
553 returned, or NULL on OK. */
555 char *
556 md_atof (int type, char *litP, int *sizeP)
558 int prec;
559 LITTLENUM_TYPE words[4];
560 char *t;
561 int i;
563 switch (type)
565 case 'f':
566 prec = 2;
567 break;
569 case 'd':
570 prec = 4;
571 break;
573 default:
574 *sizeP = 0;
575 return _("bad call to md_atof");
578 t = atof_ieee (input_line_pointer, type, words);
579 if (t)
580 input_line_pointer = t;
582 *sizeP = prec * 2;
584 for (i = prec - 1; i >= 0; i--)
586 md_number_to_chars (litP, (valueT) words[i], 2);
587 litP += 2;
590 return NULL;
593 const char *md_shortopts = "";
595 struct option md_longopts[] =
597 {NULL, no_argument, NULL, 0}
599 size_t md_longopts_size = sizeof (md_longopts);
601 /* We have no target specific options yet, so these next
602 two functions are empty. */
604 md_parse_option (int c ATTRIBUTE_UNUSED, char *arg ATTRIBUTE_UNUSED)
606 return 0;
609 void
610 md_show_usage (FILE *stream ATTRIBUTE_UNUSED)
614 /* Apply a fixup to the object file. */
616 void
617 md_apply_fix (fixS *fixP ATTRIBUTE_UNUSED,
618 valueT * valP ATTRIBUTE_UNUSED, segT seg ATTRIBUTE_UNUSED)
620 char *buf = fixP->fx_where + fixP->fx_frag->fr_literal;
621 long val = *valP;
622 long newval;
623 long max, min;
625 max = min = 0;
626 switch (fixP->fx_r_type)
628 case BFD_RELOC_32:
629 *buf++ = val >> 24;
630 *buf++ = val >> 16;
631 *buf++ = val >> 8;
632 *buf++ = val >> 0;
633 break;
635 case BFD_RELOC_16:
636 *buf++ = val >> 8;
637 *buf++ = val >> 0;
638 break;
640 case BFD_RELOC_8:
641 *buf++ = val;
642 break;
644 case BFD_RELOC_MOXIE_10_PCREL:
645 if (!val)
646 break;
647 if (val < -1024 || val > 1022)
648 as_bad_where (fixP->fx_file, fixP->fx_line,
649 _("pcrel too far BFD_RELOC_MOXIE_10"));
650 /* 11 bit offset even numbered, so we remove right bit. */
651 val >>= 1;
652 newval = md_chars_to_number (buf, 2);
653 newval |= val & 0x03ff;
654 md_number_to_chars (buf, newval, 2);
655 break;
657 default:
658 abort ();
661 if (max != 0 && (val < min || val > max))
662 as_bad_where (fixP->fx_file, fixP->fx_line, _("offset out of range"));
664 if (fixP->fx_addsy == NULL && fixP->fx_pcrel == 0)
665 fixP->fx_done = 1;
668 /* Put number into target byte order (big endian). */
670 void
671 md_number_to_chars (char *ptr, valueT use, int nbytes)
673 number_to_chars_bigendian (ptr, use, nbytes);
676 /* Convert from target byte order to host byte order. */
678 static int
679 md_chars_to_number (char *val, int n)
681 int retval = 0;
683 while (n--)
685 retval <<= 8;
686 retval |= (*val++ & 255);
689 return retval;
692 /* Generate a machine-dependent relocation. */
693 arelent *
694 tc_gen_reloc (asection *section ATTRIBUTE_UNUSED, fixS *fixP)
696 arelent *relP;
697 bfd_reloc_code_real_type code;
699 switch (fixP->fx_r_type)
701 case BFD_RELOC_32:
702 code = fixP->fx_r_type;
703 break;
704 case BFD_RELOC_MOXIE_10_PCREL:
705 code = fixP->fx_r_type;
706 break;
707 default:
708 as_bad_where (fixP->fx_file, fixP->fx_line,
709 _("Semantics error. This type of operand can not be relocated, it must be an assembly-time constant"));
710 return 0;
713 relP = xmalloc (sizeof (arelent));
714 gas_assert (relP != 0);
715 relP->sym_ptr_ptr = xmalloc (sizeof (asymbol *));
716 *relP->sym_ptr_ptr = symbol_get_bfdsym (fixP->fx_addsy);
717 relP->address = fixP->fx_frag->fr_address + fixP->fx_where;
719 relP->addend = fixP->fx_offset;
721 /* This is the standard place for KLUDGEs to work around bugs in
722 bfd_install_relocation (first such note in the documentation
723 appears with binutils-2.8).
725 That function bfd_install_relocation does the wrong thing with
726 putting stuff into the addend of a reloc (it should stay out) for a
727 weak symbol. The really bad thing is that it adds the
728 "segment-relative offset" of the symbol into the reloc. In this
729 case, the reloc should instead be relative to the symbol with no
730 other offset than the assembly code shows; and since the symbol is
731 weak, any local definition should be ignored until link time (or
732 thereafter).
733 To wit: weaksym+42 should be weaksym+42 in the reloc,
734 not weaksym+(offset_from_segment_of_local_weaksym_definition)
736 To "work around" this, we subtract the segment-relative offset of
737 "known" weak symbols. This evens out the extra offset.
739 That happens for a.out but not for ELF, since for ELF,
740 bfd_install_relocation uses the "special function" field of the
741 howto, and does not execute the code that needs to be undone. */
743 if (OUTPUT_FLAVOR == bfd_target_aout_flavour
744 && fixP->fx_addsy && S_IS_WEAK (fixP->fx_addsy)
745 && ! bfd_is_und_section (S_GET_SEGMENT (fixP->fx_addsy)))
747 relP->addend -= S_GET_VALUE (fixP->fx_addsy);
750 relP->howto = bfd_reloc_type_lookup (stdoutput, code);
751 if (! relP->howto)
753 const char *name;
755 name = S_GET_NAME (fixP->fx_addsy);
756 if (name == NULL)
757 name = _("<unknown>");
758 as_fatal (_("Cannot generate relocation type for symbol %s, code %s"),
759 name, bfd_get_reloc_code_name (code));
762 return relP;
765 /* Decide from what point a pc-relative relocation is relative to,
766 relative to the pc-relative fixup. Er, relatively speaking. */
767 long
768 md_pcrel_from (fixS *fixP)
770 valueT addr = fixP->fx_where + fixP->fx_frag->fr_address;
772 switch (fixP->fx_r_type)
774 case BFD_RELOC_32:
775 return addr + 4;
776 case BFD_RELOC_MOXIE_10_PCREL:
777 return addr;
778 default:
779 abort ();
780 return addr;