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