[BACK]Return to tc-microblaze.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / external / gpl3 / binutils.old / dist / gas / config

Annotation of src/external/gpl3/binutils.old/dist/gas/config/tc-microblaze.c, Revision 1.5

1.1       christos    1: /* tc-microblaze.c -- Assemble code for Xilinx MicroBlaze
                      2:
1.5     ! christos    3:    Copyright (C) 2009-2016 Free Software Foundation, Inc.
1.1       christos    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:
                     22: #include "as.h"
                     23: #include <stdio.h>
                     24: #include "bfd.h"
                     25: #include "subsegs.h"
                     26: #define DEFINE_TABLE
                     27: #include "../opcodes/microblaze-opc.h"
                     28: #include "../opcodes/microblaze-opcm.h"
                     29: #include "safe-ctype.h"
                     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:
1.3       christos   38: #define OPTION_EB (OPTION_MD_BASE + 0)
                     39: #define OPTION_EL (OPTION_MD_BASE + 1)
                     40:
1.1       christos   41: void microblaze_generate_symbol (char *sym);
                     42: static 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.  */
                     55: const char comment_chars[] = "#";
                     56:
                     57: const char line_separator_chars[] = ";";
                     58:
                     59: /* This array holds the chars that only start a comment at the beginning of
                     60:    a line.  */
                     61: const char line_comment_chars[] = "#";
                     62:
                     63: const 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.  */
                     67: const 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.  */
                     72: const 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
1.3       christos   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
1.1       christos   90:
                     91: /* Initialize the relax table.  */
                     92: const 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.  */
1.3       christos  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.  */
1.1       christos  111: };
                    112:
                    113: static struct hash_control * opcode_hash_control;      /* Opcode mnemonics.  */
                    114:
                    115: static segT sbss_segment = 0;  /* Small bss section.  */
                    116: static segT sbss2_segment = 0;         /* Section not used.  */
                    117: static segT sdata_segment = 0;         /* Small data section.  */
                    118: static segT sdata2_segment = 0; /* Small read-only section.  */
                    119: static segT rodata_segment = 0; /* read-only section.  */
                    120:
                    121: /* Generate a symbol for stabs information.  */
                    122:
                    123: void
                    124: microblaze_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:
                    134: static void
                    135: microblaze_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:
                    144: static void
                    145: microblaze_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:
                    156: static void
                    157: microblaze_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:
                    168: static void
                    169: microblaze_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;
                    177:   char *pfrag;
                    178:   int align2;
                    179:   segT current_seg = now_seg;
                    180:   subsegT current_subseg = now_subseg;
                    181:
1.3       christos  182:   c = get_symbol_name (&name);
1.1       christos  183:
                    184:   /* Just after name is now '\0'.  */
                    185:   p = input_line_pointer;
