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