Add support for Xilinx MicroBlaze processor.
[deliverable/binutils-gdb.git] / gas / config / tc-microblaze.c
1 /* tc-microblaze.c -- Assemble code for Xilinx MicroBlaze
2
3 Copyright 2009 Free Software Foundation.
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
9 the Free Software Foundation; either version 3, or (at your option)
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
19 Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
20 02110-1301, USA. */
21
22 #include <stdio.h>
23 #include "as.h"
24 #include "bfd.h"
25 #include "subsegs.h"
26 #define DEFINE_TABLE
27 #include "../opcodes/microblaze-opc.h"
28 #include "../opcodes/microblaze-opcm.h"
29 #include <ctype.h>
30 #include <string.h>
31 #include <dwarf2dbg.h>
32 #include "aout/stab_gnu.h"
33
34 #ifndef streq
35 #define streq(a,b) (strcmp (a, b) == 0)
36 #endif
37
38 void microblaze_generate_symbol (char *sym);
39 static bfd_boolean check_spl_reg (unsigned *);
40
41 /* Several places in this file insert raw instructions into the
42 object. They should generate the instruction
43 and then use these four macros to crack the instruction value into
44 the appropriate byte values. */
45 #define INST_BYTE0(x) (target_big_endian ? (((x) >> 24) & 0xFF) : ((x) & 0xFF))
46 #define INST_BYTE1(x) (target_big_endian ? (((x) >> 16) & 0xFF) : (((x) >> 8) & 0xFF))
47 #define INST_BYTE2(x) (target_big_endian ? (((x) >> 8) & 0xFF) : (((x) >> 16) & 0xFF))
48 #define INST_BYTE3(x) (target_big_endian ? ((x) & 0xFF) : (((x) >> 24) & 0xFF))
49
50 /* This array holds the chars that always start a comment. If the
51 pre-processor is disabled, these aren't very useful. */
52 const char comment_chars[] = "#";
53
54 const char line_separator_chars[] = ";";
55
56 /* This array holds the chars that only start a comment at the beginning of
57 a line. */
58 const char line_comment_chars[] = "#";
59
60 const int md_reloc_size = 8; /* Size of relocation record. */
61
62 /* Chars that can be used to separate mant
63 from exp in floating point numbers. */
64 const char EXP_CHARS[] = "eE";
65
66 /* Chars that mean this number is a floating point constant
67 As in 0f12.456
68 or 0d1.2345e12. */
69 const char FLT_CHARS[] = "rRsSfFdDxXpP";
70
71 /* INST_PC_OFFSET and INST_NO_OFFSET are 0 and 1. */
72 #define UNDEFINED_PC_OFFSET 2
73 #define DEFINED_ABS_SEGMENT 3
74 #define DEFINED_PC_OFFSET 4
75 #define DEFINED_RO_SEGMENT 5
76 #define DEFINED_RW_SEGMENT 6
77 #define LARGE_DEFINED_PC_OFFSET 7
78 #define GOT_OFFSET 8
79 #define PLT_OFFSET 9
80 #define GOTOFF_OFFSET 10
81
82
83 /* Initialize the relax table. */
84 const relax_typeS md_relax_table[] =
85 {
86 { 1, 1, 0, 0 }, /* 0: Unused. */
87 { 1, 1, 0, 0 }, /* 1: Unused. */
88 { 1, 1, 0, 0 }, /* 2: Unused. */
89 { 1, 1, 0, 0 }, /* 3: Unused. */
90 { 32767, -32768, INST_WORD_SIZE, LARGE_DEFINED_PC_OFFSET }, /* 4: DEFINED_PC_OFFSET. */
91 { 1, 1, 0, 0 }, /* 5: Unused. */
92 { 1, 1, 0, 0 }, /* 6: Unused. */
93 { 0x7fffffff, 0x80000000, INST_WORD_SIZE*2, 0 }, /* 7: LARGE_DEFINED_PC_OFFSET. */
94 { 0x7fffffff, 0x80000000, INST_WORD_SIZE*2, 0 }, /* 8: GOT_OFFSET. */
95 { 0x7fffffff, 0x80000000, INST_WORD_SIZE*2, 0 }, /* 9: PLT_OFFSET. */
96 { 0x7fffffff, 0x80000000, INST_WORD_SIZE*2, 0 }, /* 10: GOTOFF_OFFSET. */
97 };
98
99 static struct hash_control * opcode_hash_control; /* Opcode mnemonics. */
100
101 static segT sbss_segment = 0; /* Small bss section. */
102 static segT sbss2_segment = 0; /* Section not used. */
103 static segT sdata_segment = 0; /* Small data section. */
104 static segT sdata2_segment = 0; /* Small read-only section. */
105 static segT rodata_segment = 0; /* read-only section. */
106
107 /* Generate a symbol for stabs information. */
108
109 void
110 microblaze_generate_symbol (char *sym)
111 {
112 #define MICROBLAZE_FAKE_LABEL_NAME "XL0\001"
113 static int microblaze_label_count;
114 sprintf (sym, "%sL%d", MICROBLAZE_FAKE_LABEL_NAME, microblaze_label_count);
115 ++microblaze_label_count;
116 }
117
118 /* Handle the section changing pseudo-ops. */
119
120 static void
121 microblaze_s_text (int ignore ATTRIBUTE_UNUSED)
122 {
123 #ifdef OBJ_ELF
124 obj_elf_text (ignore);
125 #else
126 s_text (ignore);
127 #endif
128 }
129
130 static void
131 microblaze_s_data (int ignore ATTRIBUTE_UNUSED)
132 {
133 #ifdef OBJ_ELF
134 obj_elf_change_section (".data", SHT_PROGBITS, SHF_ALLOC+SHF_WRITE, 0, 0, 0, 0);
135 #else
136 s_data (ignore);
137 #endif
138 }
139
140 /* Things in the .sdata segment are always considered to be in the small data section. */
141
142 static void
143 microblaze_s_sdata (int ignore ATTRIBUTE_UNUSED)
144 {
145 #ifdef OBJ_ELF
146 obj_elf_change_section (".sdata", SHT_PROGBITS, SHF_ALLOC+SHF_WRITE, 0, 0, 0, 0);
147 #else
148 s_data (ignore);
149 #endif
150 }
151
152 /* Pseudo op to make file scope bss items. */
153
154 static void
155 microblaze_s_lcomm (int xxx ATTRIBUTE_UNUSED)
156 {
157 char *name;
158 char c;
159 char *p;
160 offsetT size;
161 symbolS *symbolP;
162 offsetT align;
163 segT old_sec;
164 int old_subsec;
165 char *pfrag;
166 int align2;
167 segT current_seg = now_seg;
168 subsegT current_subseg = now_subseg;
169
170 name = input_line_pointer;
171 c = get_symbol_end ();
172
173 /* Just after name is now '\0'. */
174 p = input_line_pointer;
175 *p = c;
176 SKIP_WHITESPACE ();
177 if (*input_line_pointer != ',')
178 {
179 as_bad (_("Expected comma after symbol-name: rest of line ignored."));
180 ignore_rest_of_line ();
181 return;
182 }
183
184 input_line_pointer++; /* skip ',' */
185 if ((size = get_absolute_expression ()) < 0)
186 {
187 as_warn (_(".COMMon length (%ld.) <0! Ignored."), (long) size);
188 ignore_rest_of_line ();
189 return;
190 }
191
192 /* The third argument to .lcomm is the alignment. */
193 if (*input_line_pointer != ',')
194 align = 8;
195 else
196 {
197 ++input_line_pointer;
198 align = get_absolute_expression ();
199 if (align <= 0)
200 {
201 as_warn (_("ignoring bad alignment"));
202 align = 8;
203 }
204 }
205
206 *p = 0;
207 symbolP = symbol_find_or_make (name);
208 *p = c;
209
210 if (S_IS_DEFINED (symbolP) && ! S_IS_COMMON (symbolP))
211 {
212 as_bad (_("Ignoring attempt to re-define symbol `%s'."),
213 S_GET_NAME (symbolP));
214 ignore_rest_of_line ();
215 return;
216 }
217
218 if (S_GET_VALUE (symbolP) && S_GET_VALUE (symbolP) != (valueT) size)
219 {
220 as_bad (_("Length of .lcomm \"%s\" is already %ld. Not changed to %ld."),
221 S_GET_NAME (symbolP),
222 (long) S_GET_VALUE (symbolP),
223 (long) size);
224
225 ignore_rest_of_line ();
226 return;
227 }
228
229 /* Allocate_bss. */
230 old_sec = now_seg;
231 old_subsec = now_subseg;
232 if (align)
233 {
234 /* Convert to a power of 2 alignment. */
235 for (align2 = 0; (align & 1) == 0; align >>= 1, ++align2);
236 if (align != 1)
237 {
238 as_bad (_("Common alignment not a power of 2"));
239 ignore_rest_of_line ();
240 return;
241 }
242 }
243 else
244 align2 = 0;
245
246 record_alignment (current_seg, align2);
247 subseg_set (current_seg, current_subseg);
248 if (align2)
249 frag_align (align2, 0, 0);
250 if (S_GET_SEGMENT (symbolP) == current_seg)
251 symbol_get_frag (symbolP)->fr_symbol = 0;
252 symbol_set_frag (symbolP, frag_now);
253 pfrag = frag_var (rs_org, 1, 1, (relax_substateT) 0, symbolP, size,
254 (char *) 0);
255 *pfrag = 0;
256 S_SET_SIZE (symbolP, size);
257 S_SET_SEGMENT (symbolP, current_seg);
258 subseg_set (current_seg, current_subseg);
259 demand_empty_rest_of_line ();
260 }
261
262 static void
263 microblaze_s_rdata (int localvar)
264 {
265 #ifdef OBJ_ELF
266 if (localvar == 0)
267 {
268 /* rodata. */
269 obj_elf_change_section (".rodata", SHT_PROGBITS, SHF_ALLOC, 0, 0, 0, 0);
270 if (rodata_segment == 0)
271 rodata_segment = subseg_new (".rodata", 0);
272 }
273 else
274 {
275 /* 1 .sdata2. */
276 obj_elf_change_section (".sdata2", SHT_PROGBITS, SHF_ALLOC, 0, 0, 0, 0);
277 }
278 #else
279 s_data (ignore);
280 #endif
281 }
282
283 static void
284 microblaze_s_bss (int localvar)
285 {
286 #ifdef OBJ_ELF
287 if (localvar == 0) /* bss. */
288 obj_elf_change_section (".bss", SHT_NOBITS, SHF_ALLOC+SHF_WRITE, 0, 0, 0, 0);
289 else if (localvar == 1)
290 {
291 /* sbss. */
292 obj_elf_change_section (".sbss", SHT_NOBITS, SHF_ALLOC+SHF_WRITE, 0, 0, 0, 0);
293 if (sbss_segment == 0)
294 sbss_segment = subseg_new (".sbss", 0);
295 }
296 #else
297 s_data (ignore);
298 #endif
299 }
300
301 /* endp_p is always 1 as this func is called only for .end <funcname>
302 This func consumes the <funcname> and calls regular processing
303 s_func(1) with arg 1 (1 for end). */
304
305 static void
306 microblaze_s_func (int end_p ATTRIBUTE_UNUSED)
307 {
308 *input_line_pointer = get_symbol_end ();
309 s_func (1);
310 }
311
312 /* Handle the .weakext pseudo-op as defined in Kane and Heinrich. */
313
314 static void
315 microblaze_s_weakext (int ignore ATTRIBUTE_UNUSED)
316 {
317 char *name;
318 int c;
319 symbolS *symbolP;
320 expressionS exp;
321
322 name = input_line_pointer;
323 c = get_symbol_end ();
324 symbolP = symbol_find_or_make (name);
325 S_SET_WEAK (symbolP);
326 *input_line_pointer = c;
327
328 SKIP_WHITESPACE ();
329
330 if (!is_end_of_line[(unsigned char) *input_line_pointer])
331 {
332 if (S_IS_DEFINED (symbolP))
333 {
334 as_bad ("Ignoring attempt to redefine symbol `%s'.",
335 S_GET_NAME (symbolP));
336 ignore_rest_of_line ();
337 return;
338 }
339
340 if (*input_line_pointer == ',')
341 {
342 ++input_line_pointer;
343 SKIP_WHITESPACE ();
344 }
345
346 expression (&exp);
347 if (exp.X_op != O_symbol)
348 {
349 as_bad ("bad .weakext directive");
350 ignore_rest_of_line ();
351 return;
352 }
353 symbol_set_value_expression (symbolP, &exp);
354 }
355
356 demand_empty_rest_of_line ();
357 }
358
359 /* This table describes all the machine specific pseudo-ops the assembler
360 has to support. The fields are:
361 Pseudo-op name without dot
362 Function to call to execute this pseudo-op
363 Integer arg to pass to the function. */
364 /* If the pseudo-op is not found in this table, it searches in the obj-elf.c,
365 and then in the read.c table. */
366 const pseudo_typeS md_pseudo_table[] =
367 {
368 {"lcomm", microblaze_s_lcomm, 1},
369 {"data", microblaze_s_data, 0},
370 {"data8", cons, 1}, /* Same as byte. */
371 {"data16", cons, 2}, /* Same as hword. */
372 {"data32", cons, 4}, /* Same as word. */
373 {"ent", s_func, 0}, /* Treat ent as function entry point. */
374 {"end", microblaze_s_func, 1}, /* Treat end as function end point. */
375 {"gpword", s_rva, 4}, /* gpword label => store resolved label address in data section. */
376 {"weakext", microblaze_s_weakext, 0},
377 {"rodata", microblaze_s_rdata, 0},
378 {"sdata2", microblaze_s_rdata, 1},
379 {"sdata", microblaze_s_sdata, 0},
380 {"bss", microblaze_s_bss, 0},
381 {"sbss", microblaze_s_bss, 1},
382 {"text", microblaze_s_text, 0},
383 {"word", cons, 4},
384 {"frame", s_ignore, 0},
385 {"mask", s_ignore, 0}, /* Emitted by gcc. */
386 {NULL, NULL, 0}
387 };
388
389 /* This function is called once, at assembler startup time. This should
390 set up all the tables, etc that the MD part of the assembler needs. */
391
392 void
393 md_begin (void)
394 {
395 struct op_code_struct * opcode;
396
397 opcode_hash_control = hash_new ();
398
399 /* Insert unique names into hash table. */
400 for (opcode = opcodes; opcode->name; opcode ++)
401 hash_insert (opcode_hash_control, opcode->name, (char *) opcode);
402 }
403
404 /* Try to parse a reg name. */
405
406 static char *
407 parse_reg (char * s, unsigned * reg)
408 {
409 unsigned tmpreg = 0;
410
411 /* Strip leading whitespace. */
412 while (isspace (* s))
413 ++ s;
414
415 if (strncasecmp (s, "rpc", 3) == 0)
416 {
417 *reg = REG_PC;
418 return s + 3;
419 }
420 else if (strncasecmp (s, "rmsr", 4) == 0)
421 {
422 *reg = REG_MSR;
423 return s + 4;
424 }
425 else if (strncasecmp (s, "rear", 4) == 0)
426 {
427 *reg = REG_EAR;
428 return s + 4;
429 }
430 else if (strncasecmp (s, "resr", 4) == 0)
431 {
432 *reg = REG_ESR;
433 return s + 4;
434 }
435 else if (strncasecmp (s, "rfsr", 4) == 0)
436 {
437 *reg = REG_FSR;
438 return s + 4;
439 }
440 else if (strncasecmp (s, "rbtr", 4) == 0)
441 {
442 *reg = REG_BTR;
443 return s + 4;
444 }
445 else if (strncasecmp (s, "redr", 4) == 0)
446 {
447 *reg = REG_EDR;
448 return s + 4;
449 }
450 /* MMU registers start. */
451 else if (strncasecmp (s, "rpid", 4) == 0)
452 {
453 *reg = REG_PID;
454 return s + 4;
455 }
456 else if (strncasecmp (s, "rzpr", 4) == 0)
457 {
458 *reg = REG_ZPR;
459 return s + 4;
460 }
461 else if (strncasecmp (s, "rtlbx", 5) == 0)
462 {
463 *reg = REG_TLBX;
464 return s + 5;
465 }
466 else if (strncasecmp (s, "rtlblo", 6) == 0)
467 {
468 *reg = REG_TLBLO;
469 return s + 6;
470 }
471 else if (strncasecmp (s, "rtlbhi", 6) == 0)
472 {
473 *reg = REG_TLBHI;
474 return s + 6;
475 }
476 else if (strncasecmp (s, "rtlbsx", 6) == 0)
477 {
478 *reg = REG_TLBSX;
479 return s + 6;
480 }
481 /* MMU registers end. */
482 else if (strncasecmp (s, "rpvr", 4) == 0)
483 {
484 if (isdigit (s[4]) && isdigit (s[5]))
485 {
486 tmpreg = (s[4]-'0')*10 + s[5] - '0';
487 s += 6;
488 }
489
490 else if (isdigit (s[4]))
491 {
492 tmpreg = s[4] - '0';
493 s += 5;
494 }
495 else
496 as_bad (_("register expected, but saw '%.6s'"), s);
497 if ((int) tmpreg >= MIN_PVR_REGNUM && tmpreg <= MAX_PVR_REGNUM)
498 *reg = REG_PVR + tmpreg;
499 else
500 {
501 as_bad (_("Invalid register number at '%.6s'"), s);
502 *reg = REG_PVR;
503 }
504 return s;
505 }
506 else if (strncasecmp (s, "rsp", 3) == 0)
507 {
508 *reg = REG_SP;
509 return s + 3;
510 }
511 else if (strncasecmp (s, "rfsl", 4) == 0)
512 {
513 if (isdigit (s[4]) && isdigit (s[5]))
514 {
515 tmpreg = (s[4] - '0') * 10 + s[5] - '0';
516 s += 6;
517 }
518 else if (isdigit (s[4]))
519 {
520 tmpreg = s[4] - '0';
521 s += 5;
522 }
523 else
524 as_bad (_("register expected, but saw '%.6s'"), s);
525
526 if ((int)tmpreg >= MIN_REGNUM && tmpreg <= MAX_REGNUM)
527 *reg = tmpreg;
528 else
529 {
530 as_bad (_("Invalid register number at '%.6s'"), s);
531 *reg = 0;
532 }
533 return s;
534 }
535 else
536 {
537 if (tolower (s[0]) == 'r')
538 {
539 if (isdigit (s[1]) && isdigit (s[2]))
540 {
541 tmpreg = (s[1] - '0') * 10 + s[2] - '0';
542 s += 3;
543 }
544 else if (isdigit (s[1]))
545 {
546 tmpreg = s[1] - '0';
547 s += 2;
548 }
549 else
550 as_bad (_("register expected, but saw '%.6s'"), s);
551
552 if ((int)tmpreg >= MIN_REGNUM && tmpreg <= MAX_REGNUM)
553 *reg = tmpreg;
554 else
555 {
556 as_bad (_("Invalid register number at '%.6s'"), s);
557 *reg = 0;
558 }
559 return s;
560 }
561 }
562 as_bad (_("register expected, but saw '%.6s'"), s);
563 *reg = 0;
564 return s;
565 }
566
567 static char *
568 parse_exp (char *s, expressionS *e)
569 {
570 char *save;
571 char *new;
572
573 /* Skip whitespace. */
574 while (isspace (* s))
575 ++ s;
576
577 save = input_line_pointer;
578 input_line_pointer = s;
579
580 expression (e);
581
582 if (e->X_op == O_absent)
583 as_fatal (_("missing operand"));
584
585 new = input_line_pointer;
586 input_line_pointer = save;
587
588 return new;
589 }
590
591 /* Symbol modifiers (@GOT, @PLT, @GOTOFF). */
592 #define IMM_GOT 1
593 #define IMM_PLT 2
594 #define IMM_GOTOFF 3
595
596 static symbolS * GOT_symbol;
597
598 #define GOT_SYMBOL_NAME "_GLOBAL_OFFSET_TABLE_"
599
600 static char *
601 parse_imm (char * s, expressionS * e, int min, int max)
602 {
603 char *new;
604 char *atp;
605
606 /* Find the start of "@GOT" or "@PLT" suffix (if any) */
607 for (atp = s; *atp != '@'; atp++)
608 if (is_end_of_line[(unsigned char) *atp])
609 break;
610
611 if (*atp == '@')
612 {
613 if (strncmp (atp + 1, "GOTOFF", 5) == 0)
614 {
615 *atp = 0;
616 e->X_md = IMM_GOTOFF;
617 }
618 else if (strncmp (atp + 1, "GOT", 3) == 0)
619 {
620 *atp = 0;
621 e->X_md = IMM_GOT;
622 }
623 else if (strncmp (atp + 1, "PLT", 3) == 0)
624 {
625 *atp = 0;
626 e->X_md = IMM_PLT;
627 }
628 else
629 {
630 atp = NULL;
631 e->X_md = 0;
632 }
633 *atp = 0;
634 }
635 else
636 {
637 atp = NULL;
638 e->X_md = 0;
639 }
640
641 if (atp && !GOT_symbol)
642 {
643 GOT_symbol = symbol_find_or_make (GOT_SYMBOL_NAME);
644 }
645
646 new = parse_exp (s, e);
647
648 if (e->X_op == O_absent)
649 ; /* An error message has already been emitted. */
650 else if ((e->X_op != O_constant && e->X_op != O_symbol) )
651 as_fatal (_("operand must be a constant or a label"));
652 else if ((e->X_op == O_constant) && ((int) e->X_add_number < min
653 || (int) e->X_add_number > max))
654 {
655 as_fatal (_("operand must be absolute in range %d..%d, not %d"),
656 min, max, (int) e->X_add_number);
657 }
658
659 if (atp)
660 {
661 *atp = '@'; /* restore back (needed?) */
662 if (new >= atp)
663 new += (e->X_md == IMM_GOTOFF)?7:4;
664 /* sizeof("@GOTOFF", "@GOT" or "@PLT") */
665
666 }
667 return new;
668 }
669
670 static char *
671 check_got (int * got_type, int * got_len)
672 {
673 char *new;
674 char *atp;
675 char *past_got;
676 int first, second;
677 char *tmpbuf;
678
679 /* Find the start of "@GOT" or "@PLT" suffix (if any). */
680 for (atp = input_line_pointer; *atp != '@'; atp++)
681 if (is_end_of_line[(unsigned char) *atp])
682 return NULL;
683
684 if (strncmp (atp + 1, "GOTOFF", 5) == 0)
685 {
686 *got_len = 6;
687 *got_type = IMM_GOTOFF;
688 }
689 else if (strncmp (atp + 1, "GOT", 3) == 0)
690 {
691 *got_len = 3;
692 *got_type = IMM_GOT;
693 }
694 else if (strncmp (atp + 1, "PLT", 3) == 0)
695 {
696 *got_len = 3;
697 *got_type = IMM_PLT;
698 }
699 else
700 return NULL;
701
702 if (!GOT_symbol)
703 GOT_symbol = symbol_find_or_make (GOT_SYMBOL_NAME);
704
705 first = atp - input_line_pointer;
706
707 past_got = atp + *got_len + 1;
708 for (new = past_got; !is_end_of_line[(unsigned char) *new++]; )
709 ;
710 second = new - past_got;
711 tmpbuf = xmalloc (first + second + 2); /* One extra byte for ' ' and one for NUL. */
712 memcpy (tmpbuf, input_line_pointer, first);
713 tmpbuf[first] = ' '; /* @GOTOFF is replaced with a single space. */
714 memcpy (tmpbuf + first + 1, past_got, second);
715 tmpbuf[first + second + 1] = '\0';
716
717 return tmpbuf;
718 }
719
720 extern void
721 parse_cons_expression_microblaze (expressionS *exp, int size)
722 {
723 if (size == 4)
724 {
725 /* Handle @GOTOFF et.al. */
726 char *save, *gotfree_copy;
727 int got_len, got_type;
728
729 save = input_line_pointer;
730 gotfree_copy = check_got (& got_type, & got_len);
731 if (gotfree_copy)
732 input_line_pointer = gotfree_copy;
733
734 expression (exp);
735
736 if (gotfree_copy)
737 {
738 exp->X_md = got_type;
739 input_line_pointer = save + (input_line_pointer - gotfree_copy)
740 + got_len;
741 free (gotfree_copy);
742 }
743 }
744 else
745 expression (exp);
746 }
747
748 /* This is the guts of the machine-dependent assembler. STR points to a
749 machine dependent instruction. This function is supposed to emit
750 the frags/bytes it assembles to. */
751
752 static char * str_microblaze_ro_anchor = "RO";
753 static char * str_microblaze_rw_anchor = "RW";
754
755 static bfd_boolean
756 check_spl_reg (unsigned * reg)
757 {
758 if ((*reg == REG_MSR) || (*reg == REG_PC)
759 || (*reg == REG_EAR) || (*reg == REG_ESR)
760 || (*reg == REG_FSR) || (*reg == REG_BTR) || (*reg == REG_EDR)
761 || (*reg == REG_PID) || (*reg == REG_ZPR)
762 || (*reg == REG_TLBX) || (*reg == REG_TLBLO)
763 || (*reg == REG_TLBHI) || (*reg == REG_TLBSX)
764 || (*reg >= REG_PVR+MIN_PVR_REGNUM && *reg <= REG_PVR+MAX_PVR_REGNUM))
765 return TRUE;
766
767 return FALSE;
768 }
769
770 /* Here we decide which fixups can be adjusted to make them relative to
771 the beginning of the section instead of the symbol. Basically we need
772 to make sure that the dynamic relocations are done correctly, so in
773 some cases we force the original symbol to be used. */
774
775 int
776 tc_microblaze_fix_adjustable (struct fix *fixP)
777 {
778 if (GOT_symbol && fixP->fx_subsy == GOT_symbol)
779 return 0;
780
781 if (fixP->fx_r_type == BFD_RELOC_MICROBLAZE_64_GOTOFF
782 || fixP->fx_r_type == BFD_RELOC_MICROBLAZE_32_GOTOFF
783 || fixP->fx_r_type == BFD_RELOC_MICROBLAZE_64_GOT
784 || fixP->fx_r_type == BFD_RELOC_MICROBLAZE_64_PLT)
785 return 0;
786
787 return 1;
788 }
789
790 void
791 md_assemble (char * str)
792 {
793 char * op_start;
794 char * op_end;
795 struct op_code_struct * opcode, *opcode1;
796 char * output = NULL;
797 int nlen = 0;
798 int i;
799 unsigned long inst, inst1;
800 unsigned reg1;
801 unsigned reg2;
802 unsigned reg3;
803 unsigned isize;
804 unsigned int imm, temp;
805 expressionS exp;
806 char name[20];
807
808 /* Drop leading whitespace. */
809 while (isspace (* str))
810 str ++;
811
812 /* Find the op code end. */
813 for (op_start = op_end = str;
814 * op_end && nlen < 20 && !is_end_of_line [(int)*op_end] && *op_end != ' ';
815 op_end++)
816 {
817 name[nlen] = op_start[nlen];
818 nlen++;
819 }
820
821 name [nlen] = 0;
822
823 if (nlen == 0)
824 {
825 as_bad (_("can't find opcode "));
826 return;
827 }
828
829 opcode = (struct op_code_struct *) hash_find (opcode_hash_control, name);
830 if (opcode == NULL)
831 {
832 as_bad (_("unknown opcode \"%s\""), name);
833 return;
834 }
835
836 inst = opcode->bit_sequence;
837 isize = 4;
838
839 switch (opcode->inst_type)
840 {
841 case INST_TYPE_RD_R1_R2:
842 if (strcmp (op_end, ""))
843 op_end = parse_reg (op_end + 1, &reg1); /* Get rd. */
844 else
845 {
846 as_fatal (_("Error in statement syntax"));
847 reg1 = 0;
848 }
849 if (strcmp (op_end, ""))
850 op_end = parse_reg (op_end + 1, &reg2); /* Get r1. */
851 else
852 {
853 as_fatal (_("Error in statement syntax"));
854 reg2 = 0;
855 }
856 if (strcmp (op_end, ""))
857 op_end = parse_reg (op_end + 1, &reg3); /* Get r2. */
858 else
859 {
860 as_fatal (_("Error in statement syntax"));
861 reg3 = 0;
862 }
863
864 /* Check for spl registers. */
865 if (check_spl_reg (& reg1))
866 as_fatal (_("Cannot use special register with this instruction"));
867 if (check_spl_reg (& reg2))
868 as_fatal (_("Cannot use special register with this instruction"));
869 if (check_spl_reg (& reg3))
870 as_fatal (_("Cannot use special register with this instruction"));
871
872 if (streq (name, "sub"))
873 {
874 /* sub rd, r1, r2 becomes rsub rd, r2, r1. */
875 inst |= (reg1 << RD_LOW) & RD_MASK;
876 inst |= (reg3 << RA_LOW) & RA_MASK;
877 inst |= (reg2 << RB_LOW) & RB_MASK;
878 }
879 else
880 {
881 inst |= (reg1 << RD_LOW) & RD_MASK;
882 inst |= (reg2 << RA_LOW) & RA_MASK;
883 inst |= (reg3 << RB_LOW) & RB_MASK;
884 }
885 output = frag_more (isize);
886 break;
887
888 case INST_TYPE_RD_R1_IMM:
889 if (strcmp (op_end, ""))
890 op_end = parse_reg (op_end + 1, &reg1); /* Get rd. */
891 else
892 {
893 as_fatal (_("Error in statement syntax"));
894 reg1 = 0;
895 }
896 if (strcmp (op_end, ""))
897 op_end = parse_reg (op_end + 1, &reg2); /* Get r1. */
898 else
899 {
900 as_fatal (_("Error in statement syntax"));
901 reg2 = 0;
902 }
903 if (strcmp (op_end, ""))
904 op_end = parse_imm (op_end + 1, & exp, MIN_IMM, MAX_IMM);
905 else
906 as_fatal (_("Error in statement syntax"));
907
908 /* Check for spl registers. */
909 if (check_spl_reg (& reg1))
910 as_fatal (_("Cannot use special register with this instruction"));
911 if (check_spl_reg (& reg2))
912 as_fatal (_("Cannot use special register with this instruction"));
913
914 if (exp.X_op != O_constant)
915 {
916 char *opc;
917 relax_substateT subtype;
918
919 if (streq (name, "lmi"))
920 as_fatal (_("lmi pseudo instruction should not use a label in imm field"));
921 else if (streq (name, "smi"))
922 as_fatal (_("smi pseudo instruction should not use a label in imm field"));
923
924 if (reg2 == REG_ROSDP)
925 opc = str_microblaze_ro_anchor;
926 else if (reg2 == REG_RWSDP)
927 opc = str_microblaze_rw_anchor;
928 else
929 opc = NULL;
930 if (exp.X_md == IMM_GOT)
931 subtype = GOT_OFFSET;
932 else if (exp.X_md == IMM_PLT)
933 subtype = PLT_OFFSET;
934 else if (exp.X_md == IMM_GOTOFF)
935 subtype = GOTOFF_OFFSET;
936 else
937 subtype = opcode->inst_offset_type;
938
939 output = frag_var (rs_machine_dependent,
940 isize * 2, /* maxm of 2 words. */
941 isize, /* minm of 1 word. */
942 subtype, /* PC-relative or not. */
943 exp.X_add_symbol,
944 exp.X_add_number,
945 opc);
946 imm = 0;
947 }
948 else
949 {
950 output = frag_more (isize);
951 imm = exp.X_add_number;
952 }
953
954 if (streq (name, "lmi") || streq (name, "smi"))
955 {
956 /* Load/store 32-d consecutive registers. Used on exit/entry
957 to subroutines to save and restore registers to stack.
958 Generate 32-d insts. */
959 int count;
960
961 count = 32 - reg1;
962 if (streq (name, "lmi"))
963 opcode = (struct op_code_struct *) hash_find (opcode_hash_control, "lwi");
964 else
965 opcode = (struct op_code_struct *) hash_find (opcode_hash_control, "swi");
966 if (opcode == NULL)
967 {
968 as_bad (_("unknown opcode \"%s\""), "lwi");
969 return;
970 }
971 inst = opcode->bit_sequence;
972 inst |= (reg1 << RD_LOW) & RD_MASK;
973 inst |= (reg2 << RA_LOW) & RA_MASK;
974 inst |= (imm << IMM_LOW) & IMM_MASK;
975
976 for (i = 0; i < count - 1; i++)
977 {
978 output[0] = INST_BYTE0 (inst);
979 output[1] = INST_BYTE1 (inst);
980 output[2] = INST_BYTE2 (inst);
981 output[3] = INST_BYTE3 (inst);
982 output = frag_more (isize);
983 imm = imm + 4;
984 reg1++;
985 inst = opcode->bit_sequence;
986 inst |= (reg1 << RD_LOW) & RD_MASK;
987 inst |= (reg2 << RA_LOW) & RA_MASK;
988 inst |= (imm << IMM_LOW) & IMM_MASK;
989 }
990 }
991 else
992 {
993 temp = imm & 0xFFFF8000;
994 if ((temp != 0) && (temp != 0xFFFF8000))
995 {
996 /* Needs an immediate inst. */
997 opcode1 = (struct op_code_struct *) hash_find (opcode_hash_control, "imm");
998 if (opcode1 == NULL)
999 {
1000 as_bad (_("unknown opcode \"%s\""), "imm");
1001 return;
1002 }
1003
1004 inst1 = opcode1->bit_sequence;
1005 inst1 |= ((imm & 0xFFFF0000) >> 16) & IMM_MASK;
1006 output[0] = INST_BYTE0 (inst1);
1007 output[1] = INST_BYTE1 (inst1);
1008 output[2] = INST_BYTE2 (inst1);
1009 output[3] = INST_BYTE3 (inst1);
1010 output = frag_more (isize);
1011 }
1012 inst |= (reg1 << RD_LOW) & RD_MASK;
1013 inst |= (reg2 << RA_LOW) & RA_MASK;
1014 inst |= (imm << IMM_LOW) & IMM_MASK;
1015 }
1016 break;
1017
1018 case INST_TYPE_RD_R1_IMM5:
1019 if (strcmp (op_end, ""))
1020 op_end = parse_reg (op_end + 1, &reg1); /* Get rd. */
1021 else
1022 {
1023 as_fatal (_("Error in statement syntax"));
1024 reg1 = 0;
1025 }
1026 if (strcmp (op_end, ""))
1027 op_end = parse_reg (op_end + 1, &reg2); /* Get r1. */
1028 else
1029 {
1030 as_fatal (_("Error in statement syntax"));
1031 reg2 = 0;
1032 }
1033 if (strcmp (op_end, ""))
1034 op_end = parse_imm (op_end + 1, & exp, MIN_IMM, MAX_IMM);
1035 else
1036 as_fatal (_("Error in statement syntax"));
1037
1038 /* Check for spl registers. */
1039 if (check_spl_reg (&reg1))
1040 as_fatal (_("Cannot use special register with this instruction"));
1041 if (check_spl_reg (&reg2))
1042 as_fatal (_("Cannot use special register with this instruction"));
1043
1044 if (exp.X_op != O_constant)
1045 as_warn (_("Symbol used as immediate for shift instruction"));
1046 else
1047 {
1048 output = frag_more (isize);
1049 imm = exp.X_add_number;
1050 }
1051
1052 if (imm != (imm % 32))
1053 {
1054 as_warn (_("Shift value > 32. using <value %% 32>"));
1055 imm = imm % 32;
1056 }
1057 inst |= (reg1 << RD_LOW) & RD_MASK;
1058 inst |= (reg2 << RA_LOW) & RA_MASK;
1059 inst |= (imm << IMM_LOW) & IMM5_MASK;
1060 break;
1061
1062 case INST_TYPE_R1_R2:
1063 if (strcmp (op_end, ""))
1064 op_end = parse_reg (op_end + 1, &reg1); /* Get r1. */
1065 else
1066 {
1067 as_fatal (_("Error in statement syntax"));
1068 reg1 = 0;
1069 }
1070 if (strcmp (op_end, ""))
1071 op_end = parse_reg (op_end + 1, &reg2); /* Get r2. */
1072 else
1073 {
1074 as_fatal (_("Error in statement syntax"));
1075 reg2 = 0;
1076 }
1077
1078 /* Check for spl registers. */
1079 if (check_spl_reg (& reg1))
1080 as_fatal (_("Cannot use special register with this instruction"));
1081 if (check_spl_reg (& reg2))
1082 as_fatal (_("Cannot use special register with this instruction"));
1083
1084 inst |= (reg1 << RA_LOW) & RA_MASK;
1085 inst |= (reg2 << RB_LOW) & RB_MASK;
1086 output = frag_more (isize);
1087 break;
1088
1089 case INST_TYPE_RD_R1:
1090 if (strcmp (op_end, ""))
1091 op_end = parse_reg (op_end + 1, &reg1); /* Get rd. */
1092 else
1093 {
1094 as_fatal (_("Error in statement syntax"));
1095 reg1 = 0;
1096 }
1097 if (strcmp (op_end, ""))
1098 op_end = parse_reg (op_end + 1, &reg2); /* Get r1. */
1099 else
1100 {
1101 as_fatal (_("Error in statement syntax"));
1102 reg2 =0;
1103 }
1104
1105 /* Check for spl registers. */
1106 if (check_spl_reg (&reg1))
1107 as_fatal (_("Cannot use special register with this instruction"));
1108 if (check_spl_reg (&reg2))
1109 as_fatal (_("Cannot use special register with this instruction"));
1110
1111 inst |= (reg1 << RD_LOW) & RD_MASK;
1112 inst |= (reg2 << RA_LOW) & RA_MASK;
1113 output = frag_more (isize);
1114 break;
1115
1116 case INST_TYPE_RD_RFSL:
1117 if (strcmp (op_end, ""))
1118 op_end = parse_reg (op_end + 1, &reg1); /* Get rd. */
1119 else
1120 {
1121 as_fatal (_("Error in statement syntax"));
1122 reg1 = 0;
1123 }
1124 if (strcmp (op_end, ""))
1125 op_end = parse_reg (op_end + 1, &imm); /* Get rfslN. */
1126 else
1127 {
1128 as_fatal (_("Error in statement syntax"));
1129 imm = 0;
1130 }
1131
1132 /* Check for spl registers. */
1133 if (check_spl_reg (&reg1))
1134 as_fatal (_("Cannot use special register with this instruction"));
1135
1136 inst |= (reg1 << RD_LOW) & RD_MASK;
1137 inst |= (imm << IMM_LOW) & RFSL_MASK;
1138 output = frag_more (isize);
1139 break;
1140
1141 case INST_TYPE_RD_IMM15:
1142 if (strcmp (op_end, ""))
1143 op_end = parse_reg (op_end + 1, &reg1); /* Get rd. */
1144 else
1145 {
1146 as_fatal (_("Error in statement syntax"));
1147 reg1 = 0;
1148 }
1149
1150 if (strcmp (op_end, ""))
1151 op_end = parse_imm (op_end + 1, & exp, MIN_IMM15, MAX_IMM15);
1152 else
1153 as_fatal (_("Error in statement syntax"));
1154
1155 /* Check for spl registers. */
1156 if (check_spl_reg (&reg1))
1157 as_fatal (_("Cannot use special register with this instruction"));
1158
1159 if (exp.X_op != O_constant)
1160 as_fatal (_("Symbol used as immediate value for msrset/msrclr instructions"));
1161 else
1162 {
1163 output = frag_more (isize);
1164 imm = exp.X_add_number;
1165 }
1166 inst |= (reg1 << RD_LOW) & RD_MASK;
1167 inst |= (imm << IMM_LOW) & IMM15_MASK;
1168 break;
1169
1170 case INST_TYPE_R1_RFSL:
1171 if (strcmp (op_end, ""))
1172 op_end = parse_reg (op_end + 1, &reg1); /* Get r1. */
1173 else
1174 {
1175 as_fatal (_("Error in statement syntax"));
1176 reg1 = 0;
1177 }
1178 if (strcmp (op_end, ""))
1179 op_end = parse_reg (op_end + 1, &imm); /* Get rfslN. */
1180 else
1181 {
1182 as_fatal (_("Error in statement syntax"));
1183 imm = 0;
1184 }
1185
1186 /* Check for spl registers. */
1187 if (check_spl_reg (&reg1))
1188 as_fatal (_("Cannot use special register with this instruction"));
1189
1190 inst |= (reg1 << RA_LOW) & RA_MASK;
1191 inst |= (imm << IMM_LOW) & RFSL_MASK;
1192 output = frag_more (isize);
1193 break;
1194
1195 case INST_TYPE_RFSL:
1196 if (strcmp (op_end, ""))
1197 op_end = parse_reg (op_end + 1, &imm); /* Get rfslN. */
1198 else
1199 {
1200 as_fatal (_("Error in statement syntax"));
1201 imm = 0;
1202 }
1203 /* Check for spl registers. */
1204 if (check_spl_reg (&reg1))
1205 as_fatal (_("Cannot use special register with this instruction"));
1206 inst |= (imm << IMM_LOW) & RFSL_MASK;
1207 output = frag_more (isize);
1208 break;
1209
1210 case INST_TYPE_R1:
1211 if (strcmp (op_end, ""))
1212 op_end = parse_reg (op_end + 1, &reg1); /* Get r1. */
1213 else
1214 {
1215 as_fatal (_("Error in statement syntax"));
1216 reg1 = 0;
1217 }
1218
1219 /* Check for spl registers. */
1220 if (check_spl_reg (&reg1))
1221 as_fatal (_("Cannot use special register with this instruction"));
1222
1223 inst |= (reg1 << RA_LOW) & RA_MASK;
1224 output = frag_more (isize);
1225 break;
1226
1227 /* For tuqula insn...:) */
1228 case INST_TYPE_RD:
1229 if (strcmp (op_end, ""))
1230 op_end = parse_reg (op_end + 1, &reg1); /* Get rd. */
1231 else
1232 {
1233 as_fatal (_("Error in statement syntax"));
1234 reg1 = 0;
1235 }
1236
1237 /* Check for spl registers. */
1238 if (check_spl_reg (&reg1))
1239 as_fatal (_("Cannot use special register with this instruction"));
1240
1241 inst |= (reg1 << RD_LOW) & RD_MASK;
1242 output = frag_more (isize);
1243 break;
1244
1245 case INST_TYPE_RD_SPECIAL:
1246 if (strcmp (op_end, ""))
1247 op_end = parse_reg (op_end + 1, &reg1); /* Get rd. */
1248 else
1249 {
1250 as_fatal (_("Error in statement syntax"));
1251 reg1 = 0;
1252 }
1253 if (strcmp (op_end, ""))
1254 op_end = parse_reg (op_end + 1, &reg2); /* Get r1. */
1255 else
1256 {
1257 as_fatal (_("Error in statement syntax"));
1258 reg2 = 0;
1259 }
1260
1261 if (reg2 == REG_MSR)
1262 imm = opcode->immval_mask | REG_MSR_MASK;
1263 else if (reg2 == REG_PC)
1264 imm = opcode->immval_mask | REG_PC_MASK;
1265 else if (reg2 == REG_EAR)
1266 imm = opcode->immval_mask | REG_EAR_MASK;
1267 else if (reg2 == REG_ESR)
1268 imm = opcode->immval_mask | REG_ESR_MASK;
1269 else if (reg2 == REG_FSR)
1270 imm = opcode->immval_mask | REG_FSR_MASK;
1271 else if (reg2 == REG_BTR)
1272 imm = opcode->immval_mask | REG_BTR_MASK;
1273 else if (reg2 == REG_EDR)
1274 imm = opcode->immval_mask | REG_EDR_MASK;
1275 else if (reg2 == REG_PID)
1276 imm = opcode->immval_mask | REG_PID_MASK;
1277 else if (reg2 == REG_ZPR)
1278 imm = opcode->immval_mask | REG_ZPR_MASK;
1279 else if (reg2 == REG_TLBX)
1280 imm = opcode->immval_mask | REG_TLBX_MASK;
1281 else if (reg2 == REG_TLBLO)
1282 imm = opcode->immval_mask | REG_TLBLO_MASK;
1283 else if (reg2 == REG_TLBHI)
1284 imm = opcode->immval_mask | REG_TLBHI_MASK;
1285 else if (reg2 >= (REG_PVR+MIN_PVR_REGNUM) && reg2 <= (REG_PVR+MAX_PVR_REGNUM))
1286 imm = opcode->immval_mask | REG_PVR_MASK | reg2;
1287 else
1288 as_fatal (_("invalid value for special purpose register"));
1289 inst |= (reg1 << RD_LOW) & RD_MASK;
1290 inst |= (imm << IMM_LOW) & IMM_MASK;
1291 output = frag_more (isize);
1292 break;
1293
1294 case INST_TYPE_SPECIAL_R1:
1295 if (strcmp (op_end, ""))
1296 op_end = parse_reg (op_end + 1, &reg1); /* Get rd. */
1297 else
1298 {
1299 as_fatal (_("Error in statement syntax"));
1300 reg1 = 0;
1301 }
1302 if (strcmp (op_end, ""))
1303 op_end = parse_reg (op_end + 1, &reg2); /* Get r1. */
1304 else
1305 {
1306 as_fatal (_("Error in statement syntax"));
1307 reg2 = 0;
1308 }
1309
1310 if (reg1 == REG_MSR)
1311 imm = opcode->immval_mask | REG_MSR_MASK;
1312 else if (reg1 == REG_PC)
1313 imm = opcode->immval_mask | REG_PC_MASK;
1314 else if (reg1 == REG_EAR)
1315 imm = opcode->immval_mask | REG_EAR_MASK;
1316 else if (reg1 == REG_ESR)
1317 imm = opcode->immval_mask | REG_ESR_MASK;
1318 else if (reg1 == REG_FSR)
1319 imm = opcode->immval_mask | REG_FSR_MASK;
1320 else if (reg1 == REG_BTR)
1321 imm = opcode->immval_mask | REG_BTR_MASK;
1322 else if (reg1 == REG_EDR)
1323 imm = opcode->immval_mask | REG_EDR_MASK;
1324 else if (reg1 == REG_PID)
1325 imm = opcode->immval_mask | REG_PID_MASK;
1326 else if (reg1 == REG_ZPR)
1327 imm = opcode->immval_mask | REG_ZPR_MASK;
1328 else if (reg1 == REG_TLBX)
1329 imm = opcode->immval_mask | REG_TLBX_MASK;
1330 else if (reg1 == REG_TLBLO)
1331 imm = opcode->immval_mask | REG_TLBLO_MASK;
1332 else if (reg1 == REG_TLBHI)
1333 imm = opcode->immval_mask | REG_TLBHI_MASK;
1334 else if (reg1 == REG_TLBSX)
1335 imm = opcode->immval_mask | REG_TLBSX_MASK;
1336 else
1337 as_fatal (_("invalid value for special purpose register"));
1338 inst |= (reg2 << RA_LOW) & RA_MASK;
1339 inst |= (imm << IMM_LOW) & IMM_MASK;
1340 output = frag_more (isize);
1341 break;
1342
1343 case INST_TYPE_RD_R1_SPECIAL:
1344 if (strcmp (op_end, ""))
1345 op_end = parse_reg (op_end + 1, &reg1); /* Get rd. */
1346 else
1347 {
1348 as_fatal (_("Error in statement syntax"));
1349 reg1 = 0;
1350 }
1351 if (strcmp (op_end, ""))
1352 op_end = parse_reg (op_end + 1, &reg2); /* Get r1. */
1353 else
1354 {
1355 as_fatal (_("Error in statement syntax"));
1356 reg2 =0;
1357 }
1358
1359 /* Check for spl registers. */
1360 if (check_spl_reg (&reg1))
1361 as_fatal (_("Cannot use special register with this instruction"));
1362 if (check_spl_reg (&reg2))
1363 as_fatal (_("Cannot use special register with this instruction"));
1364
1365 /* insn wic ra, rb => wic ra, ra, rb. */
1366 inst |= (reg1 << RD_LOW) & RD_MASK;
1367 inst |= (reg1 << RA_LOW) & RA_MASK;
1368 inst |= (reg2 << RB_LOW) & RB_MASK;
1369
1370 output = frag_more (isize);
1371 break;
1372
1373 case INST_TYPE_RD_R2:
1374 if (strcmp (op_end, ""))
1375 op_end = parse_reg (op_end + 1, &reg1); /* Get rd. */
1376 else
1377 {
1378 as_fatal (_("Error in statement syntax"));
1379 reg1 = 0;
1380 }
1381 if (strcmp (op_end, ""))
1382 op_end = parse_reg (op_end + 1, &reg2); /* Get r2. */
1383 else
1384 {
1385 as_fatal (_("Error in statement syntax"));
1386 reg2 = 0;
1387 }
1388
1389 /* Check for spl registers. */
1390 if (check_spl_reg (&reg1))
1391 as_fatal (_("Cannot use special register with this instruction"));
1392 if (check_spl_reg (&reg2))
1393 as_fatal (_("Cannot use special register with this instruction"));
1394
1395 inst |= (reg1 << RD_LOW) & RD_MASK;
1396 inst |= (reg2 << RB_LOW) & RB_MASK;
1397 output = frag_more (isize);
1398 break;
1399
1400 case INST_TYPE_R1_IMM:
1401 if (strcmp (op_end, ""))
1402 op_end = parse_reg (op_end + 1, &reg1); /* Get r1. */
1403 else
1404 {
1405 as_fatal (_("Error in statement syntax"));
1406 reg1 = 0;
1407 }
1408 if (strcmp (op_end, ""))
1409 op_end = parse_imm (op_end + 1, & exp, MIN_IMM, MAX_IMM);
1410 else
1411 as_fatal (_("Error in statement syntax"));
1412
1413 /* Check for spl registers. */
1414 if (check_spl_reg (&reg1))
1415 as_fatal (_("Cannot use special register with this instruction"));
1416
1417 if (exp.X_op != O_constant)
1418 {
1419 char *opc = NULL;
1420 relax_substateT subtype;
1421
1422 if (exp.X_md == IMM_GOT)
1423 subtype = GOT_OFFSET;
1424 else if (exp.X_md == IMM_PLT)
1425 subtype = PLT_OFFSET;
1426 else
1427 subtype = opcode->inst_offset_type;
1428 output = frag_var (rs_machine_dependent,
1429 isize * 2, /* maxm of 2 words. */
1430 isize, /* minm of 1 word. */
1431 subtype, /* PC-relative or not. */
1432 exp.X_add_symbol,
1433 exp.X_add_number,
1434 opc);
1435 imm = 0;
1436 }
1437 else
1438 {
1439 output = frag_more (isize);
1440 imm = exp.X_add_number;
1441 }
1442
1443 temp = imm & 0xFFFF8000;
1444 if ((temp != 0) && (temp != 0xFFFF8000))
1445 {
1446 /* Needs an immediate inst. */
1447 opcode1 = (struct op_code_struct *) hash_find (opcode_hash_control, "imm");
1448 if (opcode1 == NULL)
1449 {
1450 as_bad (_("unknown opcode \"%s\""), "imm");
1451 return;
1452 }
1453
1454 inst1 = opcode1->bit_sequence;
1455 inst1 |= ((imm & 0xFFFF0000) >> 16) & IMM_MASK;
1456 output[0] = INST_BYTE0 (inst1);
1457 output[1] = INST_BYTE1 (inst1);
1458 output[2] = INST_BYTE2 (inst1);
1459 output[3] = INST_BYTE3 (inst1);
1460 output = frag_more (isize);
1461 }
1462
1463 inst |= (reg1 << RA_LOW) & RA_MASK;
1464 inst |= (imm << IMM_LOW) & IMM_MASK;
1465 break;
1466
1467 case INST_TYPE_RD_IMM:
1468 if (strcmp (op_end, ""))
1469 op_end = parse_reg (op_end + 1, &reg1); /* Get rd. */
1470 else
1471 {
1472 as_fatal (_("Error in statement syntax"));
1473 reg1 = 0;
1474 }
1475 if (strcmp (op_end, ""))
1476 op_end = parse_imm (op_end + 1, & exp, MIN_IMM, MAX_IMM);
1477 else
1478 as_fatal (_("Error in statement syntax"));
1479
1480 /* Check for spl registers. */
1481 if (check_spl_reg (&reg1))
1482 as_fatal (_("Cannot use special register with this instruction"));
1483
1484 if (exp.X_op != O_constant)
1485 {
1486 char *opc = NULL;
1487 relax_substateT subtype;
1488
1489 if (exp.X_md == IMM_GOT)
1490 subtype = GOT_OFFSET;
1491 else if (exp.X_md == IMM_PLT)
1492 subtype = PLT_OFFSET;
1493 else
1494 subtype = opcode->inst_offset_type;
1495 output = frag_var (rs_machine_dependent,
1496 isize * 2, /* maxm of 2 words. */
1497 isize, /* minm of 1 word. */
1498 subtype, /* PC-relative or not. */
1499 exp.X_add_symbol,
1500 exp.X_add_number,
1501 opc);
1502 imm = 0;
1503 }
1504 else
1505 {
1506 output = frag_more (isize);
1507 imm = exp.X_add_number;
1508 }
1509
1510 temp = imm & 0xFFFF8000;
1511 if ((temp != 0) && (temp != 0xFFFF8000))
1512 {
1513 /* Needs an immediate inst. */
1514 opcode1 = (struct op_code_struct *) hash_find (opcode_hash_control, "imm");
1515 if (opcode1 == NULL)
1516 {
1517 as_bad (_("unknown opcode \"%s\""), "imm");
1518 return;
1519 }
1520
1521 inst1 = opcode1->bit_sequence;
1522 inst1 |= ((imm & 0xFFFF0000) >> 16) & IMM_MASK;
1523 output[0] = INST_BYTE0 (inst1);
1524 output[1] = INST_BYTE1 (inst1);
1525 output[2] = INST_BYTE2 (inst1);
1526 output[3] = INST_BYTE3 (inst1);
1527 output = frag_more (isize);
1528 }
1529
1530 inst |= (reg1 << RD_LOW) & RD_MASK;
1531 inst |= (imm << IMM_LOW) & IMM_MASK;
1532 break;
1533
1534 case INST_TYPE_R2:
1535 if (strcmp (op_end, ""))
1536 op_end = parse_reg (op_end + 1, &reg2); /* Get r2. */
1537 else
1538 {
1539 as_fatal (_("Error in statement syntax"));
1540 reg2 = 0;
1541 }
1542
1543 /* Check for spl registers. */
1544 if (check_spl_reg (&reg2))
1545 as_fatal (_("Cannot use special register with this instruction"));
1546
1547 inst |= (reg2 << RB_LOW) & RB_MASK;
1548 output = frag_more (isize);
1549 break;
1550
1551 case INST_TYPE_IMM:
1552 if (streq (name, "imm"))
1553 as_fatal (_("An IMM instruction should not be present in the .s file"));
1554
1555 op_end = parse_imm (op_end + 1, & exp, MIN_IMM, MAX_IMM);
1556
1557 if (exp.X_op != O_constant)
1558 {
1559 char *opc = NULL;
1560 relax_substateT subtype;
1561
1562 if (exp.X_md == IMM_GOT)
1563 subtype = GOT_OFFSET;
1564 else if (exp.X_md == IMM_PLT)
1565 subtype = PLT_OFFSET;
1566 else
1567 subtype = opcode->inst_offset_type;
1568 output = frag_var (rs_machine_dependent,
1569 isize * 2, /* maxm of 2 words. */
1570 isize, /* minm of 1 word. */
1571 subtype, /* PC-relative or not. */
1572 exp.X_add_symbol,
1573 exp.X_add_number,
1574 opc);
1575 imm = 0;
1576 }
1577 else
1578 {
1579 output = frag_more (isize);
1580 imm = exp.X_add_number;
1581 }
1582
1583
1584 temp = imm & 0xFFFF8000;
1585 if ((temp != 0) && (temp != 0xFFFF8000))
1586 {
1587 /* Needs an immediate inst. */
1588 opcode1 = (struct op_code_struct *) hash_find (opcode_hash_control, "imm");
1589 if (opcode1 == NULL)
1590 {
1591 as_bad (_("unknown opcode \"%s\""), "imm");
1592 return;
1593 }
1594
1595 inst1 = opcode1->bit_sequence;
1596 inst1 |= ((imm & 0xFFFF0000) >> 16) & IMM_MASK;
1597 output[0] = INST_BYTE0 (inst1);
1598 output[1] = INST_BYTE1 (inst1);
1599 output[2] = INST_BYTE2 (inst1);
1600 output[3] = INST_BYTE3 (inst1);
1601 output = frag_more (isize);
1602 }
1603 inst |= (imm << IMM_LOW) & IMM_MASK;
1604 break;
1605
1606 case INST_TYPE_NONE:
1607 output = frag_more (isize);
1608 break;
1609
1610 default:
1611 as_fatal (_("unimplemented opcode \"%s\""), name);
1612 }
1613
1614 /* Drop whitespace after all the operands have been parsed. */
1615 while (isspace (* op_end))
1616 op_end ++;
1617
1618 /* Give warning message if the insn has more operands than required. */
1619 if (strcmp (op_end, opcode->name) && strcmp (op_end, ""))
1620 as_warn (_("ignoring operands: %s "), op_end);
1621
1622 output[0] = INST_BYTE0 (inst);
1623 output[1] = INST_BYTE1 (inst);
1624 output[2] = INST_BYTE2 (inst);
1625 output[3] = INST_BYTE3 (inst);
1626
1627 #ifdef OBJ_ELF
1628 dwarf2_emit_insn (4);
1629 #endif
1630 }
1631
1632 symbolS *
1633 md_undefined_symbol (char * name ATTRIBUTE_UNUSED)
1634 {
1635 return NULL;
1636 }
1637
1638 /* Various routines to kill one day. */
1639 /* Equal to MAX_PRECISION in atof-ieee.c */
1640 #define MAX_LITTLENUMS 6
1641
1642 /* Turn a string in input_line_pointer into a floating point constant of type
1643 type, and store the appropriate bytes in *litP. The number of LITTLENUMS
1644 emitted is stored in *sizeP. An error message is returned, or NULL on OK.*/
1645 char *
1646 md_atof (int type, char * litP, int * sizeP)
1647 {
1648 int prec;
1649 LITTLENUM_TYPE words[MAX_LITTLENUMS];
1650 int i;
1651 char * t;
1652
1653 switch (type)
1654 {
1655 case 'f':
1656 case 'F':
1657 case 's':
1658 case 'S':
1659 prec = 2;
1660 break;
1661
1662 case 'd':
1663 case 'D':
1664 case 'r':
1665 case 'R':
1666 prec = 4;
1667 break;
1668
1669 case 'x':
1670 case 'X':
1671 prec = 6;
1672 break;
1673
1674 case 'p':
1675 case 'P':
1676 prec = 6;
1677 break;
1678
1679 default:
1680 *sizeP = 0;
1681 return _("Bad call to MD_NTOF()");
1682 }
1683
1684 t = atof_ieee (input_line_pointer, type, words);
1685
1686 if (t)
1687 input_line_pointer = t;
1688
1689 *sizeP = prec * sizeof (LITTLENUM_TYPE);
1690
1691 if (! target_big_endian)
1692 {
1693 for (i = prec - 1; i >= 0; i--)
1694 {
1695 md_number_to_chars (litP, (valueT) words[i],
1696 sizeof (LITTLENUM_TYPE));
1697 litP += sizeof (LITTLENUM_TYPE);
1698 }
1699 }
1700 else
1701 for (i = 0; i < prec; i++)
1702 {
1703 md_number_to_chars (litP, (valueT) words[i],
1704 sizeof (LITTLENUM_TYPE));
1705 litP += sizeof (LITTLENUM_TYPE);
1706 }
1707
1708 return NULL;
1709 }
1710 \f
1711 const char * md_shortopts = "";
1712
1713 struct option md_longopts[] =
1714 {
1715 { NULL, no_argument, NULL, 0}
1716 };
1717
1718 size_t md_longopts_size = sizeof (md_longopts);
1719
1720 int md_short_jump_size;
1721
1722 void
1723 md_create_short_jump (char * ptr ATTRIBUTE_UNUSED,
1724 addressT from_Nddr ATTRIBUTE_UNUSED,
1725 addressT to_Nddr ATTRIBUTE_UNUSED,
1726 fragS * frag ATTRIBUTE_UNUSED,
1727 symbolS * to_symbol ATTRIBUTE_UNUSED)
1728 {
1729 as_fatal (_("failed sanity check: short_jump"));
1730 }
1731
1732 void
1733 md_create_long_jump (char * ptr ATTRIBUTE_UNUSED,
1734 addressT from_Nddr ATTRIBUTE_UNUSED,
1735 addressT to_Nddr ATTRIBUTE_UNUSED,
1736 fragS * frag ATTRIBUTE_UNUSED,
1737 symbolS * to_symbol ATTRIBUTE_UNUSED)
1738 {
1739 as_fatal (_("failed sanity check: long_jump"));
1740 }
1741
1742 /* Called after relaxing, change the frags so they know how big they are. */
1743
1744 void
1745 md_convert_frag (bfd * abfd ATTRIBUTE_UNUSED,
1746 segT sec ATTRIBUTE_UNUSED,
1747 fragS * fragP)
1748 {
1749 fixS *fixP;
1750
1751 switch (fragP->fr_subtype)
1752 {
1753 case UNDEFINED_PC_OFFSET:
1754 fix_new (fragP, fragP->fr_fix, INST_WORD_SIZE * 2, fragP->fr_symbol,
1755 fragP->fr_offset, TRUE, BFD_RELOC_64_PCREL);
1756 fragP->fr_fix += INST_WORD_SIZE * 2;
1757 fragP->fr_var = 0;
1758 break;
1759 case DEFINED_ABS_SEGMENT:
1760 if (fragP->fr_symbol == GOT_symbol)
1761 fix_new (fragP, fragP->fr_fix, INST_WORD_SIZE * 2, fragP->fr_symbol,
1762 fragP->fr_offset, TRUE, BFD_RELOC_MICROBLAZE_64_GOTPC);
1763 else
1764 fix_new (fragP, fragP->fr_fix, INST_WORD_SIZE * 2, fragP->fr_symbol,
1765 fragP->fr_offset, FALSE, BFD_RELOC_64);
1766 fragP->fr_fix += INST_WORD_SIZE * 2;
1767 fragP->fr_var = 0;
1768 break;
1769 case DEFINED_RO_SEGMENT:
1770 fix_new (fragP, fragP->fr_fix, INST_WORD_SIZE, fragP->fr_symbol,
1771 fragP->fr_offset, FALSE, BFD_RELOC_MICROBLAZE_32_ROSDA);
1772 fragP->fr_fix += INST_WORD_SIZE;
1773 fragP->fr_var = 0;
1774 break;
1775 case DEFINED_RW_SEGMENT:
1776 fix_new (fragP, fragP->fr_fix, INST_WORD_SIZE, fragP->fr_symbol,
1777 fragP->fr_offset, FALSE, BFD_RELOC_MICROBLAZE_32_RWSDA);
1778 fragP->fr_fix += INST_WORD_SIZE;
1779 fragP->fr_var = 0;
1780 break;
1781 case DEFINED_PC_OFFSET:
1782 fix_new (fragP, fragP->fr_fix, INST_WORD_SIZE, fragP->fr_symbol,
1783 fragP->fr_offset, TRUE, BFD_RELOC_MICROBLAZE_32_LO_PCREL);
1784 fragP->fr_fix += INST_WORD_SIZE;
1785 fragP->fr_var = 0;
1786 break;
1787 case LARGE_DEFINED_PC_OFFSET:
1788 fix_new (fragP, fragP->fr_fix, INST_WORD_SIZE * 2, fragP->fr_symbol,
1789 fragP->fr_offset, TRUE, BFD_RELOC_64_PCREL);
1790 fragP->fr_fix += INST_WORD_SIZE * 2;
1791 fragP->fr_var = 0;
1792 break;
1793 case GOT_OFFSET:
1794 fix_new (fragP, fragP->fr_fix, INST_WORD_SIZE * 2, fragP->fr_symbol,
1795 fragP->fr_offset, FALSE, BFD_RELOC_MICROBLAZE_64_GOT);
1796 fragP->fr_fix += INST_WORD_SIZE * 2;
1797 fragP->fr_var = 0;
1798 break;
1799 case PLT_OFFSET:
1800 fixP = fix_new (fragP, fragP->fr_fix, INST_WORD_SIZE * 2, fragP->fr_symbol,
1801 fragP->fr_offset, TRUE, BFD_RELOC_MICROBLAZE_64_PLT);
1802 /* fixP->fx_plt = 1; */
1803 fragP->fr_fix += INST_WORD_SIZE * 2;
1804 fragP->fr_var = 0;
1805 break;
1806 case GOTOFF_OFFSET:
1807 fix_new (fragP, fragP->fr_fix, INST_WORD_SIZE * 2, fragP->fr_symbol,
1808 fragP->fr_offset, FALSE, BFD_RELOC_MICROBLAZE_64_GOTOFF);
1809 fragP->fr_fix += INST_WORD_SIZE * 2;
1810 fragP->fr_var = 0;
1811 break;
1812
1813 default:
1814 abort ();
1815 }
1816 }
1817
1818 /* Applies the desired value to the specified location.
1819 Also sets up addends for 'rela' type relocations. */
1820 void
1821 md_apply_fix (fixS * fixP,
1822 valueT * valp,
1823 segT segment)
1824 {
1825 char * buf = fixP->fx_where + fixP->fx_frag->fr_literal;
1826 char * file = fixP->fx_file ? fixP->fx_file : _("unknown");
1827 const char * symname;
1828 /* Note: use offsetT because it is signed, valueT is unsigned. */
1829 offsetT val = (offsetT) * valp;
1830 int i;
1831 struct op_code_struct * opcode1;
1832 unsigned long inst1;
1833
1834 symname = fixP->fx_addsy ? S_GET_NAME (fixP->fx_addsy) : _("<unknown>");
1835
1836 /* fixP->fx_offset is supposed to be set up correctly for all
1837 symbol relocations. */
1838 if (fixP->fx_addsy == NULL)
1839 {
1840 if (!fixP->fx_pcrel)
1841 fixP->fx_offset = val; /* Absolute relocation. */
1842 else
1843 fprintf (stderr, "NULL symbol PC-relative relocation? offset = %08x, val = %08x\n",
1844 (unsigned int) fixP->fx_offset, (unsigned int) val);
1845 }
1846
1847 /* If we aren't adjusting this fixup to be against the section
1848 symbol, we need to adjust the value. */
1849 if (fixP->fx_addsy != NULL)
1850 {
1851 if (S_IS_WEAK (fixP->fx_addsy)
1852 || (symbol_used_in_reloc_p (fixP->fx_addsy)
1853 && (((bfd_get_section_flags (stdoutput,
1854 S_GET_SEGMENT (fixP->fx_addsy))
1855 & SEC_LINK_ONCE) != 0)
1856 || !strncmp (segment_name (S_GET_SEGMENT (fixP->fx_addsy)),
1857 ".gnu.linkonce",
1858 sizeof (".gnu.linkonce") - 1))))
1859 {
1860 val -= S_GET_VALUE (fixP->fx_addsy);
1861 if (val != 0 && ! fixP->fx_pcrel)
1862 {
1863 /* In this case, the bfd_install_relocation routine will
1864 incorrectly add the symbol value back in. We just want
1865 the addend to appear in the object file.
1866 FIXME: If this makes VALUE zero, we're toast. */
1867 val -= S_GET_VALUE (fixP->fx_addsy);
1868 }
1869 }
1870 }
1871
1872 /* If the fix is relative to a symbol which is not defined, or not
1873 in the same segment as the fix, we cannot resolve it here. */
1874 /* fixP->fx_addsy is NULL if valp contains the entire relocation. */
1875 if (fixP->fx_addsy != NULL
1876 && (!S_IS_DEFINED (fixP->fx_addsy)
1877 || (S_GET_SEGMENT (fixP->fx_addsy) != segment)))
1878 {
1879 fixP->fx_done = 0;
1880 #ifdef OBJ_ELF
1881 /* For ELF we can just return and let the reloc that will be generated
1882 take care of everything. For COFF we still have to insert 'val'
1883 into the insn since the addend field will be ignored. */
1884 /* return; */
1885 #endif
1886 }
1887 /* All fixups in the text section must be handled in the linker. */
1888 else if (segment->flags & SEC_CODE)
1889 fixP->fx_done = 0;
1890 else if (!fixP->fx_pcrel && fixP->fx_addsy != NULL)
1891 fixP->fx_done = 0;
1892 else
1893 fixP->fx_done = 1;
1894
1895 switch (fixP->fx_r_type)
1896 {
1897 case BFD_RELOC_MICROBLAZE_32_LO:
1898 case BFD_RELOC_MICROBLAZE_32_LO_PCREL:
1899 if (target_big_endian)
1900 {
1901 buf[2] |= ((val >> 8) & 0xff);
1902 buf[3] |= (val & 0xff);
1903 }
1904 else
1905 {
1906 buf[1] |= ((val >> 8) & 0xff);
1907 buf[0] |= (val & 0xff);
1908 }
1909 break;
1910 case BFD_RELOC_MICROBLAZE_32_ROSDA:
1911 case BFD_RELOC_MICROBLAZE_32_RWSDA:
1912 /* Don't do anything if the symbol is not defined. */
1913 if (fixP->fx_addsy == NULL || S_IS_DEFINED (fixP->fx_addsy))
1914 {
1915 if (((val & 0xFFFF8000) != 0) && ((val & 0xFFFF8000) != 0xFFFF8000))
1916 as_bad_where (file, fixP->fx_line,
1917 _("pcrel for branch to %s too far (0x%x)"),
1918 symname, (int) val);
1919 if (target_big_endian)
1920 {
1921 buf[2] |= ((val >> 8) & 0xff);
1922 buf[3] |= (val & 0xff);
1923 }
1924 else
1925 {
1926 buf[1] |= ((val >> 8) & 0xff);
1927 buf[0] |= (val & 0xff);
1928 }
1929 }
1930 break;
1931 case BFD_RELOC_32:
1932 case BFD_RELOC_RVA:
1933 case BFD_RELOC_32_PCREL:
1934 case BFD_RELOC_MICROBLAZE_32_SYM_OP_SYM:
1935 /* Don't do anything if the symbol is not defined. */
1936 if (fixP->fx_addsy == NULL || S_IS_DEFINED (fixP->fx_addsy))
1937 {
1938 if (target_big_endian)
1939 {
1940 buf[0] |= ((val >> 24) & 0xff);
1941 buf[1] |= ((val >> 16) & 0xff);
1942 buf[2] |= ((val >> 8) & 0xff);
1943 buf[3] |= (val & 0xff);
1944 }
1945 else
1946 {
1947 buf[3] |= ((val >> 24) & 0xff);
1948 buf[2] |= ((val >> 16) & 0xff);
1949 buf[1] |= ((val >> 8) & 0xff);
1950 buf[0] |= (val & 0xff);
1951 }
1952 }
1953 break;
1954 case BFD_RELOC_64_PCREL:
1955 case BFD_RELOC_64:
1956 /* Add an imm instruction. First save the current instruction. */
1957 for (i = 0; i < INST_WORD_SIZE; i++)
1958 buf[i + INST_WORD_SIZE] = buf[i];
1959
1960 /* Generate the imm instruction. */
1961 opcode1 = (struct op_code_struct *) hash_find (opcode_hash_control, "imm");
1962 if (opcode1 == NULL)
1963 {
1964 as_bad (_("unknown opcode \"%s\""), "imm");
1965 return;
1966 }
1967
1968 inst1 = opcode1->bit_sequence;
1969 if (fixP->fx_addsy == NULL || S_IS_DEFINED (fixP->fx_addsy))
1970 inst1 |= ((val & 0xFFFF0000) >> 16) & IMM_MASK;
1971
1972 buf[0] = INST_BYTE0 (inst1);
1973 buf[1] = INST_BYTE1 (inst1);
1974 buf[2] = INST_BYTE2 (inst1);
1975 buf[3] = INST_BYTE3 (inst1);
1976
1977 /* Add the value only if the symbol is defined. */
1978 if (fixP->fx_addsy == NULL || S_IS_DEFINED (fixP->fx_addsy))
1979 {
1980 if (target_big_endian)
1981 {
1982 buf[6] |= ((val >> 8) & 0xff);
1983 buf[7] |= (val & 0xff);
1984 }
1985 else
1986 {
1987 buf[5] |= ((val >> 8) & 0xff);
1988 buf[4] |= (val & 0xff);
1989 }
1990 }
1991 break;
1992
1993 case BFD_RELOC_MICROBLAZE_64_GOTPC:
1994 case BFD_RELOC_MICROBLAZE_64_GOT:
1995 case BFD_RELOC_MICROBLAZE_64_PLT:
1996 case BFD_RELOC_MICROBLAZE_64_GOTOFF:
1997 /* Add an imm instruction. First save the current instruction. */
1998 for (i = 0; i < INST_WORD_SIZE; i++)
1999 buf[i + INST_WORD_SIZE] = buf[i];
2000
2001 /* Generate the imm instruction. */
2002 opcode1 = (struct op_code_struct *) hash_find (opcode_hash_control, "imm");
2003 if (opcode1 == NULL)
2004 {
2005 as_bad (_("unknown opcode \"%s\""), "imm");
2006 return;
2007 }
2008
2009 inst1 = opcode1->bit_sequence;
2010
2011 /* We can fixup call to a defined non-global address
2012 within the same section only. */
2013 buf[0] = INST_BYTE0 (inst1);
2014 buf[1] = INST_BYTE1 (inst1);
2015 buf[2] = INST_BYTE2 (inst1);
2016 buf[3] = INST_BYTE3 (inst1);
2017 return;
2018
2019 default:
2020 break;
2021 }
2022
2023 if (fixP->fx_addsy == NULL)
2024 {
2025 /* This fixup has been resolved. Create a reloc in case the linker
2026 moves code around due to relaxing. */
2027 if (fixP->fx_r_type == BFD_RELOC_64_PCREL)
2028 fixP->fx_r_type = BFD_RELOC_MICROBLAZE_64_NONE;
2029 else
2030 fixP->fx_r_type = BFD_RELOC_NONE;
2031 fixP->fx_addsy = section_symbol (absolute_section);
2032 }
2033 return;
2034 }
2035
2036 void
2037 md_operand (expressionS * expressionP)
2038 {
2039 /* Ignore leading hash symbol, if present. */
2040 if (*input_line_pointer == '#')
2041 {
2042 input_line_pointer ++;
2043 expression (expressionP);
2044 }
2045 }
2046
2047 /* Called just before address relaxation, return the length
2048 by which a fragment must grow to reach it's destination. */
2049
2050 int
2051 md_estimate_size_before_relax (fragS * fragP,
2052 segT segment_type)
2053 {
2054 sbss_segment = bfd_get_section_by_name (stdoutput, ".sbss");
2055 sbss2_segment = bfd_get_section_by_name (stdoutput, ".sbss2");
2056 sdata_segment = bfd_get_section_by_name (stdoutput, ".sdata");
2057 sdata2_segment = bfd_get_section_by_name (stdoutput, ".sdata2");
2058
2059 switch (fragP->fr_subtype)
2060 {
2061 case INST_PC_OFFSET:
2062 /* Used to be a PC-relative branch. */
2063 if (!fragP->fr_symbol)
2064 {
2065 /* We know the abs value: Should never happen. */
2066 as_bad (_("Absolute PC-relative value in relaxation code. Assembler error....."));
2067 abort ();
2068 }
2069 else if ((S_GET_SEGMENT (fragP->fr_symbol) == segment_type))
2070 {
2071 fragP->fr_subtype = DEFINED_PC_OFFSET;
2072 /* Don't know now whether we need an imm instruction. */
2073 fragP->fr_var = INST_WORD_SIZE;
2074 }
2075 else if (S_IS_DEFINED (fragP->fr_symbol)
2076 && (((S_GET_SEGMENT (fragP->fr_symbol))->flags & SEC_CODE) == 0))
2077 {
2078 /* Cannot have a PC-relative branch to a diff segment. */
2079 as_bad (_("PC relative branch to label %s which is not in the instruction space"),
2080 S_GET_NAME (fragP->fr_symbol));
2081 fragP->fr_subtype = UNDEFINED_PC_OFFSET;
2082 fragP->fr_var = INST_WORD_SIZE*2;
2083 }
2084 else
2085 {
2086 fragP->fr_subtype = UNDEFINED_PC_OFFSET;
2087 fragP->fr_var = INST_WORD_SIZE*2;
2088 }
2089 break;
2090
2091 case INST_NO_OFFSET:
2092 /* Used to be a reference to somewhere which was unknown. */
2093 if (fragP->fr_symbol)
2094 {
2095 if (fragP->fr_opcode == NULL)
2096 {
2097 /* Used as an absolute value. */
2098 fragP->fr_subtype = DEFINED_ABS_SEGMENT;
2099 /* Variable part does not change. */
2100 fragP->fr_var = INST_WORD_SIZE*2;
2101 }
2102 else if (streq (fragP->fr_opcode, str_microblaze_ro_anchor))
2103 {
2104 /* It is accessed using the small data read only anchor. */
2105 if ((S_GET_SEGMENT (fragP->fr_symbol) == &bfd_com_section)
2106 || (S_GET_SEGMENT (fragP->fr_symbol) == sdata2_segment)
2107 || (S_GET_SEGMENT (fragP->fr_symbol) == sbss2_segment)
2108 || (! S_IS_DEFINED (fragP->fr_symbol)))
2109 {
2110 fragP->fr_subtype = DEFINED_RO_SEGMENT;
2111 fragP->fr_var = INST_WORD_SIZE;
2112 }
2113 else
2114 {
2115 /* Variable not in small data read only segment accessed
2116 using small data read only anchor. */
2117 char *file = fragP->fr_file ? fragP->fr_file : _("unknown");
2118
2119 as_bad_where (file, fragP->fr_line,
2120 _("Variable is accessed using small data read "
2121 "only anchor, but it is not in the small data "
2122 "read only section"));
2123 fragP->fr_subtype = DEFINED_RO_SEGMENT;
2124 fragP->fr_var = INST_WORD_SIZE;
2125 }
2126 }
2127 else if (streq (fragP->fr_opcode, str_microblaze_rw_anchor))
2128 {
2129 if ((S_GET_SEGMENT (fragP->fr_symbol) == &bfd_com_section)
2130 || (S_GET_SEGMENT (fragP->fr_symbol) == sdata_segment)
2131 || (S_GET_SEGMENT (fragP->fr_symbol) == sbss_segment)
2132 || (!S_IS_DEFINED (fragP->fr_symbol)))
2133 {
2134 /* It is accessed using the small data read write anchor. */
2135 fragP->fr_subtype = DEFINED_RW_SEGMENT;
2136 fragP->fr_var = INST_WORD_SIZE;
2137 }
2138 else
2139 {
2140 char *file = fragP->fr_file ? fragP->fr_file : _("unknown");
2141
2142 as_bad_where (file, fragP->fr_line,
2143 _("Variable is accessed using small data read "
2144 "write anchor, but it is not in the small data "
2145 "read write section"));
2146 fragP->fr_subtype = DEFINED_RW_SEGMENT;
2147 fragP->fr_var = INST_WORD_SIZE;
2148 }
2149 }
2150 else
2151 {
2152 as_bad (_("Incorrect fr_opcode value in frag. Internal error....."));
2153 abort ();
2154 }
2155 }
2156 else
2157 {
2158 /* We know the abs value: Should never happen. */
2159 as_bad (_("Absolute value in relaxation code. Assembler error....."));
2160 abort ();
2161 }
2162 break;
2163
2164 case UNDEFINED_PC_OFFSET:
2165 case LARGE_DEFINED_PC_OFFSET:
2166 case DEFINED_ABS_SEGMENT:
2167 case GOT_OFFSET:
2168 case PLT_OFFSET:
2169 case GOTOFF_OFFSET:
2170 fragP->fr_var = INST_WORD_SIZE*2;
2171 break;
2172 case DEFINED_RO_SEGMENT:
2173 case DEFINED_RW_SEGMENT:
2174 case DEFINED_PC_OFFSET:
2175 fragP->fr_var = INST_WORD_SIZE;
2176 break;
2177 default:
2178 abort ();
2179 }
2180
2181 return fragP->fr_var;
2182 }
2183
2184 /* Put number into target byte order. */
2185
2186 void
2187 md_number_to_chars (char * ptr, valueT use, int nbytes)
2188 {
2189 if (target_big_endian)
2190 number_to_chars_bigendian (ptr, use, nbytes);
2191 else
2192 number_to_chars_littleendian (ptr, use, nbytes);
2193 }
2194
2195 /* Round up a section size to the appropriate boundary. */
2196
2197 valueT
2198 md_section_align (segT segment ATTRIBUTE_UNUSED, valueT size)
2199 {
2200 return size; /* Byte alignment is fine. */
2201 }
2202
2203
2204 /* The location from which a PC relative jump should be calculated,
2205 given a PC relative reloc. */
2206
2207 long
2208 md_pcrel_from_section (fixS * fixp, segT sec ATTRIBUTE_UNUSED)
2209 {
2210 #ifdef OBJ_ELF
2211 /* If the symbol is undefined or defined in another section
2212 we leave the add number alone for the linker to fix it later.
2213 Only account for the PC pre-bump (No PC-pre-bump on the Microblaze). */
2214
2215 if (fixp->fx_addsy != (symbolS *) NULL
2216 && (!S_IS_DEFINED (fixp->fx_addsy)
2217 || (S_GET_SEGMENT (fixp->fx_addsy) != sec)))
2218 return 0;
2219 else
2220 {
2221 /* The case where we are going to resolve things... */
2222 if (fixp->fx_r_type == BFD_RELOC_64_PCREL)
2223 return fixp->fx_where + fixp->fx_frag->fr_address + INST_WORD_SIZE;
2224 else
2225 return fixp->fx_where + fixp->fx_frag->fr_address;
2226 }
2227 #endif
2228 }
2229
2230
2231 #define F(SZ,PCREL) (((SZ) << 1) + (PCREL))
2232 #define MAP(SZ,PCREL,TYPE) case F (SZ, PCREL): code = (TYPE); break
2233
2234 arelent *
2235 tc_gen_reloc (asection * section ATTRIBUTE_UNUSED, fixS * fixp)
2236 {
2237 arelent * rel;
2238 bfd_reloc_code_real_type code;
2239
2240 switch (fixp->fx_r_type)
2241 {
2242 case BFD_RELOC_NONE:
2243 case BFD_RELOC_MICROBLAZE_64_NONE:
2244 case BFD_RELOC_32:
2245 case BFD_RELOC_MICROBLAZE_32_LO:
2246 case BFD_RELOC_MICROBLAZE_32_LO_PCREL:
2247 case BFD_RELOC_RVA:
2248 case BFD_RELOC_64:
2249 case BFD_RELOC_64_PCREL:
2250 case BFD_RELOC_MICROBLAZE_32_ROSDA:
2251 case BFD_RELOC_MICROBLAZE_32_RWSDA:
2252 case BFD_RELOC_MICROBLAZE_32_SYM_OP_SYM:
2253 case BFD_RELOC_MICROBLAZE_64_GOTPC:
2254 case BFD_RELOC_MICROBLAZE_64_GOT:
2255 case BFD_RELOC_MICROBLAZE_64_PLT:
2256 case BFD_RELOC_MICROBLAZE_64_GOTOFF:
2257 case BFD_RELOC_MICROBLAZE_32_GOTOFF:
2258 code = fixp->fx_r_type;
2259 break;
2260
2261 default:
2262 switch (F (fixp->fx_size, fixp->fx_pcrel))
2263 {
2264 MAP (1, 0, BFD_RELOC_8);
2265 MAP (2, 0, BFD_RELOC_16);
2266 MAP (4, 0, BFD_RELOC_32);
2267 MAP (1, 1, BFD_RELOC_8_PCREL);
2268 MAP (2, 1, BFD_RELOC_16_PCREL);
2269 MAP (4, 1, BFD_RELOC_32_PCREL);
2270 default:
2271 code = fixp->fx_r_type;
2272 as_bad (_("Can not do %d byte %srelocation"),
2273 fixp->fx_size,
2274 fixp->fx_pcrel ? _("pc-relative") : "");
2275 }
2276 break;
2277 }
2278
2279 rel = (arelent *) xmalloc (sizeof (arelent));
2280 rel->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *));
2281
2282 if (code == BFD_RELOC_MICROBLAZE_32_SYM_OP_SYM)
2283 *rel->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_subsy);
2284 else
2285 *rel->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
2286
2287 rel->address = fixp->fx_frag->fr_address + fixp->fx_where;
2288 /* Always pass the addend along! */
2289 rel->addend = fixp->fx_offset;
2290 rel->howto = bfd_reloc_type_lookup (stdoutput, code);
2291
2292 if (rel->howto == NULL)
2293 {
2294 as_bad_where (fixp->fx_file, fixp->fx_line,
2295 _("Cannot represent relocation type %s"),
2296 bfd_get_reloc_code_name (code));
2297
2298 /* Set howto to a garbage value so that we can keep going. */
2299 rel->howto = bfd_reloc_type_lookup (stdoutput, BFD_RELOC_32);
2300 gas_assert (rel->howto != NULL);
2301 }
2302 return rel;
2303 }
2304
2305 int
2306 md_parse_option (int c, char * arg ATTRIBUTE_UNUSED)
2307 {
2308 switch (c)
2309 {
2310 default:
2311 return 0;
2312 }
2313 return 1;
2314 }
2315
2316 void
2317 md_show_usage (FILE * stream ATTRIBUTE_UNUSED)
2318 {
2319 /* fprintf(stream, _("\
2320 MicroBlaze options:\n\
2321 -noSmall Data in the comm and data sections do not go into the small data section\n")); */
2322 }
2323
2324
2325 /* Create a fixup for a cons expression. If parse_cons_expression_microblaze
2326 found a machine specific op in an expression,
2327 then we create relocs accordingly. */
2328
2329 void
2330 cons_fix_new_microblaze (fragS * frag,
2331 int where,
2332 int size,
2333 expressionS *exp)
2334 {
2335
2336 bfd_reloc_code_real_type r;
2337
2338 if ((exp->X_op == O_subtract) && (exp->X_add_symbol) &&
2339 (exp->X_op_symbol) && (now_seg != absolute_section) && (size == 4)
2340 && (!S_IS_LOCAL (exp->X_op_symbol)))
2341 r = BFD_RELOC_MICROBLAZE_32_SYM_OP_SYM;
2342 else if (exp->X_md == IMM_GOTOFF && exp->X_op == O_symbol_rva)
2343 {
2344 exp->X_op = O_symbol;
2345 r = BFD_RELOC_MICROBLAZE_32_GOTOFF;
2346 }
2347 else
2348 {
2349 switch (size)
2350 {
2351 case 1:
2352 r = BFD_RELOC_8;
2353 break;
2354 case 2:
2355 r = BFD_RELOC_16;
2356 break;
2357 case 4:
2358 r = BFD_RELOC_32;
2359 break;
2360 case 8:
2361 r = BFD_RELOC_64;
2362 break;
2363 default:
2364 as_bad (_("unsupported BFD relocation size %u"), size);
2365 r = BFD_RELOC_32;
2366 break;
2367 }
2368 }
2369 fix_new_exp (frag, where, size, exp, 0, r);
2370 }
This page took 0.078 seconds and 5 git commands to generate.