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