1.3       christos  186:   (void) restore_line_pointer (c);
1.1       christos  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.  */
                    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:
                    271: static void
                    272: microblaze_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:
                    292: static void
                    293: microblaze_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:
                    314: static void
                    315: microblaze_s_func (int end_p ATTRIBUTE_UNUSED)
                    316: {
1.3       christos  317:   char *name;
                    318:   restore_line_pointer (get_symbol_name (&name));
1.1       christos  319:   s_func (1);
                    320: }
                    321:
                    322: /* Handle the .weakext pseudo-op as defined in Kane and Heinrich.  */
                    323:
                    324: static void
                    325: microblaze_s_weakext (int ignore ATTRIBUTE_UNUSED)
                    326: {
                    327:   char *name;
                    328:   int c;
                    329:   symbolS *symbolP;
                    330:   expressionS exp;
                    331:
1.3       christos  332:   c = get_symbol_name (&name);
1.1       christos  333:   symbolP = symbol_find_or_make (name);
                    334:   S_SET_WEAK (symbolP);
1.3       christos  335:   (void) restore_line_pointer (c);
1.1       christos  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.  */
                    375: const 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:
                    401: void
                    402: md_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:
                    415: static char *
                    416: parse_reg (char * s, unsigned * reg)
                    417: {
                    418:   unsigned tmpreg = 0;
                    419:
                    420:   /* Strip leading whitespace.  */
                    421:   while (ISSPACE (* s))
                    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:     {
                    493:       if (ISDIGIT (s[4]) && ISDIGIT (s[5]))
                    494:         {
                    495:           tmpreg = (s[4]-'0')*10 + s[5] - '0';
                    496:           s += 6;
                    497:         }
                    498:
                    499:       else if (ISDIGIT (s[4]))
                    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:     {
                    522:       if (ISDIGIT (s[4]) && ISDIGIT (s[5]))
                    523:         {
                    524:           tmpreg = (s[4] - '0') * 10 + s[5] - '0';
                    525:           s += 6;
                    526:         }
                    527:       else if (ISDIGIT (s[4]))
                    528:         {
                    529:           tmpreg = s[4] - '0';
                    530:           s += 5;
                    531:         }
                    532:       else
                    533:        as_bad (_("register expected, but saw '%.6s'"), s);
                    534:
                    535:       if ((int) tmpreg >= MIN_REGNUM && tmpreg <= MAX_REGNUM)
                    536:         *reg = tmpreg;
                    537:       else
                    538:        {
                    539:           as_bad (_("Invalid register number at '%.6s'"), s);
                    540:           *reg = 0;
                    541:        }
                    542:       return s;
                    543:     }
1.3       christos  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:     }
1.1       christos  555:   else
                    556:     {
                    557:       if (TOLOWER (s[0]) == 'r')
                    558:         {
                    559:           if (ISDIGIT (s[1]) && ISDIGIT (s[2]))
                    560:             {
                    561:               tmpreg = (s[1] - '0') * 10 + s[2] - '0';
                    562:               s += 3;
                    563:             }
                    564:           else if (ISDIGIT (s[1]))
                    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:
                    587: static char *
                    588: parse_exp (char *s, expressionS *e)
                    589: {
                    590:   char *save;
                    591:   char *new_pointer;
                    592:
                    593:   /* Skip whitespace.  */
                    594:   while (ISSPACE (* s))
                    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:
                    605:   new_pointer = input_line_pointer;
                    606:   input_line_pointer = save;
                    607:
                    608:   return new_pointer;
                    609: }
                    610:
                    611: /* Symbol modifiers (@GOT, @PLT, @GOTOFF).  */
1.3       christos  612: #define IMM_NONE   0
1.1       christos  613: #define IMM_GOT    1
                    614: #define IMM_PLT    2
                    615: #define IMM_GOTOFF 3
1.3       christos  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:
                    623: struct imm_type {
1.5     ! christos  624:        const char *isuffix;     /* Suffix String */
1.3       christos  625:        int itype;       /* Suffix Type */
                    626:        int otype;       /* Offset Type */
                    627: };
                    628:
                    629: /* These are NOT in assending order of type, GOTOFF is ahead to make
                    630:    sure @GOTOFF does not get matched with @GOT  */
                    631: static 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:
                    643: static int
                    644: match_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:
                    664: static int
                    665: get_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: }
1.1       christos  681:
                    682: static symbolS * GOT_symbol;
                    683:
                    684: #define GOT_SYMBOL_NAME "_GLOBAL_OFFSET_TABLE_"
                    685:
                    686: static char *
1.3       christos  687: parse_imm (char * s, expressionS * e, offsetT min, offsetT max)
1.1       christos  688: {
                    689:   char *new_pointer;
                    690:   char *atp;
1.3       christos  691:   int itype, ilen;
                    692:
                    693:   ilen = 0;
1.1       christos  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:     {
1.3       christos  702:       itype = match_imm (atp + 1, &ilen);
                    703:       if (itype != 0)
                    704:         {
                    705:           *atp = 0;
                    706:           e->X_md = itype;
                    707:         }
1.1       christos  708:       else
1.3       christos  709:         {
                    710:           atp = NULL;
                    711:           e->X_md = 0;
                    712:           ilen = 0;
                    713:         }
1.1       christos  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:
                    727:   new_pointer = parse_exp (s, e);
                    728:
1.3       christos  729:   if (!GOT_symbol && ! strncmp (s, GOT_SYMBOL_NAME, 20))
                    730:     {
                    731:       GOT_symbol = symbol_find_or_make (GOT_SYMBOL_NAME);
                    732:     }
                    733:
1.1       christos  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"));
1.3       christos  738:   else if (e->X_op == O_constant)
1.1       christos  739:     {
1.5     ! christos  740:       /* Special case: sign extend negative 32-bit values to offsetT size.  */
1.3       christos  741:       if ((e->X_add_number >> 31) == 1)
1.5     ! christos  742:        e->X_add_number |= -((addressT) (1U << 31));
1.3       christos  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:        }
1.1       christos  749:     }
                    750:
                    751:   if (atp)
                    752:     {
                    753:       *atp = '@'; /* restore back (needed?)  */
                    754:       if (new_pointer >= atp)
1.3       christos  755:         new_pointer += ilen + 1; /* sizeof (imm_suffix) + 1 for '@' */
1.1       christos  756:     }
                    757:   return new_pointer;
                    758: }
                    759:
                    760: static char *
                    761: check_got (int * got_type, int * got_len)
                    762: {
                    763:   char *new_pointer;
                    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;
                    798:   for (new_pointer = past_got; !is_end_of_line[(unsigned char) *new_pointer++];)
                    799:     ;
                    800:   second = new_pointer - past_got;
1.5     ! christos  801:   /* One extra byte for ' ' and one for NUL.  */
        !           802:   tmpbuf = XNEWVEC (char, first + second + 2);
1.1       christos  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:
1.3       christos  811: extern bfd_reloc_code_real_type
1.1       christos  812: parse_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);
1.3       christos  837:   return BFD_RELOC_NONE;
1.1       christos  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:
1.5     ! christos  844: static const char * str_microblaze_ro_anchor = "RO";
        !           845: static const char * str_microblaze_rw_anchor = "RW";
1.1       christos  846:
                    847: static bfd_boolean
                    848: check_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)
1.3       christos  856:       || (*reg == REG_SHR)   || (*reg == REG_SLR)
1.1       christos  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:
                    868: int
                    869: tc_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
1.3       christos  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)
1.1       christos  885:     return 0;
                    886:
                    887:   return 1;
                    888: }
                    889:
                    890: void
                    891: md_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;
                    904:   unsigned int immed, temp;
                    905:   expressionS exp;
                    906:   char name[20];
                    907:
                    908:   /* Drop leading whitespace.  */
                    909:   while (ISSPACE (* str))
                    910:     str ++;
                    911:
                    912:   /* Find the op code end.  */
                    913:   for (op_start = op_end = str;
                    914:        *op_end && !is_end_of_line[(unsigned char) *op_end] && *op_end != ' ';
                    915:        op_end++)
                    916:     {
                    917:       name[nlen] = op_start[nlen];
                    918:       nlen++;
                    919:       if (nlen == sizeof (name) - 1)
                    920:        break;
                    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:        {
1.5     ! christos 1018:           const char *opc;
1.1       christos 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;
1.3       christos 1032:          if (exp.X_md != 0)
                   1033:            subtype = get_imm_otype(exp.X_md);
1.1       christos 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,
1.5     ! christos 1043:                             (char *) opc);
1.1       christos 1044:          immed = 0;
                   1045:         }
                   1046:       else
                   1047:        {
                   1048:           output = frag_more (isize);
                   1049:           immed = exp.X_add_number;
                   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;
                   1072:           inst |= (immed << IMM_LOW) & IMM_MASK;
                   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);
                   1081:               immed = immed + 4;
                   1082:               reg1++;
                   1083:               inst = opcode->bit_sequence;
                   1084:               inst |= (reg1 << RD_LOW) & RD_MASK;
                   1085:               inst |= (reg2 << RA_LOW) & RA_MASK;
                   1086:               inst |= (immed << IMM_LOW) & IMM_MASK;
                   1087:             }
                   1088:        }
                   1089:       else
                   1090:        {
                   1091:           temp = immed & 0xFFFF8000;
                   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;
                   1103:               inst1 |= ((immed & 0xFFFF0000) >> 16) & IMM_MASK;
                   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;
                   1112:          inst |= (immed << IMM_LOW) & IMM_MASK;
                   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);
                   1147:           immed = exp.X_add_number;
                   1148:         }
                   1149:
                   1150:       if (immed != (immed % 32))
                   1151:        {
                   1152:           as_warn (_("Shift value > 32. using <value %% 32>"));
                   1153:           immed = immed % 32;
                   1154:         }
                   1155:       inst |= (reg1 << RD_LOW) & RD_MASK;
                   1156:       inst |= (reg2 << RA_LOW) & RA_MASK;
                   1157:       inst |= (immed << IMM_LOW) & IMM5_MASK;
                   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, ""))
                   1223:         op_end = parse_reg (op_end + 1, &immed);  /* Get rfslN.  */
                   1224:       else
                   1225:        {
                   1226:           as_fatal (_("Error in statement syntax"));
                   1227:           immed = 0;
                   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;
                   1235:       inst |= (immed << IMM_LOW) & RFSL_MASK;
                   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);
                   1262:           immed = exp.X_add_number;
                   1263:         }
                   1264:       inst |= (reg1 << RD_LOW) & RD_MASK;
                   1265:       inst |= (immed << IMM_LOW) & IMM15_MASK;
                   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, ""))
                   1277:         op_end = parse_reg (op_end + 1, &immed);  /* Get rfslN.  */
                   1278:       else
                   1279:        {
                   1280:           as_fatal (_("Error in statement syntax"));
                   1281:           immed = 0;
                   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;
                   1289:       inst |= (immed << IMM_LOW) & RFSL_MASK;
                   1290:       output = frag_more (isize);
                   1291:       break;
                   1292:
                   1293:     case INST_TYPE_RFSL:
                   1294:       if (strcmp (op_end, ""))
                   1295:         op_end = parse_reg (op_end + 1, &immed);  /* Get rfslN.  */
                   1296:       else
                   1297:        {
                   1298:           as_fatal (_("Error in statement syntax"));
                   1299:           immed = 0;
                   1300:         }
                   1301:       inst |= (immed << IMM_LOW) & RFSL_MASK;
                   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)
                   1357:         immed = opcode->immval_mask | REG_MSR_MASK;
                   1358:       else if (reg2 == REG_PC)
                   1359:         immed = opcode->immval_mask | REG_PC_MASK;
                   1360:       else if (reg2 == REG_EAR)
                   1361:         immed = opcode->immval_mask | REG_EAR_MASK;
                   1362:       else if (reg2 == REG_ESR)
                   1363:         immed = opcode->immval_mask | REG_ESR_MASK;
                   1364:       else if (reg2 == REG_FSR)
                   1365:         immed = opcode->immval_mask | REG_FSR_MASK;
                   1366:       else if (reg2 == REG_BTR)
                   1367:         immed = opcode->immval_mask | REG_BTR_MASK;
                   1368:       else if (reg2 == REG_EDR)
                   1369:         immed = opcode->immval_mask | REG_EDR_MASK;
                   1370:       else if (reg2 == REG_PID)
                   1371:         immed = opcode->immval_mask | REG_PID_MASK;
                   1372:       else if (reg2 == REG_ZPR)
                   1373:         immed = opcode->immval_mask | REG_ZPR_MASK;
                   1374:       else if (reg2 == REG_TLBX)
                   1375:         immed = opcode->immval_mask | REG_TLBX_MASK;
                   1376:       else if (reg2 == REG_TLBLO)
                   1377:         immed = opcode->immval_mask | REG_TLBLO_MASK;
                   1378:       else if (reg2 == REG_TLBHI)
                   1379:         immed = opcode->immval_mask | REG_TLBHI_MASK;
