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
;
628 switch (fixP
->fx_r_type
)
646 case BFD_RELOC_MOXIE_10_PCREL
:
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. */
654 newval
= md_chars_to_number (buf
, 2);
655 newval
|= val
& 0x03ff;
656 md_number_to_chars (buf
, newval
, 2);
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)
670 /* Put number into target byte order (big endian). */
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. */
681 md_chars_to_number (char *val
, int n
)
688 retval
|= (*val
++ & 255);
694 /* Generate a machine-dependent relocation. */
696 tc_gen_reloc (asection
*section ATTRIBUTE_UNUSED
, fixS
*fixP
)
699 bfd_reloc_code_real_type code
;
701 switch (fixP
->fx_r_type
)
704 code
= fixP
->fx_r_type
;
706 case BFD_RELOC_MOXIE_10_PCREL
:
707 code
= fixP
->fx_r_type
;
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"));
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
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
);
757 name
= S_GET_NAME (fixP
->fx_addsy
);
759 name
= _("<unknown>");
760 as_fatal (_("Cannot generate relocation type for symbol %s, code %s"),
761 name
, bfd_get_reloc_code_name (code
));
767 /* Decide from what point a pc-relative relocation is relative to,
768 relative to the pc-relative fixup. Er, relatively speaking. */
770 md_pcrel_from (fixS
*fixP
)
772 valueT addr
= fixP
->fx_where
+ fixP
->fx_frag
->fr_address
;
774 switch (fixP
->fx_r_type
)
778 case BFD_RELOC_MOXIE_10_PCREL
: