1 /* tc-moxie.c -- Assemble code for moxie
2 Copyright (C) 2009-2019 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
;
51 md_operand (expressionS
*op
__attribute__((unused
)))
56 /* This function is called once, at assembler startup time. It sets
57 up the hash table with all the opcodes in it, and also initializes
58 some aliases for compatibility with other assemblers. */
64 const moxie_opc_info_t
*opcode
;
65 opcode_hash_control
= hash_new ();
67 /* Insert names into hash table. */
68 for (count
= 0, opcode
= moxie_form1_opc_info
; count
++ < 64; opcode
++)
69 hash_insert (opcode_hash_control
, opcode
->name
, (char *) opcode
);
71 for (count
= 0, opcode
= moxie_form2_opc_info
; count
++ < 4; opcode
++)
72 hash_insert (opcode_hash_control
, opcode
->name
, (char *) opcode
);
74 for (count
= 0, opcode
= moxie_form3_opc_info
; count
++ < 10; opcode
++)
75 hash_insert (opcode_hash_control
, opcode
->name
, (char *) opcode
);
77 target_big_endian
= TARGET_BYTES_BIG_ENDIAN
;
79 bfd_set_arch_mach (stdoutput
, TARGET_ARCH
, 0);
82 /* Parse an expression and then restore the input line pointer. */
85 parse_exp_save_ilp (char *s
, expressionS
*op
)
87 char *save
= input_line_pointer
;
89 input_line_pointer
= s
;
91 s
= input_line_pointer
;
92 input_line_pointer
= save
;
97 parse_register_operand (char **ptr
)
104 as_bad (_("expecting register"));
105 ignore_rest_of_line ();
108 if (s
[1] == 'f' && s
[2] == 'p')
113 if (s
[1] == 's' && s
[2] == 'p')
121 if ((reg
< 0) || (reg
> 9))
123 as_bad (_("illegal register number"));
124 ignore_rest_of_line ();
130 if ((r2
>= 0) && (r2
<= 3))
139 as_bad (_("illegal register number"));
140 ignore_rest_of_line ();
149 /* This is the guts of the machine-dependent assembler. STR points to
150 a machine dependent instruction. This function is supposed to emit
151 the frags/bytes it assembles to. */
154 md_assemble (char *str
)
159 moxie_opc_info_t
*opcode
;
163 unsigned short iword
= 0;
167 /* Drop leading whitespace. */
171 /* Find the op code end. */
174 *op_end
&& !is_end_of_line
[*op_end
& 0xff] && *op_end
!= ' ';
182 as_bad (_("can't find opcode "));
183 opcode
= (moxie_opc_info_t
*) hash_find (opcode_hash_control
, op_start
);
188 as_bad (_("unknown opcode %s"), op_start
);
194 switch (opcode
->itype
)
197 iword
= (1<<15) | (opcode
->opcode
<< 12);
198 while (ISSPACE (*op_end
))
203 reg
= parse_register_operand (&op_end
);
206 as_warn (_("expecting comma delimited register operands"));
208 op_end
= parse_exp_save_ilp (op_end
, &arg
);
209 fix_new_exp (frag_now
,
210 ((p
+ (target_big_endian
? 1 : 0)) - frag_now
->fr_literal
),
218 iword
= opcode
->opcode
<< 8;
219 while (ISSPACE (*op_end
))
223 dest
= parse_register_operand (&op_end
);
225 as_warn (_("expecting comma delimited register operands"));
227 src
= parse_register_operand (&op_end
);
228 iword
+= (dest
<< 4) + src
;
229 while (ISSPACE (*op_end
))
232 as_warn (_("extra stuff on line ignored"));
236 iword
= opcode
->opcode
<< 8;
237 while (ISSPACE (*op_end
))
244 regnum
= parse_register_operand (&op_end
);
245 while (ISSPACE (*op_end
))
248 iword
+= (regnum
<< 4);
252 as_bad (_("expecting comma delimited operands"));
253 ignore_rest_of_line ();
258 op_end
= parse_exp_save_ilp (op_end
, &arg
);
259 where
= frag_more (4);
260 fix_new_exp (frag_now
,
261 (where
- frag_now
->fr_literal
),
270 iword
= opcode
->opcode
<< 8;
271 while (ISSPACE (*op_end
))
277 op_end
= parse_exp_save_ilp (op_end
, &arg
);
278 where
= frag_more (4);
279 fix_new_exp (frag_now
,
280 (where
- frag_now
->fr_literal
),
288 iword
= opcode
->opcode
<< 8;
289 while (ISSPACE (*op_end
))
292 as_warn (_("extra stuff on line ignored"));
295 iword
= opcode
->opcode
<< 8;
296 while (ISSPACE (*op_end
))
300 reg
= parse_register_operand (&op_end
);
301 while (ISSPACE (*op_end
))
304 as_warn (_("extra stuff on line ignored"));
309 iword
= opcode
->opcode
<< 8;
310 while (ISSPACE (*op_end
))
314 a
= parse_register_operand (&op_end
);
316 as_warn (_("expecting comma delimited register operands"));
320 as_bad (_("expecting indirect register `($rA)'"));
321 ignore_rest_of_line ();
325 b
= parse_register_operand (&op_end
);
328 as_bad (_("missing closing parenthesis"));
329 ignore_rest_of_line ();
333 iword
+= (a
<< 4) + b
;
334 while (ISSPACE (*op_end
))
337 as_warn (_("extra stuff on line ignored"));
341 iword
= opcode
->opcode
<< 8;
342 while (ISSPACE (*op_end
))
348 as_bad (_("expecting indirect register `($rA)'"));
349 ignore_rest_of_line ();
353 a
= parse_register_operand (&op_end
);
356 as_bad (_("missing closing parenthesis"));
357 ignore_rest_of_line ();
362 as_warn (_("expecting comma delimited register operands"));
364 b
= parse_register_operand (&op_end
);
365 iword
+= (a
<< 4) + b
;
366 while (ISSPACE (*op_end
))
369 as_warn (_("extra stuff on line ignored"));
373 iword
= opcode
->opcode
<< 8;
374 while (ISSPACE (*op_end
))
381 op_end
= parse_exp_save_ilp (op_end
, &arg
);
382 where
= frag_more (4);
383 fix_new_exp (frag_now
,
384 (where
- frag_now
->fr_literal
),
392 as_bad (_("expecting comma delimited operands"));
393 ignore_rest_of_line ();
398 a
= parse_register_operand (&op_end
);
399 while (ISSPACE (*op_end
))
402 as_warn (_("extra stuff on line ignored"));
408 iword
= opcode
->opcode
<< 8;
409 while (ISSPACE (*op_end
))
416 a
= parse_register_operand (&op_end
);
417 while (ISSPACE (*op_end
))
422 as_bad (_("expecting comma delimited operands"));
423 ignore_rest_of_line ();
428 op_end
= parse_exp_save_ilp (op_end
, &arg
);
429 offset
= frag_more (2);
430 fix_new_exp (frag_now
,
431 (offset
- frag_now
->fr_literal
),
439 as_bad (_("expecting indirect register `($rX)'"));
440 ignore_rest_of_line ();
444 b
= parse_register_operand (&op_end
);
447 as_bad (_("missing closing parenthesis"));
448 ignore_rest_of_line ();
453 while (ISSPACE (*op_end
))
456 as_warn (_("extra stuff on line ignored"));
458 iword
+= (a
<< 4) + b
;
462 iword
= opcode
->opcode
<< 8;
463 while (ISSPACE (*op_end
))
470 op_end
= parse_exp_save_ilp (op_end
, &arg
);
471 offset
= frag_more (2);
472 fix_new_exp (frag_now
,
473 (offset
- frag_now
->fr_literal
),
481 as_bad (_("expecting indirect register `($rX)'"));
482 ignore_rest_of_line ();
486 a
= parse_register_operand (&op_end
);
489 as_bad (_("missing closing parenthesis"));
490 ignore_rest_of_line ();
497 as_bad (_("expecting comma delimited operands"));
498 ignore_rest_of_line ();
503 b
= parse_register_operand (&op_end
);
504 while (ISSPACE (*op_end
))
507 while (ISSPACE (*op_end
))
510 as_warn (_("extra stuff on line ignored"));
512 iword
+= (a
<< 4) + b
;
516 iword
= opcode
->opcode
<< 12;
517 while (ISSPACE (*op_end
))
520 as_warn (_("extra stuff on line ignored"));
523 iword
= (3<<14) | (opcode
->opcode
<< 10);
524 while (ISSPACE (*op_end
))
529 op_end
= parse_exp_save_ilp (op_end
, &arg
);
530 fix_new_exp (frag_now
,
531 (p
- frag_now
->fr_literal
),
535 BFD_RELOC_MOXIE_10_PCREL
);
540 while (ISSPACE (*op_end
))
543 as_warn (_("extra stuff on line ignored"));
549 md_number_to_chars (p
, iword
, 2);
550 dwarf2_emit_insn (2);
552 while (ISSPACE (*op_end
))
556 as_warn (_("extra stuff on line ignored"));
559 as_bad (_("Something forgot to clean up\n"));
562 /* Turn a string in input_line_pointer into a floating point constant
563 of type type, and store the appropriate bytes in *LITP. The number
564 of LITTLENUMS emitted is stored in *SIZEP . An error message is
565 returned, or NULL on OK. */
568 md_atof (int type
, char *litP
, int *sizeP
)
571 LITTLENUM_TYPE words
[4];
587 return _("bad call to md_atof");
590 t
= atof_ieee (input_line_pointer
, type
, words
);
592 input_line_pointer
= t
;
596 for (i
= prec
- 1; i
>= 0; i
--)
598 md_number_to_chars (litP
, (valueT
) words
[i
], 2);
607 OPTION_EB
= OPTION_MD_BASE
,
611 struct option md_longopts
[] =
613 { "EB", no_argument
, NULL
, OPTION_EB
},
614 { "EL", no_argument
, NULL
, OPTION_EL
},
615 { NULL
, no_argument
, NULL
, 0}
618 size_t md_longopts_size
= sizeof (md_longopts
);
620 const char *md_shortopts
= "";
623 md_parse_option (int c ATTRIBUTE_UNUSED
, const char *arg ATTRIBUTE_UNUSED
)
628 target_big_endian
= 1;
631 target_big_endian
= 0;
641 md_show_usage (FILE *stream ATTRIBUTE_UNUSED
)
643 fprintf (stream
, _("\
644 -EB assemble for a big endian system (default)\n\
645 -EL assemble for a little endian system\n"));
648 /* Apply a fixup to the object file. */
651 md_apply_fix (fixS
*fixP ATTRIBUTE_UNUSED
,
652 valueT
* valP ATTRIBUTE_UNUSED
, segT seg ATTRIBUTE_UNUSED
)
654 char *buf
= fixP
->fx_where
+ fixP
->fx_frag
->fr_literal
;
660 switch (fixP
->fx_r_type
)
663 if (target_big_endian
)
681 if (target_big_endian
)
698 case BFD_RELOC_MOXIE_10_PCREL
:
701 if (val
< -1024 || val
> 1022)
702 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
703 _("pcrel too far BFD_RELOC_MOXIE_10"));
704 /* 11 bit offset even numbered, so we remove right bit. */
706 newval
= md_chars_to_number (buf
, 2);
707 newval
|= val
& 0x03ff;
708 md_number_to_chars (buf
, newval
, 2);
715 if (max
!= 0 && (val
< min
|| val
> max
))
716 as_bad_where (fixP
->fx_file
, fixP
->fx_line
, _("offset out of range"));
718 if (fixP
->fx_addsy
== NULL
&& fixP
->fx_pcrel
== 0)
722 /* Put number into target byte order. */
725 md_number_to_chars (char * ptr
, valueT use
, int nbytes
)
727 if (target_big_endian
)
728 number_to_chars_bigendian (ptr
, use
, nbytes
);
730 number_to_chars_littleendian (ptr
, use
, nbytes
);
733 /* Convert from target byte order to host byte order. */
736 md_chars_to_number (char * buf
, int n
)
739 unsigned char * where
= (unsigned char *) buf
;
741 if (target_big_endian
)
746 result
|= (*where
++ & 255);
754 result
|= (where
[n
] & 255);
761 /* Generate a machine-dependent relocation. */
763 tc_gen_reloc (asection
*section ATTRIBUTE_UNUSED
, fixS
*fixP
)
766 bfd_reloc_code_real_type code
;
768 switch (fixP
->fx_r_type
)
771 code
= fixP
->fx_r_type
;
773 case BFD_RELOC_MOXIE_10_PCREL
:
774 code
= fixP
->fx_r_type
;
777 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
778 _("Semantics error. This type of operand can not be relocated, it must be an assembly-time constant"));
782 relP
= XNEW (arelent
);
783 relP
->sym_ptr_ptr
= XNEW (asymbol
*);
784 *relP
->sym_ptr_ptr
= symbol_get_bfdsym (fixP
->fx_addsy
);
785 relP
->address
= fixP
->fx_frag
->fr_address
+ fixP
->fx_where
;
787 relP
->addend
= fixP
->fx_offset
;
789 /* This is the standard place for KLUDGEs to work around bugs in
790 bfd_install_relocation (first such note in the documentation
791 appears with binutils-2.8).
793 That function bfd_install_relocation does the wrong thing with
794 putting stuff into the addend of a reloc (it should stay out) for a
795 weak symbol. The really bad thing is that it adds the
796 "segment-relative offset" of the symbol into the reloc. In this
797 case, the reloc should instead be relative to the symbol with no
798 other offset than the assembly code shows; and since the symbol is
799 weak, any local definition should be ignored until link time (or
801 To wit: weaksym+42 should be weaksym+42 in the reloc,
802 not weaksym+(offset_from_segment_of_local_weaksym_definition)
804 To "work around" this, we subtract the segment-relative offset of
805 "known" weak symbols. This evens out the extra offset.
807 That happens for a.out but not for ELF, since for ELF,
808 bfd_install_relocation uses the "special function" field of the
809 howto, and does not execute the code that needs to be undone. */
811 if (OUTPUT_FLAVOR
== bfd_target_aout_flavour
812 && fixP
->fx_addsy
&& S_IS_WEAK (fixP
->fx_addsy
)
813 && ! bfd_is_und_section (S_GET_SEGMENT (fixP
->fx_addsy
)))
815 relP
->addend
-= S_GET_VALUE (fixP
->fx_addsy
);
818 relP
->howto
= bfd_reloc_type_lookup (stdoutput
, code
);
823 name
= S_GET_NAME (fixP
->fx_addsy
);
825 name
= _("<unknown>");
826 as_fatal (_("Cannot generate relocation type for symbol %s, code %s"),
827 name
, bfd_get_reloc_code_name (code
));
833 /* Decide from what point a pc-relative relocation is relative to,
834 relative to the pc-relative fixup. Er, relatively speaking. */
836 md_pcrel_from (fixS
*fixP
)
838 valueT addr
= fixP
->fx_where
+ fixP
->fx_frag
->fr_address
;
840 switch (fixP
->fx_r_type
)
844 case BFD_RELOC_MOXIE_10_PCREL
:
845 /* Offset is from the end of the instruction. */