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