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