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