1 /* tc-xgate.c -- Assembler code for Freescale XGATE
2 Copyright 2010, 2011, 2012
3 Free Software Foundation, Inc.
4 Contributed by Sean Keys <skeys@ipdatasys.com>
6 This file is part of GAS, the GNU Assembler.
8 GAS is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3, or (at your option)
13 GAS is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with GAS; see the file COPYING. If not, write to
20 the Free Software Foundation, 51 Franklin Street - Fifth Floor,
21 Boston, MA 02110-1301, USA. */
24 #include "safe-ctype.h"
26 #include "opcode/xgate.h"
27 #include "dwarf2dbg.h"
28 #include "elf/xgate.h"
30 const char comment_chars
[] = ";!";
31 const char line_comment_chars
[] = "#*";
32 const char line_separator_chars
[] = "";
33 const char EXP_CHARS
[] = "eE";
34 const char FLT_CHARS
[] = "dD";
36 #define SIXTEENTH_BIT 0x8000
37 #define N_BITS_IN_WORD 16
39 /* #define STATE_CONDITIONAL_BRANCH (1) */
40 #define STATE_PC_RELATIVE (2)
41 #define REGISTER_P(ptr) (ptr == 'r')
44 #define MAXREGISTER 07
45 #define MINREGISTER 00
47 #define OPTION_MMCU 'm'
49 /* This macro has no side-effects. */
50 #define ENCODE_RELAX(what,length) (((what) << 2) + (length))
53 struct xgate_opcode_handle
57 struct xgate_opcode
*opc0
[MAX_OPCODES
];
62 xgate_parse_exp (char *, expressionS
*);
64 skip_whitespace (char *);
66 get_default_target (void);
68 extract_word (char *, char *, int);
70 xgate_new_instruction (int size
);
72 xgate_apply_operand (unsigned short, unsigned short *, unsigned short,
75 xgate_operands (struct xgate_opcode
*, char **);
77 xgate_operand (struct xgate_opcode
*, int *, int where
, char **, char **);
78 static struct xgate_opcode
*
79 xgate_find_match (struct xgate_opcode_handle
*, int, unsigned int);
81 cmp_opcode (struct xgate_opcode
*, struct xgate_opcode
*);
83 xgate_detect_format (char *);
85 xgate_print_syntax (char *);
87 xgate_print_table (void);
90 static struct hash_control
*xgate_hash
;
92 /* Previous opcode. */
93 static unsigned int prev
= 0;
95 static unsigned char fixup_required
= 0;
97 /* Used to enable clipping of 16 bit operands into 8 bit constraints. */
98 static unsigned char macroClipping
= 0;
100 static char oper_check
;
101 static char flag_print_insn_syntax
= 0;
102 static char flag_print_opcodes
= 0;
104 static int current_architecture
;
105 static const char *default_cpu
;
107 /* ELF flags to set in the output file header. */
108 static int elf_flags
= E_XGATE_F64
;
110 /* This table describes how you change sizes for the various types of variable
111 size expressions. This version only supports two kinds. */
114 How far Forward this mode will reach.
115 How far Backward this mode will reach.
116 How many bytes this mode will add to the size of the frag.
117 Which mode to go to if the offset won't fit in this one. */
119 relax_typeS md_relax_table
[] =
121 {1, 1, 0, 0}, /* First entries aren't used. */
122 {1, 1, 0, 0}, /* For no good reason except. */
123 {1, 1, 0, 0}, /* that the VAX doesn't either. */
125 /* XGATE 9 and 10 bit pc rel todo complete and test */
126 /*{(511), (-512), 0, ENCODE_RELAX (STATE_PC_RELATIVE, STATE_WORD)},
127 {(1023), (-1024), 0, ENCODE_RELAX (STATE_PC_RELATIVE, STATE_WORD)}, */
131 /* XGATE's registers all are 16-bit general purpose. They are numbered according to the specifications. */
132 typedef enum register_id
147 /* This table describes all the machine specific pseudo-ops the assembler
148 has to support. The fields are: pseudo-op name without dot function to
149 call to execute this pseudo-op Integer arg to pass to the function. */
150 const pseudo_typeS md_pseudo_table
[] =
152 /* The following pseudo-ops are supported for MRI compatibility. */
156 const char *md_shortopts
= "m:";
158 struct option md_longopts
[] =
160 #define OPTION_PRINT_INSN_SYNTAX (OPTION_MD_BASE + 0)
161 { "print-insn-syntax", no_argument
, NULL
, OPTION_PRINT_INSN_SYNTAX
},
163 #define OPTION_PRINT_OPCODES (OPTION_MD_BASE + 1)
164 { "print-opcodes", no_argument
, NULL
, OPTION_PRINT_OPCODES
},
166 #define OPTION_GENERATE_EXAMPLE (OPTION_MD_BASE + 2)
167 { "generate-example", no_argument
, NULL
, OPTION_GENERATE_EXAMPLE
},
169 #define OPTION_MSHORT (OPTION_MD_BASE + 3)
170 { "mshort", no_argument
, NULL
, OPTION_MSHORT
},
172 #define OPTION_MLONG (OPTION_MD_BASE + 4)
173 { "mlong", no_argument
, NULL
, OPTION_MLONG
},
175 #define OPTION_MSHORT_DOUBLE (OPTION_MD_BASE + 5)
176 { "mshort-double", no_argument
, NULL
, OPTION_MSHORT_DOUBLE
},
178 #define OPTION_MLONG_DOUBLE (OPTION_MD_BASE + 6)
179 { "mlong-double", no_argument
, NULL
, OPTION_MLONG_DOUBLE
},
181 { NULL
, no_argument
, NULL
, 0 }
184 size_t md_longopts_size
= sizeof(md_longopts
);
187 md_atof (int type
, char *litP
, int *sizeP
)
189 return ieee_md_atof (type
, litP
, sizeP
, TRUE
);
193 md_parse_option (int c
, char *arg
)
198 if (strcasecmp (arg
, "v1") == 0)
199 current_architecture
= XGATE_V1
;
200 else if (strcasecmp (arg
, "v2") == 0)
201 current_architecture
= XGATE_V2
;
202 else if (strcasecmp (arg
, "v3") == 0)
203 current_architecture
= XGATE_V3
;
205 as_bad (_(" architecture variant invalid"));
208 case OPTION_PRINT_INSN_SYNTAX
:
209 flag_print_insn_syntax
= 1;
212 case OPTION_PRINT_OPCODES
:
213 flag_print_opcodes
= 1;
216 case OPTION_GENERATE_EXAMPLE
:
217 flag_print_opcodes
= 2;
221 elf_flags
&= ~E_XGATE_I32
;
225 elf_flags
|= E_XGATE_I32
;
228 case OPTION_MSHORT_DOUBLE
:
229 elf_flags
&= ~E_XGATE_F64
;
232 case OPTION_MLONG_DOUBLE
:
233 elf_flags
|= E_XGATE_F64
;
243 xgate_arch_format (void)
245 get_default_target ();
247 if (current_architecture
& cpuxgate
)
248 return "elf32-xgate";
254 get_default_target (void)
256 const bfd_target
*target
;
259 if (current_architecture
!= 0)
262 default_cpu
= "unknown";
263 target
= bfd_find_target (0, &abfd
);
265 if (target
&& target
->name
)
267 if (strcmp (target
->name
, "elf32-xgate") == 0)
269 current_architecture
= cpuxgate
;
270 default_cpu
= "XGATE V1";
274 as_bad (_("Default target `%s' is not supported."), target
->name
);
281 struct xgate_opcode
*xgate_opcode_ptr
= NULL
;
282 struct xgate_opcode
*xgate_op_table
= NULL
;
283 struct xgate_opcode_handle
*op_handles
= 0;
284 char *prev_op_name
= 0;
286 unsigned int number_of_handle_rows
= 0;
289 /* Create a local copy of our opcode table
290 including an extra line for NULL termination. */
291 xgate_op_table
= (struct xgate_opcode
*)
292 xmalloc ((xgate_num_opcodes
+ 1) * sizeof (struct xgate_opcode
));
294 memset (xgate_op_table
, 0,
295 sizeof(struct xgate_opcode
) * (xgate_num_opcodes
+ 1));
297 for (xgate_opcode_ptr
= (struct xgate_opcode
*) xgate_opcodes
, i
= 0;
298 i
< xgate_num_opcodes
; i
++)
299 xgate_op_table
[i
] = xgate_opcode_ptr
[i
];
301 qsort (xgate_op_table
, xgate_num_opcodes
, sizeof(struct xgate_opcode
),
302 (int (*)(const void *, const void *)) cmp_opcode
);
304 /* Calculate number of handles since this will be
305 smaller than the raw number of opcodes in the table. */
306 for (xgate_opcode_ptr
= xgate_op_table
; xgate_opcode_ptr
->name
;
309 if (prev_op_name
!= 0)
311 if (strcmp (prev_op_name
, xgate_opcode_ptr
->name
))
312 number_of_handle_rows
++;
314 prev_op_name
= xgate_opcode_ptr
->name
;
317 op_handles
= (struct xgate_opcode_handle
*)
318 xmalloc (sizeof(struct xgate_opcode_handle
) * (number_of_handle_rows
+ 1));
320 /* Insert opcode names into hash table, aliasing duplicates. */
321 xgate_hash
= hash_new ();
323 for (xgate_opcode_ptr
= xgate_op_table
, i
= 0, j
= 0; i
< xgate_num_opcodes
;
324 i
++, xgate_opcode_ptr
++)
326 if (strcmp (prev_op_name
, xgate_opcode_ptr
->name
) || i
== 0)
332 op_handles
[j
].name
= xgate_opcode_ptr
->name
;
333 op_handles
[j
].opc0
[0] = xgate_opcode_ptr
;
338 op_handles
[j
].opc0
[handle_enum
] = xgate_opcode_ptr
;
340 op_handles
[j
].number_of_modes
= handle_enum
;
341 prev_op_name
= op_handles
[j
].name
;
344 while (op_handles
->name
)
346 hash_insert (xgate_hash
, op_handles
->name
, (char *) op_handles
);
350 if (flag_print_opcodes
== 1)
351 xgate_print_table ();
355 xgate_init_after_args (void)
360 md_show_usage (FILE * stream
)
362 get_default_target ();
367 Freescale XGATE co-processor options:\n \
368 -mshort use 16-bit int ABI (default)\n \
369 -mlong use 32-bit int ABI\n \
370 -mshort-double use 32-bit double ABI\n \
371 -mlong-double use 64-bit double ABI (default)\n\
372 --mxgate specify the processor variant[default %s]\n\
373 --print-insn-syntax print the syntax of instruction in case of error\n\
374 --print-opcodes print the list of instructions with syntax\n\
375 --generate-example generate an example of each instruction"),
379 enum bfd_architecture
382 get_default_target ();
383 return bfd_arch_xgate
;
393 xgate_print_syntax (char *name
)
397 for (i
= 0; i
< xgate_num_opcodes
; i
++)
399 if (!strcmp (xgate_opcodes
[i
].name
, name
))
401 if (!strcmp (xgate_opcodes
[i
].constraints
, XGATE_OP_IDR
))
402 printf ("\tFormat is %s\tRx, Rx, Rx+|-Rx|Rx\n",
403 xgate_opcodes
[i
].name
);
404 if (!strcmp (xgate_opcodes
[i
].constraints
, XGATE_OP_INH
))
405 printf ("\tFormat is %s\n", xgate_opcodes
[i
].name
);
406 if (!strcmp (xgate_opcodes
[i
].constraints
, XGATE_OP_TRI
))
407 printf ("\tFormat is %s\tRx, Rx, Rx\n", xgate_opcodes
[i
].name
);
408 if (!strcmp (xgate_opcodes
[i
].constraints
, XGATE_OP_DYA
))
409 printf ("\tFormat is %s\tRx, Rx\n", xgate_opcodes
[i
].name
);
410 if (!strcmp (xgate_opcodes
[i
].constraints
, XGATE_OP_DYA_MON
)
411 || !strcmp (xgate_opcodes
[i
].constraints
, XGATE_OP_MON
))
412 printf ("\tFormat is %s\tRx\n", xgate_opcodes
[i
].name
);
413 if (!strcmp (xgate_opcodes
[i
].constraints
, XGATE_OP_IMM3
))
414 printf ("\tFormat is %s\t<3-bit value>\n", xgate_opcodes
[i
].name
);
415 if (!strcmp (xgate_opcodes
[i
].constraints
, XGATE_OP_IMM4
))
416 printf ("\tFormat is %s\t<4 -bit value>\n", xgate_opcodes
[i
].name
);
417 if (!strcmp (xgate_opcodes
[i
].constraints
, XGATE_OP_IMM8
))
418 printf ("\tFormat is %s\tRx, <8-bit value>\n",
419 xgate_opcodes
[i
].name
);
420 if (!strcmp (xgate_opcodes
[i
].constraints
, XGATE_OP_IMM16
))
421 printf ("\tFormat is %s\tRx, <16-bit value>\n",
422 xgate_opcodes
[i
].name
);
423 if (!strcmp (xgate_opcodes
[i
].constraints
, XGATE_OP_MON_R_C
))
424 printf ("\tFormat is %s\tRx, CCR\n", xgate_opcodes
[i
].name
);
425 if (!strcmp (xgate_opcodes
[i
].constraints
, XGATE_OP_MON_C_R
))
426 printf ("\tFormat is %s\tCCR, Rx\n", xgate_opcodes
[i
].name
);
427 if (!strcmp (xgate_opcodes
[i
].constraints
, XGATE_OP_MON_R_P
))
428 printf ("\tFormat is %s\tRx, PC\n", xgate_opcodes
[i
].name
);
429 if (!strcmp (xgate_opcodes
[i
].constraints
, XGATE_OP_IMM16mLDW
))
430 printf ("\tFormat is %s\tRx, <16-bit value>\n",
431 xgate_opcodes
[i
].name
);
437 xgate_print_table (void)
441 for (i
= 0; i
< xgate_num_opcodes
; i
++)
442 xgate_print_syntax (xgate_opcodes
[i
].name
);
448 xgate_listing_header (void)
450 if (current_architecture
& cpuxgate
)
453 return "ERROR MC9S12X GAS ";
457 md_undefined_symbol (char *name ATTRIBUTE_UNUSED
)
462 /* GAS will call this function for each section at the end of the assembly,
463 to permit the CPU backend to adjust the alignment of a section. */
466 md_section_align (asection
* seg
, valueT addr
)
468 int align
= bfd_get_section_alignment (stdoutput
, seg
);
469 return ((addr
+ (1 << align
) - 1) & (-1 << align
));
473 md_assemble (char *input_line
)
475 struct xgate_opcode
*opcode
= 0;
476 struct xgate_opcode
*macro_opcode
= 0;
477 struct xgate_opcode_handle
*opcode_handle
= 0;
478 /* Caller expects it to be returned as it was passed. */
479 char *saved_input_line
= input_line
;
480 char op_name
[9] = { 0 };
481 unsigned int sh_format
= 0;
485 oper_check
= 0; /* set error flags */
486 input_line
= extract_word (input_line
, op_name
, sizeof(op_name
));
488 /* Check to make sure we are not reading a bogus line. */
490 as_bad (_("opcode missing or not found on input line"));
492 if (!(opcode_handle
= (struct xgate_opcode_handle
*) hash_find (xgate_hash
,
495 as_bad (_("opcode %s not found in opcode hash table"), op_name
);
499 /* Detect operand format so we can pull the proper opcode bin. */
500 sh_format
= xgate_detect_format (input_line
);
502 opcode
= xgate_find_match (opcode_handle
, opcode_handle
->number_of_modes
,
507 as_bad (_("matching operands to opcode "));
508 xgate_print_syntax (opcode_handle
->opc0
[0]->name
);
510 else if (opcode
->size
== 2)
512 /* Size is one word - assemble that native insn. */
513 xgate_operands (opcode
, &input_line
);
517 /* Insn is a simplified instruction - expand it out. */
521 /* skip past our ';' separator. */
522 for (i
= strlen (opcode
->constraints
), p
= opcode
->constraints
; i
> 0;
531 input_line
= skip_whitespace (input_line
);
532 char *macro_inline
= input_line
;
534 /* Loop though the macro's opcode list and apply operands to each real opcode. */
535 for (i
= 0; *p
&& i
< (opcode
->size
/ 2); i
++)
537 /* Loop though macro operand list. */
538 input_line
= macro_inline
; /* Rewind. */
539 p
= extract_word (p
, op_name
, 10);
541 if (!(opcode_handle
= (struct xgate_opcode_handle
*)
542 hash_find (xgate_hash
, op_name
)))
545 _(": processing macro, real opcode handle not found in hash"));
550 sh_format
= xgate_detect_format (input_line
);
551 macro_opcode
= xgate_find_match (opcode_handle
,
552 opcode_handle
->number_of_modes
, sh_format
);
553 xgate_operands (macro_opcode
, &input_line
);
559 input_line
= saved_input_line
;
562 /* Force truly undefined symbols to their maximum size, and generally set up
563 the frag list to be relaxed. */
566 md_estimate_size_before_relax (fragS
*fragp
, asection
*seg
)
568 /* If symbol is undefined or located in a different section,
569 select the largest supported relocation. */
570 relax_substateT subtype
;
571 relax_substateT rlx_state
[] =
574 for (subtype
= 0; subtype
< ARRAY_SIZE (rlx_state
); subtype
+= 2)
576 if (fragp
->fr_subtype
== rlx_state
[subtype
]
577 && (!S_IS_DEFINED (fragp
->fr_symbol
)
578 || seg
!= S_GET_SEGMENT (fragp
->fr_symbol
)))
580 fragp
->fr_subtype
= rlx_state
[subtype
+ 1];
585 if (fragp
->fr_subtype
>= ARRAY_SIZE (md_relax_table
))
588 return md_relax_table
[fragp
->fr_subtype
].rlx_length
;
592 /* Relocation, relaxation and frag conversions. */
594 /* PC-relative offsets are relative to the start of the
595 next instruction. That is, the address of the offset, plus its
596 size, since the offset is always the last part of the insn. */
599 md_pcrel_from (fixS
* fixP
)
601 return fixP
->fx_size
+ fixP
->fx_where
+ fixP
->fx_frag
->fr_address
;
604 /* If while processing a fixup, a reloc really needs to be created
605 then it is done here. */
608 tc_gen_reloc (asection
* section ATTRIBUTE_UNUSED
, fixS
* fixp
)
612 reloc
= (arelent
*) xmalloc (sizeof(arelent
));
613 reloc
->sym_ptr_ptr
= (asymbol
**) xmalloc (sizeof(asymbol
*));
614 *reloc
->sym_ptr_ptr
= symbol_get_bfdsym (fixp
->fx_addsy
);
615 reloc
->address
= fixp
->fx_frag
->fr_address
+ fixp
->fx_where
;
617 if (fixp
->fx_r_type
== 0)
619 reloc
->howto
= bfd_reloc_type_lookup (stdoutput
, BFD_RELOC_16
);
623 reloc
->howto
= bfd_reloc_type_lookup (stdoutput
, fixp
->fx_r_type
);
626 if (reloc
->howto
== (reloc_howto_type
*) NULL
)
628 as_bad_where (fixp
->fx_file
, fixp
->fx_line
, _
629 ("Relocation %d is not supported by object file format."),
630 (int) fixp
->fx_r_type
);
634 /* Since we use Rel instead of Rela, encode the vtable entry to be
635 used in the relocation's section offset. */
636 if (fixp
->fx_r_type
== BFD_RELOC_VTABLE_ENTRY
)
637 reloc
->address
= fixp
->fx_offset
;
642 /* Patch the instruction with the resolved operand. Elf relocation
643 info will also be generated to take care of linker/loader fixups.
644 The XGATE addresses only 16-bit addresses.The BFD_RELOC_32 is necessary
645 for the support of --gstabs. */
648 md_apply_fix (fixS
* fixP
, valueT
* valP
, segT seg ATTRIBUTE_UNUSED
)
655 /* If the fixup is done mark it done so no further symbol resolution will take place. */
656 if (fixP
->fx_addsy
== (symbolS
*) NULL
)
661 /* We don't actually support subtracting a symbol. */
662 if (fixP
->fx_subsy
!= (symbolS
*) NULL
)
663 as_bad_where (fixP
->fx_file
, fixP
->fx_line
, _("Expression too complex."));
665 where
= fixP
->fx_frag
->fr_literal
+ fixP
->fx_where
;
666 opcode
= bfd_getl16 (where
);
669 switch (fixP
->fx_r_type
)
671 case R_XGATE_PCREL_9
:
672 if (value
< -512 || value
> 511)
673 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
674 _("Value %ld too large for 9-bit PC-relative branch."), value
);
675 result
= ldiv (value
, 2); /* from bytes to words */
678 as_bad_where (fixP
->fx_file
, fixP
->fx_line
, _
679 ("Value %ld not aligned by 2 for 9-bit PC-relative branch."), value
);
680 mask
= 0x1FF; /* Clip into 8-bit field FIXME I'm sure there is a more proper place for this */
682 number_to_chars_bigendian (where
, (opcode
| value
), 2);
684 case R_XGATE_PCREL_10
:
685 if (value
< -1024 || value
> 1023)
686 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
687 _("Value %ld too large for 10-bit PC-relative branch."), value
);
688 result
= ldiv (value
, 2); /* from bytes to words */
691 as_bad_where (fixP
->fx_file
, fixP
->fx_line
, _
692 ("Value %ld not aligned by 2 for 10-bit PC-relative branch."), value
);
693 mask
= 0x3FF; /* Clip into 9-bit field FIXME I'm sure there is a more proper place for this */
695 number_to_chars_bigendian (where
, (opcode
| value
), 2);
697 case BFD_RELOC_XGATE_IMM8_HI
:
698 if (value
< -65537 || value
> 65535)
699 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
700 _("Value out of 16-bit range."));
703 bfd_putb16 ((bfd_vma
) value
| opcode
, (void *) where
);
705 case BFD_RELOC_XGATE_24
:
706 case BFD_RELOC_XGATE_IMM8_LO
:
707 if (value
< -65537 || value
> 65535)
708 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
709 _("Value out of 16-bit range."));
711 bfd_putb16 ((bfd_vma
) value
| opcode
, (void *) where
);
713 case BFD_RELOC_XGATE_IMM3
:
714 if (value
< 0 || value
> 7)
715 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
716 _("Value out of 3-bit range."));
717 value
<<= 8; /* make big endian */
718 number_to_chars_bigendian (where
, (opcode
| value
), 2);
720 case BFD_RELOC_XGATE_IMM4
:
721 if (value
< 0 || value
> 15)
722 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
723 _("Value out of 4-bit range."));
724 value
<<= 4; /* align the operand bits */
725 number_to_chars_bigendian (where
, (opcode
| value
), 2);
727 case BFD_RELOC_XGATE_IMM5
:
728 if (value
< 0 || value
> 31)
729 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
730 _("Value out of 5-bit range."));
731 value
<<= 5; /* align the operand bits */
732 number_to_chars_bigendian (where
, (opcode
| value
), 2);
735 ((bfd_byte
*) where
)[0] = (bfd_byte
) value
;
738 bfd_putb32 ((bfd_vma
) value
, (unsigned char *) where
);
739 /* todo figure out how to make BFD_RELOC_16 the default */
742 bfd_putb16 ((bfd_vma
) value
, (unsigned char *) where
);
745 as_fatal (_("Line %d: unknown relocation type: 0x%x."), fixP
->fx_line
,
751 /* See whether we need to force a relocation into the output file. */
754 tc_xgate_force_relocation (fixS
* fixP
)
756 if (fixP
->fx_r_type
== BFD_RELOC_XGATE_RL_GROUP
)
758 return generic_force_reloc (fixP
);
761 /* Here we decide which fixups can be adjusted to make them relative
762 to the beginning of the section instead of the symbol. Basically
763 we need to make sure that the linker relaxation is done
764 correctly, so in some cases we force the original symbol to be
768 tc_xgate_fix_adjustable (fixS
* fixP
)
770 switch (fixP
->fx_r_type
)
772 /* For the linker relaxation to work correctly, these relocs
773 need to be on the symbol itself. */
775 case BFD_RELOC_XGATE_RL_JUMP
:
776 case BFD_RELOC_XGATE_RL_GROUP
:
777 case BFD_RELOC_VTABLE_INHERIT
:
778 case BFD_RELOC_VTABLE_ENTRY
:
787 md_convert_frag (bfd
* abfd ATTRIBUTE_UNUSED
,
788 asection
* sec ATTRIBUTE_UNUSED
,
789 fragS
* fragP ATTRIBUTE_UNUSED
)
791 as_bad (("md_convert_frag not implemented yet"));
795 /* Set the ELF specific flags. */
798 xgate_elf_final_processing (void)
800 elf_flags
|= EF_XGATE_MACH
;
801 elf_elfheader (stdoutput
)->e_flags
&= ~EF_XGATE_ABI
;
802 elf_elfheader (stdoutput
)->e_flags
|= elf_flags
;
806 skip_whitespace (char *s
)
808 while (*s
== ' ' || *s
== '\t' || *s
== '(' || *s
== ')')
814 /* Extract a word (continuous alpha-numeric chars) from the input line. */
817 extract_word (char *from
, char *to
, int limit
)
822 /* Drop leading whitespace. */
823 from
= skip_whitespace (from
);
825 /* Find the op code end. */
826 for (op_end
= from
; *op_end
!= 0 && is_part_of_name (*op_end
);)
828 to
[size
++] = *op_end
++;
829 if (size
+ 1 >= limit
)
837 xgate_new_instruction (int size
)
839 char *f
= frag_more (size
);
840 dwarf2_emit_insn (size
);
845 xgate_apply_operand (unsigned short new_mask
,
846 unsigned short *availiable_mask_bits
,
848 unsigned char n_bits
)
850 unsigned short n_shifts
;
851 unsigned int n_drop_bits
;
853 /* Shift until you find an available operand bit "1" and record the number of shifts. */
855 !(*availiable_mask_bits
& SIXTEENTH_BIT
) && n_shifts
< 16;
857 *availiable_mask_bits
<<= 1;
859 /* Shift for the number of bits your operand requires while bits are available. */
860 for (n_drop_bits
= n_bits
;
861 n_drop_bits
&& (*availiable_mask_bits
& SIXTEENTH_BIT
);
863 *availiable_mask_bits
<<= 1;
866 as_bad (_(":operand has too many bits"));
867 *availiable_mask_bits
>>= n_shifts
+ n_bits
;
868 if ((n_drop_bits
== 0) && (*availiable_mask_bits
== 0))
870 oper_check
= 1; /* flag operand check as good */
872 new_mask
<<= N_BITS_IN_WORD
- (n_shifts
+ n_bits
);
877 /* Parse ordinary expression. */
880 xgate_parse_exp (char *s
, expressionS
* op
)
882 input_line_pointer
= s
;
884 if (op
->X_op
== O_absent
)
885 as_bad (_("missing operand"));
886 return input_line_pointer
;
889 /* For testing. Comment out to prevent defined but not used warning
892 xgate_get_constant(char *str, int max)
896 str = skip_whitespace(str);
897 input_line_pointer = str;
900 if (ex.X_op != O_constant)
901 as_bad(_("constant value required"));
903 if (ex.X_add_number > max || ex.X_add_number < 0)
904 as_bad(_("number must be positive and less than %d"), max + 1);
906 return ex.X_add_number;
911 cmp_opcode (struct xgate_opcode
*op1
, struct xgate_opcode
*op2
)
913 return strcmp (op1
->name
, op2
->name
);
916 /* Parse instruction operands. */
919 xgate_operands (struct xgate_opcode
*opcode
, char **line
)
921 char *frag
= xgate_new_instruction (opcode
->size
);
922 int where
= frag
- frag_now
->fr_literal
;
923 char *op
= opcode
->constraints
;
924 unsigned int bin
= (int) opcode
->bin_opcode
;
926 unsigned short oper_mask
= 0;
927 int operand_bit_length
= 0;
928 unsigned int operand
= 0;
929 char n_operand_bits
= 0;
930 char first_operand_equals_second
= 0;
934 /* Generate available operand bits mask. */
935 for (i
= 0; (c
= opcode
->format
[i
]); i
++)
937 if (ISDIGIT (c
) || (c
== 's'))
949 /* Opcode has operands. */
950 /* Parse first operand. */
955 first_operand_equals_second
= 1;
958 operand
= xgate_operand (opcode
, &operand_bit_length
, where
, &op
, &str
);
960 bin
= xgate_apply_operand (operand
, &oper_mask
, bin
, operand_bit_length
);
961 /* Parse second operand. */
966 str
= skip_whitespace (str
);
969 if (first_operand_equals_second
)
971 bin
= xgate_apply_operand (operand
, &oper_mask
, bin
,
977 as_bad (_("`,' required before second operand"));
982 str
= skip_whitespace (str
);
983 operand
= xgate_operand (opcode
, &operand_bit_length
, where
, &op
,
985 bin
= xgate_apply_operand (operand
, &oper_mask
, bin
,
991 /* Parse the third register. */
996 str
= skip_whitespace (str
);
998 as_bad (_("`,' required before third operand"));
999 str
= skip_whitespace (str
);
1000 operand
= xgate_operand (opcode
, &operand_bit_length
, where
, &op
,
1002 bin
= xgate_apply_operand (operand
, &oper_mask
, bin
,
1003 operand_bit_length
);
1006 if (opcode
->size
== 2 && fixup_required
)
1008 bfd_putl16 (bin
, frag
);
1010 else if ((opcode
->sh_format
& XG_PCREL
))
1012 /* Write our data to a frag for further processing. */
1013 bfd_putl16 (opcode
->bin_opcode
, frag
);
1017 /* Apply operand mask(s)to bin opcode and write the output. */
1018 /* Since we are done write this frag in xgate BE format. */
1019 number_to_chars_bigendian (frag
, bin
, opcode
->size
);
1027 xgate_operand (struct xgate_opcode
*opcode
,
1033 expressionS op_expr
;
1035 char *op_constraint
= *op_con
;
1036 unsigned int op_mask
= 0;
1037 char *str
= skip_whitespace (*line
);
1040 unsigned int pp_fix
= 0;
1041 unsigned short max_size
= 0;
1047 switch (*op_constraint
)
1049 case '+': /* Indexed register operand +/- or plain r. */
1050 /* TODO should be able to combine with with case R. */
1052 /* Default to neither inc or dec. */
1055 str
= skip_whitespace (str
);
1056 while (*str
!= ' ' && *str
!= '\t')
1060 else if (*str
== '+')
1062 else if (*str
== 'r' || *str
== 'R')
1064 str
= extract_word (str
, r_name
, sizeof(r_name
));
1065 if (ISDIGIT (r_name
[1]))
1067 if (r_name
[2] == '\0' && (r_name
[1] - '0' < 8))
1068 op_mask
= r_name
[1] - '0';
1069 if (r_name
[2] != '\0' && (r_name
[1] - '0' > 7))
1070 as_bad (_(": expected register name r0-r7 read %s"), r_name
);
1080 case 'r': /* Register operand. */
1081 if (*str
== 'r' || *str
== 'R')
1084 str
= extract_word (str
, r_name
, sizeof(r_name
));
1086 if (ISDIGIT (r_name
[1]))
1088 if (r_name
[2] == '\0')
1089 op_mask
= r_name
[1] - '0';
1090 else if (r_name
[1] != '0' && ISDIGIT (r_name
[2])
1091 && r_name
[3] == '\0')
1092 op_mask
= (r_name
[1] - '0') * 10 + r_name
[2] - '0';
1093 if (op_mask
> MAXREGISTER
)
1094 as_bad (_(": expected register name r0-r7 read %s "), r_name
);
1099 as_bad (_(": expected register name r0-r7 read %s "), r_name
);
1103 case 'i': /* Immediate value or expression expected. */
1104 /* Advance the original format pointer. */
1107 if (ISDIGIT (*op_constraint
))
1109 *bit_width
= (int) *op_constraint
- '0';
1111 else if (*op_constraint
== 'a')
1115 else if (*op_constraint
== 'f')
1119 /* http://tigcc.ticalc.org/doc/gnuasm.html#SEC31 */
1122 str
= xgate_parse_exp (str
, &op_expr
);
1123 if (op_expr
.X_op
== O_constant
)
1125 if (!ISDIGIT (*op_constraint
))
1127 _(":expected bit length with constraint type i(# immediate) read %c"),
1129 op_mask
= op_expr
.X_add_number
;
1130 if ((opcode
->name
[strlen (opcode
->name
) - 1] == 'l') && macroClipping
)
1134 else if ((opcode
->name
[strlen (opcode
->name
) - 1]) == 'h'
1140 /* Make sure it fits. */
1141 for (i
= *bit_width
; i
; i
--)
1146 if (op_mask
> max_size
)
1147 as_bad (_(":operand value(%d) too big for constraint"), op_mask
);
1152 if (*op_constraint
== '8')
1154 if ((opcode
->name
[strlen (opcode
->name
) - 1] == 'l')
1157 fixp
= fix_new_exp (frag_now
, where
, 2, &op_expr
, FALSE
,
1158 BFD_RELOC_XGATE_24
);
1159 /* Should be BFD_RELOC_XGATE_IMM8_LO TODO fix. */
1160 fixp
->fx_pcrel_adjust
= 0;
1162 if ((opcode
->name
[strlen (opcode
->name
) - 1]) == 'h'
1165 fixp
= fix_new_exp (frag_now
, where
, 2, &op_expr
, FALSE
,
1166 BFD_RELOC_XGATE_IMM8_HI
);
1167 fixp
->fx_pcrel_adjust
= 0;
1170 as_bad (_(":unknown relocation"));
1172 else if (*op_constraint
== '5')
1174 fixp
= fix_new_exp (frag_now
, where
, 2, &op_expr
, FALSE
,
1175 BFD_RELOC_XGATE_IMM5
);
1176 fixp
->fx_pcrel_adjust
= 0;
1178 else if (*op_constraint
== '4')
1180 fixp
= fix_new_exp (frag_now
, where
, 2, &op_expr
, FALSE
,
1181 BFD_RELOC_XGATE_IMM4
);
1182 fixp
->fx_pcrel_adjust
= 0;
1184 else if (*op_constraint
== '3')
1186 fixp
= fix_new_exp (frag_now
, where
, 2, &op_expr
, FALSE
,
1187 BFD_RELOC_XGATE_IMM3
);
1188 fixp
->fx_pcrel_adjust
= 0;
1192 as_bad (_(":unknown relocation constraint size"));
1197 case 'c': /* CCR register expected. */
1198 if (*str
== 'c' || *str
== 'C')
1201 str
= extract_word (str
, r_name
, sizeof(r_name
));
1202 if (!(strcmp (r_name
, "ccr") || strcmp (r_name
, "CCR")))
1203 as_bad (_(": expected register name ccr read %s "), r_name
);
1207 as_bad (_(": expected character c or C read %c"), *str
);
1211 case 'p': /* PC register expected. */
1212 if (*str
== 'p' || *str
== 'P')
1215 str
= extract_word (str
, r_name
, sizeof(r_name
));
1216 if (!(strcmp (r_name
, "pc") || strcmp (r_name
, "PC")))
1217 as_bad (_(": expected register name pc read %s "), r_name
);
1221 as_bad (_(": expected character p or P read %c "), *str
);
1225 case 'b': /* Branch expected. */
1226 str
= xgate_parse_exp (str
, &op_expr
);
1229 if (op_expr
.X_op
!= O_register
)
1231 if (*op_constraint
== '9')
1233 /* mode == M68XG_OP_REL9 */
1234 fixp
= fix_new_exp (frag_now
, where
, 2, &op_expr
, TRUE
,
1236 fixp
->fx_pcrel_adjust
= 1;
1238 else if (*op_constraint
== 'a')
1239 { /* mode == M68XG_OP_REL10 */
1240 fixp
= fix_new_exp (frag_now
, where
, 2, &op_expr
, TRUE
,
1242 fixp
->fx_pcrel_adjust
= 1;
1247 as_fatal (_("Operand `%x' not recognized in fixup8."), op_expr
.X_op
);
1255 as_bad (_("unknown constraint `%c'"), *op_constraint
);
1263 xgate_detect_format (char *line_in
)
1265 char num_operands
= 0;
1266 char *str
= skip_whitespace (line_in
);
1270 unsigned int stripped_length
= 0;
1271 char sh_format
[10] =
1272 { 0 }; /* Shorthand format. */
1273 char operands_stripped
[3][20] =
1277 /* Strings. TODO maybe structure this. */
1284 char *r_r_r_string
=
1294 char *r_r_i_string
=
1297 /* If the length is zero this is an inherent instruction. */
1298 if (strlen (str
) == 0)
1301 for (i
= 0, j
= 0, num_operands
= 1; (c
= TOLOWER (*str
)) != 0; str
++)
1303 if (c
== ' ' || c
== '\t' || c
== '(' || c
== ')' || c
== '-' || c
== '+')
1314 if (i
> MAX_DETECT_CHARS
)
1317 operands_stripped
[j
][i
++] = c
;
1320 /* Process our substrings to see what we have. */
1321 for (i
= 0, j
= 0; num_operands
> i
; i
++)
1323 stripped_length
= strlen (&operands_stripped
[i
][0]);
1325 /* Add separator if we have more than one operand. */
1327 sh_format
[j
++] = ',';
1329 /* Try to process by length first. */
1330 if (stripped_length
> 3)
1332 sh_format
[j
++] = 'i';
1334 else if (stripped_length
== 1)
1336 sh_format
[j
++] = 'i';
1338 else if (stripped_length
== 2)
1340 if (operands_stripped
[i
][0]
1341 == 'r' && ISDIGIT (operands_stripped
[i
][1]))
1343 sh_format
[j
++] = 'r';
1345 else if (operands_stripped
[i
][0] == 'p'
1346 && operands_stripped
[i
][1] == 'c')
1348 sh_format
[j
++] = 'p';
1352 sh_format
[j
++] = 'i';
1355 else if (stripped_length
== 3)
1357 if (operands_stripped
[i
][0] == 'c'
1358 && (operands_stripped
[i
][1] == 'c'
1359 && operands_stripped
[i
][2] == 'r'))
1361 sh_format
[j
++] = 'c';
1363 else if (operands_stripped
[i
][0] == '#')
1365 sh_format
[j
++] = 'i';
1369 sh_format
[j
++] = 'i';
1372 else /* default to immediate */
1374 sh_format
[j
++] = 'i';
1378 /* See if we have a match. */
1379 if (!strcmp (i_string
, sh_format
) && num_operands
== 1)
1381 if (!strcmp (r_i_string
, sh_format
) && num_operands
== 2)
1383 if (!strcmp (r_r_r_string
, sh_format
) && num_operands
== 3)
1385 if (!strcmp (r_r_string
, sh_format
) && num_operands
== 2)
1387 if (!strcmp (r_string
, sh_format
) && num_operands
== 1)
1389 if (!strcmp (r_c_string
, sh_format
) && num_operands
== 2)
1391 if (!strcmp (c_r_string
, sh_format
) && num_operands
== 2)
1393 if (!strcmp (r_p_string
, sh_format
) && num_operands
== 2)
1395 if (!strcmp (r_r_i_string
, sh_format
) && num_operands
== 3)
1401 static struct xgate_opcode
*
1402 xgate_find_match (struct xgate_opcode_handle
*opcode_handle
,
1404 unsigned int sh_format
)
1408 if (numberOfModes
== 0)
1409 return opcode_handle
->opc0
[0];
1411 for (i
= 0; i
<= numberOfModes
; i
++)
1412 if (opcode_handle
->opc0
[i
]->sh_format
& sh_format
)
1413 return opcode_handle
->opc0
[i
];