1 /* tc-ft32.c -- Assemble code for ft32
2 Copyright (C) 2008-2017 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@spindazzle.org>. */
24 #include "safe-ctype.h"
25 #include "opcode/ft32.h"
27 extern const ft32_opc_info_t ft32_opc_info
[128];
29 const char comment_chars
[] = "#";
30 const char line_separator_chars
[] = ";";
31 const char line_comment_chars
[] = "#";
33 static int pending_reloc
;
34 static struct hash_control
*opcode_hash_control
;
36 static valueT
md_chars_to_number (char * buf
, int n
);
38 const pseudo_typeS md_pseudo_table
[] =
43 const char FLT_CHARS
[] = "rRsSfFdDxXpP";
44 const char EXP_CHARS
[] = "eE";
46 /* This function is called once, at assembler startup time. It sets
47 up the hash table with all the opcodes in it, and also initializes
48 some aliases for compatibility with other assemblers. */
53 const ft32_opc_info_t
*opcode
;
54 opcode_hash_control
= hash_new ();
56 /* Insert names into hash table. */
57 for (opcode
= ft32_opc_info
; opcode
->name
; opcode
++)
58 hash_insert (opcode_hash_control
, opcode
->name
, (char *) opcode
);
60 bfd_set_arch_mach (stdoutput
, TARGET_ARCH
, 0);
63 /* Parse an expression and then restore the input line pointer. */
66 parse_exp_save_ilp (char *s
, expressionS
*op
)
68 char *save
= input_line_pointer
;
70 input_line_pointer
= s
;
72 s
= input_line_pointer
;
73 input_line_pointer
= save
;
78 parse_condition (char **ptr
)
85 { "gt," , (2 << FT32_FLD_CR_BIT
) | (5 << FT32_FLD_CB_BIT
) | (1 << FT32_FLD_CV_BIT
)},
86 { "gte," , (2 << FT32_FLD_CR_BIT
) | (4 << FT32_FLD_CB_BIT
) | (1 << FT32_FLD_CV_BIT
)},
87 { "lt," , (2 << FT32_FLD_CR_BIT
) | (4 << FT32_FLD_CB_BIT
) | (0 << FT32_FLD_CV_BIT
)},
88 { "lte," , (2 << FT32_FLD_CR_BIT
) | (5 << FT32_FLD_CB_BIT
) | (0 << FT32_FLD_CV_BIT
)},
89 { "a," , (2 << FT32_FLD_CR_BIT
) | (6 << FT32_FLD_CB_BIT
) | (1 << FT32_FLD_CV_BIT
)},
90 { "ae," , (2 << FT32_FLD_CR_BIT
) | (1 << FT32_FLD_CB_BIT
) | (0 << FT32_FLD_CV_BIT
)},
91 { "be," , (2 << FT32_FLD_CR_BIT
) | (6 << FT32_FLD_CB_BIT
) | (0 << FT32_FLD_CV_BIT
)},
92 { "b," , (2 << FT32_FLD_CR_BIT
) | (1 << FT32_FLD_CB_BIT
) | (1 << FT32_FLD_CV_BIT
)},
93 { "nz," , (2 << FT32_FLD_CR_BIT
) | (0 << FT32_FLD_CB_BIT
) | (0 << FT32_FLD_CV_BIT
)},
94 { "z," , (2 << FT32_FLD_CR_BIT
) | (0 << FT32_FLD_CB_BIT
) | (1 << FT32_FLD_CV_BIT
)},
95 { "nc," , (2 << FT32_FLD_CR_BIT
) | (1 << FT32_FLD_CB_BIT
) | (0 << FT32_FLD_CV_BIT
)},
96 { "c," , (2 << FT32_FLD_CR_BIT
) | (1 << FT32_FLD_CB_BIT
) | (1 << FT32_FLD_CV_BIT
)},
97 { "no," , (2 << FT32_FLD_CR_BIT
) | (2 << FT32_FLD_CB_BIT
) | (0 << FT32_FLD_CV_BIT
)},
98 { "o," , (2 << FT32_FLD_CR_BIT
) | (2 << FT32_FLD_CB_BIT
) | (1 << FT32_FLD_CV_BIT
)},
99 { "ns," , (2 << FT32_FLD_CR_BIT
) | (3 << FT32_FLD_CB_BIT
) | (0 << FT32_FLD_CV_BIT
)},
100 { "s," , (2 << FT32_FLD_CR_BIT
) | (3 << FT32_FLD_CB_BIT
) | (1 << FT32_FLD_CV_BIT
)},
104 for (pc
= ccs
; pc
->name
; pc
++)
106 if (memcmp(pc
->name
, s
, strlen(pc
->name
)) == 0)
108 *ptr
+= strlen(pc
->name
) - 1;
116 parse_decimal (char **ptr
)
121 while (('0' <= *s
) && (*s
<= '9'))
131 parse_register_operand (char **ptr
)
138 as_bad (_("expecting register"));
139 ignore_rest_of_line ();
142 if ((s
[1] == 's') && (s
[2] == 'p'))
146 else if ((s
[1] == 'c') && (s
[2] == 'c'))
150 else if ((s
[1] == 'f') && (s
[2] == 'p'))
154 else if (s
[1] == 'r')
157 if ((reg
< 0) || (reg
> 9))
159 as_bad (_("illegal register number"));
160 ignore_rest_of_line ();
163 if ((reg
== 1) || (reg
== 2) || (reg
== 3))
166 if ((r2
>= 0) && (r2
<= 9))
168 reg
= (reg
* 10) + r2
;
175 as_bad (_("illegal register number"));
176 ignore_rest_of_line ();
185 /* This is the guts of the machine-dependent assembler. STR points to
186 a machine dependent instruction. This function is supposed to emit
187 the frags/bytes it assembles to. */
190 md_assemble (char *str
)
195 ft32_opc_info_t
*opcode
;
207 /* Drop leading whitespace. */
211 /* Find the op code end. */
214 *op_end
&& !is_end_of_line
[*op_end
& 0xff] && *op_end
!= ' ' && *op_end
!= '.';
222 as_bad (_("can't find opcode "));
224 opcode
= (ft32_opc_info_t
*) hash_find (opcode_hash_control
, op_start
);
229 as_bad (_("unknown opcode %s"), op_start
);
253 as_bad (_("unknown width specifier '.%c'"), op_end
[1]);
260 dw
= 2; /* default is ".l" */
262 b
|= dw
<< FT32_FLD_DW_BIT
;
265 while (ISSPACE (*op_end
))
268 output
= frag_more (4);
277 case FT32_FLD_CBCRCV
:
278 b
|= parse_condition( &op_end
);
281 b
|= parse_decimal (&op_end
) << FT32_FLD_CB_BIT
;
284 b
|= parse_register_operand (&op_end
) << FT32_FLD_R_D_BIT
;
287 b
|= (parse_register_operand (&op_end
) - 28) << FT32_FLD_CR_BIT
;
290 b
|= parse_decimal (&op_end
) << FT32_FLD_CV_BIT
;
293 b
|= parse_register_operand (&op_end
) << FT32_FLD_R_1_BIT
;
298 b
|= parse_register_operand (&op_end
) << FT32_FLD_RIMM_BIT
;
302 b
|= 0x400 << FT32_FLD_RIMM_BIT
;
303 op_end
= parse_exp_save_ilp (op_end
, &arg
);
304 fix_new_exp (frag_now
,
305 (output
- frag_now
->fr_literal
),
313 b
|= parse_register_operand (&op_end
) << FT32_FLD_R_2_BIT
;
316 op_end
= parse_exp_save_ilp (op_end
, &arg
);
317 fix_new_exp (frag_now
,
318 (output
- frag_now
->fr_literal
),
325 op_end
= parse_exp_save_ilp (op_end
, &arg
);
326 fix_new_exp (frag_now
,
327 (output
- frag_now
->fr_literal
),
334 op_end
= parse_exp_save_ilp (op_end
, &arg
);
335 fix_new_exp (frag_now
,
336 (output
- frag_now
->fr_literal
),
343 op_end
= parse_exp_save_ilp (op_end
, &arg
);
344 fix_new_exp (frag_now
,
345 (output
- frag_now
->fr_literal
),
352 op_end
= parse_exp_save_ilp (op_end
, &arg
);
353 if (arg
.X_add_number
& 0x80)
354 arg
.X_add_number
^= 0x7f00;
355 fix_new_exp (frag_now
,
356 (output
- frag_now
->fr_literal
),
362 case FT32_FLD_R_D_POST
:
363 b
|= parse_register_operand (&op_end
) << FT32_FLD_R_D_BIT
;
365 case FT32_FLD_R_1_POST
:
366 b
|= parse_register_operand (&op_end
) << FT32_FLD_R_1_BIT
;
369 as_bad (_("internal error in argument parsing"));
375 while (ISSPACE (*op_end
))
380 as_bad (_("expected comma separator"));
381 ignore_rest_of_line ();
385 while (ISSPACE (*op_end
))
391 as_warn (_("extra stuff on line ignored"));
393 output
[idx
++] = 0xff & (b
>> 0);
394 output
[idx
++] = 0xff & (b
>> 8);
395 output
[idx
++] = 0xff & (b
>> 16);
396 output
[idx
++] = 0xff & (b
>> 24);
398 dwarf2_emit_insn (4);
400 while (ISSPACE (*op_end
))
404 as_warn ("extra stuff on line ignored");
407 as_bad ("Something forgot to clean up\n");
410 /* Turn a string in input_line_pointer into a floating point constant
411 of type type, and store the appropriate bytes in *LITP. The number
412 of LITTLENUMS emitted is stored in *SIZEP . An error message is
413 returned, or NULL on OK. */
416 md_atof (int type
, char *litP
, int *sizeP
)
419 LITTLENUM_TYPE words
[4];
435 return _("bad call to md_atof");
438 t
= atof_ieee (input_line_pointer
, type
, words
);
440 input_line_pointer
= t
;
444 for (i
= prec
- 1; i
>= 0; i
--)
446 md_number_to_chars (litP
, (valueT
) words
[i
], 2);
453 const char *md_shortopts
= "";
455 struct option md_longopts
[] =
457 {NULL
, no_argument
, NULL
, 0}
459 size_t md_longopts_size
= sizeof (md_longopts
);
461 /* We have no target specific options yet, so these next
462 two functions are empty. */
464 md_parse_option (int c ATTRIBUTE_UNUSED
, const char *arg ATTRIBUTE_UNUSED
)
470 md_show_usage (FILE *stream ATTRIBUTE_UNUSED
)
474 /* Convert from target byte order to host byte order. */
477 md_chars_to_number (char * buf
, int n
)
480 unsigned char * where
= (unsigned char *) buf
;
485 result
|= (where
[n
] & 255);
490 /* Apply a fixup to the object file. */
493 md_apply_fix (fixS
*fixP ATTRIBUTE_UNUSED
,
494 valueT
* valP ATTRIBUTE_UNUSED
, segT seg ATTRIBUTE_UNUSED
)
496 char *buf
= fixP
->fx_where
+ fixP
->fx_frag
->fr_literal
;
500 switch (fixP
->fx_r_type
)
518 case BFD_RELOC_FT32_10
:
521 newval
= md_chars_to_number (buf
, 2);
522 newval
|= (val
& ((1 << 10) - 1)) << FT32_FLD_RIMM_BIT
;
523 md_number_to_chars (buf
, newval
, 2);
526 case BFD_RELOC_FT32_20
:
529 newval
= md_chars_to_number (buf
, 3);
530 newval
|= val
& ((1 << 20) - 1);
531 md_number_to_chars (buf
, newval
, 3);
534 case BFD_RELOC_FT32_15
:
537 newval
= md_chars_to_number (buf
, 2);
538 newval
|= val
& ((1 << 15) - 1);
539 md_number_to_chars (buf
, newval
, 2);
542 case BFD_RELOC_FT32_17
:
545 newval
= md_chars_to_number (buf
, 3);
546 newval
|= val
& ((1 << 17) - 1);
547 md_number_to_chars (buf
, newval
, 3);
550 case BFD_RELOC_FT32_18
:
553 newval
= md_chars_to_number (buf
, 4);
554 newval
|= (val
>> 2) & ((1 << 18) - 1);
555 md_number_to_chars (buf
, newval
, 4);
562 if (fixP
->fx_addsy
== NULL
&& fixP
->fx_pcrel
== 0)
564 // printf("fx_addsy=%p fixP->fx_pcrel=%d fx_done=%d\n", fixP->fx_addsy, fixP->fx_pcrel, fixP->fx_done);
568 md_number_to_chars (char *ptr
, valueT use
, int nbytes
)
570 number_to_chars_littleendian (ptr
, use
, nbytes
);
573 /* Generate a machine-dependent relocation. */
575 tc_gen_reloc (asection
*section ATTRIBUTE_UNUSED
, fixS
*fixP
)
578 bfd_reloc_code_real_type code
;
580 switch (fixP
->fx_r_type
)
585 case BFD_RELOC_FT32_10
:
586 case BFD_RELOC_FT32_20
:
587 case BFD_RELOC_FT32_15
:
588 case BFD_RELOC_FT32_17
:
589 case BFD_RELOC_FT32_18
:
590 code
= fixP
->fx_r_type
;
593 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
594 _("Semantics error. This type of operand can not be relocated, it must be an assembly-time constant"));
598 relP
= XNEW (arelent
);
599 gas_assert (relP
!= 0);
600 relP
->sym_ptr_ptr
= XNEW (asymbol
*);
601 *relP
->sym_ptr_ptr
= symbol_get_bfdsym (fixP
->fx_addsy
);
602 relP
->address
= fixP
->fx_frag
->fr_address
+ fixP
->fx_where
;
604 relP
->addend
= fixP
->fx_offset
;
606 relP
->howto
= bfd_reloc_type_lookup (stdoutput
, code
);
611 name
= S_GET_NAME (fixP
->fx_addsy
);
613 name
= _("<unknown>");
614 as_fatal (_("Cannot generate relocation type for symbol %s, code %s"),
615 name
, bfd_get_reloc_code_name (code
));