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
42static 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*/
53int size_type_function = 1;
54/*TB end */
55
56struct 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. */
82const struct kvx_Register *kvx_registers = NULL;
83/* Default kvx_modifiers array. */
84const char ***kvx_modifiers = NULL;
85/* Default kvx_regfiles array. */
86const int *kvx_regfiles = NULL;
87/* Default values used if no assume directive is given */
88const struct kvx_core_info *kvx_core_info = NULL;
89
90/***********************************************/
91/*    Generic Globals for GAS                  */
92/***********************************************/
93
94const char comment_chars[]        = "#";
95const char line_comment_chars[]   = "#";
96const char line_separator_chars[] = ";";
97const char EXP_CHARS[]            = "eE";
98const char FLT_CHARS[]            = "dD";
99const int md_short_jump_size      = 0;
100const int md_long_jump_size       = 0;
101
102/***********************************************/
103/*           Local Types                       */
104/***********************************************/
105
106/* a fix up record                       */
107
108struct 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  */
120struct 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
142typedef void (*print_insn_t) (struct kvxopc * op);
143static print_insn_t print_insn = NULL;
144
145/* Set to TRUE when we assemble instructions.  */
146static bool assembling_insn = false;
147
148#define NOIMMX -1
149
150/* Was KVXMAXBUNDLEISSUE, changed because of NOPs */
151static struct kvxinsn insbuf[KVXMAXBUNDLEWORDS];
152static int insncnt = 0;
153static struct kvxinsn immxbuf[KVXMAXBUNDLEWORDS];
154static int immxcnt = 0;
155
156static void
157incr_immxcnt (void)
158{
159  immxcnt++;
160  if (immxcnt >= KVXMAXBUNDLEWORDS)
161    as_bad ("Max immx number exceeded: %d", immxcnt);
162}
163
164static void set_byte_counter (asection * sec, int value);
165static void
166set_byte_counter (asection * sec, int value)
167{
168  sec->target_index = value;
169}
170
171static int get_byte_counter (asection * sec);
172int
173get_byte_counter (asection * sec)
174{
175  return sec->target_index;
176}
177
178const char *
179kvx_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
190static void kvx_check_resources (int);
191static void kvx_proc (int start);
192static void kvx_endp (int start);
193static void kvx_type (int start);
194
195const 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
222static int inside_bundle = 0;
223
224/* Stores the labels inside bundles (typically debug labels) that need
225   to be postponed to the next bundle. */
226struct label_fix
227{
228  struct label_fix *next;
229  symbolS *sym;
230} *label_fixes = 0;
231
232/*****************************************************/
233/*   OPTIONS PROCESSING                              */
234/*****************************************************/
235
236const 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
257struct 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
276size_t md_longopts_size = sizeof (md_longopts);
277
278int
279md_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
363void
364md_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
385static valueT md_chars_to_number (char *buf, int n);
386valueT
387md_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 */
405static struct pseudo_func *
406kvx_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 */
417static struct pseudo_func *
418kvx_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
431static void
432supported_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 */
457static int
458insert_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 */
686static void
687assemble_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 */
747static void
748emit_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 */
821void
822md_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
878err:
879  ignore_rest_of_line ();
880}
881
882/*
883 * Return the Bundling type for an insn.
884 */
885static int
886find_bundling (const struct kvxinsn * insn)
887{
888  return insn->opdef->bundling;
889}
890
891static int
892find_reservation (const struct kvxinsn * insn)
893{
894  return insn->opdef->reservation;
895}
896
897static struct kvxopc *
898assemble_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 */
960static int ATTRIBUTE_UNUSED
961insn_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
1011static void
1012kvx_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.  */
1083static int
1084kvxinsn_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
1097static void
1098kvx_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
1238static void
1239kvx_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 */
1274void
1275md_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
1398static void
1399kvx_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
1441static int
1442kvxop_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
1463static int
1464print_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
1471static void
1472declare_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
1481void
1482md_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
1625static bfd_boolean
1626signed_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
1639void
1640md_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 */
1834int
1835kvx_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.  */
1867void
1868kvx_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
1910arelent *
1911tc_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
2007valueT
2008md_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
2021int
2022md_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
2028void
2029md_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
2036symbolS *
2037md_undefined_symbol (char *name ATTRIBUTE_UNUSED)
2038{
2039  return 0;
2040}
2041
2042const char *
2043md_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
2054long
2055md_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
2067static symbolS *last_proc_sym = NULL;
2068static int update_last_proc_sym = 0;
2069
2070void
2071kvx_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
2091void
2092kvx_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 */
2106void
2107kvx_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
2131void
2132kvx_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
2197static void
2198kvx_check_resources (int f)
2199{
2200  env.opts.check_resource_usage = f;
2201}
2202
2203/** called before write_object_file */
2204void
2205kvx_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
2227static void
2228kvx_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
2303static int proc_endp_status = 0;
2304
2305static void
2306kvx_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
2389static void
2390kvx_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
2426int
2427kvx_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
2468int
2469kvx_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
2531static void
2532kvx_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. */
2575void
2576kvx_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
2603ATTRIBUTE_UNUSED
2604static void
2605print_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
2647void
2648kvx_cfi_frame_initial_instructions (void)
2649{
2650  cfi_add_CFA_def_cfa (KVX_SP_REGNO, 0);
2651}
2652
2653int
2654kvx_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