1 /* tc-moxie.c -- Assemble code for moxie
2 Copyright (C) 2009-2014 Free Software Foundation, Inc.
4 This file is part of GAS, the GNU Assembler.
6 GAS is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3, or (at your option)
11 GAS is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GAS; see the file COPYING. If not, write to
18 the Free Software Foundation, 51 Franklin Street - Fifth Floor,
19 Boston, MA 02110-1301, USA. */
21 /* Contributed by Anthony Green <green@moxielogic.com>. */
24 #include "safe-ctype.h"
25 #include "opcode/moxie.h"
26 #include "elf/moxie.h"
28 extern const moxie_opc_info_t moxie_opc_info
[128];
30 const char comment_chars
[] = "#";
31 const char line_separator_chars
[] = ";";
32 const char line_comment_chars
[] = "#";
34 static int pending_reloc
;
35 static struct hash_control
*opcode_hash_control
;
37 const pseudo_typeS md_pseudo_table
[] =
42 const char FLT_CHARS
[] = "rRsSfFdDxXpP";
43 const char EXP_CHARS
[] = "eE";
45 static valueT
md_chars_to_number (char * buf
, int n
);
48 extern int target_big_endian
;
49 const char *moxie_target_format
= DEFAULT_TARGET_FORMAT
;
52 md_operand (expressionS
*op
__attribute__((unused
)))
57 /* This function is called once, at assembler startup time. It sets
58 up the hash table with all the opcodes in it, and also initializes
59 some aliases for compatibility with other assemblers. */
65 const moxie_opc_info_t
*opcode
;
66 opcode_hash_control
= hash_new ();
68 /* Insert names into hash table. */
69 for (count
= 0, opcode
= moxie_form1_opc_info
; count
++ < 64; opcode
++)
70 hash_insert (opcode_hash_control
, opcode
->name
, (char *) opcode
);
72 for (count
= 0, opcode
= moxie_form2_opc_info
; count
++ < 4; opcode
++)
73 hash_insert (opcode_hash_control
, opcode
->name
, (char *) opcode
);
75 for (count
= 0, opcode
= moxie_form3_opc_info
; count
++ < 10; opcode
++)
76 hash_insert (opcode_hash_control
, opcode
->name
, (char *) opcode
);
78 bfd_set_arch_mach (stdoutput
, TARGET_ARCH
, 0);
81 /* Parse an expression and then restore the input line pointer. */
84 parse_exp_save_ilp (char *s
, expressionS
*op
)
86 char *save
= input_line_pointer
;
88 input_line_pointer
= s
;
90 s
= input_line_pointer
;
91 input_line_pointer
= save
;
96 parse_register_operand (char **ptr
)
103 as_bad (_("expecting register"));
104 ignore_rest_of_line ();
107 if (s
[1] == 'f' && s
[2] == 'p')
112 if (s
[1] == 's' && s
[2] == 'p')
120 if ((reg
< 0) || (reg
> 9))
122 as_bad (_("illegal register number"));
123 ignore_rest_of_line ();
129 if ((r2
>= 0) && (r2
<= 3))
138 as_bad (_("illegal register number"));
139 ignore_rest_of_line ();
148 /* This is the guts of the machine-dependent assembler. STR points to
149 a machine dependent instruction. This function is supposed to emit
150 the frags/bytes it assembles to. */
153 md_assemble (char *str
)
158 moxie_opc_info_t
*opcode
;
162 unsigned short iword
= 0;
166 /* Drop leading whitespace. */
170 /* Find the op code end. */
173 *op_end
&& !is_end_of_line
[*op_end
& 0xff] && *op_end
!= ' ';
181 as_bad (_("can't find opcode "));
182 opcode
= (moxie_opc_info_t
*) hash_find (opcode_hash_control
, op_start
);
187 as_bad (_("unknown opcode %s"), op_start
);
193 switch (opcode
->itype
)
196 iword
= (1<<15) | (opcode
->opcode
<< 12);
197 while (ISSPACE (*op_end
))
202 reg
= parse_register_operand (&op_end
);
205 as_warn (_("expecting comma delimited register operands"));
207 op_end
= parse_exp_save_ilp (op_end
, &arg
);
208 fix_new_exp (frag_now
,
209 ((p
+ (target_big_endian
? 1 : 0)) - frag_now
->fr_literal
),
217 iword
= opcode
->opcode
<< 8;
218 while (ISSPACE (*op_end
))
222 dest
= parse_register_operand (&op_end
);
224 as_warn (_("expecting comma delimited register operands"));
226 src
= parse_register_operand (&op_end
);
227 iword
+= (dest
<< 4) + src
;
228 while (ISSPACE (*op_end
))
231 as_warn (_("extra stuff on line ignored"));
235 iword
= opcode
->opcode
<< 8;
236 while (ISSPACE (*op_end
))
243 regnum
= parse_register_operand (&op_end
);
244 while (ISSPACE (*op_end
))
247 iword
+= (regnum
<< 4);
251 as_bad (_("expecting comma delimited operands"));
252 ignore_rest_of_line ();
257 op_end
= parse_exp_save_ilp (op_end
, &arg
);
258 where
= frag_more (4);
259 fix_new_exp (frag_now
,
260 (where
- frag_now
->fr_literal
),
269 iword
= opcode
->opcode
<< 8;
270 while (ISSPACE (*op_end
))
276 op_end
= parse_exp_save_ilp (op_end
, &arg
);
277 where
= frag_more (4);
278 fix_new_exp (frag_now
,
279 (where
- frag_now
->fr_literal
),
287 iword
= opcode
->opcode
<< 8;
288 while (ISSPACE (*op_end
))
291 as_warn (_("extra stuff on line ignored"));
294 iword
= opcode
->opcode
<< 8;
295 while (ISSPACE (*op_end
))
299 reg
= parse_register_operand (&op_end
);
300 while (ISSPACE (*op_end
))
303 as_warn (_("extra stuff on line ignored"));
308 iword
= opcode
->opcode
<< 8;
309 while (ISSPACE (*op_end
))
313 a
= parse_register_operand (&op_end
);
315 as_warn (_("expecting comma delimited register operands"));
319 as_bad (_("expecting indirect register `($rA)'"));
320 ignore_rest_of_line ();
324 b
= parse_register_operand (&op_end
);
327 as_bad (_("missing closing parenthesis"));
328 ignore_rest_of_line ();
332 iword
+= (a
<< 4) + b
;
333 while (ISSPACE (*op_end
))
336 as_warn (_("extra stuff on line ignored"));
340 iword
= opcode
->opcode
<< 8;
341 while (ISSPACE (*op_end
))
347 as_bad (_("expecting indirect register `($rA)'"));
348 ignore_rest_of_line ();
352 a
= parse_register_operand (&op_end
);
355 as_bad (_("missing closing parenthesis"));
356 ignore_rest_of_line ();
361 as_warn (_("expecting comma delimited register operands"));
363 b
= parse_register_operand (&op_end
);
364 iword
+= (a
<< 4) + b
;
365 while (ISSPACE (*op_end
))
368 as_warn (_("extra stuff on line ignored"));
372 iword
= opcode
->opcode
<< 8;
373 while (ISSPACE (*op_end
))
380 op_end
= parse_exp_save_ilp (op_end
, &arg
);
381 where
= frag_more (4);
382 fix_new_exp (frag_now
,
383 (where
- frag_now
->fr_literal
),
391 as_bad (_("expecting comma delimited operands"));
392 ignore_rest_of_line ();
397 a
= parse_register_operand (&op_end
);
398 while (ISSPACE (*op_end
))
401 as_warn (_("extra stuff on line ignored"));
407 iword
= opcode
->opcode
<< 8;
408 while (ISSPACE (*op_end
))
415 a
= parse_register_operand (&op_end
);
416 while (ISSPACE (*op_end
))
421 as_bad (_("expecting comma delimited operands"));
422 ignore_rest_of_line ();
427 op_end
= parse_exp_save_ilp (op_end
, &arg
);
428 offset
= frag_more (4);
429 fix_new_exp (frag_now
,
430 (offset
- frag_now
->fr_literal
),
438 as_bad (_("expecting indirect register `($rX)'"));
439 ignore_rest_of_line ();
443 b
= parse_register_operand (&op_end
);
446 as_bad (_("missing closing parenthesis"));
447 ignore_rest_of_line ();
452 while (ISSPACE (*op_end
))
455 as_warn (_("extra stuff on line ignored"));
457 iword
+= (a
<< 4) + b
;
461 iword
= opcode
->opcode
<< 8;
462 while (ISSPACE (*op_end
))
469 op_end
= parse_exp_save_ilp (op_end
, &arg
);
470 offset
= frag_more (4);
471 fix_new_exp (frag_now
,
472 (offset
- frag_now
->fr_literal
),
480 as_bad (_("expecting indirect register `($rX)'"));
481 ignore_rest_of_line ();
485 a
= parse_register_operand (&op_end
);
488 as_bad (_("missing closing parenthesis"));
489 ignore_rest_of_line ();
496 as_bad (_("expecting comma delimited operands"));
497 ignore_rest_of_line ();
502 b
= parse_register_operand (&op_end
);
503 while (ISSPACE (*op_end
))
506 while (ISSPACE (*op_end
))
509 as_warn (_("extra stuff on line ignored"));
511 iword
+= (a
<< 4) + b
;
515 iword
= opcode
->opcode
<< 12;
516 while (ISSPACE (*op_end
))
519 as_warn (_("extra stuff on line ignored"));
522 iword
= (3<<14) | (opcode
->opcode
<< 10);
523 while (ISSPACE (*op_end
))
528 op_end
= parse_exp_save_ilp (op_end
, &arg
);
529 fix_new_exp (frag_now
,
530 (p
- frag_now
->fr_literal
),
534 BFD_RELOC_MOXIE_10_PCREL
);
541 md_number_to_chars (p
, iword
, 2);
543 while (ISSPACE (*op_end
))
547 as_warn (_("extra stuff on line ignored"));
550 as_bad (_("Something forgot to clean up\n"));
553 /* Turn a string in input_line_pointer into a floating point constant
554 of type type, and store the appropriate bytes in *LITP. The number
555 of LITTLENUMS emitted is stored in *SIZEP . An error message is
556 returned, or NULL on OK. */
559 md_atof (int type
, char *litP
, int *sizeP
)
562 LITTLENUM_TYPE words
[4];
578 return _("bad call to md_atof");
581 t
= atof_ieee (input_line_pointer
, type
, words
);
583 input_line_pointer
= t
;
587 for (i
= prec
- 1; i
>= 0; i
--)
589 md_number_to_chars (litP
, (valueT
) words
[i
], 2);
598 OPTION_EB
= OPTION_MD_BASE
,
602 struct option md_longopts
[] =
604 { "EB", no_argument
, NULL
, OPTION_EB
},
605 { "EL", no_argument
, NULL
, OPTION_EL
},
606 { NULL
, no_argument
, NULL
, 0}
609 size_t md_longopts_size
= sizeof (md_longopts
);
611 const char *md_shortopts
= "";
614 md_parse_option (int c ATTRIBUTE_UNUSED
, char *arg ATTRIBUTE_UNUSED
)
619 target_big_endian
= 1;
620 moxie_target_format
= "elf32-bigmoxie";
623 target_big_endian
= 0;
624 moxie_target_format
= "elf32-littlemoxie";
634 md_show_usage (FILE *stream ATTRIBUTE_UNUSED
)
636 fprintf (stream
, _("\
637 -EB assemble for a big endian system (default)\n\
638 -EL assemble for a little endian system\n"));
641 /* Apply a fixup to the object file. */
644 md_apply_fix (fixS
*fixP ATTRIBUTE_UNUSED
,
645 valueT
* valP ATTRIBUTE_UNUSED
, segT seg ATTRIBUTE_UNUSED
)
647 char *buf
= fixP
->fx_where
+ fixP
->fx_frag
->fr_literal
;
653 switch (fixP
->fx_r_type
)
656 if (target_big_endian
)
674 if (target_big_endian
)
691 case BFD_RELOC_MOXIE_10_PCREL
:
694 if (val
< -1024 || val
> 1022)
695 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
696 _("pcrel too far BFD_RELOC_MOXIE_10"));
697 /* 11 bit offset even numbered, so we remove right bit. */
699 newval
= md_chars_to_number (buf
, 2);
700 newval
|= val
& 0x03ff;
701 md_number_to_chars (buf
, newval
, 2);
708 if (max
!= 0 && (val
< min
|| val
> max
))
709 as_bad_where (fixP
->fx_file
, fixP
->fx_line
, _("offset out of range"));
711 if (fixP
->fx_addsy
== NULL
&& fixP
->fx_pcrel
== 0)
715 /* Put number into target byte order. */
718 md_number_to_chars (char * ptr
, valueT use
, int nbytes
)
720 if (target_big_endian
)
721 number_to_chars_bigendian (ptr
, use
, nbytes
);
723 number_to_chars_littleendian (ptr
, use
, nbytes
);
726 /* Convert from target byte order to host byte order. */
729 md_chars_to_number (char * buf
, int n
)
732 unsigned char * where
= (unsigned char *) buf
;
734 if (target_big_endian
)
739 result
|= (*where
++ & 255);
747 result
|= (where
[n
] & 255);
754 /* Generate a machine-dependent relocation. */
756 tc_gen_reloc (asection
*section ATTRIBUTE_UNUSED
, fixS
*fixP
)
759 bfd_reloc_code_real_type code
;
761 switch (fixP
->fx_r_type
)
764 code
= fixP
->fx_r_type
;
766 case BFD_RELOC_MOXIE_10_PCREL
:
767 code
= fixP
->fx_r_type
;
770 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
771 _("Semantics error. This type of operand can not be relocated, it must be an assembly-time constant"));
775 relP
= xmalloc (sizeof (arelent
));
776 gas_assert (relP
!= 0);
777 relP
->sym_ptr_ptr
= xmalloc (sizeof (asymbol
*));
778 *relP
->sym_ptr_ptr
= symbol_get_bfdsym (fixP
->fx_addsy
);
779 relP
->address
= fixP
->fx_frag
->fr_address
+ fixP
->fx_where
;
781 relP
->addend
= fixP
->fx_offset
;
783 /* This is the standard place for KLUDGEs to work around bugs in
784 bfd_install_relocation (first such note in the documentation
785 appears with binutils-2.8).
787 That function bfd_install_relocation does the wrong thing with
788 putting stuff into the addend of a reloc (it should stay out) for a
789 weak symbol. The really bad thing is that it adds the
790 "segment-relative offset" of the symbol into the reloc. In this
791 case, the reloc should instead be relative to the symbol with no
792 other offset than the assembly code shows; and since the symbol is
793 weak, any local definition should be ignored until link time (or
795 To wit: weaksym+42 should be weaksym+42 in the reloc,
796 not weaksym+(offset_from_segment_of_local_weaksym_definition)
798 To "work around" this, we subtract the segment-relative offset of
799 "known" weak symbols. This evens out the extra offset.
801 That happens for a.out but not for ELF, since for ELF,
802 bfd_install_relocation uses the "special function" field of the
803 howto, and does not execute the code that needs to be undone. */
805 if (OUTPUT_FLAVOR
== bfd_target_aout_flavour
806 && fixP
->fx_addsy
&& S_IS_WEAK (fixP
->fx_addsy
)
807 && ! bfd_is_und_section (S_GET_SEGMENT (fixP
->fx_addsy
)))
809 relP
->addend
-= S_GET_VALUE (fixP
->fx_addsy
);
812 relP
->howto
= bfd_reloc_type_lookup (stdoutput
, code
);
817 name
= S_GET_NAME (fixP
->fx_addsy
);
819 name
= _("<unknown>");
820 as_fatal (_("Cannot generate relocation type for symbol %s, code %s"),
821 name
, bfd_get_reloc_code_name (code
));
827 /* Decide from what point a pc-relative relocation is relative to,
828 relative to the pc-relative fixup. Er, relatively speaking. */
830 md_pcrel_from (fixS
*fixP
)
832 valueT addr
= fixP
->fx_where
+ fixP
->fx_frag
->fr_address
;
834 switch (fixP
->fx_r_type
)
838 case BFD_RELOC_MOXIE_10_PCREL
:
839 /* Offset is from the end of the instruction. */