Home | History | Annotate | Line # | Download | only in config
tc-kvx.c revision 1.1.1.1.2.2
      1 /* tc-kvx.c -- Assemble for the KVX ISA
      2 
      3    Copyright (C) 2009-2024 Free Software Foundation, Inc.
      4    Contributed by Kalray SA.
      5 
      6    This file is part of GAS.
      7 
      8    GAS is free software; you can redistribute it and/or modify
      9    it under the terms of the GNU General Public License as published by
     10    the Free Software Foundation; either version 3 of the license, or
     11    (at your option) any later version.
     12 
     13    GAS is distributed in the hope that it will be useful,
     14    but WITHOUT ANY WARRANTY; without even the implied warranty of
     15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     16    GNU General Public License for more details.
     17 
     18    You should have received a copy of the GNU General Public License
     19    along with this program; see the file COPYING3. If not,
     20    see <http://www.gnu.org/licenses/>.  */
     21 
     22 #include "as.h"
     23 #include "obstack.h"
     24 #include "subsegs.h"
     25 #include "tc-kvx.h"
     26 #include "libiberty.h"
     27 
     28 #include <assert.h>
     29 #include <stdio.h>
     30 #include <stdint.h>
     31 #include <string.h>
     32 #include <ctype.h>
     33 
     34 #ifdef OBJ_ELF
     35 #include "elf/kvx.h"
     36 #include "dwarf2dbg.h"
     37 #include "dw2gencfi.h"
     38 #endif
     39 
     40 #define D(args...) do { if(debug) fprintf(args); } while(0)
     41 
     42 static void supported_cores (char buf[], size_t buflen);
     43 
     44 #define NELEMS(a) ((int) (sizeof (a)/sizeof ((a)[0])))
     45 
     46 #define STREQ(x,y) !strcmp(((x) ? (x) : ""), ((y) ? (y) : ""))
     47 #define STRNEQ(x,y,n) !strncmp(((x) ? (x) : ""), ((y) ? (y) : ""),(n))
     48 
     49 /* The PARALLEL_BIT is set to 0 when an instruction is the last of a bundle. */
     50 #define PARALLEL_BIT (1u << 31)
     51 
     52 /*TB begin*/
     53 int size_type_function = 1;
     54 /*TB end */
     55 
     56 struct kvx_as_env env = {
     57   .params = {
     58     .abi = ELF_KVX_ABI_UNDEF,
     59     .osabi = ELFOSABI_NONE,
     60     .core = -1,
     61     .core_set = 0,
     62     .abi_set = 0,
     63     .osabi_set = 0,
     64     .pic_flags = 0,
     65     .arch_size = 64
     66   },
     67   .opts = {
     68     .march = NULL,
     69     .check_resource_usage = 1,
     70     .generate_illegal_code = 0,
     71     .dump_table = 0,
     72     .dump_insn = 0,
     73     .diagnostics = 1,
     74     .more = 1,
     75     .allow_all_sfr = 0
     76   }
     77 };
     78 
     79 /* This string should contain position in string where error occured. */
     80 
     81 /* Default kvx_registers array. */
     82 const struct kvx_Register *kvx_registers = NULL;
     83 /* Default kvx_modifiers array. */
     84 const char ***kvx_modifiers = NULL;
     85 /* Default kvx_regfiles array. */
     86 const int *kvx_regfiles = NULL;
     87 /* Default values used if no assume directive is given */
     88 const struct kvx_core_info *kvx_core_info = NULL;
     89 
     90 /***********************************************/
     91 /*    Generic Globals for GAS                  */
     92 /***********************************************/
     93 
     94 const char comment_chars[]        = "#";
     95 const char line_comment_chars[]   = "#";
     96 const char line_separator_chars[] = ";";
     97 const char EXP_CHARS[]            = "eE";
     98 const char FLT_CHARS[]            = "dD";
     99 const int md_short_jump_size      = 0;
    100 const int md_long_jump_size       = 0;
    101 
    102 /***********************************************/
    103 /*           Local Types                       */
    104 /***********************************************/
    105 
    106 /* a fix up record                       */
    107 
    108 struct kvx_fixup
    109 {
    110   /* The expression used.  */
    111   expressionS exp;
    112   /* The place in the frag where this goes.  */
    113   int where;
    114   /* The relocation.  */
    115   bfd_reloc_code_real_type reloc;
    116 };
    117 
    118 /* a single assembled instruction record */
    119 /* may include immediate extension words  */
    120 struct kvxinsn
    121 {
    122   /* written out?  */
    123   int written;
    124   /* Opcode table entry for this insn */
    125   const struct kvxopc *opdef;
    126   /* length of instruction in words (1 or 2) */
    127   int len;
    128   /* insn is extended */
    129   int immx0;
    130   /* insn has two immx */
    131   int immx1;
    132   /* order to stabilize sort */
    133   int order;
    134   /* instruction words */
    135   uint32_t words[KVXMAXBUNDLEWORDS];
    136   /* the number of fixups [0,2] */
    137   int nfixups;
    138   /* the actual fixups */
    139   struct kvx_fixup fixup[2];
    140 };
    141 
    142 typedef void (*print_insn_t) (struct kvxopc * op);
    143 static print_insn_t print_insn = NULL;
    144 
    145 /* Set to TRUE when we assemble instructions.  */
    146 static bool assembling_insn = false;
    147 
    148 #define NOIMMX -1
    149 
    150 /* Was KVXMAXBUNDLEISSUE, changed because of NOPs */
    151 static struct kvxinsn insbuf[KVXMAXBUNDLEWORDS];
    152 static int insncnt = 0;
    153 static struct kvxinsn immxbuf[KVXMAXBUNDLEWORDS];
    154 static int immxcnt = 0;
    155 
    156 static void
    157 incr_immxcnt (void)
    158 {
    159   immxcnt++;
    160   if (immxcnt >= KVXMAXBUNDLEWORDS)
    161     as_bad ("Max immx number exceeded: %d", immxcnt);
    162 }
    163 
    164 static void set_byte_counter (asection * sec, int value);
    165 static void
    166 set_byte_counter (asection * sec, int value)
    167 {
    168   sec->target_index = value;
    169 }
    170 
    171 static int get_byte_counter (asection * sec);
    172 int
    173 get_byte_counter (asection * sec)
    174 {
    175   return sec->target_index;
    176 }
    177 
    178 const char *
    179 kvx_target_format (void)
    180 {
    181   return env.params.arch_size == 64 ? "elf64-kvx" : "elf32-kvx";
    182 }
    183 
    184 /****************************************************/
    185 /*  ASSEMBLER Pseudo-ops.  Some of this just        */
    186 /*  extends the default definitions                 */
    187 /*  others are KVX specific                          */
    188 /****************************************************/
    189 
    190 static void kvx_check_resources (int);
    191 static void kvx_proc (int start);
    192 static void kvx_endp (int start);
    193 static void kvx_type (int start);
    194 
    195 const pseudo_typeS md_pseudo_table[] = {
    196   /* override default 2-bytes */
    197   { "word",             cons,                  4 },
    198 
    199   /* KVX specific */
    200   { "dword",            cons,                  8 },
    201 
    202   /* Override align directives to have a boundary as argument (and not the
    203      power of two as in p2align) */
    204   { "align",            s_align_bytes,         0 },
    205 
    206   { "checkresources",   kvx_check_resources,   1 },
    207   { "nocheckresources", kvx_check_resources,   0 },
    208 
    209   { "proc",             kvx_proc,              1 },
    210   { "endp",             kvx_endp,              0 },
    211 
    212   { "type",             kvx_type,              0 },
    213 
    214 #ifdef OBJ_ELF
    215   { "file",             dwarf2_directive_file, 0 },
    216   { "loc",              dwarf2_directive_loc,  0 },
    217 #endif
    218   { NULL,               0,                     0 }
    219 };
    220 
    221 
    222 static int inside_bundle = 0;
    223 
    224 /* Stores the labels inside bundles (typically debug labels) that need
    225    to be postponed to the next bundle. */
    226 struct label_fix
    227 {
    228   struct label_fix *next;
    229   symbolS *sym;
    230 } *label_fixes = 0;
    231 
    232 /*****************************************************/
    233 /*   OPTIONS PROCESSING                              */
    234 /*****************************************************/
    235 
    236 const char *md_shortopts = "hV";	/* catted to std short options */
    237 
    238 /* added to std long options */
    239 
    240 #define OPTION_HEXFILE               (OPTION_MD_BASE + 0)
    241 #define OPTION_MARCH                 (OPTION_MD_BASE + 4)
    242 #define OPTION_CHECK_RESOURCES       (OPTION_MD_BASE + 5)
    243 #define OPTION_NO_CHECK_RESOURCES    (OPTION_MD_BASE + 6)
    244 #define OPTION_GENERATE_ILLEGAL_CODE (OPTION_MD_BASE + 7)
    245 #define OPTION_DUMP_TABLE            (OPTION_MD_BASE + 8)
    246 #define OPTION_PIC                   (OPTION_MD_BASE + 9)
    247 #define OPTION_BIGPIC                (OPTION_MD_BASE + 10)
    248 #define OPTION_NOPIC                 (OPTION_MD_BASE + 12)
    249 #define OPTION_32                    (OPTION_MD_BASE + 13)
    250 #define OPTION_DUMPINSN              (OPTION_MD_BASE + 15)
    251 #define OPTION_ALL_SFR               (OPTION_MD_BASE + 16)
    252 #define OPTION_DIAGNOSTICS           (OPTION_MD_BASE + 17)
    253 #define OPTION_NO_DIAGNOSTICS        (OPTION_MD_BASE + 18)
    254 #define OPTION_MORE                  (OPTION_MD_BASE + 19)
    255 #define OPTION_NO_MORE               (OPTION_MD_BASE + 20)
    256 
    257 struct option md_longopts[] = {
    258   { "march",                 required_argument, NULL, OPTION_MARCH                 },
    259   { "check-resources",       no_argument,       NULL, OPTION_CHECK_RESOURCES       },
    260   { "no-check-resources",    no_argument,       NULL, OPTION_NO_CHECK_RESOURCES    },
    261   { "generate-illegal-code", no_argument,       NULL, OPTION_GENERATE_ILLEGAL_CODE },
    262   { "dump-table",            no_argument,       NULL, OPTION_DUMP_TABLE            },
    263   { "mpic",                  no_argument,       NULL, OPTION_PIC                   },
    264   { "mPIC",                  no_argument,       NULL, OPTION_BIGPIC                },
    265   { "mnopic",                no_argument,       NULL, OPTION_NOPIC                 },
    266   { "m32",                   no_argument,       NULL, OPTION_32                    },
    267   { "dump-insn",             no_argument,       NULL, OPTION_DUMPINSN              },
    268   { "all-sfr",               no_argument,       NULL, OPTION_ALL_SFR               },
    269   { "diagnostics",           no_argument,       NULL, OPTION_DIAGNOSTICS           },
    270   { "no-diagnostics",        no_argument,       NULL, OPTION_NO_DIAGNOSTICS        },
    271   { "more",                  no_argument,       NULL, OPTION_MORE                  },
    272   { "no-more",               no_argument,       NULL, OPTION_NO_MORE               },
    273   { NULL,                    no_argument,       NULL, 0                            }
    274 };
    275 
    276 size_t md_longopts_size = sizeof (md_longopts);
    277 
    278 int
    279 md_parse_option (int c, const char *arg ATTRIBUTE_UNUSED)
    280 {
    281   int find_core = 0;
    282 
    283   switch (c)
    284     {
    285     case 'h':
    286       md_show_usage (stdout);
    287       exit (EXIT_SUCCESS);
    288       break;
    289 
    290       /* -V: SVR4 argument to print version ID.  */
    291     case 'V':
    292       print_version_id ();
    293       exit (EXIT_SUCCESS);
    294       break;
    295     case OPTION_MARCH:
    296       env.opts.march = strdup (arg);
    297       for (int i = 0; i < KVXNUMCORES && !find_core; ++i)
    298 	    if (!strcasecmp (env.opts.march, kvx_core_info_table[i]->name))
    299 	      {
    300 		kvx_core_info = kvx_core_info_table[i];
    301 		kvx_registers = kvx_registers_table[i];
    302 		kvx_modifiers = kvx_modifiers_table[i];
    303 		kvx_regfiles = kvx_regfiles_table[i];
    304 
    305 		find_core = 1;
    306 		break;
    307 	      }
    308       if (!find_core)
    309 	{
    310 	  char buf[100];
    311 	  supported_cores (buf, sizeof (buf));
    312 	  as_fatal ("Specified arch not supported [%s]", buf);
    313 	}
    314       break;
    315     case OPTION_CHECK_RESOURCES:
    316       env.opts.check_resource_usage = 1;
    317       break;
    318     case OPTION_NO_CHECK_RESOURCES:
    319       env.opts.check_resource_usage = 0;
    320       break;
    321     case OPTION_GENERATE_ILLEGAL_CODE:
    322       env.opts.generate_illegal_code = 1;
    323       break;
    324     case OPTION_DUMP_TABLE:
    325       env.opts.dump_table = 1;
    326       break;
    327     case OPTION_DUMPINSN:
    328       env.opts.dump_insn = 1;
    329       break;
    330     case OPTION_ALL_SFR:
    331       env.opts.allow_all_sfr = 1;
    332       break;
    333     case OPTION_DIAGNOSTICS:
    334       env.opts.diagnostics = 1;
    335       break;
    336     case OPTION_NO_DIAGNOSTICS:
    337       env.opts.diagnostics = 0;
    338       break;
    339     case OPTION_MORE:
    340       env.opts.more = 1;
    341       break;
    342     case OPTION_NO_MORE:
    343       env.opts.more = 0;
    344       break;
    345     case OPTION_PIC:
    346       /* fallthrough, for now the same on KVX */
    347     case OPTION_BIGPIC:
    348       env.params.pic_flags |= ELF_KVX_ABI_PIC_BIT;
    349       break;
    350     case OPTION_NOPIC:
    351       env.params.pic_flags &= ~(ELF_KVX_ABI_PIC_BIT);
    352       break;
    353     case OPTION_32:
    354       env.params.arch_size = 32;
    355       break;
    356 
    357     default:
    358       return 0;
    359     }
    360   return 1;
    361 }
    362 
    363 void
    364 md_show_usage (FILE * stream)
    365 {
    366   char buf[100];
    367   supported_cores (buf, sizeof (buf));
    368 
    369   fprintf (stream, "\n"
    370 "KVX specific options:\n\n"
    371 "  --check-resources\t Perform minimal resource checking\n"
    372 "  --march [%s]\t Select architecture\n"
    373 "  -V \t\t\t Print assembler version number\n\n"
    374 "  The options -M, --mri and -f are not supported in this assembler.\n", buf);
    375 }
    376 
    377 /**************************************************/
    378 /*              UTILITIES                         */
    379 /**************************************************/
    380 
    381 /*
    382  * Read a value from to the object file
    383  */
    384 
    385 static valueT md_chars_to_number (char *buf, int n);
    386 valueT
    387 md_chars_to_number (char *buf, int n)
    388 {
    389   valueT val = 0;
    390 
    391   if (n > (int) sizeof (val) || n <= 0)
    392     abort ();
    393 
    394   while (n--)
    395     {
    396       val <<= 8;
    397       val |= (buf[n] & 0xff);
    398     }
    399 
    400   return val;
    401 }
    402 
    403 /* Returns the corresponding pseudo function matching SYM and to be
    404    used for data section */
    405 static struct pseudo_func *
    406 kvx_get_pseudo_func_data_scn (symbolS * sym)
    407 {
    408   for (int i = 0; i < kvx_core_info->nb_pseudo_funcs; i++)
    409     if (sym == kvx_core_info->pseudo_funcs[i].sym
    410 	&& kvx_core_info->pseudo_funcs[i].pseudo_relocs.single != BFD_RELOC_UNUSED)
    411 	return &kvx_core_info->pseudo_funcs[i];
    412   return NULL;
    413 }
    414 
    415 /* Returns the corresponding pseudo function matching SYM and operand
    416    format OPND */
    417 static struct pseudo_func *
    418 kvx_get_pseudo_func2 (symbolS *sym, struct kvx_operand * opnd)
    419 {
    420   for (int i = 0; i < kvx_core_info->nb_pseudo_funcs; i++)
    421     if (sym == kvx_core_info->pseudo_funcs[i].sym)
    422       for (int relidx = 0; relidx < opnd->reloc_nb; relidx++)
    423 	if (opnd->relocs[relidx] == kvx_core_info->pseudo_funcs[i].pseudo_relocs.kreloc
    424 	    && (env.params.arch_size == (int) kvx_core_info->pseudo_funcs[i].pseudo_relocs.avail_modes
    425 	      || kvx_core_info->pseudo_funcs[i].pseudo_relocs.avail_modes == PSEUDO_ALL))
    426 	  return &kvx_core_info->pseudo_funcs[i];
    427 
    428   return NULL;
    429 }
    430 
    431 static void
    432 supported_cores (char buf[], size_t buflen)
    433 {
    434   buf[0] = '\0';
    435   for (int i = 0; i < KVXNUMCORES; i++)
    436     {
    437       if (buf[0] == '\0')
    438 	strcpy (buf, kvx_core_info_table[i]->name);
    439       else
    440 	if ((strlen (buf) + 1 + strlen (kvx_core_info_table[i]->name) + 1) < buflen)
    441 	  {
    442 	    strcat (buf, "|");
    443 	    strcat (buf, kvx_core_info_table[i]->name);
    444 	  }
    445     }
    446 }
    447 
    448 /***************************************************/
    449 /*   ASSEMBLE AN INSTRUCTION                       */
    450 /***************************************************/
    451 
    452 /*
    453  * Insert ARG into the operand described by OPDEF in instruction INSN
    454  * Returns 1 if the immediate extension (IMMX) has been
    455  * handled along with relocation, 0 if not.
    456  */
    457 static int
    458 insert_operand (struct kvxinsn *insn, struct kvx_operand *opdef,
    459 		struct token_list *tok)
    460 {
    461   uint64_t op = 0;
    462   struct kvx_bitfield *bfields = opdef->bfield;
    463   int bf_nb = opdef->bitfields;
    464   int immx_ready = 0;
    465 
    466   if (opdef->width == 0)
    467     return 0;
    468 
    469 #define add_fixup(insn_, reloc_, exp_) \
    470   do { \
    471     (insn_)->fixup[(insn_)->nfixups].reloc = (reloc_); \
    472     (insn_)->fixup[(insn_)->nfixups].exp = (exp_);     \
    473     (insn_)->fixup[(insn_)->nfixups].where = 0;        \
    474     (insn_)->nfixups++;                                \
    475   } while (0)
    476 
    477 #define add_immx(insn_, words_, reloc_, exp_, nfixups_, len_) \
    478   do { \
    479     immxbuf[immxcnt].words[0] = (words_);                \
    480     immxbuf[immxcnt].fixup[0].reloc = (reloc_);          \
    481     immxbuf[immxcnt].fixup[0].exp = (exp_);              \
    482     immxbuf[immxcnt].fixup[0].where = 0;                 \
    483     immxbuf[immxcnt].nfixups = (nfixups_);               \
    484     immxbuf[immxcnt].len = (len_);                       \
    485     /* decrement insn->len: immx part handled separately \
    486        from insn and must not be emited twice.  */       \
    487     (insn_)->len -= 1;                                   \
    488     incr_immxcnt ();                                     \
    489   } while (0)
    490 
    491 #define chk_imm(core_, imm_) \
    492   (env.params.core == ELF_KVX_CORE_## core_ && opdef->type == (imm_))
    493 
    494   /* try to resolve the value */
    495 
    496   switch (tok->category)
    497     {
    498     case CAT_REGISTER:
    499       op = S_GET_VALUE (str_hash_find (env.reg_hash, tok->tok));
    500       op -= opdef->bias;
    501       op >>= opdef->shift;
    502       break;
    503     case CAT_MODIFIER:
    504       op = tok->val;
    505       op -= opdef->bias;
    506       op >>= opdef->shift;
    507       break;
    508     case CAT_IMMEDIATE:
    509       {
    510 	char *ilp_save = input_line_pointer;
    511 	input_line_pointer = tok->tok;
    512 	expressionS exp = { 0 };
    513 	expression (&exp);
    514 	input_line_pointer = ilp_save;
    515 
    516 	/* We are dealing with a pseudo-function.  */
    517 	if (tok->tok[0] == '@')
    518 	  {
    519 	    if (insn->nfixups == 0)
    520 	      {
    521 		expressionS reloc_arg;
    522 		reloc_arg = exp;
    523 		reloc_arg.X_op = O_symbol;
    524 		struct pseudo_func *pf =
    525 		  kvx_get_pseudo_func2 (exp.X_op_symbol, opdef);
    526 		/* S64 uses LO10/UP27/EX27 format (3 words), with one reloc in each words (3) */
    527 		/* S43 uses LO10/EX6/UP27 format (2 words), with 2 relocs in main syllabes and 1 in extra word */
    528 		/* S37 uses LO10/UP27 format (2 words), with one reloc in each word (2) */
    529 
    530 		/* Beware that immxbuf must be filled in the same order as relocs should be emitted. */
    531 
    532 		if (pf->pseudo_relocs.reloc_type == S64_LO10_UP27_EX27
    533 		    || pf->pseudo_relocs.reloc_type == S43_LO10_UP27_EX6
    534 		    || pf->pseudo_relocs.reloc_type == S37_LO10_UP27)
    535 		  {
    536 		    add_fixup (insn, pf->pseudo_relocs.reloc_lo10, reloc_arg);
    537 
    538 		    insn->immx0 = immxcnt;
    539 		    add_immx (insn, 0, pf->pseudo_relocs.reloc_up27,
    540 			      reloc_arg, 1, 1);
    541 		    immx_ready = 1;
    542 		  }
    543 		else if (pf->pseudo_relocs.reloc_type == S32_LO5_UP27)
    544 		  {
    545 		    add_fixup (insn, pf->pseudo_relocs.reloc_lo5, reloc_arg);
    546 
    547 		    insn->immx0 = immxcnt;
    548 		    add_immx (insn, 0, pf->pseudo_relocs.reloc_up27,
    549 			      reloc_arg, 1, 1);
    550 		    immx_ready = 1;
    551 		  }
    552 		else if (pf->pseudo_relocs.reloc_type == S16)
    553 		  add_fixup (insn, pf->pseudo_relocs.single, reloc_arg);
    554 		else
    555 		  as_fatal ("Unexpected fixup");
    556 
    557 		if (pf->pseudo_relocs.reloc_type == S64_LO10_UP27_EX27)
    558 		  {
    559 		    insn->immx1 = immxcnt;
    560 		    add_immx (insn, 0, pf->pseudo_relocs.reloc_ex, reloc_arg,
    561 			      1, 1);
    562 		  }
    563 		else if (pf->pseudo_relocs.reloc_type == S43_LO10_UP27_EX6)
    564 		  add_fixup (insn, pf->pseudo_relocs.reloc_ex, reloc_arg);
    565 	      }
    566 	  }
    567 	else
    568 	  {
    569 	    if (exp.X_op == O_constant)
    570 	      {
    571 		/* This is a immediate: either a regular immediate, or an
    572 		   immediate that was saved in a variable through `.equ'.  */
    573 		uint64_t sval = (int64_t) tok->val;
    574 		op = opdef->flags & kvxSIGNED ? sval : tok->val;
    575 		op >>= opdef->shift;
    576 	      }
    577 	    else if (exp.X_op == O_subtract)
    578 	      as_fatal ("O_subtract not supported.");
    579 	    else
    580 	      {
    581 
    582 		/* This is a symbol which needs a relocation.  */
    583 		if (insn->nfixups == 0)
    584 		  {
    585 		    if (chk_imm (KV3_1, Immediate_kv3_v1_pcrel17)
    586 			|| chk_imm (KV3_2, Immediate_kv3_v2_pcrel17)
    587 			|| chk_imm (KV4_1, Immediate_kv4_v1_pcrel17))
    588 		      add_fixup (insn, BFD_RELOC_KVX_PCREL17, exp);
    589 		    else if (chk_imm (KV3_1, Immediate_kv3_v1_pcrel27)
    590 			     || chk_imm (KV3_2, Immediate_kv3_v2_pcrel27)
    591 			     || chk_imm (KV4_1, Immediate_kv4_v1_pcrel27))
    592 		      add_fixup (insn, BFD_RELOC_KVX_PCREL27, exp);
    593 		    else if (chk_imm (KV3_1, Immediate_kv3_v1_wrapped32)
    594 			     || chk_imm (KV3_2, Immediate_kv3_v2_wrapped32)
    595 			     || chk_imm (KV4_1, Immediate_kv4_v1_wrapped32))
    596 		      {
    597 			add_fixup (insn, BFD_RELOC_KVX_S32_LO5, exp);
    598 
    599 			insn->immx0 = immxcnt;
    600 			add_immx (insn, 0, BFD_RELOC_KVX_S32_UP27, exp, 1, 1);
    601 
    602 			immx_ready = 1;
    603 		      }
    604 		    else if (chk_imm (KV3_1, Immediate_kv3_v1_signed10)
    605 			     || chk_imm (KV3_2, Immediate_kv3_v2_signed10)
    606 			     || chk_imm (KV4_1, Immediate_kv4_v1_signed10))
    607 		      add_fixup (insn, BFD_RELOC_KVX_S37_LO10, exp);
    608 		    else if (chk_imm (KV3_1, Immediate_kv3_v1_signed37)
    609 			     || chk_imm (KV3_2, Immediate_kv3_v2_signed37)
    610 			     || chk_imm (KV4_1, Immediate_kv4_v1_signed37))
    611 		      {
    612 			add_fixup (insn, BFD_RELOC_KVX_S37_LO10, exp);
    613 
    614 			insn->immx0 = immxcnt;
    615 			add_immx (insn, 0, BFD_RELOC_KVX_S37_UP27, exp, 1, 1);
    616 
    617 			immx_ready = 1;
    618 		      }
    619 		    else if (chk_imm (KV3_1, Immediate_kv3_v1_signed43)
    620 			     || chk_imm (KV3_2, Immediate_kv3_v2_signed43)
    621 			     || chk_imm (KV4_1, Immediate_kv4_v1_signed43))
    622 		      {
    623 			add_fixup (insn, BFD_RELOC_KVX_S43_LO10, exp);
    624 			add_fixup (insn, BFD_RELOC_KVX_S43_EX6, exp);
    625 
    626 			insn->immx0 = immxcnt;
    627 			add_immx (insn, insn->words[1],
    628 				  BFD_RELOC_KVX_S43_UP27, exp, 1, 1);
    629 
    630 			immx_ready = 1;
    631 		      }
    632 		    else if (chk_imm (KV3_1, Immediate_kv3_v1_wrapped64)
    633 			     || chk_imm (KV3_2, Immediate_kv3_v2_wrapped64)
    634 			     || chk_imm (KV4_1, Immediate_kv4_v1_wrapped64))
    635 		      {
    636 			add_fixup (insn, BFD_RELOC_KVX_S64_LO10, exp);
    637 
    638 			insn->immx0 = immxcnt;
    639 			add_immx (insn, insn->words[1],
    640 				  BFD_RELOC_KVX_S64_UP27, exp, 1, 1);
    641 
    642 			insn->immx1 = immxcnt;
    643 			add_immx (insn, insn->words[2],
    644 				  BFD_RELOC_KVX_S64_EX27, exp, 1, 1);
    645 
    646 			immx_ready = 1;
    647 		      }
    648 		    else
    649 		      as_fatal ("don't know how to generate a fixup record");
    650 		    return immx_ready;
    651 		  }
    652 		else
    653 		  as_fatal ("No room for fixup ");
    654 	      }
    655 	  }
    656       }
    657       break;
    658     default:
    659       break;
    660     }
    661 
    662   for (int bf_idx = 0; bf_idx < bf_nb; bf_idx++)
    663     {
    664       uint64_t value =
    665 	((uint64_t) op >> bfields[bf_idx].from_offset);
    666       int j = 0;
    667       int to_offset = bfields[bf_idx].to_offset;
    668       value &= (1LL << bfields[bf_idx].size) - 1;
    669       j = to_offset / 32;
    670       to_offset = to_offset % 32;
    671       insn->words[j] |= (value << to_offset) & 0xffffffff;
    672     }
    673 
    674   return immx_ready;
    675 
    676 #undef chk_imm
    677 #undef add_immx
    678 #undef add_fixup
    679 }
    680 
    681 /*
    682  * Given a set of operands and a matching instruction,
    683  * assemble it
    684  *
    685  */
    686 static void
    687 assemble_insn (const struct kvxopc * opcode, struct token_list *tok, struct kvxinsn *insn)
    688 {
    689   unsigned immx_ready = 0;
    690 
    691   memset (insn, 0, sizeof (*insn));
    692   insn->opdef = opcode;
    693   for (int i = 0; i < opcode->wordcount; i++)
    694     {
    695       insn->words[i] = opcode->codewords[i].opcode;
    696       insn->len += 1;
    697     }
    698 
    699   insn->immx0 = NOIMMX;
    700   insn->immx1 = NOIMMX;
    701 
    702   struct token_list *tok_ = tok;
    703   struct kvx_operand **format = (struct kvx_operand **) opcode->format;
    704 
    705   while (tok_)
    706     {
    707       int ret = insert_operand (insn, *format, tok_);
    708       immx_ready |= ret;
    709       while ((tok_ = tok_->next) && tok_->category == CAT_SEPARATOR);
    710       format++;
    711     }
    712 
    713   // Handle immx if insert_operand did not already take care of that
    714   if (!immx_ready)
    715     {
    716       for (int i = 0; i < opcode->wordcount; i++)
    717 	{
    718 	  if (opcode->codewords[i].flags & kvxOPCODE_FLAG_IMMX0)
    719 	    {
    720 	      insn->immx0 = immxcnt;
    721 	      immxbuf[immxcnt].words[0] = insn->words[i];
    722 	      immxbuf[immxcnt].nfixups = 0;
    723 	      immxbuf[immxcnt].len = 1;
    724 	      insn->len -= 1;
    725 	      incr_immxcnt ();
    726 	    }
    727 	  if (opcode->codewords[i].flags & kvxOPCODE_FLAG_IMMX1)
    728 	    {
    729 	      insn->immx1 = immxcnt;
    730 	      immxbuf[immxcnt].words[0] = insn->words[i];
    731 	      immxbuf[immxcnt].nfixups = 0;
    732 	      immxbuf[immxcnt].len = 1;
    733 	      insn->len -= 1;
    734 	      incr_immxcnt ();
    735 	    }
    736 	}
    737     }
    738 }
    739 
    740 /* Emit an instruction from the instruction array into the object
    741  * file. INSN points to an element of the instruction array. STOPFLAG
    742  * is true if this is the last instruction in the bundle.
    743  *
    744  * Only handles main syllables of bundle. Immediate extensions are
    745  * handled by insert_operand.
    746  */
    747 static void
    748 emit_insn (struct kvxinsn * insn, int insn_pos, int stopflag)
    749 {
    750   char *f;
    751   unsigned int image;
    752 
    753   /* if we are listing, attach frag to previous line.  */
    754   if (listing)
    755     listing_prev_line ();
    756 
    757   /* Update text size for lane parity checking.  */
    758   set_byte_counter (now_seg, (get_byte_counter (now_seg) + (insn->len * 4)));
    759 
    760   /* allocate space in the fragment.  */
    761   f = frag_more (insn->len * 4);
    762 
    763   /* spit out bits.  */
    764   for (int i = 0; i < insn->len; i++)
    765     {
    766       image = insn->words[i];
    767 
    768       /* Handle bundle parallel bit. */ ;
    769       if ((i == insn->len - 1) && stopflag)
    770 	image &= ~PARALLEL_BIT;
    771       else
    772 	image |= PARALLEL_BIT;
    773 
    774       /* Emit the instruction image. */
    775       md_number_to_chars (f + (i * 4), image, 4);
    776     }
    777 
    778   /* generate fixup records */
    779 
    780   for (int i = 0; i < insn->nfixups; i++)
    781     {
    782       int size, pcrel;
    783       reloc_howto_type *reloc_howto =
    784 	bfd_reloc_type_lookup (stdoutput, insn->fixup[i].reloc);
    785       assert (reloc_howto);
    786       size = bfd_get_reloc_size (reloc_howto);
    787       pcrel = reloc_howto->pc_relative;
    788 
    789       /* In case the PCREL relocation is not for the first insn in the
    790          bundle, we have to offset it.  The pc used by the hardware
    791          references a bundle and not separate insn.
    792        */
    793       assert (!(insn_pos == -1 && pcrel));
    794       if (pcrel && insn_pos > 0)
    795 	insn->fixup[i].exp.X_add_number += insn_pos * 4;
    796 
    797       fixS *fixup = fix_new_exp (frag_now,
    798 				 f - frag_now->fr_literal +
    799 				 insn->fixup[i].where,
    800 				 size,
    801 				 &(insn->fixup[i].exp),
    802 				 pcrel,
    803 				 insn->fixup[i].reloc);
    804       /*
    805        * Set this bit so that large value can still be
    806        * handled. Without it, assembler will fail in fixup_segment
    807        * when it checks there is enough bits to store the value. As we
    808        * usually split our reloc across different words, it may think
    809        * that 4 bytes are not enough for large value. This simply
    810        * skips the tests
    811        */
    812       fixup->fx_no_overflow = 1;
    813     }
    814 }
    815 
    816 
    817 /* Called for any expression that can not be recognized.  When the
    818  * function is called, `input_line_pointer' will point to the start of
    819  * the expression.  */
    820 /* FIXME: Should be done by the parser */
    821 void
    822 md_operand (expressionS * e)
    823 {
    824   /* enum pseudo_type pseudo_type; */
    825   /* char *name = NULL; */
    826   size_t len;
    827   int ch, i;
    828 
    829   switch (*input_line_pointer)
    830     {
    831     case '@':
    832       /* Find what relocation pseudo-function we're dealing with. */
    833       /* pseudo_type = 0; */
    834       ch = *++input_line_pointer;
    835       for (i = 0; i < kvx_core_info->nb_pseudo_funcs; ++i)
    836 	if (kvx_core_info->pseudo_funcs[i].name && kvx_core_info->pseudo_funcs[i].name[0] == ch)
    837 	  {
    838 	    len = strlen (kvx_core_info->pseudo_funcs[i].name);
    839 	    if (strncmp (kvx_core_info->pseudo_funcs[i].name + 1,
    840 			 input_line_pointer + 1, len - 1) == 0
    841 		&& !is_part_of_name (input_line_pointer[len]))
    842 	      {
    843 		input_line_pointer += len;
    844 		break;
    845 	      }
    846 	  }
    847       SKIP_WHITESPACE ();
    848       if (*input_line_pointer != '(')
    849 	{
    850 	  as_bad ("Expected '('");
    851 	  goto err;
    852 	}
    853       /* Skip '('.  */
    854       ++input_line_pointer;
    855       if (!kvx_core_info->pseudo_funcs[i].pseudo_relocs.has_no_arg)
    856 	expression (e);
    857       if (*input_line_pointer++ != ')')
    858 	{
    859 	  as_bad ("Missing ')'");
    860 	  goto err;
    861 	}
    862       if (!kvx_core_info->pseudo_funcs[i].pseudo_relocs.has_no_arg)
    863 	{
    864 	  if (e->X_op != O_symbol)
    865 	    as_fatal ("Illegal combination of relocation functions");
    866 	}
    867       /* Make sure gas doesn't get rid of local symbols that are used
    868          in relocs.  */
    869       e->X_op = O_pseudo_fixup;
    870       e->X_op_symbol = kvx_core_info->pseudo_funcs[i].sym;
    871       break;
    872 
    873     default:
    874       break;
    875     }
    876   return;
    877 
    878 err:
    879   ignore_rest_of_line ();
    880 }
    881 
    882 /*
    883  * Return the Bundling type for an insn.
    884  */
    885 static int
    886 find_bundling (const struct kvxinsn * insn)
    887 {
    888   return insn->opdef->bundling;
    889 }
    890 
    891 static int
    892 find_reservation (const struct kvxinsn * insn)
    893 {
    894   return insn->opdef->reservation;
    895 }
    896 
    897 static struct kvxopc *
    898 assemble_tokens (struct token_list *tok_list)
    899 {
    900   assert (tok_list != NULL);
    901   struct token_list *toks = tok_list;
    902 
    903   /* make sure there is room in instruction buffer */
    904   /* Was KVXMAXBUNDLEISSUE, changed because of NOPs */
    905   if (insncnt >= KVXMAXBUNDLEWORDS)
    906     as_fatal ("[assemble_tokens]: too many instructions in bundle.");
    907 
    908   /* TODO: Merge */
    909   struct kvxinsn *insn;
    910   insn = insbuf + insncnt;
    911 
    912   /* The formats table registers the modifier into the opcode, therefore we need
    913      to fuse both before looking up the opcodes hashtable.  */
    914   char *opcode = NULL;
    915 
    916   opcode = toks->tok;
    917   toks = toks->next;
    918 
    919   while (toks && toks->category == CAT_SEPARATOR)
    920     toks = toks->next;
    921 
    922   /* Find the format requested by the instruction.  */
    923   struct kvxopc *format_tbl = str_hash_find (env.opcode_hash, opcode);
    924   struct kvxopc *format = NULL;
    925 
    926   struct token_list *toks_ = toks;
    927 
    928   while (!format && format_tbl && STREQ (opcode, format_tbl->as_op))
    929   {
    930     for (int i = 0 ; toks_ && format_tbl->format[i]
    931 	&& toks_->class_id == format_tbl->format[i]->type ;)
    932       {
    933 	toks_ = toks_->next;
    934 	while (toks_ && toks_->category == CAT_SEPARATOR)
    935 	  toks_ = toks_->next;
    936 	i += 1;
    937       }
    938 
    939     if (!toks_)
    940       format = format_tbl;
    941     else
    942       {
    943 	toks_ = toks;
    944 	format_tbl++;
    945       }
    946   }
    947 
    948   assert (format != NULL);
    949 
    950   assemble_insn (format, toks, insn);
    951   insncnt++;
    952 
    953   return NULL;
    954 }
    955 
    956 /*
    957  * Write in buf at most buf_size.
    958  * Returns the number of writen characters.
    959  */
    960 static int ATTRIBUTE_UNUSED
    961 insn_syntax (struct kvxopc * op, char *buf, int buf_size)
    962 {
    963   int chars = snprintf (buf, buf_size, "%s ", op->as_op);
    964   const char *fmtp = op->fmtstring;
    965   char ch = 0;
    966 
    967   for (int i = 0; op->format[i]; i++)
    968     {
    969       int type = op->format[i]->type;
    970       const char *type_name = TOKEN_NAME (type);
    971       int offset = 0;
    972 
    973       for (int j = 0 ; type_name[j] ; ++j)
    974 	if (type_name[j] == '_')
    975 	  offset = j + 1;
    976 
    977       /* Print characters in the format string up to the following * % or nul. */
    978       while ((chars < buf_size) && (ch = *fmtp) && ch != '%')
    979 	{
    980 	  buf[chars++] = ch;
    981 	  fmtp++;
    982 	}
    983 
    984       /* Skip past %s */
    985       if (ch == '%')
    986 	{
    987 	  ch = *fmtp++;
    988 	  fmtp++;
    989 	}
    990 
    991       chars += snprintf (&buf[chars], buf_size - chars, "%s", type_name + offset);
    992     }
    993 
    994   /* Print trailing characters in the format string, if any */
    995   while ((chars < buf_size) && (ch = *fmtp))
    996     {
    997       buf[chars++] = ch;
    998       fmtp++;
    999     }
   1000 
   1001   if (chars < buf_size)
   1002     buf[chars++] = '\0';
   1003   else
   1004     buf[buf_size - 1] = '\0';
   1005 
   1006   return chars;
   1007 }
   1008 
   1009 #define ASM_CHARS_MAX (71)
   1010 
   1011 static void
   1012 kvx_print_insn (struct kvxopc * op ATTRIBUTE_UNUSED)
   1013 {
   1014   char asm_str[ASM_CHARS_MAX];
   1015   int chars = insn_syntax (op, asm_str, ASM_CHARS_MAX);
   1016   const char *insn_type = "UNKNOWN";
   1017   const char *insn_mode = "";
   1018 
   1019   for (int i = chars - 1; i < ASM_CHARS_MAX - 1; i++)
   1020     asm_str[i] = '-';
   1021 
   1022   /* This is a hack which works because the Bundling is the same for all cores
   1023      for now.  */
   1024   switch ((int) op->bundling)
   1025     {
   1026     case Bundling_kv3_v1_ALL:
   1027       insn_type = "ALL  ";
   1028       break;
   1029     case Bundling_kv3_v1_BCU:
   1030       insn_type = "BCU  ";
   1031       break;
   1032     case Bundling_kv3_v1_TCA:
   1033       insn_type = "TCA  ";
   1034       break;
   1035     case Bundling_kv3_v1_FULL:
   1036     case Bundling_kv3_v1_FULL_X:
   1037     case Bundling_kv3_v1_FULL_Y:
   1038       insn_type = "FULL ";
   1039       break;
   1040     case Bundling_kv3_v1_LITE:
   1041     case Bundling_kv3_v1_LITE_X:
   1042     case Bundling_kv3_v1_LITE_Y:
   1043       insn_type = "LITE ";
   1044       break;
   1045     case Bundling_kv3_v1_TINY:
   1046     case Bundling_kv3_v1_TINY_X:
   1047     case Bundling_kv3_v1_TINY_Y:
   1048       insn_type = "TINY ";
   1049       break;
   1050     case Bundling_kv3_v1_MAU:
   1051     case Bundling_kv3_v1_MAU_X:
   1052     case Bundling_kv3_v1_MAU_Y:
   1053       insn_type = "MAU  ";
   1054       break;
   1055     case Bundling_kv3_v1_LSU:
   1056     case Bundling_kv3_v1_LSU_X:
   1057     case Bundling_kv3_v1_LSU_Y:
   1058       insn_type = "LSU  ";
   1059       break;
   1060     case Bundling_kv3_v1_NOP:
   1061       insn_type = "NOP  ";
   1062       break;
   1063     default:
   1064       as_fatal ("Unhandled Bundling class %d", op->bundling);
   1065     }
   1066 
   1067   if (op->codewords[0].flags & kvxOPCODE_FLAG_MODE64
   1068       && op->codewords[0].flags & kvxOPCODE_FLAG_MODE32)
   1069     insn_mode = "32 and 64";
   1070   else if (op->codewords[0].flags & kvxOPCODE_FLAG_MODE64)
   1071     insn_mode = "64";
   1072   else if (op->codewords[0].flags & kvxOPCODE_FLAG_MODE32)
   1073     insn_mode = "32";
   1074   else
   1075     as_fatal ("Unknown instruction mode.");
   1076 
   1077   printf ("%s | syllables: %d | type: %s | mode: %s bits\n", asm_str,
   1078 	  op->wordcount, insn_type, insn_mode);
   1079 }
   1080 
   1081 /* Comparison function compatible with qsort.  This is used to sort the issues
   1082    into the right order.  */
   1083 static int
   1084 kvxinsn_compare (const void *a, const void *b)
   1085 {
   1086   struct kvxinsn *kvxinsn_a = *(struct kvxinsn **) a;
   1087   struct kvxinsn *kvxinsn_b = *(struct kvxinsn **) b;
   1088   int bundling_a = find_bundling (kvxinsn_a);
   1089   int bundling_b = find_bundling (kvxinsn_b);
   1090   int order_a = kvxinsn_a->order;
   1091   int order_b = kvxinsn_b->order;
   1092   if (bundling_a != bundling_b)
   1093     return (bundling_b < bundling_a) - (bundling_a < bundling_b);
   1094   return (order_b < order_a) - (order_a < order_b);
   1095 }
   1096 
   1097 static void
   1098 kvx_reorder_bundle (struct kvxinsn *bundle_insn[], int bundle_insncnt)
   1099 {
   1100   enum
   1101   { EXU_BCU, EXU_TCA, EXU_ALU0, EXU_ALU1, EXU_MAU, EXU_LSU, EXU__ };
   1102   struct kvxinsn *issued[EXU__];
   1103   int tag, exu;
   1104 
   1105   memset (issued, 0, sizeof (issued));
   1106   for (int i = 0; i < bundle_insncnt; i++)
   1107     {
   1108       struct kvxinsn *kvxinsn = bundle_insn[i];
   1109       tag = -1, exu = -1;
   1110       /* This is a hack. It works because all the Bundling are the same for all
   1111          cores for now.  */
   1112       switch ((int) find_bundling (kvxinsn))
   1113 	{
   1114 	case Bundling_kv3_v1_ALL:
   1115 	  if (bundle_insncnt > 1)
   1116 	    as_fatal ("Too many ops in a single op bundle");
   1117 	  issued[0] = kvxinsn;
   1118 	  break;
   1119 	case Bundling_kv3_v1_BCU:
   1120 	  if (!issued[EXU_BCU])
   1121 	    issued[EXU_BCU] = kvxinsn;
   1122 	  else
   1123 	    as_fatal ("More than one BCU instruction in bundle");
   1124 	  break;
   1125 	case Bundling_kv3_v1_TCA:
   1126 	  if (!issued[EXU_TCA])
   1127 	    issued[EXU_TCA] = kvxinsn;
   1128 	  else
   1129 	    as_fatal ("More than one TCA instruction in bundle");
   1130 	  break;
   1131 	case Bundling_kv3_v1_FULL:
   1132 	case Bundling_kv3_v1_FULL_X:
   1133 	case Bundling_kv3_v1_FULL_Y:
   1134 	  if (!issued[EXU_ALU0])
   1135 	    {
   1136 	      issued[EXU_ALU0] = kvxinsn;
   1137 	      tag = Modifier_kv3_v1_exunum_ALU0;
   1138 	      exu = EXU_ALU0;
   1139 	    }
   1140 	  else
   1141 	    as_fatal ("More than one ALU FULL instruction in bundle");
   1142 	  break;
   1143 	case Bundling_kv3_v1_LITE:
   1144 	case Bundling_kv3_v1_LITE_X:
   1145 	case Bundling_kv3_v1_LITE_Y:
   1146 	  if (!issued[EXU_ALU0])
   1147 	    {
   1148 	      issued[EXU_ALU0] = kvxinsn;
   1149 	      tag = Modifier_kv3_v1_exunum_ALU0;
   1150 	      exu = EXU_ALU0;
   1151 	    }
   1152 	  else if (!issued[EXU_ALU1])
   1153 	    {
   1154 	      issued[EXU_ALU1] = kvxinsn;
   1155 	      tag = Modifier_kv3_v1_exunum_ALU1;
   1156 	      exu = EXU_ALU1;
   1157 	    }
   1158 	  else
   1159 	    as_fatal ("Too many ALU FULL or LITE instructions in bundle");
   1160 	  break;
   1161 	case Bundling_kv3_v1_MAU:
   1162 	case Bundling_kv3_v1_MAU_X:
   1163 	case Bundling_kv3_v1_MAU_Y:
   1164 	  if (!issued[EXU_MAU])
   1165 	    {
   1166 	      issued[EXU_MAU] = kvxinsn;
   1167 	      tag = Modifier_kv3_v1_exunum_MAU;
   1168 	      exu = EXU_MAU;
   1169 	    }
   1170 	  else
   1171 	    as_fatal ("More than one MAU instruction in bundle");
   1172 	  break;
   1173 	case Bundling_kv3_v1_LSU:
   1174 	case Bundling_kv3_v1_LSU_X:
   1175 	case Bundling_kv3_v1_LSU_Y:
   1176 	  if (!issued[EXU_LSU])
   1177 	    {
   1178 	      issued[EXU_LSU] = kvxinsn;
   1179 	      tag = Modifier_kv3_v1_exunum_LSU;
   1180 	      exu = EXU_LSU;
   1181 	    }
   1182 	  else
   1183 	    as_fatal ("More than one LSU instruction in bundle");
   1184 	  break;
   1185 	case Bundling_kv3_v1_TINY:
   1186 	case Bundling_kv3_v1_TINY_X:
   1187 	case Bundling_kv3_v1_TINY_Y:
   1188 	case Bundling_kv3_v1_NOP:
   1189 	  if (!issued[EXU_ALU0])
   1190 	    {
   1191 	      issued[EXU_ALU0] = kvxinsn;
   1192 	      tag = Modifier_kv3_v1_exunum_ALU0;
   1193 	      exu = EXU_ALU0;
   1194 	    }
   1195 	  else if (!issued[EXU_ALU1])
   1196 	    {
   1197 	      issued[EXU_ALU1] = kvxinsn;
   1198 	      tag = Modifier_kv3_v1_exunum_ALU1;
   1199 	      exu = EXU_ALU1;
   1200 	    }
   1201 	  else if (!issued[EXU_MAU])
   1202 	    {
   1203 	      issued[EXU_MAU] = kvxinsn;
   1204 	      tag = Modifier_kv3_v1_exunum_MAU;
   1205 	      exu = EXU_MAU;
   1206 	    }
   1207 	  else if (!issued[EXU_LSU])
   1208 	    {
   1209 	      issued[EXU_LSU] = kvxinsn;
   1210 	      tag = Modifier_kv3_v1_exunum_LSU;
   1211 	      exu = EXU_LSU;
   1212 	    }
   1213 	  else
   1214 	    as_fatal ("Too many ALU instructions in bundle");
   1215 	  break;
   1216 	default:
   1217 	  as_fatal ("Unhandled Bundling class %d", find_bundling (kvxinsn));
   1218 	}
   1219       if (tag >= 0)
   1220 	{
   1221 	  if (issued[exu]->immx0 != NOIMMX)
   1222 	    immxbuf[issued[exu]->immx0].words[0] |= (tag << 27);
   1223 	  if (issued[exu]->immx1 != NOIMMX)
   1224 	    immxbuf[issued[exu]->immx1].words[0] |= (tag << 27);
   1225 	}
   1226     }
   1227 
   1228   int i;
   1229   for (i = 0, exu = 0; exu < EXU__; exu++)
   1230     {
   1231       if (issued[exu])
   1232 	bundle_insn[i++] = issued[exu];
   1233     }
   1234   if (i != bundle_insncnt)
   1235     as_fatal ("Mismatch between bundle and issued instructions");
   1236 }
   1237 
   1238 static void
   1239 kvx_check_resource_usage (struct kvxinsn **bundle_insn, int bundle_insncnt)
   1240 {
   1241   const int reservation_table_len =
   1242     (kvx_core_info->reservation_table_lines * kvx_core_info->resource_max);
   1243   const int *resources = kvx_core_info->resources;
   1244   int *resources_used =
   1245     malloc (reservation_table_len * sizeof (int));
   1246   memset (resources_used, 0, reservation_table_len * sizeof (int));
   1247 
   1248   for (int i = 0; i < bundle_insncnt; i++)
   1249   {
   1250     int insn_reservation = find_reservation (bundle_insn[i]);
   1251     int reservation = insn_reservation & 0xff;
   1252     const int *reservation_table = kvx_core_info->reservation_table_table[reservation];
   1253     for (int j = 0; j < reservation_table_len; j++)
   1254       resources_used[j] += reservation_table[j];
   1255   }
   1256 
   1257   for (int i = 0; i < kvx_core_info->reservation_table_lines; i++)
   1258     {
   1259       for (int j = 0; j < kvx_core_info->resource_max; j++)
   1260 	if (resources_used[(i * kvx_core_info->resource_max) + j] > resources[j])
   1261 	  {
   1262 	    int v = resources_used[(i * kvx_core_info->resource_max) + j];
   1263 	    free (resources_used);
   1264 	    as_fatal ("Resource %s over-used in bundle: %d used, %d available",
   1265 		kvx_core_info->resource_names[j], v, resources[j]);
   1266 	  }
   1267   }
   1268   free (resources_used);
   1269 }
   1270 
   1271 /*
   1272  * Called by core to assemble a single line
   1273  */
   1274 void
   1275 md_assemble (char *line)
   1276 {
   1277   char *line_cursor = line;
   1278 
   1279   if (get_byte_counter (now_seg) & 3)
   1280     as_fatal ("code segment not word aligned in md_assemble");
   1281 
   1282   while (line_cursor && line_cursor[0] && (line_cursor[0] == ' '))
   1283     line_cursor++;
   1284 
   1285   /* ;; was converted to "be" by line hook          */
   1286   /* here we look for the bundle end                */
   1287   /* and actually output any instructions in bundle */
   1288   /* also we need to implement the stop bit         */
   1289   /* check for bundle end */
   1290   if (strncmp (line_cursor, "be", 2) == 0)
   1291   {
   1292     inside_bundle = 0;
   1293     //int sec_align = bfd_get_section_alignment(stdoutput, now_seg);
   1294     /* Was KVXMAXBUNDLEISSUE, changed because of NOPs */
   1295     struct kvxinsn *bundle_insn[KVXMAXBUNDLEWORDS];
   1296     int bundle_insncnt = 0;
   1297     int syllables = 0;
   1298     int entry;
   1299 
   1300 #ifdef OBJ_ELF
   1301     /* Emit Dwarf debug line information */
   1302     dwarf2_emit_insn (0);
   1303 #endif
   1304     for (int j = 0; j < insncnt; j++)
   1305     {
   1306       insbuf[j].order = j;
   1307       bundle_insn[bundle_insncnt++] = &insbuf[j];
   1308       syllables += insbuf[j].len;
   1309     }
   1310 
   1311     if (syllables + immxcnt > KVXMAXBUNDLEWORDS)
   1312       as_fatal ("Bundle has too many syllables : %d instead of %d",
   1313 	  syllables + immxcnt, KVXMAXBUNDLEWORDS);
   1314 
   1315     if (env.opts.check_resource_usage)
   1316       kvx_check_resource_usage (bundle_insn, bundle_insncnt);
   1317 
   1318     /* Reorder and check the bundle.  */
   1319     if (!env.opts.generate_illegal_code)
   1320     {
   1321       /* Sort the bundle_insn in order of bundling. */
   1322       qsort (bundle_insn, bundle_insncnt, sizeof (struct kvxinsn *), kvxinsn_compare);
   1323 
   1324       kvx_reorder_bundle (bundle_insn, bundle_insncnt);
   1325     }
   1326 
   1327     /* The ordering of the insns has been set correctly in bundle_insn. */
   1328     for (int i = 0; i < bundle_insncnt; i++)
   1329     {
   1330       emit_insn (bundle_insn[i], i, (i == bundle_insncnt + immxcnt - 1));
   1331       bundle_insn[i]->written = 1;
   1332     }
   1333 
   1334     // Emit immx, ordering them by EXU tags, 0 to 3
   1335     entry = 0;
   1336     for (int tag = 0; tag < 4; tag++)
   1337     {
   1338       for (int j = 0; j < immxcnt; j++)
   1339       {
   1340 #define kv3_exunum2_fld(x) (int)(((unsigned int)(x) >> 27) & 0x3)
   1341 	if (kv3_exunum2_fld (immxbuf[j].words[0]) == tag)
   1342 	{
   1343 	  assert (immxbuf[j].written == 0);
   1344 	  int insn_pos = bundle_insncnt + entry;
   1345 	  emit_insn (&(immxbuf[j]), insn_pos, entry == immxcnt - 1);
   1346 	  immxbuf[j].written = 1;
   1347 	  entry++;
   1348 	}
   1349 #undef kv3_exunum2_fld
   1350       }
   1351     }
   1352     if (entry != immxcnt)
   1353       as_fatal ("%d IMMX produced, only %d emitted.", immxcnt, entry);
   1354 
   1355     /* The debug label that appear in the middle of bundles
   1356        had better appear to be attached to the next
   1357        bundle. This is because usually these labels point to
   1358        the first instruction where some condition is met. If
   1359        the label isn't handled this way it will be attached to
   1360        the current bundle which is wrong as the corresponding
   1361        instruction wasn't executed yet. */
   1362     while (label_fixes)
   1363     {
   1364       struct label_fix *fix = label_fixes;
   1365 
   1366       label_fixes = fix->next;
   1367       symbol_set_value_now (fix->sym);
   1368       free (fix);
   1369     }
   1370 
   1371     insncnt = 0;
   1372     immxcnt = 0;
   1373     memset (immxbuf, 0, sizeof (immxbuf));
   1374 
   1375     return;
   1376   }
   1377 
   1378     char *buf = NULL;
   1379     sscanf (line_cursor, "%m[^\n]", &buf);
   1380     struct token_s my_tok = { .insn = buf, .begin = 0, .end = 0, .class_id = -1 , .val = 0 };
   1381     struct token_list *tok_lst = parse (my_tok);
   1382     free (buf);
   1383 
   1384     if (!tok_lst)
   1385       return;
   1386 
   1387     /* Skip opcode */
   1388     line_cursor += strlen (tok_lst->tok);
   1389 
   1390   assembling_insn = true;
   1391 
   1392   inside_bundle = 1;
   1393   assemble_tokens (tok_lst);
   1394   free_token_list (tok_lst);
   1395   assembling_insn = false;
   1396 }
   1397 
   1398 static void
   1399 kvx_set_cpu (void)
   1400 {
   1401   if (!kvx_core_info)
   1402     kvx_core_info = &kvx_kv3_v1_core_info;
   1403 
   1404   if (!kvx_registers)
   1405     kvx_registers = kvx_kv3_v1_registers;
   1406 
   1407   if (!kvx_regfiles)
   1408     kvx_regfiles = kvx_kv3_v1_regfiles;
   1409 
   1410   if (!kvx_modifiers)
   1411     kvx_modifiers = kvx_kv3_v1_modifiers;
   1412 
   1413   if (env.params.core == -1)
   1414       env.params.core = kvx_core_info->elf_core;
   1415 
   1416   int kvx_bfd_mach;
   1417   print_insn = kvx_print_insn;
   1418 
   1419   switch (kvx_core_info->elf_core)
   1420     {
   1421     case ELF_KVX_CORE_KV3_1:
   1422       kvx_bfd_mach = env.params.arch_size == 32 ? bfd_mach_kv3_1 : bfd_mach_kv3_1_64;
   1423       setup (ELF_KVX_CORE_KV3_1);
   1424       break;
   1425     case ELF_KVX_CORE_KV3_2:
   1426       kvx_bfd_mach = env.params.arch_size == 32 ? bfd_mach_kv3_2 : bfd_mach_kv3_2_64;
   1427       setup (ELF_KVX_CORE_KV3_2);
   1428       break;
   1429     case ELF_KVX_CORE_KV4_1:
   1430       kvx_bfd_mach = env.params.arch_size == 32 ? bfd_mach_kv4_1 : bfd_mach_kv4_1_64;
   1431       setup (ELF_KVX_CORE_KV4_1);
   1432       break;
   1433     default:
   1434       as_fatal ("Unknown elf core: 0x%x", kvx_core_info->elf_core);
   1435     }
   1436 
   1437   if (!bfd_set_arch_mach (stdoutput, TARGET_ARCH, kvx_bfd_mach))
   1438     as_warn (_("could not set architecture and machine"));
   1439 }
   1440 
   1441 static int
   1442 kvxop_compar (const void *a, const void *b)
   1443 {
   1444   const struct kvxopc *opa = (const struct kvxopc *) a;
   1445   const struct kvxopc *opb = (const struct kvxopc *) b;
   1446   int res = strcmp (opa->as_op, opb->as_op);
   1447 
   1448   if (res)
   1449     return res;
   1450   else
   1451     {
   1452       for (int i = 0; opa->format[i] && opb->format[i]; ++i)
   1453 	if (opa->format[i]->width != opb->format[i]->width)
   1454 	  return opa->format[i]->width - opb->format[i]->width;
   1455       return 0;
   1456     }
   1457 }
   1458 
   1459 /***************************************************/
   1460 /*    INITIALIZE ASSEMBLER                         */
   1461 /***************************************************/
   1462 
   1463 static int
   1464 print_hash (void **slot, void *arg ATTRIBUTE_UNUSED)
   1465 {
   1466   string_tuple_t *tuple = *((string_tuple_t **) slot);
   1467   printf ("%s\n", tuple->key);
   1468   return 1;
   1469 }
   1470 
   1471 static void
   1472 declare_register (const char *name, int number)
   1473 {
   1474   symbolS *regS = symbol_create (name, reg_section,
   1475 				 &zero_address_frag, number);
   1476 
   1477   if (str_hash_insert (env.reg_hash, S_GET_NAME (regS), regS, 0) != NULL)
   1478     as_fatal (_("duplicate %s"), name);
   1479 }
   1480 
   1481 void
   1482 md_begin ()
   1483 {
   1484   kvx_set_cpu ();
   1485 
   1486   /*
   1487    * Declare register names with symbols
   1488    */
   1489 
   1490   env.reg_hash = str_htab_create ();
   1491 
   1492   for (int i = 0; i < kvx_regfiles[KVX_REGFILE_REGISTERS]; i++)
   1493     declare_register (kvx_registers[i].name, kvx_registers[i].id);
   1494 
   1495   /* Sort optab, so that identical mnemonics appear consecutively */
   1496   {
   1497     int nel;
   1498     for (nel = 0; !STREQ ("", kvx_core_info->optab[nel].as_op); nel++)
   1499       ;
   1500     qsort (kvx_core_info->optab, nel, sizeof (kvx_core_info->optab[0]),
   1501 	   kvxop_compar);
   1502   }
   1503 
   1504   /* The '?' is an operand separator */
   1505   lex_type['?'] = 0;
   1506 
   1507   /* Create the opcode hash table      */
   1508   /* Each name should appear only once */
   1509 
   1510   env.opcode_hash = str_htab_create ();
   1511   env.reloc_hash = str_htab_create ();
   1512 
   1513   {
   1514     struct kvxopc *op;
   1515     const char *name = 0;
   1516     for (op = kvx_core_info->optab; !(STREQ ("", op->as_op)); op++)
   1517       {
   1518 	/* enter in hash table if this is a new name */
   1519 	if (!(STREQ (name, op->as_op)))
   1520 	  {
   1521 	    name = op->as_op;
   1522 	    if (str_hash_insert (env.opcode_hash, name, op, 0))
   1523 	      as_fatal ("internal error: can't hash opcode `%s'", name);
   1524 	  }
   1525 
   1526 
   1527 	for (int i = 0 ; op->format[i] ; ++i)
   1528 	  {
   1529 	    const char *reloc_name = TOKEN_NAME (op->format[i]->type);
   1530 	    void *relocs = op->format[i]->relocs;
   1531 	    if (op->format[i]->relocs[0] != 0
   1532 		&& !str_hash_find (env.reloc_hash, reloc_name))
   1533 	      if (str_hash_insert (env.reloc_hash, reloc_name, relocs, 0))
   1534 		  as_fatal ("internal error: can't hash type `%s'", reloc_name);
   1535 	  }
   1536       }
   1537   }
   1538 
   1539   if (env.opts.dump_table)
   1540     {
   1541       htab_traverse (env.opcode_hash, print_hash, NULL);
   1542       exit (0);
   1543     }
   1544 
   1545   if (env.opts.dump_insn)
   1546     {
   1547       for (struct kvxopc *op = kvx_core_info->optab; !(STREQ ("", op->as_op)); op++)
   1548 	print_insn (op);
   1549       exit (0);
   1550     }
   1551 
   1552   /* Here we enforce the minimum section alignment.  Remember, in
   1553    * the linker we can make the boudaries between the linked sections
   1554    * on larger boundaries.  The text segment is aligned to long words
   1555    * because of the odd/even constraint on immediate extensions
   1556    */
   1557 
   1558   bfd_set_section_alignment (text_section, 3);	/* -- 8 bytes */
   1559   bfd_set_section_alignment (data_section, 2);	/* -- 4 bytes */
   1560   bfd_set_section_alignment (bss_section, 2);	/* -- 4 bytes */
   1561   subseg_set (text_section, 0);
   1562 
   1563   symbolS *gotoff_sym   = symbol_create (".<gotoff>",   undefined_section, &zero_address_frag, 0);
   1564   symbolS *got_sym      = symbol_create (".<got>",      undefined_section, &zero_address_frag, 0);
   1565   symbolS *plt_sym      = symbol_create (".<plt>",      undefined_section, &zero_address_frag, 0);
   1566   symbolS *tlsgd_sym    = symbol_create (".<tlsgd>",    undefined_section, &zero_address_frag, 0);
   1567   symbolS *tlsie_sym    = symbol_create (".<tlsie>",    undefined_section, &zero_address_frag, 0);
   1568   symbolS *tlsle_sym    = symbol_create (".<tlsle>",    undefined_section, &zero_address_frag, 0);
   1569   symbolS *tlsld_sym    = symbol_create (".<tlsld>",    undefined_section, &zero_address_frag, 0);
   1570   symbolS *dtpoff_sym   = symbol_create (".<dtpoff>",   undefined_section, &zero_address_frag, 0);
   1571   symbolS *plt64_sym    = symbol_create (".<plt64>",    undefined_section, &zero_address_frag, 0);
   1572   symbolS *gotaddr_sym  = symbol_create (".<gotaddr>",  undefined_section, &zero_address_frag, 0);
   1573   symbolS *pcrel16_sym  = symbol_create (".<pcrel16>",  undefined_section, &zero_address_frag, 0);
   1574   symbolS *pcrel_sym    = symbol_create (".<pcrel>",    undefined_section, &zero_address_frag, 0);
   1575   symbolS *signed32_sym = symbol_create (".<signed32>", undefined_section, &zero_address_frag, 0);
   1576 
   1577   for (int i = 0; i < kvx_core_info->nb_pseudo_funcs; ++i)
   1578     {
   1579       symbolS *sym;
   1580       if (!strcmp (kvx_core_info->pseudo_funcs[i].name, "gotoff"))
   1581 	sym = gotoff_sym;
   1582       else if (!strcmp (kvx_core_info->pseudo_funcs[i].name, "got"))
   1583 	sym = got_sym;
   1584       else if (!strcmp (kvx_core_info->pseudo_funcs[i].name, "plt"))
   1585 	sym = plt_sym;
   1586       else if (!strcmp (kvx_core_info->pseudo_funcs[i].name, "tlsgd"))
   1587 	sym = tlsgd_sym;
   1588       else if (!strcmp (kvx_core_info->pseudo_funcs[i].name, "tlsle"))
   1589 	sym = tlsle_sym;
   1590       else if (!strcmp (kvx_core_info->pseudo_funcs[i].name, "tlsld"))
   1591 	sym = tlsld_sym;
   1592       else if (!strcmp (kvx_core_info->pseudo_funcs[i].name, "dtpoff"))
   1593 	sym = dtpoff_sym;
   1594       else if (!strcmp (kvx_core_info->pseudo_funcs[i].name, "tlsie"))
   1595 	sym = tlsie_sym;
   1596       else if (!strcmp (kvx_core_info->pseudo_funcs[i].name, "plt64"))
   1597 	sym = plt64_sym;
   1598       else if (!strcmp (kvx_core_info->pseudo_funcs[i].name, "pcrel16"))
   1599 	sym = pcrel16_sym;
   1600       else if (!strcmp (kvx_core_info->pseudo_funcs[i].name, "pcrel"))
   1601 	sym = pcrel_sym;
   1602       else if (!strcmp (kvx_core_info->pseudo_funcs[i].name, "gotaddr"))
   1603 	sym = gotaddr_sym;
   1604       else if (!strcmp (kvx_core_info->pseudo_funcs[i].name, "signed32"))
   1605 	sym = signed32_sym;
   1606       else
   1607 	as_fatal ("internal error: Unknown pseudo func `%s'",
   1608 	    kvx_core_info->pseudo_funcs[i].name);
   1609 
   1610       kvx_core_info->pseudo_funcs[i].sym = sym;
   1611     }
   1612 }
   1613 
   1614 /***************************************************/
   1615 /*          ASSEMBLER CLEANUP STUFF                */
   1616 /***************************************************/
   1617 
   1618 /* Return non-zero if the indicated VALUE has overflowed the maximum
   1619    range expressible by a signed number with the indicated number of
   1620    BITS.
   1621 
   1622    This is from tc-aarch64.c
   1623 */
   1624 
   1625 static bfd_boolean
   1626 signed_overflow (offsetT value, unsigned bits)
   1627 {
   1628   offsetT lim;
   1629   if (bits >= sizeof (offsetT) * 8)
   1630     return FALSE;
   1631   lim = (offsetT) 1 << (bits - 1);
   1632   return (value < -lim || value >= lim);
   1633 }
   1634 
   1635 /***************************************************/
   1636 /*          ASSEMBLER FIXUP STUFF                  */
   1637 /***************************************************/
   1638 
   1639 void
   1640 md_apply_fix (fixS * fixP, valueT * valueP, segT segmentP ATTRIBUTE_UNUSED)
   1641 {
   1642   char *const fixpos = fixP->fx_frag->fr_literal + fixP->fx_where;
   1643   valueT value = *valueP;
   1644   valueT image;
   1645   arelent *rel;
   1646 
   1647   rel = (arelent *) xmalloc (sizeof (arelent));
   1648 
   1649   rel->howto = bfd_reloc_type_lookup (stdoutput, fixP->fx_r_type);
   1650   if (rel->howto == NULL)
   1651     {
   1652       as_fatal
   1653 	("[md_apply_fix] unsupported relocation type (can't find howto)");
   1654     }
   1655 
   1656   /* Note whether this will delete the relocation.  */
   1657   if (fixP->fx_addsy == NULL && fixP->fx_pcrel == 0)
   1658     fixP->fx_done = 1;
   1659 
   1660   if (fixP->fx_size > 0)
   1661     image = md_chars_to_number (fixpos, fixP->fx_size);
   1662   else
   1663     image = 0;
   1664   if (fixP->fx_addsy != NULL)
   1665     {
   1666       switch (fixP->fx_r_type)
   1667 	{
   1668 	case BFD_RELOC_KVX_S37_TLS_LE_UP27:
   1669 	case BFD_RELOC_KVX_S37_TLS_LE_LO10:
   1670 
   1671 	case BFD_RELOC_KVX_S43_TLS_LE_EX6:
   1672 	case BFD_RELOC_KVX_S43_TLS_LE_UP27:
   1673 	case BFD_RELOC_KVX_S43_TLS_LE_LO10:
   1674 
   1675 	case BFD_RELOC_KVX_S37_TLS_GD_LO10:
   1676 	case BFD_RELOC_KVX_S37_TLS_GD_UP27:
   1677 
   1678 	case BFD_RELOC_KVX_S43_TLS_GD_LO10:
   1679 	case BFD_RELOC_KVX_S43_TLS_GD_UP27:
   1680 	case BFD_RELOC_KVX_S43_TLS_GD_EX6:
   1681 
   1682 	case BFD_RELOC_KVX_S37_TLS_IE_LO10:
   1683 	case BFD_RELOC_KVX_S37_TLS_IE_UP27:
   1684 
   1685 	case BFD_RELOC_KVX_S43_TLS_IE_LO10:
   1686 	case BFD_RELOC_KVX_S43_TLS_IE_UP27:
   1687 	case BFD_RELOC_KVX_S43_TLS_IE_EX6:
   1688 
   1689 	case BFD_RELOC_KVX_S37_TLS_LD_LO10:
   1690 	case BFD_RELOC_KVX_S37_TLS_LD_UP27:
   1691 
   1692 	case BFD_RELOC_KVX_S43_TLS_LD_LO10:
   1693 	case BFD_RELOC_KVX_S43_TLS_LD_UP27:
   1694 	case BFD_RELOC_KVX_S43_TLS_LD_EX6:
   1695 
   1696 	  S_SET_THREAD_LOCAL (fixP->fx_addsy);
   1697 	  break;
   1698 	default:
   1699 	  break;
   1700 	}
   1701     }
   1702 
   1703   /* If relocation has been marked for deletion, apply remaining changes */
   1704   if (fixP->fx_done)
   1705     {
   1706       switch (fixP->fx_r_type)
   1707 	{
   1708 	case BFD_RELOC_8:
   1709 	case BFD_RELOC_16:
   1710 	case BFD_RELOC_32:
   1711 	case BFD_RELOC_64:
   1712 
   1713 	case BFD_RELOC_KVX_GLOB_DAT:
   1714 	case BFD_RELOC_KVX_32_GOT:
   1715 	case BFD_RELOC_KVX_64_GOT:
   1716 	case BFD_RELOC_KVX_64_GOTOFF:
   1717 	case BFD_RELOC_KVX_32_GOTOFF:
   1718 	  image = value;
   1719 	  md_number_to_chars (fixpos, image, fixP->fx_size);
   1720 	  break;
   1721 
   1722 	case BFD_RELOC_KVX_PCREL17:
   1723 	  if (signed_overflow (value, 17 + 2))
   1724 	    as_bad_where (fixP->fx_file, fixP->fx_line,
   1725 			  _("branch out of range"));
   1726 	  goto pcrel_common;
   1727 
   1728 	case BFD_RELOC_KVX_PCREL27:
   1729 	  if (signed_overflow (value, 27 + 2))
   1730 	    as_bad_where (fixP->fx_file, fixP->fx_line,
   1731 			  _("branch out of range"));
   1732 	  goto pcrel_common;
   1733 
   1734 	case BFD_RELOC_KVX_S16_PCREL:
   1735 	  if (signed_overflow (value, 16))
   1736 	    as_bad_where (fixP->fx_file, fixP->fx_line,
   1737 			  _("signed16 PCREL value out of range"));
   1738 	  goto pcrel_common;
   1739 
   1740 	case BFD_RELOC_KVX_S43_PCREL_LO10:
   1741 	case BFD_RELOC_KVX_S43_PCREL_UP27:
   1742 	case BFD_RELOC_KVX_S43_PCREL_EX6:
   1743 	  if (signed_overflow (value, 10 + 27 + 6))
   1744 	    as_bad_where (fixP->fx_file, fixP->fx_line,
   1745 			  _("signed43 PCREL value out of range"));
   1746 	  goto pcrel_common;
   1747 
   1748 	case BFD_RELOC_KVX_S37_PCREL_LO10:
   1749 	case BFD_RELOC_KVX_S37_PCREL_UP27:
   1750 	  if (signed_overflow (value, 10 + 27))
   1751 	    as_bad_where (fixP->fx_file, fixP->fx_line,
   1752 			  _("signed37 PCREL value out of range"));
   1753 	  goto pcrel_common;
   1754 
   1755 	case BFD_RELOC_KVX_S64_PCREL_LO10:
   1756 	case BFD_RELOC_KVX_S64_PCREL_UP27:
   1757 	case BFD_RELOC_KVX_S64_PCREL_EX27:
   1758 
   1759 	pcrel_common:
   1760 	  if (fixP->fx_pcrel || fixP->fx_addsy)
   1761 	    return;
   1762 	  value =
   1763 	    (((value >> rel->howto->rightshift) << rel->howto->bitpos) & rel->
   1764 	     howto->dst_mask);
   1765 	  image = (image & ~(rel->howto->dst_mask)) | value;
   1766 	  md_number_to_chars (fixpos, image, fixP->fx_size);
   1767 	  break;
   1768 
   1769 	case BFD_RELOC_KVX_S64_GOTADDR_LO10:
   1770 	case BFD_RELOC_KVX_S64_GOTADDR_UP27:
   1771 	case BFD_RELOC_KVX_S64_GOTADDR_EX27:
   1772 
   1773 	case BFD_RELOC_KVX_S43_GOTADDR_LO10:
   1774 	case BFD_RELOC_KVX_S43_GOTADDR_UP27:
   1775 	case BFD_RELOC_KVX_S43_GOTADDR_EX6:
   1776 
   1777 	case BFD_RELOC_KVX_S37_GOTADDR_LO10:
   1778 	case BFD_RELOC_KVX_S37_GOTADDR_UP27:
   1779 	  value = 0;
   1780 	  /* Fallthrough */
   1781 
   1782 	case BFD_RELOC_KVX_S32_UP27:
   1783 
   1784 	case BFD_RELOC_KVX_S37_UP27:
   1785 
   1786 	case BFD_RELOC_KVX_S43_UP27:
   1787 
   1788 	case BFD_RELOC_KVX_S64_UP27:
   1789 	case BFD_RELOC_KVX_S64_EX27:
   1790 	case BFD_RELOC_KVX_S64_LO10:
   1791 
   1792 	case BFD_RELOC_KVX_S43_TLS_LE_UP27:
   1793 	case BFD_RELOC_KVX_S43_TLS_LE_EX6:
   1794 
   1795 	case BFD_RELOC_KVX_S37_TLS_LE_UP27:
   1796 
   1797 	case BFD_RELOC_KVX_S37_GOTOFF_UP27:
   1798 
   1799 	case BFD_RELOC_KVX_S43_GOTOFF_UP27:
   1800 	case BFD_RELOC_KVX_S43_GOTOFF_EX6:
   1801 
   1802 	case BFD_RELOC_KVX_S43_GOT_UP27:
   1803 	case BFD_RELOC_KVX_S43_GOT_EX6:
   1804 
   1805 	case BFD_RELOC_KVX_S37_GOT_UP27:
   1806 
   1807 	case BFD_RELOC_KVX_S32_LO5:
   1808 	case BFD_RELOC_KVX_S37_LO10:
   1809 
   1810 	case BFD_RELOC_KVX_S43_LO10:
   1811 	case BFD_RELOC_KVX_S43_EX6:
   1812 
   1813 	case BFD_RELOC_KVX_S43_TLS_LE_LO10:
   1814 	case BFD_RELOC_KVX_S37_TLS_LE_LO10:
   1815 
   1816 	case BFD_RELOC_KVX_S37_GOTOFF_LO10:
   1817 	case BFD_RELOC_KVX_S43_GOTOFF_LO10:
   1818 
   1819 	case BFD_RELOC_KVX_S43_GOT_LO10:
   1820 	case BFD_RELOC_KVX_S37_GOT_LO10:
   1821 
   1822 	default:
   1823 	  as_fatal ("[md_apply_fix]:"
   1824 		    "unsupported relocation type (type not handled : %d)",
   1825 		    fixP->fx_r_type);
   1826 	}
   1827     }
   1828 }
   1829 
   1830 /*
   1831  * Warning: Can be called only in fixup_segment() after fx_addsy field
   1832  * has been updated by calling symbol_get_value_expression(...->X_add_symbol)
   1833  */
   1834 int
   1835 kvx_validate_sub_fix (fixS * fixP)
   1836 {
   1837   segT add_symbol_segment, sub_symbol_segment;
   1838 
   1839   switch (fixP->fx_r_type)
   1840     {
   1841     case BFD_RELOC_8:
   1842     case BFD_RELOC_16:
   1843     case BFD_RELOC_32:
   1844       if (fixP->fx_addsy != NULL)
   1845 	add_symbol_segment = S_GET_SEGMENT (fixP->fx_addsy);
   1846       else
   1847 	return 0;
   1848       if (fixP->fx_subsy != NULL)
   1849 	sub_symbol_segment = S_GET_SEGMENT (fixP->fx_subsy);
   1850       else
   1851 	return 0;
   1852 
   1853       if ((strcmp (S_GET_NAME (fixP->fx_addsy),
   1854 		   S_GET_NAME (fixP->fx_subsy)) == 0) &&
   1855 	  (add_symbol_segment == sub_symbol_segment))
   1856 	return 1;
   1857       break;
   1858     default:
   1859       break;
   1860     }
   1861 
   1862   return 0;
   1863 }
   1864 
   1865 /* This is called whenever some data item (not an instruction) needs a
   1866  * fixup.  */
   1867 void
   1868 kvx_cons_fix_new (fragS * f, int where, int nbytes, expressionS * exp,
   1869 		  bfd_reloc_code_real_type code)
   1870 {
   1871   if (exp->X_op == O_pseudo_fixup)
   1872     {
   1873       exp->X_op = O_symbol;
   1874       struct pseudo_func *pf =
   1875 	kvx_get_pseudo_func_data_scn (exp->X_op_symbol);
   1876       assert (pf != NULL);
   1877       code = pf->pseudo_relocs.single;
   1878 
   1879       if (code == BFD_RELOC_UNUSED)
   1880 	as_fatal ("Unsupported relocation");
   1881     }
   1882   else
   1883     {
   1884       switch (nbytes)
   1885 	{
   1886 	case 1:
   1887 	  code = BFD_RELOC_8;
   1888 	  break;
   1889 	case 2:
   1890 	  code = BFD_RELOC_16;
   1891 	  break;
   1892 	case 4:
   1893 	  code = BFD_RELOC_32;
   1894 	  break;
   1895 	case 8:
   1896 	  code = BFD_RELOC_64;
   1897 	  break;
   1898 	default:
   1899 	  as_fatal ("unsupported BFD relocation size %u", nbytes);
   1900 	  break;
   1901 	}
   1902     }
   1903   fix_new_exp (f, where, nbytes, exp, 0, code);
   1904 }
   1905 
   1906 /*
   1907  * generate a relocation record
   1908  */
   1909 
   1910 arelent *
   1911 tc_gen_reloc (asection * sec ATTRIBUTE_UNUSED, fixS * fixp)
   1912 {
   1913   arelent *reloc;
   1914   bfd_reloc_code_real_type code;
   1915 
   1916   reloc = (arelent *) xmalloc (sizeof (arelent));
   1917 
   1918   reloc->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *));
   1919   *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
   1920   reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
   1921 
   1922   code = fixp->fx_r_type;
   1923   if (code == BFD_RELOC_32 && fixp->fx_pcrel)
   1924     code = BFD_RELOC_32_PCREL;
   1925   reloc->howto = bfd_reloc_type_lookup (stdoutput, code);
   1926 
   1927   if (reloc->howto == NULL)
   1928     {
   1929       as_bad_where (fixp->fx_file, fixp->fx_line,
   1930 		    "cannot represent `%s' relocation in object file",
   1931 		    bfd_get_reloc_code_name (code));
   1932       return NULL;
   1933     }
   1934 
   1935 //  if (!fixp->fx_pcrel != !reloc->howto->pc_relative)
   1936 //    {
   1937 //      as_fatal ("internal error? cannot generate `%s' relocation",
   1938 //		bfd_get_reloc_code_name (code));
   1939 //    }
   1940 //  assert (!fixp->fx_pcrel == !reloc->howto->pc_relative);
   1941 
   1942   reloc->addend = fixp->fx_offset;
   1943 
   1944   /*
   1945    * Ohhh, this is ugly.  The problem is that if this is a local global
   1946    * symbol, the relocation will entirely be performed at link time, not
   1947    * at assembly time.  bfd_perform_reloc doesn't know about this sort
   1948    * of thing, and as a result we need to fake it out here.
   1949    */
   1950 
   1951   /* GD I'm not sure what this is used for in the kvx case but it sure  */
   1952   /* messes up the relocs when emit_all_relocs is used as they are not */
   1953   /* resolved with respect to a global sysmbol (e.g. .text), and hence */
   1954   /* they are ALWAYS resolved at link time                             */
   1955   /* FIXME FIXME                                                       */
   1956 
   1957   /* clarkes: 030827:  This code (and the other half of the fix in write.c)
   1958    * have caused problems with the PIC relocations.
   1959    * The root problem is that bfd_install_relocation adds in to the reloc
   1960    * addend the section offset of a symbol defined in the current object.
   1961    * This causes problems on numerous other targets too, and there are
   1962    * several different methods used to get around it:
   1963    *   1.  In tc_gen_reloc, subtract off the value that bfd_install_relocation
   1964    *       added.  That is what we do here, and it is also done the
   1965    *       same way for alpha.
   1966    *   2.  In md_apply_fix, subtract off the value that bfd_install_relocation
   1967    *       will add.  This is done on SH (non-ELF) and sparc targets.
   1968    *   3.  In the howto structure for the relocations, specify a
   1969    *       special function that does not return bfd_reloc_continue.
   1970    *       This causes bfd_install_relocaion to terminate before it
   1971    *       adds in the symbol offset.  This is done on SH ELF targets.
   1972    *       Note that on ST200 we specify bfd_elf_generic_reloc as
   1973    *       the special function.  This will return bfd_reloc_continue
   1974    *       only in some circumstances, but in particular if the reloc
   1975    *       is marked as partial_inplace in the bfd howto structure, then
   1976    *       bfd_elf_generic_reloc will return bfd_reloc_continue.
   1977    *       Some ST200 relocations are marked as partial_inplace
   1978    *       (this is an error in my opinion because ST200 always uses
   1979    *       a separate addend), but some are not.  The PIC relocations
   1980    *       are not marked as partial_inplace, so for them,
   1981    *       bfd_elf_generic_reloc returns bfd_reloc_ok, and the addend
   1982    *       is not modified by bfd_install_relocation.   The relocations
   1983    *       R_KVX_16 and R_KVX_32 are marked partial_inplace, and so for
   1984    *       these we need to correct the addend.
   1985    * In the code below, the condition in the emit_all_relocs branch
   1986    * (now moved to write.c) is the inverse of the condition that
   1987    * bfd_elf_generic_reloc uses to short-circuit the code in
   1988    * bfd_install_relocation that modifies the addend.  The condition
   1989    * in the else branch match the condition used in the alpha version
   1990    * of tc_gen_reloc (see tc-alpha.c).
   1991    * I do not know why we need to use different conditions in these
   1992    * two branches, it seems to me that the condition should be the same
   1993    * whether or not emit_all_relocs is true.
   1994    * I also do not understand why it was necessary to move the emit_all_relocs
   1995    * condition to write.c.
   1996    */
   1997 
   1998   if (S_IS_EXTERNAL (fixp->fx_addsy) &&
   1999       !S_IS_COMMON (fixp->fx_addsy) && reloc->howto->partial_inplace)
   2000     reloc->addend -= symbol_get_bfdsym (fixp->fx_addsy)->value;
   2001 
   2002   return reloc;
   2003 }
   2004 
   2005 /* Round up segment to appropriate boundary */
   2006 
   2007 valueT
   2008 md_section_align (asection * seg ATTRIBUTE_UNUSED, valueT size)
   2009 {
   2010 #ifndef OBJ_ELF
   2011   /* This is not right for ELF; a.out wants it, and COFF will force
   2012    * the alignment anyways.  */
   2013   int align = bfd_get_section_alignment (stdoutput, seg);
   2014   valueT mask = ((valueT) 1 << align) - 1;
   2015   return (size + mask) & ~mask;
   2016 #else
   2017   return size;
   2018 #endif
   2019 }
   2020 
   2021 int
   2022 md_estimate_size_before_relax (register fragS * fragP ATTRIBUTE_UNUSED,
   2023 			       segT segtype ATTRIBUTE_UNUSED)
   2024 {
   2025   as_fatal ("estimate_size_before_relax called");
   2026 }
   2027 
   2028 void
   2029 md_convert_frag (bfd * abfd ATTRIBUTE_UNUSED,
   2030 		 asection * sec ATTRIBUTE_UNUSED,
   2031 		 fragS * fragp ATTRIBUTE_UNUSED)
   2032 {
   2033   as_fatal ("kvx convert_frag");
   2034 }
   2035 
   2036 symbolS *
   2037 md_undefined_symbol (char *name ATTRIBUTE_UNUSED)
   2038 {
   2039   return 0;
   2040 }
   2041 
   2042 const char *
   2043 md_atof (int type ATTRIBUTE_UNUSED,
   2044 	 char *litp ATTRIBUTE_UNUSED, int *sizep ATTRIBUTE_UNUSED)
   2045 {
   2046   return ieee_md_atof (type, litp, sizep, TARGET_BYTES_BIG_ENDIAN);
   2047 }
   2048 
   2049 /*
   2050  * calculate the base for a pcrel fixup
   2051  * -- for relocation, we might need to add addend ?
   2052  */
   2053 
   2054 long
   2055 md_pcrel_from (fixS * fixP)
   2056 {
   2057   return (fixP->fx_where + fixP->fx_frag->fr_address);
   2058 }
   2059 
   2060 /************************************************************/
   2061 /*   Hooks into standard processing -- we hook into label   */
   2062 /*   handling code to detect double ':' and we hook before  */
   2063 /*   a line of code is processed to do some simple sed style */
   2064 /*   edits.                                                 */
   2065 /************************************************************/
   2066 
   2067 static symbolS *last_proc_sym = NULL;
   2068 static int update_last_proc_sym = 0;
   2069 
   2070 void
   2071 kvx_frob_label (symbolS *sym)
   2072 {
   2073   if (update_last_proc_sym)
   2074     {
   2075       last_proc_sym = sym;
   2076       update_last_proc_sym = 0;
   2077     }
   2078 
   2079   if (inside_bundle)
   2080     {
   2081       struct label_fix *fix;
   2082       fix = malloc (sizeof (*fix));
   2083       fix->next = label_fixes;
   2084       fix->sym = sym;
   2085       label_fixes = fix;
   2086     }
   2087 
   2088   dwarf2_emit_label (sym);
   2089 }
   2090 
   2091 void
   2092 kvx_check_label (symbolS *sym)
   2093 {
   2094   /* Labels followed by a second semi-colon are considered external symbols.  */
   2095   if (*input_line_pointer == ':')
   2096     {
   2097       S_SET_EXTERNAL (sym);
   2098       input_line_pointer++;
   2099     }
   2100 }
   2101 
   2102 /* Emit single bundle nop. This is needed by .nop asm directive
   2103  * Have to manage end of bundle done usually by start_line_hook
   2104  * using BE pseudo op
   2105  */
   2106 void
   2107 kvx_emit_single_noop (void)
   2108 {
   2109   char *nop;
   2110   char *end_of_bundle;
   2111 
   2112   if (asprintf (&nop, "nop") < 0)
   2113     as_fatal ("%s", xstrerror (errno));
   2114 
   2115   if (asprintf (&end_of_bundle, "be") < 0)
   2116     as_fatal ("%s", xstrerror (errno));
   2117 
   2118   char *saved_ilp = input_line_pointer;
   2119   md_assemble (nop);
   2120   md_assemble (end_of_bundle);
   2121   input_line_pointer = saved_ilp;
   2122   free (nop);
   2123   free (end_of_bundle);
   2124 }
   2125 
   2126 /*  edit out some syntactic sugar that confuses GAS       */
   2127 /*  input_line_pointer is guaranteed to point to the      */
   2128 /*  the current line but may include text from following  */
   2129 /*  lines.  Thus, '\n' must be scanned for as well as '\0' */
   2130 
   2131 void
   2132 kvx_md_start_line_hook (void)
   2133 {
   2134   char *t;
   2135 
   2136   for (t = input_line_pointer; t && t[0] == ' '; t++);
   2137 
   2138   /* Detect illegal syntax patterns:
   2139    * - two bundle ends on the same line: ;; ;;
   2140    * - illegal token: ;;;
   2141    */
   2142   if (t && (t[0] == ';') && (t[1] == ';'))
   2143     {
   2144       char *tmp_t;
   2145       bool newline_seen = false;
   2146 
   2147       if (t[2] == ';')
   2148 	as_fatal ("Syntax error: Illegal ;;; token");
   2149 
   2150       tmp_t = t + 2;
   2151 
   2152       while (tmp_t && tmp_t[0])
   2153 	{
   2154 	  while (tmp_t && tmp_t[0] &&
   2155 		 ((tmp_t[0] == ' ') || (tmp_t[0] == '\n')))
   2156 	    {
   2157 	      if (tmp_t[0] == '\n')
   2158 		newline_seen = true;
   2159 	      tmp_t++;
   2160 	    }
   2161 	  if (tmp_t[0] == ';' && tmp_t[1] == ';')
   2162 	    {
   2163 	      /* if there's no newline between the two bundle stops
   2164 	       * then raise a syntax error now, otherwise a strange error
   2165 	       * message from read.c will be raised: "junk at end of line..."
   2166 	       */
   2167 	      if (tmp_t[2] == ';')
   2168 		as_fatal ("Syntax error: Illegal ;;; token");
   2169 
   2170 	      if (!newline_seen)
   2171 		  as_fatal ("Syntax error: More than one bundle stop on a line");
   2172 	      newline_seen = false;	/* reset */
   2173 
   2174 	      /* this is an empty bundle, transform it into an
   2175 	       * empty statement */
   2176 	      tmp_t[0] = ';';
   2177 	      tmp_t[1] = ' ';
   2178 
   2179 	      tmp_t += 2;
   2180 	    }
   2181 	  else
   2182 	    break;
   2183 	}
   2184     }
   2185 
   2186   /* check for bundle end                             */
   2187   /* we transform these into a special opcode BE      */
   2188   /* because gas has ';' hardwired as a statement end */
   2189   if (t && (t[0] == ';') && (t[1] == ';'))
   2190     {
   2191       t[0] = 'B';
   2192       t[1] = 'E';
   2193       return;
   2194     }
   2195 }
   2196 
   2197 static void
   2198 kvx_check_resources (int f)
   2199 {
   2200   env.opts.check_resource_usage = f;
   2201 }
   2202 
   2203 /** called before write_object_file */
   2204 void
   2205 kvx_end (void)
   2206 {
   2207   int newflags;
   2208 
   2209   if (!env.params.core_set)
   2210     env.params.core = kvx_core_info->elf_core;
   2211 
   2212   /* (pp) the flags must be set at once */
   2213   newflags = env.params.core | env.params.abi | env.params.pic_flags;
   2214 
   2215   if (env.params.arch_size == 64)
   2216     newflags |= ELF_KVX_ABI_64B_ADDR_BIT;
   2217 
   2218   bfd_set_private_flags (stdoutput, newflags);
   2219 
   2220   cleanup ();
   2221 
   2222   if (inside_bundle && insncnt != 0)
   2223     as_bad ("unexpected end-of-file while processing a bundle."
   2224 	    "  Please check that ;; is on its own line.");
   2225 }
   2226 
   2227 static void
   2228 kvx_type (int start ATTRIBUTE_UNUSED)
   2229 {
   2230   char *name;
   2231   char c;
   2232   int type;
   2233   char *typename = NULL;
   2234   symbolS *sym;
   2235   elf_symbol_type *elfsym;
   2236 
   2237   c = get_symbol_name (&name);
   2238   sym = symbol_find_or_make (name);
   2239   elfsym = (elf_symbol_type *) symbol_get_bfdsym (sym);
   2240   *input_line_pointer = c;
   2241 
   2242   if (!*S_GET_NAME (sym))
   2243     as_bad (_("Missing symbol name in directive"));
   2244 
   2245   SKIP_WHITESPACE ();
   2246   if (*input_line_pointer == ',')
   2247     ++input_line_pointer;
   2248 
   2249 
   2250   SKIP_WHITESPACE ();
   2251   if (*input_line_pointer == '#'
   2252       || *input_line_pointer == '@'
   2253       || *input_line_pointer == '"' || *input_line_pointer == '%')
   2254     ++input_line_pointer;
   2255 
   2256   /* typename = input_line_pointer; */
   2257   /* c = get_symbol_end(); */
   2258   c = get_symbol_name (&typename);
   2259 
   2260   type = 0;
   2261   if (strcmp (typename, "function") == 0
   2262       || strcmp (typename, "STT_FUNC") == 0)
   2263     type = BSF_FUNCTION;
   2264   else if (strcmp (typename, "object") == 0
   2265 	   || strcmp (typename, "STT_OBJECT") == 0)
   2266     type = BSF_OBJECT;
   2267   else if (strcmp (typename, "tls_object") == 0
   2268 	   || strcmp (typename, "STT_TLS") == 0)
   2269     type = BSF_OBJECT | BSF_THREAD_LOCAL;
   2270   else if (strcmp (typename, "common") == 0
   2271 	   || strcmp (typename, "STT_COMMON") == 0)
   2272     type = BSF_ELF_COMMON;
   2273   else if (strcmp (typename, "gnu_unique_object") == 0
   2274 	   || strcmp (typename, "STB_GNU_UNIQUE") == 0)
   2275     {
   2276       elf_tdata (stdoutput)->has_gnu_osabi |= elf_gnu_osabi_unique;
   2277       type = BSF_OBJECT | BSF_GNU_UNIQUE;
   2278     }
   2279   else if (strcmp (typename, "notype") == 0
   2280 	   || strcmp (typename, "STT_NOTYPE") == 0)
   2281     ;
   2282 #ifdef md_elf_symbol_type
   2283   else if ((type = md_elf_symbol_type (typename, sym, elfsym)) != -1)
   2284     ;
   2285 #endif
   2286   else
   2287     as_bad (_("unrecognized symbol type \"%s\""), typename);
   2288 
   2289   *input_line_pointer = c;
   2290 
   2291   if (*input_line_pointer == '"')
   2292     ++input_line_pointer;
   2293 
   2294   elfsym->symbol.flags |= type;
   2295   symbol_get_bfdsym (sym)->flags |= type;
   2296 
   2297   demand_empty_rest_of_line ();
   2298 }
   2299 
   2300 #define ENDPROCEXTENSION	"$endproc"
   2301 #define MINUSEXPR		".-"
   2302 
   2303 static int proc_endp_status = 0;
   2304 
   2305 static void
   2306 kvx_endp (int start ATTRIBUTE_UNUSED)
   2307 {
   2308   char c;
   2309   char *name;
   2310 
   2311   if (inside_bundle)
   2312     as_warn (".endp directive inside a bundle.");
   2313   /* function name is optionnal and is ignored */
   2314   /* there may be several names separated by commas... */
   2315   while (1)
   2316     {
   2317       SKIP_WHITESPACE ();
   2318       c = get_symbol_name (&name);
   2319       (void) restore_line_pointer (c);
   2320       SKIP_WHITESPACE ();
   2321       if (*input_line_pointer != ',')
   2322 	break;
   2323       ++input_line_pointer;
   2324     }
   2325   demand_empty_rest_of_line ();
   2326 
   2327   if (!proc_endp_status)
   2328     {
   2329       as_warn (".endp directive doesn't follow .proc -- ignoring ");
   2330       return;
   2331     }
   2332 
   2333   proc_endp_status = 0;
   2334 
   2335   /* TB begin : add BSF_FUNCTION attribute to last_proc_sym symbol */
   2336   if (size_type_function)
   2337     {
   2338       if (!last_proc_sym)
   2339 	{
   2340 	  as_bad ("Cannot set function attributes (bad symbol)");
   2341 	  return;
   2342 	}
   2343 
   2344       /*    last_proc_sym->symbol.flags |= BSF_FUNCTION; */
   2345       symbol_get_bfdsym (last_proc_sym)->flags |= BSF_FUNCTION;
   2346       /* Add .size funcname,.-funcname in order to add size
   2347        * attribute to the current function */
   2348       {
   2349 	const int newdirective_sz =
   2350 	  strlen (S_GET_NAME (last_proc_sym)) + strlen (MINUSEXPR) + 1;
   2351 	char *newdirective = malloc (newdirective_sz);
   2352 	char *savep = input_line_pointer;
   2353 	expressionS exp;
   2354 
   2355 	memset (newdirective, 0, newdirective_sz);
   2356 
   2357 	/* BUILD :".-funcname" expression */
   2358 	strcat (newdirective, MINUSEXPR);
   2359 	strcat (newdirective, S_GET_NAME (last_proc_sym));
   2360 	input_line_pointer = newdirective;
   2361 	expression (&exp);
   2362 
   2363 	if (exp.X_op == O_constant)
   2364 	  {
   2365 	    S_SET_SIZE (last_proc_sym, exp.X_add_number);
   2366 	    if (symbol_get_obj (last_proc_sym)->size)
   2367 	      {
   2368 		xfree (symbol_get_obj (last_proc_sym)->size);
   2369 		symbol_get_obj (last_proc_sym)->size = NULL;
   2370 	      }
   2371 	  }
   2372 	else
   2373 	  {
   2374 	    symbol_get_obj (last_proc_sym)->size =
   2375 	      (expressionS *) xmalloc (sizeof (expressionS));
   2376 	    *symbol_get_obj (last_proc_sym)->size = exp;
   2377 	  }
   2378 
   2379 	/* just restore the real input pointer */
   2380 	input_line_pointer = savep;
   2381 	free (newdirective);
   2382       }
   2383     }
   2384   /* TB end */
   2385 
   2386   last_proc_sym = NULL;
   2387 }
   2388 
   2389 static void
   2390 kvx_proc (int start ATTRIBUTE_UNUSED)
   2391 {
   2392   char c;
   2393   char *name;
   2394   /* there may be several names separated by commas... */
   2395   while (1)
   2396     {
   2397       SKIP_WHITESPACE ();
   2398       c = get_symbol_name (&name);
   2399       (void) restore_line_pointer (c);
   2400 
   2401       SKIP_WHITESPACE ();
   2402       if (*input_line_pointer != ',')
   2403 	break;
   2404       ++input_line_pointer;
   2405     }
   2406   demand_empty_rest_of_line ();
   2407 
   2408   if (proc_endp_status)
   2409     {
   2410       as_warn (".proc follows .proc -- ignoring");
   2411       return;
   2412     }
   2413 
   2414   proc_endp_status = 1;
   2415 
   2416   /* this code emit a global symbol to mark the end of each function    */
   2417   /* the symbol emitted has a name formed by the original function name */
   2418   /* concatenated with $endproc so if _foo is a function name the symbol */
   2419   /* marking the end of it is _foo$endproc                              */
   2420   /* It is also required for generation of .size directive in kvx_endp() */
   2421 
   2422   if (size_type_function)
   2423     update_last_proc_sym = 1;
   2424 }
   2425 
   2426 int
   2427 kvx_force_reloc (fixS * fixP)
   2428 {
   2429   symbolS *sym;
   2430   asection *symsec;
   2431 
   2432   if (generic_force_reloc (fixP))
   2433     return 1;
   2434 
   2435   switch (fixP->fx_r_type)
   2436     {
   2437     case BFD_RELOC_KVX_32_GOTOFF:
   2438     case BFD_RELOC_KVX_S37_GOTOFF_UP27:
   2439     case BFD_RELOC_KVX_S37_GOTOFF_LO10:
   2440 
   2441     case BFD_RELOC_KVX_64_GOTOFF:
   2442     case BFD_RELOC_KVX_S43_GOTOFF_UP27:
   2443     case BFD_RELOC_KVX_S43_GOTOFF_LO10:
   2444     case BFD_RELOC_KVX_S43_GOTOFF_EX6:
   2445 
   2446     case BFD_RELOC_KVX_32_GOT:
   2447     case BFD_RELOC_KVX_64_GOT:
   2448     case BFD_RELOC_KVX_S37_GOT_UP27:
   2449     case BFD_RELOC_KVX_S37_GOT_LO10:
   2450 
   2451     case BFD_RELOC_KVX_GLOB_DAT:
   2452       return 1;
   2453     default:
   2454       return 0;
   2455     }
   2456 
   2457   sym = fixP->fx_addsy;
   2458   if (sym)
   2459     {
   2460       symsec = S_GET_SEGMENT (sym);
   2461       /* if (bfd_is_abs_section (symsec)) return 0; */
   2462       if (!SEG_NORMAL (symsec))
   2463 	return 0;
   2464     }
   2465   return 1;
   2466 }
   2467 
   2468 int
   2469 kvx_force_reloc_sub_same (fixS * fixP, segT sec)
   2470 {
   2471   symbolS *sym;
   2472   asection *symsec;
   2473   const char *sec_name = NULL;
   2474 
   2475   if (generic_force_reloc (fixP))
   2476     return 1;
   2477 
   2478   switch (fixP->fx_r_type)
   2479     {
   2480     case BFD_RELOC_KVX_32_GOTOFF:
   2481     case BFD_RELOC_KVX_S37_GOTOFF_UP27:
   2482     case BFD_RELOC_KVX_S37_GOTOFF_LO10:
   2483 
   2484     case BFD_RELOC_KVX_64_GOTOFF:
   2485     case BFD_RELOC_KVX_S43_GOTOFF_UP27:
   2486     case BFD_RELOC_KVX_S43_GOTOFF_LO10:
   2487     case BFD_RELOC_KVX_S43_GOTOFF_EX6:
   2488 
   2489     case BFD_RELOC_KVX_32_GOT:
   2490     case BFD_RELOC_KVX_64_GOT:
   2491     case BFD_RELOC_KVX_S37_GOT_UP27:
   2492     case BFD_RELOC_KVX_S37_GOT_LO10:
   2493 
   2494     case BFD_RELOC_KVX_S37_LO10:
   2495     case BFD_RELOC_KVX_S37_UP27:
   2496 
   2497     case BFD_RELOC_KVX_GLOB_DAT:
   2498       return 1;
   2499 
   2500     default:
   2501       return 0;
   2502     }
   2503 
   2504   sym = fixP->fx_addsy;
   2505   if (sym)
   2506     {
   2507       symsec = S_GET_SEGMENT (sym);
   2508       /* if (bfd_is_abs_section (symsec)) return 0; */
   2509       if (!SEG_NORMAL (symsec))
   2510 	return 0;
   2511 
   2512       /*
   2513        * for .debug_arrange, .debug_frame, .eh_frame sections, containing
   2514        * expressions of the form "sym2 - sym1 + addend", solve them even when
   2515        * --emit-all-relocs is set. Otherwise, a relocation on two symbols
   2516        * is necessary and fails at elf level. Binopt should not be impacted by
   2517        * the resolution of this relocatable expression on symbols inside a
   2518        * function.
   2519        */
   2520       sec_name = segment_name (sec);
   2521       if ((strcmp (sec_name, ".eh_frame") == 0) ||
   2522 	  (strcmp (sec_name, ".except_table") == 0) ||
   2523 	  (strncmp (sec_name, ".debug_", sizeof (".debug_")) == 0))
   2524 	return 0;
   2525     }
   2526   return 1;
   2527 }
   2528 
   2529 /* Implement HANDLE_ALIGN.  */
   2530 
   2531 static void
   2532 kvx_make_nops (char *buf, bfd_vma bytes)
   2533 {
   2534   bfd_vma i = 0;
   2535   unsigned int j;
   2536 
   2537   static unsigned int nop_single = 0;
   2538 
   2539   if (!nop_single)
   2540     {
   2541       const struct kvxopc *opcode =
   2542 	(struct kvxopc *) str_hash_find (env.opcode_hash, "nop");
   2543 
   2544       if (opcode == NULL)
   2545 	as_fatal
   2546 	  ("internal error: could not find opcode for 'nop' during padding");
   2547 
   2548       nop_single = opcode->codewords[0].opcode;
   2549     }
   2550 
   2551   /* KVX instructions are always 4-bytes aligned. If we are at a position */
   2552   /* that is not 4 bytes aligned, it means this is not part of an instruction, */
   2553   /* so it is safe to use a zero byte for padding. */
   2554 
   2555   for (j = bytes % 4; j > 0; j--)
   2556     buf[i++] = 0;
   2557 
   2558   for (j = 0; j < (bytes - i); j += 4)
   2559     {
   2560       unsigned nop = nop_single;
   2561 
   2562       // nop has bundle end only if #4 nop or last padding nop.
   2563       // Sets the parallel bit when neither conditions are matched.
   2564       // 4*4 = biggest nop bundle we can get
   2565       // 12 = offset when writting the last nop possible in a 4 nops bundle
   2566       // bytes-i-4 = offset for the last 4-words in the padding
   2567       if (j % (4 * 4) != 12 && j != (bytes - i - 4))
   2568 	nop |= PARALLEL_BIT;
   2569 
   2570       memcpy (buf + i + j, &nop, sizeof (nop));
   2571     }
   2572 }
   2573 
   2574 /* Pads code section with bundle of nops when possible, 0 if not. */
   2575 void
   2576 kvx_handle_align (fragS *fragP)
   2577 {
   2578   switch (fragP->fr_type)
   2579     {
   2580     case rs_align_code:
   2581       {
   2582 	bfd_signed_vma bytes = (fragP->fr_next->fr_address
   2583 				- fragP->fr_address - fragP->fr_fix);
   2584 	char *p = fragP->fr_literal + fragP->fr_fix;
   2585 
   2586 	if (bytes <= 0)
   2587 	  break;
   2588 
   2589 	/* Insert zeros or nops to get 4 byte alignment.  */
   2590 	kvx_make_nops (p, bytes);
   2591 	fragP->fr_fix += bytes;
   2592       }
   2593       break;
   2594 
   2595     default:
   2596       break;
   2597     }
   2598 }
   2599 /*
   2600  * This is just used for debugging
   2601  */
   2602 
   2603 ATTRIBUTE_UNUSED
   2604 static void
   2605 print_operand (expressionS * e, FILE * out)
   2606 {
   2607   if (e)
   2608     {
   2609       switch (e->X_op)
   2610 	{
   2611 	case O_register:
   2612 	  fprintf (out, "%s", kvx_registers[e->X_add_number].name);
   2613 	  break;
   2614 
   2615 	case O_constant:
   2616 	  if (e->X_add_symbol)
   2617 	    {
   2618 	      if (e->X_add_number)
   2619 		fprintf (out, "(%s + %d)", S_GET_NAME (e->X_add_symbol),
   2620 			 (int) e->X_add_number);
   2621 	      else
   2622 		fprintf (out, "%s", S_GET_NAME (e->X_add_symbol));
   2623 	    }
   2624 	  else
   2625 	    fprintf (out, "%d", (int) e->X_add_number);
   2626 	  break;
   2627 
   2628 	case O_symbol:
   2629 	  if (e->X_add_symbol)
   2630 	    {
   2631 	      if (e->X_add_number)
   2632 		fprintf (out, "(%s + %d)", S_GET_NAME (e->X_add_symbol),
   2633 			 (int) e->X_add_number);
   2634 	      else
   2635 		fprintf (out, "%s", S_GET_NAME (e->X_add_symbol));
   2636 	    }
   2637 	  else
   2638 	    fprintf (out, "%d", (int) e->X_add_number);
   2639 	  break;
   2640 
   2641 	default:
   2642 	  fprintf (out, "o,ptype-%d", e->X_op);
   2643 	}
   2644     }
   2645 }
   2646 
   2647 void
   2648 kvx_cfi_frame_initial_instructions (void)
   2649 {
   2650   cfi_add_CFA_def_cfa (KVX_SP_REGNO, 0);
   2651 }
   2652 
   2653 int
   2654 kvx_regname_to_dw2regnum (const char *regname)
   2655 {
   2656   unsigned int regnum = -1;
   2657   const char *p;
   2658   char *q;
   2659 
   2660   if (regname[0] == 'r')
   2661     {
   2662       p = regname + 1;
   2663       regnum = strtoul (p, &q, 10);
   2664       if (p == q || *q || regnum >= 64)
   2665 	return -1;
   2666     }
   2667   return regnum;
   2668 }
   2669