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