Add support for Motorola XGATE embedded CPU
[deliverable/binutils-gdb.git] / gas / config / tc-xgate.c
CommitLineData
f6c1a2d5
NC
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>
5
6 This file is part of GAS, the GNU Assembler.
7
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)
11 any later version.
12
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.
17
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. */
22
23#include "as.h"
24#include "safe-ctype.h"
25#include "subsegs.h"
26#include "opcode/xgate.h"
27#include "dwarf2dbg.h"
28#include "elf/xgate.h"
29
30const char comment_chars[] = ";!";
31const char line_comment_chars[] = "#*";
32const char line_separator_chars[] = "";
33const char EXP_CHARS[] = "eE";
34const char FLT_CHARS[] = "dD";
35
36#define SIXTEENTH_BIT 0x8000
37#define N_BITS_IN_WORD 16
38
39/* #define STATE_CONDITIONAL_BRANCH (1) */
40#define STATE_PC_RELATIVE (2)
41#define REGISTER_P(ptr) (ptr == 'r')
42#define INCREMENT 01
43#define DECREMENT 02
44#define MAXREGISTER 07
45#define MINREGISTER 00
46
47#define OPTION_MMCU 'm'
48
49/* This macro has no side-effects. */
50#define ENCODE_RELAX(what,length) (((what) << 2) + (length))
51
52/* what this is */
53struct xgate_opcode_handle
54{
55 int number_of_modes;
56 char *name;
57 struct xgate_opcode *opc0[MAX_OPCODES];
58};
59
60/* LOCAL FUNCTIONS */
61static char *
62xgate_parse_exp (char *, expressionS *);
63static inline char *
64skip_whitespace (char *);
65static void
66get_default_target (void);
67static char *
68extract_word (char *, char *, int);
69static char *
70xgate_new_instruction (int size);
71unsigned short
72xgate_apply_operand (unsigned short, unsigned short *, unsigned short,
73 unsigned char);
74void
75xgate_operands (struct xgate_opcode *, char **);
76static unsigned int
77xgate_operand (struct xgate_opcode *, int *, int where, char **, char **);
78static struct xgate_opcode *
79xgate_find_match (struct xgate_opcode_handle *, int, unsigned int);
80static int
81cmp_opcode (struct xgate_opcode *, struct xgate_opcode *);
82unsigned int
83xgate_detect_format (char *);
84void
85xgate_print_syntax (char *);
86void
87xgate_print_table (void);
88
89/* LOCAL DATA */
90static struct hash_control *xgate_hash;
91
92/* Previous opcode. */
93static unsigned int prev = 0;
94
95static unsigned char fixup_required = 0;
96
97/* Used to enable clipping of 16 bit operands into 8 bit constraints. */
98static unsigned char macroClipping = 0;
99
100static char oper_check;
101static char flag_print_insn_syntax = 0;
102static char flag_print_opcodes = 0;
103
104static int current_architecture;
105static const char *default_cpu;
106
107/* ELF flags to set in the output file header. */
108static int elf_flags = E_XGATE_F64;
109
110/* This table describes how you change sizes for the various types of variable
111 size expressions. This version only supports two kinds. */
112
113/* The fields are:
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. */
118
119relax_typeS md_relax_table[] =
120{
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. */
124 {1, 1, 0, 0},
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)}, */
128 {0, 0, 0, 0}
129};
130
131/* XGATE's registers all are 16-bit general purpose. They are numbered according to the specifications. */
132typedef enum register_id
133{
134 REG_NONE = -1,
135 REG_R0 = 0,
136 REG_R1 = 1,
137 REG_R2 = 2,
138 REG_R3 = 3,
139 REG_R4 = 4,
140 REG_R5 = 5,
141 REG_R6 = 6,
142 REG_R7 = 7,
143 REG_PC = 8,
144 REG_CCR = 9
145} register_id;
146
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. */
150const pseudo_typeS md_pseudo_table[] =
151{
152 /* The following pseudo-ops are supported for MRI compatibility. */
153 {0, 0, 0}
154};
155
156const char *md_shortopts = "m:";
157
158struct option md_longopts[] =
159{
160#define OPTION_PRINT_INSN_SYNTAX (OPTION_MD_BASE + 0)
161 { "print-insn-syntax", no_argument, NULL, OPTION_PRINT_INSN_SYNTAX },
162
163#define OPTION_PRINT_OPCODES (OPTION_MD_BASE + 1)
164 { "print-opcodes", no_argument, NULL, OPTION_PRINT_OPCODES },
165
166#define OPTION_GENERATE_EXAMPLE (OPTION_MD_BASE + 2)
167 { "generate-example", no_argument, NULL, OPTION_GENERATE_EXAMPLE },
168
169#define OPTION_MSHORT (OPTION_MD_BASE + 3)
170 { "mshort", no_argument, NULL, OPTION_MSHORT },
171
172#define OPTION_MLONG (OPTION_MD_BASE + 4)
173 { "mlong", no_argument, NULL, OPTION_MLONG },
174
175#define OPTION_MSHORT_DOUBLE (OPTION_MD_BASE + 5)
176 { "mshort-double", no_argument, NULL, OPTION_MSHORT_DOUBLE },
177
178#define OPTION_MLONG_DOUBLE (OPTION_MD_BASE + 6)
179 { "mlong-double", no_argument, NULL, OPTION_MLONG_DOUBLE },
180
181 { NULL, no_argument, NULL, 0 }
182};
183
184size_t md_longopts_size = sizeof(md_longopts);
185
186char *
187md_atof (int type, char *litP, int *sizeP)
188{
189 return ieee_md_atof (type, litP, sizeP, TRUE);
190}
191
192int
193md_parse_option (int c, char *arg)
194{
195 switch (c)
196 {
197 case OPTION_MMCU:
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;
204 else
205 as_bad (_(" architecture variant invalid"));
206 break;
207
208 case OPTION_PRINT_INSN_SYNTAX:
209 flag_print_insn_syntax = 1;
210 break;
211
212 case OPTION_PRINT_OPCODES:
213 flag_print_opcodes = 1;
214 break;
215
216 case OPTION_GENERATE_EXAMPLE:
217 flag_print_opcodes = 2;
218 break;
219
220 case OPTION_MSHORT:
221 elf_flags &= ~E_XGATE_I32;
222 break;
223
224 case OPTION_MLONG:
225 elf_flags |= E_XGATE_I32;
226 break;
227
228 case OPTION_MSHORT_DOUBLE:
229 elf_flags &= ~E_XGATE_F64;
230 break;
231
232 case OPTION_MLONG_DOUBLE:
233 elf_flags |= E_XGATE_F64;
234 break;
235
236 default:
237 return 0;
238 }
239 return 1;
240}
241
242const char *
243xgate_arch_format (void)
244{
245 get_default_target ();
246
247 if (current_architecture & cpuxgate)
248 return "elf32-xgate";
249
250 return "error";
251}
252
253static void
254get_default_target (void)
255{
256 const bfd_target *target;
257 bfd abfd;
258
259 if (current_architecture != 0)
260 return;
261
262 default_cpu = "unknown";
263 target = bfd_find_target (0, &abfd);
264
265 if (target && target->name)
266 {
267 if (strcmp (target->name, "elf32-xgate") == 0)
268 {
269 current_architecture = cpuxgate;
270 default_cpu = "XGATE V1";
271 return;
272 }
273
274 as_bad (_("Default target `%s' is not supported."), target->name);
275 }
276}
277
278void
279md_begin (void)
280{
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;
285 int handle_enum = 0;
286 unsigned int number_of_handle_rows = 0;
287 int i, j = 0;
288
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));
293
294 memset (xgate_op_table, 0,
295 sizeof(struct xgate_opcode) * (xgate_num_opcodes + 1));
296
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];
300
301 qsort (xgate_op_table, xgate_num_opcodes, sizeof(struct xgate_opcode),
302 (int (*)(const void *, const void *)) cmp_opcode);
303
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;
307 xgate_opcode_ptr++)
308 {
309 if (prev_op_name != 0)
310 {
311 if (strcmp (prev_op_name, xgate_opcode_ptr->name))
312 number_of_handle_rows++;
313 }
314 prev_op_name = xgate_opcode_ptr->name;
315 }
316
317 op_handles = (struct xgate_opcode_handle *)
318 xmalloc (sizeof(struct xgate_opcode_handle) * (number_of_handle_rows + 1));
319
320 /* Insert opcode names into hash table, aliasing duplicates. */
321 xgate_hash = hash_new ();
322
323 for (xgate_opcode_ptr = xgate_op_table, i = 0, j = 0; i < xgate_num_opcodes;
324 i++, xgate_opcode_ptr++)
325 {
326 if (strcmp (prev_op_name, xgate_opcode_ptr->name) || i == 0)
327 {
328 handle_enum = 0;
329 if (i)
330 j++;
331
332 op_handles[j].name = xgate_opcode_ptr->name;
333 op_handles[j].opc0[0] = xgate_opcode_ptr;
334 }
335 else
336 {
337 handle_enum++;
338 op_handles[j].opc0[handle_enum] = xgate_opcode_ptr;
339 }
340 op_handles[j].number_of_modes = handle_enum;
341 prev_op_name = op_handles[j].name;
342 }
343
344 while (op_handles->name)
345 {
346 hash_insert (xgate_hash, op_handles->name, (char *) op_handles);
347 op_handles++;
348 }
349
350 if (flag_print_opcodes == 1)
351 xgate_print_table ();
352}
353
354void
355xgate_init_after_args (void)
356{
357}
358
359void
360md_show_usage (FILE * stream)
361{
362 get_default_target ();
363
364 fprintf (
365 stream,
366 _("\
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"),
376 default_cpu);
377}
378
379enum bfd_architecture
380xgate_arch (void)
381{
382 get_default_target ();
383 return bfd_arch_xgate;
384}
385
386int
387xgate_mach (void)
388{
389 return 0;
390}
391
392void
393xgate_print_syntax (char *name)
394{
395 int i;
396
397 for (i = 0; i < xgate_num_opcodes; i++)
398 {
399 if (!strcmp (xgate_opcodes[i].name, name))
400 {
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);
432 }
433 }
434}
435
436void
437xgate_print_table (void)
438{
439 int i;
440
441 for (i = 0; i < xgate_num_opcodes; i++)
442 xgate_print_syntax (xgate_opcodes[i].name);
443
444 return;
445}
446
447const char *
448xgate_listing_header (void)
449{
450 if (current_architecture & cpuxgate)
451 return "XGATE GAS ";
452
453 return "ERROR MC9S12X GAS ";
454}
455
456symbolS *
457md_undefined_symbol (char *name ATTRIBUTE_UNUSED)
458{
459 return 0;
460}
461
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. */
464
465valueT
466md_section_align (asection * seg, valueT addr)
467{
468 int align = bfd_get_section_alignment (stdoutput, seg);
469 return ((addr + (1 << align) - 1) & (-1 << align));
470}
471
472void
473md_assemble (char *input_line)
474{
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;
482 char *p = 0;
483
484 fixup_required = 0;
485 oper_check = 0; /* set error flags */
486 input_line = extract_word (input_line, op_name, sizeof(op_name));
487
488 /* Check to make sure we are not reading a bogus line. */
489 if (!op_name[0])
490 as_bad (_("opcode missing or not found on input line"));
491
492 if (!(opcode_handle = (struct xgate_opcode_handle *) hash_find (xgate_hash,
493 op_name)))
494 {
495 as_bad (_("opcode %s not found in opcode hash table"), op_name);
496 }
497 else
498 {
499 /* Detect operand format so we can pull the proper opcode bin. */
500 sh_format = xgate_detect_format (input_line);
501
502 opcode = xgate_find_match (opcode_handle, opcode_handle->number_of_modes,
503 sh_format);
504
505 if (!opcode)
506 {
507 as_bad (_("matching operands to opcode "));
508 xgate_print_syntax (opcode_handle->opc0[0]->name);
509 }
510 else if (opcode->size == 2)
511 {
512 /* Size is one word - assemble that native insn. */
513 xgate_operands (opcode, &input_line);
514 }
515 else
516 {
517 /* Insn is a simplified instruction - expand it out. */
518 macroClipping = 1;
519 unsigned int i;
520
521 /* skip past our ';' separator. */
522 for (i = strlen (opcode->constraints), p = opcode->constraints; i > 0;
523 i--, p++)
524 {
525 if (*p == ';')
526 {
527 p++;
528 break;
529 }
530 }
531 input_line = skip_whitespace (input_line);
532 char *macro_inline = input_line;
533
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++)
536 {
537 /* Loop though macro operand list. */
538 input_line = macro_inline; /* Rewind. */
539 p = extract_word (p, op_name, 10);
540
541 if (!(opcode_handle = (struct xgate_opcode_handle *)
542 hash_find (xgate_hash, op_name)))
543 {
544 as_bad (
545 _(": processing macro, real opcode handle not found in hash"));
546 break;
547 }
548 else
549 {
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);
554 }
555 }
556 }
557 }
558 macroClipping = 0;
559 input_line = saved_input_line;
560}
561
562/* Force truly undefined symbols to their maximum size, and generally set up
563 the frag list to be relaxed. */
564
565int
566md_estimate_size_before_relax (fragS *fragp, asection *seg)
567{
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[] =
572 { 0, 2 };
573
574 for (subtype = 0; subtype < ARRAY_SIZE (rlx_state); subtype += 2)
575 {
576 if (fragp->fr_subtype == rlx_state[subtype]
577 && (!S_IS_DEFINED (fragp->fr_symbol)
578 || seg != S_GET_SEGMENT (fragp->fr_symbol)))
579 {
580 fragp->fr_subtype = rlx_state[subtype + 1];
581 break;
582 }
583 }
584
585 if (fragp->fr_subtype >= ARRAY_SIZE (md_relax_table))
586 abort ();
587
588 return md_relax_table[fragp->fr_subtype].rlx_length;
589}
590
591
592/* Relocation, relaxation and frag conversions. */
593
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. */
597
598long
599md_pcrel_from (fixS * fixP)
600{
601 return fixP->fx_size + fixP->fx_where + fixP->fx_frag->fr_address;
602}
603
604/* If while processing a fixup, a reloc really needs to be created
605 then it is done here. */
606
607arelent *
608tc_gen_reloc (asection * section ATTRIBUTE_UNUSED, fixS * fixp)
609{
610 arelent * reloc;
611
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;
616
617 if (fixp->fx_r_type == 0)
618 {
619 reloc->howto = bfd_reloc_type_lookup (stdoutput, BFD_RELOC_16);
620 }
621 else
622 {
623 reloc->howto = bfd_reloc_type_lookup (stdoutput, fixp->fx_r_type);
624 }
625
626 if (reloc->howto == (reloc_howto_type *) NULL)
627 {
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);
631 return NULL;
632 }
633
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;
638 reloc->addend = 0;
639 return reloc;
640}
641
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. */
646
647void
648md_apply_fix (fixS * fixP, valueT * valP, segT seg ATTRIBUTE_UNUSED)
649{
650 char *where;
651 long value = *valP;
652 int opcode = 0;
653 ldiv_t result;
654
655 /* If the fixup is done mark it done so no further symbol resolution will take place. */
656 if (fixP->fx_addsy == (symbolS *) NULL)
657 {
658 fixP->fx_done = 1;
659 }
660
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."));
664
665 where = fixP->fx_frag->fr_literal + fixP->fx_where;
666 opcode = bfd_getl16 (where);
667 int mask = 0;
668
669 switch (fixP->fx_r_type)
670 {
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 */
676 value = result.quot;
677 if (result.rem)
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 */
681 value &= mask;
682 number_to_chars_bigendian (where, (opcode | value), 2);
683 break;
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 */
689 value = result.quot;
690 if (result.rem)
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 */
694 value &= mask;
695 number_to_chars_bigendian (where, (opcode | value), 2);
696 break;
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."));
701 value >>= 8;
702 value &= 0x00ff;
703 bfd_putb16 ((bfd_vma) value | opcode, (void *) where);
704 break;
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."));
710 value &= 0x00ff;
711 bfd_putb16 ((bfd_vma) value | opcode, (void *) where);
712 break;
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);
719 break;
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);
726 break;
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);
733 break;
734 case BFD_RELOC_8:
735 ((bfd_byte *) where)[0] = (bfd_byte) value;
736 break;
737 case BFD_RELOC_32:
738 bfd_putb32 ((bfd_vma) value, (unsigned char *) where);
739 /* todo figure out how to make BFD_RELOC_16 the default */
740 break;
741 case BFD_RELOC_16:
742 bfd_putb16 ((bfd_vma) value, (unsigned char *) where);
743 break;
744 default:
745 as_fatal (_("Line %d: unknown relocation type: 0x%x."), fixP->fx_line,
746 fixP->fx_r_type);
747 break;
748 }
749}
750
751/* See whether we need to force a relocation into the output file. */
752
753int
754tc_xgate_force_relocation (fixS * fixP)
755{
756 if (fixP->fx_r_type == BFD_RELOC_XGATE_RL_GROUP)
757 return 1;
758 return generic_force_reloc (fixP);
759}
760
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
765 used. */
766
767int
768tc_xgate_fix_adjustable (fixS * fixP)
769{
770 switch (fixP->fx_r_type)
771 {
772 /* For the linker relaxation to work correctly, these relocs
773 need to be on the symbol itself. */
774 case BFD_RELOC_16:
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:
779 case BFD_RELOC_32:
780 return 0;
781 default:
782 return 1;
783 }
784}
785
786void
787md_convert_frag (bfd * abfd ATTRIBUTE_UNUSED,
788 asection * sec ATTRIBUTE_UNUSED,
789 fragS * fragP ATTRIBUTE_UNUSED)
790{
791 as_bad (("md_convert_frag not implemented yet"));
792 abort ();
793}
794
795/* Set the ELF specific flags. */
796
797void
798xgate_elf_final_processing (void)
799{
800 elf_flags |= EF_XGATE_MACH;
801 elf_elfheader (stdoutput)->e_flags &= ~EF_XGATE_ABI;
802 elf_elfheader (stdoutput)->e_flags |= elf_flags;
803}
804
805static inline char *
806skip_whitespace (char *s)
807{
808 while (*s == ' ' || *s == '\t' || *s == '(' || *s == ')')
809 s++;
810
811 return s;
812}
813
814/* Extract a word (continuous alpha-numeric chars) from the input line. */
815
816static char *
817extract_word (char *from, char *to, int limit)
818{
819 char *op_end;
820 int size = 0;
821
822 /* Drop leading whitespace. */
823 from = skip_whitespace (from);
824 *to = 0;
825 /* Find the op code end. */
826 for (op_end = from; *op_end != 0 && is_part_of_name (*op_end);)
827 {
828 to[size++] = *op_end++;
829 if (size + 1 >= limit)
830 break;
831 }
832 to[size] = 0;
833 return op_end;
834}
835
836static char *
837xgate_new_instruction (int size)
838{
839 char *f = frag_more (size);
840 dwarf2_emit_insn (size);
841 return f;
842}
843
844unsigned short
845xgate_apply_operand (unsigned short new_mask,
846 unsigned short *availiable_mask_bits,
847 unsigned short mask,
848 unsigned char n_bits)
849{
850 unsigned short n_shifts;
851 unsigned int n_drop_bits;
852
853 /* Shift until you find an available operand bit "1" and record the number of shifts. */
854 for (n_shifts = 0;
855 !(*availiable_mask_bits & SIXTEENTH_BIT) && n_shifts < 16;
856 n_shifts++)
857 *availiable_mask_bits <<= 1;
858
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);
862 --n_drop_bits)
863 *availiable_mask_bits <<= 1;
864
865 if (n_drop_bits)
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))
869 {
870 oper_check = 1; /* flag operand check as good */
871 }
872 new_mask <<= N_BITS_IN_WORD - (n_shifts + n_bits);
873 mask |= new_mask;
874 return mask;
875}
876
877/* Parse ordinary expression. */
878
879static char *
880xgate_parse_exp (char *s, expressionS * op)
881{
882 input_line_pointer = s;
883 expression(op);
884 if (op->X_op == O_absent)
885 as_bad (_("missing operand"));
886 return input_line_pointer;
887}
888
889/* For testing. Comment out to prevent defined but not used warning
890
891static unsigned int
892xgate_get_constant(char *str, int max)
893{
894 expressionS ex;
895
896 str = skip_whitespace(str);
897 input_line_pointer = str;
898 expression (& ex);
899
900 if (ex.X_op != O_constant)
901 as_bad(_("constant value required"));
902
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);
905
906 return ex.X_add_number;
907}
908*/
909
910static int
911cmp_opcode (struct xgate_opcode *op1, struct xgate_opcode *op2)
912{
913 return strcmp (op1->name, op2->name);
914}
915
916/* Parse instruction operands. */
917
918void
919xgate_operands (struct xgate_opcode *opcode, char **line)
920{
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;
925 char *str = *line;
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;
931 int i = 0;
932 char c = 0;
933
934 /* Generate available operand bits mask. */
935 for (i = 0; (c = opcode->format[i]); i++)
936 {
937 if (ISDIGIT (c) || (c == 's'))
938 {
939 oper_mask <<= 1;
940 }
941 else
942 {
943 oper_mask <<= 1;
944 oper_mask += 1;
945 n_operand_bits++;
946 }
947 }
948
949 /* Opcode has operands. */
950 /* Parse first operand. */
951 if (*op)
952 {
953 if (*op == '=')
954 {
955 first_operand_equals_second = 1;
956 ++op;
957 }
958 operand = xgate_operand (opcode, &operand_bit_length, where, &op, &str);
959 ++op;
960 bin = xgate_apply_operand (operand, &oper_mask, bin, operand_bit_length);
961 /* Parse second operand. */
962 if (*op)
963 {
964 if (*op == ',')
965 ++op;
966 str = skip_whitespace (str);
967 if (*str++ != ',')
968 {
969 if (first_operand_equals_second)
970 {
971 bin = xgate_apply_operand (operand, &oper_mask, bin,
972 operand_bit_length);
973 ++op;
974 }
975 else
976 {
977 as_bad (_("`,' required before second operand"));
978 }
979 }
980 else
981 {
982 str = skip_whitespace (str);
983 operand = xgate_operand (opcode, &operand_bit_length, where, &op,
984 &str);
985 bin = xgate_apply_operand (operand, &oper_mask, bin,
986 operand_bit_length);
987 ++op;
988 }
989 }
990
991 /* Parse the third register. */
992 if (*op)
993 {
994 if (*op == ',')
995 ++op;
996 str = skip_whitespace (str);
997 if (*str++ != ',')
998 as_bad (_("`,' required before third operand"));
999 str = skip_whitespace (str);
1000 operand = xgate_operand (opcode, &operand_bit_length, where, &op,
1001 &str);
1002 bin = xgate_apply_operand (operand, &oper_mask, bin,
1003 operand_bit_length);
1004 }
1005 }
1006 if (opcode->size == 2 && fixup_required)
1007 {
1008 bfd_putl16 (bin, frag);
1009 }
1010 else if ((opcode->sh_format & XG_PCREL))
1011 {
1012 /* Write our data to a frag for further processing. */
1013 bfd_putl16 (opcode->bin_opcode, frag);
1014 }
1015 else
1016 {
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);
1020 }
1021 prev = bin;
1022 *line = str;
1023 return;
1024}
1025
1026static unsigned int
1027xgate_operand (struct xgate_opcode *opcode,
1028 int *bit_width,
1029 int where,
1030 char **op_con,
1031 char **line)
1032{
1033 expressionS op_expr;
1034 fixS *fixp = 0;
1035 char *op_constraint = *op_con;
1036 unsigned int op_mask = 0;
1037 char *str = skip_whitespace (*line);
1038 char r_name[20] =
1039 { 0 };
1040 unsigned int pp_fix = 0;
1041 unsigned short max_size = 0;
1042 int i;
1043
1044 *bit_width = 0;
1045 /* Reset. */
1046
1047 switch (*op_constraint)
1048 {
1049 case '+': /* Indexed register operand +/- or plain r. */
1050 /* TODO should be able to combine with with case R. */
1051
1052 /* Default to neither inc or dec. */
1053 pp_fix = 0;
1054 *bit_width = 5;
1055 str = skip_whitespace (str);
1056 while (*str != ' ' && *str != '\t')
1057 {
1058 if (*str == '-')
1059 pp_fix = DECREMENT;
1060 else if (*str == '+')
1061 pp_fix = INCREMENT;
1062 else if (*str == 'r' || *str == 'R')
1063 {
1064 str = extract_word (str, r_name, sizeof(r_name));
1065 if (ISDIGIT (r_name[1]))
1066 {
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);
1071 continue;
1072 }
1073 }
1074 str++;
1075 }
1076 op_mask <<= 2;
1077 op_mask |= pp_fix;
1078 break;
1079
1080 case 'r': /* Register operand. */
1081 if (*str == 'r' || *str == 'R')
1082 {
1083 *bit_width = 3;
1084 str = extract_word (str, r_name, sizeof(r_name));
1085 op_mask = 0xff;
1086 if (ISDIGIT (r_name[1]))
1087 {
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);
1095 }
1096 }
1097 else
1098 {
1099 as_bad (_(": expected register name r0-r7 read %s "), r_name);
1100 }
1101 break;
1102
1103 case 'i': /* Immediate value or expression expected. */
1104 /* Advance the original format pointer. */
1105 (*op_con)++;
1106 op_constraint++;
1107 if (ISDIGIT (*op_constraint))
1108 {
1109 *bit_width = (int) *op_constraint - '0';
1110 }
1111 else if (*op_constraint == 'a')
1112 {
1113 *bit_width = 0x0A;
1114 }
1115 else if (*op_constraint == 'f')
1116 {
1117 *bit_width = 0x0F;
1118 }
1119 /* http://tigcc.ticalc.org/doc/gnuasm.html#SEC31 */
1120 if (*str == '#')
1121 str++;
1122 str = xgate_parse_exp (str, &op_expr);
1123 if (op_expr.X_op == O_constant)
1124 {
1125 if (!ISDIGIT (*op_constraint))
1126 as_bad (
1127 _(":expected bit length with constraint type i(# immediate) read %c"),
1128 *op_constraint);
1129 op_mask = op_expr.X_add_number;
1130 if ((opcode->name[strlen (opcode->name) - 1] == 'l') && macroClipping)
1131 {
1132 op_mask &= 0x00FF;
1133 }
1134 else if ((opcode->name[strlen (opcode->name) - 1]) == 'h'
1135 && macroClipping)
1136 {
1137 op_mask >>= 8;
1138 }
1139
1140 /* Make sure it fits. */
1141 for (i = *bit_width; i; i--)
1142 {
1143 max_size <<= 1;
1144 max_size += 1;
1145 }
1146 if (op_mask > max_size)
1147 as_bad (_(":operand value(%d) too big for constraint"), op_mask);
1148 }
1149 else
1150 {
1151 fixup_required = 1;
1152 if (*op_constraint == '8')
1153 {
1154 if ((opcode->name[strlen (opcode->name) - 1] == 'l')
1155 && macroClipping)
1156 {
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;
1161 }
1162 if ((opcode->name[strlen (opcode->name) - 1]) == 'h'
1163 && macroClipping)
1164 {
1165 fixp = fix_new_exp (frag_now, where, 2, &op_expr, FALSE,
1166 BFD_RELOC_XGATE_IMM8_HI);
1167 fixp->fx_pcrel_adjust = 0;
1168 }
1169 if (!fixp)
1170 as_bad (_(":unknown relocation"));
1171 }
1172 else if (*op_constraint == '5')
1173 {
1174 fixp = fix_new_exp (frag_now, where, 2, &op_expr, FALSE,
1175 BFD_RELOC_XGATE_IMM5);
1176 fixp->fx_pcrel_adjust = 0;
1177 }
1178 else if (*op_constraint == '4')
1179 {
1180 fixp = fix_new_exp (frag_now, where, 2, &op_expr, FALSE,
1181 BFD_RELOC_XGATE_IMM4);
1182 fixp->fx_pcrel_adjust = 0;
1183 }
1184 else if (*op_constraint == '3')
1185 {
1186 fixp = fix_new_exp (frag_now, where, 2, &op_expr, FALSE,
1187 BFD_RELOC_XGATE_IMM3);
1188 fixp->fx_pcrel_adjust = 0;
1189 }
1190 else
1191 {
1192 as_bad (_(":unknown relocation constraint size"));
1193 }
1194 }
1195 break;
1196
1197 case 'c': /* CCR register expected. */
1198 if (*str == 'c' || *str == 'C')
1199 {
1200 *bit_width = 0;
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);
1204 }
1205 else
1206 {
1207 as_bad (_(": expected character c or C read %c"), *str);
1208 }
1209 break;
1210
1211 case 'p': /* PC register expected. */
1212 if (*str == 'p' || *str == 'P')
1213 {
1214 *bit_width = 0;
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);
1218 }
1219 else
1220 {
1221 as_bad (_(": expected character p or P read %c "), *str);
1222 }
1223 break;
1224
1225 case 'b': /* Branch expected. */
1226 str = xgate_parse_exp (str, &op_expr);
1227 (*op_con)++;
1228 op_constraint++;
1229 if (op_expr.X_op != O_register)
1230 {
1231 if (*op_constraint == '9')
1232 {
1233 /* mode == M68XG_OP_REL9 */
1234 fixp = fix_new_exp (frag_now, where, 2, &op_expr, TRUE,
1235 R_XGATE_PCREL_9);
1236 fixp->fx_pcrel_adjust = 1;
1237 }
1238 else if (*op_constraint == 'a')
1239 { /* mode == M68XG_OP_REL10 */
1240 fixp = fix_new_exp (frag_now, where, 2, &op_expr, TRUE,
1241 R_XGATE_PCREL_10);
1242 fixp->fx_pcrel_adjust = 1;
1243 }
1244 }
1245 else
1246 {
1247 as_fatal (_("Operand `%x' not recognized in fixup8."), op_expr.X_op);
1248 }
1249 break;
1250
1251 case '?':
1252 break;
1253
1254 default:
1255 as_bad (_("unknown constraint `%c'"), *op_constraint);
1256 break;
1257 }
1258 *line = str;
1259 return op_mask;
1260}
1261
1262unsigned int
1263xgate_detect_format (char *line_in)
1264{
1265 char num_operands = 0;
1266 char *str = skip_whitespace (line_in);
1267 int i = 0;
1268 int j = 0;
1269 char c = 0;
1270 unsigned int stripped_length = 0;
1271 char sh_format[10] =
1272 { 0 }; /* Shorthand format. */
1273 char operands_stripped[3][20] =
1274 {
1275 { 0 }
1276 };
1277 /* Strings. TODO maybe structure this. */
1278 char *i_string =
1279 { "i" };
1280 char *r_string =
1281 { "r" };
1282 char *r_r_string =
1283 { "r,r" };
1284 char *r_r_r_string =
1285 { "r,r,r" };
1286 char *r_i_string =
1287 { "r,i" };
1288 char *r_c_string =
1289 { "r,c" };
1290 char *c_r_string =
1291 { "c,r" };
1292 char *r_p_string =
1293 { "r,p" };
1294 char *r_r_i_string =
1295 { "r,r,i" };
1296
1297 /* If the length is zero this is an inherent instruction. */
1298 if (strlen (str) == 0)
1299 return XG_INH;
1300
1301 for (i = 0, j = 0, num_operands = 1; (c = TOLOWER (*str)) != 0; str++)
1302 {
1303 if (c == ' ' || c == '\t' || c == '(' || c == ')' || c == '-' || c == '+')
1304 continue;
1305
1306 if (c == ',')
1307 {
1308 j++;
1309 num_operands++;
1310 i = 0;
1311 continue;
1312 }
1313
1314 if (i > MAX_DETECT_CHARS)
1315 continue;
1316
1317 operands_stripped[j][i++] = c;
1318 }
1319
1320 /* Process our substrings to see what we have. */
1321 for (i = 0, j = 0; num_operands > i; i++)
1322 {
1323 stripped_length = strlen (&operands_stripped[i][0]);
1324
1325 /* Add separator if we have more than one operand. */
1326 if (i > 0)
1327 sh_format[j++] = ',';
1328
1329 /* Try to process by length first. */
1330 if (stripped_length > 3)
1331 {
1332 sh_format[j++] = 'i';
1333 }
1334 else if (stripped_length == 1)
1335 {
1336 sh_format[j++] = 'i';
1337 }
1338 else if (stripped_length == 2)
1339 {
1340 if (operands_stripped[i][0]
1341 == 'r' && ISDIGIT (operands_stripped[i][1]))
1342 {
1343 sh_format[j++] = 'r';
1344 }
1345 else if (operands_stripped[i][0] == 'p'
1346 && operands_stripped[i][1] == 'c')
1347 {
1348 sh_format[j++] = 'p';
1349 }
1350 else
1351 {
1352 sh_format[j++] = 'i';
1353 }
1354 }
1355 else if (stripped_length == 3)
1356 {
1357 if (operands_stripped[i][0] == 'c'
1358 && (operands_stripped[i][1] == 'c'
1359 && operands_stripped[i][2] == 'r'))
1360 {
1361 sh_format[j++] = 'c';
1362 }
1363 else if (operands_stripped[i][0] == '#')
1364 {
1365 sh_format[j++] = 'i';
1366 }
1367 else
1368 {
1369 sh_format[j++] = 'i';
1370 }
1371 }
1372 else /* default to immediate */
1373 {
1374 sh_format[j++] = 'i';
1375 }
1376 }
1377
1378 /* See if we have a match. */
1379 if (!strcmp (i_string, sh_format) && num_operands == 1)
1380 return XG_I;
1381 if (!strcmp (r_i_string, sh_format) && num_operands == 2)
1382 return XG_R_I;
1383 if (!strcmp (r_r_r_string, sh_format) && num_operands == 3)
1384 return XG_R_R_R;
1385 if (!strcmp (r_r_string, sh_format) && num_operands == 2)
1386 return XG_R_R;
1387 if (!strcmp (r_string, sh_format) && num_operands == 1)
1388 return XG_R;
1389 if (!strcmp (r_c_string, sh_format) && num_operands == 2)
1390 return XG_R_C;
1391 if (!strcmp (c_r_string, sh_format) && num_operands == 2)
1392 return XG_C_R;
1393 if (!strcmp (r_p_string, sh_format) && num_operands == 2)
1394 return XG_R_P;
1395 if (!strcmp (r_r_i_string, sh_format) && num_operands == 3)
1396 return XG_R_R_I;
1397
1398 return 0;
1399}
1400
1401static struct xgate_opcode *
1402xgate_find_match (struct xgate_opcode_handle *opcode_handle,
1403 int numberOfModes,
1404 unsigned int sh_format)
1405{
1406 int i;
1407
1408 if (numberOfModes == 0)
1409 return opcode_handle->opc0[0];
1410
1411 for (i = 0; i <= numberOfModes; i++)
1412 if (opcode_handle->opc0[i]->sh_format & sh_format)
1413 return opcode_handle->opc0[i];
1414
1415 return NULL;
1416}
This page took 0.073722 seconds and 4 git commands to generate.