xref: /openbsd/gnu/usr.bin/binutils/gas/config/tc-dlx.c (revision 771fbea0)
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 */
47 static struct hash_control *op_hash = NULL;
48 
49 struct 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 }
62 the_insn;
63 
64 /* static void print_insn PARAMS ((struct machine_it *)); */
65 char * parse_operand    PARAMS ((char *, expressionS *));
66 int md_chars_to_number  PARAMS ((unsigned char *, int));
67 
68 static void machine_ip          PARAMS ((char *));
69 static void s_proc              PARAMS ((int));
70 static void insert_sreg         PARAMS ((char *, int));
71 static int  hilo_modifier_ok    PARAMS ((char *));
72 static int  is_ldst_registers   PARAMS ((char *));
73 static int  match_sft_register  PARAMS ((char *));
74 static void define_some_regs    PARAMS ((void));
75 static char * dlx_parse_loadop  PARAMS ((char *));
76 static char * dlx_parse_storeop PARAMS ((char *));
77 static char * fix_ld_st_operand PARAMS ((unsigned long, char *));
78 
79 const pseudo_typeS
80 
81 dlx_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.  */
95 const 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.  */
104 const 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.  */
108 const char line_separator_chars[] = "@";
109 
110 /* Chars that can be used to separate mant from exp in floating point nums.  */
111 const 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.  */
116 const char FLT_CHARS[] = "rRsSfFdDxXpP";
117 
118 static void
119 insert_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 
140 static void
141 define_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 
219 static int
220 match_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 
251 static int
252 is_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 
269 static void
270 s_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 
343 void
344 md_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 
378 void
379 md_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 
455 static int
456 hilo_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 
480 char *
481 parse_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
544 static char iBuf[81];
545 
546 static char *
547 dlx_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 
665 static char *
666 dlx_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 
783 static char *
784 fix_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 
813 static void
814 machine_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 
1073 char *
1074 md_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.  */
1131 void
1132 md_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 
1142 int
1143 md_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 
1158 bfd_boolean
1159 md_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 
1167 void
1168 md_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 
1243 const char *md_shortopts = "";
1244 
1245 struct option md_longopts[] =
1246   {
1247     {NULL, no_argument, NULL, 0}
1248   };
1249 
1250 size_t md_longopts_size = sizeof (md_longopts);
1251 
1252 int
1253 md_parse_option (c, arg)
1254      int c     ATTRIBUTE_UNUSED;
1255      char *arg ATTRIBUTE_UNUSED;
1256 {
1257   return 0;
1258 }
1259 
1260 void
1261 md_show_usage (stream)
1262      FILE *stream ATTRIBUTE_UNUSED;
1263 {
1264 }
1265 
1266 /* This is called when a line is unrecognized.  */
1267 
1268 int
1269 dlx_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 
1310 symbolS *
1311 md_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 
1322 void
1323 md_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 
1371 valueT
1372 md_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 
1384 long
1385 md_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
1394 static short
1395 tc_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 
1420 arelent *
1421 tc_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 
1452 extern void pop_insert PARAMS ((const pseudo_typeS *));
1453 
1454 void
1455 dlx_pop_insert ()
1456 {
1457   pop_insert (dlx_pseudo_table);
1458   return ;
1459 }
1460