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