xref: /netbsd-src/external/gpl3/binutils/dist/gas/config/tc-dlx.c (revision c3ab26950fe8540fb553d1d1dcae454bc98e5a25)
1 /* tc-dlx.c -- Assemble for the DLX
2    Copyright 2002, 2003, 2004, 2005, 2007, 2009, 2010, 2012
3    Free Software Foundation, Inc.
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 the Free
19    Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
20    02110-1301, USA.  */
21 
22 /* Initially created by Kuang Hwa Lin, 3/20/2002.  */
23 
24 #include "as.h"
25 #include "safe-ctype.h"
26 #include "tc-dlx.h"
27 #include "opcode/dlx.h"
28 
29 /* Make it easier to clone this machine desc into another one.  */
30 #define	machine_opcode      dlx_opcode
31 #define	machine_opcodes     dlx_opcodes
32 #define	machine_ip          dlx_ip
33 #define	machine_it          dlx_it
34 
35 #define NO_RELOC            BFD_RELOC_NONE
36 #define RELOC_DLX_REL26     BFD_RELOC_DLX_JMP26
37 #define RELOC_DLX_16        BFD_RELOC_16
38 #define RELOC_DLX_REL16     BFD_RELOC_16_PCREL_S2
39 #define RELOC_DLX_HI16      BFD_RELOC_HI16_S
40 #define RELOC_DLX_LO16      BFD_RELOC_LO16
41 #define RELOC_DLX_VTINHERIT BFD_RELOC_VTABLE_INHERIT
42 #define RELOC_DLX_VTENTRY   BFD_RELOC_VTABLE_ENTRY
43 
44 /* handle of the OPCODE hash table */
45 static struct hash_control *op_hash = NULL;
46 
47 struct machine_it
48 {
49   char *error;
50   unsigned long opcode;
51   struct nlist *nlistp;
52   expressionS exp;
53   int pcrel;
54   int size;
55   int reloc_offset;		/* Offset of reloc within insn.  */
56   int reloc;
57   int HI;
58   int LO;
59 }
60 the_insn;
61 
62 /* This array holds the chars that always start a comment.  If the
63    pre-processor is disabled, these aren't very useful.  */
64 const char comment_chars[] = ";";
65 
66 /* This array holds the chars that only start a comment at the beginning of
67    a line.  If the line seems to have the form '# 123 filename'
68    .line and .file directives will appear in the pre-processed output.  */
69 /* Note that input_file.c hand checks for '#' at the beginning of the
70    first line of the input file.  This is because the compiler outputs
71    #NO_APP at the beginning of its output.  */
72 /* Also note that comments like this one will always work.  */
73 const char line_comment_chars[] = "#";
74 
75 /* We needed an unused char for line separation to work around the
76    lack of macros, using sed and such.  */
77 const char line_separator_chars[] = "@";
78 
79 /* Chars that can be used to separate mant from exp in floating point nums.  */
80 const char EXP_CHARS[] = "eE";
81 
82 /* Chars that mean this number is a floating point constant.
83    As in 0f12.456
84    or    0d1.2345e12.  */
85 const char FLT_CHARS[] = "rRsSfFdDxXpP";
86 
87 static void
88 insert_sreg (char *regname, int regnum)
89 {
90   /* Must be large enough to hold the names of the special registers.  */
91   char buf[80];
92   int i;
93 
94   symbol_table_insert (symbol_new (regname, reg_section, (valueT) regnum,
95 				   &zero_address_frag));
96   for (i = 0; regname[i]; i++)
97     buf[i] = ISLOWER (regname[i]) ? TOUPPER (regname[i]) : regname[i];
98   buf[i] = '\0';
99 
100   symbol_table_insert (symbol_new (buf, reg_section, (valueT) regnum,
101 				   &zero_address_frag));
102 }
103 
104 /* Install symbol definitions for assorted special registers.
105    See MIPS Assembly Language Programmer's Guide page 1-4   */
106 
107 static void
108 define_some_regs (void)
109 {
110   /* Software representation.  */
111   insert_sreg ("zero",  0);
112   insert_sreg ("at",    1);
113   insert_sreg ("v0",    2);
114   insert_sreg ("v1",    3);
115   insert_sreg ("a0",    4);
116   insert_sreg ("a1",    5);
117   insert_sreg ("a2",    6);
118   insert_sreg ("a3",    7);
119   insert_sreg ("t0",    8);
120   insert_sreg ("t1",    9);
121   insert_sreg ("t2",    10);
122   insert_sreg ("t3",    11);
123   insert_sreg ("t4",    12);
124   insert_sreg ("t5",    13);
125   insert_sreg ("t6",    14);
126   insert_sreg ("t7",    15);
127   insert_sreg ("s0",    16);
128   insert_sreg ("s1",    17);
129   insert_sreg ("s2",    18);
130   insert_sreg ("s3",    19);
131   insert_sreg ("s4",    20);
132   insert_sreg ("s5",    21);
133   insert_sreg ("s6",    22);
134   insert_sreg ("s7",    23);
135   insert_sreg ("t8",    24);
136   insert_sreg ("t9",    25);
137   insert_sreg ("k0",    26);
138   insert_sreg ("k1",    27);
139   insert_sreg ("gp",    28);
140   insert_sreg ("sp",    29);
141   insert_sreg ("fp",    30);
142   insert_sreg ("ra",    31);
143   /* Special registers.  */
144   insert_sreg ("pc",    0);
145   insert_sreg ("npc",   1);
146   insert_sreg ("iad",   2);
147 }
148 
149 /* Subroutine check the string to match an register.  */
150 
151 static int
152 match_sft_register (char *name)
153 {
154 #define MAX_REG_NO  35
155 /* Currently we have 35 software registers defined -
156    we borrowed from MIPS.   */
157   static char *soft_reg[] =
158     {
159       "zero", "at", "v0", "v1", "a0", "a1", "a2", "a3",
160       "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7", "t8", "t9",
161       "s0", "s1", "s2", "s3", "s4", "s5", "s7", "k0", "k1",
162       "gp", "sp", "fp", "ra", "pc", "npc", "iad",
163       "EndofTab"  /* End of the Table indicator */
164     };
165   char low_name[21], *ptr;
166   int idx;
167 
168   for (ptr = name,idx = 0; *ptr != '\0'; ptr++)
169     low_name[idx++] = TOLOWER (*ptr);
170 
171   low_name[idx] = '\0';
172   idx = 0;
173 
174   while (idx < MAX_REG_NO && strcmp (soft_reg[idx], & low_name [0]))
175     idx += 1;
176 
177   return idx < MAX_REG_NO;
178 }
179 
180 /* Subroutine check the string to match an register.  */
181 
182 static int
183 is_ldst_registers (char *name)
184 {
185   char *ptr = name;
186 
187   /* The first character of the register name got to be either %, $, r of R.  */
188   if ((ptr[0] == '%' || ptr[0] == '$' || ptr[0] == 'r' || ptr[0] == 'R')
189       && ISDIGIT ((unsigned char) ptr[1]))
190     return 1;
191 
192   /* Now check the software register representation.  */
193   return match_sft_register (ptr);
194 }
195 
196 /* Subroutine of s_proc so targets can choose a different default prefix.
197    If DEFAULT_PREFIX is NULL, use the target's "leading char".  */
198 
199 static void
200 s_proc (int end_p)
201 {
202   /* Record the current function so that we can issue an error message for
203      misplaced .func,.endfunc, and also so that .endfunc needs no
204      arguments.  */
205   static char *current_name;
206   static char *current_label;
207 
208   if (end_p)
209     {
210       if (current_name == NULL)
211 	{
212 	  as_bad (_("missing .proc"));
213 	  ignore_rest_of_line ();
214 	  return;
215 	}
216 
217       current_name = current_label = NULL;
218       SKIP_WHITESPACE ();
219       while (!is_end_of_line[(unsigned char) *input_line_pointer])
220         input_line_pointer++;
221     }
222   else
223     {
224       char *name, *label;
225       char delim1, delim2;
226 
227       if (current_name != NULL)
228 	{
229 	  as_bad (_(".endfunc missing for previous .proc"));
230 	  ignore_rest_of_line ();
231 	  return;
232 	}
233 
234       name = input_line_pointer;
235       delim1 = get_symbol_end ();
236       name = xstrdup (name);
237       *input_line_pointer = delim1;
238       SKIP_WHITESPACE ();
239 
240       if (*input_line_pointer != ',')
241 	{
242 	  char leading_char = 0;
243 
244 	  leading_char = bfd_get_symbol_leading_char (stdoutput);
245 	  /* Missing entry point, use function's name with the leading
246 	     char prepended.  */
247 	  if (leading_char)
248 	    {
249 	      unsigned len = strlen (name) + 1;
250 	      label = xmalloc (len + 1);
251 	      label[0] = leading_char;
252 	      memcpy (label + 1, name, len);
253 	    }
254 	  else
255 	    label = name;
256 	}
257       else
258 	{
259 	  ++input_line_pointer;
260 	  SKIP_WHITESPACE ();
261 	  label = input_line_pointer;
262 	  delim2 = get_symbol_end ();
263 	  label = xstrdup (label);
264 	  *input_line_pointer = delim2;
265 	}
266 
267       current_name = name;
268       current_label = label;
269     }
270   demand_empty_rest_of_line ();
271 }
272 
273 /* This function is called once, at assembler startup time.  It should
274    set up all the tables, etc., that the MD part of the assembler will
275    need.  */
276 
277 void
278 md_begin (void)
279 {
280   const char *retval = NULL;
281   int lose = 0;
282   unsigned int i;
283 
284   /* Create a new hash table.  */
285   op_hash = hash_new ();
286 
287   /* Hash up all the opcodes for fast use later.  */
288   for (i = 0; i < num_dlx_opcodes; i++)
289     {
290       const char *name = machine_opcodes[i].name;
291 
292       retval = hash_insert (op_hash, name, (void *) &machine_opcodes[i]);
293 
294       if (retval != NULL)
295 	{
296 	  fprintf (stderr, _("internal error: can't hash `%s': %s\n"),
297 		   machine_opcodes[i].name, retval);
298 	  lose = 1;
299 	}
300     }
301 
302   if (lose)
303     as_fatal (_("Broken assembler.  No assembly attempted."));
304 
305   define_some_regs ();
306 }
307 
308 /* This function will check the opcode and return 1 if the opcode is one
309    of the load/store instruction, and it will fix the operand string to
310    the standard form so we can use the standard parse_operand routine.  */
311 
312 #define READ_OP     0x100
313 #define WRITE_OP    0x200
314 static char iBuf[81];
315 
316 static char *
317 dlx_parse_loadop (char * str)
318 {
319   char *ptr = str;
320   int   idx = 0;
321 
322   /* The last pair of ()/[] is the register, all other are the
323      reloc displacement, and if there is a register then it ought
324      to have a pair of ()/[]
325      This is not necessarily true, what if the load instruction come
326      without the register and with %hi/%lo modifier?  */
327   for (idx = 0; idx < 72 && ptr[idx] != '\0'; idx++)
328     ;
329 
330   if (idx == 72)
331     {
332     badoperand_load:
333       as_bad (_("Bad operand for a load instruction: <%s>"), str);
334       return NULL;
335     }
336   else
337     {
338       int i, pb = 0;
339       int m2 = 0;
340       char rs1[7], rd[7], endm, match = '0';
341       char imm[72];
342 
343       idx -= 1;
344       switch (str[idx])
345 	{
346 	case ')':
347 	  match = '(';
348 	  endm  = ')';
349 	  break;
350 	case ']':
351 	  match = '[';
352 	  endm  = ']';
353 	  break;
354 	default:
355 	  /* No register indicated, fill in zero.  */
356 	  rs1[0] = 'r';
357 	  rs1[1] = '0';
358 	  rs1[2] = '\0';
359 	  match  = 0;
360 	  endm = 0;
361 	  m2 = 1;
362 	}
363 
364       if (!m2)
365 	{
366 	  /* Searching for (/[ which will match the ]/).  */
367 	  for (pb = idx - 1; str[pb] != match; pb -= 1)
368 	    /* Match can only be either '[' or '(', if it is
369 	       '(' then this can be a normal expression, we'll treat
370 	       it as an operand.  */
371 	    if (str[pb] == endm || pb < (idx - 5))
372 	      goto load_no_rs1;
373 	  pb += 1;
374 
375 	  for (i = 0; (pb + i) < idx; i++)
376 	    rs1[i] = str[pb+i];
377 
378 	  rs1[i] = '\0';
379 
380 	  if (is_ldst_registers (& rs1[0]))
381 	    /* Point to the last character of the imm.  */
382 	    pb -= 1;
383 	  else
384 	    {
385 	    load_no_rs1:
386 	      if (match == '[')
387 		goto badoperand_load;
388 	      /* No register indicated, fill in zero and restore the imm.  */
389 	      rs1[0] = 'r';
390 	      rs1[1] = '0';
391 	      rs1[2] = '\0';
392 	      m2 = 1;
393 	    }
394 	}
395 
396       /* Duplicate the first register.  */
397       for (i = 0; i < 7 && str[i] != ','; i++)
398 	rd[i] = ptr[i];
399 
400       if (str[i] != ',')
401 	goto badoperand_load;
402       else
403 	rd[i] = '\0';
404 
405       /* Copy the immd.  */
406       if (m2)
407 	/* Put the '\0' back in.  */
408 	pb = idx + 1;
409 
410       for (i++, m2 = 0; i < pb; m2++,i++)
411 	imm[m2] = ptr[i];
412 
413       imm[m2] = '\0';
414 
415       /* Assemble the instruction to gas internal format.  */
416       for (i = 0; rd[i] != '\0'; i++)
417 	iBuf[i] = rd[i];
418 
419       iBuf[i++] = ',';
420 
421       for (pb = 0 ; rs1[pb] != '\0'; i++, pb++)
422 	iBuf[i] = rs1[pb];
423 
424       iBuf[i++] = ',';
425 
426       for (pb = 0; imm[pb] != '\0'; i++, pb++)
427 	iBuf[i] = imm[pb];
428 
429       iBuf[i] = '\0';
430       return iBuf;
431     }
432 }
433 
434 static char *
435 dlx_parse_storeop (char * str)
436 {
437   char *ptr = str;
438   int   idx = 0;
439 
440   /* Search for the ','.  */
441   for (idx = 0; idx < 72 && ptr[idx] != ','; idx++)
442     ;
443 
444   if (idx == 72)
445     {
446     badoperand_store:
447       as_bad (_("Bad operand for a store instruction: <%s>"), str);
448       return NULL;
449     }
450   else
451     {
452       /* idx now points to the ','.  */
453       int i, pb = 0;
454       int comma = idx;
455       int m2 = 0;
456       char rs1[7], rd[7], endm, match = '0';
457       char imm[72];
458 
459       /* Now parse the '(' and ')', and make idx point to ')'.  */
460       idx -= 1;
461       switch (str[idx])
462 	{
463 	case ')':
464 	  match = '(';
465 	  endm  = ')';
466 	  break;
467 	case ']':
468 	  match = '[';
469 	  endm  = ']';
470 	  break;
471 	default:
472 	  /* No register indicated, fill in zero.  */
473 	  rs1[0] = 'r';
474 	  rs1[1] = '0';
475 	  rs1[2] = '\0';
476 	  match  = 0;
477 	  endm = 0;
478 	  m2 = 1;
479 	}
480 
481       if (!m2)
482 	{
483 	  /* Searching for (/[ which will match the ]/).  */
484 	  for (pb = idx - 1; str[pb] != match; pb -= 1)
485 	    if (pb < (idx - 5) || str[pb] == endm)
486 	      goto store_no_rs1;
487 	  pb += 1;
488 
489 	  for (i = 0; (pb + i) < idx; i++)
490 	    rs1[i] = str[pb + i];
491 
492 	  rs1[i] = '\0';
493 
494 	  if (is_ldst_registers (& rs1[0]))
495 	    /* Point to the last character of the imm.  */
496 	    pb -= 1;
497 	  else
498 	    {
499 	    store_no_rs1:
500 	      if (match == '[')
501 		goto badoperand_store;
502 
503 	      /* No register indicated, fill in zero and restore the imm.  */
504 	      rs1[0] = 'r';
505 	      rs1[1] = '0';
506 	      rs1[2] = '\0';
507 	      pb = comma;
508 	    }
509 	}
510       else
511 	/* No register was specified.  */
512 	pb = comma;
513 
514       /* Duplicate the first register.  */
515       for (i = comma + 1; (str[i] == ' ' || str[i] == '\t'); i++)
516 	;
517 
518       for (m2 = 0; (m2 < 7 && str[i] != '\0'); i++, m2++)
519 	{
520 	  if (str[i] != ' ' && str[i] != '\t')
521 	    rd[m2] = str[i];
522 	  else
523 	    goto badoperand_store;
524 	}
525 
526       if (str[i] != '\0')
527 	goto badoperand_store;
528       else
529 	rd[m2] = '\0';
530 
531       /* Copy the immd.  */
532       for (i = 0; i < pb; i++)
533 	imm[i] = ptr[i];
534 
535       imm[i] = '\0';
536 
537       /* Assemble the instruction to gas internal format.  */
538       for (i = 0; rd[i] != '\0'; i++)
539 	iBuf[i] = rd[i];
540       iBuf[i++] = ',';
541       for (pb = 0 ; rs1[pb] != '\0'; i++, pb++)
542 	iBuf[i] = rs1[pb];
543       iBuf[i++] = ',';
544       for (pb = 0; imm[pb] != '\0'; i++, pb++)
545 	iBuf[i] = imm[pb];
546       iBuf[i] = '\0';
547       return iBuf;
548     }
549 }
550 
551 static char *
552 fix_ld_st_operand (unsigned long opcode, char* str)
553 {
554   /* Check the opcode.  */
555   switch ((int) opcode)
556     {
557     case  LBOP:
558     case  LBUOP:
559     case  LSBUOP:
560     case  LHOP:
561     case  LHUOP:
562     case  LSHUOP:
563     case  LWOP:
564     case  LSWOP:
565       return dlx_parse_loadop (str);
566     case  SBOP:
567     case  SHOP:
568     case  SWOP:
569       return dlx_parse_storeop (str);
570     default:
571       return str;
572     }
573 }
574 
575 static int
576 hilo_modifier_ok (char *s)
577 {
578   char *ptr = s;
579   int   idx, count = 1;
580 
581   if (*ptr != '(')
582     return 1;
583 
584   for (idx = 1; ptr[idx] != '\0' && ptr[idx] != '[' && idx < 73; idx += 1)
585     {
586       if (count == 0)
587 	return count;
588 
589       if (ptr[idx] == '(')
590 	count += 1;
591 
592       if (ptr[idx] == ')')
593 	count -= 1;
594     }
595 
596   return (count == 0) ? 1:0;
597 }
598 
599 static char *
600 parse_operand (char *s, expressionS *operandp)
601 {
602   char *save = input_line_pointer;
603   char *new_pos;
604 
605   the_insn.HI = the_insn.LO = 0;
606 
607   /* Search for %hi and %lo, make a mark and skip it.  */
608   if (strncmp (s, "%hi", 3) == 0)
609     {
610       s += 3;
611       the_insn.HI = 1;
612     }
613   else
614     {
615       if (strncmp (s, "%lo", 3) == 0)
616 	{
617 	  s += 3;
618 	  the_insn.LO = 1;
619 	}
620       else
621 	the_insn.LO = 0;
622     }
623 
624   if (the_insn.HI || the_insn.LO)
625     {
626       if (!hilo_modifier_ok (s))
627 	as_bad (_("Expression Error for operand modifier %%hi/%%lo\n"));
628     }
629 
630   /* Check for the % and $ register representation    */
631   if ((s[0] == '%' || s[0] == '$' || s[0] == 'r' || s[0] == 'R')
632       && ISDIGIT ((unsigned char) s[1]))
633     {
634       /* We have a numeric register expression.  No biggy.  */
635       s += 1;
636       input_line_pointer = s;
637       (void) expression (operandp);
638       if (operandp->X_op != O_constant
639 	  || operandp->X_add_number > 31)
640 	as_bad (_("Invalid expression after %%%%\n"));
641       operandp->X_op = O_register;
642     }
643   else
644     {
645       /* Normal operand parsing.  */
646       input_line_pointer = s;
647       (void) expression (operandp);
648     }
649 
650   new_pos = input_line_pointer;
651   input_line_pointer = save;
652   return new_pos;
653 }
654 
655 /* Instruction parsing.  Takes a string containing the opcode.
656    Operands are at input_line_pointer.  Output is in the_insn.
657    Warnings or errors are generated.  */
658 
659 static void
660 machine_ip (char *str)
661 {
662   char *s;
663   const char *args;
664   struct machine_opcode *insn;
665   unsigned long opcode;
666   expressionS the_operand;
667   expressionS *operand = &the_operand;
668   unsigned int reg, reg_shift = 0;
669 
670   /* Fixup the opcode string to all lower cases, and also
671      allow numerical digits.  */
672   s = str;
673 
674   if (ISALPHA (*s))
675     for (; ISALNUM (*s); ++s)
676       if (ISUPPER (*s))
677 	*s = TOLOWER (*s);
678 
679   switch (*s)
680     {
681     case '\0':
682       break;
683 
684       /* FIXME-SOMEDAY more whitespace.  */
685     case ' ':
686       *s++ = '\0';
687       break;
688 
689     default:
690       as_bad (_("Unknown opcode: `%s'"), str);
691       return;
692     }
693 
694   /* Hash the opcode, insn will have the string from opcode table.
695      also initialized the_insn struct.  */
696   if ((insn = (struct machine_opcode *) hash_find (op_hash, str)) == NULL)
697     {
698       /* Handle the ret and return macro here.  */
699       if ((strcmp (str, "ret") == 0) || (strcmp (str, "return") == 0))
700 	{
701 	  memset (&the_insn, '\0', sizeof (the_insn));
702 	  the_insn.reloc = NO_RELOC;
703 	  the_insn.pcrel = 0;
704 	  the_insn.opcode =
705 	    (unsigned long)(JROP | 0x03e00000);    /* 0x03e00000 = r31 << 21 */
706 	}
707       else
708 	as_bad (_("Unknown opcode `%s'."), str);
709 
710       return;
711     }
712 
713   opcode = insn->opcode;
714   memset (&the_insn, '\0', sizeof (the_insn));
715   the_insn.reloc = NO_RELOC;
716   the_insn.pcrel = 0;
717 
718   /* Set the sip reloc HI16 flag.  */
719   if (!set_dlx_skip_hi16_flag (1))
720     as_bad (_("Can not set dlx_skip_hi16_flag"));
721 
722   /* Fix the operand string if it is one of load store instructions.  */
723   s = fix_ld_st_operand (opcode, s);
724 
725   /* Build the opcode, checking as we go to make sure that the
726      operands match.
727      If an operand matches, we modify the_insn or opcode appropriately,
728      and do a "continue".  If an operand fails to match, we "break".  */
729   if (insn->args[0] != '\0' && insn->args[0] != 'N')
730     {
731       /* Prime the pump.  */
732       if (*s == '\0')
733 	{
734 	  as_bad (_("Missing arguments for opcode <%s>."), str);
735 	  return;
736 	}
737       else
738 	s = parse_operand (s, operand);
739     }
740   else if (insn->args[0] == 'N')
741     {
742       /* Clean up the insn and done!  */
743       the_insn.opcode = opcode;
744       return;
745     }
746 
747   /* Parse through the args (this is from opcode table), *s point to
748      the current character of the instruction stream.  */
749   for (args = insn->args;; ++args)
750     {
751       switch (*args)
752 	{
753 	  /* End of Line.  */
754 	case '\0':
755 	  /* End of args.  */
756 	  if (*s == '\0')
757 	    {
758 	      /* We are truly done.  */
759 	      the_insn.opcode = opcode;
760 	      /* Clean up the HI and LO mark.  */
761 	      the_insn.HI = 0;
762 	      the_insn.LO = 0;
763 	      return;
764 	    }
765 
766 	  the_insn.HI = 0;
767 	  the_insn.LO = 0;
768 	  as_bad (_("Too many operands: %s"), s);
769 	  break;
770 
771 	  /* ',' Args separator */
772 	case ',':
773 	  /* Must match a comma.  */
774 	  if (*s++ == ',')
775 	    {
776 	      /* Parse next operand.  */
777 	      s = parse_operand (s, operand);
778 	      continue;
779 	    }
780 	  break;
781 
782 	  /* It can be a 'a' register or 'i' operand.  */
783 	case 'P':
784 	  /* Macro move operand/reg.  */
785 	  if (operand->X_op == O_register)
786 	    {
787 	      /* Its a register.  */
788 	      reg_shift = 21;
789 	      goto general_reg;
790 	    }
791 
792 	  /* The immediate 16 bits literal, bit 0-15.  */
793 	case 'i':
794 	  /* offset, unsigned.  */
795 	case 'I':
796 	  /* offset, signed.  */
797 	  if (operand->X_op == O_constant)
798 	    {
799 	      if (the_insn.HI)
800 		operand->X_add_number >>= 16;
801 
802 	      opcode |= operand->X_add_number & 0xFFFF;
803 
804 	      if (the_insn.HI && the_insn.LO)
805 		as_bad (_("Both the_insn.HI and the_insn.LO are set : %s"), s);
806 	      else
807 		{
808 		  the_insn.HI = 0;
809 		  the_insn.LO = 0;
810 		}
811 	      continue;
812 	    }
813 
814 	  the_insn.reloc        = (the_insn.HI) ? RELOC_DLX_HI16
815 	    : (the_insn.LO ? RELOC_DLX_LO16 : RELOC_DLX_16);
816 	  the_insn.reloc_offset = 2;
817 	  the_insn.size         = 2;
818 	  the_insn.pcrel        = 0;
819 	  the_insn.exp          = * operand;
820 	  the_insn.HI           = 0;
821 	  the_insn.LO           = 0;
822 	  continue;
823 
824 	case 'd':
825 	  /* offset, signed.  */
826 	  if (operand->X_op == O_constant)
827 	    {
828 	      opcode |= operand->X_add_number & 0xFFFF;
829 	      continue;
830 	    }
831 	  the_insn.reloc        = RELOC_DLX_REL16;
832 	  the_insn.reloc_offset = 0;    /* BIG-ENDIAN Byte 3 of insn.  */
833 	  the_insn.size         = 4;
834 	  the_insn.pcrel        = 1;
835 	  the_insn.exp          = *operand;
836 	  continue;
837 
838 	  /* The immediate 26 bits literal, bit 0-25.  */
839 	case 'D':
840 	  /* offset, signed.  */
841 	  if (operand->X_op == O_constant)
842 	    {
843 	      opcode |= operand->X_add_number & 0x3FFFFFF;
844 	      continue;
845 	    }
846 	  the_insn.reloc = RELOC_DLX_REL26;
847 	  the_insn.reloc_offset = 0;    /* BIG-ENDIAN Byte 3 of insn.  */
848 	  the_insn.size  = 4;
849 	  the_insn.pcrel = 1;
850 	  the_insn.exp = *operand;
851 	  continue;
852 
853 	  /* Type 'a' Register.  */
854 	case 'a':
855 	  /* A general register at bits 21-25, rs1.  */
856 	  reg_shift = 21;
857 	  goto general_reg;
858 
859 	  /* Type 'b' Register.  */
860 	case 'b':
861 	  /* A general register at bits 16-20, rs2/rd.  */
862 	  reg_shift = 16;
863 	  goto general_reg;
864 
865 	  /* Type 'c' Register.  */
866 	case 'c':
867 	  /* A general register at bits 11-15, rd.  */
868 	  reg_shift = 11;
869 
870 	general_reg:
871 	  know (operand->X_add_symbol == 0);
872 	  know (operand->X_op_symbol == 0);
873 	  reg = operand->X_add_number;
874 	  if (reg & 0xffffffe0)
875 	    as_fatal (_("failed regnum sanity check."));
876 	  else
877 	    /* Got the register, now figure out where it goes in the opcode.  */
878 	    opcode |= reg << reg_shift;
879 
880 	  switch (*args)
881 	    {
882 	    case 'a':
883 	    case 'b':
884 	    case 'c':
885 	    case 'P':
886 	      continue;
887 	    }
888 	  as_fatal (_("failed general register sanity check."));
889 	  break;
890 
891 	default:
892 	  BAD_CASE (*args);
893 	}
894 
895       /* Types or values of args don't match.  */
896       as_bad (_("Invalid operands"));
897       return;
898     }
899 }
900 
901 /* Assemble a single instruction.  Its label has already been handled
902    by the generic front end.  We just parse opcode and operands, and
903    produce the bytes of data and relocation.  */
904 
905 void
906 md_assemble (char *str)
907 {
908   char *toP;
909   fixS *fixP;
910   bit_fixS *bitP;
911 
912   know (str);
913   machine_ip (str);
914   toP = frag_more (4);
915   dwarf2_emit_insn (4);
916 
917   /* Put out the opcode.  */
918   md_number_to_chars (toP, the_insn.opcode, 4);
919 
920   /* Put out the symbol-dependent stuff.  */
921   if (the_insn.reloc != NO_RELOC)
922     {
923       fixP = fix_new_exp (frag_now,
924 			  (toP - frag_now->fr_literal + the_insn.reloc_offset),
925 			  the_insn.size, & the_insn.exp, the_insn.pcrel,
926 			  the_insn.reloc);
927 
928       /* Turn off complaints that the addend is
929 	 too large for things like foo+100000@ha.  */
930       switch (the_insn.reloc)
931 	{
932 	case RELOC_DLX_HI16:
933 	case RELOC_DLX_LO16:
934 	  fixP->fx_no_overflow = 1;
935 	  break;
936 	default:
937 	  break;
938 	}
939 
940       switch (fixP->fx_r_type)
941 	{
942 	case RELOC_DLX_REL26:
943 	  bitP = malloc (sizeof (bit_fixS));
944 	  bitP->fx_bit_size = 26;
945 	  bitP->fx_bit_offset = 25;
946 	  bitP->fx_bit_base = the_insn.opcode & 0xFC000000;
947 	  bitP->fx_bit_base_adj = 0;
948 	  bitP->fx_bit_max = 0;
949 	  bitP->fx_bit_min = 0;
950 	  bitP->fx_bit_add = 0x03FFFFFF;
951 	  fixP->fx_bit_fixP = bitP;
952 	  break;
953 	case RELOC_DLX_LO16:
954 	case RELOC_DLX_REL16:
955 	  bitP = malloc (sizeof (bit_fixS));
956 	  bitP->fx_bit_size = 16;
957 	  bitP->fx_bit_offset = 15;
958 	  bitP->fx_bit_base = the_insn.opcode & 0xFFFF0000;
959 	  bitP->fx_bit_base_adj = 0;
960 	  bitP->fx_bit_max = 0;
961 	  bitP->fx_bit_min = 0;
962 	  bitP->fx_bit_add = 0x0000FFFF;
963 	  fixP->fx_bit_fixP = bitP;
964 	  break;
965 	case RELOC_DLX_HI16:
966 	  bitP = malloc (sizeof (bit_fixS));
967 	  bitP->fx_bit_size = 16;
968 	  bitP->fx_bit_offset = 15;
969 	  bitP->fx_bit_base = the_insn.opcode & 0xFFFF0000;
970 	  bitP->fx_bit_base_adj = 0;
971 	  bitP->fx_bit_max = 0;
972 	  bitP->fx_bit_min = 0;
973 	  bitP->fx_bit_add = 0x0000FFFF;
974 	  fixP->fx_bit_fixP = bitP;
975 	  break;
976 	default:
977 	  fixP->fx_bit_fixP = NULL;
978 	  break;
979 	}
980     }
981 }
982 
983 /* This is identical to the md_atof in m68k.c.  I think this is right,
984    but I'm not sure.  Dlx will not use it anyway, so I just leave it
985    here for now.  */
986 
987 char *
988 md_atof (int type, char *litP, int *sizeP)
989 {
990   return ieee_md_atof (type, litP, sizeP, TRUE);
991 }
992 
993 /* Write out big-endian.  */
994 void
995 md_number_to_chars (char *buf, valueT val, int n)
996 {
997   number_to_chars_bigendian (buf, val, n);
998 }
999 
1000 bfd_boolean
1001 md_dlx_fix_adjustable (fixS *fixP)
1002 {
1003   /* We need the symbol name for the VTABLE entries.  */
1004   return (fixP->fx_r_type != BFD_RELOC_VTABLE_INHERIT
1005           && fixP->fx_r_type != BFD_RELOC_VTABLE_ENTRY);
1006 }
1007 
1008 void
1009 md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
1010 {
1011   long val = *valP;
1012   char *place = fixP->fx_where + fixP->fx_frag->fr_literal;
1013 
1014   switch (fixP->fx_r_type)
1015     {
1016     case RELOC_DLX_LO16:
1017     case RELOC_DLX_REL16:
1018       if (fixP->fx_bit_fixP != NULL)
1019 	{
1020 	  val = (val & 0x0000FFFF) | fixP->fx_bit_fixP->fx_bit_base;
1021 	  free (fixP->fx_bit_fixP);
1022 	  fixP->fx_bit_fixP = NULL;
1023 	}
1024 #ifdef DEBUG
1025       else
1026 	know ((fixP->fx_bit_fixP != NULL));
1027 #endif
1028       break;
1029 
1030     case RELOC_DLX_HI16:
1031       if (fixP->fx_bit_fixP != NULL)
1032 	{
1033 	  val = (val >> 16) | fixP->fx_bit_fixP->fx_bit_base;
1034 	  free (fixP->fx_bit_fixP);
1035 	  fixP->fx_bit_fixP = NULL;
1036 	}
1037 #ifdef DEBUG
1038       else
1039 	know ((fixP->fx_bit_fixP != NULL));
1040 #endif
1041       break;
1042 
1043     case RELOC_DLX_REL26:
1044       if (fixP->fx_bit_fixP != NULL)
1045 	{
1046 	  val = (val & 0x03FFFFFF) | fixP->fx_bit_fixP->fx_bit_base;
1047 	  free (fixP->fx_bit_fixP);
1048 	  fixP->fx_bit_fixP = NULL;
1049 	}
1050 #ifdef DEBUG
1051       else
1052 	know ((fixP->fx_bit_fixP != NULL));
1053 #endif
1054       break;
1055 
1056     case BFD_RELOC_VTABLE_INHERIT:
1057       /* This borrowed from tc-ppc.c on a whim.  */
1058       fixP->fx_done = 0;
1059       if (fixP->fx_addsy
1060 	  && !S_IS_DEFINED (fixP->fx_addsy)
1061 	  && !S_IS_WEAK (fixP->fx_addsy))
1062 	S_SET_WEAK (fixP->fx_addsy);
1063       return;
1064 
1065     case BFD_RELOC_VTABLE_ENTRY:
1066       fixP->fx_done = 0;
1067       return;
1068 
1069     default:
1070       break;
1071     }
1072 
1073   number_to_chars_bigendian (place, val, fixP->fx_size);
1074   if (fixP->fx_addsy == NULL)
1075     fixP->fx_done = 1;
1076 }
1077 
1078 const char *md_shortopts = "";
1079 
1080 struct option md_longopts[] =
1081   {
1082     {NULL, no_argument, NULL, 0}
1083   };
1084 
1085 size_t md_longopts_size = sizeof (md_longopts);
1086 
1087 int
1088 md_parse_option (int c     ATTRIBUTE_UNUSED,
1089 		 char *arg ATTRIBUTE_UNUSED)
1090 {
1091   return 0;
1092 }
1093 
1094 void
1095 md_show_usage (FILE *stream ATTRIBUTE_UNUSED)
1096 {
1097 }
1098 
1099 /* This is called when a line is unrecognized.  */
1100 
1101 int
1102 dlx_unrecognized_line (int c)
1103 {
1104   int lab;
1105   char *s;
1106 
1107   if (c != '$' || ! ISDIGIT ((unsigned char) input_line_pointer[0]))
1108     return 0;
1109 
1110   s = input_line_pointer;
1111 
1112   lab = 0;
1113   while (ISDIGIT ((unsigned char) *s))
1114     {
1115       lab = lab * 10 + *s - '0';
1116       ++s;
1117     }
1118 
1119   if (*s != ':')
1120     /* Not a label definition.  */
1121     return 0;
1122 
1123   if (dollar_label_defined (lab))
1124     {
1125       as_bad (_("label \"$%d\" redefined"), lab);
1126       return 0;
1127     }
1128 
1129   define_dollar_label (lab);
1130   colon (dollar_label_name (lab, 0));
1131   input_line_pointer = s + 1;
1132 
1133   return 1;
1134 }
1135 
1136 /* Default the values of symbols known that should be "predefined".  We
1137    don't bother to predefine them unless you actually use one, since there
1138    are a lot of them.  */
1139 
1140 symbolS *
1141 md_undefined_symbol (char *name ATTRIBUTE_UNUSED)
1142 {
1143   return NULL;
1144 }
1145 
1146 /* Parse an operand that is machine-specific, the function was called
1147    in expr.c by operand() function, when everything failed before it
1148    call a quit.  */
1149 
1150 void
1151 md_operand (expressionS* expressionP)
1152 {
1153   /* Check for the #number representation    */
1154   if (input_line_pointer[0] == '#' &&
1155       ISDIGIT ((unsigned char) input_line_pointer[1]))
1156     {
1157       /* We have a numeric number expression.  No biggy.  */
1158       input_line_pointer += 1;	/* Skip # */
1159 
1160       (void) expression (expressionP);
1161 
1162       if (expressionP->X_op != O_constant)
1163 	as_bad (_("Invalid expression after # number\n"));
1164     }
1165 
1166   return;
1167 }
1168 
1169 /* Round up a section size to the appropriate boundary.  */
1170 
1171 valueT
1172 md_section_align (segT segment ATTRIBUTE_UNUSED,
1173 		  valueT size)
1174 {
1175   /* Byte alignment is fine.  */
1176   return size;
1177 }
1178 
1179 /* Exactly what point is a PC-relative offset relative TO?
1180    On the 29000, they're relative to the address of the instruction,
1181    which we have set up as the address of the fixup too.  */
1182 
1183 long
1184 md_pcrel_from (fixS* fixP)
1185 {
1186   return 4 + fixP->fx_where + fixP->fx_frag->fr_address;
1187 }
1188 
1189 /* Translate internal representation of relocation info to BFD target
1190    format.
1191    FIXME: To what extent can we get all relevant targets to use this?
1192    The above FIXME is from a29k, but I think it is also needed here.    */
1193 
1194 arelent *
1195 tc_gen_reloc (asection *section ATTRIBUTE_UNUSED,
1196 	      fixS *fixP)
1197 {
1198   arelent * reloc;
1199 
1200   reloc = xmalloc (sizeof (arelent));
1201   reloc->howto = bfd_reloc_type_lookup (stdoutput, fixP->fx_r_type);
1202 
1203   if (reloc->howto == NULL)
1204     {
1205       as_bad_where (fixP->fx_file, fixP->fx_line,
1206 		    _("internal error: can't export reloc type %d (`%s')"),
1207 		    fixP->fx_r_type,
1208 		    bfd_get_reloc_code_name (fixP->fx_r_type));
1209       return NULL;
1210     }
1211 
1212   gas_assert (!fixP->fx_pcrel == !reloc->howto->pc_relative);
1213 
1214   reloc->sym_ptr_ptr = xmalloc (sizeof (asymbol *));
1215   *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixP->fx_addsy);
1216   reloc->address = fixP->fx_frag->fr_address + fixP->fx_where;
1217 
1218   if (fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
1219     reloc->address = fixP->fx_offset;
1220   reloc->addend = 0;
1221 
1222   return reloc;
1223 }
1224 
1225 const pseudo_typeS
1226 dlx_pseudo_table[] =
1227 {
1228   /* Some additional ops that are used by gcc-dlx.  */
1229   {"asciiz", stringer, 8 + 1},
1230   {"half", cons, 2},
1231   {"dword", cons, 8},
1232   {"word", cons, 4},
1233   {"proc", s_proc, 0},
1234   {"endproc", s_proc, 1},
1235   {NULL, NULL, 0}
1236 };
1237 
1238 void
1239 dlx_pop_insert (void)
1240 {
1241   pop_insert (dlx_pseudo_table);
1242   return ;
1243 }
1244