1.3       christos 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;
1.1       christos 1384:       else if (reg2 >= (REG_PVR+MIN_PVR_REGNUM) && reg2 <= (REG_PVR+MAX_PVR_REGNUM))
                   1385:        immed = opcode->immval_mask | REG_PVR_MASK | reg2;
                   1386:       else
                   1387:         as_fatal (_("invalid value for special purpose register"));
                   1388:       inst |= (reg1 << RD_LOW) & RD_MASK;
                   1389:       inst |= (immed << IMM_LOW) & IMM_MASK;
                   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)
                   1410:         immed = opcode->immval_mask | REG_MSR_MASK;
                   1411:       else if (reg1 == REG_PC)
                   1412:         immed = opcode->immval_mask | REG_PC_MASK;
                   1413:       else if (reg1 == REG_EAR)
                   1414:         immed = opcode->immval_mask | REG_EAR_MASK;
                   1415:       else if (reg1 == REG_ESR)
                   1416:         immed = opcode->immval_mask | REG_ESR_MASK;
                   1417:       else if (reg1 == REG_FSR)
                   1418:         immed = opcode->immval_mask | REG_FSR_MASK;
                   1419:       else if (reg1 == REG_BTR)
                   1420:         immed = opcode->immval_mask | REG_BTR_MASK;
                   1421:       else if (reg1 == REG_EDR)
                   1422:         immed = opcode->immval_mask | REG_EDR_MASK;
                   1423:       else if (reg1 == REG_PID)
                   1424:         immed = opcode->immval_mask | REG_PID_MASK;
                   1425:       else if (reg1 == REG_ZPR)
                   1426:         immed = opcode->immval_mask | REG_ZPR_MASK;
                   1427:       else if (reg1 == REG_TLBX)
                   1428:         immed = opcode->immval_mask | REG_TLBX_MASK;
                   1429:       else if (reg1 == REG_TLBLO)
                   1430:         immed = opcode->immval_mask | REG_TLBLO_MASK;
                   1431:       else if (reg1 == REG_TLBHI)
                   1432:         immed = opcode->immval_mask | REG_TLBHI_MASK;
                   1433:       else if (reg1 == REG_TLBSX)
                   1434:         immed = opcode->immval_mask | REG_TLBSX_MASK;
