xref: /netbsd-src/external/gpl3/binutils/dist/gas/config/tc-xgate.c (revision d11b170b9000ada93db553723522a63d5deac310)
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 
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";
35 
36 #define SIXTEENTH_BIT           0x8000
37 #define N_BITS_IN_WORD          16
38 #define MAX_NUM_OPERANDS        3
39 
40 /* #define STATE_CONDITIONAL_BRANCH		(1) */
41 #define STATE_PC_RELATIVE	(2)
42 #define REGISTER_P(ptr)		(ptr == 'r')
43 #define INCREMENT		01
44 #define DECREMENT		02
45 #define MAXREGISTER		07
46 #define MINREGISTER		00
47 
48 #define OPTION_MMCU 'm'
49 
50 /* This macro has no side-effects.  */
51 #define ENCODE_RELAX(what,length) (((what) << 2) + (length))
52 
53 /* Each unique opcode name has a handle.  That handle may
54    contain pointers to opcodes with the same name but
55    different address modes.  */
56 struct xgate_opcode_handle
57 {
58   int number_of_modes;
59   char *name;
60   struct xgate_opcode *opc0[MAX_OPCODES];
61 };
62 
63 /* XGATE's registers all are 16-bit general purpose.  They are numbered according to the specifications.  */
64 typedef enum register_id
65 {
66   REG_NONE = -1,
67   REG_R0 = 0,
68   REG_R1 = 1,
69   REG_R2 = 2,
70   REG_R3 = 3,
71   REG_R4 = 4,
72   REG_R5 = 5,
73   REG_R6 = 6,
74   REG_R7 = 7,
75   REG_PC = 8,
76   REG_CCR = 9
77 } register_id;
78 
79 /* Operand Modifiers */
80 typedef enum op_modifiers
81 {
82   MOD_NONE = -1,
83   MOD_POSTINC = 1,
84   MOD_PREDEC = 2,
85   MOD_CONSTANT = 3,
86   MOD_LOAD_HIGH = 4,
87   MOD_LOAD_LOW = 5
88 }op_modifiers;
89 
90 typedef struct s_operand
91 {
92   expressionS exp;
93   register_id reg;
94   op_modifiers mod;
95 } s_operand;
96 
97 
98 /*  LOCAL FUNCTIONS */
99 static char *
100 xgate_parse_exp (char *, expressionS *);
101 static inline char *
102 skip_whitespace (char *);
103 static void
104 get_default_target (void);
105 static char *
106 extract_word (char *, char *, int);
107 static char *
108 xgate_new_instruction (int size);
109 unsigned short
110 xgate_apply_operand (unsigned short, unsigned short *, unsigned short,
111     unsigned char);
112 static struct xgate_opcode *
113 xgate_find_match (struct xgate_opcode_handle *, int, unsigned int);
114 static int
115 cmp_opcode (struct xgate_opcode *, struct xgate_opcode *);
116 void
117 xgate_print_syntax (char *);
118 void
119 xgate_print_table (void);
120 unsigned int
121 xgate_get_operands (char *, s_operand []);
122 static register_id
123 reg_name_search (char *);
124 op_modifiers
125 xgate_determine_modifiers(char **);
126 
127 void
128 xgate_scan_operands (struct xgate_opcode *opcode, s_operand []);
129 
130 static unsigned int
131 xgate_parse_operand (struct xgate_opcode *, int *, int where, char **,
132                s_operand);
133 
134 /* LOCAL DATA */
135 static struct hash_control *xgate_hash;
136 
137 /* Previous opcode.  */
138 static unsigned int prev = 0;
139 
140 static unsigned char fixup_required = 0;
141 
142 /* Used to enable clipping of 16 bit operands into 8 bit constraints.  */
143 static unsigned char autoHiLo = 0;
144 
145 static char oper_check;
146 static char flag_print_insn_syntax = 0;
147 static char flag_print_opcodes = 0;
148 
149 static int current_architecture;
150 static const char *default_cpu;
151 
152 /* ELF flags to set in the output file header.  */
153 static int elf_flags = E_XGATE_F64;
154 
155 /* This table describes how you change sizes for the various types of variable
156    size expressions.  This version only supports two kinds.  */
157 
158 /* The fields are:
159    How far Forward this mode will reach.
160    How far Backward this mode will reach.
161    How many bytes this mode will add to the size of the frag.
162    Which mode to go to if the offset won't fit in this one.  */
163 
164 relax_typeS md_relax_table[] =
165 {
166   {1, 1, 0, 0},			/* First entries aren't used.  */
167   {1, 1, 0, 0},			/* For no good reason except.  */
168   {1, 1, 0, 0},			/* that the VAX doesn't either.  */
169   {1, 1, 0, 0},
170   /* XGATE 9 and 10 bit pc rel todo complete and test */
171 /*{(511), (-512), 0, ENCODE_RELAX (STATE_PC_RELATIVE, STATE_WORD)},
172   {(1023), (-1024), 0, ENCODE_RELAX (STATE_PC_RELATIVE, STATE_WORD)}, */
173   {0, 0, 0, 0}
174 };
175 
176 /* This table describes all the machine specific pseudo-ops the assembler
177    has to support.  The fields are: pseudo-op name without dot function to
178    call to execute this pseudo-op Integer arg to pass to the function.  */
179 const pseudo_typeS md_pseudo_table[] =
180 {
181   /* The following pseudo-ops are supported for MRI compatibility.  */
182   {0, 0, 0}
183 };
184 
185 const char *md_shortopts = "m:";
186 
187 struct option md_longopts[] =
188 {
189 #define OPTION_PRINT_INSN_SYNTAX  (OPTION_MD_BASE + 0)
190   { "print-insn-syntax", no_argument, NULL, OPTION_PRINT_INSN_SYNTAX },
191 
192 #define OPTION_PRINT_OPCODES  (OPTION_MD_BASE + 1)
193   { "print-opcodes", no_argument, NULL, OPTION_PRINT_OPCODES },
194 
195 #define OPTION_GENERATE_EXAMPLE  (OPTION_MD_BASE + 2)
196   { "generate-example", no_argument, NULL, OPTION_GENERATE_EXAMPLE },
197 
198 #define OPTION_MSHORT  (OPTION_MD_BASE + 3)
199   { "mshort", no_argument, NULL, OPTION_MSHORT },
200 
201 #define OPTION_MLONG  (OPTION_MD_BASE + 4)
202   { "mlong", no_argument, NULL, OPTION_MLONG },
203 
204 #define OPTION_MSHORT_DOUBLE  (OPTION_MD_BASE + 5)
205   { "mshort-double", no_argument, NULL, OPTION_MSHORT_DOUBLE },
206 
207 #define OPTION_MLONG_DOUBLE  (OPTION_MD_BASE + 6)
208   { "mlong-double", no_argument, NULL, OPTION_MLONG_DOUBLE },
209 
210   { NULL, no_argument, NULL, 0 }
211 };
212 
213 size_t md_longopts_size = sizeof(md_longopts);
214 
215 char *
216 md_atof (int type, char *litP, int *sizeP)
217 {
218   return ieee_md_atof (type, litP, sizeP, TRUE);
219 }
220 
221 int
222 md_parse_option (int c, char *arg)
223 {
224   switch (c)
225     {
226     case OPTION_MMCU:
227       if (strcasecmp (arg, "v1") == 0)
228 	current_architecture = XGATE_V1;
229       else if (strcasecmp (arg, "v2") == 0)
230 	current_architecture = XGATE_V2;
231       else if (strcasecmp (arg, "v3") == 0)
232 	current_architecture = XGATE_V3;
233       else
234 	as_bad (_(" architecture variant invalid"));
235       break;
236 
237     case OPTION_PRINT_INSN_SYNTAX:
238       flag_print_insn_syntax = 1;
239       break;
240 
241     case OPTION_PRINT_OPCODES:
242       flag_print_opcodes = 1;
243       break;
244 
245     case OPTION_GENERATE_EXAMPLE:
246       flag_print_opcodes = 2;
247       break;
248 
249     case OPTION_MSHORT:
250       elf_flags &= ~E_XGATE_I32;
251       break;
252 
253     case OPTION_MLONG:
254       elf_flags |= E_XGATE_I32;
255       break;
256 
257     case OPTION_MSHORT_DOUBLE:
258       elf_flags &= ~E_XGATE_F64;
259       break;
260 
261     case OPTION_MLONG_DOUBLE:
262       elf_flags |= E_XGATE_F64;
263       break;
264 
265     default:
266       return 0;
267     }
268   return 1;
269 }
270 
271 const char *
272 xgate_arch_format (void)
273 {
274   get_default_target ();
275 
276   if (current_architecture & cpuxgate)
277     return "elf32-xgate";
278 
279   return "error";
280 }
281 
282 static void
283 get_default_target (void)
284 {
285   const bfd_target *target;
286   bfd abfd;
287 
288   if (current_architecture != 0)
289     return;
290 
291   default_cpu = "unknown";
292   target = bfd_find_target (0, &abfd);
293 
294   if (target && target->name)
295     {
296       if (strcmp (target->name, "elf32-xgate") == 0)
297         {
298           current_architecture = cpuxgate;
299           default_cpu = "XGATE V1";
300           return;
301         }
302 
303       as_bad (_("Default target `%s' is not supported."), target->name);
304     }
305 }
306 
307 void
308 md_begin (void)
309 {
310   struct xgate_opcode *xgate_opcode_ptr = NULL;
311   struct xgate_opcode *xgate_op_table = NULL;
312   struct xgate_opcode_handle *op_handles = 0;
313   char *prev_op_name = 0;
314   int handle_enum = 0;
315   int number_of_op_handles = 0;
316   int i, j = 0;
317 
318   /* Create a local copy of our opcode table
319      including an extra line for NULL termination.  */
320   xgate_op_table = (struct xgate_opcode *)
321     xmalloc ((xgate_num_opcodes) * sizeof (struct xgate_opcode));
322 
323   memset (xgate_op_table, 0,
324 	  sizeof(struct xgate_opcode) * (xgate_num_opcodes));
325 
326   for (xgate_opcode_ptr = (struct xgate_opcode*) xgate_opcodes, i = 0;
327       i < xgate_num_opcodes; i++)
328     xgate_op_table[i] = xgate_opcode_ptr[i];
329 
330   qsort (xgate_op_table, xgate_num_opcodes, sizeof(struct xgate_opcode),
331 	 (int (*)(const void *, const void *)) cmp_opcode);
332 
333   /* Calculate number of handles since this will be
334      smaller than the raw number of opcodes in the table.  */
335   prev_op_name = "";
336   for (xgate_opcode_ptr = xgate_op_table, i = 0;  i < xgate_num_opcodes;
337       xgate_opcode_ptr++, i++)
338     {
339       if (strcmp (prev_op_name, xgate_opcode_ptr->name))
340         number_of_op_handles++;
341       prev_op_name = xgate_opcode_ptr->name;
342     }
343 
344   op_handles = (struct xgate_opcode_handle *)
345     xmalloc (sizeof(struct xgate_opcode_handle) * (number_of_op_handles));
346 
347   /* Insert unique opcode names into hash table, aliasing duplicates.  */
348   xgate_hash = hash_new ();
349 
350   prev_op_name = "";
351   for (xgate_opcode_ptr = xgate_op_table, i = 0, j = 0; i < xgate_num_opcodes;
352       i++, xgate_opcode_ptr++)
353     {
354       if (!strcmp (prev_op_name, xgate_opcode_ptr->name))
355         {
356           handle_enum++;
357           op_handles[j].opc0[handle_enum] = xgate_opcode_ptr;
358         }
359       else
360         {
361           handle_enum = 0;
362           if (i)
363             j++;
364           op_handles[j].name = xgate_opcode_ptr->name;
365           op_handles[j].opc0[0] = xgate_opcode_ptr;
366           hash_insert (xgate_hash, (char *) op_handles[j].name,
367               (char *) &(op_handles[j]));
368         }
369       op_handles[j].number_of_modes = handle_enum;
370       prev_op_name = op_handles[j].name;
371     }
372 
373   if (flag_print_opcodes == 1)
374     xgate_print_table ();
375 }
376 
377 void
378 xgate_init_after_args (void)
379 {
380 }
381 
382 void
383 md_show_usage (FILE * stream)
384 {
385   get_default_target ();
386 
387   fprintf (
388 	   stream,
389 	   _("\
390       Freescale XGATE co-processor options:\n			\
391        -mshort                 use 16-bit int ABI (default)\n	\
392        -mlong                  use 32-bit int ABI\n		\
393        -mshort-double          use 32-bit double ABI\n			\
394        -mlong-double           use 64-bit double ABI (default)\n\
395       --mxgate                 specify the processor variant[default %s]\n\
396       --print-insn-syntax     print the syntax of instruction in case of error\n\
397       --print-opcodes         print the list of instructions with syntax\n\
398       --generate-example      generate an example of each instruction"),
399 	   default_cpu);
400 }
401 
402 enum bfd_architecture
403 xgate_arch (void)
404 {
405   get_default_target ();
406   return bfd_arch_xgate;
407 }
408 
409 int
410 xgate_mach (void)
411 {
412   return 0;
413 }
414 
415 void
416 xgate_print_syntax (char *name)
417 {
418   int i;
419 
420   for (i = 0; i < xgate_num_opcodes; i++)
421     {
422       if (!strcmp (xgate_opcodes[i].name, name))
423         {
424           if (!strcmp (xgate_opcodes[i].constraints, XGATE_OP_IDR))
425             printf ("\tFormat is %s\tRx, Rx, Rx+|-Rx|Rx\n",
426 		    xgate_opcodes[i].name);
427           if (!strcmp (xgate_opcodes[i].constraints, XGATE_OP_INH))
428             printf ("\tFormat is %s\n", xgate_opcodes[i].name);
429           if (!strcmp (xgate_opcodes[i].constraints, XGATE_OP_TRI))
430             printf ("\tFormat is %s\tRx, Rx, Rx\n", xgate_opcodes[i].name);
431           if (!strcmp (xgate_opcodes[i].constraints, XGATE_OP_DYA))
432             printf ("\tFormat is %s\tRx, Rx\n", xgate_opcodes[i].name);
433           if (!strcmp (xgate_opcodes[i].constraints, XGATE_OP_IMM3))
434             printf ("\tFormat is %s\t<3-bit value>\n", xgate_opcodes[i].name);
435           if (!strcmp (xgate_opcodes[i].constraints, XGATE_OP_IMM4))
436             printf ("\tFormat is %s\t<4 -bit value>\n", xgate_opcodes[i].name);
437           if (!strcmp (xgate_opcodes[i].constraints, XGATE_OP_IMM8))
438             printf ("\tFormat is %s\tRx, <8-bit value>\n",
439 		    xgate_opcodes[i].name);
440           if (!strcmp (xgate_opcodes[i].constraints, XGATE_OP_IMM16))
441             printf ("\tFormat is %s\tRx, <16-bit value>\n",
442 		    xgate_opcodes[i].name);
443           if (!strcmp (xgate_opcodes[i].constraints, XGATE_OP_MON_R_C))
444             printf ("\tFormat is %s\tRx, CCR\n", xgate_opcodes[i].name);
445           if (!strcmp (xgate_opcodes[i].constraints, XGATE_OP_MON_C_R))
446             printf ("\tFormat is %s\tCCR, Rx\n", xgate_opcodes[i].name);
447           if (!strcmp (xgate_opcodes[i].constraints, XGATE_OP_MON_R_P))
448             printf ("\tFormat is %s\tRx, PC\n", xgate_opcodes[i].name);
449           if (!strcmp (xgate_opcodes[i].constraints, XGATE_OP_IMM16mLDW))
450             printf ("\tFormat is %s\tRx, <16-bit value>\n",
451 		    xgate_opcodes[i].name);
452         }
453     }
454 }
455 
456 void
457 xgate_print_table (void)
458 {
459   int i;
460 
461   for (i = 0; i < xgate_num_opcodes; i++)
462     xgate_print_syntax (xgate_opcodes[i].name);
463 
464   return;
465 }
466 
467 const char *
468 xgate_listing_header (void)
469 {
470   if (current_architecture & cpuxgate)
471     return "XGATE GAS ";
472 
473   return "ERROR MC9S12X GAS ";
474 }
475 
476 symbolS *
477 md_undefined_symbol (char *name ATTRIBUTE_UNUSED)
478 {
479   return 0;
480 }
481 
482 /* GAS will call this function for each section at the end of the assembly,
483    to permit the CPU backend to adjust the alignment of a section.  */
484 
485 valueT
486 md_section_align (asection * seg, valueT addr)
487 {
488   int align = bfd_get_section_alignment (stdoutput, seg);
489   return ((addr + (1 << align) - 1) & (-1 << align));
490 }
491 
492 void
493 md_assemble (char *input_line)
494 {
495   struct xgate_opcode *opcode = 0;
496   struct xgate_opcode *macro_opcode = 0;
497   struct xgate_opcode_handle *opcode_handle = 0;
498   /* Caller expects it to be returned as it was passed.  */
499   char *saved_input_line = input_line;
500   char op_name[9] =  { 0 };
501   unsigned int sh_format = 0;
502   char *p = 0;
503 
504   s_operand new_operands[MAX_NUM_OPERANDS];
505 
506   fixup_required = 0;
507   oper_check = 0; /* set error flags */
508   input_line = extract_word (input_line, op_name, sizeof(op_name));
509 
510   /* Check to make sure we are not reading a bogus line.  */
511   if (!op_name[0])
512     as_bad (_("opcode missing or not found on input line"));
513 
514   if (!(opcode_handle = (struct xgate_opcode_handle *) hash_find (xgate_hash,
515       op_name)))
516     {
517       as_bad (_("opcode %s not found in opcode hash table"), op_name);
518     }
519   else
520     {
521       /* Parse operands so we can find the proper opcode bin.  */
522 
523       sh_format = xgate_get_operands(input_line, new_operands);
524 
525       opcode = xgate_find_match (opcode_handle, opcode_handle->number_of_modes,
526           sh_format);
527 
528       if (!opcode)
529         {
530           as_bad (_("matching operands to opcode "));
531           xgate_print_syntax (opcode_handle->opc0[0]->name);
532         }
533       else if (opcode->size == 2)
534         {
535 	  /* Size is one word - assemble that native insn.  */
536           xgate_scan_operands (opcode, new_operands);
537         }
538       else
539         {
540 	  /* Insn is a simplified instruction - expand it out.  */
541           autoHiLo = 1;
542           unsigned int i;
543 
544           /* skip past our ';' separator.  */
545           for (i = strlen (opcode->constraints), p = opcode->constraints; i > 0;
546               i--, p++)
547             {
548               if (*p == ';')
549                 {
550                   p++;
551                   break;
552                 }
553             }
554           input_line = skip_whitespace (input_line);
555           char *macro_inline = input_line;
556 
557           /* Loop though the macro's opcode list and apply operands to each real opcode. */
558           for (i = 0; *p && i < (opcode->size / 2); i++)
559             {
560 	      /* Loop though macro operand list.  */
561               input_line = macro_inline; /* Rewind.  */
562               p = extract_word (p, op_name, 10);
563 
564               if (!(opcode_handle = (struct xgate_opcode_handle *)
565 		    hash_find (xgate_hash, op_name)))
566                 {
567                   as_bad (
568                       _(": processing macro, real opcode handle not found in hash"));
569                   break;
570                 }
571               else
572                 {
573                   sh_format = xgate_get_operands(input_line, new_operands);
574                   macro_opcode = xgate_find_match (opcode_handle,
575                       opcode_handle->number_of_modes, sh_format);
576                   xgate_scan_operands (macro_opcode, new_operands);
577 
578                 }
579             }
580         }
581     }
582   autoHiLo = 0;
583   input_line = saved_input_line;
584 }
585 
586 /* Force truly undefined symbols to their maximum size, and generally set up
587    the frag list to be relaxed.  */
588 
589 int
590 md_estimate_size_before_relax (fragS *fragp, asection *seg)
591 {
592   /* If symbol is undefined or located in a different section,
593      select the largest supported relocation.  */
594   relax_substateT subtype;
595   relax_substateT rlx_state[] =
596     { 0, 2 };
597 
598   for (subtype = 0; subtype < ARRAY_SIZE (rlx_state); subtype += 2)
599     {
600       if (fragp->fr_subtype == rlx_state[subtype]
601           && (!S_IS_DEFINED (fragp->fr_symbol)
602               || seg != S_GET_SEGMENT (fragp->fr_symbol)))
603         {
604           fragp->fr_subtype = rlx_state[subtype + 1];
605           break;
606         }
607     }
608 
609   if (fragp->fr_subtype >= ARRAY_SIZE (md_relax_table))
610     abort ();
611 
612   return md_relax_table[fragp->fr_subtype].rlx_length;
613 }
614 
615 
616 /* Relocation, relaxation and frag conversions.  */
617 
618 /* PC-relative offsets are relative to the start of the
619    next instruction.  That is, the address of the offset, plus its
620    size, since the offset is always the last part of the insn.  */
621 
622 long
623 md_pcrel_from (fixS * fixP)
624 {
625   return fixP->fx_size + fixP->fx_where + fixP->fx_frag->fr_address;
626 }
627 
628 /* If while processing a fixup, a reloc really needs to be created
629    then it is done here.  */
630 
631 arelent *
632 tc_gen_reloc (asection * section ATTRIBUTE_UNUSED, fixS * fixp)
633 {
634   arelent * reloc;
635 
636   reloc = (arelent *) xmalloc (sizeof(arelent));
637   reloc->sym_ptr_ptr = (asymbol **) xmalloc (sizeof(asymbol *));
638   *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
639   reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
640 
641   if (fixp->fx_r_type == 0)
642     {
643       reloc->howto = bfd_reloc_type_lookup (stdoutput, BFD_RELOC_16);
644     }
645   else
646     {
647       reloc->howto = bfd_reloc_type_lookup (stdoutput, fixp->fx_r_type);
648     }
649 
650   if (reloc->howto == (reloc_howto_type *) NULL)
651     {
652       as_bad_where (fixp->fx_file, fixp->fx_line, _
653       ("Relocation %d is not supported by object file format."),
654           (int) fixp->fx_r_type);
655       return NULL;
656     }
657 
658   /* Since we use Rel instead of Rela, encode the vtable entry to be
659      used in the relocation's section offset.  */
660   if (fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
661     reloc->address = fixp->fx_offset;
662   reloc->addend = 0;
663   return reloc;
664 }
665 
666 /* Patch the instruction with the resolved operand.  Elf relocation
667    info will also be generated to take care of linker/loader fixups.
668    The XGATE addresses only 16-bit addresses.The BFD_RELOC_32 is necessary
669    for the support of --gstabs.  */
670 
671 void
672 md_apply_fix (fixS * fixP, valueT * valP, segT seg ATTRIBUTE_UNUSED)
673 {
674   char *where;
675   long value = *valP;
676   int opcode = 0;
677   ldiv_t result;
678 
679   /* If the fixup is done mark it done so no further symbol resolution will take place.  */
680   if (fixP->fx_addsy == (symbolS *) NULL)
681     {
682       fixP->fx_done = 1;
683     }
684 
685   /* We don't actually support subtracting a symbol.  */
686   if (fixP->fx_subsy != (symbolS *) NULL)
687     as_bad_where (fixP->fx_file, fixP->fx_line, _("Expression too complex."));
688 
689   where = fixP->fx_frag->fr_literal + fixP->fx_where;
690   opcode = bfd_getl16 (where);
691   int mask = 0;
692 
693   switch (fixP->fx_r_type)
694     {
695     case R_XGATE_PCREL_9:
696       if (value < -512 || value > 511)
697 	as_bad_where (fixP->fx_file, fixP->fx_line,
698 		      _("Value %ld too large for 9-bit PC-relative branch."), value);
699       result = ldiv (value, 2); /* from bytes to words */
700       value = result.quot;
701       if (result.rem)
702 	as_bad_where (fixP->fx_file, fixP->fx_line, _
703 		      ("Value %ld not aligned by 2 for 9-bit PC-relative branch."), value);
704       mask = 0x1FF; /* Clip into 8-bit field FIXME I'm sure there is a more proper place for this */
705       value &= mask;
706       number_to_chars_bigendian (where, (opcode | value), 2);
707       break;
708     case R_XGATE_PCREL_10:
709       if (value < -1024 || value > 1023)
710 	as_bad_where (fixP->fx_file, fixP->fx_line,
711 		      _("Value %ld too large for 10-bit PC-relative branch."), value);
712       result = ldiv (value, 2); /* from bytes to words */
713       value = result.quot;
714       if (result.rem)
715 	as_bad_where (fixP->fx_file, fixP->fx_line, _
716 		      ("Value %ld not aligned by 2 for 10-bit PC-relative branch."), value);
717       mask = 0x3FF; /* Clip into 9-bit field FIXME I'm sure there is a more proper place for this */
718       value &= mask;
719       number_to_chars_bigendian (where, (opcode | value), 2);
720       break;
721     case BFD_RELOC_XGATE_IMM8_HI:
722       if (value < -65537 || value > 65535)
723 	as_bad_where (fixP->fx_file, fixP->fx_line,
724 		      _("Value out of 16-bit range."));
725       value >>= 8;
726       value &= 0x00ff;
727       bfd_putb16 ((bfd_vma) value | opcode, (void *) where);
728       break;
729     case BFD_RELOC_XGATE_24:
730     case BFD_RELOC_XGATE_IMM8_LO:
731       if (value < -65537 || value > 65535)
732 	as_bad_where (fixP->fx_file, fixP->fx_line,
733 		      _("Value out of 16-bit range."));
734       value &= 0x00ff;
735       bfd_putb16 ((bfd_vma) value | opcode, (void *) where);
736       break;
737     case BFD_RELOC_XGATE_IMM3:
738       if (value < 0 || value > 7)
739 	as_bad_where (fixP->fx_file, fixP->fx_line,
740 		      _("Value out of 3-bit range."));
741       value <<= 8; /* make big endian */
742       number_to_chars_bigendian (where, (opcode | value), 2);
743       break;
744     case BFD_RELOC_XGATE_IMM4:
745       if (value < 0 || value > 15)
746 	as_bad_where (fixP->fx_file, fixP->fx_line,
747 		      _("Value out of 4-bit range."));
748       value <<= 4; /* align the operand bits */
749       number_to_chars_bigendian (where, (opcode | value), 2);
750       break;
751     case BFD_RELOC_XGATE_IMM5:
752       if (value < 0 || value > 31)
753 	as_bad_where (fixP->fx_file, fixP->fx_line,
754 		      _("Value out of 5-bit range."));
755       value <<= 5; /* align the operand bits */
756       number_to_chars_bigendian (where, (opcode | value), 2);
757       break;
758     case BFD_RELOC_8:
759       ((bfd_byte *) where)[0] = (bfd_byte) value;
760       break;
761     case BFD_RELOC_32:
762       bfd_putb32 ((bfd_vma) value, (unsigned char *) where);
763       break;
764     case BFD_RELOC_16:
765       bfd_putb16 ((bfd_vma) value, (unsigned char *) where);
766       break;
767     default:
768       as_fatal (_("Line %d: unknown relocation type: 0x%x."), fixP->fx_line,
769 		fixP->fx_r_type);
770       break;
771     }
772 }
773 
774 /* See whether we need to force a relocation into the output file.  */
775 
776 int
777 tc_xgate_force_relocation (fixS * fixP)
778 {
779   if (fixP->fx_r_type == BFD_RELOC_XGATE_RL_GROUP)
780     return 1;
781   return generic_force_reloc (fixP);
782 }
783 
784 /* Here we decide which fixups can be adjusted to make them relative
785    to the beginning of the section instead of the symbol.  Basically
786    we need to make sure that the linker relaxation is done
787    correctly, so in some cases we force the original symbol to be
788    used.  */
789 
790 int
791 tc_xgate_fix_adjustable (fixS * fixP)
792 {
793   switch (fixP->fx_r_type)
794     {
795       /* For the linker relaxation to work correctly, these relocs
796 	 need to be on the symbol itself.  */
797     case BFD_RELOC_16:
798     case BFD_RELOC_XGATE_RL_JUMP:
799     case BFD_RELOC_XGATE_RL_GROUP:
800     case BFD_RELOC_VTABLE_INHERIT:
801     case BFD_RELOC_VTABLE_ENTRY:
802     case BFD_RELOC_32:
803       return 0;
804     default:
805       return 1;
806     }
807 }
808 
809 void
810 md_convert_frag (bfd * abfd ATTRIBUTE_UNUSED,
811 		 asection * sec ATTRIBUTE_UNUSED,
812 		 fragS * fragP ATTRIBUTE_UNUSED)
813 {
814   as_bad (("md_convert_frag not implemented yet"));
815   abort ();
816 }
817 
818 /* Set the ELF specific flags.  */
819 
820 void
821 xgate_elf_final_processing (void)
822 {
823   elf_flags |= EF_XGATE_MACH;
824   elf_elfheader (stdoutput)->e_flags &= ~EF_XGATE_ABI;
825   elf_elfheader (stdoutput)->e_flags |= elf_flags;
826 }
827 
828 static inline char *
829 skip_whitespace (char *s)
830 {
831   while (*s == ' ' || *s == '\t' || *s == '(' || *s == ')')
832     s++;
833 
834   return s;
835 }
836 
837 /* Extract a word (continuous alpha-numeric chars) from the input line.  */
838 
839 static char *
840 extract_word (char *from, char *to, int limit)
841 {
842   char *op_end;
843   int size = 0;
844 
845   /* Drop leading whitespace.  */
846   from = skip_whitespace (from);
847   *to = 0;
848   /* Find the op code end.  */
849   for (op_end = from; *op_end != 0 && is_part_of_name (*op_end);)
850     {
851       to[size++] = *op_end++;
852       if (size + 1 >= limit)
853         break;
854     }
855   to[size] = 0;
856   return op_end;
857 }
858 
859 static char *
860 xgate_new_instruction (int size)
861 {
862   char *f = frag_more (size);
863   dwarf2_emit_insn (size);
864   return f;
865 }
866 
867 unsigned short
868 xgate_apply_operand (unsigned short new_mask,
869 		     unsigned short *availiable_mask_bits,
870 		     unsigned short mask,
871 		     unsigned char n_bits)
872 {
873   unsigned short n_shifts;
874   unsigned int n_drop_bits;
875 
876   /* Shift until you find an available operand bit "1" and record the number of shifts.  */
877   for (n_shifts = 0;
878        !(*availiable_mask_bits & SIXTEENTH_BIT) && n_shifts < 16;
879        n_shifts++)
880     *availiable_mask_bits <<= 1;
881 
882   /* Shift for the number of bits your operand requires while bits are available.  */
883   for (n_drop_bits = n_bits;
884        n_drop_bits && (*availiable_mask_bits & SIXTEENTH_BIT);
885        --n_drop_bits)
886     *availiable_mask_bits <<= 1;
887 
888   if (n_drop_bits)
889     as_bad (_(":operand has too many bits"));
890   *availiable_mask_bits >>= n_shifts + n_bits;
891   if ((n_drop_bits == 0) && (*availiable_mask_bits == 0))
892     {
893       oper_check = 1; /* flag operand check as good */
894     }
895   new_mask <<= N_BITS_IN_WORD - (n_shifts + n_bits);
896   mask |= new_mask;
897   return mask;
898 }
899 
900 /* Parse ordinary expression.  */
901 
902 static char *
903 xgate_parse_exp (char *s, expressionS * op)
904 {
905   input_line_pointer = s;
906   expression(op);
907   if (op->X_op == O_absent)
908     as_bad (_("missing operand"));
909   return input_line_pointer;
910 }
911 
912 static int
913 cmp_opcode (struct xgate_opcode *op1, struct xgate_opcode *op2)
914 {
915   return strcmp (op1->name, op2->name);
916 }
917 
918 static struct xgate_opcode *
919 xgate_find_match (struct xgate_opcode_handle *opcode_handle,
920 		  int numberOfModes,
921 		  unsigned int sh_format)
922 {
923   int i;
924 
925   if (numberOfModes == 0)
926     return opcode_handle->opc0[0];
927 
928   for (i = 0; i <= numberOfModes; i++)
929     if (opcode_handle->opc0[i]->sh_format & sh_format)
930       return opcode_handle->opc0[i];
931 
932   return NULL;
933 }
934 
935 /* Because we are dealing with two different core that view the system
936    memory with different offsets, we must differentiate what core a
937    symbol belongs to, in order for the linker to cross-link.  */
938 
939 int
940 xgate_frob_symbol (symbolS *sym)
941 {
942   asymbol *bfdsym;
943   elf_symbol_type *elfsym;
944 
945   bfdsym = symbol_get_bfdsym (sym);
946   elfsym = elf_symbol_from (bfd_asymbol_bfd (bfdsym), bfdsym);
947 
948   gas_assert(elfsym);
949 
950   /* Mark the symbol as being *from XGATE  */
951   elfsym->internal_elf_sym.st_target_internal = 1;
952 
953   return 0;
954 }
955 
956 unsigned int
957 xgate_get_operands (char *line, s_operand oprs[])
958 {
959   int num_operands;
960 
961   /* If there are no operands, then it must be inherent.  */
962   if (*line == 0 || *line == '\n' || *line == '\r')
963     return XG_INH;
964 
965   for (num_operands = 0; strlen (line) && (num_operands < MAX_NUM_OPERANDS);
966       num_operands++)
967     {
968       line = skip_whitespace (line);
969       if (*line == '#')
970         line++;
971 
972       oprs[num_operands].mod = xgate_determine_modifiers (&line);
973 
974       if ((oprs[num_operands].reg = reg_name_search (line)) == REG_NONE)
975         line = xgate_parse_exp (line, &oprs[num_operands].exp);
976 
977       /* skip to next operand */
978       while (*line != 0)
979         {
980           if (*line == ',')
981             {
982               line++;
983               break;
984             }
985           line++;
986         }
987     }
988 
989   if (num_operands > MAX_NUM_OPERANDS)
990     return 0;
991 
992   switch (num_operands)
993     {
994   case 1:
995     if (oprs[0].reg >= REG_R0 && oprs[0].reg <= REG_R7)
996       return XG_R;
997     if (oprs[0].reg == REG_NONE)
998       return XG_I;
999     break;
1000   case 2:
1001     if (oprs[0].reg >= REG_R0 && oprs[0].reg <= REG_R7)
1002       {
1003         if (oprs[1].reg >= REG_R0 && oprs[1].reg <= REG_R7)
1004           return XG_R_R;
1005         if (oprs[1].reg == REG_CCR)
1006           return XG_R_C;
1007         if (oprs[1].reg == REG_PC)
1008           return XG_R_P;
1009         if (oprs[1].reg == REG_NONE)
1010           return XG_R_I;
1011       }
1012     if (oprs[0].reg == REG_CCR)
1013       return XG_C_R;
1014     break;
1015   case 3:
1016     if (oprs[0].reg >= REG_R0 && oprs[0].reg <= REG_R7)
1017       {
1018         if (oprs[1].reg >= REG_R0 && oprs[1].reg <= REG_R7)
1019           {
1020             if (oprs[2].reg >= REG_R0 && oprs[2].reg <= REG_R7)
1021               return XG_R_R_R;
1022             if (oprs[2].reg >= REG_NONE)
1023               return XG_R_R_I;
1024           }
1025       }
1026     break;
1027   default:
1028     as_bad (_("unknown operand format"));
1029     break;
1030     }
1031 
1032   return 0;
1033 }
1034 
1035 /* reg_name_search() finds the register number given its name.
1036    Returns the register number or REG_NONE on failure.  */
1037 static register_id
1038 reg_name_search (char *name)
1039 {
1040   if (strncasecmp (name, "r0", 2) == 0)
1041     return REG_R0;
1042   if (strncasecmp (name, "r1", 2) == 0)
1043     return REG_R1;
1044   if (strncasecmp (name, "r2", 2) == 0)
1045     return REG_R2;
1046   if (strncasecmp (name, "r3", 2) == 0)
1047     return REG_R3;
1048   if (strncasecmp (name, "r4", 2) == 0)
1049     return REG_R4;
1050   if (strncasecmp (name, "r5", 2) == 0)
1051     return REG_R5;
1052   if (strncasecmp (name, "r6", 2) == 0)
1053     return REG_R6;
1054   if (strncasecmp (name, "r7", 2) == 0)
1055     return REG_R7;
1056   if (strncasecmp (name, "pc", 2) == 0)
1057     return REG_PC;
1058   if (strncasecmp (name, "ccr", 3) == 0)
1059     return REG_CCR;
1060   return REG_NONE;
1061 }
1062 
1063 /* Parse operand modifiers such as inc/dec/hi/low.  */
1064 
1065 op_modifiers
1066 xgate_determine_modifiers(char **line)
1067 {
1068   char *local_line = line[0];
1069 
1070   if (strncasecmp (local_line, "%hi", 3) == 0)
1071     {
1072       *line += 3;
1073       return MOD_LOAD_HIGH;
1074     }
1075   if (strncasecmp (local_line, "%lo", 3) == 0)
1076     {
1077       *line += 3;
1078       return MOD_LOAD_LOW;
1079     }
1080   if (*(local_line + 2) == '+')
1081         return MOD_POSTINC;
1082   if (strncasecmp (local_line, "-r", 2) == 0)
1083     {
1084       *line += 1;
1085       return MOD_PREDEC;
1086    }
1087   return MOD_NONE;
1088 }
1089 
1090 /* Parse instruction operands.  */
1091 
1092 void
1093 xgate_scan_operands (struct xgate_opcode *opcode, s_operand oprs[])
1094 {
1095   char *frag = xgate_new_instruction (opcode->size);
1096   int where = frag - frag_now->fr_literal;
1097   char *op = opcode->constraints;
1098   unsigned int bin = (int) opcode->bin_opcode;
1099   unsigned short oper_mask = 0;
1100   int operand_bit_length = 0;
1101   unsigned int operand = 0;
1102   char n_operand_bits = 0;
1103   char first_operand_equals_second = 0;
1104   int i = 0;
1105   char c = 0;
1106 
1107   /* Generate available operand bits mask.  */
1108   for (i = 0; (c = opcode->format[i]); i++)
1109     {
1110       if (ISDIGIT (c) || (c == 's'))
1111         {
1112           oper_mask <<= 1;
1113         }
1114       else
1115         {
1116           oper_mask <<= 1;
1117           oper_mask += 1;
1118           n_operand_bits++;
1119         }
1120     }
1121 
1122   /* Parse first operand.  */
1123   if (*op)
1124     {
1125       if (*op == '=')
1126         {
1127           first_operand_equals_second = 1;
1128           ++op;
1129         }
1130       operand = xgate_parse_operand (opcode, &operand_bit_length, where, &op, oprs[0]);
1131       ++op;
1132       bin = xgate_apply_operand (operand, &oper_mask, bin, operand_bit_length);
1133 
1134       if(first_operand_equals_second)
1135         bin = xgate_apply_operand (operand, &oper_mask, bin, operand_bit_length);
1136       /* Parse second operand.  */
1137       if (*op)
1138         {
1139           if (*op == ',')
1140             ++op;
1141           if (first_operand_equals_second)
1142             {
1143               bin = xgate_apply_operand (operand, &oper_mask, bin,
1144                   operand_bit_length);
1145               ++op;
1146             }
1147           else
1148             {
1149               operand = xgate_parse_operand (opcode, &operand_bit_length, where,
1150                   &op, oprs[1]);
1151               bin = xgate_apply_operand (operand, &oper_mask, bin,
1152                   operand_bit_length);
1153               ++op;
1154             }
1155         }
1156       /* Parse the third register.  */
1157       if (*op)
1158         {
1159           if (*op == ',')
1160             ++op;
1161           operand = xgate_parse_operand (opcode, &operand_bit_length, where, &op,
1162               oprs[2]);
1163           bin = xgate_apply_operand (operand, &oper_mask, bin,
1164               operand_bit_length);
1165         }
1166     }
1167   if (opcode->size == 2 && fixup_required)
1168     {
1169       bfd_putl16 (bin, frag);
1170     }
1171   else if ((opcode->sh_format & XG_PCREL))
1172     {
1173       /* Write our data to a frag for further processing.  */
1174       bfd_putl16 (opcode->bin_opcode, frag);
1175     }
1176   else
1177     {
1178       /* Apply operand mask(s)to bin opcode and write the output.  */
1179       /* Since we are done write this frag in xgate BE format.  */
1180       number_to_chars_bigendian (frag, bin, opcode->size);
1181     }
1182   prev = bin;
1183   return;
1184 }
1185 
1186 static unsigned int
1187 xgate_parse_operand (struct xgate_opcode *opcode,
1188                int *bit_width,
1189                int where,
1190                char **op_con,
1191                s_operand operand)
1192 {
1193   fixS *fixp = 0;
1194   char *op_constraint = *op_con;
1195   unsigned int op_mask = 0;
1196   unsigned int pp_fix = 0;
1197   unsigned short max_size = 0;
1198   int i;
1199 
1200   *bit_width = 0;
1201   /* Reset.  */
1202 
1203   switch (*op_constraint)
1204     {
1205     case '+': /* Indexed register operand +/- or plain r.  */
1206       /* Default to neither inc or dec.  */
1207       pp_fix = 0;
1208       *bit_width = 5;
1209 
1210       if (operand.reg == REG_NONE)
1211             as_bad (_(": expected register name r0-r7 ") );
1212       op_mask = operand.reg;
1213       if(operand.mod == MOD_POSTINC)
1214         pp_fix = INCREMENT;
1215       if(operand.mod == MOD_PREDEC)
1216         pp_fix = DECREMENT;
1217       op_mask <<= 2;
1218       op_mask |= pp_fix;
1219       break;
1220 
1221     case 'r': /* Register operand.  */
1222     if (operand.reg == REG_NONE)
1223       as_bad (_(": expected register name r0-r7 "));
1224 
1225     *bit_width = 3;
1226 
1227     op_mask = operand.reg;
1228       break;
1229 
1230     case 'i': /* Immediate value or expression expected.  */
1231       /* Advance the original format pointer.  */
1232       (*op_con)++;
1233       op_constraint++;
1234       if (ISDIGIT (*op_constraint))
1235         {
1236           *bit_width = (int) *op_constraint - '0';
1237         }
1238       else if (*op_constraint == 'a')
1239         {
1240           *bit_width = 0x0A;
1241         }
1242       else if (*op_constraint == 'f')
1243         {
1244           *bit_width = 0x0F;
1245         }
1246       /* http://tigcc.ticalc.org/doc/gnuasm.html#SEC31 */
1247       if (operand.exp.X_op == O_constant)
1248         {
1249           op_mask = operand.exp.X_add_number;
1250           if (((opcode->name[strlen (opcode->name) - 1] == 'l') && autoHiLo)
1251               || operand.mod == MOD_LOAD_LOW)
1252             {
1253               op_mask &= 0x00FF;
1254             }
1255           else if (((opcode->name[strlen (opcode->name) - 1]) == 'h'
1256                    && autoHiLo) || operand.mod == MOD_LOAD_HIGH)
1257             {
1258               op_mask >>= 8;
1259             }
1260 
1261           /* Make sure it fits.  */
1262           for (i = *bit_width; i; i--)
1263             {
1264               max_size <<= 1;
1265               max_size += 1;
1266             }
1267           if (op_mask > max_size)
1268             as_bad (_(":operand value(%d) too big for constraint"), op_mask);
1269         }
1270       else
1271         {
1272           /* Should be BFD_RELOC_XGATE_IMM8_LO instead of BFD_RELOC_XGATE_24
1273              TODO fix.  */
1274           fixup_required = 1;
1275           if (*op_constraint == '8')
1276             {
1277               if (((opcode->name[strlen (opcode->name) - 1] == 'l')
1278                   && autoHiLo) || operand.mod == MOD_LOAD_LOW)
1279                 {
1280                     fixp = fix_new_exp (frag_now, where, 2, &operand.exp, FALSE,
1281                                       BFD_RELOC_XGATE_24);
1282                 }
1283               else if (((opcode->name[strlen (opcode->name) - 1]) == 'h'
1284                   && autoHiLo) || operand.mod == MOD_LOAD_HIGH )
1285                 {
1286                     fixp = fix_new_exp (frag_now, where, 2, &operand.exp, FALSE,
1287                                       BFD_RELOC_XGATE_IMM8_HI);
1288                 }
1289               else
1290                 {
1291                   as_bad (_("you must use a hi/lo directive or 16-bit macro "
1292                       "to load a 16-bit value."));
1293                   break;
1294                 }
1295               fixp->fx_pcrel_adjust = 0;
1296             }
1297           else if (*op_constraint == '5')
1298             {
1299               fixp = fix_new_exp (frag_now, where, 2, &operand.exp, FALSE,
1300                                   BFD_RELOC_XGATE_IMM5);
1301               fixp->fx_pcrel_adjust = 0;
1302             }
1303           else if (*op_constraint == '4')
1304             {
1305               fixp = fix_new_exp (frag_now, where, 2, &operand.exp, FALSE,
1306                                   BFD_RELOC_XGATE_IMM4);
1307               fixp->fx_pcrel_adjust = 0;
1308             }
1309           else if (*op_constraint == '3')
1310             {
1311             fixp = fix_new_exp (frag_now, where, 2, &operand.exp, FALSE,
1312                 BFD_RELOC_XGATE_IMM3);
1313             fixp->fx_pcrel_adjust = 0;
1314           }
1315         else
1316           {
1317             as_bad (_(":unknown relocation constraint size"));
1318           }
1319       }
1320       break;
1321 
1322     case 'c': /* CCR register expected.  */
1323       *bit_width = 0;
1324       if (operand.reg != REG_CCR)
1325             as_bad (_(": expected register name ccr "));
1326       break;
1327 
1328     case 'p': /* PC register expected.  */
1329       *bit_width = 0;
1330             if (operand.reg != REG_PC)
1331                   as_bad (_(": expected register name pc "));
1332       break;
1333 
1334     case 'b': /* Branch expected.  */
1335       (*op_con)++;
1336       op_constraint++;
1337 
1338       if (operand.exp.X_op != O_register)
1339         {
1340           if (*op_constraint == '9')
1341             {
1342               fixp = fix_new_exp (frag_now, where, 2, &operand.exp, TRUE,
1343                                   R_XGATE_PCREL_9);
1344               fixp->fx_pcrel_adjust = 1;
1345             }
1346           else if (*op_constraint == 'a')
1347             {
1348               fixp = fix_new_exp (frag_now, where, 2, &operand.exp, TRUE,
1349                                   R_XGATE_PCREL_10);
1350               fixp->fx_pcrel_adjust = 1;
1351             }
1352         }
1353       else
1354         {
1355           as_fatal (_("Operand `%x' not recognized in fixup8."), operand.exp.X_op);
1356         }
1357       break;
1358     case '?':
1359       break;
1360 
1361     default:
1362       as_bad (_("unknown constraint `%c'"), *op_constraint);
1363       break;
1364     }
1365   return op_mask;
1366 }
1367