]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - opcodes/or1k-asm.c
[binutils, ARM, 12/16] Scalar Low Overhead loop instructions for Armv8.1-M Mainline
[thirdparty/binutils-gdb.git] / opcodes / or1k-asm.c
CommitLineData
4162bb66 1/* DO NOT EDIT! -*- buffer-read-only: t -*- vi:set ro: */
87e6d782
NC
2/* Assembler interface for targets using CGEN. -*- C -*-
3 CGEN: Cpu tools GENerator
4
47b0e7ad
NC
5 THIS FILE IS MACHINE GENERATED WITH CGEN.
6 - the resultant file is machine generated, cgen-asm.in isn't
87e6d782 7
82704155 8 Copyright (C) 1996-2019 Free Software Foundation, Inc.
87e6d782 9
9b201bb5 10 This file is part of libopcodes.
87e6d782 11
9b201bb5 12 This library is free software; you can redistribute it and/or modify
47b0e7ad 13 it under the terms of the GNU General Public License as published by
9b201bb5 14 the Free Software Foundation; either version 3, or (at your option)
47b0e7ad 15 any later version.
87e6d782 16
9b201bb5
NC
17 It is distributed in the hope that it will be useful, but WITHOUT
18 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
19 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
20 License for more details.
87e6d782 21
47b0e7ad
NC
22 You should have received a copy of the GNU General Public License
23 along with this program; if not, write to the Free Software Foundation, Inc.,
24 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */
87e6d782 25
9b201bb5 26
87e6d782
NC
27/* ??? Eventually more and more of this stuff can go to cpu-independent files.
28 Keep that in mind. */
29
30#include "sysdep.h"
87e6d782
NC
31#include <stdio.h>
32#include "ansidecl.h"
33#include "bfd.h"
34#include "symcat.h"
73589c9d
CS
35#include "or1k-desc.h"
36#include "or1k-opc.h"
87e6d782 37#include "opintl.h"
fc7bc883 38#include "xregex.h"
fc05c67f 39#include "libiberty.h"
37111cc7 40#include "safe-ctype.h"
87e6d782 41
37111cc7 42#undef min
87e6d782 43#define min(a,b) ((a) < (b) ? (a) : (b))
37111cc7 44#undef max
87e6d782
NC
45#define max(a,b) ((a) > (b) ? (a) : (b))
46
47static const char * parse_insn_normal
ffead7ae 48 (CGEN_CPU_DESC, const CGEN_INSN *, const char **, CGEN_FIELDS *);
87e6d782 49\f
37111cc7 50/* -- assembler routines inserted here. */
87e6d782
NC
51
52/* -- asm.c */
53
47b0e7ad 54static const char * MISSING_CLOSING_PARENTHESIS = N_("missing `)'");
1c4f3780
RH
55static const char * INVALID_STORE_RELOC = N_("relocation invalid for store");
56static const char * INVALID_RELOC_TYPE = N_("internal relocation type invalid");
87e6d782 57
47b0e7ad 58#define CGEN_VERBOSE_ASSEMBLER_ERRORS
0e2ee3ca 59
73589c9d
CS
60static const char *
61parse_disp26 (CGEN_CPU_DESC cd,
c151b1c6
AM
62 const char ** strp,
63 int opindex,
c8e98e36 64 int opinfo ATTRIBUTE_UNUSED,
c151b1c6
AM
65 enum cgen_parse_operand_result * resultp,
66 bfd_vma * valuep)
87e6d782 67{
c8e98e36 68 const char *str = *strp;
73589c9d 69 const char *errmsg = NULL;
c8e98e36 70 bfd_reloc_code_real_type reloc = BFD_RELOC_OR1K_REL_26;
87e6d782 71
c8e98e36 72 if (strncasecmp (str, "plta(", 5) == 0)
73589c9d 73 {
c8e98e36
SH
74 *strp = str + 5;
75 reloc = BFD_RELOC_OR1K_PLTA26;
76 }
77 else if (strncasecmp (str, "plt(", 4) == 0)
78 {
79 *strp = str + 4;
80 reloc = BFD_RELOC_OR1K_PLT26;
81 }
82
83 errmsg = cgen_parse_address (cd, strp, opindex, reloc, resultp, valuep);
73589c9d 84
c8e98e36
SH
85 if (reloc != BFD_RELOC_OR1K_REL_26)
86 {
73589c9d 87 if (**strp != ')')
c8e98e36
SH
88 errmsg = MISSING_CLOSING_PARENTHESIS;
89 else
90 ++*strp;
91 }
92
93 return errmsg;
94}
95
96static const char *
97parse_disp21 (CGEN_CPU_DESC cd,
98 const char ** strp,
99 int opindex,
100 int opinfo ATTRIBUTE_UNUSED,
101 enum cgen_parse_operand_result * resultp,
102 bfd_vma * valuep)
103{
104 const char *str = *strp;
105 const char *errmsg = NULL;
106 bfd_reloc_code_real_type reloc = BFD_RELOC_OR1K_PCREL_PG21;
107
108 if (strncasecmp (str, "got(", 4) == 0)
109 {
110 *strp = str + 4;
111 reloc = BFD_RELOC_OR1K_GOT_PG21;
112 }
113 else if (strncasecmp (str, "tlsgd(", 6) == 0)
114 {
115 *strp = str + 6;
116 reloc = BFD_RELOC_OR1K_TLS_GD_PG21;
117 }
118 else if (strncasecmp (str, "tlsldm(", 7) == 0)
119 {
120 *strp = str + 7;
121 reloc = BFD_RELOC_OR1K_TLS_LDM_PG21;
73589c9d 122 }
c8e98e36
SH
123 else if (strncasecmp (str, "gottp(", 6) == 0)
124 {
125 *strp = str + 6;
126 reloc = BFD_RELOC_OR1K_TLS_IE_PG21;
127 }
128
129 errmsg = cgen_parse_address (cd, strp, opindex, reloc, resultp, valuep);
130
131 if (reloc != BFD_RELOC_OR1K_PCREL_PG21)
132 {
133 if (**strp != ')')
134 errmsg = MISSING_CLOSING_PARENTHESIS;
135 else
136 ++*strp;
137 }
138
139 return errmsg;
73589c9d 140}
87e6d782 141
c8e98e36
SH
142enum or1k_rclass
143{
144 RCLASS_DIRECT = 0,
145 RCLASS_GOT = 1,
146 RCLASS_GOTPC = 2,
147 RCLASS_GOTOFF = 3,
148 RCLASS_TLSGD = 4,
149 RCLASS_TLSLDM = 5,
150 RCLASS_DTPOFF = 6,
151 RCLASS_GOTTPOFF = 7,
152 RCLASS_TPOFF = 8,
153};
154
155enum or1k_rtype
156{
1c4f3780 157 RTYPE_LO = 0,
c8e98e36
SH
158 RTYPE_SLO = 1,
159 RTYPE_PO = 2,
160 RTYPE_SPO = 3,
161 RTYPE_HI = 4,
162 RTYPE_AHI = 5,
1c4f3780
RH
163};
164
c8e98e36
SH
165#define RCLASS_SHIFT 3
166#define RTYPE_MASK 7
167
168static const bfd_reloc_code_real_type or1k_imm16_relocs[][6] = {
1c4f3780 169 { BFD_RELOC_LO16,
c8e98e36
SH
170 BFD_RELOC_OR1K_SLO16,
171 BFD_RELOC_OR1K_LO13,
172 BFD_RELOC_OR1K_SLO13,
1c4f3780 173 BFD_RELOC_HI16,
c8e98e36 174 BFD_RELOC_HI16_S, },
1c4f3780 175 { BFD_RELOC_OR1K_GOT16,
c8e98e36
SH
176 BFD_RELOC_UNUSED,
177 BFD_RELOC_OR1K_GOT_LO13,
1c4f3780
RH
178 BFD_RELOC_UNUSED,
179 BFD_RELOC_UNUSED,
180 BFD_RELOC_UNUSED },
181 { BFD_RELOC_OR1K_GOTPC_LO16,
1c4f3780 182 BFD_RELOC_UNUSED,
c8e98e36
SH
183 BFD_RELOC_UNUSED,
184 BFD_RELOC_UNUSED,
185 BFD_RELOC_OR1K_GOTPC_HI16,
1c4f3780
RH
186 BFD_RELOC_UNUSED },
187 { BFD_RELOC_LO16_GOTOFF,
c8e98e36
SH
188 BFD_RELOC_OR1K_GOTOFF_SLO16,
189 BFD_RELOC_UNUSED,
190 BFD_RELOC_UNUSED,
1c4f3780 191 BFD_RELOC_HI16_GOTOFF,
c8e98e36 192 BFD_RELOC_HI16_S_GOTOFF },
1c4f3780 193 { BFD_RELOC_OR1K_TLS_GD_LO16,
1c4f3780 194 BFD_RELOC_UNUSED,
c8e98e36
SH
195 BFD_RELOC_OR1K_TLS_GD_LO13,
196 BFD_RELOC_UNUSED,
197 BFD_RELOC_OR1K_TLS_GD_HI16,
1c4f3780
RH
198 BFD_RELOC_UNUSED },
199 { BFD_RELOC_OR1K_TLS_LDM_LO16,
1c4f3780 200 BFD_RELOC_UNUSED,
c8e98e36
SH
201 BFD_RELOC_OR1K_TLS_LDM_LO13,
202 BFD_RELOC_UNUSED,
203 BFD_RELOC_OR1K_TLS_LDM_HI16,
1c4f3780
RH
204 BFD_RELOC_UNUSED },
205 { BFD_RELOC_OR1K_TLS_LDO_LO16,
1c4f3780 206 BFD_RELOC_UNUSED,
c8e98e36
SH
207 BFD_RELOC_UNUSED,
208 BFD_RELOC_UNUSED,
209 BFD_RELOC_OR1K_TLS_LDO_HI16,
1c4f3780
RH
210 BFD_RELOC_UNUSED },
211 { BFD_RELOC_OR1K_TLS_IE_LO16,
c8e98e36
SH
212 BFD_RELOC_UNUSED,
213 BFD_RELOC_OR1K_TLS_IE_LO13,
214 BFD_RELOC_UNUSED,
1c4f3780 215 BFD_RELOC_OR1K_TLS_IE_HI16,
c8e98e36 216 BFD_RELOC_OR1K_TLS_IE_AHI16 },
1c4f3780 217 { BFD_RELOC_OR1K_TLS_LE_LO16,
c8e98e36
SH
218 BFD_RELOC_OR1K_TLS_LE_SLO16,
219 BFD_RELOC_UNUSED,
220 BFD_RELOC_UNUSED,
1c4f3780 221 BFD_RELOC_OR1K_TLS_LE_HI16,
c8e98e36 222 BFD_RELOC_OR1K_TLS_LE_AHI16 },
1c4f3780
RH
223};
224
225static int
c8e98e36 226parse_reloc (const char **strp)
87e6d782 227{
1c4f3780 228 const char *str = *strp;
c8e98e36
SH
229 enum or1k_rclass cls = RCLASS_DIRECT;
230 enum or1k_rtype typ;
73589c9d 231
1c4f3780 232 if (strncasecmp (str, "got(", 4) == 0)
c8e98e36 233 {
1c4f3780 234 *strp = str + 4;
c8e98e36
SH
235 return (RCLASS_GOT << RCLASS_SHIFT) | RTYPE_LO;
236 }
237 if (strncasecmp (str, "gotpo(", 6) == 0)
238 {
239 *strp = str + 6;
240 return (RCLASS_GOT << RCLASS_SHIFT) | RTYPE_PO;
241 }
242 if (strncasecmp (str, "gottppo(", 8) == 0)
243 {
244 *strp = str + 8;
245 return (RCLASS_GOTTPOFF << RCLASS_SHIFT) | RTYPE_PO;
246 }
73589c9d 247
1c4f3780 248 if (strncasecmp (str, "gotpc", 5) == 0)
c8e98e36 249 {
1c4f3780 250 str += 5;
c8e98e36
SH
251 cls = RCLASS_GOTPC;
252 }
1c4f3780 253 else if (strncasecmp (str, "gotoff", 6) == 0)
c8e98e36 254 {
1c4f3780 255 str += 6;
c8e98e36
SH
256 cls = RCLASS_GOTOFF;
257 }
1c4f3780 258 else if (strncasecmp (str, "tlsgd", 5) == 0)
c8e98e36 259 {
1c4f3780 260 str += 5;
c8e98e36
SH
261 cls = RCLASS_TLSGD;
262 }
1c4f3780 263 else if (strncasecmp (str, "tlsldm", 6) == 0)
c8e98e36 264 {
1c4f3780 265 str += 6;
c8e98e36
SH
266 cls = RCLASS_TLSLDM;
267 }
1c4f3780 268 else if (strncasecmp (str, "dtpoff", 6) == 0)
c8e98e36 269 {
1c4f3780 270 str += 6;
c8e98e36
SH
271 cls = RCLASS_DTPOFF;
272 }
1c4f3780 273 else if (strncasecmp (str, "gottpoff", 8) == 0)
c8e98e36 274 {
1c4f3780 275 str += 8;
c8e98e36
SH
276 cls = RCLASS_GOTTPOFF;
277 }
1c4f3780 278 else if (strncasecmp (str, "tpoff", 5) == 0)
c8e98e36 279 {
1c4f3780 280 str += 5;
c8e98e36
SH
281 cls = RCLASS_TPOFF;
282 }
87e6d782 283
1c4f3780 284 if (strncasecmp (str, "hi(", 3) == 0)
c8e98e36 285 {
1c4f3780 286 str += 3;
c8e98e36
SH
287 typ = RTYPE_HI;
288 }
1c4f3780 289 else if (strncasecmp (str, "lo(", 3) == 0)
c8e98e36 290 {
1c4f3780 291 str += 3;
c8e98e36
SH
292 typ = RTYPE_LO;
293 }
1c4f3780 294 else if (strncasecmp (str, "ha(", 3) == 0)
c8e98e36 295 {
1c4f3780 296 str += 3;
c8e98e36
SH
297 typ = RTYPE_AHI;
298 }
299 else if (strncasecmp (str, "po(", 3) == 0 && cls != RCLASS_GOTTPOFF)
300 {
301 str += 3;
302 typ = RTYPE_PO;
303 }
1c4f3780
RH
304 else
305 return -1;
73589c9d 306
1c4f3780 307 *strp = str;
c8e98e36 308 return (cls << RCLASS_SHIFT) | typ;
1c4f3780 309}
8f807746 310
1c4f3780
RH
311static const char *
312parse_imm16 (CGEN_CPU_DESC cd, const char **strp, int opindex,
313 long *valuep, int splitp)
314{
315 const char *errmsg;
316 enum cgen_parse_operand_result result_type;
317 bfd_reloc_code_real_type reloc = BFD_RELOC_UNUSED;
c8e98e36
SH
318 enum or1k_rtype reloc_type;
319 int reloc_code;
1c4f3780 320 bfd_vma ret;
73589c9d 321
1c4f3780 322 if (**strp == '#')
c8e98e36 323 ++*strp;
1c4f3780 324
c8e98e36
SH
325 reloc_code = parse_reloc (strp);
326 reloc_type = reloc_code & RTYPE_MASK;
327 if (reloc_code >= 0)
1c4f3780 328 {
c8e98e36 329 enum or1k_rclass reloc_class = reloc_code >> RCLASS_SHIFT;
1c4f3780
RH
330 if (splitp)
331 {
c8e98e36
SH
332 if ((reloc_type == RTYPE_LO || reloc_type == RTYPE_PO)
333 && reloc_class != RCLASS_GOT)
334 /* If split we or up the type to RTYPE_SLO or RTYPE_SPO. */
335 reloc_type |= 1;
1c4f3780
RH
336 else
337 return INVALID_STORE_RELOC;
c8e98e36
SH
338 }
339 reloc = or1k_imm16_relocs[reloc_class][reloc_type];
1c4f3780
RH
340 }
341
342 if (reloc != BFD_RELOC_UNUSED)
73589c9d
CS
343 {
344 bfd_vma value;
345
1c4f3780 346 errmsg = cgen_parse_address (cd, strp, opindex, reloc,
c151b1c6 347 &result_type, &value);
73589c9d 348 if (**strp != ')')
1c4f3780 349 errmsg = MISSING_CLOSING_PARENTHESIS;
73589c9d 350 ++*strp;
73589c9d 351
1c4f3780 352 ret = value;
73589c9d 353
1c4f3780 354 if (errmsg == NULL && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
c8e98e36
SH
355 switch (reloc_type)
356 {
1c4f3780
RH
357 case RTYPE_AHI:
358 ret += 0x8000;
359 /* FALLTHRU */
360 case RTYPE_HI:
361 ret >>= 16;
362 /* FALLTHRU */
363 case RTYPE_LO:
364 case RTYPE_SLO:
365 ret &= 0xffff;
366 ret = (ret ^ 0x8000) - 0x8000;
367 break;
c8e98e36
SH
368 case RTYPE_PO:
369 case RTYPE_SPO:
370 ret &= 0x1fff;
371 break;
1c4f3780
RH
372 default:
373 errmsg = INVALID_RELOC_TYPE;
374 }
73589c9d
CS
375 }
376 else
377 {
378 long value;
379 errmsg = cgen_parse_signed_integer (cd, strp, opindex, &value);
380 ret = value;
381 }
382
383 if (errmsg == NULL)
384 *valuep = ret;
385
386 return errmsg;
387}
388
389static const char *
1c4f3780
RH
390parse_simm16 (CGEN_CPU_DESC cd, const char **strp, int opindex, long *valuep)
391{
392 return parse_imm16(cd, strp, opindex, (long *) valuep, 0);
393}
394
395static const char *
396parse_simm16_split (CGEN_CPU_DESC cd, const char **strp, int opindex,
397 long *valuep)
73589c9d 398{
1c4f3780
RH
399 return parse_imm16(cd, strp, opindex, (long *) valuep, 1);
400}
c151b1c6 401
1c4f3780
RH
402static const char *
403parse_uimm16 (CGEN_CPU_DESC cd, const char **strp, int opindex,
404 unsigned long *valuep)
405{
406 const char *errmsg = parse_imm16(cd, strp, opindex, (long *) valuep, 0);
407 if (errmsg == NULL)
408 *valuep &= 0xffff;
409 return errmsg;
410}
411
412static const char *
413parse_uimm16_split (CGEN_CPU_DESC cd, const char **strp, int opindex,
414 unsigned long *valuep)
415{
416 const char *errmsg = parse_imm16(cd, strp, opindex, (long *) valuep, 1);
73589c9d
CS
417 if (errmsg == NULL)
418 *valuep &= 0xffff;
87e6d782
NC
419 return errmsg;
420}
421
422/* -- */
423
73589c9d 424const char * or1k_cgen_parse_operand
47b0e7ad 425 (CGEN_CPU_DESC, int, const char **, CGEN_FIELDS *);
0e2ee3ca 426
87e6d782
NC
427/* Main entry point for operand parsing.
428
429 This function is basically just a big switch statement. Earlier versions
430 used tables to look up the function to use, but
431 - if the table contains both assembler and disassembler functions then
432 the disassembler contains much of the assembler and vice-versa,
433 - there's a lot of inlining possibilities as things grow,
434 - using a switch statement avoids the function call overhead.
435
436 This function could be moved into `parse_insn_normal', but keeping it
437 separate makes clear the interface between `parse_insn_normal' and each of
9a2e995d 438 the handlers. */
87e6d782
NC
439
440const char *
73589c9d 441or1k_cgen_parse_operand (CGEN_CPU_DESC cd,
47b0e7ad
NC
442 int opindex,
443 const char ** strp,
444 CGEN_FIELDS * fields)
87e6d782
NC
445{
446 const char * errmsg = NULL;
447 /* Used by scalar operands that still need to be parsed. */
fc05c67f 448 long junk ATTRIBUTE_UNUSED;
87e6d782
NC
449
450 switch (opindex)
451 {
c8e98e36
SH
452 case OR1K_OPERAND_DISP21 :
453 {
454 bfd_vma value = 0;
455 errmsg = parse_disp21 (cd, strp, OR1K_OPERAND_DISP21, 0, NULL, & value);
456 fields->f_disp21 = value;
457 }
458 break;
73589c9d 459 case OR1K_OPERAND_DISP26 :
87e6d782 460 {
9494d739 461 bfd_vma value = 0;
73589c9d 462 errmsg = parse_disp26 (cd, strp, OR1K_OPERAND_DISP26, 0, NULL, & value);
87e6d782
NC
463 fields->f_disp26 = value;
464 }
465 break;
73589c9d
CS
466 case OR1K_OPERAND_RA :
467 errmsg = cgen_parse_keyword (cd, strp, & or1k_cgen_opval_h_gpr, & fields->f_r2);
468 break;
469 case OR1K_OPERAND_RADF :
470 errmsg = cgen_parse_keyword (cd, strp, & or1k_cgen_opval_h_fdr, & fields->f_r1);
87e6d782 471 break;
73589c9d
CS
472 case OR1K_OPERAND_RASF :
473 errmsg = cgen_parse_keyword (cd, strp, & or1k_cgen_opval_h_fsr, & fields->f_r2);
87e6d782 474 break;
73589c9d
CS
475 case OR1K_OPERAND_RB :
476 errmsg = cgen_parse_keyword (cd, strp, & or1k_cgen_opval_h_gpr, & fields->f_r3);
87e6d782 477 break;
73589c9d
CS
478 case OR1K_OPERAND_RBDF :
479 errmsg = cgen_parse_keyword (cd, strp, & or1k_cgen_opval_h_fdr, & fields->f_r1);
87e6d782 480 break;
73589c9d
CS
481 case OR1K_OPERAND_RBSF :
482 errmsg = cgen_parse_keyword (cd, strp, & or1k_cgen_opval_h_fsr, & fields->f_r3);
87e6d782 483 break;
73589c9d
CS
484 case OR1K_OPERAND_RD :
485 errmsg = cgen_parse_keyword (cd, strp, & or1k_cgen_opval_h_gpr, & fields->f_r1);
87e6d782 486 break;
73589c9d
CS
487 case OR1K_OPERAND_RDDF :
488 errmsg = cgen_parse_keyword (cd, strp, & or1k_cgen_opval_h_fdr, & fields->f_r1);
87e6d782 489 break;
73589c9d
CS
490 case OR1K_OPERAND_RDSF :
491 errmsg = cgen_parse_keyword (cd, strp, & or1k_cgen_opval_h_fsr, & fields->f_r1);
87e6d782 492 break;
73589c9d
CS
493 case OR1K_OPERAND_SIMM16 :
494 errmsg = parse_simm16 (cd, strp, OR1K_OPERAND_SIMM16, (long *) (& fields->f_simm16));
87e6d782 495 break;
73589c9d 496 case OR1K_OPERAND_SIMM16_SPLIT :
1c4f3780 497 errmsg = parse_simm16_split (cd, strp, OR1K_OPERAND_SIMM16_SPLIT, (long *) (& fields->f_simm16_split));
87e6d782 498 break;
73589c9d
CS
499 case OR1K_OPERAND_UIMM16 :
500 errmsg = parse_uimm16 (cd, strp, OR1K_OPERAND_UIMM16, (unsigned long *) (& fields->f_uimm16));
501 break;
502 case OR1K_OPERAND_UIMM16_SPLIT :
1c4f3780 503 errmsg = parse_uimm16_split (cd, strp, OR1K_OPERAND_UIMM16_SPLIT, (unsigned long *) (& fields->f_uimm16_split));
73589c9d
CS
504 break;
505 case OR1K_OPERAND_UIMM6 :
506 errmsg = cgen_parse_unsigned_integer (cd, strp, OR1K_OPERAND_UIMM6, (unsigned long *) (& fields->f_uimm6));
87e6d782
NC
507 break;
508
509 default :
510 /* xgettext:c-format */
a6743a54
AM
511 opcodes_error_handler
512 (_("internal error: unrecognized field %d while parsing"),
513 opindex);
87e6d782
NC
514 abort ();
515 }
516
517 return errmsg;
518}
519
43e65147 520cgen_parse_fn * const or1k_cgen_parse_handlers[] =
87e6d782
NC
521{
522 parse_insn_normal,
523};
524
525void
73589c9d 526or1k_cgen_init_asm (CGEN_CPU_DESC cd)
87e6d782 527{
73589c9d
CS
528 or1k_cgen_init_opcode_table (cd);
529 or1k_cgen_init_ibld_table (cd);
530 cd->parse_handlers = & or1k_cgen_parse_handlers[0];
531 cd->parse_operand = or1k_cgen_parse_operand;
1620f33d
AM
532#ifdef CGEN_ASM_INIT_HOOK
533CGEN_ASM_INIT_HOOK
534#endif
87e6d782
NC
535}
536
fc7bc883
RH
537\f
538
37111cc7 539/* Regex construction routine.
fc7bc883 540
37111cc7
NC
541 This translates an opcode syntax string into a regex string,
542 by replacing any non-character syntax element (such as an
543 opcode) with the pattern '.*'
fc7bc883 544
37111cc7 545 It then compiles the regex and stores it in the opcode, for
73589c9d 546 later use by or1k_cgen_assemble_insn
fc7bc883 547
37111cc7 548 Returns NULL for success, an error message for failure. */
fc7bc883 549
43e65147 550char *
73589c9d 551or1k_cgen_build_insn_regex (CGEN_INSN *insn)
43e65147 552{
fc05c67f 553 CGEN_OPCODE *opc = (CGEN_OPCODE *) CGEN_INSN_OPCODE (insn);
fc7bc883 554 const char *mnem = CGEN_INSN_MNEMONIC (insn);
fc7bc883
RH
555 char rxbuf[CGEN_MAX_RX_ELEMENTS];
556 char *rx = rxbuf;
557 const CGEN_SYNTAX_CHAR_TYPE *syn;
558 int reg_err;
559
560 syn = CGEN_SYNTAX_STRING (CGEN_OPCODE_SYNTAX (opc));
561
f3a55c17
NC
562 /* Mnemonics come first in the syntax string. */
563 if (! CGEN_SYNTAX_MNEMONIC_P (* syn))
564 return _("missing mnemonic in syntax string");
fc7bc883
RH
565 ++syn;
566
f3a55c17
NC
567 /* Generate a case sensitive regular expression that emulates case
568 insensitive matching in the "C" locale. We cannot generate a case
569 insensitive regular expression because in Turkish locales, 'i' and 'I'
570 are not equal modulo case conversion. */
fc7bc883 571
f3a55c17
NC
572 /* Copy the literal mnemonic out of the insn. */
573 for (; *mnem; mnem++)
574 {
575 char c = *mnem;
576
577 if (ISALPHA (c))
578 {
579 *rx++ = '[';
580 *rx++ = TOLOWER (c);
581 *rx++ = TOUPPER (c);
582 *rx++ = ']';
583 }
584 else
585 *rx++ = c;
586 }
587
588 /* Copy any remaining literals from the syntax string into the rx. */
589 for(; * syn != 0 && rx <= rxbuf + (CGEN_MAX_RX_ELEMENTS - 7 - 4); ++syn)
fc7bc883 590 {
43e65147 591 if (CGEN_SYNTAX_CHAR_P (* syn))
fc7bc883 592 {
f3a55c17
NC
593 char c = CGEN_SYNTAX_CHAR (* syn);
594
43e65147 595 switch (c)
f3a55c17
NC
596 {
597 /* Escape any regex metacharacters in the syntax. */
43e65147
L
598 case '.': case '[': case '\\':
599 case '*': case '^': case '$':
fc7bc883
RH
600
601#ifdef CGEN_ESCAPE_EXTENDED_REGEX
43e65147 602 case '?': case '{': case '}':
f3a55c17
NC
603 case '(': case ')': case '*':
604 case '|': case '+': case ']':
fc7bc883 605#endif
f3a55c17
NC
606 *rx++ = '\\';
607 *rx++ = c;
608 break;
609
610 default:
611 if (ISALPHA (c))
612 {
613 *rx++ = '[';
614 *rx++ = TOLOWER (c);
615 *rx++ = TOUPPER (c);
616 *rx++ = ']';
617 }
618 else
619 *rx++ = c;
620 break;
621 }
fc7bc883
RH
622 }
623 else
624 {
f3a55c17
NC
625 /* Replace non-syntax fields with globs. */
626 *rx++ = '.';
627 *rx++ = '*';
fc7bc883
RH
628 }
629 }
630
f3a55c17 631 /* Trailing whitespace ok. */
43e65147
L
632 * rx++ = '[';
633 * rx++ = ' ';
634 * rx++ = '\t';
635 * rx++ = ']';
636 * rx++ = '*';
fc7bc883 637
f3a55c17 638 /* But anchor it after that. */
43e65147 639 * rx++ = '$';
fc7bc883
RH
640 * rx = '\0';
641
642 CGEN_INSN_RX (insn) = xmalloc (sizeof (regex_t));
f3a55c17 643 reg_err = regcomp ((regex_t *) CGEN_INSN_RX (insn), rxbuf, REG_NOSUB);
fc7bc883 644
43e65147 645 if (reg_err == 0)
fc7bc883
RH
646 return NULL;
647 else
648 {
649 static char msg[80];
f3a55c17 650
fc7bc883
RH
651 regerror (reg_err, (regex_t *) CGEN_INSN_RX (insn), msg, 80);
652 regfree ((regex_t *) CGEN_INSN_RX (insn));
653 free (CGEN_INSN_RX (insn));
654 (CGEN_INSN_RX (insn)) = NULL;
37111cc7 655 return msg;
fc7bc883
RH
656 }
657}
658
87e6d782
NC
659\f
660/* Default insn parser.
661
662 The syntax string is scanned and operands are parsed and stored in FIELDS.
663 Relocs are queued as we go via other callbacks.
664
665 ??? Note that this is currently an all-or-nothing parser. If we fail to
666 parse the instruction, we return 0 and the caller will start over from
667 the beginning. Backtracking will be necessary in parsing subexpressions,
668 but that can be handled there. Not handling backtracking here may get
669 expensive in the case of the m68k. Deal with later.
670
f3a55c17 671 Returns NULL for success, an error message for failure. */
87e6d782
NC
672
673static const char *
ffead7ae
MM
674parse_insn_normal (CGEN_CPU_DESC cd,
675 const CGEN_INSN *insn,
676 const char **strp,
677 CGEN_FIELDS *fields)
87e6d782
NC
678{
679 /* ??? Runtime added insns not handled yet. */
680 const CGEN_SYNTAX *syntax = CGEN_INSN_SYNTAX (insn);
681 const char *str = *strp;
682 const char *errmsg;
683 const char *p;
684 const CGEN_SYNTAX_CHAR_TYPE * syn;
685#ifdef CGEN_MNEMONIC_OPERANDS
686 /* FIXME: wip */
687 int past_opcode_p;
688#endif
689
690 /* For now we assume the mnemonic is first (there are no leading operands).
691 We can parse it without needing to set up operand parsing.
692 GAS's input scrubber will ensure mnemonics are lowercase, but we may
693 not be called from GAS. */
694 p = CGEN_INSN_MNEMONIC (insn);
37111cc7 695 while (*p && TOLOWER (*p) == TOLOWER (*str))
87e6d782
NC
696 ++p, ++str;
697
698 if (* p)
699 return _("unrecognized instruction");
700
701#ifndef CGEN_MNEMONIC_OPERANDS
37111cc7 702 if (* str && ! ISSPACE (* str))
87e6d782
NC
703 return _("unrecognized instruction");
704#endif
705
706 CGEN_INIT_PARSE (cd);
707 cgen_init_parse_operand (cd);
708#ifdef CGEN_MNEMONIC_OPERANDS
709 past_opcode_p = 0;
710#endif
711
712 /* We don't check for (*str != '\0') here because we want to parse
713 any trailing fake arguments in the syntax string. */
714 syn = CGEN_SYNTAX_STRING (syntax);
715
716 /* Mnemonics come first for now, ensure valid string. */
717 if (! CGEN_SYNTAX_MNEMONIC_P (* syn))
718 abort ();
719
720 ++syn;
721
722 while (* syn != 0)
723 {
724 /* Non operand chars must match exactly. */
725 if (CGEN_SYNTAX_CHAR_P (* syn))
726 {
727 /* FIXME: While we allow for non-GAS callers above, we assume the
728 first char after the mnemonic part is a space. */
729 /* FIXME: We also take inappropriate advantage of the fact that
730 GAS's input scrubber will remove extraneous blanks. */
37111cc7 731 if (TOLOWER (*str) == TOLOWER (CGEN_SYNTAX_CHAR (* syn)))
87e6d782
NC
732 {
733#ifdef CGEN_MNEMONIC_OPERANDS
734 if (CGEN_SYNTAX_CHAR(* syn) == ' ')
735 past_opcode_p = 1;
736#endif
737 ++ syn;
738 ++ str;
739 }
740 else if (*str)
741 {
742 /* Syntax char didn't match. Can't be this insn. */
743 static char msg [80];
f3a55c17 744
87e6d782
NC
745 /* xgettext:c-format */
746 sprintf (msg, _("syntax error (expected char `%c', found `%c')"),
747 CGEN_SYNTAX_CHAR(*syn), *str);
748 return msg;
749 }
750 else
751 {
752 /* Ran out of input. */
753 static char msg [80];
f3a55c17 754
87e6d782
NC
755 /* xgettext:c-format */
756 sprintf (msg, _("syntax error (expected char `%c', found end of instruction)"),
757 CGEN_SYNTAX_CHAR(*syn));
758 return msg;
759 }
760 continue;
761 }
762
c7e2358a
AM
763#ifdef CGEN_MNEMONIC_OPERANDS
764 (void) past_opcode_p;
765#endif
87e6d782 766 /* We have an operand of some sort. */
c7e2358a 767 errmsg = cd->parse_operand (cd, CGEN_SYNTAX_FIELD (*syn), &str, fields);
87e6d782
NC
768 if (errmsg)
769 return errmsg;
770
771 /* Done with this operand, continue with next one. */
772 ++ syn;
773 }
774
775 /* If we're at the end of the syntax string, we're done. */
776 if (* syn == 0)
777 {
778 /* FIXME: For the moment we assume a valid `str' can only contain
779 blanks now. IE: We needn't try again with a longer version of
780 the insn and it is assumed that longer versions of insns appear
781 before shorter ones (eg: lsr r2,r3,1 vs lsr r2,r3). */
37111cc7 782 while (ISSPACE (* str))
87e6d782
NC
783 ++ str;
784
785 if (* str != '\0')
786 return _("junk at end of line"); /* FIXME: would like to include `str' */
787
788 return NULL;
789 }
790
791 /* We couldn't parse it. */
792 return _("unrecognized instruction");
793}
794\f
795/* Main entry point.
796 This routine is called for each instruction to be assembled.
797 STR points to the insn to be assembled.
798 We assume all necessary tables have been initialized.
799 The assembled instruction, less any fixups, is stored in BUF.
800 Remember that if CGEN_INT_INSN_P then BUF is an int and thus the value
801 still needs to be converted to target byte order, otherwise BUF is an array
802 of bytes in target byte order.
803 The result is a pointer to the insn's entry in the opcode table,
804 or NULL if an error occured (an error message will have already been
805 printed).
806
807 Note that when processing (non-alias) macro-insns,
808 this function recurses.
809
810 ??? It's possible to make this cpu-independent.
811 One would have to deal with a few minor things.
812 At this point in time doing so would be more of a curiosity than useful
813 [for example this file isn't _that_ big], but keeping the possibility in
814 mind helps keep the design clean. */
815
816const CGEN_INSN *
73589c9d 817or1k_cgen_assemble_insn (CGEN_CPU_DESC cd,
ffead7ae
MM
818 const char *str,
819 CGEN_FIELDS *fields,
820 CGEN_INSN_BYTES_PTR buf,
821 char **errmsg)
87e6d782
NC
822{
823 const char *start;
824 CGEN_INSN_LIST *ilist;
825 const char *parse_errmsg = NULL;
826 const char *insert_errmsg = NULL;
fc7bc883 827 int recognized_mnemonic = 0;
87e6d782
NC
828
829 /* Skip leading white space. */
37111cc7 830 while (ISSPACE (* str))
87e6d782
NC
831 ++ str;
832
833 /* The instructions are stored in hashed lists.
834 Get the first in the list. */
835 ilist = CGEN_ASM_LOOKUP_INSN (cd, str);
836
837 /* Keep looking until we find a match. */
87e6d782
NC
838 start = str;
839 for ( ; ilist != NULL ; ilist = CGEN_ASM_NEXT_INSN (ilist))
840 {
841 const CGEN_INSN *insn = ilist->insn;
fc7bc883 842 recognized_mnemonic = 1;
87e6d782 843
43e65147 844#ifdef CGEN_VALIDATE_INSN_SUPPORTED
f3a55c17
NC
845 /* Not usually needed as unsupported opcodes
846 shouldn't be in the hash lists. */
87e6d782 847 /* Is this insn supported by the selected cpu? */
73589c9d 848 if (! or1k_cgen_insn_supported (cd, insn))
87e6d782
NC
849 continue;
850#endif
b11dcf4e 851 /* If the RELAXED attribute is set, this is an insn that shouldn't be
87e6d782
NC
852 chosen immediately. Instead, it is used during assembler/linker
853 relaxation if possible. */
b11dcf4e 854 if (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_RELAXED) != 0)
87e6d782
NC
855 continue;
856
857 str = start;
858
f3a55c17 859 /* Skip this insn if str doesn't look right lexically. */
fc7bc883
RH
860 if (CGEN_INSN_RX (insn) != NULL &&
861 regexec ((regex_t *) CGEN_INSN_RX (insn), str, 0, NULL, 0) == REG_NOMATCH)
862 continue;
863
87e6d782
NC
864 /* Allow parse/insert handlers to obtain length of insn. */
865 CGEN_FIELDS_BITSIZE (fields) = CGEN_INSN_BITSIZE (insn);
866
867 parse_errmsg = CGEN_PARSE_FN (cd, insn) (cd, insn, & str, fields);
868 if (parse_errmsg != NULL)
869 continue;
870
f3a55c17 871 /* ??? 0 is passed for `pc'. */
87e6d782
NC
872 insert_errmsg = CGEN_INSERT_FN (cd, insn) (cd, insn, fields, buf,
873 (bfd_vma) 0);
874 if (insert_errmsg != NULL)
875 continue;
876
877 /* It is up to the caller to actually output the insn and any
878 queued relocs. */
879 return insn;
880 }
881
882 {
883 static char errbuf[150];
87e6d782 884 const char *tmp_errmsg;
c7e2358a
AM
885#ifdef CGEN_VERBOSE_ASSEMBLER_ERRORS
886#define be_verbose 1
87e6d782 887#else
c7e2358a 888#define be_verbose 0
87e6d782 889#endif
c7e2358a
AM
890
891 if (be_verbose)
892 {
893 /* If requesting verbose error messages, use insert_errmsg.
894 Failing that, use parse_errmsg. */
895 tmp_errmsg = (insert_errmsg ? insert_errmsg :
896 parse_errmsg ? parse_errmsg :
897 recognized_mnemonic ?
898 _("unrecognized form of instruction") :
899 _("unrecognized instruction"));
900
901 if (strlen (start) > 50)
902 /* xgettext:c-format */
903 sprintf (errbuf, "%s `%.50s...'", tmp_errmsg, start);
43e65147 904 else
c7e2358a
AM
905 /* xgettext:c-format */
906 sprintf (errbuf, "%s `%.50s'", tmp_errmsg, start);
907 }
908 else
909 {
910 if (strlen (start) > 50)
911 /* xgettext:c-format */
912 sprintf (errbuf, _("bad instruction `%.50s...'"), start);
43e65147 913 else
c7e2358a
AM
914 /* xgettext:c-format */
915 sprintf (errbuf, _("bad instruction `%.50s'"), start);
916 }
43e65147 917
87e6d782
NC
918 *errmsg = errbuf;
919 return NULL;
920 }
921}