1.3       christos 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;
1.1       christos 1439:       else
                   1440:         as_fatal (_("invalid value for special purpose register"));
                   1441:       inst |= (reg2 << RA_LOW) & RA_MASK;
                   1442:       inst |= (immed << IMM_LOW) & IMM_MASK;
                   1443:       output = frag_more (isize);
                   1444:       break;
                   1445:
1.3       christos 1446:     case INST_TYPE_R1_R2_SPECIAL:
1.1       christos 1447:       if (strcmp (op_end, ""))
1.3       christos 1448:         op_end = parse_reg (op_end + 1, &reg1);  /* Get r1.  */
1.1       christos 1449:       else
                   1450:        {
                   1451:           as_fatal (_("Error in statement syntax"));
                   1452:           reg1 = 0;
                   1453:         }
                   1454:       if (strcmp (op_end, ""))
1.3       christos 1455:         op_end = parse_reg (op_end + 1, &reg2);  /* Get r2.  */
1.1       christos 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.  */
                   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:
1.3       christos 1524:          if (exp.X_md != 0)
                   1525:            subtype = get_imm_otype(exp.X_md);
1.1       christos 1526:          else
                   1527:            subtype = opcode->inst_offset_type;
1.3       christos 1528:
1.1       christos 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);
                   1536:          immed = 0;
                   1537:        }
                   1538:       else
                   1539:        {
                   1540:           output = frag_more (isize);
                   1541:           immed = exp.X_add_number;
                   1542:         }
                   1543:
                   1544:       temp = immed & 0xFFFF8000;
                   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;
                   1556:           inst1 |= ((immed & 0xFFFF0000) >> 16) & IMM_MASK;
                   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;
                   1565:       inst |= (immed << IMM_LOW) & IMM_MASK;
                   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:
1.3       christos 1590:          if (exp.X_md != 0)
                   1591:            subtype = get_imm_otype(exp.X_md);
                   1592:          else
1.1       christos 1593:            subtype = opcode->inst_offset_type;
1.3       christos 1594:
1.1       christos 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);
                   1602:           immed = 0;
                   1603:        }
                   1604:       else
                   1605:        {
                   1606:           output = frag_more (isize);
                   1607:           immed = exp.X_add_number;
                   1608:         }
                   1609:
                   1610:       temp = immed & 0xFFFF8000;
                   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;
                   1622:           inst1 |= ((immed & 0xFFFF0000) >> 16) & IMM_MASK;
                   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;
                   1631:       inst |= (immed << IMM_LOW) & IMM_MASK;
                   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:
1.3       christos 1662:          if (exp.X_md != 0)
                   1663:            subtype = get_imm_otype(exp.X_md);
                   1664:          else
                   1665:            subtype = opcode->inst_offset_type;
                   1666:
1.1       christos 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);
                   1674:           immed = 0;
                   1675:         }
                   1676:       else
                   1677:        {
                   1678:           output = frag_more (isize);
                   1679:           immed = exp.X_add_number;
                   1680:         }
                   1681:
                   1682:
                   1683:       temp = immed & 0xFFFF8000;
                   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;
                   1695:           inst1 |= ((immed & 0xFFFF0000) >> 16) & IMM_MASK;
                   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:         }
                   1702:       inst |= (immed << IMM_LOW) & IMM_MASK;
                   1703:       break;
                   1704:
                   1705:     case INST_TYPE_NONE:
                   1706:       output = frag_more (isize);
                   1707:       break;
                   1708:
