1 /* tc-moxie.c -- Assemble code for moxie
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)
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>. */
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
[] =
43 const char FLT_CHARS
[] = "rRsSfFdDxXpP";
44 const char EXP_CHARS
[] = "eE";
46 static int md_chars_to_number (char *val
, int n
);
49 md_operand (expressionS
*op
__attribute__((unused
)))
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. */
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. */
81 parse_exp_save_ilp (char *s
, expressionS
*op
)
83 char *save
= input_line_pointer
;
85 input_line_pointer
= s
;
87 s
= input_line_pointer
;
88 input_line_pointer
= save
;
93 parse_register_operand (char **ptr
)
100 as_bad (_("expecting register"));
101 ignore_rest_of_line ();
104 if (s
[1] == 'f' && s
[2] == 'p')
109 if (s
[1] == 's' && s
[2] == 'p')
117 if ((reg
< 0) || (reg
> 9))
119 as_bad (_("illegal register number"));
120 ignore_rest_of_line ();
126 if ((r2
>= 0) && (r2
<= 3))
135 as_bad (_("illegal register number"));
136 ignore_rest_of_line ();
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. */
150 md_assemble (char *str
)
155 moxie_opc_info_t
*opcode
;
159 unsigned short iword
= 0;
163 /* Drop leading whitespace. */
167 /* Find the op code end. */
170 *op_end
&& !is_end_of_line
[*op_end
& 0xff] && *op_end
!= ' ';
178 as_bad (_("can't find opcode "));
179 opcode
= (moxie_opc_info_t
*) hash_find (opcode_hash_control
, op_start
);
184 as_bad (_("unknown opcode %s"), op_start
);
190 switch (opcode
->itype
)
193 iword
= (1<<15) | (opcode
->opcode
<< 12);
194 while (ISSPACE (*op_end
))
199 reg
= parse_register_operand (&op_end
);
202 as_warn (_("expecting comma delimited register operands"));
204 op_end
= parse_exp_save_ilp (op_end
, &arg
);
205 fix_new_exp (frag_now
,
206 ((p
+1) - frag_now
->fr_literal
),
214 iword
= opcode
->opcode
<< 8;
215 while (ISSPACE (*op_end
))
219 dest
= parse_register_operand (&op_end
);
221 as_warn (_("expecting comma delimited register operands"));
223 src
= parse_register_operand (&op_end
);
224 iword
+= (dest
<< 4) + src
;
225 while (ISSPACE (*op_end
))
228 as_warn (_("extra stuff on line ignored"));
232 iword
= opcode
->opcode
<< 8;
233 while (ISSPACE (*op_end
))
240 regnum
= parse_register_operand (&op_end
);
241 while (ISSPACE (*op_end
))
244 iword
+= (regnum
<< 4);
248 as_bad (_("expecting comma delimited operands"));
249 ignore_rest_of_line ();
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
),
266 iword
= opcode
->opcode
<< 8;
267 while (ISSPACE (*op_end
))
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
),
284 iword
= opcode
->opcode
<< 8;
285 while (ISSPACE (*op_end
))
288 as_warn (_("extra stuff on line ignored"));
291 iword
= opcode
->opcode
<< 8;
292 while (ISSPACE (*op_end
))
296 reg
= parse_register_operand (&op_end
);
297 while (ISSPACE (*op_end
))
300 as_warn (_("extra stuff on line ignored"));
305 iword
= opcode
->opcode
<< 8;
306 while (ISSPACE (*op_end
))
310 a
= parse_register_operand (&op_end
);
312 as_warn (_("expecting comma delimited register operands"));
316 as_bad (_("expecting indirect register `($rA)'"));
317 ignore_rest_of_line ();
321 b
= parse_register_operand (&op_end
);
324 as_bad (_("missing closing parenthesis"));
325 ignore_rest_of_line ();
329 iword
+= (a
<< 4) + b
;
330 while (ISSPACE (*op_end
))
333 as_warn (_("extra stuff on line ignored"));
337 iword
= opcode
->opcode
<< 8;
338 while (ISSPACE (*op_end
))
344 as_bad (_("expecting indirect register `($rA)'"));
345 ignore_rest_of_line ();
349 a
= parse_register_operand (&op_end
);
352 as_bad (_("missing closing parenthesis"));
353 ignore_rest_of_line ();
358 as_warn (_("expecting comma delimited register operands"));
360 b
= parse_register_operand (&op_end
);
361 iword
+= (a
<< 4) + b
;
362 while (ISSPACE (*op_end
))
365 as_warn (_("extra stuff on line ignored"));
369 iword
= opcode
->opcode
<< 8;
370 while (ISSPACE (*op_end
))
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
),
388 as_bad (_("expecting comma delimited operands"));
389 ignore_rest_of_line ();
394 a
= parse_register_operand (&op_end
);
395 while (ISSPACE (*op_end
))
398 as_warn (_("extra stuff on line ignored"));
404 iword
= opcode
->opcode
<< 8;
405 while (ISSPACE (*op_end
))
412 a
= parse_register_operand (&op_end
);
413 while (ISSPACE (*op_end
))
418 as_bad (_("expecting comma delimited operands"));
419 ignore_rest_of_line ();
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
),
435 as_bad (_("expecting indirect register `($rX)'"));
436 ignore_rest_of_line ();
440 b
= parse_register_operand (&op_end
);
443 as_bad (_("missing closing parenthesis"));
444 ignore_rest_of_line ();
449 while (ISSPACE (*op_end
))
452 as_warn (_("extra stuff on line ignored"));
454 iword
+= (a
<< 4) + b
;
458 iword
= opcode
->opcode
<< 8;
459 while (ISSPACE (*op_end
))
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
),
477 as_bad (_("expecting indirect register `($rX)'"));
478 ignore_rest_of_line ();
482 a
= parse_register_operand (&op_end
);
485 as_bad (_("missing closing parenthesis"));
486 ignore_rest_of_line ();
493 as_bad (_("expecting comma delimited operands"));
494 ignore_rest_of_line ();
499 b
= parse_register_operand (&op_end
);
500 while (ISSPACE (*op_end
))
503 while (ISSPACE (*op_end
))
506 as_warn (_("extra stuff on line ignored"));
508 iword
+= (a
<< 4) + b
;
512 iword
= opcode
->opcode
<< 12;
513 while (ISSPACE (*op_end
))
516 as_warn (_("extra stuff on line ignored"));
519 iword
= (3<<14) | (opcode
->opcode
<< 10);
520 while (ISSPACE (*op_end
))
525 op_end
= parse_exp_save_ilp (op_end
, &arg
);
526 fix_new_exp (frag_now
,
527 (p
- frag_now
->fr_literal
),
531 BFD_RELOC_MOXIE_10_PCREL
);
538 md_number_to_chars (p
, iword
, 2);
540 while (ISSPACE (*op_end
))
544 as_warn (_("extra stuff on line ignored"));
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. */
556 md_atof (int type
, char *litP
, int *sizeP
)
559 LITTLENUM_TYPE words
[4];
575 return _("bad call to md_atof");
578 t
= atof_ieee (input_line_pointer
, type
, words
);
580 input_line_pointer
= t
;
584 for (i
= prec
- 1; i
>= 0; i
--)
586 md_number_to_chars (litP
, (valueT
) words
[i
], 2);
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
)
610 md_show_usage (FILE *stream ATTRIBUTE_UNUSED
)
614 /* Apply a fixup to the object file. */
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
;
626 switch (fixP
->fx_r_type
)
644 case BFD_RELOC_MOXIE_10_PCREL
:
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. */
652 newval
= md_chars_to_number (buf
, 2);
653 newval
|= val
& 0x03ff;
654 md_number_to_chars (buf
, newval
, 2);
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)
668 /* Put number into target byte order (big endian). */
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. */
679 md_chars_to_number (char *val
, int n
)
686 retval
|= (*val
++ & 255);
692 /* Generate a machine-dependent relocation. */
694 tc_gen_reloc (asection
*section ATTRIBUTE_UNUSED
, fixS
*fixP
)
697 bfd_reloc_code_real_type code
;
699 switch (fixP
->fx_r_type
)
702 code
= fixP
->fx_r_type
;
704 case BFD_RELOC_MOXIE_10_PCREL
:
705 code
= fixP
->fx_r_type
;
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"));
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
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
);
755 name
= S_GET_NAME (fixP
->fx_addsy
);
757 name
= _("<unknown>");
758 as_fatal (_("Cannot generate relocation type for symbol %s, code %s"),
759 name
, bfd_get_reloc_code_name (code
));
765 /* Decide from what point a pc-relative relocation is relative to,
766 relative to the pc-relative fixup. Er, relatively speaking. */
768 md_pcrel_from (fixS
*fixP
)
770 valueT addr
= fixP
->fx_where
+ fixP
->fx_frag
->fr_address
;
772 switch (fixP
->fx_r_type
)
776 case BFD_RELOC_MOXIE_10_PCREL
: