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