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