1 /* tc-moxie.c -- Assemble code for moxie
2 Copyright (C) 2009-2023 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 htab_t 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
= str_htab_create ();
67 /* Insert names into hash table. */
68 for (count
= 0, opcode
= moxie_form1_opc_info
; count
++ < 64; opcode
++)
69 str_hash_insert (opcode_hash_control
, opcode
->name
, opcode
, 0);
71 for (count
= 0, opcode
= moxie_form2_opc_info
; count
++ < 4; opcode
++)
72 str_hash_insert (opcode_hash_control
, opcode
->name
, opcode
, 0);
74 for (count
= 0, opcode
= moxie_form3_opc_info
; count
++ < 10; opcode
++)
75 str_hash_insert (opcode_hash_control
, opcode
->name
, opcode
, 0);
77 bfd_set_arch_mach (stdoutput
, TARGET_ARCH
, 0);
80 /* Parse an expression and then restore the input line pointer. */
83 parse_exp_save_ilp (char *s
, expressionS
*op
)
85 char *save
= input_line_pointer
;
87 input_line_pointer
= s
;
89 s
= input_line_pointer
;
90 input_line_pointer
= save
;
95 parse_register_operand (char **ptr
)
102 as_bad (_("expecting register"));
103 ignore_rest_of_line ();
106 if (s
[1] == 'f' && s
[2] == 'p')
111 if (s
[1] == 's' && s
[2] == 'p')
119 if ((reg
< 0) || (reg
> 9))
121 as_bad (_("illegal register number"));
122 ignore_rest_of_line ();
128 if ((r2
>= 0) && (r2
<= 3))
137 as_bad (_("illegal register number"));
138 ignore_rest_of_line ();
147 /* This is the guts of the machine-dependent assembler. STR points to
148 a machine dependent instruction. This function is supposed to emit
149 the frags/bytes it assembles to. */
152 md_assemble (char *str
)
157 moxie_opc_info_t
*opcode
;
161 unsigned short iword
= 0;
165 /* Drop leading whitespace. */
169 /* Find the op code end. */
172 *op_end
&& !is_end_of_line
[*op_end
& 0xff] && *op_end
!= ' ';
180 as_bad (_("can't find opcode "));
181 opcode
= (moxie_opc_info_t
*) str_hash_find (opcode_hash_control
, op_start
);
186 as_bad (_("unknown opcode %s"), op_start
);
192 switch (opcode
->itype
)
195 iword
= (1<<15) | (opcode
->opcode
<< 12);
196 while (ISSPACE (*op_end
))
201 reg
= parse_register_operand (&op_end
);
204 as_warn (_("expecting comma delimited register operands"));
206 op_end
= parse_exp_save_ilp (op_end
, &arg
);
207 fix_new_exp (frag_now
,
208 ((p
+ (target_big_endian
? 1 : 0)) - frag_now
->fr_literal
),
216 iword
= opcode
->opcode
<< 8;
217 while (ISSPACE (*op_end
))
221 dest
= parse_register_operand (&op_end
);
223 as_warn (_("expecting comma delimited register operands"));
225 src
= parse_register_operand (&op_end
);
226 iword
+= (dest
<< 4) + src
;
227 while (ISSPACE (*op_end
))
230 as_warn (_("extra stuff on line ignored"));
234 iword
= opcode
->opcode
<< 8;
235 while (ISSPACE (*op_end
))
242 regnum
= parse_register_operand (&op_end
);
243 while (ISSPACE (*op_end
))
246 iword
+= (regnum
<< 4);
250 as_bad (_("expecting comma delimited operands"));
251 ignore_rest_of_line ();
256 op_end
= parse_exp_save_ilp (op_end
, &arg
);
257 where
= frag_more (4);
258 fix_new_exp (frag_now
,
259 (where
- frag_now
->fr_literal
),
268 iword
= opcode
->opcode
<< 8;
269 while (ISSPACE (*op_end
))
275 op_end
= parse_exp_save_ilp (op_end
, &arg
);
276 where
= frag_more (4);
277 fix_new_exp (frag_now
,
278 (where
- frag_now
->fr_literal
),
286 iword
= opcode
->opcode
<< 8;
287 while (ISSPACE (*op_end
))
290 as_warn (_("extra stuff on line ignored"));
293 iword
= opcode
->opcode
<< 8;
294 while (ISSPACE (*op_end
))
298 reg
= parse_register_operand (&op_end
);
299 while (ISSPACE (*op_end
))
302 as_warn (_("extra stuff on line ignored"));
307 iword
= opcode
->opcode
<< 8;
308 while (ISSPACE (*op_end
))
312 a
= parse_register_operand (&op_end
);
314 as_warn (_("expecting comma delimited register operands"));
318 as_bad (_("expecting indirect register `($rA)'"));
319 ignore_rest_of_line ();
323 b
= parse_register_operand (&op_end
);
326 as_bad (_("missing closing parenthesis"));
327 ignore_rest_of_line ();
331 iword
+= (a
<< 4) + b
;
332 while (ISSPACE (*op_end
))
335 as_warn (_("extra stuff on line ignored"));
339 iword
= opcode
->opcode
<< 8;
340 while (ISSPACE (*op_end
))
346 as_bad (_("expecting indirect register `($rA)'"));
347 ignore_rest_of_line ();
351 a
= parse_register_operand (&op_end
);
354 as_bad (_("missing closing parenthesis"));
355 ignore_rest_of_line ();
360 as_warn (_("expecting comma delimited register operands"));
362 b
= parse_register_operand (&op_end
);
363 iword
+= (a
<< 4) + b
;
364 while (ISSPACE (*op_end
))
367 as_warn (_("extra stuff on line ignored"));
371 iword
= opcode
->opcode
<< 8;
372 while (ISSPACE (*op_end
))
379 op_end
= parse_exp_save_ilp (op_end
, &arg
);
380 where
= frag_more (4);
381 fix_new_exp (frag_now
,
382 (where
- frag_now
->fr_literal
),
390 as_bad (_("expecting comma delimited operands"));
391 ignore_rest_of_line ();
396 a
= parse_register_operand (&op_end
);
397 while (ISSPACE (*op_end
))
400 as_warn (_("extra stuff on line ignored"));
406 iword
= opcode
->opcode
<< 8;
407 while (ISSPACE (*op_end
))
414 a
= parse_register_operand (&op_end
);
415 while (ISSPACE (*op_end
))
420 as_bad (_("expecting comma delimited operands"));
421 ignore_rest_of_line ();
426 op_end
= parse_exp_save_ilp (op_end
, &arg
);
427 offset
= frag_more (2);
428 fix_new_exp (frag_now
,
429 (offset
- frag_now
->fr_literal
),
437 as_bad (_("expecting indirect register `($rX)'"));
438 ignore_rest_of_line ();
442 b
= parse_register_operand (&op_end
);
445 as_bad (_("missing closing parenthesis"));
446 ignore_rest_of_line ();
451 while (ISSPACE (*op_end
))
454 as_warn (_("extra stuff on line ignored"));
456 iword
+= (a
<< 4) + b
;
460 iword
= opcode
->opcode
<< 8;
461 while (ISSPACE (*op_end
))
468 op_end
= parse_exp_save_ilp (op_end
, &arg
);
469 offset
= frag_more (2);
470 fix_new_exp (frag_now
,
471 (offset
- frag_now
->fr_literal
),
479 as_bad (_("expecting indirect register `($rX)'"));
480 ignore_rest_of_line ();
484 a
= parse_register_operand (&op_end
);
487 as_bad (_("missing closing parenthesis"));
488 ignore_rest_of_line ();
495 as_bad (_("expecting comma delimited operands"));
496 ignore_rest_of_line ();
501 b
= parse_register_operand (&op_end
);
502 while (ISSPACE (*op_end
))
505 while (ISSPACE (*op_end
))
508 as_warn (_("extra stuff on line ignored"));
510 iword
+= (a
<< 4) + b
;
514 iword
= opcode
->opcode
<< 12;
515 while (ISSPACE (*op_end
))
518 as_warn (_("extra stuff on line ignored"));
521 iword
= (3<<14) | (opcode
->opcode
<< 10);
522 while (ISSPACE (*op_end
))
527 op_end
= parse_exp_save_ilp (op_end
, &arg
);
528 fix_new_exp (frag_now
,
529 (p
- frag_now
->fr_literal
),
533 BFD_RELOC_MOXIE_10_PCREL
);
538 while (ISSPACE (*op_end
))
541 as_warn (_("extra stuff on line ignored"));
547 md_number_to_chars (p
, iword
, 2);
548 dwarf2_emit_insn (2);
550 while (ISSPACE (*op_end
))
554 as_warn (_("extra stuff on line ignored"));
557 as_bad (_("Something forgot to clean up\n"));
560 /* Turn a string in input_line_pointer into a floating point constant
561 of type type, and store the appropriate bytes in *LITP. The number
562 of LITTLENUMS emitted is stored in *SIZEP . An error message is
563 returned, or NULL on OK. */
566 md_atof (int type
, char *litP
, int *sizeP
)
569 LITTLENUM_TYPE words
[4];
585 return _("bad call to md_atof");
588 t
= atof_ieee (input_line_pointer
, type
, words
);
590 input_line_pointer
= t
;
594 for (i
= prec
- 1; i
>= 0; i
--)
596 md_number_to_chars (litP
, (valueT
) words
[i
], 2);
605 OPTION_EB
= OPTION_MD_BASE
,
609 struct option md_longopts
[] =
611 { "EB", no_argument
, NULL
, OPTION_EB
},
612 { "EL", no_argument
, NULL
, OPTION_EL
},
613 { NULL
, no_argument
, NULL
, 0}
616 size_t md_longopts_size
= sizeof (md_longopts
);
618 const char *md_shortopts
= "";
621 md_parse_option (int c ATTRIBUTE_UNUSED
, const char *arg ATTRIBUTE_UNUSED
)
626 target_big_endian
= 1;
629 target_big_endian
= 0;
639 md_show_usage (FILE *stream ATTRIBUTE_UNUSED
)
641 fprintf (stream
, _("\
642 -EB assemble for a big endian system (default)\n\
643 -EL assemble for a little endian system\n"));
646 /* Apply a fixup to the object file. */
649 md_apply_fix (fixS
*fixP ATTRIBUTE_UNUSED
,
650 valueT
* valP ATTRIBUTE_UNUSED
, segT seg ATTRIBUTE_UNUSED
)
652 char *buf
= fixP
->fx_where
+ fixP
->fx_frag
->fr_literal
;
658 switch (fixP
->fx_r_type
)
661 if (target_big_endian
)
679 if (target_big_endian
)
696 case BFD_RELOC_MOXIE_10_PCREL
:
699 if (val
< -1024 || val
> 1022)
700 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
701 _("pcrel too far BFD_RELOC_MOXIE_10"));
702 /* 11 bit offset even numbered, so we remove right bit. */
704 newval
= md_chars_to_number (buf
, 2);
705 newval
|= val
& 0x03ff;
706 md_number_to_chars (buf
, newval
, 2);
713 if (max
!= 0 && (val
< min
|| val
> max
))
714 as_bad_where (fixP
->fx_file
, fixP
->fx_line
, _("offset out of range"));
716 if (fixP
->fx_addsy
== NULL
&& fixP
->fx_pcrel
== 0)
720 /* Put number into target byte order. */
723 md_number_to_chars (char * ptr
, valueT use
, int nbytes
)
725 if (target_big_endian
)
726 number_to_chars_bigendian (ptr
, use
, nbytes
);
728 number_to_chars_littleendian (ptr
, use
, nbytes
);
731 /* Convert from target byte order to host byte order. */
734 md_chars_to_number (char * buf
, int n
)
737 unsigned char * where
= (unsigned char *) buf
;
739 if (target_big_endian
)
744 result
|= (*where
++ & 255);
752 result
|= (where
[n
] & 255);
759 /* Generate a machine-dependent relocation. */
761 tc_gen_reloc (asection
*section ATTRIBUTE_UNUSED
, fixS
*fixP
)
764 bfd_reloc_code_real_type code
;
766 switch (fixP
->fx_r_type
)
769 code
= fixP
->fx_r_type
;
771 case BFD_RELOC_MOXIE_10_PCREL
:
772 code
= fixP
->fx_r_type
;
775 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
776 _("Semantics error. This type of operand can not be relocated, it must be an assembly-time constant"));
780 relP
= XNEW (arelent
);
781 relP
->sym_ptr_ptr
= XNEW (asymbol
*);
782 *relP
->sym_ptr_ptr
= symbol_get_bfdsym (fixP
->fx_addsy
);
783 relP
->address
= fixP
->fx_frag
->fr_address
+ fixP
->fx_where
;
785 relP
->addend
= fixP
->fx_offset
;
787 /* This is the standard place for KLUDGEs to work around bugs in
788 bfd_install_relocation (first such note in the documentation
789 appears with binutils-2.8).
791 That function bfd_install_relocation does the wrong thing with
792 putting stuff into the addend of a reloc (it should stay out) for a
793 weak symbol. The really bad thing is that it adds the
794 "segment-relative offset" of the symbol into the reloc. In this
795 case, the reloc should instead be relative to the symbol with no
796 other offset than the assembly code shows; and since the symbol is
797 weak, any local definition should be ignored until link time (or
799 To wit: weaksym+42 should be weaksym+42 in the reloc,
800 not weaksym+(offset_from_segment_of_local_weaksym_definition)
802 To "work around" this, we subtract the segment-relative offset of
803 "known" weak symbols. This evens out the extra offset.
805 That happens for a.out but not for ELF, since for ELF,
806 bfd_install_relocation uses the "special function" field of the
807 howto, and does not execute the code that needs to be undone. */
809 if (OUTPUT_FLAVOR
== bfd_target_aout_flavour
810 && fixP
->fx_addsy
&& S_IS_WEAK (fixP
->fx_addsy
)
811 && ! bfd_is_und_section (S_GET_SEGMENT (fixP
->fx_addsy
)))
813 relP
->addend
-= S_GET_VALUE (fixP
->fx_addsy
);
816 relP
->howto
= bfd_reloc_type_lookup (stdoutput
, code
);
821 name
= S_GET_NAME (fixP
->fx_addsy
);
823 name
= _("<unknown>");
824 as_fatal (_("Cannot generate relocation type for symbol %s, code %s"),
825 name
, bfd_get_reloc_code_name (code
));
831 /* Decide from what point a pc-relative relocation is relative to,
832 relative to the pc-relative fixup. Er, relatively speaking. */
834 md_pcrel_from (fixS
*fixP
)
836 valueT addr
= fixP
->fx_where
+ fixP
->fx_frag
->fr_address
;
838 switch (fixP
->fx_r_type
)
842 case BFD_RELOC_MOXIE_10_PCREL
:
843 /* Offset is from the end of the instruction. */