tc-dlx.c revision 1.1.1.1
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 */
44static struct hash_control *op_hash = NULL;
45
46struct 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}
59the_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.  */
63const 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.  */
72const 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.  */
76const char line_separator_chars[] = "@";
77
78/* Chars that can be used to separate mant from exp in floating point nums.  */
79const 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.  */
84const char FLT_CHARS[] = "rRsSfFdDxXpP";
85
86static void
87insert_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
106static void
107define_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
150static int
151match_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
181static int
182is_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
198static void
199s_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
271void
272md_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
308static char iBuf[81];
309
310static char *
311dlx_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
428static char *
429dlx_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
545static char *
546fix_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
569static int
570hilo_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
593static char *
594parse_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
653static void
654machine_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
901void
902md_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
981char *
982md_atof (int type, char *litP, int *sizeP)
983{
984  return ieee_md_atof (type, litP, sizeP, TRUE);
985}
986
987/* Write out big-endian.  */
988void
989md_number_to_chars (char *buf, valueT val, int n)
990{
991  number_to_chars_bigendian (buf, val, n);
992}
993
994bfd_boolean
995md_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
1002void
1003md_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
1072const char *md_shortopts = "";
1073
1074struct option md_longopts[] =
1075  {
1076    {NULL, no_argument, NULL, 0}
1077  };
1078
1079size_t md_longopts_size = sizeof (md_longopts);
1080
1081int
1082md_parse_option (int c     ATTRIBUTE_UNUSED,
1083		 char *arg ATTRIBUTE_UNUSED)
1084{
1085  return 0;
1086}
1087
1088void
1089md_show_usage (FILE *stream ATTRIBUTE_UNUSED)
1090{
1091}
1092
1093/* This is called when a line is unrecognized.  */
1094
1095int
1096dlx_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
1134symbolS *
1135md_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
1144void
1145md_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
1165valueT
1166md_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
1177long
1178md_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
1188arelent *
1189tc_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
1219const pseudo_typeS
1220dlx_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
1232void
1233dlx_pop_insert (void)
1234{
1235  pop_insert (dlx_pseudo_table);
1236  return ;
1237}
1238
1239