ld/
[binutils.git] / gas / config / tc-dlx.c
blobac0aabae622ba7d9a7a0a91b7b6e28e5d5608564
1 /* tc-ldx.c -- Assemble for the DLX
2 Copyright 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
4 This file is part of GAS, the GNU Assembler.
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.
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.
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. */
21 /* Initially created by Kuang Hwa Lin, 3/20/2002. */
23 #include "safe-ctype.h"
24 #include "as.h"
25 #include "tc-dlx.h"
26 #include "opcode/dlx.h"
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
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
43 /* handle of the OPCODE hash table */
44 static struct hash_control *op_hash = NULL;
46 struct machine_it
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;
59 the_insn;
61 /* This array holds the chars that always start a comment. If the
62 pre-processor is disabled, these aren't very useful. */
63 const char comment_chars[] = ";";
65 /* This array holds the chars that only start a comment at the beginning of
66 a line. If the line seems to have the form '# 123 filename'
67 .line and .file directives will appear in the pre-processed output. */
68 /* Note that input_file.c hand checks for '#' at the beginning of the
69 first line of the input file. This is because the compiler outputs
70 #NO_APP at the beginning of its output. */
71 /* Also note that comments like this one will always work. */
72 const char line_comment_chars[] = "#";
74 /* We needed an unused char for line separation to work around the
75 lack of macros, using sed and such. */
76 const char line_separator_chars[] = "@";
78 /* Chars that can be used to separate mant from exp in floating point nums. */
79 const char EXP_CHARS[] = "eE";
81 /* Chars that mean this number is a floating point constant.
82 As in 0f12.456
83 or 0d1.2345e12. */
84 const char FLT_CHARS[] = "rRsSfFdDxXpP";
86 static void
87 insert_sreg (char *regname, int regnum)
89 /* Must be large enough to hold the names of the special registers. */
90 char buf[80];
91 int i;
93 symbol_table_insert (symbol_new (regname, reg_section, (valueT) regnum,
94 &zero_address_frag));
95 for (i = 0; regname[i]; i++)
96 buf[i] = ISLOWER (regname[i]) ? TOUPPER (regname[i]) : regname[i];
97 buf[i] = '\0';
99 symbol_table_insert (symbol_new (buf, reg_section, (valueT) regnum,
100 &zero_address_frag));
103 /* Install symbol definitions for assorted special registers.
104 See MIPS Assembly Language Programmer's Guide page 1-4 */
106 static void
107 define_some_regs (void)
109 /* Software representation. */
110 insert_sreg ("zero", 0);
111 insert_sreg ("at", 1);
112 insert_sreg ("v0", 2);
113 insert_sreg ("v1", 3);
114 insert_sreg ("a0", 4);
115 insert_sreg ("a1", 5);
116 insert_sreg ("a2", 6);
117 insert_sreg ("a3", 7);
118 insert_sreg ("t0", 8);
119 insert_sreg ("t1", 9);
120 insert_sreg ("t2", 10);
121 insert_sreg ("t3", 11);
122 insert_sreg ("t4", 12);
123 insert_sreg ("t5", 13);
124 insert_sreg ("t6", 14);
125 insert_sreg ("t7", 15);
126 insert_sreg ("s0", 16);
127 insert_sreg ("s1", 17);
128 insert_sreg ("s2", 18);
129 insert_sreg ("s3", 19);
130 insert_sreg ("s4", 20);
131 insert_sreg ("s5", 21);
132 insert_sreg ("s6", 22);
133 insert_sreg ("s7", 23);
134 insert_sreg ("t8", 24);
135 insert_sreg ("t9", 25);
136 insert_sreg ("k0", 26);
137 insert_sreg ("k1", 27);
138 insert_sreg ("gp", 28);
139 insert_sreg ("sp", 29);
140 insert_sreg ("fp", 30);
141 insert_sreg ("ra", 31);
142 /* Special registers. */
143 insert_sreg ("pc", 0);
144 insert_sreg ("npc", 1);
145 insert_sreg ("iad", 2);
148 /* Subroutine check the string to match an register. */
150 static int
151 match_sft_register (char *name)
153 #define MAX_REG_NO 35
154 /* Currently we have 35 software registers defined -
155 we borrowed from MIPS. */
156 static char *soft_reg[] =
158 "zero", "at", "v0", "v1", "a0", "a1", "a2", "a3",
159 "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7", "t8", "t9",
160 "s0", "s1", "s2", "s3", "s4", "s5", "s7", "k0", "k1",
161 "gp", "sp", "fp", "ra", "pc", "npc", "iad",
162 "EndofTab" /* End of the Table indicator */
164 char low_name[21], *ptr;
165 int idx;
167 for (ptr = name,idx = 0; *ptr != '\0'; ptr++)
168 low_name[idx++] = TOLOWER (*ptr);
170 low_name[idx] = '\0';
171 idx = 0;
173 while (idx < MAX_REG_NO && strcmp (soft_reg[idx], & low_name [0]))
174 idx += 1;
176 return idx < MAX_REG_NO;
179 /* Subroutine check the string to match an register. */
181 static int
182 is_ldst_registers (char *name)
184 char *ptr = name;
186 /* The first character of the register name got to be either %, $, r of R. */
187 if ((ptr[0] == '%' || ptr[0] == '$' || ptr[0] == 'r' || ptr[0] == 'R')
188 && ISDIGIT ((unsigned char) ptr[1]))
189 return 1;
191 /* Now check the software register representation. */
192 return match_sft_register (ptr);
195 /* Subroutine of s_proc so targets can choose a different default prefix.
196 If DEFAULT_PREFIX is NULL, use the target's "leading char". */
198 static void
199 s_proc (int end_p)
201 /* Record the current function so that we can issue an error message for
202 misplaced .func,.endfunc, and also so that .endfunc needs no
203 arguments. */
204 static char *current_name;
205 static char *current_label;
207 if (end_p)
209 if (current_name == NULL)
211 as_bad (_("missing .proc"));
212 ignore_rest_of_line ();
213 return;
216 current_name = current_label = NULL;
217 SKIP_WHITESPACE ();
218 while (!is_end_of_line[(unsigned char) *input_line_pointer])
219 input_line_pointer++;
221 else
223 char *name, *label;
224 char delim1, delim2;
226 if (current_name != NULL)
228 as_bad (_(".endfunc missing for previous .proc"));
229 ignore_rest_of_line ();
230 return;
233 name = input_line_pointer;
234 delim1 = get_symbol_end ();
235 name = xstrdup (name);
236 *input_line_pointer = delim1;
237 SKIP_WHITESPACE ();
239 if (*input_line_pointer != ',')
241 char leading_char = 0;
243 leading_char = bfd_get_symbol_leading_char (stdoutput);
244 /* Missing entry point, use function's name with the leading
245 char prepended. */
246 if (leading_char)
247 asprintf (&label, "%c%s", leading_char, name);
248 else
249 label = name;
251 else
253 ++input_line_pointer;
254 SKIP_WHITESPACE ();
255 label = input_line_pointer;
256 delim2 = get_symbol_end ();
257 label = xstrdup (label);
258 *input_line_pointer = delim2;
261 current_name = name;
262 current_label = label;
264 demand_empty_rest_of_line ();
267 /* This function is called once, at assembler startup time. It should
268 set up all the tables, etc., that the MD part of the assembler will
269 need. */
271 void
272 md_begin (void)
274 const char *retval = NULL;
275 int lose = 0;
276 unsigned int i;
278 /* Create a new hash table. */
279 op_hash = hash_new ();
281 /* Hash up all the opcodes for fast use later. */
282 for (i = 0; i < num_dlx_opcodes; i++)
284 const char *name = machine_opcodes[i].name;
286 retval = hash_insert (op_hash, name, (void *) &machine_opcodes[i]);
288 if (retval != NULL)
290 fprintf (stderr, "internal error: can't hash `%s': %s\n",
291 machine_opcodes[i].name, retval);
292 lose = 1;
296 if (lose)
297 as_fatal (_("Broken assembler. No assembly attempted."));
299 define_some_regs ();
302 /* This function will check the opcode and return 1 if the opcode is one
303 of the load/store instruction, and it will fix the operand string to
304 the standard form so we can use the standard parse_operand routine. */
306 #define READ_OP 0x100
307 #define WRITE_OP 0x200
308 static char iBuf[81];
310 static char *
311 dlx_parse_loadop (char * str)
313 char *ptr = str;
314 int idx = 0;
316 /* The last pair of ()/[] is the register, all other are the
317 reloc displacement, and if there is a register then it ought
318 to have a pair of ()/[]
319 This is not necessarily true, what if the load instruction come
320 without the register and with %hi/%lo modifier? */
321 for (idx = 0; idx < 72 && ptr[idx] != '\0'; idx++)
324 if (idx == 72)
326 badoperand_load:
327 as_bad (_("Bad operand for a load instruction: <%s>"), str);
328 return NULL;
330 else
332 int i, pb = 0;
333 int m2 = 0;
334 char rs1[7], rd[7], endm, match = '0';
335 char imm[72];
337 idx -= 1;
338 switch (str[idx])
340 case ')':
341 match = '(';
342 endm = ')';
343 break;
344 case ']':
345 match = '[';
346 endm = ']';
347 break;
348 default:
349 /* No register indicated, fill in zero. */
350 rs1[0] = 'r';
351 rs1[1] = '0';
352 rs1[2] = '\0';
353 match = 0;
354 endm = 0;
355 m2 = 1;
358 if (!m2)
360 /* Searching for (/[ which will match the ]/). */
361 for (pb = idx - 1; str[pb] != match; pb -= 1)
362 /* Match can only be either '[' or '(', if it is
363 '(' then this can be a normal expression, we'll treat
364 it as an operand. */
365 if (str[pb] == endm || pb < (idx - 5))
366 goto load_no_rs1;
367 pb += 1;
369 for (i = 0; (pb + i) < idx; i++)
370 rs1[i] = str[pb+i];
372 rs1[i] = '\0';
374 if (is_ldst_registers (& rs1[0]))
375 /* Point to the last character of the imm. */
376 pb -= 1;
377 else
379 load_no_rs1:
380 if (match == '[')
381 goto badoperand_load;
382 /* No register indicated, fill in zero and restore the imm. */
383 rs1[0] = 'r';
384 rs1[1] = '0';
385 rs1[2] = '\0';
386 m2 = 1;
390 /* Duplicate the first register. */
391 for (i = 0; i < 7 && str[i] != ','; i++)
392 rd[i] = ptr[i];
394 if (str[i] != ',')
395 goto badoperand_load;
396 else
397 rd[i] = '\0';
399 /* Copy the immd. */
400 if (m2)
401 /* Put the '\0' back in. */
402 pb = idx + 1;
404 for (i++, m2 = 0; i < pb; m2++,i++)
405 imm[m2] = ptr[i];
407 imm[m2] = '\0';
409 /* Assemble the instruction to gas internal format. */
410 for (i = 0; rd[i] != '\0'; i++)
411 iBuf[i] = rd[i];
413 iBuf[i++] = ',';
415 for (pb = 0 ; rs1[pb] != '\0'; i++, pb++)
416 iBuf[i] = rs1[pb];
418 iBuf[i++] = ',';
420 for (pb = 0; imm[pb] != '\0'; i++, pb++)
421 iBuf[i] = imm[pb];
423 iBuf[i] = '\0';
424 return iBuf;
428 static char *
429 dlx_parse_storeop (char * str)
431 char *ptr = str;
432 int idx = 0;
434 /* Search for the ','. */
435 for (idx = 0; idx < 72 && ptr[idx] != ','; idx++)
438 if (idx == 72)
440 badoperand_store:
441 as_bad (_("Bad operand for a store instruction: <%s>"), str);
442 return NULL;
444 else
446 /* idx now points to the ','. */
447 int i, pb = 0;
448 int comma = idx;
449 int m2 = 0;
450 char rs1[7], rd[7], endm, match = '0';
451 char imm[72];
453 /* Now parse the '(' and ')', and make idx point to ')'. */
454 idx -= 1;
455 switch (str[idx])
457 case ')':
458 match = '(';
459 endm = ')';
460 break;
461 case ']':
462 match = '[';
463 endm = ']';
464 break;
465 default:
466 /* No register indicated, fill in zero. */
467 rs1[0] = 'r';
468 rs1[1] = '0';
469 rs1[2] = '\0';
470 match = 0;
471 endm = 0;
472 m2 = 1;
475 if (!m2)
477 /* Searching for (/[ which will match the ]/). */
478 for (pb = idx - 1; str[pb] != match; pb -= 1)
479 if (pb < (idx - 5) || str[pb] == endm)
480 goto store_no_rs1;
481 pb += 1;
483 for (i = 0; (pb + i) < idx; i++)
484 rs1[i] = str[pb + i];
486 rs1[i] = '\0';
488 if (is_ldst_registers (& rs1[0]))
489 /* Point to the last character of the imm. */
490 pb -= 1;
491 else
493 store_no_rs1:
494 if (match == '[')
495 goto badoperand_store;
497 /* No register indicated, fill in zero and restore the imm. */
498 rs1[0] = 'r';
499 rs1[1] = '0';
500 rs1[2] = '\0';
501 pb = comma;
504 else
505 /* No register was specified. */
506 pb = comma;
508 /* Duplicate the first register. */
509 for (i = comma + 1; (str[i] == ' ' || str[i] == '\t'); i++)
512 for (m2 = 0; (m2 < 7 && str[i] != '\0'); i++, m2++)
514 if (str[i] != ' ' && str[i] != '\t')
515 rd[m2] = str[i];
516 else
517 goto badoperand_store;
520 if (str[i] != '\0')
521 goto badoperand_store;
522 else
523 rd[m2] = '\0';
525 /* Copy the immd. */
526 for (i = 0; i < pb; i++)
527 imm[i] = ptr[i];
529 imm[i] = '\0';
531 /* Assemble the instruction to gas internal format. */
532 for (i = 0; rd[i] != '\0'; i++)
533 iBuf[i] = rd[i];
534 iBuf[i++] = ',';
535 for (pb = 0 ; rs1[pb] != '\0'; i++, pb++)
536 iBuf[i] = rs1[pb];
537 iBuf[i++] = ',';
538 for (pb = 0; imm[pb] != '\0'; i++, pb++)
539 iBuf[i] = imm[pb];
540 iBuf[i] = '\0';
541 return iBuf;
545 static char *
546 fix_ld_st_operand (unsigned long opcode, char* str)
548 /* Check the opcode. */
549 switch ((int) opcode)
551 case LBOP:
552 case LBUOP:
553 case LSBUOP:
554 case LHOP:
555 case LHUOP:
556 case LSHUOP:
557 case LWOP:
558 case LSWOP:
559 return dlx_parse_loadop (str);
560 case SBOP:
561 case SHOP:
562 case SWOP:
563 return dlx_parse_storeop (str);
564 default:
565 return str;
569 static int
570 hilo_modifier_ok (char *s)
572 char *ptr = s;
573 int idx, count = 1;
575 if (*ptr != '(')
576 return 1;
578 for (idx = 1; ptr[idx] != '\0' && ptr[idx] != '[' && idx < 73; idx += 1)
580 if (count == 0)
581 return count;
583 if (ptr[idx] == '(')
584 count += 1;
586 if (ptr[idx] == ')')
587 count -= 1;
590 return (count == 0) ? 1:0;
593 static char *
594 parse_operand (char *s, expressionS *operandp)
596 char *save = input_line_pointer;
597 char *new;
599 the_insn.HI = the_insn.LO = 0;
601 /* Search for %hi and %lo, make a mark and skip it. */
602 if (strncmp (s, "%hi", 3) == 0)
604 s += 3;
605 the_insn.HI = 1;
607 else
609 if (strncmp (s, "%lo", 3) == 0)
611 s += 3;
612 the_insn.LO = 1;
614 else
615 the_insn.LO = 0;
618 if (the_insn.HI || the_insn.LO)
620 if (!hilo_modifier_ok (s))
621 as_bad (_("Expression Error for operand modifier %%hi/%%lo\n"));
624 /* Check for the % and $ register representation */
625 if ((s[0] == '%' || s[0] == '$' || s[0] == 'r' || s[0] == 'R')
626 && ISDIGIT ((unsigned char) s[1]))
628 /* We have a numeric register expression. No biggy. */
629 s += 1;
630 input_line_pointer = s;
631 (void) expression (operandp);
632 if (operandp->X_op != O_constant
633 || operandp->X_add_number > 31)
634 as_bad (_("Invalid expression after %%%%\n"));
635 operandp->X_op = O_register;
637 else
639 /* Normal operand parsing. */
640 input_line_pointer = s;
641 (void) expression (operandp);
644 new = input_line_pointer;
645 input_line_pointer = save;
646 return new;
649 /* Instruction parsing. Takes a string containing the opcode.
650 Operands are at input_line_pointer. Output is in the_insn.
651 Warnings or errors are generated. */
653 static void
654 machine_ip (char *str)
656 char *s;
657 const char *args;
658 struct machine_opcode *insn;
659 char *argsStart;
660 unsigned long opcode;
661 expressionS the_operand;
662 expressionS *operand = &the_operand;
663 unsigned int reg, reg_shift = 0;
665 /* Fixup the opcode string to all lower cases, and also
666 allow numerical digits. */
667 s = str;
669 if (ISALPHA (*s))
670 for (; ISALNUM (*s); ++s)
671 if (ISUPPER (*s))
672 *s = TOLOWER (*s);
674 switch (*s)
676 case '\0':
677 break;
679 /* FIXME-SOMEDAY more whitespace. */
680 case ' ':
681 *s++ = '\0';
682 break;
684 default:
685 as_bad (_("Unknown opcode: `%s'"), str);
686 return;
689 /* Hash the opcode, insn will have the string from opcode table.
690 also initialized the_insn struct. */
691 if ((insn = (struct machine_opcode *) hash_find (op_hash, str)) == NULL)
693 /* Handle the ret and return macro here. */
694 if ((strcmp (str, "ret") == 0) || (strcmp (str, "return") == 0))
696 memset (&the_insn, '\0', sizeof (the_insn));
697 the_insn.reloc = NO_RELOC;
698 the_insn.pcrel = 0;
699 the_insn.opcode =
700 (unsigned long)(JROP | 0x03e00000); /* 0x03e00000 = r31 << 21 */
702 else
703 as_bad (_("Unknown opcode `%s'."), str);
705 return;
708 argsStart = s;
709 opcode = insn->opcode;
710 memset (&the_insn, '\0', sizeof (the_insn));
711 the_insn.reloc = NO_RELOC;
712 the_insn.pcrel = 0;
714 /* Set the sip reloc HI16 flag. */
715 if (!set_dlx_skip_hi16_flag (1))
716 as_bad (_("Can not set dlx_skip_hi16_flag"));
718 /* Fix the operand string if it is one of load store instructions. */
719 s = fix_ld_st_operand (opcode, s);
721 /* Build the opcode, checking as we go to make sure that the
722 operands match.
723 If an operand matches, we modify the_insn or opcode appropriately,
724 and do a "continue". If an operand fails to match, we "break". */
725 if (insn->args[0] != '\0' && insn->args[0] != 'N')
727 /* Prime the pump. */
728 if (*s == '\0')
730 as_bad (_("Missing arguments for opcode <%s>."), str);
731 return;
733 else
734 s = parse_operand (s, operand);
736 else if (insn->args[0] == 'N')
738 /* Clean up the insn and done! */
739 the_insn.opcode = opcode;
740 return;
743 /* Parse through the args (this is from opcode table), *s point to
744 the current character of the instruction stream. */
745 for (args = insn->args;; ++args)
747 switch (*args)
749 /* End of Line. */
750 case '\0':
751 /* End of args. */
752 if (*s == '\0')
754 /* We are truly done. */
755 the_insn.opcode = opcode;
756 /* Clean up the HI and LO mark. */
757 the_insn.HI = 0;
758 the_insn.LO = 0;
759 return;
762 the_insn.HI = 0;
763 the_insn.LO = 0;
764 as_bad (_("Too many operands: %s"), s);
765 break;
767 /* ',' Args separator */
768 case ',':
769 /* Must match a comma. */
770 if (*s++ == ',')
772 /* Parse next operand. */
773 s = parse_operand (s, operand);
774 continue;
776 break;
778 /* It can be a 'a' register or 'i' operand. */
779 case 'P':
780 /* Macro move operand/reg. */
781 if (operand->X_op == O_register)
783 /* Its a register. */
784 reg_shift = 21;
785 goto general_reg;
788 /* The immediate 16 bits literal, bit 0-15. */
789 case 'i':
790 /* offset, unsigned. */
791 case 'I':
792 /* offset, signed. */
793 if (operand->X_op == O_constant)
795 if (the_insn.HI)
796 operand->X_add_number >>= 16;
798 opcode |= operand->X_add_number & 0xFFFF;
800 if (the_insn.HI && the_insn.LO)
801 as_bad (_("Both the_insn.HI and the_insn.LO are set : %s"), s);
802 else
804 the_insn.HI = 0;
805 the_insn.LO = 0;
807 continue;
810 the_insn.reloc = (the_insn.HI) ? RELOC_DLX_HI16
811 : (the_insn.LO ? RELOC_DLX_LO16 : RELOC_DLX_16);
812 the_insn.reloc_offset = 2;
813 the_insn.size = 2;
814 the_insn.pcrel = 0;
815 the_insn.exp = * operand;
816 the_insn.HI = 0;
817 the_insn.LO = 0;
818 continue;
820 case 'd':
821 /* offset, signed. */
822 if (operand->X_op == O_constant)
824 opcode |= operand->X_add_number & 0xFFFF;
825 continue;
827 the_insn.reloc = RELOC_DLX_REL16;
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;
834 /* The immediate 26 bits literal, bit 0-25. */
835 case 'D':
836 /* offset, signed. */
837 if (operand->X_op == O_constant)
839 opcode |= operand->X_add_number & 0x3FFFFFF;
840 continue;
842 the_insn.reloc = RELOC_DLX_REL26;
843 the_insn.reloc_offset = 0; /* BIG-ENDIAN Byte 3 of insn. */
844 the_insn.size = 4;
845 the_insn.pcrel = 1;
846 the_insn.exp = *operand;
847 continue;
849 /* Type 'a' Register. */
850 case 'a':
851 /* A general register at bits 21-25, rs1. */
852 reg_shift = 21;
853 goto general_reg;
855 /* Type 'b' Register. */
856 case 'b':
857 /* A general register at bits 16-20, rs2/rd. */
858 reg_shift = 16;
859 goto general_reg;
861 /* Type 'c' Register. */
862 case 'c':
863 /* A general register at bits 11-15, rd. */
864 reg_shift = 11;
866 general_reg:
867 know (operand->X_add_symbol == 0);
868 know (operand->X_op_symbol == 0);
869 reg = operand->X_add_number;
870 if (reg & 0xffffffe0)
871 as_fatal (_("failed regnum sanity check."));
872 else
873 /* Got the register, now figure out where it goes in the opcode. */
874 opcode |= reg << reg_shift;
876 switch (*args)
878 case 'a':
879 case 'b':
880 case 'c':
881 case 'P':
882 continue;
884 as_fatal (_("failed general register sanity check."));
885 break;
887 default:
888 BAD_CASE (*args);
891 /* Types or values of args don't match. */
892 as_bad ("Invalid operands");
893 return;
897 /* Assemble a single instruction. Its label has already been handled
898 by the generic front end. We just parse opcode and operands, and
899 produce the bytes of data and relocation. */
901 void
902 md_assemble (char *str)
904 char *toP;
905 fixS *fixP;
906 bit_fixS *bitP;
908 know (str);
909 machine_ip (str);
910 toP = frag_more (4);
911 /* Put out the opcode. */
912 md_number_to_chars (toP, the_insn.opcode, 4);
914 /* Put out the symbol-dependent stuff. */
915 if (the_insn.reloc != NO_RELOC)
917 fixP = fix_new_exp (frag_now,
918 (toP - frag_now->fr_literal + the_insn.reloc_offset),
919 the_insn.size, & the_insn.exp, the_insn.pcrel,
920 the_insn.reloc);
922 /* Turn off complaints that the addend is
923 too large for things like foo+100000@ha. */
924 switch (the_insn.reloc)
926 case RELOC_DLX_HI16:
927 case RELOC_DLX_LO16:
928 fixP->fx_no_overflow = 1;
929 break;
930 default:
931 break;
934 switch (fixP->fx_r_type)
936 case RELOC_DLX_REL26:
937 bitP = malloc (sizeof (bit_fixS));
938 bitP->fx_bit_size = 26;
939 bitP->fx_bit_offset = 25;
940 bitP->fx_bit_base = the_insn.opcode & 0xFC000000;
941 bitP->fx_bit_base_adj = 0;
942 bitP->fx_bit_max = 0;
943 bitP->fx_bit_min = 0;
944 bitP->fx_bit_add = 0x03FFFFFF;
945 fixP->fx_bit_fixP = bitP;
946 break;
947 case RELOC_DLX_LO16:
948 case RELOC_DLX_REL16:
949 bitP = malloc (sizeof (bit_fixS));
950 bitP->fx_bit_size = 16;
951 bitP->fx_bit_offset = 15;
952 bitP->fx_bit_base = the_insn.opcode & 0xFFFF0000;
953 bitP->fx_bit_base_adj = 0;
954 bitP->fx_bit_max = 0;
955 bitP->fx_bit_min = 0;
956 bitP->fx_bit_add = 0x0000FFFF;
957 fixP->fx_bit_fixP = bitP;
958 break;
959 case RELOC_DLX_HI16:
960 bitP = malloc (sizeof (bit_fixS));
961 bitP->fx_bit_size = 16;
962 bitP->fx_bit_offset = 15;
963 bitP->fx_bit_base = the_insn.opcode & 0xFFFF0000;
964 bitP->fx_bit_base_adj = 0;
965 bitP->fx_bit_max = 0;
966 bitP->fx_bit_min = 0;
967 bitP->fx_bit_add = 0x0000FFFF;
968 fixP->fx_bit_fixP = bitP;
969 break;
970 default:
971 fixP->fx_bit_fixP = NULL;
972 break;
977 /* This is identical to the md_atof in m68k.c. I think this is right,
978 but I'm not sure.
980 Turn a string in input_line_pointer into a floating point constant
981 of type TYPE, and store the appropriate bytes in *LITP. The number
982 of LITTLENUMS emitted is stored in *SIZEP. An error message is
983 returned, or NULL on OK. */
984 /* Dlx will not use it anyway, so I just leave it here for now. */
986 /* Equal to MAX_PRECISION in atof-ieee.c. */
987 #define MAX_LITTLENUMS 6
989 char *
990 md_atof (int type, char *litP, int *sizeP)
992 int prec;
993 LITTLENUM_TYPE words[MAX_LITTLENUMS];
994 LITTLENUM_TYPE *wordP;
995 char *t;
997 switch (type)
999 case 'f':
1000 case 'F':
1001 case 's':
1002 case 'S':
1003 prec = 2;
1004 break;
1006 case 'd':
1007 case 'D':
1008 case 'r':
1009 case 'R':
1010 prec = 4;
1011 break;
1013 case 'x':
1014 case 'X':
1015 prec = 6;
1016 break;
1018 case 'p':
1019 case 'P':
1020 prec = 6;
1021 break;
1023 default:
1024 *sizeP = 0;
1025 return "Bad call to MD_ATOF()";
1028 t = atof_ieee (input_line_pointer, type, words);
1029 if (t)
1030 input_line_pointer = t;
1032 *sizeP = prec * sizeof (LITTLENUM_TYPE);
1034 for (wordP = words; prec--;)
1036 md_number_to_chars (litP, (valueT) (*wordP++), sizeof (LITTLENUM_TYPE));
1037 litP += sizeof (LITTLENUM_TYPE);
1040 return 0;
1043 /* Write out big-endian. */
1044 void
1045 md_number_to_chars (char *buf, valueT val, int n)
1047 number_to_chars_bigendian (buf, val, n);
1050 bfd_boolean
1051 md_dlx_fix_adjustable (fixS *fixP)
1053 /* We need the symbol name for the VTABLE entries. */
1054 return (fixP->fx_r_type != BFD_RELOC_VTABLE_INHERIT
1055 && fixP->fx_r_type != BFD_RELOC_VTABLE_ENTRY);
1058 void
1059 md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
1061 long val = *valP;
1062 char *place = fixP->fx_where + fixP->fx_frag->fr_literal;
1064 switch (fixP->fx_r_type)
1066 case RELOC_DLX_LO16:
1067 case RELOC_DLX_REL16:
1068 if (fixP->fx_bit_fixP != NULL)
1070 val = (val & 0x0000FFFF) | fixP->fx_bit_fixP->fx_bit_base;
1071 free (fixP->fx_bit_fixP);
1072 fixP->fx_bit_fixP = NULL;
1074 #ifdef DEBUG
1075 else
1076 know ((fixP->fx_bit_fixP != NULL));
1077 #endif
1078 break;
1080 case RELOC_DLX_HI16:
1081 if (fixP->fx_bit_fixP != NULL)
1083 val = (val >> 16) | fixP->fx_bit_fixP->fx_bit_base;
1084 free (fixP->fx_bit_fixP);
1085 fixP->fx_bit_fixP = NULL;
1087 #ifdef DEBUG
1088 else
1089 know ((fixP->fx_bit_fixP != NULL));
1090 #endif
1091 break;
1093 case RELOC_DLX_REL26:
1094 if (fixP->fx_bit_fixP != NULL)
1096 val = (val & 0x03FFFFFF) | fixP->fx_bit_fixP->fx_bit_base;
1097 free (fixP->fx_bit_fixP);
1098 fixP->fx_bit_fixP = NULL;
1100 #ifdef DEBUG
1101 else
1102 know ((fixP->fx_bit_fixP != NULL));
1103 #endif
1104 break;
1106 case BFD_RELOC_VTABLE_INHERIT:
1107 /* This borrowed from tc-ppc.c on a whim. */
1108 fixP->fx_done = 0;
1109 if (fixP->fx_addsy
1110 && !S_IS_DEFINED (fixP->fx_addsy)
1111 && !S_IS_WEAK (fixP->fx_addsy))
1112 S_SET_WEAK (fixP->fx_addsy);
1113 return;
1115 case BFD_RELOC_VTABLE_ENTRY:
1116 fixP->fx_done = 0;
1117 return;
1119 default:
1120 break;
1123 number_to_chars_bigendian (place, val, fixP->fx_size);
1124 if (fixP->fx_addsy == NULL)
1125 fixP->fx_done = 1;
1128 const char *md_shortopts = "";
1130 struct option md_longopts[] =
1132 {NULL, no_argument, NULL, 0}
1135 size_t md_longopts_size = sizeof (md_longopts);
1138 md_parse_option (int c ATTRIBUTE_UNUSED,
1139 char *arg ATTRIBUTE_UNUSED)
1141 return 0;
1144 void
1145 md_show_usage (FILE *stream ATTRIBUTE_UNUSED)
1149 /* This is called when a line is unrecognized. */
1152 dlx_unrecognized_line (int c)
1154 int lab;
1155 char *s;
1157 if (c != '$' || ! ISDIGIT ((unsigned char) input_line_pointer[0]))
1158 return 0;
1160 s = input_line_pointer;
1162 lab = 0;
1163 while (ISDIGIT ((unsigned char) *s))
1165 lab = lab * 10 + *s - '0';
1166 ++s;
1169 if (*s != ':')
1170 /* Not a label definition. */
1171 return 0;
1173 if (dollar_label_defined (lab))
1175 as_bad (_("label \"$%d\" redefined"), lab);
1176 return 0;
1179 define_dollar_label (lab);
1180 colon (dollar_label_name (lab, 0));
1181 input_line_pointer = s + 1;
1183 return 1;
1186 /* Default the values of symbols known that should be "predefined". We
1187 don't bother to predefine them unless you actually use one, since there
1188 are a lot of them. */
1190 symbolS *
1191 md_undefined_symbol (char *name ATTRIBUTE_UNUSED)
1193 return NULL;
1196 /* Parse an operand that is machine-specific, the function was called
1197 in expr.c by operand() function, when everything failed before it
1198 call a quit. */
1200 void
1201 md_operand (expressionS* expressionP)
1203 /* Check for the #number representation */
1204 if (input_line_pointer[0] == '#' &&
1205 ISDIGIT ((unsigned char) input_line_pointer[1]))
1207 /* We have a numeric number expression. No biggy. */
1208 input_line_pointer += 1; /* Skip # */
1210 (void) expression (expressionP);
1212 if (expressionP->X_op != O_constant)
1213 as_bad (_("Invalid expression after # number\n"));
1216 return;
1219 /* Round up a section size to the appropriate boundary. */
1221 valueT
1222 md_section_align (segT segment ATTRIBUTE_UNUSED,
1223 valueT size)
1225 /* Byte alignment is fine. */
1226 return size;
1229 /* Exactly what point is a PC-relative offset relative TO?
1230 On the 29000, they're relative to the address of the instruction,
1231 which we have set up as the address of the fixup too. */
1233 long
1234 md_pcrel_from (fixS* fixP)
1236 return 4 + fixP->fx_where + fixP->fx_frag->fr_address;
1239 /* Translate internal representation of relocation info to BFD target
1240 format.
1241 FIXME: To what extent can we get all relevant targets to use this?
1242 The above FIXME is from a29k, but I think it is also needed here. */
1244 arelent *
1245 tc_gen_reloc (asection *section ATTRIBUTE_UNUSED,
1246 fixS *fixP)
1248 arelent * reloc;
1250 reloc = xmalloc (sizeof (arelent));
1251 reloc->howto = bfd_reloc_type_lookup (stdoutput, fixP->fx_r_type);
1253 if (reloc->howto == NULL)
1255 as_bad_where (fixP->fx_file, fixP->fx_line,
1256 "internal error: can't export reloc type %d (`%s')",
1257 fixP->fx_r_type,
1258 bfd_get_reloc_code_name (fixP->fx_r_type));
1259 return NULL;
1262 assert (!fixP->fx_pcrel == !reloc->howto->pc_relative);
1264 reloc->sym_ptr_ptr = xmalloc (sizeof (asymbol *));
1265 *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixP->fx_addsy);
1266 reloc->address = fixP->fx_frag->fr_address + fixP->fx_where;
1268 if (fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
1269 reloc->address = fixP->fx_offset;
1270 reloc->addend = 0;
1272 return reloc;
1275 const pseudo_typeS
1276 dlx_pseudo_table[] =
1278 /* Some additional ops that are used by gcc-dlx. */
1279 {"asciiz", stringer, 1},
1280 {"half", cons, 2},
1281 {"dword", cons, 8},
1282 {"word", cons, 4},
1283 {"proc", s_proc, 0},
1284 {"endproc", s_proc, 1},
1285 {NULL, NULL, 0}
1288 void
1289 dlx_pop_insert (void)
1291 pop_insert (dlx_pseudo_table);
1292 return ;