1.3       christos 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:
1.1       christos 1727:     default:
                   1728:       as_fatal (_("unimplemented opcode \"%s\""), name);
                   1729:     }
                   1730:
                   1731:   /* Drop whitespace after all the operands have been parsed.  */
                   1732:   while (ISSPACE (* op_end))
                   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:
                   1749: symbolS *
                   1750: md_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.*/
1.5     ! christos 1762: const char *
1.1       christos 1763: md_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: 
                   1828: const char * md_shortopts = "";
                   1829:
                   1830: struct option md_longopts[] =
                   1831: {
1.3       christos 1832:   {"EB", no_argument, NULL, OPTION_EB},
                   1833:   {"EL", no_argument, NULL, OPTION_EL},
1.1       christos 1834:   { NULL,          no_argument, NULL, 0}
                   1835: };
                   1836:
                   1837: size_t md_longopts_size = sizeof (md_longopts);
                   1838:
                   1839: int md_short_jump_size;
                   1840:
                   1841: void
                   1842: md_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:
                   1851: void
                   1852: md_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:
                   1863: void
                   1864: md_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; */
                   1922:       (void) fixP;
                   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;
1.3       christos 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;
1.1       christos 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.  */
                   1958: void
                   1959: md_apply_fix (fixS *   fixP,
                   1960:              valueT * valp,
                   1961:              segT     segment)
                   1962: {
                   1963:   char *       buf  = fixP->fx_where + fixP->fx_frag->fr_literal;
1.5     ! christos 1964:   const char *       file = fixP->fx_file ? fixP->fx_file : _("unknown");
1.1       christos 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:
1.3       christos 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);
                   2135:
