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