Automatic date update in version.in
[deliverable/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
250d07de 8 Copyright (C) 1996-2021 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,
0b3e14c9 180 BFD_RELOC_OR1K_GOT_AHI16 },
1c4f3780 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 }
0b3e14c9
SH
283 else if (strncasecmp (str, "got", 3) == 0)
284 {
285 str += 3;
286 cls = RCLASS_GOT;
287 }
87e6d782 288
1c4f3780 289 if (strncasecmp (str, "hi(", 3) == 0)
c8e98e36 290 {
1c4f3780 291 str += 3;
c8e98e36
SH
292 typ = RTYPE_HI;
293 }
1c4f3780 294 else if (strncasecmp (str, "lo(", 3) == 0)
c8e98e36 295 {
1c4f3780 296 str += 3;
c8e98e36
SH
297 typ = RTYPE_LO;
298 }
1c4f3780 299 else if (strncasecmp (str, "ha(", 3) == 0)
c8e98e36 300 {
1c4f3780 301 str += 3;
c8e98e36
SH
302 typ = RTYPE_AHI;
303 }
304 else if (strncasecmp (str, "po(", 3) == 0 && cls != RCLASS_GOTTPOFF)
305 {
306 str += 3;
307 typ = RTYPE_PO;
308 }
1c4f3780
RH
309 else
310 return -1;
73589c9d 311
1c4f3780 312 *strp = str;
c8e98e36 313 return (cls << RCLASS_SHIFT) | typ;
1c4f3780 314}
8f807746 315
1c4f3780
RH
316static const char *
317parse_imm16 (CGEN_CPU_DESC cd, const char **strp, int opindex,
318 long *valuep, int splitp)
319{
320 const char *errmsg;
321 enum cgen_parse_operand_result result_type;
322 bfd_reloc_code_real_type reloc = BFD_RELOC_UNUSED;
c8e98e36
SH
323 enum or1k_rtype reloc_type;
324 int reloc_code;
1c4f3780 325 bfd_vma ret;
73589c9d 326
1c4f3780 327 if (**strp == '#')
c8e98e36 328 ++*strp;
1c4f3780 329
c8e98e36
SH
330 reloc_code = parse_reloc (strp);
331 reloc_type = reloc_code & RTYPE_MASK;
332 if (reloc_code >= 0)
1c4f3780 333 {
c8e98e36 334 enum or1k_rclass reloc_class = reloc_code >> RCLASS_SHIFT;
1c4f3780
RH
335 if (splitp)
336 {
c8e98e36
SH
337 if ((reloc_type == RTYPE_LO || reloc_type == RTYPE_PO)
338 && reloc_class != RCLASS_GOT)
339 /* If split we or up the type to RTYPE_SLO or RTYPE_SPO. */
340 reloc_type |= 1;
1c4f3780
RH
341 else
342 return INVALID_STORE_RELOC;
c8e98e36
SH
343 }
344 reloc = or1k_imm16_relocs[reloc_class][reloc_type];
1c4f3780
RH
345 }
346
347 if (reloc != BFD_RELOC_UNUSED)
73589c9d
CS
348 {
349 bfd_vma value;
350
1c4f3780 351 errmsg = cgen_parse_address (cd, strp, opindex, reloc,
c151b1c6 352 &result_type, &value);
73589c9d 353 if (**strp != ')')
1c4f3780 354 errmsg = MISSING_CLOSING_PARENTHESIS;
73589c9d 355 ++*strp;
73589c9d 356
1c4f3780 357 ret = value;
73589c9d 358
1c4f3780 359 if (errmsg == NULL && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
c8e98e36
SH
360 switch (reloc_type)
361 {
1c4f3780
RH
362 case RTYPE_AHI:
363 ret += 0x8000;
364 /* FALLTHRU */
365 case RTYPE_HI:
366 ret >>= 16;
367 /* FALLTHRU */
368 case RTYPE_LO:
369 case RTYPE_SLO:
370 ret &= 0xffff;
371 ret = (ret ^ 0x8000) - 0x8000;
372 break;
c8e98e36
SH
373 case RTYPE_PO:
374 case RTYPE_SPO:
375 ret &= 0x1fff;
376 break;
1c4f3780
RH
377 default:
378 errmsg = INVALID_RELOC_TYPE;
379 }
73589c9d
CS
380 }
381 else
382 {
383 long value;
384 errmsg = cgen_parse_signed_integer (cd, strp, opindex, &value);
385 ret = value;
386 }
387
388 if (errmsg == NULL)
389 *valuep = ret;
390
391 return errmsg;
392}
393
394static const char *
1c4f3780
RH
395parse_simm16 (CGEN_CPU_DESC cd, const char **strp, int opindex, long *valuep)
396{
397 return parse_imm16(cd, strp, opindex, (long *) valuep, 0);
398}
399
400static const char *
401parse_simm16_split (CGEN_CPU_DESC cd, const char **strp, int opindex,
402 long *valuep)
73589c9d 403{
1c4f3780
RH
404 return parse_imm16(cd, strp, opindex, (long *) valuep, 1);
405}
c151b1c6 406
1c4f3780
RH
407static const char *
408parse_uimm16 (CGEN_CPU_DESC cd, const char **strp, int opindex,
409 unsigned long *valuep)
410{
411 const char *errmsg = parse_imm16(cd, strp, opindex, (long *) valuep, 0);
412 if (errmsg == NULL)
413 *valuep &= 0xffff;
414 return errmsg;
415}
416
417static const char *
418parse_uimm16_split (CGEN_CPU_DESC cd, const char **strp, int opindex,
419 unsigned long *valuep)
420{
421 const char *errmsg = parse_imm16(cd, strp, opindex, (long *) valuep, 1);
73589c9d
CS
422 if (errmsg == NULL)
423 *valuep &= 0xffff;
87e6d782
NC
424 return errmsg;
425}
426
e4c4ac46
SH
427/* Parse register pairs with syntax rA,rB to a flag + rA value. */
428
429static const char *
430parse_regpair (CGEN_CPU_DESC cd, const char **strp,
431 int opindex ATTRIBUTE_UNUSED, unsigned long *valuep)
432{
433 long reg1_index;
434 long reg2_index;
435 const char *errmsg;
436
437 /* The first part should just be a register. */
438 errmsg = cgen_parse_keyword (cd, strp, &or1k_cgen_opval_h_gpr,
439 &reg1_index);
440
441 /* If that worked skip the comma separator. */
442 if (errmsg == NULL)
443 {
444 if (**strp == ',')
445 ++*strp;
446 else
447 errmsg = "Unexpected character, expected ','";
448 }
449
450 /* If that worked the next part is just another register. */
451 if (errmsg == NULL)
452 errmsg = cgen_parse_keyword (cd, strp, &or1k_cgen_opval_h_gpr,
453 &reg2_index);
454
455 /* Validate the register pair is valid and create the output value. */
456 if (errmsg == NULL)
457 {
458 int regoffset = reg2_index - reg1_index;
459
460 if (regoffset == 1 || regoffset == 2)
461 {
462 unsigned short offsetmask;
463 unsigned short value;
464
465 offsetmask = ((regoffset == 2 ? 1 : 0) << 5);
466 value = offsetmask | reg1_index;
467
468 *valuep = value;
469 }
470 else
471 errmsg = "Invalid register pair, offset not 1 or 2.";
472 }
473
474 return errmsg;
475}
476
87e6d782
NC
477/* -- */
478
73589c9d 479const char * or1k_cgen_parse_operand
47b0e7ad 480 (CGEN_CPU_DESC, int, const char **, CGEN_FIELDS *);
0e2ee3ca 481
87e6d782
NC
482/* Main entry point for operand parsing.
483
484 This function is basically just a big switch statement. Earlier versions
485 used tables to look up the function to use, but
486 - if the table contains both assembler and disassembler functions then
487 the disassembler contains much of the assembler and vice-versa,
488 - there's a lot of inlining possibilities as things grow,
489 - using a switch statement avoids the function call overhead.
490
491 This function could be moved into `parse_insn_normal', but keeping it
492 separate makes clear the interface between `parse_insn_normal' and each of
9a2e995d 493 the handlers. */
87e6d782
NC
494
495const char *
73589c9d 496or1k_cgen_parse_operand (CGEN_CPU_DESC cd,
47b0e7ad
NC
497 int opindex,
498 const char ** strp,
499 CGEN_FIELDS * fields)
87e6d782
NC
500{
501 const char * errmsg = NULL;
502 /* Used by scalar operands that still need to be parsed. */
fc05c67f 503 long junk ATTRIBUTE_UNUSED;
87e6d782
NC
504
505 switch (opindex)
506 {
c8e98e36
SH
507 case OR1K_OPERAND_DISP21 :
508 {
509 bfd_vma value = 0;
510 errmsg = parse_disp21 (cd, strp, OR1K_OPERAND_DISP21, 0, NULL, & value);
511 fields->f_disp21 = value;
512 }
513 break;
73589c9d 514 case OR1K_OPERAND_DISP26 :
87e6d782 515 {
9494d739 516 bfd_vma value = 0;
73589c9d 517 errmsg = parse_disp26 (cd, strp, OR1K_OPERAND_DISP26, 0, NULL, & value);
87e6d782
NC
518 fields->f_disp26 = value;
519 }
520 break;
73589c9d
CS
521 case OR1K_OPERAND_RA :
522 errmsg = cgen_parse_keyword (cd, strp, & or1k_cgen_opval_h_gpr, & fields->f_r2);
523 break;
e4c4ac46
SH
524 case OR1K_OPERAND_RAD32F :
525 errmsg = parse_regpair (cd, strp, OR1K_OPERAND_RAD32F, (unsigned long *) (& fields->f_rad32));
526 break;
e4c4ac46
SH
527 case OR1K_OPERAND_RADI :
528 errmsg = parse_regpair (cd, strp, OR1K_OPERAND_RADI, (unsigned long *) (& fields->f_rad32));
87e6d782 529 break;
73589c9d
CS
530 case OR1K_OPERAND_RASF :
531 errmsg = cgen_parse_keyword (cd, strp, & or1k_cgen_opval_h_fsr, & fields->f_r2);
87e6d782 532 break;
73589c9d
CS
533 case OR1K_OPERAND_RB :
534 errmsg = cgen_parse_keyword (cd, strp, & or1k_cgen_opval_h_gpr, & fields->f_r3);
87e6d782 535 break;
e4c4ac46
SH
536 case OR1K_OPERAND_RBD32F :
537 errmsg = parse_regpair (cd, strp, OR1K_OPERAND_RBD32F, (unsigned long *) (& fields->f_rbd32));
538 break;
e4c4ac46
SH
539 case OR1K_OPERAND_RBDI :
540 errmsg = parse_regpair (cd, strp, OR1K_OPERAND_RBDI, (unsigned long *) (& fields->f_rbd32));
87e6d782 541 break;
73589c9d
CS
542 case OR1K_OPERAND_RBSF :
543 errmsg = cgen_parse_keyword (cd, strp, & or1k_cgen_opval_h_fsr, & fields->f_r3);
87e6d782 544 break;
73589c9d
CS
545 case OR1K_OPERAND_RD :
546 errmsg = cgen_parse_keyword (cd, strp, & or1k_cgen_opval_h_gpr, & fields->f_r1);
87e6d782 547 break;
e4c4ac46
SH
548 case OR1K_OPERAND_RDD32F :
549 errmsg = parse_regpair (cd, strp, OR1K_OPERAND_RDD32F, (unsigned long *) (& fields->f_rdd32));
550 break;
e4c4ac46
SH
551 case OR1K_OPERAND_RDDI :
552 errmsg = parse_regpair (cd, strp, OR1K_OPERAND_RDDI, (unsigned long *) (& fields->f_rdd32));
553 break;
73589c9d
CS
554 case OR1K_OPERAND_RDSF :
555 errmsg = cgen_parse_keyword (cd, strp, & or1k_cgen_opval_h_fsr, & fields->f_r1);
87e6d782 556 break;
73589c9d
CS
557 case OR1K_OPERAND_SIMM16 :
558 errmsg = parse_simm16 (cd, strp, OR1K_OPERAND_SIMM16, (long *) (& fields->f_simm16));
87e6d782 559 break;
73589c9d 560 case OR1K_OPERAND_SIMM16_SPLIT :
1c4f3780 561 errmsg = parse_simm16_split (cd, strp, OR1K_OPERAND_SIMM16_SPLIT, (long *) (& fields->f_simm16_split));
87e6d782 562 break;
73589c9d
CS
563 case OR1K_OPERAND_UIMM16 :
564 errmsg = parse_uimm16 (cd, strp, OR1K_OPERAND_UIMM16, (unsigned long *) (& fields->f_uimm16));
565 break;
566 case OR1K_OPERAND_UIMM16_SPLIT :
1c4f3780 567 errmsg = parse_uimm16_split (cd, strp, OR1K_OPERAND_UIMM16_SPLIT, (unsigned long *) (& fields->f_uimm16_split));
73589c9d
CS
568 break;
569 case OR1K_OPERAND_UIMM6 :
570 errmsg = cgen_parse_unsigned_integer (cd, strp, OR1K_OPERAND_UIMM6, (unsigned long *) (& fields->f_uimm6));
87e6d782
NC
571 break;
572
573 default :
574 /* xgettext:c-format */
a6743a54
AM
575 opcodes_error_handler
576 (_("internal error: unrecognized field %d while parsing"),
577 opindex);
87e6d782
NC
578 abort ();
579 }
580
581 return errmsg;
582}
583
43e65147 584cgen_parse_fn * const or1k_cgen_parse_handlers[] =
87e6d782
NC
585{
586 parse_insn_normal,
587};
588
589void
73589c9d 590or1k_cgen_init_asm (CGEN_CPU_DESC cd)
87e6d782 591{
73589c9d
CS
592 or1k_cgen_init_opcode_table (cd);
593 or1k_cgen_init_ibld_table (cd);
594 cd->parse_handlers = & or1k_cgen_parse_handlers[0];
595 cd->parse_operand = or1k_cgen_parse_operand;
1620f33d
AM
596#ifdef CGEN_ASM_INIT_HOOK
597CGEN_ASM_INIT_HOOK
598#endif
87e6d782
NC
599}
600
fc7bc883
RH
601\f
602
37111cc7 603/* Regex construction routine.
fc7bc883 604
37111cc7
NC
605 This translates an opcode syntax string into a regex string,
606 by replacing any non-character syntax element (such as an
607 opcode) with the pattern '.*'
fc7bc883 608
37111cc7 609 It then compiles the regex and stores it in the opcode, for
73589c9d 610 later use by or1k_cgen_assemble_insn
fc7bc883 611
37111cc7 612 Returns NULL for success, an error message for failure. */
fc7bc883 613
43e65147 614char *
73589c9d 615or1k_cgen_build_insn_regex (CGEN_INSN *insn)
43e65147 616{
fc05c67f 617 CGEN_OPCODE *opc = (CGEN_OPCODE *) CGEN_INSN_OPCODE (insn);
fc7bc883 618 const char *mnem = CGEN_INSN_MNEMONIC (insn);
fc7bc883
RH
619 char rxbuf[CGEN_MAX_RX_ELEMENTS];
620 char *rx = rxbuf;
621 const CGEN_SYNTAX_CHAR_TYPE *syn;
622 int reg_err;
623
624 syn = CGEN_SYNTAX_STRING (CGEN_OPCODE_SYNTAX (opc));
625
f3a55c17
NC
626 /* Mnemonics come first in the syntax string. */
627 if (! CGEN_SYNTAX_MNEMONIC_P (* syn))
628 return _("missing mnemonic in syntax string");
fc7bc883
RH
629 ++syn;
630
f3a55c17
NC
631 /* Generate a case sensitive regular expression that emulates case
632 insensitive matching in the "C" locale. We cannot generate a case
633 insensitive regular expression because in Turkish locales, 'i' and 'I'
634 are not equal modulo case conversion. */
fc7bc883 635
f3a55c17
NC
636 /* Copy the literal mnemonic out of the insn. */
637 for (; *mnem; mnem++)
638 {
639 char c = *mnem;
640
641 if (ISALPHA (c))
642 {
643 *rx++ = '[';
644 *rx++ = TOLOWER (c);
645 *rx++ = TOUPPER (c);
646 *rx++ = ']';
647 }
648 else
649 *rx++ = c;
650 }
651
652 /* Copy any remaining literals from the syntax string into the rx. */
653 for(; * syn != 0 && rx <= rxbuf + (CGEN_MAX_RX_ELEMENTS - 7 - 4); ++syn)
fc7bc883 654 {
43e65147 655 if (CGEN_SYNTAX_CHAR_P (* syn))
fc7bc883 656 {
f3a55c17
NC
657 char c = CGEN_SYNTAX_CHAR (* syn);
658
43e65147 659 switch (c)
f3a55c17
NC
660 {
661 /* Escape any regex metacharacters in the syntax. */
43e65147
L
662 case '.': case '[': case '\\':
663 case '*': case '^': case '$':
fc7bc883
RH
664
665#ifdef CGEN_ESCAPE_EXTENDED_REGEX
43e65147 666 case '?': case '{': case '}':
f3a55c17
NC
667 case '(': case ')': case '*':
668 case '|': case '+': case ']':
fc7bc883 669#endif
f3a55c17
NC
670 *rx++ = '\\';
671 *rx++ = c;
672 break;
673
674 default:
675 if (ISALPHA (c))
676 {
677 *rx++ = '[';
678 *rx++ = TOLOWER (c);
679 *rx++ = TOUPPER (c);
680 *rx++ = ']';
681 }
682 else
683 *rx++ = c;
684 break;
685 }
fc7bc883
RH
686 }
687 else
688 {
f3a55c17
NC
689 /* Replace non-syntax fields with globs. */
690 *rx++ = '.';
691 *rx++ = '*';
fc7bc883
RH
692 }
693 }
694
f3a55c17 695 /* Trailing whitespace ok. */
43e65147
L
696 * rx++ = '[';
697 * rx++ = ' ';
698 * rx++ = '\t';
699 * rx++ = ']';
700 * rx++ = '*';
fc7bc883 701
f3a55c17 702 /* But anchor it after that. */
43e65147 703 * rx++ = '$';
fc7bc883
RH
704 * rx = '\0';
705
706 CGEN_INSN_RX (insn) = xmalloc (sizeof (regex_t));
f3a55c17 707 reg_err = regcomp ((regex_t *) CGEN_INSN_RX (insn), rxbuf, REG_NOSUB);
fc7bc883 708
43e65147 709 if (reg_err == 0)
fc7bc883
RH
710 return NULL;
711 else
712 {
713 static char msg[80];
f3a55c17 714
fc7bc883
RH
715 regerror (reg_err, (regex_t *) CGEN_INSN_RX (insn), msg, 80);
716 regfree ((regex_t *) CGEN_INSN_RX (insn));
717 free (CGEN_INSN_RX (insn));
718 (CGEN_INSN_RX (insn)) = NULL;
37111cc7 719 return msg;
fc7bc883
RH
720 }
721}
722
87e6d782
NC
723\f
724/* Default insn parser.
725
726 The syntax string is scanned and operands are parsed and stored in FIELDS.
727 Relocs are queued as we go via other callbacks.
728
729 ??? Note that this is currently an all-or-nothing parser. If we fail to
730 parse the instruction, we return 0 and the caller will start over from
731 the beginning. Backtracking will be necessary in parsing subexpressions,
732 but that can be handled there. Not handling backtracking here may get
733 expensive in the case of the m68k. Deal with later.
734
f3a55c17 735 Returns NULL for success, an error message for failure. */
87e6d782
NC
736
737static const char *
ffead7ae
MM
738parse_insn_normal (CGEN_CPU_DESC cd,
739 const CGEN_INSN *insn,
740 const char **strp,
741 CGEN_FIELDS *fields)
87e6d782
NC
742{
743 /* ??? Runtime added insns not handled yet. */
744 const CGEN_SYNTAX *syntax = CGEN_INSN_SYNTAX (insn);
745 const char *str = *strp;
746 const char *errmsg;
747 const char *p;
748 const CGEN_SYNTAX_CHAR_TYPE * syn;
749#ifdef CGEN_MNEMONIC_OPERANDS
750 /* FIXME: wip */
751 int past_opcode_p;
752#endif
753
754 /* For now we assume the mnemonic is first (there are no leading operands).
755 We can parse it without needing to set up operand parsing.
756 GAS's input scrubber will ensure mnemonics are lowercase, but we may
757 not be called from GAS. */
758 p = CGEN_INSN_MNEMONIC (insn);
37111cc7 759 while (*p && TOLOWER (*p) == TOLOWER (*str))
87e6d782
NC
760 ++p, ++str;
761
762 if (* p)
763 return _("unrecognized instruction");
764
765#ifndef CGEN_MNEMONIC_OPERANDS
37111cc7 766 if (* str && ! ISSPACE (* str))
87e6d782
NC
767 return _("unrecognized instruction");
768#endif
769
770 CGEN_INIT_PARSE (cd);
771 cgen_init_parse_operand (cd);
772#ifdef CGEN_MNEMONIC_OPERANDS
773 past_opcode_p = 0;
774#endif
775
776 /* We don't check for (*str != '\0') here because we want to parse
777 any trailing fake arguments in the syntax string. */
778 syn = CGEN_SYNTAX_STRING (syntax);
779
780 /* Mnemonics come first for now, ensure valid string. */
781 if (! CGEN_SYNTAX_MNEMONIC_P (* syn))
782 abort ();
783
784 ++syn;
785
786 while (* syn != 0)
787 {
788 /* Non operand chars must match exactly. */
789 if (CGEN_SYNTAX_CHAR_P (* syn))
790 {
791 /* FIXME: While we allow for non-GAS callers above, we assume the
792 first char after the mnemonic part is a space. */
793 /* FIXME: We also take inappropriate advantage of the fact that
794 GAS's input scrubber will remove extraneous blanks. */
37111cc7 795 if (TOLOWER (*str) == TOLOWER (CGEN_SYNTAX_CHAR (* syn)))
87e6d782
NC
796 {
797#ifdef CGEN_MNEMONIC_OPERANDS
798 if (CGEN_SYNTAX_CHAR(* syn) == ' ')
799 past_opcode_p = 1;
800#endif
801 ++ syn;
802 ++ str;
803 }
804 else if (*str)
805 {
806 /* Syntax char didn't match. Can't be this insn. */
807 static char msg [80];
f3a55c17 808
87e6d782
NC
809 /* xgettext:c-format */
810 sprintf (msg, _("syntax error (expected char `%c', found `%c')"),
811 CGEN_SYNTAX_CHAR(*syn), *str);
812 return msg;
813 }
814 else
815 {
816 /* Ran out of input. */
817 static char msg [80];
f3a55c17 818
87e6d782
NC
819 /* xgettext:c-format */
820 sprintf (msg, _("syntax error (expected char `%c', found end of instruction)"),
821 CGEN_SYNTAX_CHAR(*syn));
822 return msg;
823 }
824 continue;
825 }
826
c7e2358a
AM
827#ifdef CGEN_MNEMONIC_OPERANDS
828 (void) past_opcode_p;
829#endif
87e6d782 830 /* We have an operand of some sort. */
c7e2358a 831 errmsg = cd->parse_operand (cd, CGEN_SYNTAX_FIELD (*syn), &str, fields);
87e6d782
NC
832 if (errmsg)
833 return errmsg;
834
835 /* Done with this operand, continue with next one. */
836 ++ syn;
837 }
838
839 /* If we're at the end of the syntax string, we're done. */
840 if (* syn == 0)
841 {
842 /* FIXME: For the moment we assume a valid `str' can only contain
843 blanks now. IE: We needn't try again with a longer version of
844 the insn and it is assumed that longer versions of insns appear
845 before shorter ones (eg: lsr r2,r3,1 vs lsr r2,r3). */
37111cc7 846 while (ISSPACE (* str))
87e6d782
NC
847 ++ str;
848
849 if (* str != '\0')
850 return _("junk at end of line"); /* FIXME: would like to include `str' */
851
852 return NULL;
853 }
854
855 /* We couldn't parse it. */
856 return _("unrecognized instruction");
857}
858\f
859/* Main entry point.
860 This routine is called for each instruction to be assembled.
861 STR points to the insn to be assembled.
862 We assume all necessary tables have been initialized.
863 The assembled instruction, less any fixups, is stored in BUF.
864 Remember that if CGEN_INT_INSN_P then BUF is an int and thus the value
865 still needs to be converted to target byte order, otherwise BUF is an array
866 of bytes in target byte order.
867 The result is a pointer to the insn's entry in the opcode table,
868 or NULL if an error occured (an error message will have already been
869 printed).
870
871 Note that when processing (non-alias) macro-insns,
872 this function recurses.
873
874 ??? It's possible to make this cpu-independent.
875 One would have to deal with a few minor things.
876 At this point in time doing so would be more of a curiosity than useful
877 [for example this file isn't _that_ big], but keeping the possibility in
878 mind helps keep the design clean. */
879
880const CGEN_INSN *
73589c9d 881or1k_cgen_assemble_insn (CGEN_CPU_DESC cd,
ffead7ae
MM
882 const char *str,
883 CGEN_FIELDS *fields,
884 CGEN_INSN_BYTES_PTR buf,
885 char **errmsg)
87e6d782
NC
886{
887 const char *start;
888 CGEN_INSN_LIST *ilist;
889 const char *parse_errmsg = NULL;
890 const char *insert_errmsg = NULL;
fc7bc883 891 int recognized_mnemonic = 0;
87e6d782
NC
892
893 /* Skip leading white space. */
37111cc7 894 while (ISSPACE (* str))
87e6d782
NC
895 ++ str;
896
897 /* The instructions are stored in hashed lists.
898 Get the first in the list. */
899 ilist = CGEN_ASM_LOOKUP_INSN (cd, str);
900
901 /* Keep looking until we find a match. */
87e6d782
NC
902 start = str;
903 for ( ; ilist != NULL ; ilist = CGEN_ASM_NEXT_INSN (ilist))
904 {
905 const CGEN_INSN *insn = ilist->insn;
fc7bc883 906 recognized_mnemonic = 1;
87e6d782 907
43e65147 908#ifdef CGEN_VALIDATE_INSN_SUPPORTED
f3a55c17
NC
909 /* Not usually needed as unsupported opcodes
910 shouldn't be in the hash lists. */
87e6d782 911 /* Is this insn supported by the selected cpu? */
73589c9d 912 if (! or1k_cgen_insn_supported (cd, insn))
87e6d782
NC
913 continue;
914#endif
b11dcf4e 915 /* If the RELAXED attribute is set, this is an insn that shouldn't be
87e6d782
NC
916 chosen immediately. Instead, it is used during assembler/linker
917 relaxation if possible. */
b11dcf4e 918 if (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_RELAXED) != 0)
87e6d782
NC
919 continue;
920
921 str = start;
922
f3a55c17 923 /* Skip this insn if str doesn't look right lexically. */
fc7bc883
RH
924 if (CGEN_INSN_RX (insn) != NULL &&
925 regexec ((regex_t *) CGEN_INSN_RX (insn), str, 0, NULL, 0) == REG_NOMATCH)
926 continue;
927
87e6d782
NC
928 /* Allow parse/insert handlers to obtain length of insn. */
929 CGEN_FIELDS_BITSIZE (fields) = CGEN_INSN_BITSIZE (insn);
930
931 parse_errmsg = CGEN_PARSE_FN (cd, insn) (cd, insn, & str, fields);
932 if (parse_errmsg != NULL)
933 continue;
934
f3a55c17 935 /* ??? 0 is passed for `pc'. */
87e6d782
NC
936 insert_errmsg = CGEN_INSERT_FN (cd, insn) (cd, insn, fields, buf,
937 (bfd_vma) 0);
938 if (insert_errmsg != NULL)
939 continue;
940
941 /* It is up to the caller to actually output the insn and any
942 queued relocs. */
943 return insn;
944 }
945
946 {
947 static char errbuf[150];
87e6d782 948 const char *tmp_errmsg;
c7e2358a
AM
949#ifdef CGEN_VERBOSE_ASSEMBLER_ERRORS
950#define be_verbose 1
87e6d782 951#else
c7e2358a 952#define be_verbose 0
87e6d782 953#endif
c7e2358a
AM
954
955 if (be_verbose)
956 {
957 /* If requesting verbose error messages, use insert_errmsg.
958 Failing that, use parse_errmsg. */
959 tmp_errmsg = (insert_errmsg ? insert_errmsg :
960 parse_errmsg ? parse_errmsg :
961 recognized_mnemonic ?
962 _("unrecognized form of instruction") :
963 _("unrecognized instruction"));
964
965 if (strlen (start) > 50)
966 /* xgettext:c-format */
967 sprintf (errbuf, "%s `%.50s...'", tmp_errmsg, start);
43e65147 968 else
c7e2358a
AM
969 /* xgettext:c-format */
970 sprintf (errbuf, "%s `%.50s'", tmp_errmsg, start);
971 }
972 else
973 {
974 if (strlen (start) > 50)
975 /* xgettext:c-format */
976 sprintf (errbuf, _("bad instruction `%.50s...'"), start);
43e65147 977 else
c7e2358a
AM
978 /* xgettext:c-format */
979 sprintf (errbuf, _("bad instruction `%.50s'"), start);
980 }
43e65147 981
87e6d782
NC
982 *errmsg = errbuf;
983 return NULL;
984 }
985}
This page took 1.005497 seconds and 4 git commands to generate.