1.1       christos 2136:     case BFD_RELOC_MICROBLAZE_64_GOTPC:
                   2137:     case BFD_RELOC_MICROBLAZE_64_GOT:
                   2138:     case BFD_RELOC_MICROBLAZE_64_PLT:
                   2139:     case BFD_RELOC_MICROBLAZE_64_GOTOFF:
                   2140:       /* Add an imm instruction.  First save the current instruction.  */
                   2141:       for (i = 0; i < INST_WORD_SIZE; i++)
                   2142:        buf[i + INST_WORD_SIZE] = buf[i];
                   2143:
                   2144:       /* Generate the imm instruction.  */
                   2145:       opcode1 = (struct op_code_struct *) hash_find (opcode_hash_control, "imm");
                   2146:       if (opcode1 == NULL)
                   2147:        {
                   2148:          as_bad (_("unknown opcode \"%s\""), "imm");
                   2149:          return;
                   2150:        }
                   2151:
                   2152:       inst1 = opcode1->bit_sequence;
                   2153:
                   2154:       /* We can fixup call to a defined non-global address
                   2155:         within the same section only.  */
                   2156:       buf[0] = INST_BYTE0 (inst1);
                   2157:       buf[1] = INST_BYTE1 (inst1);
                   2158:       buf[2] = INST_BYTE2 (inst1);
                   2159:       buf[3] = INST_BYTE3 (inst1);
                   2160:       return;
                   2161:
                   2162:     default:
                   2163:       break;
                   2164:     }
                   2165:
                   2166:   if (fixP->fx_addsy == NULL)
                   2167:     {
                   2168:       /* This fixup has been resolved.  Create a reloc in case the linker
                   2169:         moves code around due to relaxing.  */
                   2170:       if (fixP->fx_r_type == BFD_RELOC_64_PCREL)
                   2171:        fixP->fx_r_type = BFD_RELOC_MICROBLAZE_64_NONE;
                   2172:       else
                   2173:        fixP->fx_r_type = BFD_RELOC_NONE;
                   2174:       fixP->fx_addsy = section_symbol (absolute_section);
                   2175:     }
                   2176:   return;
                   2177: }
                   2178:
                   2179: void
                   2180: md_operand (expressionS * expressionP)
                   2181: {
                   2182:   /* Ignore leading hash symbol, if present.  */
                   2183:   if (*input_line_pointer == '#')
                   2184:     {
                   2185:       input_line_pointer ++;
                   2186:       expression (expressionP);
                   2187:     }
                   2188: }
                   2189:
                   2190: /* Called just before address relaxation, return the length
                   2191:    by which a fragment must grow to reach it's destination.  */
                   2192:
                   2193: int
                   2194: md_estimate_size_before_relax (fragS * fragP,
                   2195:                               segT segment_type)
                   2196: {
                   2197:   sbss_segment = bfd_get_section_by_name (stdoutput, ".sbss");
                   2198:   sbss2_segment = bfd_get_section_by_name (stdoutput, ".sbss2");
                   2199:   sdata_segment = bfd_get_section_by_name (stdoutput, ".sdata");
                   2200:   sdata2_segment = bfd_get_section_by_name (stdoutput, ".sdata2");
                   2201:
                   2202:   switch (fragP->fr_subtype)
                   2203:     {
                   2204:     case INST_PC_OFFSET:
                   2205:       /* Used to be a PC-relative branch.  */
                   2206:       if (!fragP->fr_symbol)
                   2207:         {
                   2208:           /* We know the abs value: Should never happen.  */
                   2209:           as_bad (_("Absolute PC-relative value in relaxation code.  Assembler error....."));
                   2210:           abort ();
                   2211:         }
1.3       christos 2212:       else if (S_GET_SEGMENT (fragP->fr_symbol) == segment_type &&
                   2213:                !S_IS_WEAK (fragP->fr_symbol))
1.1       christos 2214:         {
                   2215:           fragP->fr_subtype = DEFINED_PC_OFFSET;
                   2216:           /* Don't know now whether we need an imm instruction.  */
                   2217:           fragP->fr_var = INST_WORD_SIZE;
                   2218:         }
                   2219:       else if (S_IS_DEFINED (fragP->fr_symbol)
                   2220:               && (((S_GET_SEGMENT (fragP->fr_symbol))->flags & SEC_CODE) == 0))
                   2221:         {
                   2222:           /* Cannot have a PC-relative branch to a diff segment.  */
                   2223:           as_bad (_("PC relative branch to label %s which is not in the instruction space"),
                   2224:                  S_GET_NAME (fragP->fr_symbol));
                   2225:           fragP->fr_subtype = UNDEFINED_PC_OFFSET;
                   2226:           fragP->fr_var = INST_WORD_SIZE*2;
                   2227:         }
                   2228:       else
                   2229:        {
                   2230:          fragP->fr_subtype = UNDEFINED_PC_OFFSET;
                   2231:          fragP->fr_var = INST_WORD_SIZE*2;
                   2232:        }
                   2233:       break;
                   2234:
                   2235:     case INST_NO_OFFSET:
                   2236:       /* Used to be a reference to somewhere which was unknown.  */
                   2237:       if (fragP->fr_symbol)
                   2238:         {
                   2239:          if (fragP->fr_opcode == NULL)
                   2240:            {
                   2241:               /* Used as an absolute value.  */
                   2242:               fragP->fr_subtype = DEFINED_ABS_SEGMENT;
                   2243:               /* Variable part does not change.  */
                   2244:               fragP->fr_var = INST_WORD_SIZE*2;
                   2245:             }
                   2246:          else if (streq (fragP->fr_opcode, str_microblaze_ro_anchor))
                   2247:            {
                   2248:               /* It is accessed using the small data read only anchor.  */
                   2249:               if ((S_GET_SEGMENT (fragP->fr_symbol) == bfd_com_section_ptr)
                   2250:                  || (S_GET_SEGMENT (fragP->fr_symbol) == sdata2_segment)
                   2251:                  || (S_GET_SEGMENT (fragP->fr_symbol) == sbss2_segment)
                   2252:                  || (! S_IS_DEFINED (fragP->fr_symbol)))
                   2253:                {
                   2254:                   fragP->fr_subtype = DEFINED_RO_SEGMENT;
                   2255:                   fragP->fr_var = INST_WORD_SIZE;
                   2256:                 }
                   2257:              else
                   2258:                {
                   2259:                   /* Variable not in small data read only segment accessed
                   2260:                     using small data read only anchor.  */
1.5     ! christos 2261:                   const char *file = fragP->fr_file ? fragP->fr_file : _("unknown");
1.1       christos 2262:
                   2263:                   as_bad_where (file, fragP->fr_line,
                   2264:                                 _("Variable is accessed using small data read "
                   2265:                                  "only anchor, but it is not in the small data "
                   2266:                                  "read only section"));
                   2267:                   fragP->fr_subtype = DEFINED_RO_SEGMENT;
                   2268:                   fragP->fr_var = INST_WORD_SIZE;
                   2269:                 }
                   2270:             }
                   2271:          else if (streq (fragP->fr_opcode, str_microblaze_rw_anchor))
                   2272:            {
                   2273:               if ((S_GET_SEGMENT (fragP->fr_symbol) == bfd_com_section_ptr)
                   2274:                  || (S_GET_SEGMENT (fragP->fr_symbol) == sdata_segment)
                   2275:                  || (S_GET_SEGMENT (fragP->fr_symbol) == sbss_segment)
                   2276:                  || (!S_IS_DEFINED (fragP->fr_symbol)))
                   2277:                {
                   2278:                   /* It is accessed using the small data read write anchor.  */
                   2279:                   fragP->fr_subtype = DEFINED_RW_SEGMENT;
                   2280:                   fragP->fr_var = INST_WORD_SIZE;
                   2281:                 }
                   2282:              else
                   2283:                {
1.5     ! christos 2284:                   const char *file = fragP->fr_file ? fragP->fr_file : _("unknown");
1.1       christos 2285:
                   2286:                   as_bad_where (file, fragP->fr_line,
                   2287:                                 _("Variable is accessed using small data read "
                   2288:                                  "write anchor, but it is not in the small data "
                   2289:                                  "read write section"));
                   2290:                   fragP->fr_subtype = DEFINED_RW_SEGMENT;
                   2291:                   fragP->fr_var = INST_WORD_SIZE;
                   2292:                 }
                   2293:             }
                   2294:           else
                   2295:            {
                   2296:               as_bad (_("Incorrect fr_opcode value in frag.  Internal error....."));
                   2297:               abort ();
                   2298:             }
                   2299:        }
                   2300:       else
                   2301:        {
                   2302:          /* We know the abs value: Should never happen.  */
                   2303:          as_bad (_("Absolute value in relaxation code.  Assembler error....."));
                   2304:          abort ();
                   2305:        }
                   2306:       break;
                   2307:
                   2308:     case UNDEFINED_PC_OFFSET:
                   2309:     case LARGE_DEFINED_PC_OFFSET:
                   2310:     case DEFINED_ABS_SEGMENT:
                   2311:     case GOT_OFFSET:
                   2312:     case PLT_OFFSET:
                   2313:     case GOTOFF_OFFSET:
1.3       christos 2314:     case TLSGD_OFFSET:
                   2315:     case TLSLD_OFFSET:
                   2316:     case TLSTPREL_OFFSET:
                   2317:     case TLSDTPREL_OFFSET:
1.1       christos 2318:       fragP->fr_var = INST_WORD_SIZE*2;
                   2319:       break;
                   2320:     case DEFINED_RO_SEGMENT:
                   2321:     case DEFINED_RW_SEGMENT:
                   2322:     case DEFINED_PC_OFFSET:
1.3       christos 2323:     case TLSDTPMOD_OFFSET:
1.1       christos 2324:       fragP->fr_var = INST_WORD_SIZE;
                   2325:       break;
                   2326:     default:
                   2327:       abort ();
                   2328:     }
                   2329:
                   2330:   return fragP->fr_var;
                   2331: }
                   2332:
                   2333: /* Put number into target byte order.  */
                   2334:
                   2335: void
                   2336: md_number_to_chars (char * ptr, valueT use, int nbytes)
                   2337: {
                   2338:   if (target_big_endian)
                   2339:     number_to_chars_bigendian (ptr, use, nbytes);
                   2340:   else
                   2341:     number_to_chars_littleendian (ptr, use, nbytes);
                   2342: }
                   2343:
                   2344: /* Round up a section size to the appropriate boundary.  */
                   2345:
                   2346: valueT
                   2347: md_section_align (segT segment ATTRIBUTE_UNUSED, valueT size)
                   2348: {
                   2349:   return size;                 /* Byte alignment is fine.  */
                   2350: }
                   2351:
                   2352:
                   2353: /* The location from which a PC relative jump should be calculated,
                   2354:    given a PC relative reloc.  */
                   2355:
                   2356: long
                   2357: md_pcrel_from_section (fixS * fixp, segT sec ATTRIBUTE_UNUSED)
                   2358: {
                   2359: #ifdef OBJ_ELF
                   2360:   /* If the symbol is undefined or defined in another section
                   2361:      we leave the add number alone for the linker to fix it later.
                   2362:      Only account for the PC pre-bump (No PC-pre-bump on the Microblaze). */
                   2363:
                   2364:   if (fixp->fx_addsy != (symbolS *) NULL
                   2365:       && (!S_IS_DEFINED (fixp->fx_addsy)
                   2366:           || (S_GET_SEGMENT (fixp->fx_addsy) != sec)))
                   2367:     return 0;
                   2368:   else
                   2369:     {
                   2370:       /* The case where we are going to resolve things... */
                   2371:       if (fixp->fx_r_type == BFD_RELOC_64_PCREL)
                   2372:         return  fixp->fx_where + fixp->fx_frag->fr_address + INST_WORD_SIZE;
                   2373:       else
                   2374:         return  fixp->fx_where + fixp->fx_frag->fr_address;
                   2375:     }
                   2376: #endif
                   2377: }
                   2378:
                   2379:
                   2380: #define F(SZ,PCREL)            (((SZ) << 1) + (PCREL))
                   2381: #define MAP(SZ,PCREL,TYPE)     case F (SZ, PCREL): code = (TYPE); break
                   2382:
                   2383: arelent *
                   2384: tc_gen_reloc (asection * section ATTRIBUTE_UNUSED, fixS * fixp)
                   2385: {
                   2386:   arelent * rel;
                   2387:   bfd_reloc_code_real_type code;
                   2388:
                   2389:   switch (fixp->fx_r_type)
                   2390:     {
                   2391:     case BFD_RELOC_NONE:
                   2392:     case BFD_RELOC_MICROBLAZE_64_NONE:
                   2393:     case BFD_RELOC_32:
                   2394:     case BFD_RELOC_MICROBLAZE_32_LO:
                   2395:     case BFD_RELOC_MICROBLAZE_32_LO_PCREL:
                   2396:     case BFD_RELOC_RVA:
                   2397:     case BFD_RELOC_64:
                   2398:     case BFD_RELOC_64_PCREL:
                   2399:     case BFD_RELOC_MICROBLAZE_32_ROSDA:
                   2400:     case BFD_RELOC_MICROBLAZE_32_RWSDA:
                   2401:     case BFD_RELOC_MICROBLAZE_32_SYM_OP_SYM:
                   2402:     case BFD_RELOC_MICROBLAZE_64_GOTPC:
                   2403:     case BFD_RELOC_MICROBLAZE_64_GOT:
                   2404:     case BFD_RELOC_MICROBLAZE_64_PLT:
                   2405:     case BFD_RELOC_MICROBLAZE_64_GOTOFF:
                   2406:     case BFD_RELOC_MICROBLAZE_32_GOTOFF:
1.3       christos 2407:     case BFD_RELOC_MICROBLAZE_64_TLSGD:
                   2408:     case BFD_RELOC_MICROBLAZE_64_TLSLD:
                   2409:     case BFD_RELOC_MICROBLAZE_32_TLSDTPMOD:
                   2410:     case BFD_RELOC_MICROBLAZE_32_TLSDTPREL:
                   2411:     case BFD_RELOC_MICROBLAZE_64_TLSDTPREL:
                   2412:     case BFD_RELOC_MICROBLAZE_64_TLSGOTTPREL:
                   2413:     case BFD_RELOC_MICROBLAZE_64_TLSTPREL:
1.1       christos 2414:       code = fixp->fx_r_type;
                   2415:       break;
                   2416:
                   2417:     default:
                   2418:       switch (F (fixp->fx_size, fixp->fx_pcrel))
                   2419:         {
                   2420:           MAP (1, 0, BFD_RELOC_8);
                   2421:           MAP (2, 0, BFD_RELOC_16);
                   2422:           MAP (4, 0, BFD_RELOC_32);
                   2423:           MAP (1, 1, BFD_RELOC_8_PCREL);
                   2424:           MAP (2, 1, BFD_RELOC_16_PCREL);
                   2425:           MAP (4, 1, BFD_RELOC_32_PCREL);
                   2426:         default:
                   2427:           code = fixp->fx_r_type;
                   2428:           as_bad (_("Can not do %d byte %srelocation"),
                   2429:                   fixp->fx_size,
                   2430:                   fixp->fx_pcrel ? _("pc-relative") : "");
                   2431:         }
                   2432:       break;
                   2433:     }
                   2434:
1.5     ! christos 2435:   rel = XNEW (arelent);
        !          2436:   rel->sym_ptr_ptr = XNEW (asymbol *);
1.1       christos 2437:
                   2438:   if (code == BFD_RELOC_MICROBLAZE_32_SYM_OP_SYM)
                   2439:     *rel->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_subsy);
                   2440:   else
                   2441:     *rel->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
                   2442:
                   2443:   rel->address = fixp->fx_frag->fr_address + fixp->fx_where;
                   2444:   /* Always pass the addend along!  */
                   2445:   rel->addend = fixp->fx_offset;
                   2446:   rel->howto = bfd_reloc_type_lookup (stdoutput, code);
                   2447:
                   2448:   if (rel->howto == NULL)
                   2449:     {
                   2450:       as_bad_where (fixp->fx_file, fixp->fx_line,
                   2451:                     _("Cannot represent relocation type %s"),
                   2452:                     bfd_get_reloc_code_name (code));
                   2453:
                   2454:       /* Set howto to a garbage value so that we can keep going.  */
                   2455:       rel->howto = bfd_reloc_type_lookup (stdoutput, BFD_RELOC_32);
                   2456:       gas_assert (rel->howto != NULL);
                   2457:     }
                   2458:   return rel;
                   2459: }
                   2460:
                   2461: int
