ld: Move the .note.build-id section to near the start of the memory map.
[binutils-gdb.git] / gas / config / tc-kvx.c
blobb864b95721fb3c82befbc926b790e153c3658dd0
1 /* tc-kvx.c -- Assemble for the KVX ISA
3 Copyright (C) 2009-2024 Free Software Foundation, Inc.
4 Contributed by Kalray SA.
6 This file is part of GAS.
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.
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.
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/>. */
22 #include "as.h"
23 #include "obstack.h"
24 #include "subsegs.h"
25 #include "tc-kvx.h"
26 #include "libiberty.h"
28 #include <assert.h>
29 #include <stdio.h>
30 #include <stdint.h>
31 #include <string.h>
32 #include <ctype.h>
34 #ifdef OBJ_ELF
35 #include "elf/kvx.h"
36 #include "dwarf2dbg.h"
37 #include "dw2gencfi.h"
38 #endif
40 #define D(args...) do { if(debug) fprintf(args); } while(0)
42 static void supported_cores (char buf[], size_t buflen);
44 #define NELEMS(a) ((int) (sizeof (a)/sizeof ((a)[0])))
46 #define STREQ(x,y) !strcmp(((x) ? (x) : ""), ((y) ? (y) : ""))
47 #define STRNEQ(x,y,n) !strncmp(((x) ? (x) : ""), ((y) ? (y) : ""),(n))
49 /* The PARALLEL_BIT is set to 0 when an instruction is the last of a bundle. */
50 #define PARALLEL_BIT (1u << 31)
52 /*TB begin*/
53 int size_type_function = 1;
54 /*TB end */
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
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
79 /* This string should contain position in string where error occured. */
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;
90 /***********************************************/
91 /* Generic Globals for GAS */
92 /***********************************************/
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;
102 /***********************************************/
103 /* Local Types */
104 /***********************************************/
106 /* a fix up record */
108 struct kvx_fixup
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;
118 /* a single assembled instruction record */
119 /* may include immediate extension words */
120 struct kvxinsn
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];
142 typedef void (*print_insn_t) (struct kvxopc * op);
143 static print_insn_t print_insn = NULL;
145 /* Set to TRUE when we assemble instructions. */
146 static bool assembling_insn = false;
148 #define NOIMMX -1
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;
156 static void
157 incr_immxcnt (void)
159 immxcnt++;
160 if (immxcnt >= KVXMAXBUNDLEWORDS)
161 as_bad ("Max immx number exceeded: %d", immxcnt);
164 static void set_byte_counter (asection * sec, int value);
165 static void
166 set_byte_counter (asection * sec, int value)
168 sec->target_index = value;
171 static int get_byte_counter (asection * sec);
173 get_byte_counter (asection * sec)
175 return sec->target_index;
178 const char *
179 kvx_target_format (void)
181 return env.params.arch_size == 64 ? "elf64-kvx" : "elf32-kvx";
184 /****************************************************/
185 /* ASSEMBLER Pseudo-ops. Some of this just */
186 /* extends the default definitions */
187 /* others are KVX specific */
188 /****************************************************/
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);
195 const pseudo_typeS md_pseudo_table[] = {
196 /* override default 2-bytes */
197 { "word", cons, 4 },
199 /* KVX specific */
200 { "dword", cons, 8 },
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 },
206 { "checkresources", kvx_check_resources, 1 },
207 { "nocheckresources", kvx_check_resources, 0 },
209 { "proc", kvx_proc, 1 },
210 { "endp", kvx_endp, 0 },
212 { "type", kvx_type, 0 },
214 #ifdef OBJ_ELF
215 { "file", dwarf2_directive_file, 0 },
216 { "loc", dwarf2_directive_loc, 0 },
217 #endif
218 { NULL, 0, 0 }
222 static int inside_bundle = 0;
224 /* Stores the labels inside bundles (typically debug labels) that need
225 to be postponed to the next bundle. */
226 struct label_fix
228 struct label_fix *next;
229 symbolS *sym;
230 } *label_fixes = 0;
232 /*****************************************************/
233 /* OPTIONS PROCESSING */
234 /*****************************************************/
236 const char *md_shortopts = "hV"; /* catted to std short options */
238 /* added to std long options */
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)
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 }
276 size_t md_longopts_size = sizeof (md_longopts);
279 md_parse_option (int c, const char *arg ATTRIBUTE_UNUSED)
281 int find_core = 0;
283 switch (c)
285 case 'h':
286 md_show_usage (stdout);
287 exit (EXIT_SUCCESS);
288 break;
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))
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];
305 find_core = 1;
306 break;
308 if (!find_core)
310 char buf[100];
311 supported_cores (buf, sizeof (buf));
312 as_fatal ("Specified arch not supported [%s]", buf);
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;
357 default:
358 return 0;
360 return 1;
363 void
364 md_show_usage (FILE * stream)
366 char buf[100];
367 supported_cores (buf, sizeof (buf));
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);
377 /**************************************************/
378 /* UTILITIES */
379 /**************************************************/
382 * Read a value from to the object file
385 static valueT md_chars_to_number (char *buf, int n);
386 valueT
387 md_chars_to_number (char *buf, int n)
389 valueT val = 0;
391 if (n > (int) sizeof (val) || n <= 0)
392 abort ();
394 while (n--)
396 val <<= 8;
397 val |= (buf[n] & 0xff);
400 return val;
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)
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;
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)
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];
428 return NULL;
431 static void
432 supported_cores (char buf[], size_t buflen)
434 buf[0] = '\0';
435 for (int i = 0; i < KVXNUMCORES; i++)
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)
442 strcat (buf, "|");
443 strcat (buf, kvx_core_info_table[i]->name);
448 /***************************************************/
449 /* ASSEMBLE AN INSTRUCTION */
450 /***************************************************/
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.
457 static int
458 insert_operand (struct kvxinsn *insn, struct kvx_operand *opdef,
459 struct token_list *tok)
461 uint64_t op = 0;
462 struct kvx_bitfield *bfields = opdef->bfield;
463 int bf_nb = opdef->bitfields;
464 int immx_ready = 0;
466 if (opdef->width == 0)
467 return 0;
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)
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)
491 #define chk_imm(core_, imm_) \
492 (env.params.core == ELF_KVX_CORE_## core_ && opdef->type == (imm_))
494 /* try to resolve the value */
496 switch (tok->category)
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:
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;
516 /* We are dealing with a pseudo-function. */
517 if (tok->tok[0] == '@')
519 if (insn->nfixups == 0)
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) */
530 /* Beware that immxbuf must be filled in the same order as relocs should be emitted. */
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)
536 add_fixup (insn, pf->pseudo_relocs.reloc_lo10, reloc_arg);
538 insn->immx0 = immxcnt;
539 add_immx (insn, 0, pf->pseudo_relocs.reloc_up27,
540 reloc_arg, 1, 1);
541 immx_ready = 1;
543 else if (pf->pseudo_relocs.reloc_type == S32_LO5_UP27)
545 add_fixup (insn, pf->pseudo_relocs.reloc_lo5, reloc_arg);
547 insn->immx0 = immxcnt;
548 add_immx (insn, 0, pf->pseudo_relocs.reloc_up27,
549 reloc_arg, 1, 1);
550 immx_ready = 1;
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");
557 if (pf->pseudo_relocs.reloc_type == S64_LO10_UP27_EX27)
559 insn->immx1 = immxcnt;
560 add_immx (insn, 0, pf->pseudo_relocs.reloc_ex, reloc_arg,
561 1, 1);
563 else if (pf->pseudo_relocs.reloc_type == S43_LO10_UP27_EX6)
564 add_fixup (insn, pf->pseudo_relocs.reloc_ex, reloc_arg);
567 else
569 if (exp.X_op == O_constant)
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;
577 else if (exp.X_op == O_subtract)
578 as_fatal ("O_subtract not supported.");
579 else
582 /* This is a symbol which needs a relocation. */
583 if (insn->nfixups == 0)
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))
597 add_fixup (insn, BFD_RELOC_KVX_S32_LO5, exp);
599 insn->immx0 = immxcnt;
600 add_immx (insn, 0, BFD_RELOC_KVX_S32_UP27, exp, 1, 1);
602 immx_ready = 1;
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))
612 add_fixup (insn, BFD_RELOC_KVX_S37_LO10, exp);
614 insn->immx0 = immxcnt;
615 add_immx (insn, 0, BFD_RELOC_KVX_S37_UP27, exp, 1, 1);
617 immx_ready = 1;
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))
623 add_fixup (insn, BFD_RELOC_KVX_S43_LO10, exp);
624 add_fixup (insn, BFD_RELOC_KVX_S43_EX6, exp);
626 insn->immx0 = immxcnt;
627 add_immx (insn, insn->words[1],
628 BFD_RELOC_KVX_S43_UP27, exp, 1, 1);
630 immx_ready = 1;
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))
636 add_fixup (insn, BFD_RELOC_KVX_S64_LO10, exp);
638 insn->immx0 = immxcnt;
639 add_immx (insn, insn->words[1],
640 BFD_RELOC_KVX_S64_UP27, exp, 1, 1);
642 insn->immx1 = immxcnt;
643 add_immx (insn, insn->words[2],
644 BFD_RELOC_KVX_S64_EX27, exp, 1, 1);
646 immx_ready = 1;
648 else
649 as_fatal ("don't know how to generate a fixup record");
650 return immx_ready;
652 else
653 as_fatal ("No room for fixup ");
657 break;
658 default:
659 break;
662 for (int bf_idx = 0; bf_idx < bf_nb; bf_idx++)
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;
674 return immx_ready;
676 #undef chk_imm
677 #undef add_immx
678 #undef add_fixup
682 * Given a set of operands and a matching instruction,
683 * assemble it
686 static void
687 assemble_insn (const struct kvxopc * opcode, struct token_list *tok, struct kvxinsn *insn)
689 unsigned immx_ready = 0;
691 memset (insn, 0, sizeof (*insn));
692 insn->opdef = opcode;
693 for (int i = 0; i < opcode->wordcount; i++)
695 insn->words[i] = opcode->codewords[i].opcode;
696 insn->len += 1;
699 insn->immx0 = NOIMMX;
700 insn->immx1 = NOIMMX;
702 struct token_list *tok_ = tok;
703 struct kvx_operand **format = (struct kvx_operand **) opcode->format;
705 while (tok_)
707 int ret = insert_operand (insn, *format, tok_);
708 immx_ready |= ret;
709 while ((tok_ = tok_->next) && tok_->category == CAT_SEPARATOR);
710 format++;
713 // Handle immx if insert_operand did not already take care of that
714 if (!immx_ready)
716 for (int i = 0; i < opcode->wordcount; i++)
718 if (opcode->codewords[i].flags & kvxOPCODE_FLAG_IMMX0)
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 ();
727 if (opcode->codewords[i].flags & kvxOPCODE_FLAG_IMMX1)
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 ();
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.
744 * Only handles main syllables of bundle. Immediate extensions are
745 * handled by insert_operand.
747 static void
748 emit_insn (struct kvxinsn * insn, int insn_pos, int stopflag)
750 char *f;
751 unsigned int image;
753 /* if we are listing, attach frag to previous line. */
754 if (listing)
755 listing_prev_line ();
757 /* Update text size for lane parity checking. */
758 set_byte_counter (now_seg, (get_byte_counter (now_seg) + (insn->len * 4)));
760 /* allocate space in the fragment. */
761 f = frag_more (insn->len * 4);
763 /* spit out bits. */
764 for (int i = 0; i < insn->len; i++)
766 image = insn->words[i];
768 /* Handle bundle parallel bit. */ ;
769 if ((i == insn->len - 1) && stopflag)
770 image &= ~PARALLEL_BIT;
771 else
772 image |= PARALLEL_BIT;
774 /* Emit the instruction image. */
775 md_number_to_chars (f + (i * 4), image, 4);
778 /* generate fixup records */
780 for (int i = 0; i < insn->nfixups; i++)
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;
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.
793 assert (!(insn_pos == -1 && pcrel));
794 if (pcrel && insn_pos > 0)
795 insn->fixup[i].exp.X_add_number += insn_pos * 4;
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);
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
812 fixup->fx_no_overflow = 1;
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)
824 /* enum pseudo_type pseudo_type; */
825 /* char *name = NULL; */
826 size_t len;
827 int ch, i;
829 switch (*input_line_pointer)
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)
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]))
843 input_line_pointer += len;
844 break;
847 SKIP_WHITESPACE ();
848 if (*input_line_pointer != '(')
850 as_bad ("Expected '('");
851 goto err;
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++ != ')')
859 as_bad ("Missing ')'");
860 goto err;
862 if (!kvx_core_info->pseudo_funcs[i].pseudo_relocs.has_no_arg)
864 if (e->X_op != O_symbol)
865 as_fatal ("Illegal combination of relocation functions");
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;
873 default:
874 break;
876 return;
878 err:
879 ignore_rest_of_line ();
883 * Return the Bundling type for an insn.
885 static int
886 find_bundling (const struct kvxinsn * insn)
888 return insn->opdef->bundling;
891 static int
892 find_reservation (const struct kvxinsn * insn)
894 return insn->opdef->reservation;
897 static struct kvxopc *
898 assemble_tokens (struct token_list *tok_list)
900 assert (tok_list != NULL);
901 struct token_list *toks = tok_list;
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.");
908 /* TODO: Merge */
909 struct kvxinsn *insn;
910 insn = insbuf + insncnt;
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;
916 opcode = toks->tok;
917 toks = toks->next;
919 while (toks && toks->category == CAT_SEPARATOR)
920 toks = toks->next;
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;
926 struct token_list *toks_ = toks;
928 while (!format && format_tbl && STREQ (opcode, format_tbl->as_op))
930 for (int i = 0 ; toks_ && format_tbl->format[i]
931 && toks_->class_id == format_tbl->format[i]->type ;)
933 toks_ = toks_->next;
934 while (toks_ && toks_->category == CAT_SEPARATOR)
935 toks_ = toks_->next;
936 i += 1;
939 if (!toks_)
940 format = format_tbl;
941 else
943 toks_ = toks;
944 format_tbl++;
948 assert (format != NULL);
950 assemble_insn (format, toks, insn);
951 insncnt++;
953 return NULL;
957 * Write in buf at most buf_size.
958 * Returns the number of writen characters.
960 static int ATTRIBUTE_UNUSED
961 insn_syntax (struct kvxopc * op, char *buf, int buf_size)
963 int chars = snprintf (buf, buf_size, "%s ", op->as_op);
964 const char *fmtp = op->fmtstring;
965 char ch = 0;
967 for (int i = 0; op->format[i]; i++)
969 int type = op->format[i]->type;
970 const char *type_name = TOKEN_NAME (type);
971 int offset = 0;
973 for (int j = 0 ; type_name[j] ; ++j)
974 if (type_name[j] == '_')
975 offset = j + 1;
977 /* Print characters in the format string up to the following * % or nul. */
978 while ((chars < buf_size) && (ch = *fmtp) && ch != '%')
980 buf[chars++] = ch;
981 fmtp++;
984 /* Skip past %s */
985 if (ch == '%')
987 ch = *fmtp++;
988 fmtp++;
991 chars += snprintf (&buf[chars], buf_size - chars, "%s", type_name + offset);
994 /* Print trailing characters in the format string, if any */
995 while ((chars < buf_size) && (ch = *fmtp))
997 buf[chars++] = ch;
998 fmtp++;
1001 if (chars < buf_size)
1002 buf[chars++] = '\0';
1003 else
1004 buf[buf_size - 1] = '\0';
1006 return chars;
1009 #define ASM_CHARS_MAX (71)
1011 static void
1012 kvx_print_insn (struct kvxopc * op ATTRIBUTE_UNUSED)
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 = "";
1019 for (int i = chars - 1; i < ASM_CHARS_MAX - 1; i++)
1020 asm_str[i] = '-';
1022 /* This is a hack which works because the Bundling is the same for all cores
1023 for now. */
1024 switch ((int) op->bundling)
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);
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.");
1077 printf ("%s | syllables: %d | type: %s | mode: %s bits\n", asm_str,
1078 op->wordcount, insn_type, insn_mode);
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)
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);
1097 static void
1098 kvx_reorder_bundle (struct kvxinsn *bundle_insn[], int bundle_insncnt)
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;
1105 memset (issued, 0, sizeof (issued));
1106 for (int i = 0; i < bundle_insncnt; i++)
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))
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])
1136 issued[EXU_ALU0] = kvxinsn;
1137 tag = Modifier_kv3_v1_exunum_ALU0;
1138 exu = EXU_ALU0;
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])
1148 issued[EXU_ALU0] = kvxinsn;
1149 tag = Modifier_kv3_v1_exunum_ALU0;
1150 exu = EXU_ALU0;
1152 else if (!issued[EXU_ALU1])
1154 issued[EXU_ALU1] = kvxinsn;
1155 tag = Modifier_kv3_v1_exunum_ALU1;
1156 exu = EXU_ALU1;
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])
1166 issued[EXU_MAU] = kvxinsn;
1167 tag = Modifier_kv3_v1_exunum_MAU;
1168 exu = EXU_MAU;
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])
1178 issued[EXU_LSU] = kvxinsn;
1179 tag = Modifier_kv3_v1_exunum_LSU;
1180 exu = EXU_LSU;
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])
1191 issued[EXU_ALU0] = kvxinsn;
1192 tag = Modifier_kv3_v1_exunum_ALU0;
1193 exu = EXU_ALU0;
1195 else if (!issued[EXU_ALU1])
1197 issued[EXU_ALU1] = kvxinsn;
1198 tag = Modifier_kv3_v1_exunum_ALU1;
1199 exu = EXU_ALU1;
1201 else if (!issued[EXU_MAU])
1203 issued[EXU_MAU] = kvxinsn;
1204 tag = Modifier_kv3_v1_exunum_MAU;
1205 exu = EXU_MAU;
1207 else if (!issued[EXU_LSU])
1209 issued[EXU_LSU] = kvxinsn;
1210 tag = Modifier_kv3_v1_exunum_LSU;
1211 exu = EXU_LSU;
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));
1219 if (tag >= 0)
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);
1228 int i;
1229 for (i = 0, exu = 0; exu < EXU__; exu++)
1231 if (issued[exu])
1232 bundle_insn[i++] = issued[exu];
1234 if (i != bundle_insncnt)
1235 as_fatal ("Mismatch between bundle and issued instructions");
1238 static void
1239 kvx_check_resource_usage (struct kvxinsn **bundle_insn, int bundle_insncnt)
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));
1248 for (int i = 0; i < bundle_insncnt; i++)
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];
1257 for (int i = 0; i < kvx_core_info->reservation_table_lines; i++)
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])
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]);
1268 free (resources_used);
1272 * Called by core to assemble a single line
1274 void
1275 md_assemble (char *line)
1277 char *line_cursor = line;
1279 if (get_byte_counter (now_seg) & 3)
1280 as_fatal ("code segment not word aligned in md_assemble");
1282 while (line_cursor && line_cursor[0] && (line_cursor[0] == ' '))
1283 line_cursor++;
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)
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;
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++)
1306 insbuf[j].order = j;
1307 bundle_insn[bundle_insncnt++] = &insbuf[j];
1308 syllables += insbuf[j].len;
1311 if (syllables + immxcnt > KVXMAXBUNDLEWORDS)
1312 as_fatal ("Bundle has too many syllables : %d instead of %d",
1313 syllables + immxcnt, KVXMAXBUNDLEWORDS);
1315 if (env.opts.check_resource_usage)
1316 kvx_check_resource_usage (bundle_insn, bundle_insncnt);
1318 /* Reorder and check the bundle. */
1319 if (!env.opts.generate_illegal_code)
1321 /* Sort the bundle_insn in order of bundling. */
1322 qsort (bundle_insn, bundle_insncnt, sizeof (struct kvxinsn *), kvxinsn_compare);
1324 kvx_reorder_bundle (bundle_insn, bundle_insncnt);
1327 /* The ordering of the insns has been set correctly in bundle_insn. */
1328 for (int i = 0; i < bundle_insncnt; i++)
1330 emit_insn (bundle_insn[i], i, (i == bundle_insncnt + immxcnt - 1));
1331 bundle_insn[i]->written = 1;
1334 // Emit immx, ordering them by EXU tags, 0 to 3
1335 entry = 0;
1336 for (int tag = 0; tag < 4; tag++)
1338 for (int j = 0; j < immxcnt; j++)
1340 #define kv3_exunum2_fld(x) (int)(((unsigned int)(x) >> 27) & 0x3)
1341 if (kv3_exunum2_fld (immxbuf[j].words[0]) == tag)
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++;
1349 #undef kv3_exunum2_fld
1352 if (entry != immxcnt)
1353 as_fatal ("%d IMMX produced, only %d emitted.", immxcnt, entry);
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)
1364 struct label_fix *fix = label_fixes;
1366 label_fixes = fix->next;
1367 symbol_set_value_now (fix->sym);
1368 free (fix);
1371 insncnt = 0;
1372 immxcnt = 0;
1373 memset (immxbuf, 0, sizeof (immxbuf));
1375 return;
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);
1384 if (!tok_lst)
1385 return;
1387 /* Skip opcode */
1388 line_cursor += strlen (tok_lst->tok);
1390 assembling_insn = true;
1392 inside_bundle = 1;
1393 assemble_tokens (tok_lst);
1394 free_token_list (tok_lst);
1395 assembling_insn = false;
1398 static void
1399 kvx_set_cpu (void)
1401 if (!kvx_core_info)
1402 kvx_core_info = &kvx_kv3_v1_core_info;
1404 if (!kvx_registers)
1405 kvx_registers = kvx_kv3_v1_registers;
1407 if (!kvx_regfiles)
1408 kvx_regfiles = kvx_kv3_v1_regfiles;
1410 if (!kvx_modifiers)
1411 kvx_modifiers = kvx_kv3_v1_modifiers;
1413 if (env.params.core == -1)
1414 env.params.core = kvx_core_info->elf_core;
1416 int kvx_bfd_mach;
1417 print_insn = kvx_print_insn;
1419 switch (kvx_core_info->elf_core)
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);
1437 if (!bfd_set_arch_mach (stdoutput, TARGET_ARCH, kvx_bfd_mach))
1438 as_warn (_("could not set architecture and machine"));
1441 static int
1442 kvxop_compar (const void *a, const void *b)
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);
1448 if (res)
1449 return res;
1450 else
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;
1459 /***************************************************/
1460 /* INITIALIZE ASSEMBLER */
1461 /***************************************************/
1463 static int
1464 print_hash (void **slot, void *arg ATTRIBUTE_UNUSED)
1466 string_tuple_t *tuple = *((string_tuple_t **) slot);
1467 printf ("%s\n", tuple->key);
1468 return 1;
1471 static void
1472 declare_register (const char *name, int number)
1474 symbolS *regS = symbol_create (name, reg_section,
1475 &zero_address_frag, number);
1477 if (str_hash_insert (env.reg_hash, S_GET_NAME (regS), regS, 0) != NULL)
1478 as_fatal (_("duplicate %s"), name);
1481 void
1482 md_begin ()
1484 kvx_set_cpu ();
1487 * Declare register names with symbols
1490 env.reg_hash = str_htab_create ();
1492 for (int i = 0; i < kvx_regfiles[KVX_REGFILE_REGISTERS]; i++)
1493 declare_register (kvx_registers[i].name, kvx_registers[i].id);
1495 /* Sort optab, so that identical mnemonics appear consecutively */
1497 int nel;
1498 for (nel = 0; !STREQ ("", kvx_core_info->optab[nel].as_op); nel++)
1500 qsort (kvx_core_info->optab, nel, sizeof (kvx_core_info->optab[0]),
1501 kvxop_compar);
1504 /* The '?' is an operand separator */
1505 lex_type['?'] = 0;
1507 /* Create the opcode hash table */
1508 /* Each name should appear only once */
1510 env.opcode_hash = str_htab_create ();
1511 env.reloc_hash = str_htab_create ();
1514 struct kvxopc *op;
1515 const char *name = 0;
1516 for (op = kvx_core_info->optab; !(STREQ ("", op->as_op)); op++)
1518 /* enter in hash table if this is a new name */
1519 if (!(STREQ (name, op->as_op)))
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);
1527 for (int i = 0 ; op->format[i] ; ++i)
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);
1539 if (env.opts.dump_table)
1541 htab_traverse (env.opcode_hash, print_hash, NULL);
1542 exit (0);
1545 if (env.opts.dump_insn)
1547 for (struct kvxopc *op = kvx_core_info->optab; !(STREQ ("", op->as_op)); op++)
1548 print_insn (op);
1549 exit (0);
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
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);
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);
1577 for (int i = 0; i < kvx_core_info->nb_pseudo_funcs; ++i)
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);
1610 kvx_core_info->pseudo_funcs[i].sym = sym;
1614 /***************************************************/
1615 /* ASSEMBLER CLEANUP STUFF */
1616 /***************************************************/
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.
1622 This is from tc-aarch64.c
1625 static bfd_boolean
1626 signed_overflow (offsetT value, unsigned bits)
1628 offsetT lim;
1629 if (bits >= sizeof (offsetT) * 8)
1630 return FALSE;
1631 lim = (offsetT) 1 << (bits - 1);
1632 return (value < -lim || value >= lim);
1635 /***************************************************/
1636 /* ASSEMBLER FIXUP STUFF */
1637 /***************************************************/
1639 void
1640 md_apply_fix (fixS * fixP, valueT * valueP, segT segmentP ATTRIBUTE_UNUSED)
1642 char *const fixpos = fixP->fx_frag->fr_literal + fixP->fx_where;
1643 valueT value = *valueP;
1644 valueT image;
1645 arelent *rel;
1647 rel = (arelent *) xmalloc (sizeof (arelent));
1649 rel->howto = bfd_reloc_type_lookup (stdoutput, fixP->fx_r_type);
1650 if (rel->howto == NULL)
1652 as_fatal
1653 ("[md_apply_fix] unsupported relocation type (can't find howto)");
1656 /* Note whether this will delete the relocation. */
1657 if (fixP->fx_addsy == NULL && fixP->fx_pcrel == 0)
1658 fixP->fx_done = 1;
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)
1666 switch (fixP->fx_r_type)
1668 case BFD_RELOC_KVX_S37_TLS_LE_UP27:
1669 case BFD_RELOC_KVX_S37_TLS_LE_LO10:
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:
1675 case BFD_RELOC_KVX_S37_TLS_GD_LO10:
1676 case BFD_RELOC_KVX_S37_TLS_GD_UP27:
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:
1682 case BFD_RELOC_KVX_S37_TLS_IE_LO10:
1683 case BFD_RELOC_KVX_S37_TLS_IE_UP27:
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:
1689 case BFD_RELOC_KVX_S37_TLS_LD_LO10:
1690 case BFD_RELOC_KVX_S37_TLS_LD_UP27:
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:
1696 S_SET_THREAD_LOCAL (fixP->fx_addsy);
1697 break;
1698 default:
1699 break;
1703 /* If relocation has been marked for deletion, apply remaining changes */
1704 if (fixP->fx_done)
1706 switch (fixP->fx_r_type)
1708 case BFD_RELOC_8:
1709 case BFD_RELOC_16:
1710 case BFD_RELOC_32:
1711 case BFD_RELOC_64:
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;
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;
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;
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;
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;
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;
1755 case BFD_RELOC_KVX_S64_PCREL_LO10:
1756 case BFD_RELOC_KVX_S64_PCREL_UP27:
1757 case BFD_RELOC_KVX_S64_PCREL_EX27:
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;
1769 case BFD_RELOC_KVX_S64_GOTADDR_LO10:
1770 case BFD_RELOC_KVX_S64_GOTADDR_UP27:
1771 case BFD_RELOC_KVX_S64_GOTADDR_EX27:
1773 case BFD_RELOC_KVX_S43_GOTADDR_LO10:
1774 case BFD_RELOC_KVX_S43_GOTADDR_UP27:
1775 case BFD_RELOC_KVX_S43_GOTADDR_EX6:
1777 case BFD_RELOC_KVX_S37_GOTADDR_LO10:
1778 case BFD_RELOC_KVX_S37_GOTADDR_UP27:
1779 value = 0;
1780 /* Fallthrough */
1782 case BFD_RELOC_KVX_S32_UP27:
1784 case BFD_RELOC_KVX_S37_UP27:
1786 case BFD_RELOC_KVX_S43_UP27:
1788 case BFD_RELOC_KVX_S64_UP27:
1789 case BFD_RELOC_KVX_S64_EX27:
1790 case BFD_RELOC_KVX_S64_LO10:
1792 case BFD_RELOC_KVX_S43_TLS_LE_UP27:
1793 case BFD_RELOC_KVX_S43_TLS_LE_EX6:
1795 case BFD_RELOC_KVX_S37_TLS_LE_UP27:
1797 case BFD_RELOC_KVX_S37_GOTOFF_UP27:
1799 case BFD_RELOC_KVX_S43_GOTOFF_UP27:
1800 case BFD_RELOC_KVX_S43_GOTOFF_EX6:
1802 case BFD_RELOC_KVX_S43_GOT_UP27:
1803 case BFD_RELOC_KVX_S43_GOT_EX6:
1805 case BFD_RELOC_KVX_S37_GOT_UP27:
1807 case BFD_RELOC_KVX_S32_LO5:
1808 case BFD_RELOC_KVX_S37_LO10:
1810 case BFD_RELOC_KVX_S43_LO10:
1811 case BFD_RELOC_KVX_S43_EX6:
1813 case BFD_RELOC_KVX_S43_TLS_LE_LO10:
1814 case BFD_RELOC_KVX_S37_TLS_LE_LO10:
1816 case BFD_RELOC_KVX_S37_GOTOFF_LO10:
1817 case BFD_RELOC_KVX_S43_GOTOFF_LO10:
1819 case BFD_RELOC_KVX_S43_GOT_LO10:
1820 case BFD_RELOC_KVX_S37_GOT_LO10:
1822 default:
1823 as_fatal ("[md_apply_fix]:"
1824 "unsupported relocation type (type not handled : %d)",
1825 fixP->fx_r_type);
1828 xfree (rel);
1832 * Warning: Can be called only in fixup_segment() after fx_addsy field
1833 * has been updated by calling symbol_get_value_expression(...->X_add_symbol)
1836 kvx_validate_sub_fix (fixS * fixP)
1838 segT add_symbol_segment, sub_symbol_segment;
1840 switch (fixP->fx_r_type)
1842 case BFD_RELOC_8:
1843 case BFD_RELOC_16:
1844 case BFD_RELOC_32:
1845 if (fixP->fx_addsy != NULL)
1846 add_symbol_segment = S_GET_SEGMENT (fixP->fx_addsy);
1847 else
1848 return 0;
1849 if (fixP->fx_subsy != NULL)
1850 sub_symbol_segment = S_GET_SEGMENT (fixP->fx_subsy);
1851 else
1852 return 0;
1854 if ((strcmp (S_GET_NAME (fixP->fx_addsy),
1855 S_GET_NAME (fixP->fx_subsy)) == 0) &&
1856 (add_symbol_segment == sub_symbol_segment))
1857 return 1;
1858 break;
1859 default:
1860 break;
1863 return 0;
1866 /* This is called whenever some data item (not an instruction) needs a
1867 * fixup. */
1868 void
1869 kvx_cons_fix_new (fragS * f, int where, int nbytes, expressionS * exp,
1870 bfd_reloc_code_real_type code)
1872 if (exp->X_op == O_pseudo_fixup)
1874 exp->X_op = O_symbol;
1875 struct pseudo_func *pf =
1876 kvx_get_pseudo_func_data_scn (exp->X_op_symbol);
1877 assert (pf != NULL);
1878 code = pf->pseudo_relocs.single;
1880 if (code == BFD_RELOC_UNUSED)
1881 as_fatal ("Unsupported relocation");
1883 else
1885 switch (nbytes)
1887 case 1:
1888 code = BFD_RELOC_8;
1889 break;
1890 case 2:
1891 code = BFD_RELOC_16;
1892 break;
1893 case 4:
1894 code = BFD_RELOC_32;
1895 break;
1896 case 8:
1897 code = BFD_RELOC_64;
1898 break;
1899 default:
1900 as_fatal ("unsupported BFD relocation size %u", nbytes);
1901 break;
1904 fix_new_exp (f, where, nbytes, exp, 0, code);
1908 * generate a relocation record
1911 arelent *
1912 tc_gen_reloc (asection * sec ATTRIBUTE_UNUSED, fixS * fixp)
1914 arelent *reloc;
1915 bfd_reloc_code_real_type code;
1917 reloc = (arelent *) xmalloc (sizeof (arelent));
1919 reloc->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *));
1920 *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
1921 reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
1923 code = fixp->fx_r_type;
1924 if (code == BFD_RELOC_32 && fixp->fx_pcrel)
1925 code = BFD_RELOC_32_PCREL;
1926 reloc->howto = bfd_reloc_type_lookup (stdoutput, code);
1928 if (reloc->howto == NULL)
1930 as_bad_where (fixp->fx_file, fixp->fx_line,
1931 "cannot represent `%s' relocation in object file",
1932 bfd_get_reloc_code_name (code));
1933 return NULL;
1936 // if (!fixp->fx_pcrel != !reloc->howto->pc_relative)
1937 // {
1938 // as_fatal ("internal error? cannot generate `%s' relocation",
1939 // bfd_get_reloc_code_name (code));
1940 // }
1941 // assert (!fixp->fx_pcrel == !reloc->howto->pc_relative);
1943 reloc->addend = fixp->fx_offset;
1946 * Ohhh, this is ugly. The problem is that if this is a local global
1947 * symbol, the relocation will entirely be performed at link time, not
1948 * at assembly time. bfd_perform_reloc doesn't know about this sort
1949 * of thing, and as a result we need to fake it out here.
1952 /* GD I'm not sure what this is used for in the kvx case but it sure */
1953 /* messes up the relocs when emit_all_relocs is used as they are not */
1954 /* resolved with respect to a global sysmbol (e.g. .text), and hence */
1955 /* they are ALWAYS resolved at link time */
1956 /* FIXME FIXME */
1958 /* clarkes: 030827: This code (and the other half of the fix in write.c)
1959 * have caused problems with the PIC relocations.
1960 * The root problem is that bfd_install_relocation adds in to the reloc
1961 * addend the section offset of a symbol defined in the current object.
1962 * This causes problems on numerous other targets too, and there are
1963 * several different methods used to get around it:
1964 * 1. In tc_gen_reloc, subtract off the value that bfd_install_relocation
1965 * added. That is what we do here, and it is also done the
1966 * same way for alpha.
1967 * 2. In md_apply_fix, subtract off the value that bfd_install_relocation
1968 * will add. This is done on SH (non-ELF) and sparc targets.
1969 * 3. In the howto structure for the relocations, specify a
1970 * special function that does not return bfd_reloc_continue.
1971 * This causes bfd_install_relocaion to terminate before it
1972 * adds in the symbol offset. This is done on SH ELF targets.
1973 * Note that on ST200 we specify bfd_elf_generic_reloc as
1974 * the special function. This will return bfd_reloc_continue
1975 * only in some circumstances, but in particular if the reloc
1976 * is marked as partial_inplace in the bfd howto structure, then
1977 * bfd_elf_generic_reloc will return bfd_reloc_continue.
1978 * Some ST200 relocations are marked as partial_inplace
1979 * (this is an error in my opinion because ST200 always uses
1980 * a separate addend), but some are not. The PIC relocations
1981 * are not marked as partial_inplace, so for them,
1982 * bfd_elf_generic_reloc returns bfd_reloc_ok, and the addend
1983 * is not modified by bfd_install_relocation. The relocations
1984 * R_KVX_16 and R_KVX_32 are marked partial_inplace, and so for
1985 * these we need to correct the addend.
1986 * In the code below, the condition in the emit_all_relocs branch
1987 * (now moved to write.c) is the inverse of the condition that
1988 * bfd_elf_generic_reloc uses to short-circuit the code in
1989 * bfd_install_relocation that modifies the addend. The condition
1990 * in the else branch match the condition used in the alpha version
1991 * of tc_gen_reloc (see tc-alpha.c).
1992 * I do not know why we need to use different conditions in these
1993 * two branches, it seems to me that the condition should be the same
1994 * whether or not emit_all_relocs is true.
1995 * I also do not understand why it was necessary to move the emit_all_relocs
1996 * condition to write.c.
1999 if (S_IS_EXTERNAL (fixp->fx_addsy) &&
2000 !S_IS_COMMON (fixp->fx_addsy) && reloc->howto->partial_inplace)
2001 reloc->addend -= symbol_get_bfdsym (fixp->fx_addsy)->value;
2003 return reloc;
2006 /* Round up segment to appropriate boundary */
2008 valueT
2009 md_section_align (asection * seg ATTRIBUTE_UNUSED, valueT size)
2011 #ifndef OBJ_ELF
2012 /* This is not right for ELF; a.out wants it, and COFF will force
2013 * the alignment anyways. */
2014 int align = bfd_get_section_alignment (stdoutput, seg);
2015 valueT mask = ((valueT) 1 << align) - 1;
2016 return (size + mask) & ~mask;
2017 #else
2018 return size;
2019 #endif
2023 md_estimate_size_before_relax (register fragS * fragP ATTRIBUTE_UNUSED,
2024 segT segtype ATTRIBUTE_UNUSED)
2026 as_fatal ("estimate_size_before_relax called");
2029 void
2030 md_convert_frag (bfd * abfd ATTRIBUTE_UNUSED,
2031 asection * sec ATTRIBUTE_UNUSED,
2032 fragS * fragp ATTRIBUTE_UNUSED)
2034 as_fatal ("kvx convert_frag");
2037 symbolS *
2038 md_undefined_symbol (char *name ATTRIBUTE_UNUSED)
2040 return 0;
2043 const char *
2044 md_atof (int type ATTRIBUTE_UNUSED,
2045 char *litp ATTRIBUTE_UNUSED, int *sizep ATTRIBUTE_UNUSED)
2047 return ieee_md_atof (type, litp, sizep, TARGET_BYTES_BIG_ENDIAN);
2051 * calculate the base for a pcrel fixup
2052 * -- for relocation, we might need to add addend ?
2055 long
2056 md_pcrel_from (fixS * fixP)
2058 return (fixP->fx_where + fixP->fx_frag->fr_address);
2061 /************************************************************/
2062 /* Hooks into standard processing -- we hook into label */
2063 /* handling code to detect double ':' and we hook before */
2064 /* a line of code is processed to do some simple sed style */
2065 /* edits. */
2066 /************************************************************/
2068 static symbolS *last_proc_sym = NULL;
2069 static int update_last_proc_sym = 0;
2071 void
2072 kvx_frob_label (symbolS *sym)
2074 if (update_last_proc_sym)
2076 last_proc_sym = sym;
2077 update_last_proc_sym = 0;
2080 if (inside_bundle)
2082 struct label_fix *fix;
2083 fix = malloc (sizeof (*fix));
2084 fix->next = label_fixes;
2085 fix->sym = sym;
2086 label_fixes = fix;
2089 dwarf2_emit_label (sym);
2092 void
2093 kvx_check_label (symbolS *sym)
2095 /* Labels followed by a second semi-colon are considered external symbols. */
2096 if (*input_line_pointer == ':')
2098 S_SET_EXTERNAL (sym);
2099 input_line_pointer++;
2103 /* Emit single bundle nop. This is needed by .nop asm directive
2104 * Have to manage end of bundle done usually by start_line_hook
2105 * using BE pseudo op
2107 void
2108 kvx_emit_single_noop (void)
2110 char *nop;
2111 char *end_of_bundle;
2113 if (asprintf (&nop, "nop") < 0)
2114 as_fatal ("%s", xstrerror (errno));
2116 if (asprintf (&end_of_bundle, "be") < 0)
2117 as_fatal ("%s", xstrerror (errno));
2119 char *saved_ilp = input_line_pointer;
2120 md_assemble (nop);
2121 md_assemble (end_of_bundle);
2122 input_line_pointer = saved_ilp;
2123 free (nop);
2124 free (end_of_bundle);
2127 /* edit out some syntactic sugar that confuses GAS */
2128 /* input_line_pointer is guaranteed to point to the */
2129 /* the current line but may include text from following */
2130 /* lines. Thus, '\n' must be scanned for as well as '\0' */
2132 void
2133 kvx_md_start_line_hook (void)
2135 char *t;
2137 for (t = input_line_pointer; t && t[0] == ' '; t++);
2139 /* Detect illegal syntax patterns:
2140 * - two bundle ends on the same line: ;; ;;
2141 * - illegal token: ;;;
2143 if (t && (t[0] == ';') && (t[1] == ';'))
2145 char *tmp_t;
2146 bool newline_seen = false;
2148 if (t[2] == ';')
2149 as_fatal ("Syntax error: Illegal ;;; token");
2151 tmp_t = t + 2;
2153 while (tmp_t && tmp_t[0])
2155 while (tmp_t && tmp_t[0] &&
2156 ((tmp_t[0] == ' ') || (tmp_t[0] == '\n')))
2158 if (tmp_t[0] == '\n')
2159 newline_seen = true;
2160 tmp_t++;
2162 if (tmp_t[0] == ';' && tmp_t[1] == ';')
2164 /* if there's no newline between the two bundle stops
2165 * then raise a syntax error now, otherwise a strange error
2166 * message from read.c will be raised: "junk at end of line..."
2168 if (tmp_t[2] == ';')
2169 as_fatal ("Syntax error: Illegal ;;; token");
2171 if (!newline_seen)
2172 as_fatal ("Syntax error: More than one bundle stop on a line");
2173 newline_seen = false; /* reset */
2175 /* this is an empty bundle, transform it into an
2176 * empty statement */
2177 tmp_t[0] = ';';
2178 tmp_t[1] = ' ';
2180 tmp_t += 2;
2182 else
2183 break;
2187 /* check for bundle end */
2188 /* we transform these into a special opcode BE */
2189 /* because gas has ';' hardwired as a statement end */
2190 if (t && (t[0] == ';') && (t[1] == ';'))
2192 t[0] = 'B';
2193 t[1] = 'E';
2194 return;
2198 static void
2199 kvx_check_resources (int f)
2201 env.opts.check_resource_usage = f;
2204 /** called before write_object_file */
2205 void
2206 kvx_end (void)
2208 int newflags;
2210 if (!env.params.core_set)
2211 env.params.core = kvx_core_info->elf_core;
2213 /* (pp) the flags must be set at once */
2214 newflags = env.params.core | env.params.abi | env.params.pic_flags;
2216 if (env.params.arch_size == 64)
2217 newflags |= ELF_KVX_ABI_64B_ADDR_BIT;
2219 bfd_set_private_flags (stdoutput, newflags);
2221 cleanup ();
2223 if (inside_bundle && insncnt != 0)
2224 as_bad ("unexpected end-of-file while processing a bundle."
2225 " Please check that ;; is on its own line.");
2228 static void
2229 kvx_type (int start ATTRIBUTE_UNUSED)
2231 char *name;
2232 char c;
2233 int type;
2234 char *typename = NULL;
2235 symbolS *sym;
2236 elf_symbol_type *elfsym;
2238 c = get_symbol_name (&name);
2239 sym = symbol_find_or_make (name);
2240 elfsym = (elf_symbol_type *) symbol_get_bfdsym (sym);
2241 *input_line_pointer = c;
2243 if (!*S_GET_NAME (sym))
2244 as_bad (_("Missing symbol name in directive"));
2246 SKIP_WHITESPACE ();
2247 if (*input_line_pointer == ',')
2248 ++input_line_pointer;
2251 SKIP_WHITESPACE ();
2252 if (*input_line_pointer == '#'
2253 || *input_line_pointer == '@'
2254 || *input_line_pointer == '"' || *input_line_pointer == '%')
2255 ++input_line_pointer;
2257 /* typename = input_line_pointer; */
2258 /* c = get_symbol_end(); */
2259 c = get_symbol_name (&typename);
2261 type = 0;
2262 if (strcmp (typename, "function") == 0
2263 || strcmp (typename, "STT_FUNC") == 0)
2264 type = BSF_FUNCTION;
2265 else if (strcmp (typename, "object") == 0
2266 || strcmp (typename, "STT_OBJECT") == 0)
2267 type = BSF_OBJECT;
2268 else if (strcmp (typename, "tls_object") == 0
2269 || strcmp (typename, "STT_TLS") == 0)
2270 type = BSF_OBJECT | BSF_THREAD_LOCAL;
2271 else if (strcmp (typename, "common") == 0
2272 || strcmp (typename, "STT_COMMON") == 0)
2273 type = BSF_ELF_COMMON;
2274 else if (strcmp (typename, "gnu_unique_object") == 0
2275 || strcmp (typename, "STB_GNU_UNIQUE") == 0)
2277 elf_tdata (stdoutput)->has_gnu_osabi |= elf_gnu_osabi_unique;
2278 type = BSF_OBJECT | BSF_GNU_UNIQUE;
2280 else if (strcmp (typename, "notype") == 0
2281 || strcmp (typename, "STT_NOTYPE") == 0)
2283 #ifdef md_elf_symbol_type
2284 else if ((type = md_elf_symbol_type (typename, sym, elfsym)) != -1)
2286 #endif
2287 else
2288 as_bad (_("unrecognized symbol type \"%s\""), typename);
2290 *input_line_pointer = c;
2292 if (*input_line_pointer == '"')
2293 ++input_line_pointer;
2295 elfsym->symbol.flags |= type;
2296 symbol_get_bfdsym (sym)->flags |= type;
2298 demand_empty_rest_of_line ();
2301 #define ENDPROCEXTENSION "$endproc"
2302 #define MINUSEXPR ".-"
2304 static int proc_endp_status = 0;
2306 static void
2307 kvx_endp (int start ATTRIBUTE_UNUSED)
2309 char c;
2310 char *name;
2312 if (inside_bundle)
2313 as_warn (".endp directive inside a bundle.");
2314 /* function name is optionnal and is ignored */
2315 /* there may be several names separated by commas... */
2316 while (1)
2318 SKIP_WHITESPACE ();
2319 c = get_symbol_name (&name);
2320 (void) restore_line_pointer (c);
2321 SKIP_WHITESPACE ();
2322 if (*input_line_pointer != ',')
2323 break;
2324 ++input_line_pointer;
2326 demand_empty_rest_of_line ();
2328 if (!proc_endp_status)
2330 as_warn (".endp directive doesn't follow .proc -- ignoring ");
2331 return;
2334 proc_endp_status = 0;
2336 /* TB begin : add BSF_FUNCTION attribute to last_proc_sym symbol */
2337 if (size_type_function)
2339 if (!last_proc_sym)
2341 as_bad ("Cannot set function attributes (bad symbol)");
2342 return;
2345 /* last_proc_sym->symbol.flags |= BSF_FUNCTION; */
2346 symbol_get_bfdsym (last_proc_sym)->flags |= BSF_FUNCTION;
2347 /* Add .size funcname,.-funcname in order to add size
2348 * attribute to the current function */
2350 const int newdirective_sz =
2351 strlen (S_GET_NAME (last_proc_sym)) + strlen (MINUSEXPR) + 1;
2352 char *newdirective = malloc (newdirective_sz);
2353 char *savep = input_line_pointer;
2354 expressionS exp;
2356 memset (newdirective, 0, newdirective_sz);
2358 /* BUILD :".-funcname" expression */
2359 strcat (newdirective, MINUSEXPR);
2360 strcat (newdirective, S_GET_NAME (last_proc_sym));
2361 input_line_pointer = newdirective;
2362 expression (&exp);
2364 if (exp.X_op == O_constant)
2366 S_SET_SIZE (last_proc_sym, exp.X_add_number);
2367 if (symbol_get_obj (last_proc_sym)->size)
2369 xfree (symbol_get_obj (last_proc_sym)->size);
2370 symbol_get_obj (last_proc_sym)->size = NULL;
2373 else
2375 symbol_get_obj (last_proc_sym)->size =
2376 (expressionS *) xmalloc (sizeof (expressionS));
2377 *symbol_get_obj (last_proc_sym)->size = exp;
2380 /* just restore the real input pointer */
2381 input_line_pointer = savep;
2382 free (newdirective);
2385 /* TB end */
2387 last_proc_sym = NULL;
2390 static void
2391 kvx_proc (int start ATTRIBUTE_UNUSED)
2393 char c;
2394 char *name;
2395 /* there may be several names separated by commas... */
2396 while (1)
2398 SKIP_WHITESPACE ();
2399 c = get_symbol_name (&name);
2400 (void) restore_line_pointer (c);
2402 SKIP_WHITESPACE ();
2403 if (*input_line_pointer != ',')
2404 break;
2405 ++input_line_pointer;
2407 demand_empty_rest_of_line ();
2409 if (proc_endp_status)
2411 as_warn (".proc follows .proc -- ignoring");
2412 return;
2415 proc_endp_status = 1;
2417 /* this code emit a global symbol to mark the end of each function */
2418 /* the symbol emitted has a name formed by the original function name */
2419 /* concatenated with $endproc so if _foo is a function name the symbol */
2420 /* marking the end of it is _foo$endproc */
2421 /* It is also required for generation of .size directive in kvx_endp() */
2423 if (size_type_function)
2424 update_last_proc_sym = 1;
2428 kvx_force_reloc (fixS * fixP)
2430 symbolS *sym;
2431 asection *symsec;
2433 if (generic_force_reloc (fixP))
2434 return 1;
2436 switch (fixP->fx_r_type)
2438 case BFD_RELOC_KVX_32_GOTOFF:
2439 case BFD_RELOC_KVX_S37_GOTOFF_UP27:
2440 case BFD_RELOC_KVX_S37_GOTOFF_LO10:
2442 case BFD_RELOC_KVX_64_GOTOFF:
2443 case BFD_RELOC_KVX_S43_GOTOFF_UP27:
2444 case BFD_RELOC_KVX_S43_GOTOFF_LO10:
2445 case BFD_RELOC_KVX_S43_GOTOFF_EX6:
2447 case BFD_RELOC_KVX_32_GOT:
2448 case BFD_RELOC_KVX_64_GOT:
2449 case BFD_RELOC_KVX_S37_GOT_UP27:
2450 case BFD_RELOC_KVX_S37_GOT_LO10:
2452 case BFD_RELOC_KVX_GLOB_DAT:
2453 return 1;
2454 default:
2455 return 0;
2458 sym = fixP->fx_addsy;
2459 if (sym)
2461 symsec = S_GET_SEGMENT (sym);
2462 /* if (bfd_is_abs_section (symsec)) return 0; */
2463 if (!SEG_NORMAL (symsec))
2464 return 0;
2466 return 1;
2470 kvx_force_reloc_sub_same (fixS * fixP, segT sec)
2472 symbolS *sym;
2473 asection *symsec;
2474 const char *sec_name = NULL;
2476 if (generic_force_reloc (fixP))
2477 return 1;
2479 switch (fixP->fx_r_type)
2481 case BFD_RELOC_KVX_32_GOTOFF:
2482 case BFD_RELOC_KVX_S37_GOTOFF_UP27:
2483 case BFD_RELOC_KVX_S37_GOTOFF_LO10:
2485 case BFD_RELOC_KVX_64_GOTOFF:
2486 case BFD_RELOC_KVX_S43_GOTOFF_UP27:
2487 case BFD_RELOC_KVX_S43_GOTOFF_LO10:
2488 case BFD_RELOC_KVX_S43_GOTOFF_EX6:
2490 case BFD_RELOC_KVX_32_GOT:
2491 case BFD_RELOC_KVX_64_GOT:
2492 case BFD_RELOC_KVX_S37_GOT_UP27:
2493 case BFD_RELOC_KVX_S37_GOT_LO10:
2495 case BFD_RELOC_KVX_S37_LO10:
2496 case BFD_RELOC_KVX_S37_UP27:
2498 case BFD_RELOC_KVX_GLOB_DAT:
2499 return 1;
2501 default:
2502 return 0;
2505 sym = fixP->fx_addsy;
2506 if (sym)
2508 symsec = S_GET_SEGMENT (sym);
2509 /* if (bfd_is_abs_section (symsec)) return 0; */
2510 if (!SEG_NORMAL (symsec))
2511 return 0;
2514 * for .debug_arrange, .debug_frame, .eh_frame sections, containing
2515 * expressions of the form "sym2 - sym1 + addend", solve them even when
2516 * --emit-all-relocs is set. Otherwise, a relocation on two symbols
2517 * is necessary and fails at elf level. Binopt should not be impacted by
2518 * the resolution of this relocatable expression on symbols inside a
2519 * function.
2521 sec_name = segment_name (sec);
2522 if ((strcmp (sec_name, ".eh_frame") == 0) ||
2523 (strcmp (sec_name, ".except_table") == 0) ||
2524 (strncmp (sec_name, ".debug_", sizeof (".debug_")) == 0))
2525 return 0;
2527 return 1;
2530 /* Implement HANDLE_ALIGN. */
2532 static void
2533 kvx_make_nops (char *buf, bfd_vma bytes)
2535 bfd_vma i = 0;
2536 unsigned int j;
2538 static unsigned int nop_single = 0;
2540 if (!nop_single)
2542 const struct kvxopc *opcode =
2543 (struct kvxopc *) str_hash_find (env.opcode_hash, "nop");
2545 if (opcode == NULL)
2546 as_fatal
2547 ("internal error: could not find opcode for 'nop' during padding");
2549 nop_single = opcode->codewords[0].opcode;
2552 /* KVX instructions are always 4-bytes aligned. If we are at a position */
2553 /* that is not 4 bytes aligned, it means this is not part of an instruction, */
2554 /* so it is safe to use a zero byte for padding. */
2556 for (j = bytes % 4; j > 0; j--)
2557 buf[i++] = 0;
2559 for (j = 0; j < (bytes - i); j += 4)
2561 unsigned nop = nop_single;
2563 // nop has bundle end only if #4 nop or last padding nop.
2564 // Sets the parallel bit when neither conditions are matched.
2565 // 4*4 = biggest nop bundle we can get
2566 // 12 = offset when writting the last nop possible in a 4 nops bundle
2567 // bytes-i-4 = offset for the last 4-words in the padding
2568 if (j % (4 * 4) != 12 && j != (bytes - i - 4))
2569 nop |= PARALLEL_BIT;
2571 memcpy (buf + i + j, &nop, sizeof (nop));
2575 /* Pads code section with bundle of nops when possible, 0 if not. */
2576 void
2577 kvx_handle_align (fragS *fragP)
2579 switch (fragP->fr_type)
2581 case rs_align_code:
2583 bfd_signed_vma bytes = (fragP->fr_next->fr_address
2584 - fragP->fr_address - fragP->fr_fix);
2585 char *p = fragP->fr_literal + fragP->fr_fix;
2587 if (bytes <= 0)
2588 break;
2590 /* Insert zeros or nops to get 4 byte alignment. */
2591 kvx_make_nops (p, bytes);
2592 fragP->fr_fix += bytes;
2594 break;
2596 default:
2597 break;
2601 * This is just used for debugging
2604 ATTRIBUTE_UNUSED
2605 static void
2606 print_operand (expressionS * e, FILE * out)
2608 if (e)
2610 switch (e->X_op)
2612 case O_register:
2613 fprintf (out, "%s", kvx_registers[e->X_add_number].name);
2614 break;
2616 case O_constant:
2617 if (e->X_add_symbol)
2619 if (e->X_add_number)
2620 fprintf (out, "(%s + %d)", S_GET_NAME (e->X_add_symbol),
2621 (int) e->X_add_number);
2622 else
2623 fprintf (out, "%s", S_GET_NAME (e->X_add_symbol));
2625 else
2626 fprintf (out, "%d", (int) e->X_add_number);
2627 break;
2629 case O_symbol:
2630 if (e->X_add_symbol)
2632 if (e->X_add_number)
2633 fprintf (out, "(%s + %d)", S_GET_NAME (e->X_add_symbol),
2634 (int) e->X_add_number);
2635 else
2636 fprintf (out, "%s", S_GET_NAME (e->X_add_symbol));
2638 else
2639 fprintf (out, "%d", (int) e->X_add_number);
2640 break;
2642 default:
2643 fprintf (out, "o,ptype-%d", e->X_op);
2648 void
2649 kvx_cfi_frame_initial_instructions (void)
2651 cfi_add_CFA_def_cfa (KVX_SP_REGNO, 0);
2655 kvx_regname_to_dw2regnum (const char *regname)
2657 unsigned int regnum = -1;
2658 const char *p;
2659 char *q;
2661 if (regname[0] == 'r')
2663 p = regname + 1;
2664 regnum = strtoul (p, &q, 10);
2665 if (p == q || *q || regnum >= 64)
2666 return -1;
2668 return regnum;