Add new binutils target: moxie
[deliverable/binutils-gdb.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 }
This page took 0.0456 seconds and 4 git commands to generate.