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