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 */
46static struct hash_control *op_hash = NULL;
47
48struct 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}
61the_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.  */
65const 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.  */
74const 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.  */
78const char line_separator_chars[] = "@";
79
80/* Chars that can be used to separate mant from exp in floating point nums.  */
81const 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.  */
86const char FLT_CHARS[] = "rRsSfFdDxXpP";
87
88static void
89insert_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
108static void
109define_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
152static int
153match_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
183static int
184is_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
200static void
201s_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
276void
277md_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
313static char iBuf[81];
314
315static char *
316dlx_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
433static char *
434dlx_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
550static char *
551fix_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
574static int
575hilo_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
598static char *
599parse_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
658static void
659machine_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
898void
899md_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
980const char *
981md_atof (int type, char *litP, int *sizeP)
982{
983  return ieee_md_atof (type, litP, sizeP, TRUE);
984}
985
986/* Write out big-endian.  */
987void
988md_number_to_chars (char *buf, valueT val, int n)
989{
990  number_to_chars_bigendian (buf, val, n);
991}
992
993bfd_boolean
994md_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
1001void
1002md_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
1061const char *md_shortopts = "";
1062
1063struct option md_longopts[] =
1064  {
1065    {NULL, no_argument, NULL, 0}
1066  };
1067
1068size_t md_longopts_size = sizeof (md_longopts);
1069
1070int
1071md_parse_option (int c     ATTRIBUTE_UNUSED,
1072		 const char *arg ATTRIBUTE_UNUSED)
1073{
1074  return 0;
1075}
1076
1077void
1078md_show_usage (FILE *stream ATTRIBUTE_UNUSED)
1079{
1080}
1081
1082/* This is called when a line is unrecognized.  */
1083
1084int
1085dlx_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
1123symbolS *
1124md_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
1133void
1134md_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
1154valueT
1155md_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
1166long
1167md_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
1177arelent *
1178tc_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
1208const pseudo_typeS
1209dlx_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
1221void
1222dlx_pop_insert (void)
1223{
1224  pop_insert (dlx_pseudo_table);
1225  return ;
1226}
1227