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