gdb/testsuite/
[deliverable/binutils-gdb.git] / gas / config / tc-microblaze.c
CommitLineData
7ba29e2a
NC
1/* tc-microblaze.c -- Assemble code for Xilinx MicroBlaze
2
45dfa85a 3 Copyright 2009, 2010, 2012 Free Software Foundation.
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
805extern void
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);
831}
832
833/* This is the guts of the machine-dependent assembler. STR points to a
834 machine dependent instruction. This function is supposed to emit
835 the frags/bytes it assembles to. */
836
837static char * str_microblaze_ro_anchor = "RO";
838static char * str_microblaze_rw_anchor = "RW";
839
840static bfd_boolean
841check_spl_reg (unsigned * reg)
842{
843 if ((*reg == REG_MSR) || (*reg == REG_PC)
844 || (*reg == REG_EAR) || (*reg == REG_ESR)
845 || (*reg == REG_FSR) || (*reg == REG_BTR) || (*reg == REG_EDR)
846 || (*reg == REG_PID) || (*reg == REG_ZPR)
847 || (*reg == REG_TLBX) || (*reg == REG_TLBLO)
848 || (*reg == REG_TLBHI) || (*reg == REG_TLBSX)
0db4b326 849 || (*reg == REG_SHR) || (*reg == REG_SLR)
7ba29e2a
NC
850 || (*reg >= REG_PVR+MIN_PVR_REGNUM && *reg <= REG_PVR+MAX_PVR_REGNUM))
851 return TRUE;
852
853 return FALSE;
854}
855
856/* Here we decide which fixups can be adjusted to make them relative to
857 the beginning of the section instead of the symbol. Basically we need
858 to make sure that the dynamic relocations are done correctly, so in
859 some cases we force the original symbol to be used. */
860
861int
862tc_microblaze_fix_adjustable (struct fix *fixP)
863{
864 if (GOT_symbol && fixP->fx_subsy == GOT_symbol)
865 return 0;
866
867 if (fixP->fx_r_type == BFD_RELOC_MICROBLAZE_64_GOTOFF
868 || fixP->fx_r_type == BFD_RELOC_MICROBLAZE_32_GOTOFF
869 || fixP->fx_r_type == BFD_RELOC_MICROBLAZE_64_GOT
69b06cc8
ME
870 || fixP->fx_r_type == BFD_RELOC_MICROBLAZE_64_PLT
871 || fixP->fx_r_type == BFD_RELOC_MICROBLAZE_64_TLSGD
872 || fixP->fx_r_type == BFD_RELOC_MICROBLAZE_64_TLSLD
873 || fixP->fx_r_type == BFD_RELOC_MICROBLAZE_32_TLSDTPMOD
874 || fixP->fx_r_type == BFD_RELOC_MICROBLAZE_32_TLSDTPREL
875 || fixP->fx_r_type == BFD_RELOC_MICROBLAZE_64_TLSDTPREL
876 || fixP->fx_r_type == BFD_RELOC_MICROBLAZE_64_TLSGOTTPREL
877 || fixP->fx_r_type == BFD_RELOC_MICROBLAZE_64_TLSTPREL)
7ba29e2a
NC
878 return 0;
879
880 return 1;
881}
882
883void
884md_assemble (char * str)
885{
886 char * op_start;
887 char * op_end;
888 struct op_code_struct * opcode, *opcode1;
889 char * output = NULL;
890 int nlen = 0;
891 int i;
892 unsigned long inst, inst1;
893 unsigned reg1;
894 unsigned reg2;
895 unsigned reg3;
896 unsigned isize;
c7d6f518 897 unsigned int immed, temp;
7ba29e2a
NC
898 expressionS exp;
899 char name[20];
900
901 /* Drop leading whitespace. */
e23c5ac0 902 while (ISSPACE (* str))
7ba29e2a
NC
903 str ++;
904
905 /* Find the op code end. */
906 for (op_start = op_end = str;
4ad7ac30 907 *op_end && !is_end_of_line[(unsigned char) *op_end] && *op_end != ' ';
7ba29e2a
NC
908 op_end++)
909 {
910 name[nlen] = op_start[nlen];
911 nlen++;
4ad7ac30
AM
912 if (nlen == sizeof (name) - 1)
913 break;
7ba29e2a
NC
914 }
915
916 name [nlen] = 0;
917
918 if (nlen == 0)
919 {
920 as_bad (_("can't find opcode "));
921 return;
922 }
923
924 opcode = (struct op_code_struct *) hash_find (opcode_hash_control, name);
925 if (opcode == NULL)
926 {
927 as_bad (_("unknown opcode \"%s\""), name);
928 return;
929 }
930
931 inst = opcode->bit_sequence;
932 isize = 4;
933
934 switch (opcode->inst_type)
935 {
936 case INST_TYPE_RD_R1_R2:
937 if (strcmp (op_end, ""))
938 op_end = parse_reg (op_end + 1, &reg1); /* Get rd. */
939 else
940 {
941 as_fatal (_("Error in statement syntax"));
942 reg1 = 0;
943 }
944 if (strcmp (op_end, ""))
945 op_end = parse_reg (op_end + 1, &reg2); /* Get r1. */
946 else
947 {
948 as_fatal (_("Error in statement syntax"));
949 reg2 = 0;
950 }
951 if (strcmp (op_end, ""))
952 op_end = parse_reg (op_end + 1, &reg3); /* Get r2. */
953 else
954 {
955 as_fatal (_("Error in statement syntax"));
956 reg3 = 0;
957 }
958
959 /* Check for spl registers. */
960 if (check_spl_reg (& reg1))
961 as_fatal (_("Cannot use special register with this instruction"));
962 if (check_spl_reg (& reg2))
963 as_fatal (_("Cannot use special register with this instruction"));
964 if (check_spl_reg (& reg3))
965 as_fatal (_("Cannot use special register with this instruction"));
966
967 if (streq (name, "sub"))
968 {
969 /* sub rd, r1, r2 becomes rsub rd, r2, r1. */
970 inst |= (reg1 << RD_LOW) & RD_MASK;
971 inst |= (reg3 << RA_LOW) & RA_MASK;
972 inst |= (reg2 << RB_LOW) & RB_MASK;
973 }
974 else
975 {
976 inst |= (reg1 << RD_LOW) & RD_MASK;
977 inst |= (reg2 << RA_LOW) & RA_MASK;
978 inst |= (reg3 << RB_LOW) & RB_MASK;
979 }
980 output = frag_more (isize);
981 break;
982
983 case INST_TYPE_RD_R1_IMM:
984 if (strcmp (op_end, ""))
985 op_end = parse_reg (op_end + 1, &reg1); /* Get rd. */
986 else
987 {
988 as_fatal (_("Error in statement syntax"));
989 reg1 = 0;
990 }
991 if (strcmp (op_end, ""))
992 op_end = parse_reg (op_end + 1, &reg2); /* Get r1. */
993 else
994 {
995 as_fatal (_("Error in statement syntax"));
996 reg2 = 0;
997 }
998 if (strcmp (op_end, ""))
999 op_end = parse_imm (op_end + 1, & exp, MIN_IMM, MAX_IMM);
1000 else
1001 as_fatal (_("Error in statement syntax"));
1002
1003 /* Check for spl registers. */
1004 if (check_spl_reg (& reg1))
1005 as_fatal (_("Cannot use special register with this instruction"));
1006 if (check_spl_reg (& reg2))
1007 as_fatal (_("Cannot use special register with this instruction"));
1008
1009 if (exp.X_op != O_constant)
1010 {
1011 char *opc;
1012 relax_substateT subtype;
1013
1014 if (streq (name, "lmi"))
1015 as_fatal (_("lmi pseudo instruction should not use a label in imm field"));
1016 else if (streq (name, "smi"))
1017 as_fatal (_("smi pseudo instruction should not use a label in imm field"));
1018
1019 if (reg2 == REG_ROSDP)
1020 opc = str_microblaze_ro_anchor;
1021 else if (reg2 == REG_RWSDP)
1022 opc = str_microblaze_rw_anchor;
1023 else
1024 opc = NULL;
69b06cc8
ME
1025 if (exp.X_md != 0)
1026 subtype = get_imm_otype(exp.X_md);
7ba29e2a
NC
1027 else
1028 subtype = opcode->inst_offset_type;
1029
1030 output = frag_var (rs_machine_dependent,
1031 isize * 2, /* maxm of 2 words. */
1032 isize, /* minm of 1 word. */
1033 subtype, /* PC-relative or not. */
1034 exp.X_add_symbol,
1035 exp.X_add_number,
1036 opc);
c7d6f518 1037 immed = 0;
7ba29e2a
NC
1038 }
1039 else
1040 {
1041 output = frag_more (isize);
c7d6f518 1042 immed = exp.X_add_number;
7ba29e2a
NC
1043 }
1044
1045 if (streq (name, "lmi") || streq (name, "smi"))
1046 {
1047 /* Load/store 32-d consecutive registers. Used on exit/entry
1048 to subroutines to save and restore registers to stack.
1049 Generate 32-d insts. */
1050 int count;
1051
1052 count = 32 - reg1;
1053 if (streq (name, "lmi"))
1054 opcode = (struct op_code_struct *) hash_find (opcode_hash_control, "lwi");
1055 else
1056 opcode = (struct op_code_struct *) hash_find (opcode_hash_control, "swi");
1057 if (opcode == NULL)
1058 {
1059 as_bad (_("unknown opcode \"%s\""), "lwi");
1060 return;
1061 }
1062 inst = opcode->bit_sequence;
1063 inst |= (reg1 << RD_LOW) & RD_MASK;
1064 inst |= (reg2 << RA_LOW) & RA_MASK;
c7d6f518 1065 inst |= (immed << IMM_LOW) & IMM_MASK;
7ba29e2a
NC
1066
1067 for (i = 0; i < count - 1; i++)
1068 {
1069 output[0] = INST_BYTE0 (inst);
1070 output[1] = INST_BYTE1 (inst);
1071 output[2] = INST_BYTE2 (inst);
1072 output[3] = INST_BYTE3 (inst);
1073 output = frag_more (isize);
c7d6f518 1074 immed = immed + 4;
7ba29e2a
NC
1075 reg1++;
1076 inst = opcode->bit_sequence;
1077 inst |= (reg1 << RD_LOW) & RD_MASK;
1078 inst |= (reg2 << RA_LOW) & RA_MASK;
c7d6f518 1079 inst |= (immed << IMM_LOW) & IMM_MASK;
7ba29e2a
NC
1080 }
1081 }
1082 else
1083 {
c7d6f518 1084 temp = immed & 0xFFFF8000;
7ba29e2a
NC
1085 if ((temp != 0) && (temp != 0xFFFF8000))
1086 {
1087 /* Needs an immediate inst. */
1088 opcode1 = (struct op_code_struct *) hash_find (opcode_hash_control, "imm");
1089 if (opcode1 == NULL)
1090 {
1091 as_bad (_("unknown opcode \"%s\""), "imm");
1092 return;
1093 }
1094
1095 inst1 = opcode1->bit_sequence;
c7d6f518 1096 inst1 |= ((immed & 0xFFFF0000) >> 16) & IMM_MASK;
7ba29e2a
NC
1097 output[0] = INST_BYTE0 (inst1);
1098 output[1] = INST_BYTE1 (inst1);
1099 output[2] = INST_BYTE2 (inst1);
1100 output[3] = INST_BYTE3 (inst1);
1101 output = frag_more (isize);
1102 }
1103 inst |= (reg1 << RD_LOW) & RD_MASK;
1104 inst |= (reg2 << RA_LOW) & RA_MASK;
c7d6f518 1105 inst |= (immed << IMM_LOW) & IMM_MASK;
7ba29e2a
NC
1106 }
1107 break;
1108
1109 case INST_TYPE_RD_R1_IMM5:
1110 if (strcmp (op_end, ""))
1111 op_end = parse_reg (op_end + 1, &reg1); /* Get rd. */
1112 else
1113 {
1114 as_fatal (_("Error in statement syntax"));
1115 reg1 = 0;
1116 }
1117 if (strcmp (op_end, ""))
1118 op_end = parse_reg (op_end + 1, &reg2); /* Get r1. */
1119 else
1120 {
1121 as_fatal (_("Error in statement syntax"));
1122 reg2 = 0;
1123 }
1124 if (strcmp (op_end, ""))
1125 op_end = parse_imm (op_end + 1, & exp, MIN_IMM, MAX_IMM);
1126 else
1127 as_fatal (_("Error in statement syntax"));
1128
1129 /* Check for spl registers. */
1130 if (check_spl_reg (&reg1))
1131 as_fatal (_("Cannot use special register with this instruction"));
1132 if (check_spl_reg (&reg2))
1133 as_fatal (_("Cannot use special register with this instruction"));
1134
1135 if (exp.X_op != O_constant)
1136 as_warn (_("Symbol used as immediate for shift instruction"));
1137 else
1138 {
1139 output = frag_more (isize);
c7d6f518 1140 immed = exp.X_add_number;
7ba29e2a
NC
1141 }
1142
c7d6f518 1143 if (immed != (immed % 32))
7ba29e2a
NC
1144 {
1145 as_warn (_("Shift value > 32. using <value %% 32>"));
c7d6f518 1146 immed = immed % 32;
7ba29e2a
NC
1147 }
1148 inst |= (reg1 << RD_LOW) & RD_MASK;
1149 inst |= (reg2 << RA_LOW) & RA_MASK;
c7d6f518 1150 inst |= (immed << IMM_LOW) & IMM5_MASK;
7ba29e2a
NC
1151 break;
1152
1153 case INST_TYPE_R1_R2:
1154 if (strcmp (op_end, ""))
1155 op_end = parse_reg (op_end + 1, &reg1); /* Get r1. */
1156 else
1157 {
1158 as_fatal (_("Error in statement syntax"));
1159 reg1 = 0;
1160 }
1161 if (strcmp (op_end, ""))
1162 op_end = parse_reg (op_end + 1, &reg2); /* Get r2. */
1163 else
1164 {
1165 as_fatal (_("Error in statement syntax"));
1166 reg2 = 0;
1167 }
1168
1169 /* Check for spl registers. */
1170 if (check_spl_reg (& reg1))
1171 as_fatal (_("Cannot use special register with this instruction"));
1172 if (check_spl_reg (& reg2))
1173 as_fatal (_("Cannot use special register with this instruction"));
1174
1175 inst |= (reg1 << RA_LOW) & RA_MASK;
1176 inst |= (reg2 << RB_LOW) & RB_MASK;
1177 output = frag_more (isize);
1178 break;
1179
1180 case INST_TYPE_RD_R1:
1181 if (strcmp (op_end, ""))
1182 op_end = parse_reg (op_end + 1, &reg1); /* Get rd. */
1183 else
1184 {
1185 as_fatal (_("Error in statement syntax"));
1186 reg1 = 0;
1187 }
1188 if (strcmp (op_end, ""))
1189 op_end = parse_reg (op_end + 1, &reg2); /* Get r1. */
1190 else
1191 {
1192 as_fatal (_("Error in statement syntax"));
1193 reg2 =0;
1194 }
1195
1196 /* Check for spl registers. */
1197 if (check_spl_reg (&reg1))
1198 as_fatal (_("Cannot use special register with this instruction"));
1199 if (check_spl_reg (&reg2))
1200 as_fatal (_("Cannot use special register with this instruction"));
1201
1202 inst |= (reg1 << RD_LOW) & RD_MASK;
1203 inst |= (reg2 << RA_LOW) & RA_MASK;
1204 output = frag_more (isize);
1205 break;
1206
1207 case INST_TYPE_RD_RFSL:
1208 if (strcmp (op_end, ""))
1209 op_end = parse_reg (op_end + 1, &reg1); /* Get rd. */
1210 else
1211 {
1212 as_fatal (_("Error in statement syntax"));
1213 reg1 = 0;
1214 }
1215 if (strcmp (op_end, ""))
c7d6f518 1216 op_end = parse_reg (op_end + 1, &immed); /* Get rfslN. */
7ba29e2a
NC
1217 else
1218 {
1219 as_fatal (_("Error in statement syntax"));
c7d6f518 1220 immed = 0;
7ba29e2a
NC
1221 }
1222
1223 /* Check for spl registers. */
1224 if (check_spl_reg (&reg1))
1225 as_fatal (_("Cannot use special register with this instruction"));
1226
1227 inst |= (reg1 << RD_LOW) & RD_MASK;
c7d6f518 1228 inst |= (immed << IMM_LOW) & RFSL_MASK;
7ba29e2a
NC
1229 output = frag_more (isize);
1230 break;
1231
1232 case INST_TYPE_RD_IMM15:
1233 if (strcmp (op_end, ""))
1234 op_end = parse_reg (op_end + 1, &reg1); /* Get rd. */
1235 else
1236 {
1237 as_fatal (_("Error in statement syntax"));
1238 reg1 = 0;
1239 }
1240
1241 if (strcmp (op_end, ""))
1242 op_end = parse_imm (op_end + 1, & exp, MIN_IMM15, MAX_IMM15);
1243 else
1244 as_fatal (_("Error in statement syntax"));
1245
1246 /* Check for spl registers. */
1247 if (check_spl_reg (&reg1))
1248 as_fatal (_("Cannot use special register with this instruction"));
1249
1250 if (exp.X_op != O_constant)
1251 as_fatal (_("Symbol used as immediate value for msrset/msrclr instructions"));
1252 else
1253 {
1254 output = frag_more (isize);
c7d6f518 1255 immed = exp.X_add_number;
7ba29e2a
NC
1256 }
1257 inst |= (reg1 << RD_LOW) & RD_MASK;
c7d6f518 1258 inst |= (immed << IMM_LOW) & IMM15_MASK;
7ba29e2a
NC
1259 break;
1260
1261 case INST_TYPE_R1_RFSL:
1262 if (strcmp (op_end, ""))
1263 op_end = parse_reg (op_end + 1, &reg1); /* Get r1. */
1264 else
1265 {
1266 as_fatal (_("Error in statement syntax"));
1267 reg1 = 0;
1268 }
1269 if (strcmp (op_end, ""))
c7d6f518 1270 op_end = parse_reg (op_end + 1, &immed); /* Get rfslN. */
7ba29e2a
NC
1271 else
1272 {
1273 as_fatal (_("Error in statement syntax"));
c7d6f518 1274 immed = 0;
7ba29e2a
NC
1275 }
1276
1277 /* Check for spl registers. */
1278 if (check_spl_reg (&reg1))
1279 as_fatal (_("Cannot use special register with this instruction"));
1280
1281 inst |= (reg1 << RA_LOW) & RA_MASK;
c7d6f518 1282 inst |= (immed << IMM_LOW) & RFSL_MASK;
7ba29e2a
NC
1283 output = frag_more (isize);
1284 break;
1285
1286 case INST_TYPE_RFSL:
1287 if (strcmp (op_end, ""))
c7d6f518 1288 op_end = parse_reg (op_end + 1, &immed); /* Get rfslN. */
7ba29e2a
NC
1289 else
1290 {
1291 as_fatal (_("Error in statement syntax"));
c7d6f518 1292 immed = 0;
7ba29e2a 1293 }
c7d6f518 1294 inst |= (immed << IMM_LOW) & RFSL_MASK;
7ba29e2a
NC
1295 output = frag_more (isize);
1296 break;
1297
1298 case INST_TYPE_R1:
1299 if (strcmp (op_end, ""))
1300 op_end = parse_reg (op_end + 1, &reg1); /* Get r1. */
1301 else
1302 {
1303 as_fatal (_("Error in statement syntax"));
1304 reg1 = 0;
1305 }
1306
1307 /* Check for spl registers. */
1308 if (check_spl_reg (&reg1))
1309 as_fatal (_("Cannot use special register with this instruction"));
1310
1311 inst |= (reg1 << RA_LOW) & RA_MASK;
1312 output = frag_more (isize);
1313 break;
1314
1315 /* For tuqula insn...:) */
1316 case INST_TYPE_RD:
1317 if (strcmp (op_end, ""))
1318 op_end = parse_reg (op_end + 1, &reg1); /* Get rd. */
1319 else
1320 {
1321 as_fatal (_("Error in statement syntax"));
1322 reg1 = 0;
1323 }
1324
1325 /* Check for spl registers. */
1326 if (check_spl_reg (&reg1))
1327 as_fatal (_("Cannot use special register with this instruction"));
1328
1329 inst |= (reg1 << RD_LOW) & RD_MASK;
1330 output = frag_more (isize);
1331 break;
1332
1333 case INST_TYPE_RD_SPECIAL:
1334 if (strcmp (op_end, ""))
1335 op_end = parse_reg (op_end + 1, &reg1); /* Get rd. */
1336 else
1337 {
1338 as_fatal (_("Error in statement syntax"));
1339 reg1 = 0;
1340 }
1341 if (strcmp (op_end, ""))
1342 op_end = parse_reg (op_end + 1, &reg2); /* Get r1. */
1343 else
1344 {
1345 as_fatal (_("Error in statement syntax"));
1346 reg2 = 0;
1347 }
1348
1349 if (reg2 == REG_MSR)
c7d6f518 1350 immed = opcode->immval_mask | REG_MSR_MASK;
7ba29e2a 1351 else if (reg2 == REG_PC)
c7d6f518 1352 immed = opcode->immval_mask | REG_PC_MASK;
7ba29e2a 1353 else if (reg2 == REG_EAR)
c7d6f518 1354 immed = opcode->immval_mask | REG_EAR_MASK;
7ba29e2a 1355 else if (reg2 == REG_ESR)
c7d6f518 1356 immed = opcode->immval_mask | REG_ESR_MASK;
7ba29e2a 1357 else if (reg2 == REG_FSR)
c7d6f518 1358 immed = opcode->immval_mask | REG_FSR_MASK;
7ba29e2a 1359 else if (reg2 == REG_BTR)
c7d6f518 1360 immed = opcode->immval_mask | REG_BTR_MASK;
7ba29e2a 1361 else if (reg2 == REG_EDR)
c7d6f518 1362 immed = opcode->immval_mask | REG_EDR_MASK;
7ba29e2a 1363 else if (reg2 == REG_PID)
c7d6f518 1364 immed = opcode->immval_mask | REG_PID_MASK;
7ba29e2a 1365 else if (reg2 == REG_ZPR)
c7d6f518 1366 immed = opcode->immval_mask | REG_ZPR_MASK;
7ba29e2a 1367 else if (reg2 == REG_TLBX)
c7d6f518 1368 immed = opcode->immval_mask | REG_TLBX_MASK;
7ba29e2a 1369 else if (reg2 == REG_TLBLO)
c7d6f518 1370 immed = opcode->immval_mask | REG_TLBLO_MASK;
7ba29e2a 1371 else if (reg2 == REG_TLBHI)
c7d6f518 1372 immed = opcode->immval_mask | REG_TLBHI_MASK;
0db4b326
ME
1373 else if (reg2 == REG_SHR)
1374 immed = opcode->immval_mask | REG_SHR_MASK;
1375 else if (reg2 == REG_SLR)
1376 immed = opcode->immval_mask | REG_SLR_MASK;
7ba29e2a 1377 else if (reg2 >= (REG_PVR+MIN_PVR_REGNUM) && reg2 <= (REG_PVR+MAX_PVR_REGNUM))
c7d6f518 1378 immed = opcode->immval_mask | REG_PVR_MASK | reg2;
7ba29e2a
NC
1379 else
1380 as_fatal (_("invalid value for special purpose register"));
1381 inst |= (reg1 << RD_LOW) & RD_MASK;
c7d6f518 1382 inst |= (immed << IMM_LOW) & IMM_MASK;
7ba29e2a
NC
1383 output = frag_more (isize);
1384 break;
1385
1386 case INST_TYPE_SPECIAL_R1:
1387 if (strcmp (op_end, ""))
1388 op_end = parse_reg (op_end + 1, &reg1); /* Get rd. */
1389 else
1390 {
1391 as_fatal (_("Error in statement syntax"));
1392 reg1 = 0;
1393 }
1394 if (strcmp (op_end, ""))
1395 op_end = parse_reg (op_end + 1, &reg2); /* Get r1. */
1396 else
1397 {
1398 as_fatal (_("Error in statement syntax"));
1399 reg2 = 0;
1400 }
1401
1402 if (reg1 == REG_MSR)
c7d6f518 1403 immed = opcode->immval_mask | REG_MSR_MASK;
7ba29e2a 1404 else if (reg1 == REG_PC)
c7d6f518 1405 immed = opcode->immval_mask | REG_PC_MASK;
7ba29e2a 1406 else if (reg1 == REG_EAR)
c7d6f518 1407 immed = opcode->immval_mask | REG_EAR_MASK;
7ba29e2a 1408 else if (reg1 == REG_ESR)
c7d6f518 1409 immed = opcode->immval_mask | REG_ESR_MASK;
7ba29e2a 1410 else if (reg1 == REG_FSR)
c7d6f518 1411 immed = opcode->immval_mask | REG_FSR_MASK;
7ba29e2a 1412 else if (reg1 == REG_BTR)
c7d6f518 1413 immed = opcode->immval_mask | REG_BTR_MASK;
7ba29e2a 1414 else if (reg1 == REG_EDR)
c7d6f518 1415 immed = opcode->immval_mask | REG_EDR_MASK;
7ba29e2a 1416 else if (reg1 == REG_PID)
c7d6f518 1417 immed = opcode->immval_mask | REG_PID_MASK;
7ba29e2a 1418 else if (reg1 == REG_ZPR)
c7d6f518 1419 immed = opcode->immval_mask | REG_ZPR_MASK;
7ba29e2a 1420 else if (reg1 == REG_TLBX)
c7d6f518 1421 immed = opcode->immval_mask | REG_TLBX_MASK;
7ba29e2a 1422 else if (reg1 == REG_TLBLO)
c7d6f518 1423 immed = opcode->immval_mask | REG_TLBLO_MASK;
7ba29e2a 1424 else if (reg1 == REG_TLBHI)
c7d6f518 1425 immed = opcode->immval_mask | REG_TLBHI_MASK;
7ba29e2a 1426 else if (reg1 == REG_TLBSX)
c7d6f518 1427 immed = opcode->immval_mask | REG_TLBSX_MASK;
0db4b326
ME
1428 else if (reg1 == REG_SHR)
1429 immed = opcode->immval_mask | REG_SHR_MASK;
1430 else if (reg1 == REG_SLR)
1431 immed = opcode->immval_mask | REG_SLR_MASK;
7ba29e2a
NC
1432 else
1433 as_fatal (_("invalid value for special purpose register"));
1434 inst |= (reg2 << RA_LOW) & RA_MASK;
c7d6f518 1435 inst |= (immed << IMM_LOW) & IMM_MASK;
7ba29e2a
NC
1436 output = frag_more (isize);
1437 break;
1438
94dda8b7 1439 case INST_TYPE_R1_R2_SPECIAL:
7ba29e2a 1440 if (strcmp (op_end, ""))
94dda8b7 1441 op_end = parse_reg (op_end + 1, &reg1); /* Get r1. */
7ba29e2a
NC
1442 else
1443 {
1444 as_fatal (_("Error in statement syntax"));
1445 reg1 = 0;
1446 }
1447 if (strcmp (op_end, ""))
94dda8b7 1448 op_end = parse_reg (op_end + 1, &reg2); /* Get r2. */
7ba29e2a
NC
1449 else
1450 {
1451 as_fatal (_("Error in statement syntax"));
1452 reg2 =0;
1453 }
1454
1455 /* Check for spl registers. */
1456 if (check_spl_reg (&reg1))
1457 as_fatal (_("Cannot use special register with this instruction"));
1458 if (check_spl_reg (&reg2))
1459 as_fatal (_("Cannot use special register with this instruction"));
1460
1461 /* insn wic ra, rb => wic ra, ra, rb. */
7ba29e2a
NC
1462 inst |= (reg1 << RA_LOW) & RA_MASK;
1463 inst |= (reg2 << RB_LOW) & RB_MASK;
1464
1465 output = frag_more (isize);
1466 break;
1467
1468 case INST_TYPE_RD_R2:
1469 if (strcmp (op_end, ""))
1470 op_end = parse_reg (op_end + 1, &reg1); /* Get rd. */
1471 else
1472 {
1473 as_fatal (_("Error in statement syntax"));
1474 reg1 = 0;
1475 }
1476 if (strcmp (op_end, ""))
1477 op_end = parse_reg (op_end + 1, &reg2); /* Get r2. */
1478 else
1479 {
1480 as_fatal (_("Error in statement syntax"));
1481 reg2 = 0;
1482 }
1483
1484 /* Check for spl registers. */
1485 if (check_spl_reg (&reg1))
1486 as_fatal (_("Cannot use special register with this instruction"));
1487 if (check_spl_reg (&reg2))
1488 as_fatal (_("Cannot use special register with this instruction"));
1489
1490 inst |= (reg1 << RD_LOW) & RD_MASK;
1491 inst |= (reg2 << RB_LOW) & RB_MASK;
1492 output = frag_more (isize);
1493 break;
1494
1495 case INST_TYPE_R1_IMM:
1496 if (strcmp (op_end, ""))
1497 op_end = parse_reg (op_end + 1, &reg1); /* Get r1. */
1498 else
1499 {
1500 as_fatal (_("Error in statement syntax"));
1501 reg1 = 0;
1502 }
1503 if (strcmp (op_end, ""))
1504 op_end = parse_imm (op_end + 1, & exp, MIN_IMM, MAX_IMM);
1505 else
1506 as_fatal (_("Error in statement syntax"));
1507
1508 /* Check for spl registers. */
1509 if (check_spl_reg (&reg1))
1510 as_fatal (_("Cannot use special register with this instruction"));
1511
1512 if (exp.X_op != O_constant)
1513 {
1514 char *opc = NULL;
1515 relax_substateT subtype;
1516
69b06cc8
ME
1517 if (exp.X_md != 0)
1518 subtype = get_imm_otype(exp.X_md);
7ba29e2a
NC
1519 else
1520 subtype = opcode->inst_offset_type;
69b06cc8 1521
7ba29e2a
NC
1522 output = frag_var (rs_machine_dependent,
1523 isize * 2, /* maxm of 2 words. */
1524 isize, /* minm of 1 word. */
1525 subtype, /* PC-relative or not. */
1526 exp.X_add_symbol,
1527 exp.X_add_number,
1528 opc);
c7d6f518 1529 immed = 0;
7ba29e2a
NC
1530 }
1531 else
1532 {
1533 output = frag_more (isize);
c7d6f518 1534 immed = exp.X_add_number;
7ba29e2a
NC
1535 }
1536
c7d6f518 1537 temp = immed & 0xFFFF8000;
7ba29e2a
NC
1538 if ((temp != 0) && (temp != 0xFFFF8000))
1539 {
1540 /* Needs an immediate inst. */
1541 opcode1 = (struct op_code_struct *) hash_find (opcode_hash_control, "imm");
1542 if (opcode1 == NULL)
1543 {
1544 as_bad (_("unknown opcode \"%s\""), "imm");
1545 return;
1546 }
1547
1548 inst1 = opcode1->bit_sequence;
c7d6f518 1549 inst1 |= ((immed & 0xFFFF0000) >> 16) & IMM_MASK;
7ba29e2a
NC
1550 output[0] = INST_BYTE0 (inst1);
1551 output[1] = INST_BYTE1 (inst1);
1552 output[2] = INST_BYTE2 (inst1);
1553 output[3] = INST_BYTE3 (inst1);
1554 output = frag_more (isize);
1555 }
1556
1557 inst |= (reg1 << RA_LOW) & RA_MASK;
c7d6f518 1558 inst |= (immed << IMM_LOW) & IMM_MASK;
7ba29e2a
NC
1559 break;
1560
1561 case INST_TYPE_RD_IMM:
1562 if (strcmp (op_end, ""))
1563 op_end = parse_reg (op_end + 1, &reg1); /* Get rd. */
1564 else
1565 {
1566 as_fatal (_("Error in statement syntax"));
1567 reg1 = 0;
1568 }
1569 if (strcmp (op_end, ""))
1570 op_end = parse_imm (op_end + 1, & exp, MIN_IMM, MAX_IMM);
1571 else
1572 as_fatal (_("Error in statement syntax"));
1573
1574 /* Check for spl registers. */
1575 if (check_spl_reg (&reg1))
1576 as_fatal (_("Cannot use special register with this instruction"));
1577
1578 if (exp.X_op != O_constant)
1579 {
1580 char *opc = NULL;
1581 relax_substateT subtype;
1582
69b06cc8
ME
1583 if (exp.X_md != 0)
1584 subtype = get_imm_otype(exp.X_md);
1585 else
7ba29e2a 1586 subtype = opcode->inst_offset_type;
69b06cc8 1587
7ba29e2a
NC
1588 output = frag_var (rs_machine_dependent,
1589 isize * 2, /* maxm of 2 words. */
1590 isize, /* minm of 1 word. */
1591 subtype, /* PC-relative or not. */
1592 exp.X_add_symbol,
1593 exp.X_add_number,
1594 opc);
c7d6f518 1595 immed = 0;
7ba29e2a
NC
1596 }
1597 else
1598 {
1599 output = frag_more (isize);
c7d6f518 1600 immed = exp.X_add_number;
7ba29e2a
NC
1601 }
1602
c7d6f518 1603 temp = immed & 0xFFFF8000;
7ba29e2a
NC
1604 if ((temp != 0) && (temp != 0xFFFF8000))
1605 {
1606 /* Needs an immediate inst. */
1607 opcode1 = (struct op_code_struct *) hash_find (opcode_hash_control, "imm");
1608 if (opcode1 == NULL)
1609 {
1610 as_bad (_("unknown opcode \"%s\""), "imm");
1611 return;
1612 }
1613
1614 inst1 = opcode1->bit_sequence;
c7d6f518 1615 inst1 |= ((immed & 0xFFFF0000) >> 16) & IMM_MASK;
7ba29e2a
NC
1616 output[0] = INST_BYTE0 (inst1);
1617 output[1] = INST_BYTE1 (inst1);
1618 output[2] = INST_BYTE2 (inst1);
1619 output[3] = INST_BYTE3 (inst1);
1620 output = frag_more (isize);
1621 }
1622
1623 inst |= (reg1 << RD_LOW) & RD_MASK;
c7d6f518 1624 inst |= (immed << IMM_LOW) & IMM_MASK;
7ba29e2a
NC
1625 break;
1626
1627 case INST_TYPE_R2:
1628 if (strcmp (op_end, ""))
1629 op_end = parse_reg (op_end + 1, &reg2); /* Get r2. */
1630 else
1631 {
1632 as_fatal (_("Error in statement syntax"));
1633 reg2 = 0;
1634 }
1635
1636 /* Check for spl registers. */
1637 if (check_spl_reg (&reg2))
1638 as_fatal (_("Cannot use special register with this instruction"));
1639
1640 inst |= (reg2 << RB_LOW) & RB_MASK;
1641 output = frag_more (isize);
1642 break;
1643
1644 case INST_TYPE_IMM:
1645 if (streq (name, "imm"))
1646 as_fatal (_("An IMM instruction should not be present in the .s file"));
1647
1648 op_end = parse_imm (op_end + 1, & exp, MIN_IMM, MAX_IMM);
1649
1650 if (exp.X_op != O_constant)
1651 {
1652 char *opc = NULL;
1653 relax_substateT subtype;
1654
69b06cc8
ME
1655 if (exp.X_md != 0)
1656 subtype = get_imm_otype(exp.X_md);
1657 else
1658 subtype = opcode->inst_offset_type;
1659
7ba29e2a
NC
1660 output = frag_var (rs_machine_dependent,
1661 isize * 2, /* maxm of 2 words. */
1662 isize, /* minm of 1 word. */
1663 subtype, /* PC-relative or not. */
1664 exp.X_add_symbol,
1665 exp.X_add_number,
1666 opc);
c7d6f518 1667 immed = 0;
7ba29e2a
NC
1668 }
1669 else
1670 {
1671 output = frag_more (isize);
c7d6f518 1672 immed = exp.X_add_number;
7ba29e2a
NC
1673 }
1674
1675
c7d6f518 1676 temp = immed & 0xFFFF8000;
7ba29e2a
NC
1677 if ((temp != 0) && (temp != 0xFFFF8000))
1678 {
1679 /* Needs an immediate inst. */
1680 opcode1 = (struct op_code_struct *) hash_find (opcode_hash_control, "imm");
1681 if (opcode1 == NULL)
1682 {
1683 as_bad (_("unknown opcode \"%s\""), "imm");
1684 return;
1685 }
1686
1687 inst1 = opcode1->bit_sequence;
c7d6f518 1688 inst1 |= ((immed & 0xFFFF0000) >> 16) & IMM_MASK;
7ba29e2a
NC
1689 output[0] = INST_BYTE0 (inst1);
1690 output[1] = INST_BYTE1 (inst1);
1691 output[2] = INST_BYTE2 (inst1);
1692 output[3] = INST_BYTE3 (inst1);
1693 output = frag_more (isize);
1694 }
c7d6f518 1695 inst |= (immed << IMM_LOW) & IMM_MASK;
7ba29e2a
NC
1696 break;
1697
1698 case INST_TYPE_NONE:
1699 output = frag_more (isize);
1700 break;
1701
d3da7741
ME
1702 case INST_TYPE_IMM5:
1703 if (strcmp(op_end, ""))
1704 op_end = parse_imm (op_end + 1, & exp, MIN_IMM5, MAX_IMM5);
1705 else
1706 as_fatal(_("Error in statement syntax"));
1707 if (exp.X_op != O_constant) {
1708 as_warn(_("Symbol used as immediate for mbar instruction"));
1709 } else {
1710 output = frag_more (isize);
1711 immed = exp.X_add_number;
1712 }
1713 if (immed != (immed % 32)) {
1714 as_warn(_("Immediate value for mbar > 32. using <value %% 32>"));
1715 immed = immed % 32;
1716 }
1717 inst |= (immed << IMM_MBAR);
1718 break;
1719
7ba29e2a
NC
1720 default:
1721 as_fatal (_("unimplemented opcode \"%s\""), name);
1722 }
1723
1724 /* Drop whitespace after all the operands have been parsed. */
e23c5ac0 1725 while (ISSPACE (* op_end))
7ba29e2a
NC
1726 op_end ++;
1727
1728 /* Give warning message if the insn has more operands than required. */
1729 if (strcmp (op_end, opcode->name) && strcmp (op_end, ""))
1730 as_warn (_("ignoring operands: %s "), op_end);
1731
1732 output[0] = INST_BYTE0 (inst);
1733 output[1] = INST_BYTE1 (inst);
1734 output[2] = INST_BYTE2 (inst);
1735 output[3] = INST_BYTE3 (inst);
1736
1737#ifdef OBJ_ELF
1738 dwarf2_emit_insn (4);
1739#endif
1740}
1741
1742symbolS *
1743md_undefined_symbol (char * name ATTRIBUTE_UNUSED)
1744{
1745 return NULL;
1746}
1747
1748/* Various routines to kill one day. */
1749/* Equal to MAX_PRECISION in atof-ieee.c */
1750#define MAX_LITTLENUMS 6
1751
1752/* Turn a string in input_line_pointer into a floating point constant of type
1753 type, and store the appropriate bytes in *litP. The number of LITTLENUMS
1754 emitted is stored in *sizeP. An error message is returned, or NULL on OK.*/
1755char *
1756md_atof (int type, char * litP, int * sizeP)
1757{
1758 int prec;
1759 LITTLENUM_TYPE words[MAX_LITTLENUMS];
1760 int i;
1761 char * t;
1762
1763 switch (type)
1764 {
1765 case 'f':
1766 case 'F':
1767 case 's':
1768 case 'S':
1769 prec = 2;
1770 break;
1771
1772 case 'd':
1773 case 'D':
1774 case 'r':
1775 case 'R':
1776 prec = 4;
1777 break;
1778
1779 case 'x':
1780 case 'X':
1781 prec = 6;
1782 break;
1783
1784 case 'p':
1785 case 'P':
1786 prec = 6;
1787 break;
1788
1789 default:
1790 *sizeP = 0;
1791 return _("Bad call to MD_NTOF()");
1792 }
1793
1794 t = atof_ieee (input_line_pointer, type, words);
1795
1796 if (t)
1797 input_line_pointer = t;
1798
1799 *sizeP = prec * sizeof (LITTLENUM_TYPE);
1800
1801 if (! target_big_endian)
1802 {
1803 for (i = prec - 1; i >= 0; i--)
1804 {
1805 md_number_to_chars (litP, (valueT) words[i],
1806 sizeof (LITTLENUM_TYPE));
1807 litP += sizeof (LITTLENUM_TYPE);
1808 }
1809 }
1810 else
1811 for (i = 0; i < prec; i++)
1812 {
1813 md_number_to_chars (litP, (valueT) words[i],
1814 sizeof (LITTLENUM_TYPE));
1815 litP += sizeof (LITTLENUM_TYPE);
1816 }
1817
1818 return NULL;
1819}
1820\f
1821const char * md_shortopts = "";
1822
1823struct option md_longopts[] =
1824{
f23200ad
ME
1825 {"EB", no_argument, NULL, OPTION_EB},
1826 {"EL", no_argument, NULL, OPTION_EL},
7ba29e2a
NC
1827 { NULL, no_argument, NULL, 0}
1828};
1829
1830size_t md_longopts_size = sizeof (md_longopts);
1831
1832int md_short_jump_size;
1833
1834void
1835md_create_short_jump (char * ptr ATTRIBUTE_UNUSED,
1836 addressT from_Nddr ATTRIBUTE_UNUSED,
1837 addressT to_Nddr ATTRIBUTE_UNUSED,
1838 fragS * frag ATTRIBUTE_UNUSED,
1839 symbolS * to_symbol ATTRIBUTE_UNUSED)
1840{
1841 as_fatal (_("failed sanity check: short_jump"));
1842}
1843
1844void
1845md_create_long_jump (char * ptr ATTRIBUTE_UNUSED,
1846 addressT from_Nddr ATTRIBUTE_UNUSED,
1847 addressT to_Nddr ATTRIBUTE_UNUSED,
1848 fragS * frag ATTRIBUTE_UNUSED,
1849 symbolS * to_symbol ATTRIBUTE_UNUSED)
1850{
1851 as_fatal (_("failed sanity check: long_jump"));
1852}
1853
1854/* Called after relaxing, change the frags so they know how big they are. */
1855
1856void
1857md_convert_frag (bfd * abfd ATTRIBUTE_UNUSED,
1858 segT sec ATTRIBUTE_UNUSED,
1859 fragS * fragP)
1860{
1861 fixS *fixP;
1862
1863 switch (fragP->fr_subtype)
1864 {
1865 case UNDEFINED_PC_OFFSET:
1866 fix_new (fragP, fragP->fr_fix, INST_WORD_SIZE * 2, fragP->fr_symbol,
1867 fragP->fr_offset, TRUE, BFD_RELOC_64_PCREL);
1868 fragP->fr_fix += INST_WORD_SIZE * 2;
1869 fragP->fr_var = 0;
1870 break;
1871 case DEFINED_ABS_SEGMENT:
1872 if (fragP->fr_symbol == GOT_symbol)
1873 fix_new (fragP, fragP->fr_fix, INST_WORD_SIZE * 2, fragP->fr_symbol,
1874 fragP->fr_offset, TRUE, BFD_RELOC_MICROBLAZE_64_GOTPC);
1875 else
1876 fix_new (fragP, fragP->fr_fix, INST_WORD_SIZE * 2, fragP->fr_symbol,
1877 fragP->fr_offset, FALSE, BFD_RELOC_64);
1878 fragP->fr_fix += INST_WORD_SIZE * 2;
1879 fragP->fr_var = 0;
1880 break;
1881 case DEFINED_RO_SEGMENT:
1882 fix_new (fragP, fragP->fr_fix, INST_WORD_SIZE, fragP->fr_symbol,
1883 fragP->fr_offset, FALSE, BFD_RELOC_MICROBLAZE_32_ROSDA);
1884 fragP->fr_fix += INST_WORD_SIZE;
1885 fragP->fr_var = 0;
1886 break;
1887 case DEFINED_RW_SEGMENT:
1888 fix_new (fragP, fragP->fr_fix, INST_WORD_SIZE, fragP->fr_symbol,
1889 fragP->fr_offset, FALSE, BFD_RELOC_MICROBLAZE_32_RWSDA);
1890 fragP->fr_fix += INST_WORD_SIZE;
1891 fragP->fr_var = 0;
1892 break;
1893 case DEFINED_PC_OFFSET:
1894 fix_new (fragP, fragP->fr_fix, INST_WORD_SIZE, fragP->fr_symbol,
1895 fragP->fr_offset, TRUE, BFD_RELOC_MICROBLAZE_32_LO_PCREL);
1896 fragP->fr_fix += INST_WORD_SIZE;
1897 fragP->fr_var = 0;
1898 break;
1899 case LARGE_DEFINED_PC_OFFSET:
1900 fix_new (fragP, fragP->fr_fix, INST_WORD_SIZE * 2, fragP->fr_symbol,
1901 fragP->fr_offset, TRUE, BFD_RELOC_64_PCREL);
1902 fragP->fr_fix += INST_WORD_SIZE * 2;
1903 fragP->fr_var = 0;
1904 break;
1905 case GOT_OFFSET:
1906 fix_new (fragP, fragP->fr_fix, INST_WORD_SIZE * 2, fragP->fr_symbol,
1907 fragP->fr_offset, FALSE, BFD_RELOC_MICROBLAZE_64_GOT);
1908 fragP->fr_fix += INST_WORD_SIZE * 2;
1909 fragP->fr_var = 0;
1910 break;
1911 case PLT_OFFSET:
1912 fixP = fix_new (fragP, fragP->fr_fix, INST_WORD_SIZE * 2, fragP->fr_symbol,
1913 fragP->fr_offset, TRUE, BFD_RELOC_MICROBLAZE_64_PLT);
1914 /* fixP->fx_plt = 1; */
87975d2a 1915 (void) fixP;
7ba29e2a
NC
1916 fragP->fr_fix += INST_WORD_SIZE * 2;
1917 fragP->fr_var = 0;
1918 break;
1919 case GOTOFF_OFFSET:
1920 fix_new (fragP, fragP->fr_fix, INST_WORD_SIZE * 2, fragP->fr_symbol,
1921 fragP->fr_offset, FALSE, BFD_RELOC_MICROBLAZE_64_GOTOFF);
1922 fragP->fr_fix += INST_WORD_SIZE * 2;
1923 fragP->fr_var = 0;
1924 break;
69b06cc8
ME
1925 case TLSGD_OFFSET:
1926 fix_new (fragP, fragP->fr_fix, INST_WORD_SIZE * 2, fragP->fr_symbol,
1927 fragP->fr_offset, FALSE, BFD_RELOC_MICROBLAZE_64_TLSGD);
1928 fragP->fr_fix += INST_WORD_SIZE * 2;
1929 fragP->fr_var = 0;
1930 break;
1931 case TLSLD_OFFSET:
1932 fix_new (fragP, fragP->fr_fix, INST_WORD_SIZE * 2, fragP->fr_symbol,
1933 fragP->fr_offset, FALSE, BFD_RELOC_MICROBLAZE_64_TLSLD);
1934 fragP->fr_fix += INST_WORD_SIZE * 2;
1935 fragP->fr_var = 0;
1936 break;
1937 case TLSDTPREL_OFFSET:
1938 fix_new (fragP, fragP->fr_fix, INST_WORD_SIZE * 2, fragP->fr_symbol,
1939 fragP->fr_offset, FALSE, BFD_RELOC_MICROBLAZE_64_TLSDTPREL);
1940 fragP->fr_fix += INST_WORD_SIZE * 2;
1941 fragP->fr_var = 0;
1942 break;
7ba29e2a
NC
1943
1944 default:
1945 abort ();
1946 }
1947}
1948
1949/* Applies the desired value to the specified location.
1950 Also sets up addends for 'rela' type relocations. */
1951void
1952md_apply_fix (fixS * fixP,
1953 valueT * valp,
1954 segT segment)
1955{
1956 char * buf = fixP->fx_where + fixP->fx_frag->fr_literal;
1957 char * file = fixP->fx_file ? fixP->fx_file : _("unknown");
1958 const char * symname;
1959 /* Note: use offsetT because it is signed, valueT is unsigned. */
1960 offsetT val = (offsetT) * valp;
1961 int i;
1962 struct op_code_struct * opcode1;
1963 unsigned long inst1;
1964
1965 symname = fixP->fx_addsy ? S_GET_NAME (fixP->fx_addsy) : _("<unknown>");
1966
1967 /* fixP->fx_offset is supposed to be set up correctly for all
1968 symbol relocations. */
1969 if (fixP->fx_addsy == NULL)
1970 {
1971 if (!fixP->fx_pcrel)
1972 fixP->fx_offset = val; /* Absolute relocation. */
1973 else
1974 fprintf (stderr, "NULL symbol PC-relative relocation? offset = %08x, val = %08x\n",
1975 (unsigned int) fixP->fx_offset, (unsigned int) val);
1976 }
1977
1978 /* If we aren't adjusting this fixup to be against the section
1979 symbol, we need to adjust the value. */
1980 if (fixP->fx_addsy != NULL)
1981 {
1982 if (S_IS_WEAK (fixP->fx_addsy)
1983 || (symbol_used_in_reloc_p (fixP->fx_addsy)
1984 && (((bfd_get_section_flags (stdoutput,
1985 S_GET_SEGMENT (fixP->fx_addsy))
1986 & SEC_LINK_ONCE) != 0)
1987 || !strncmp (segment_name (S_GET_SEGMENT (fixP->fx_addsy)),
1988 ".gnu.linkonce",
1989 sizeof (".gnu.linkonce") - 1))))
1990 {
1991 val -= S_GET_VALUE (fixP->fx_addsy);
1992 if (val != 0 && ! fixP->fx_pcrel)
1993 {
1994 /* In this case, the bfd_install_relocation routine will
1995 incorrectly add the symbol value back in. We just want
1996 the addend to appear in the object file.
1997 FIXME: If this makes VALUE zero, we're toast. */
1998 val -= S_GET_VALUE (fixP->fx_addsy);
1999 }
2000 }
2001 }
2002
2003 /* If the fix is relative to a symbol which is not defined, or not
2004 in the same segment as the fix, we cannot resolve it here. */
2005 /* fixP->fx_addsy is NULL if valp contains the entire relocation. */
2006 if (fixP->fx_addsy != NULL
2007 && (!S_IS_DEFINED (fixP->fx_addsy)
2008 || (S_GET_SEGMENT (fixP->fx_addsy) != segment)))
2009 {
2010 fixP->fx_done = 0;
2011#ifdef OBJ_ELF
2012 /* For ELF we can just return and let the reloc that will be generated
2013 take care of everything. For COFF we still have to insert 'val'
2014 into the insn since the addend field will be ignored. */
2015 /* return; */
2016#endif
2017 }
2018 /* All fixups in the text section must be handled in the linker. */
2019 else if (segment->flags & SEC_CODE)
2020 fixP->fx_done = 0;
2021 else if (!fixP->fx_pcrel && fixP->fx_addsy != NULL)
2022 fixP->fx_done = 0;
2023 else
2024 fixP->fx_done = 1;
2025
2026 switch (fixP->fx_r_type)
2027 {
2028 case BFD_RELOC_MICROBLAZE_32_LO:
2029 case BFD_RELOC_MICROBLAZE_32_LO_PCREL:
2030 if (target_big_endian)
2031 {
2032 buf[2] |= ((val >> 8) & 0xff);
2033 buf[3] |= (val & 0xff);
2034 }
2035 else
2036 {
2037 buf[1] |= ((val >> 8) & 0xff);
2038 buf[0] |= (val & 0xff);
2039 }
2040 break;
2041 case BFD_RELOC_MICROBLAZE_32_ROSDA:
2042 case BFD_RELOC_MICROBLAZE_32_RWSDA:
2043 /* Don't do anything if the symbol is not defined. */
2044 if (fixP->fx_addsy == NULL || S_IS_DEFINED (fixP->fx_addsy))
2045 {
2046 if (((val & 0xFFFF8000) != 0) && ((val & 0xFFFF8000) != 0xFFFF8000))
2047 as_bad_where (file, fixP->fx_line,
2048 _("pcrel for branch to %s too far (0x%x)"),
2049 symname, (int) val);
2050 if (target_big_endian)
2051 {
2052 buf[2] |= ((val >> 8) & 0xff);
2053 buf[3] |= (val & 0xff);
2054 }
2055 else
2056 {
2057 buf[1] |= ((val >> 8) & 0xff);
2058 buf[0] |= (val & 0xff);
2059 }
2060 }
2061 break;
2062 case BFD_RELOC_32:
2063 case BFD_RELOC_RVA:
2064 case BFD_RELOC_32_PCREL:
2065 case BFD_RELOC_MICROBLAZE_32_SYM_OP_SYM:
2066 /* Don't do anything if the symbol is not defined. */
2067 if (fixP->fx_addsy == NULL || S_IS_DEFINED (fixP->fx_addsy))
2068 {
2069 if (target_big_endian)
2070 {
2071 buf[0] |= ((val >> 24) & 0xff);
2072 buf[1] |= ((val >> 16) & 0xff);
2073 buf[2] |= ((val >> 8) & 0xff);
2074 buf[3] |= (val & 0xff);
2075 }
2076 else
2077 {
2078 buf[3] |= ((val >> 24) & 0xff);
2079 buf[2] |= ((val >> 16) & 0xff);
2080 buf[1] |= ((val >> 8) & 0xff);
2081 buf[0] |= (val & 0xff);
2082 }
2083 }
2084 break;
2085 case BFD_RELOC_64_PCREL:
2086 case BFD_RELOC_64:
2087 /* Add an imm instruction. First save the current instruction. */
2088 for (i = 0; i < INST_WORD_SIZE; i++)
2089 buf[i + INST_WORD_SIZE] = buf[i];
2090
2091 /* Generate the imm instruction. */
2092 opcode1 = (struct op_code_struct *) hash_find (opcode_hash_control, "imm");
2093 if (opcode1 == NULL)
2094 {
2095 as_bad (_("unknown opcode \"%s\""), "imm");
2096 return;
2097 }
2098
2099 inst1 = opcode1->bit_sequence;
2100 if (fixP->fx_addsy == NULL || S_IS_DEFINED (fixP->fx_addsy))
2101 inst1 |= ((val & 0xFFFF0000) >> 16) & IMM_MASK;
2102
2103 buf[0] = INST_BYTE0 (inst1);
2104 buf[1] = INST_BYTE1 (inst1);
2105 buf[2] = INST_BYTE2 (inst1);
2106 buf[3] = INST_BYTE3 (inst1);
2107
2108 /* Add the value only if the symbol is defined. */
2109 if (fixP->fx_addsy == NULL || S_IS_DEFINED (fixP->fx_addsy))
2110 {
2111 if (target_big_endian)
2112 {
2113 buf[6] |= ((val >> 8) & 0xff);
2114 buf[7] |= (val & 0xff);
2115 }
2116 else
2117 {
2118 buf[5] |= ((val >> 8) & 0xff);
2119 buf[4] |= (val & 0xff);
2120 }
2121 }
2122 break;
2123
69b06cc8
ME
2124 case BFD_RELOC_MICROBLAZE_64_TLSDTPREL:
2125 case BFD_RELOC_MICROBLAZE_64_TLSGD:
2126 case BFD_RELOC_MICROBLAZE_64_TLSLD:
2127 S_SET_THREAD_LOCAL (fixP->fx_addsy);
2128
7ba29e2a
NC
2129 case BFD_RELOC_MICROBLAZE_64_GOTPC:
2130 case BFD_RELOC_MICROBLAZE_64_GOT:
2131 case BFD_RELOC_MICROBLAZE_64_PLT:
2132 case BFD_RELOC_MICROBLAZE_64_GOTOFF:
2133 /* Add an imm instruction. First save the current instruction. */
2134 for (i = 0; i < INST_WORD_SIZE; i++)
2135 buf[i + INST_WORD_SIZE] = buf[i];
2136
2137 /* Generate the imm instruction. */
2138 opcode1 = (struct op_code_struct *) hash_find (opcode_hash_control, "imm");
2139 if (opcode1 == NULL)
2140 {
2141 as_bad (_("unknown opcode \"%s\""), "imm");
2142 return;
2143 }
2144
2145 inst1 = opcode1->bit_sequence;
2146
2147 /* We can fixup call to a defined non-global address
2148 within the same section only. */
2149 buf[0] = INST_BYTE0 (inst1);
2150 buf[1] = INST_BYTE1 (inst1);
2151 buf[2] = INST_BYTE2 (inst1);
2152 buf[3] = INST_BYTE3 (inst1);
2153 return;
2154
2155 default:
2156 break;
2157 }
2158
2159 if (fixP->fx_addsy == NULL)
2160 {
2161 /* This fixup has been resolved. Create a reloc in case the linker
2162 moves code around due to relaxing. */
2163 if (fixP->fx_r_type == BFD_RELOC_64_PCREL)
2164 fixP->fx_r_type = BFD_RELOC_MICROBLAZE_64_NONE;
2165 else
2166 fixP->fx_r_type = BFD_RELOC_NONE;
2167 fixP->fx_addsy = section_symbol (absolute_section);
2168 }
2169 return;
2170}
2171
2172void
2173md_operand (expressionS * expressionP)
2174{
2175 /* Ignore leading hash symbol, if present. */
2176 if (*input_line_pointer == '#')
2177 {
2178 input_line_pointer ++;
2179 expression (expressionP);
2180 }
2181}
2182
2183/* Called just before address relaxation, return the length
2184 by which a fragment must grow to reach it's destination. */
2185
2186int
2187md_estimate_size_before_relax (fragS * fragP,
2188 segT segment_type)
2189{
2190 sbss_segment = bfd_get_section_by_name (stdoutput, ".sbss");
2191 sbss2_segment = bfd_get_section_by_name (stdoutput, ".sbss2");
2192 sdata_segment = bfd_get_section_by_name (stdoutput, ".sdata");
2193 sdata2_segment = bfd_get_section_by_name (stdoutput, ".sdata2");
2194
2195 switch (fragP->fr_subtype)
2196 {
2197 case INST_PC_OFFSET:
2198 /* Used to be a PC-relative branch. */
2199 if (!fragP->fr_symbol)
2200 {
2201 /* We know the abs value: Should never happen. */
2202 as_bad (_("Absolute PC-relative value in relaxation code. Assembler error....."));
2203 abort ();
2204 }
28ad2e2d
ME
2205 else if (S_GET_SEGMENT (fragP->fr_symbol) == segment_type &&
2206 !S_IS_WEAK (fragP->fr_symbol))
7ba29e2a
NC
2207 {
2208 fragP->fr_subtype = DEFINED_PC_OFFSET;
2209 /* Don't know now whether we need an imm instruction. */
2210 fragP->fr_var = INST_WORD_SIZE;
2211 }
2212 else if (S_IS_DEFINED (fragP->fr_symbol)
2213 && (((S_GET_SEGMENT (fragP->fr_symbol))->flags & SEC_CODE) == 0))
2214 {
2215 /* Cannot have a PC-relative branch to a diff segment. */
2216 as_bad (_("PC relative branch to label %s which is not in the instruction space"),
2217 S_GET_NAME (fragP->fr_symbol));
2218 fragP->fr_subtype = UNDEFINED_PC_OFFSET;
2219 fragP->fr_var = INST_WORD_SIZE*2;
2220 }
2221 else
2222 {
2223 fragP->fr_subtype = UNDEFINED_PC_OFFSET;
2224 fragP->fr_var = INST_WORD_SIZE*2;
2225 }
2226 break;
2227
2228 case INST_NO_OFFSET:
2229 /* Used to be a reference to somewhere which was unknown. */
2230 if (fragP->fr_symbol)
2231 {
2232 if (fragP->fr_opcode == NULL)
2233 {
2234 /* Used as an absolute value. */
2235 fragP->fr_subtype = DEFINED_ABS_SEGMENT;
2236 /* Variable part does not change. */
2237 fragP->fr_var = INST_WORD_SIZE*2;
2238 }
2239 else if (streq (fragP->fr_opcode, str_microblaze_ro_anchor))
2240 {
2241 /* It is accessed using the small data read only anchor. */
45dfa85a 2242 if ((S_GET_SEGMENT (fragP->fr_symbol) == bfd_com_section_ptr)
7ba29e2a
NC
2243 || (S_GET_SEGMENT (fragP->fr_symbol) == sdata2_segment)
2244 || (S_GET_SEGMENT (fragP->fr_symbol) == sbss2_segment)
2245 || (! S_IS_DEFINED (fragP->fr_symbol)))
2246 {
2247 fragP->fr_subtype = DEFINED_RO_SEGMENT;
2248 fragP->fr_var = INST_WORD_SIZE;
2249 }
2250 else
2251 {
2252 /* Variable not in small data read only segment accessed
2253 using small data read only anchor. */
2254 char *file = fragP->fr_file ? fragP->fr_file : _("unknown");
2255
2256 as_bad_where (file, fragP->fr_line,
2257 _("Variable is accessed using small data read "
2258 "only anchor, but it is not in the small data "
2259 "read only section"));
2260 fragP->fr_subtype = DEFINED_RO_SEGMENT;
2261 fragP->fr_var = INST_WORD_SIZE;
2262 }
2263 }
2264 else if (streq (fragP->fr_opcode, str_microblaze_rw_anchor))
2265 {
45dfa85a 2266 if ((S_GET_SEGMENT (fragP->fr_symbol) == bfd_com_section_ptr)
7ba29e2a
NC
2267 || (S_GET_SEGMENT (fragP->fr_symbol) == sdata_segment)
2268 || (S_GET_SEGMENT (fragP->fr_symbol) == sbss_segment)
2269 || (!S_IS_DEFINED (fragP->fr_symbol)))
2270 {
2271 /* It is accessed using the small data read write anchor. */
2272 fragP->fr_subtype = DEFINED_RW_SEGMENT;
2273 fragP->fr_var = INST_WORD_SIZE;
2274 }
2275 else
2276 {
2277 char *file = fragP->fr_file ? fragP->fr_file : _("unknown");
2278
2279 as_bad_where (file, fragP->fr_line,
2280 _("Variable is accessed using small data read "
2281 "write anchor, but it is not in the small data "
2282 "read write section"));
2283 fragP->fr_subtype = DEFINED_RW_SEGMENT;
2284 fragP->fr_var = INST_WORD_SIZE;
2285 }
2286 }
2287 else
2288 {
2289 as_bad (_("Incorrect fr_opcode value in frag. Internal error....."));
2290 abort ();
2291 }
2292 }
2293 else
2294 {
2295 /* We know the abs value: Should never happen. */
2296 as_bad (_("Absolute value in relaxation code. Assembler error....."));
2297 abort ();
2298 }
2299 break;
2300
2301 case UNDEFINED_PC_OFFSET:
2302 case LARGE_DEFINED_PC_OFFSET:
2303 case DEFINED_ABS_SEGMENT:
2304 case GOT_OFFSET:
2305 case PLT_OFFSET:
2306 case GOTOFF_OFFSET:
69b06cc8
ME
2307 case TLSGD_OFFSET:
2308 case TLSLD_OFFSET:
2309 case TLSTPREL_OFFSET:
2310 case TLSDTPREL_OFFSET:
7ba29e2a
NC
2311 fragP->fr_var = INST_WORD_SIZE*2;
2312 break;
2313 case DEFINED_RO_SEGMENT:
2314 case DEFINED_RW_SEGMENT:
2315 case DEFINED_PC_OFFSET:
69b06cc8 2316 case TLSDTPMOD_OFFSET:
7ba29e2a
NC
2317 fragP->fr_var = INST_WORD_SIZE;
2318 break;
2319 default:
2320 abort ();
2321 }
2322
2323 return fragP->fr_var;
2324}
2325
2326/* Put number into target byte order. */
2327
2328void
2329md_number_to_chars (char * ptr, valueT use, int nbytes)
2330{
2331 if (target_big_endian)
2332 number_to_chars_bigendian (ptr, use, nbytes);
2333 else
2334 number_to_chars_littleendian (ptr, use, nbytes);
2335}
2336
2337/* Round up a section size to the appropriate boundary. */
2338
2339valueT
2340md_section_align (segT segment ATTRIBUTE_UNUSED, valueT size)
2341{
2342 return size; /* Byte alignment is fine. */
2343}
2344
2345
2346/* The location from which a PC relative jump should be calculated,
2347 given a PC relative reloc. */
2348
2349long
2350md_pcrel_from_section (fixS * fixp, segT sec ATTRIBUTE_UNUSED)
2351{
2352#ifdef OBJ_ELF
2353 /* If the symbol is undefined or defined in another section
2354 we leave the add number alone for the linker to fix it later.
2355 Only account for the PC pre-bump (No PC-pre-bump on the Microblaze). */
2356
2357 if (fixp->fx_addsy != (symbolS *) NULL
2358 && (!S_IS_DEFINED (fixp->fx_addsy)
2359 || (S_GET_SEGMENT (fixp->fx_addsy) != sec)))
2360 return 0;
2361 else
2362 {
2363 /* The case where we are going to resolve things... */
2364 if (fixp->fx_r_type == BFD_RELOC_64_PCREL)
2365 return fixp->fx_where + fixp->fx_frag->fr_address + INST_WORD_SIZE;
2366 else
2367 return fixp->fx_where + fixp->fx_frag->fr_address;
2368 }
2369#endif
2370}
2371
2372
2373#define F(SZ,PCREL) (((SZ) << 1) + (PCREL))
2374#define MAP(SZ,PCREL,TYPE) case F (SZ, PCREL): code = (TYPE); break
2375
2376arelent *
2377tc_gen_reloc (asection * section ATTRIBUTE_UNUSED, fixS * fixp)
2378{
2379 arelent * rel;
2380 bfd_reloc_code_real_type code;
2381
2382 switch (fixp->fx_r_type)
2383 {
2384 case BFD_RELOC_NONE:
2385 case BFD_RELOC_MICROBLAZE_64_NONE:
2386 case BFD_RELOC_32:
2387 case BFD_RELOC_MICROBLAZE_32_LO:
2388 case BFD_RELOC_MICROBLAZE_32_LO_PCREL:
2389 case BFD_RELOC_RVA:
2390 case BFD_RELOC_64:
2391 case BFD_RELOC_64_PCREL:
2392 case BFD_RELOC_MICROBLAZE_32_ROSDA:
2393 case BFD_RELOC_MICROBLAZE_32_RWSDA:
2394 case BFD_RELOC_MICROBLAZE_32_SYM_OP_SYM:
2395 case BFD_RELOC_MICROBLAZE_64_GOTPC:
2396 case BFD_RELOC_MICROBLAZE_64_GOT:
2397 case BFD_RELOC_MICROBLAZE_64_PLT:
2398 case BFD_RELOC_MICROBLAZE_64_GOTOFF:
2399 case BFD_RELOC_MICROBLAZE_32_GOTOFF:
69b06cc8
ME
2400 case BFD_RELOC_MICROBLAZE_64_TLSGD:
2401 case BFD_RELOC_MICROBLAZE_64_TLSLD:
2402 case BFD_RELOC_MICROBLAZE_32_TLSDTPMOD:
2403 case BFD_RELOC_MICROBLAZE_32_TLSDTPREL:
2404 case BFD_RELOC_MICROBLAZE_64_TLSDTPREL:
2405 case BFD_RELOC_MICROBLAZE_64_TLSGOTTPREL:
2406 case BFD_RELOC_MICROBLAZE_64_TLSTPREL:
7ba29e2a
NC
2407 code = fixp->fx_r_type;
2408 break;
2409
2410 default:
2411 switch (F (fixp->fx_size, fixp->fx_pcrel))
2412 {
2413 MAP (1, 0, BFD_RELOC_8);
2414 MAP (2, 0, BFD_RELOC_16);
2415 MAP (4, 0, BFD_RELOC_32);
2416 MAP (1, 1, BFD_RELOC_8_PCREL);
2417 MAP (2, 1, BFD_RELOC_16_PCREL);
2418 MAP (4, 1, BFD_RELOC_32_PCREL);
2419 default:
2420 code = fixp->fx_r_type;
2421 as_bad (_("Can not do %d byte %srelocation"),
2422 fixp->fx_size,
2423 fixp->fx_pcrel ? _("pc-relative") : "");
2424 }
2425 break;
2426 }
2427
2428 rel = (arelent *) xmalloc (sizeof (arelent));
2429 rel->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *));
2430
2431 if (code == BFD_RELOC_MICROBLAZE_32_SYM_OP_SYM)
2432 *rel->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_subsy);
2433 else
2434 *rel->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
2435
2436 rel->address = fixp->fx_frag->fr_address + fixp->fx_where;
2437 /* Always pass the addend along! */
2438 rel->addend = fixp->fx_offset;
2439 rel->howto = bfd_reloc_type_lookup (stdoutput, code);
2440
2441 if (rel->howto == NULL)
2442 {
2443 as_bad_where (fixp->fx_file, fixp->fx_line,
2444 _("Cannot represent relocation type %s"),
2445 bfd_get_reloc_code_name (code));
2446
2447 /* Set howto to a garbage value so that we can keep going. */
2448 rel->howto = bfd_reloc_type_lookup (stdoutput, BFD_RELOC_32);
2449 gas_assert (rel->howto != NULL);
2450 }
2451 return rel;
2452}
2453
2454int
2455md_parse_option (int c, char * arg ATTRIBUTE_UNUSED)
2456{
2457 switch (c)
2458 {
f23200ad
ME
2459 case OPTION_EB:
2460 target_big_endian = 1;
2461 break;
2462 case OPTION_EL:
2463 target_big_endian = 0;
2464 break;
7ba29e2a
NC
2465 default:
2466 return 0;
2467 }
2468 return 1;
2469}
2470
2471void
2472md_show_usage (FILE * stream ATTRIBUTE_UNUSED)
2473{
2474 /* fprintf(stream, _("\
2475 MicroBlaze options:\n\
2476 -noSmall Data in the comm and data sections do not go into the small data section\n")); */
2477}
2478
2479
2480/* Create a fixup for a cons expression. If parse_cons_expression_microblaze
2481 found a machine specific op in an expression,
2482 then we create relocs accordingly. */
2483
2484void
2485cons_fix_new_microblaze (fragS * frag,
2486 int where,
2487 int size,
2488 expressionS *exp)
2489{
2490
2491 bfd_reloc_code_real_type r;
2492
2493 if ((exp->X_op == O_subtract) && (exp->X_add_symbol) &&
2494 (exp->X_op_symbol) && (now_seg != absolute_section) && (size == 4)
2495 && (!S_IS_LOCAL (exp->X_op_symbol)))
2496 r = BFD_RELOC_MICROBLAZE_32_SYM_OP_SYM;
2497 else if (exp->X_md == IMM_GOTOFF && exp->X_op == O_symbol_rva)
2498 {
2499 exp->X_op = O_symbol;
2500 r = BFD_RELOC_MICROBLAZE_32_GOTOFF;
2501 }
2502 else
2503 {
2504 switch (size)
2505 {
2506 case 1:
2507 r = BFD_RELOC_8;
2508 break;
2509 case 2:
2510 r = BFD_RELOC_16;
2511 break;
2512 case 4:
2513 r = BFD_RELOC_32;
2514 break;
2515 case 8:
2516 r = BFD_RELOC_64;
2517 break;
2518 default:
2519 as_bad (_("unsupported BFD relocation size %u"), size);
2520 r = BFD_RELOC_32;
2521 break;
2522 }
2523 }
2524 fix_new_exp (frag, where, size, exp, 0, r);
2525}
This page took 0.347083 seconds and 4 git commands to generate.