* gas/app, gas/as.c, gas/as.h, gas/atof-generic.c, gas/cgen.c,
[binutils.git] / gas / config / tc-moxie.c
blob2eaa827193d646999419461dda90002aeebbc347
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 delimeted 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 delimeted 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 delimeted 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 delimeted 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;
624 int shift;
626 max = min = 0;
627 shift = 0;
628 switch (fixP->fx_r_type)
630 case BFD_RELOC_32:
631 *buf++ = val >> 24;
632 *buf++ = val >> 16;
633 *buf++ = val >> 8;
634 *buf++ = val >> 0;
635 break;
637 case BFD_RELOC_16:
638 *buf++ = val >> 8;
639 *buf++ = val >> 0;
640 break;
642 case BFD_RELOC_8:
643 *buf++ = val;
644 break;
646 case BFD_RELOC_MOXIE_10_PCREL:
647 if (!val)
648 break;
649 if (val < -1024 || val > 1022)
650 as_bad_where (fixP->fx_file, fixP->fx_line,
651 _("pcrel too far BFD_RELOC_MOXIE_10"));
652 /* 11 bit offset even numbered, so we remove right bit. */
653 val >>= 1;
654 newval = md_chars_to_number (buf, 2);
655 newval |= val & 0x03ff;
656 md_number_to_chars (buf, newval, 2);
657 break;
659 default:
660 abort ();
663 if (max != 0 && (val < min || val > max))
664 as_bad_where (fixP->fx_file, fixP->fx_line, _("offset out of range"));
666 if (fixP->fx_addsy == NULL && fixP->fx_pcrel == 0)
667 fixP->fx_done = 1;
670 /* Put number into target byte order (big endian). */
672 void
673 md_number_to_chars (char *ptr, valueT use, int nbytes)
675 number_to_chars_bigendian (ptr, use, nbytes);
678 /* Convert from target byte order to host byte order. */
680 static int
681 md_chars_to_number (char *val, int n)
683 int retval = 0;
685 while (n--)
687 retval <<= 8;
688 retval |= (*val++ & 255);
691 return retval;
694 /* Generate a machine-dependent relocation. */
695 arelent *
696 tc_gen_reloc (asection *section ATTRIBUTE_UNUSED, fixS *fixP)
698 arelent *relP;
699 bfd_reloc_code_real_type code;
701 switch (fixP->fx_r_type)
703 case BFD_RELOC_32:
704 code = fixP->fx_r_type;
705 break;
706 case BFD_RELOC_MOXIE_10_PCREL:
707 code = fixP->fx_r_type;
708 break;
709 default:
710 as_bad_where (fixP->fx_file, fixP->fx_line,
711 _("Semantics error. This type of operand can not be relocated, it must be an assembly-time constant"));
712 return 0;
715 relP = xmalloc (sizeof (arelent));
716 gas_assert (relP != 0);
717 relP->sym_ptr_ptr = xmalloc (sizeof (asymbol *));
718 *relP->sym_ptr_ptr = symbol_get_bfdsym (fixP->fx_addsy);
719 relP->address = fixP->fx_frag->fr_address + fixP->fx_where;
721 relP->addend = fixP->fx_offset;
723 /* This is the standard place for KLUDGEs to work around bugs in
724 bfd_install_relocation (first such note in the documentation
725 appears with binutils-2.8).
727 That function bfd_install_relocation does the wrong thing with
728 putting stuff into the addend of a reloc (it should stay out) for a
729 weak symbol. The really bad thing is that it adds the
730 "segment-relative offset" of the symbol into the reloc. In this
731 case, the reloc should instead be relative to the symbol with no
732 other offset than the assembly code shows; and since the symbol is
733 weak, any local definition should be ignored until link time (or
734 thereafter).
735 To wit: weaksym+42 should be weaksym+42 in the reloc,
736 not weaksym+(offset_from_segment_of_local_weaksym_definition)
738 To "work around" this, we subtract the segment-relative offset of
739 "known" weak symbols. This evens out the extra offset.
741 That happens for a.out but not for ELF, since for ELF,
742 bfd_install_relocation uses the "special function" field of the
743 howto, and does not execute the code that needs to be undone. */
745 if (OUTPUT_FLAVOR == bfd_target_aout_flavour
746 && fixP->fx_addsy && S_IS_WEAK (fixP->fx_addsy)
747 && ! bfd_is_und_section (S_GET_SEGMENT (fixP->fx_addsy)))
749 relP->addend -= S_GET_VALUE (fixP->fx_addsy);
752 relP->howto = bfd_reloc_type_lookup (stdoutput, code);
753 if (! relP->howto)
755 const char *name;
757 name = S_GET_NAME (fixP->fx_addsy);
758 if (name == NULL)
759 name = _("<unknown>");
760 as_fatal (_("Cannot generate relocation type for symbol %s, code %s"),
761 name, bfd_get_reloc_code_name (code));
764 return relP;
767 /* Decide from what point a pc-relative relocation is relative to,
768 relative to the pc-relative fixup. Er, relatively speaking. */
769 long
770 md_pcrel_from (fixS *fixP)
772 valueT addr = fixP->fx_where + fixP->fx_frag->fr_address;
774 switch (fixP->fx_r_type)
776 case BFD_RELOC_32:
777 return addr + 4;
778 case BFD_RELOC_MOXIE_10_PCREL:
779 return addr;
780 default:
781 abort ();
782 return addr;