]>
git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - gas/config/kvx-parse.c
1 /* kvx-parse.c -- Recursive decent parser driver for the KVX ISA
3 Copyright (C) 2009-2023 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/>. */
28 #include <elf/kvx_elfids.h>
29 #include "kvx-parse.h"
34 struct node_list_s
*nxt
;
40 struct node_list_s
*succs
;
47 has_relocation_of_size (const struct kvx_reloc
**relocs
)
49 const int symbol_size
= env
.params
.arch_size
;
52 * This is a bit hackish: in case of PCREL here, it means we are
53 * trying to fit a symbol in the insn, not a pseudo function
54 * (eg. @gotaddr, ...).
55 * We don't want to use a GOTADDR (pcrel) in any insn that tries to fit a symbol.
56 * One way to filter out these is to use the following assumption:
57 * - Any insn that accepts a pcrel immediate has only one immediate variant.
59 * - call accepts only a pcrel27 -> allow pcrel reloc here
60 * - cb accepts only a pcrel17 -> allow pcrel reloc here
61 * - addd accepts signed10,37,64 -> deny pcrel reloc here
63 * The motivation here is to prevent the function to allow a 64bits
64 * symbol in a 37bits variant of any ALU insn (that would match with
65 * the GOTADDR 37bits reloc switch case below)
71 struct kvx_reloc
**relocs_it
= (struct kvx_reloc
**) relocs
;
72 int has_only_one_p
= relocs
[0] && !relocs
[1];
76 switch ((*relocs_it
)->relative
)
78 /* An absolute reloc needs a full size symbol reloc */
80 if ((*relocs_it
)->bitsize
>= symbol_size
)
84 /* Most likely relative jumps. Let something else check size is
85 OK. We don't currently have several relocations for such insns */
91 /* These relocations should be handled elsewhere with pseudo functions */
105 kvx_get_pseudo_func2 (symbolS
* sym
, struct kvx_reloc
**relocs
);
107 kvx_get_pseudo_func2 (symbolS
*sym
, struct kvx_reloc
**relocs
)
112 struct kvx_reloc
**relocs_it
= (struct kvx_reloc
**) relocs
;
114 for (int i
= 0; i
< 26; i
++)
116 if (sym
== kvx_core_info
->pseudo_funcs
[i
].sym
)
121 if (*relocs_it
== kvx_core_info
->pseudo_funcs
[i
].pseudo_relocs
.kreloc
122 && (env
.params
.arch_size
== (int) kvx_core_info
->pseudo_funcs
[i
].pseudo_relocs
.avail_modes
123 || kvx_core_info
->pseudo_funcs
[i
].pseudo_relocs
.avail_modes
== PSEUDO_ALL
))
124 return &kvx_core_info
->pseudo_funcs
[i
];
137 insert_in_succ_list (struct node_s
*node
, struct node_s
*base
)
139 struct node_list_s
*new_hd
= NULL
;
140 if (!(new_hd
= calloc (1, sizeof (*new_hd
))))
144 new_hd
->nxt
= base
->succs
;
151 make_node (const char *str
, int len
)
153 struct node_s
*n
= NULL
;
154 if (!(n
= calloc (1, sizeof (*n
))))
159 if (!(n
->val
= calloc (n
->len
+ 1, sizeof (*n
->val
))))
162 strncpy (n
->val
, str
, n
->len
);
173 insert (const char *str
, struct node_s
*node
)
176 int len
= strlen (str
);
180 struct node_s
*n
= make_node (str
, len
);
181 n
->succs
= insert_in_succ_list (NULL
, n
);
185 while (i
< len
&& i
< node
->len
&& str
[i
] == node
->val
[i
])
188 /* The strings share a prefix. */
189 if (i
< len
&& i
< node
->len
)
191 /* Split the current node on that common prefix. */
193 /* Create a new node with only the unshared suffix, and makes it inherit
194 the successor of the node under consideration. */
195 struct node_s
*suf
= make_node (node
->val
+ i
, node
->len
- i
);
196 suf
->succs
= node
->succs
;
197 suf
->nb_succs
= node
->nb_succs
;
198 /* Insert the remainder on the other branch */
199 struct node_s
*rem
= make_node (str
+ i
, len
- i
);
200 rem
->succs
= insert_in_succ_list (NULL
, rem
);
206 node
->succs
= insert_in_succ_list (suf
, node
);
207 node
->succs
= insert_in_succ_list (rem
, node
);
211 /* str is a strict prefix of node->val */
212 if (i
== len
&& i
< node
->len
)
214 /* Split the current node at position */
215 struct node_s
*suf
= make_node (node
->val
+ i
, node
->len
- i
);
216 suf
->succs
= node
->succs
;
217 suf
->nb_succs
= node
->nb_succs
;
220 /* Insert an empty leaf */
223 node
->succs
= insert_in_succ_list (NULL
, node
);
224 node
->succs
= insert_in_succ_list (suf
, node
);
228 /* node->val is a prefix of str */
231 /* Find a successor of node into which the remainder can be inserted. */
232 struct node_list_s
*cur_succ
= node
->succs
;
235 struct node_s
*n
= cur_succ
->node
;
236 if (n
&& n
->val
&& n
->val
[0] == str
[i
])
238 cur_succ
->node
= insert (str
+ i
, cur_succ
->node
);
241 cur_succ
= cur_succ
->nxt
;
243 /* No successor shares a common prefix */
244 if (cur_succ
== NULL
)
246 struct node_s
*suf
= make_node (str
+ i
, len
- i
);
247 suf
->succs
= insert_in_succ_list (NULL
, suf
);
248 node
->succs
= insert_in_succ_list (suf
, node
);
258 free_node (struct node_s
*node
)
265 struct node_list_s
*cur_succ
= node
->succs
;
266 struct node_list_s
*tmp
= NULL
;
267 while ((tmp
= cur_succ
))
269 struct node_s
*n
= cur_succ
->node
;
271 free_node (n
), n
= NULL
;
272 cur_succ
= cur_succ
->nxt
;
279 #define max(a,b) (((a)>(b))?(a):(b))
282 longest_match (const char *str
, int len
, struct node_s
*node
)
286 struct node_s
*cur
= node
;
290 if (i
+ cur
->len
> len
291 || strncmp (str
+ i
, cur
->val
, max(0, cur
->len
)))
295 struct node_list_s
*cur_succ
= cur
->succs
;
299 struct node_s
*n
= cur_succ
->node
;
302 else if (n
->val
[0] == str
[i
])
304 cur_succ
= cur_succ
->nxt
;
311 __attribute__((unused
))
313 dump_graph_1 (FILE *fd
, struct node_s
*node
, int id
)
315 struct node_list_s
*cur_succ
= node
->succs
;
319 fprintf (fd
, "\t%d [label=\"%s\"];\n", id
, node
->val
);
323 if (cur_succ
->node
== NULL
)
324 fprintf (fd
, "\t%d -> \"()\";\n", id
);
327 fprintf (fd
, "\t%d [label=\"%s\"];\n",
328 node
->nb_succs
* id
+ i
, cur_succ
->node
->val
);
329 fprintf (fd
, "\t%d -> %d;\n", id
, node
->nb_succs
* id
+ i
);
330 dump_graph_1 (fd
, cur_succ
->node
, node
->nb_succs
* id
+ i
);
333 cur_succ
= cur_succ
->nxt
;
337 __attribute__((unused
))
339 dump_graph (char *name
, char *path
, struct node_s
*node
)
341 FILE *fd
= fopen (path
, "w");
342 fprintf (fd
, "digraph %s {\n", name
);
344 dump_graph_1 (fd
, node
, 1);
350 __attribute__((unused
))
352 print_n (const char *str
, int n
)
354 for (int i
= 0 ; i
< n
; ++i
)
362 __attribute__((unused
))
364 printf_debug (int lvl
, const char *fmt
, ...)
367 if (debug_level
>= lvl
)
370 va_start (args
, fmt
);
371 ret
= vprintf (fmt
, args
);
381 char delims
[] = { '[', ']', '?', ',', '=' };
382 int nb_delims
= sizeof (delims
) / (sizeof (*delims
));
383 for (int i
= 0; i
< nb_delims
; ++i
)
389 __attribute__((unused
))
391 print_token (struct token_s token
, char *buf
, int bufsz
)
393 for (int i
= 0; i
< token
.end
- token
.begin
&& i
< bufsz
; ++i
)
394 buf
[i
] = token
.insn
[token
.begin
+ i
];
395 for (int i
= token
.end
- token
.begin
; i
< bufsz
; ++i
)
400 promote_token (struct token_s tok
)
402 int64_t cur_class
= tok
.class_id
& -tok
.class_id
;
403 switch (tok
.category
)
407 return (cur_class
!= tok
.class_id
)
408 ? tok
.class_id
^ cur_class
412 expressionS exp
= { 0 };
413 char *ilp_save
= input_line_pointer
;
414 input_line_pointer
= tok
.insn
+ tok
.begin
;
416 input_line_pointer
= ilp_save
;
417 int64_t new_class_id
= tok
.class_id
;
418 int64_t old_class_id
= tok
.class_id
;
419 while (((new_class_id
= env
.promote_immediate (old_class_id
))
421 && ((exp
.X_op
== O_symbol
422 && !(has_relocation_of_size
423 (str_hash_find (env
.reloc_hash
,
424 TOKEN_NAME (new_class_id
)))))
425 || (exp
.X_op
== O_pseudo_fixup
426 && !(kvx_get_pseudo_func2
428 str_hash_find (env
.reloc_hash
,
429 TOKEN_NAME (new_class_id
)))))))
430 old_class_id
= new_class_id
;
439 is_insn (const struct token_s
*token
, struct token_class
*classes
)
443 int tok_sz
= token
->end
- token
->begin
;
444 char *tok
= token
->insn
+ token
->begin
;
445 while (!res
&& classes
[i
].class_values
!= NULL
)
447 res
= !strncmp (classes
[i
].class_values
[0], tok
, tok_sz
);
455 get_token_class (struct token_s
*token
, struct token_classes
*classes
, int insn_p
, int modifier_p
)
459 int tok_sz
= token
->end
- token
->begin
;
460 char *tok
= token
->insn
+ token
->begin
;
461 expressionS exp
= {0};
466 struct token_class
*class;
469 class = classes
->reg_classes
;
470 token
->category
= CAT_REGISTER
;
472 else if (modifier_p
&& tok
[0] == '.')
474 class = classes
->mod_classes
;
475 token
->category
= CAT_MODIFIER
;
477 else if (isdigit (tok
[0]) || tok
[0] == '+' || tok
[0] == '-')
479 class = classes
->imm_classes
;
480 token
->category
= CAT_IMMEDIATE
;
481 char *ilp_save
= input_line_pointer
;
482 input_line_pointer
= tok
;
484 token
->val
= exp
.X_add_number
;
486 input_line_pointer
= ilp_save
;
488 else if (tok_sz
== 1 && is_delim (tok
[0]))
490 class = classes
->sep_classes
;
491 token
->category
= CAT_SEPARATOR
;
493 else if (insn_p
&& is_insn (token
, classes
->insn_classes
))
495 class = classes
->insn_classes
;
496 token
->category
= CAT_INSTRUCTION
;
500 /* We are in fact dealing with a symbol. */
501 class = classes
->imm_classes
;
502 token
->category
= CAT_IMMEDIATE
;
504 char *ilp_save
= input_line_pointer
;
505 input_line_pointer
= tok
;
508 /* If the symbol can be resolved easily takes it value now. Otherwise it
509 means that is either a symbol which will need a real relocation or an
510 internal fixup (ie, a pseudo-function, or a computation on symbols). */
511 if (exp
.X_op
!= O_symbol
&& exp
.X_op
!= O_pseudo_fixup
)
513 token
->val
= exp
.X_add_number
;
517 input_line_pointer
= ilp_save
;
520 if (class == classes
->imm_classes
)
525 : strtoull (tok
+ (tok
[0] == '-') + (tok
[0] == '+'), NULL
, 0));
527 int64_t pval
= val
< 0 ? -uval
: uval
;
528 int neg_power2_p
= val
< 0 && !(uval
& (uval
- 1));
529 unsigned len
= pval
? 8 * sizeof (pval
) - __builtin_clzll (pval
) : 0;
530 while (class[cur
].class_id
!= -1
531 && ((unsigned) (class[cur
].sz
< 0
532 ? -class[cur
].sz
- !neg_power2_p
533 : class[cur
].sz
) < len
534 || (exp
.X_op
== O_symbol
535 && !(has_relocation_of_size
536 (str_hash_find (env
.reloc_hash
,
537 TOKEN_NAME (class[cur
].class_id
)))))
538 || (exp
.X_op
== O_pseudo_fixup
539 && !(kvx_get_pseudo_func2
541 str_hash_find (env
.reloc_hash
,
542 TOKEN_NAME (class[cur
].class_id
)))))))
546 // if (exp.X_op == O_pseudo_fixup)
547 // token->val = (uintptr_t) !kvx_get_pseudo_func2 (exp.X_op_symbol, str_hash_find (env.reloc_hash, TOKEN_NAME (class[cur].class_id)));
554 for (int i
= 0; !found
&& i
< class[cur
].sz
; ++i
)
556 const char *ref
= class[cur
].class_values
[i
];
557 found
= ((long) strlen (ref
) == tok_sz
) && !strncmp (tok
, ref
, tok_sz
);
563 while (!found
&& class[cur
].class_id
!= -1);
568 token
->category
= CAT_IMMEDIATE
;
569 return token
->class_id
= classes
->imm_classes
[0].class_id
;
572 #define unset(w, rg) ((w) & (~(1ULL << ((rg) - env.fst_reg))))
573 if (class == classes
->reg_classes
&& !env
.opts
.allow_all_sfr
)
574 return token
->class_id
= unset (class[cur
].class_id
, env
.sys_reg
);
577 return token
->class_id
= class[cur
].class_id
;
581 read_token (struct token_s
*tok
)
583 int insn_p
= tok
->begin
== 0;
585 char *str
= tok
->insn
;
586 int *begin
= &tok
->begin
;
587 int *end
= &tok
->end
;
589 /* Eat up all leading spaces. */
590 while (str
[*begin
] && (str
[*begin
] == ' ' || str
[*begin
] == '\n'))
598 /* Special case, we're reading an instruction. Try to read as much as possible
599 as long as the prefix is a valid instruction. */
601 *end
+= longest_match (str
+ *begin
, strlen (str
+ *begin
), env
.insns
);
604 if (is_delim (str
[*begin
]))
607 get_token_class (tok
, env
.token_classes
, insn_p
, modifier_p
);
611 if (str
[*begin
] == '.' && !(*begin
> 0 && (str
[*begin
- 1] == ' ' || is_delim(str
[*begin
- 1]))))
614 /* This is a modifier or a register */
615 if (str
[*begin
] == '.' || str
[*begin
] == '$')
618 /* Stop when reaching the start of the new token. */
619 while (!(!str
[*end
] || is_delim (str
[*end
]) || str
[*end
] == ' ' || (modifier_p
&& str
[*end
] == '.')))
624 get_token_class (tok
, env
.token_classes
, insn_p
, modifier_p
);
628 /* Rewrite with as_bad. */
630 rule_expect_error (int rule_id
, char *buf
, int bufsz
__attribute__((unused
)))
635 pos
+= sprintf (buf
+ pos
, "expected one of [");
636 struct steering_rule
*rules
= env
.rules
[rule_id
].rules
;
637 while (rules
[i
].steering
!= -1)
639 if ((env
.opts
.allow_all_sfr
|| rules
[i
].steering
!= env
.sys_reg
)
640 && rules
[i
].steering
!= -3)
642 pos
+= sprintf (buf
+ pos
, "%s%s", comma
? ", " : "", TOKEN_NAME (rules
[i
].steering
));
647 pos
+= sprintf (buf
+ pos
, "].");
650 static struct token_list
*
651 create_token (struct token_s tok
, int len
, int loc
)
653 struct token_list
*tl
= calloc (1, sizeof *tl
);
654 int tok_sz
= tok
.end
- tok
.begin
;
655 tl
->tok
= calloc (tok_sz
+ 1, sizeof (char));
656 memcpy (tl
->tok
, tok
.insn
+ tok
.begin
, tok_sz
* sizeof (char));
658 tl
->class_id
= tok
.class_id
;
659 tl
->category
= tok
.category
;
667 print_token_list (struct token_list
*lst
)
669 struct token_list
*cur
= lst
;
672 printf_debug (1, "%s (%d : %s : %d) / ",
673 cur
->tok
, cur
->val
, TOKEN_NAME (cur
->class_id
), cur
->loc
);
676 printf_debug (1, "\n");
680 free_token_list (struct token_list
*tok_list
)
682 struct token_list
*cur
= tok_list
;
683 struct token_list
*tmp
;
693 static struct token_list
*
694 token_list_append (struct token_list
*lst1
, struct token_list
*lst2
)
702 struct token_list
*hd
= lst1
;
705 hd
->len
+= lst2
->len
;
709 hd
->len
+= lst2
->len
;
717 struct error_list
*nxt
;
720 static struct error_list
*
721 error_list_insert (int rule
, int loc
, struct error_list
*nxt
)
723 struct error_list
*n
= calloc (1, sizeof (*n
));
724 n
->loc
= loc
> 0 ? loc
- 1 : loc
;
731 free_error_list (struct error_list
*l
)
733 struct error_list
*tmp
, *cur_err
= l
;
734 while ((tmp
= cur_err
))
736 cur_err
= cur_err
->nxt
;
742 CLASS_ID (struct token_s tok
)
744 int offset
= __builtin_ctzll (tok
.class_id
& -tok
.class_id
);
745 switch (tok
.category
)
748 return env
.fst_reg
+ offset
;
750 return env
.fst_mod
+ offset
;
760 static struct token_list
*
761 parse_with_restarts (struct token_s tok
, int jump_target
, struct rule rules
[],
762 struct error_list
**errs
)
765 struct steering_rule
*cur_rule
= rules
[jump_target
].rules
;
767 if (!tok
.insn
[tok
.begin
])
770 if (CLASS_ID (tok
) == -1)
773 *errs
= error_list_insert (jump_target
, tok
.begin
, *errs
);
777 printf_debug (1, "\nEntering rule: %d (Trying to match: (%s)[%d])\n",
778 jump_target
, TOKEN_NAME (CLASS_ID (tok
)), CLASS_ID (tok
));
780 /* 1. Find a rule that can be used with the current token. */
782 while (cur_rule
[i
].steering
!= -1 && cur_rule
[i
].steering
!= CLASS_ID (tok
))
785 printf_debug (1, "steering: %d (%s), jump_target: %d, stack_it: %d\n",
786 cur_rule
[i
].steering
, TOKEN_NAME (cur_rule
[i
].steering
),
787 cur_rule
[i
].jump_target
, cur_rule
[i
].stack_it
);
789 struct token_s init_tok
= tok
;
792 if (cur_rule
[i
].jump_target
== -2 && cur_rule
[i
].stack_it
== -2)
794 /* We're reading eps. */
795 printf_debug (1, "successfully ignored: %s\n", TOKEN_NAME (jump_target
));
796 struct token_s tok_
=
797 { (char *)".", 0, 1, CAT_MODIFIER
, jump_target
, 0 };
798 return create_token (tok_
, 0, tok
.begin
);
800 else if (cur_rule
[i
].jump_target
== -1 && cur_rule
[i
].stack_it
== -1)
802 /* We're handling the rule for a terminal (not eps) */
803 if (cur_rule
[i
].steering
== CLASS_ID (tok
))
804 // && tok.begin != tok.end) -- only fails when eps is last, eg. fence.
806 /* We matched a token */
807 printf_debug (1, "matched %s\n", TOKEN_NAME (CLASS_ID (tok
)));
808 tok
.class_id
= CLASS_ID (tok
);
809 return create_token (tok
, 1, tok
.begin
);
813 /* This is a mandatory modifier */
814 *errs
= error_list_insert (jump_target
, tok
.begin
, *errs
);
819 /* Not on a terminal */
820 struct token_list
*fst_part
=
821 parse_with_restarts (tok
, cur_rule
[i
].jump_target
, rules
, errs
);
822 /* While parsing fails but there is hope since the current token can be
824 while (!fst_part
&& tok
.class_id
!= (int64_t) promote_token (tok
))
826 free_token_list (fst_part
);
827 tok
.class_id
= promote_token (tok
);
828 printf_debug (1, "> Restart with %s?\n", TOKEN_NAME (CLASS_ID (tok
)));
829 fst_part
= parse_with_restarts (tok
, cur_rule
[i
].jump_target
, rules
, errs
);
835 while (cur_rule
[i
].steering
!= CLASS_ID(tok
) && cur_rule
[i
].steering
!= -1)
837 if (cur_rule
[i
].steering
!= -1)
843 printf_debug (1, "fst_part == NULL (Exiting %d)\n", jump_target
);
847 for (int _
= 0; _
< fst_part
->len
; ++_
)
850 end_of_line
= !read_token (&tok
);
853 if (end_of_line
&& cur_rule
[i
].stack_it
== -1)
855 /* No more tokens and no more place to go */
856 printf_debug (1, "return fst_part.\n");
859 else if (!end_of_line
&& cur_rule
[i
].stack_it
== -1)
861 /* Too much tokens. */
862 printf_debug (1, "too much tokens\n");
863 *errs
= error_list_insert (cur_rule
[i
].stack_it
, tok
.begin
, *errs
);
866 else if (cur_rule
[i
].stack_it
== -1)
868 printf_debug (1, "return fst_part. (end of rule)\n");
872 printf_debug (1, "snd_part: Trying to match: %s\n", TOKEN_NAME (CLASS_ID (tok
)));
873 struct token_list
*snd_part
= parse_with_restarts (tok
, cur_rule
[i
].stack_it
, rules
, errs
);
874 while (!snd_part
&& tok
.class_id
!= (int64_t) promote_token (tok
))
876 tok
.class_id
= promote_token (tok
);
877 printf_debug (1, ">> Restart with %s?\n", TOKEN_NAME (CLASS_ID (tok
)));
878 snd_part
= parse_with_restarts (tok
, cur_rule
[i
].stack_it
, rules
, errs
);
883 free_token_list (fst_part
);
886 while (cur_rule
[i
].steering
!= CLASS_ID (tok
) && cur_rule
[i
].steering
!= -1)
888 if (cur_rule
[i
].steering
!= -1)
894 printf_debug (1, "snd_part == NULL (Exiting %d)\n", jump_target
);
898 printf_debug (1, "Exiting rule: %d\n", jump_target
,
899 TOKEN_NAME (CLASS_ID (tok
)), tok
.class_id
);
901 /* Combine fst & snd parts */
902 return token_list_append (fst_part
, snd_part
);
905 /* During the parsing the modifiers and registers are handled through pseudo
906 classes such that each register and modifier appears in at most one pseudo
907 class. Since the pseudo-classes are not correlated with how the modifiers
908 and registers are encoded we fix that after a successful match instead of
909 updating it many times during the parsing.
911 Currently, only assigning correct values to modifiers is of interest. The
912 real value of registers is computed in tc-kvx.c:insert_operand. */
915 assign_final_values (struct token_list
*lst
)
918 struct token_list
*cur
= lst
;
922 if (cur
->category
== CAT_MODIFIER
)
924 int idx
= cur
->class_id
- env
.fst_mod
;
926 for (int i
= 0 ; !found
&& kvx_modifiers
[idx
][i
]; ++i
)
927 if ((found
= !strcmp (cur
->tok
, kvx_modifiers
[idx
][i
])))
935 parse (struct token_s tok
)
939 struct error_list
*errs
= NULL
;
942 struct token_list
*tok_list
=
943 parse_with_restarts (tok
, 0, env
.rules
, &errs
);
947 struct error_list
*cur_err
= errs
;
950 if (cur_err
->loc
> error_char
)
952 error_char
= cur_err
->loc
;
953 error_code
= cur_err
->rule
;
955 cur_err
= cur_err
->nxt
;
959 free_error_list (errs
);
963 if (error_code
!= -1)
965 char buf
[256] = { 0 };
966 const char * msg
= "Unexpected token when parsing %s.";
967 for (int i
= 0; i
< (int) (strlen (msg
) + error_char
+ 1 - 4) ; ++i
)
969 buf
[strlen (msg
) + error_char
+ 1 - 4] = '^';
970 as_bad (msg
, tok
.insn
);
971 if (env
.opts
.diagnostics
)
974 char err_buf
[10000] = { 0 };
975 rule_expect_error (error_code
, err_buf
, 10000);
976 as_bad ("%s", err_buf
);
981 char buf
[256] = { 0 };
982 const char * msg
= "Extra token when parsing %s.";
983 for (int i
= 0; i
< (int) (strlen (msg
) + error_char
+ 1 - 4) ; ++i
)
985 buf
[strlen (msg
) + error_char
+ 1 - 4] = '^';
986 as_bad (msg
, tok
.insn
);
987 if (env
.opts
.diagnostics
)
988 as_bad ("%s\n", buf
);
993 printf_debug (1, "[PASS] Successfully matched %s\n", tok
.insn
);
994 assign_final_values (tok_list
);
995 // print_token_list (tok_list);
996 // free_token_list (tok_list);
1006 case ELF_KVX_CORE_KV3_1
:
1009 case ELF_KVX_CORE_KV3_2
:
1012 case ELF_KVX_CORE_KV4_1
:
1016 as_bad ("Unknown architecture");
1020 for (int i
= 0; env
.token_classes
->insn_classes
[i
].class_values
; ++i
)
1022 insert (env
.token_classes
->insn_classes
[i
].class_values
[0], env
.insns
);
1028 free_node (env
.insns
);