1.5     ! christos 2462: md_parse_option (int c, const char * arg ATTRIBUTE_UNUSED)
1.1       christos 2463: {
                   2464:   switch (c)
                   2465:     {
1.3       christos 2466:     case OPTION_EB:
                   2467:       target_big_endian = 1;
                   2468:       break;
                   2469:     case OPTION_EL:
                   2470:       target_big_endian = 0;
                   2471:       break;
1.1       christos 2472:     default:
                   2473:       return 0;
                   2474:     }
                   2475:   return 1;
                   2476: }
                   2477:
                   2478: void
                   2479: md_show_usage (FILE * stream ATTRIBUTE_UNUSED)
                   2480: {
                   2481:   /*  fprintf(stream, _("\
                   2482:       MicroBlaze options:\n\
                   2483:       -noSmall         Data in the comm and data sections do not go into the small data section\n")); */
                   2484: }
                   2485:
                   2486:
                   2487: /* Create a fixup for a cons expression.  If parse_cons_expression_microblaze
                   2488:    found a machine specific op in an expression,
                   2489:    then we create relocs accordingly.  */
                   2490:
                   2491: void
                   2492: cons_fix_new_microblaze (fragS * frag,
                   2493:                         int where,
                   2494:                         int size,
1.3       christos 2495:                         expressionS *exp,
                   2496:                         bfd_reloc_code_real_type r)
