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