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