1.1       christos 2497: {
                   2498:   if ((exp->X_op == O_subtract) && (exp->X_add_symbol) &&
                   2499:       (exp->X_op_symbol) && (now_seg != absolute_section) && (size == 4)
                   2500:       && (!S_IS_LOCAL (exp->X_op_symbol)))
                   2501:     r = BFD_RELOC_MICROBLAZE_32_SYM_OP_SYM;
                   2502:   else if (exp->X_md == IMM_GOTOFF && exp->X_op == O_symbol_rva)
                   2503:     {
                   2504:       exp->X_op = O_symbol;
                   2505:       r = BFD_RELOC_MICROBLAZE_32_GOTOFF;
                   2506:     }
                   2507:   else
                   2508:     {
                   2509:       switch (size)
                   2510:         {
                   2511:         case 1:
                   2512:           r = BFD_RELOC_8;
                   2513:           break;
                   2514:         case 2:
                   2515:           r = BFD_RELOC_16;
                   2516:           break;
                   2517:         case 4:
                   2518:           r = BFD_RELOC_32;
                   2519:           break;
                   2520:         case 8:
                   2521:           r = BFD_RELOC_64;
                   2522:           break;
                   2523:         default:
                   2524:           as_bad (_("unsupported BFD relocation size %u"), size);
                   2525:           r = BFD_RELOC_32;
                   2526:           break;
                   2527:         }
                   2528:     }
                   2529:   fix_new_exp (frag, where, size, exp, 0, r);
                   2530: }

CVSweb <webmaster@jp.NetBSD.org>