]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - opcodes/ms1-asm.c
2005-05-07 Paul Brook <paul@codesourcery.com>
[thirdparty/binutils-gdb.git] / opcodes / ms1-asm.c
CommitLineData
ac188222
DB
1/* Assembler interface for targets using CGEN. -*- C -*-
2 CGEN: Cpu tools GENerator
3
47b0e7ad
NC
4 THIS FILE IS MACHINE GENERATED WITH CGEN.
5 - the resultant file is machine generated, cgen-asm.in isn't
ac188222 6
47b0e7ad
NC
7 Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2005
8 Free Software Foundation, Inc.
ac188222 9
47b0e7ad 10 This file is part of the GNU Binutils and GDB, the GNU debugger.
ac188222 11
47b0e7ad
NC
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 2, or (at your option)
15 any later version.
ac188222 16
47b0e7ad
NC
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
ac188222 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. */
ac188222
DB
25
26/* ??? Eventually more and more of this stuff can go to cpu-independent files.
27 Keep that in mind. */
28
29#include "sysdep.h"
30#include <stdio.h>
31#include "ansidecl.h"
32#include "bfd.h"
33#include "symcat.h"
34#include "ms1-desc.h"
35#include "ms1-opc.h"
36#include "opintl.h"
37#include "xregex.h"
38#include "libiberty.h"
39#include "safe-ctype.h"
40
41#undef min
42#define min(a,b) ((a) < (b) ? (a) : (b))
43#undef max
44#define max(a,b) ((a) > (b) ? (a) : (b))
45
46static const char * parse_insn_normal
47 (CGEN_CPU_DESC, const CGEN_INSN *, const char **, CGEN_FIELDS *);
48\f
49/* -- assembler routines inserted here. */
50
51/* -- asm.c */
52static int signed_out_of_bounds (long);
53static const char * parse_imm16 (CGEN_CPU_DESC, const char **, int, long *);
54static const char * parse_dup (CGEN_CPU_DESC, const char **, int, long *);
55static const char * parse_ball (CGEN_CPU_DESC, const char **, int, long *);
56static const char * parse_xmode (CGEN_CPU_DESC, const char **, int, long *);
57static const char * parse_rc (CGEN_CPU_DESC, const char **, int, long *);
58static const char * parse_cbrb (CGEN_CPU_DESC, const char **, int, long *);
59static const char * parse_rbbc (CGEN_CPU_DESC, const char **, int, long *);
60static const char * parse_type (CGEN_CPU_DESC, const char **, int, long *);
61
62/* Range checking for signed numbers. Returns 0 if acceptable
63 and 1 if the value is out of bounds for a signed quantity. */
64
65static int
66signed_out_of_bounds (long val)
67{
68 if ((val < -32768) || (val > 32767))
69 return 1;
70 return 0;
71}
72
73static const char *
74parse_imm16 (CGEN_CPU_DESC cd,
75 const char **strp,
76 int opindex,
77 long *valuep)
78{
79 const char *errmsg;
80 enum cgen_parse_operand_result result_type;
81 bfd_reloc_code_real_type code = BFD_RELOC_NONE;
82 bfd_vma value;
83
84 /* Is it a control transfer instructions? */
85 if (opindex == (CGEN_OPERAND_TYPE) MS1_OPERAND_IMM16O)
86 {
87 code = BFD_RELOC_16_PCREL;
88 errmsg = cgen_parse_address (cd, strp, opindex, code,
89 & result_type, & value);
90 if (errmsg == NULL)
91 {
92 if (signed_out_of_bounds (value))
93 errmsg = _("Operand out of range. Must be between -32768 and 32767.");
94 }
95 *valuep = value;
96 return errmsg;
97 }
98
99 /* If it's not a control transfer instruction, then
100 we have to check for %OP relocating operators. */
101 if (strncmp (*strp, "%hi16", 5) == 0)
102 {
103 *strp += 5;
104 code = BFD_RELOC_HI16;
105 }
106 else if (strncmp (*strp, "%lo16", 5) == 0)
107 {
108 *strp += 5;
109 code = BFD_RELOC_LO16;
110 }
111
112 /* If we found a %OP relocating operator, then parse it as an address.
113 If not, we need to parse it as an integer, either signed or unsigned
114 depending on which operand type we have. */
115 if (code != BFD_RELOC_NONE)
116 {
117 /* %OP relocating operator found. */
118 errmsg = cgen_parse_address (cd, strp, opindex, code,
119 & result_type, & value);
120 if (errmsg == NULL)
121 {
122 switch (result_type)
123 {
124 case (CGEN_PARSE_OPERAND_RESULT_NUMBER):
125 if (code == BFD_RELOC_HI16)
126 value = (value >> 16) & 0xFFFF;
127 else if (code == BFD_RELOC_LO16)
128 value = value & 0xFFFF;
129 else
130 errmsg = _("Biiiig Trouble in parse_imm16!");
131 break;
132
133 case (CGEN_PARSE_OPERAND_RESULT_QUEUED):
134 /* No special processing for this case. */
135 break;
136
137 default:
138 errmsg = _("%operator operand is not a symbol");
139 break;
140 }
141 }
142 *valuep = value;
143 }
144 else
145 {
146 /* Parse hex values like 0xffff as unsigned, and sign extend
147 them manually. */
148 int parse_signed = (opindex == (CGEN_OPERAND_TYPE)MS1_OPERAND_IMM16);
149
150 if ((*strp)[0] == '0'
151 && ((*strp)[1] == 'x' || (*strp)[1] == 'X'))
152 parse_signed = 0;
153
154 /* No relocating operator. Parse as an number. */
155 if (parse_signed)
156 {
157 /* Parse as as signed integer. */
158
159 errmsg = cgen_parse_signed_integer (cd, strp, opindex, valuep);
160
161 if (errmsg == NULL)
162 {
163#if 0
164 /* Manual range checking is needed for the signed case. */
165 if (*valuep & 0x8000)
166 value = 0xffff0000 | *valuep;
167 else
168 value = *valuep;
169
170 if (signed_out_of_bounds (value))
171 errmsg = _("Operand out of range. Must be between -32768 and 32767.");
172 /* Truncate to 16 bits. This is necessary
173 because cgen will have sign extended *valuep. */
174 *valuep &= 0xFFFF;
175#endif
176 }
177 }
178 else
179 {
180 /* MS1_OPERAND_IMM16Z. Parse as an unsigned integer. */
181 errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
182
183 if (opindex == (CGEN_OPERAND_TYPE)MS1_OPERAND_IMM16
184 && *valuep >= 0x8000
185 && *valuep <= 0xffff)
186 *valuep -= 0x10000;
187 }
188 }
189
190 return errmsg;
191}
192
193
194static const char *
195parse_dup (CGEN_CPU_DESC cd,
196 const char **strp,
197 int opindex,
198 long *valuep)
199{
200 const char *errmsg = NULL;
201
202 if (strncmp (*strp, "dup", 3) == 0 || strncmp (*strp, "DUP", 3) == 0)
203 {
204 *strp += 3;
205 *valuep = 1;
206 }
207 else if (strncmp (*strp, "xx", 2) == 0 || strncmp (*strp, "XX", 2) == 0)
208 {
209 *strp += 2;
210 *valuep = 0;
211 }
212 else
213 errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
214
215 return errmsg;
216}
217
218
219static const char *
220parse_ball (CGEN_CPU_DESC cd,
221 const char **strp,
222 int opindex,
223 long *valuep)
224{
225 const char *errmsg = NULL;
226
227 if (strncmp (*strp, "all", 3) == 0 || strncmp (*strp, "ALL", 3) == 0)
228 {
229 *strp += 3;
230 *valuep = 1;
231 }
232 else if (strncmp (*strp, "one", 3) == 0 || strncmp (*strp, "ONE", 3) == 0)
233 {
234 *strp += 3;
235 *valuep = 0;
236 }
237 else
238 errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
239
240 return errmsg;
241}
242
243static const char *
244parse_xmode (CGEN_CPU_DESC cd,
245 const char **strp,
246 int opindex,
247 long *valuep)
248{
249 const char *errmsg = NULL;
250
251 if (strncmp (*strp, "pm", 2) == 0 || strncmp (*strp, "PM", 2) == 0)
252 {
253 *strp += 2;
254 *valuep = 1;
255 }
256 else if (strncmp (*strp, "xm", 2) == 0 || strncmp (*strp, "XM", 2) == 0)
257 {
258 *strp += 2;
259 *valuep = 0;
260 }
261 else
262 errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
263
264 return errmsg;
265}
266
267static const char *
268parse_rc (CGEN_CPU_DESC cd,
269 const char **strp,
270 int opindex,
271 long *valuep)
272{
273 const char *errmsg = NULL;
274
275 if (strncmp (*strp, "r", 1) == 0 || strncmp (*strp, "R", 1) == 0)
276 {
277 *strp += 1;
278 *valuep = 1;
279 }
280 else if (strncmp (*strp, "c", 1) == 0 || strncmp (*strp, "C", 1) == 0)
281 {
282 *strp += 1;
283 *valuep = 0;
284 }
285 else
286 errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
287
288 return errmsg;
289}
290
291static const char *
292parse_cbrb (CGEN_CPU_DESC cd,
293 const char **strp,
294 int opindex,
295 long *valuep)
296{
297 const char *errmsg = NULL;
298
299 if (strncmp (*strp, "rb", 2) == 0 || strncmp (*strp, "RB", 2) == 0)
300 {
301 *strp += 2;
302 *valuep = 1;
303 }
304 else if (strncmp (*strp, "cb", 2) == 0 || strncmp (*strp, "CB", 2) == 0)
305 {
306 *strp += 2;
307 *valuep = 0;
308 }
309 else
310 errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
311
312 return errmsg;
313}
314
315static const char *
316parse_rbbc (CGEN_CPU_DESC cd,
317 const char **strp,
318 int opindex,
319 long *valuep)
320{
321 const char *errmsg = NULL;
322
323 if (strncmp (*strp, "rt", 2) == 0 || strncmp (*strp, "RT", 2) == 0)
324 {
325 *strp += 2;
326 *valuep = 0;
327 }
328 else if (strncmp (*strp, "br1", 3) == 0 || strncmp (*strp, "BR1", 3) == 0)
329 {
330 *strp += 3;
331 *valuep = 1;
332 }
333 else if (strncmp (*strp, "br2", 3) == 0 || strncmp (*strp, "BR2", 3) == 0)
334 {
335 *strp += 3;
336 *valuep = 2;
337 }
338 else if (strncmp (*strp, "cs", 2) == 0 || strncmp (*strp, "CS", 2) == 0)
339 {
340 *strp += 2;
341 *valuep = 3;
342 }
343 else
344 errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
345
346 return errmsg;
347}
348
349static const char *
350parse_type (CGEN_CPU_DESC cd,
351 const char **strp,
352 int opindex,
353 long *valuep)
354{
355 const char *errmsg = NULL;
356
357 if (strncmp (*strp, "odd", 3) == 0 || strncmp (*strp, "ODD", 3) == 0)
358 {
359 *strp += 3;
360 *valuep = 0;
361 }
362 else if (strncmp (*strp, "even", 4) == 0 || strncmp (*strp, "EVEN", 4) == 0)
363 {
364 *strp += 4;
365 *valuep = 1;
366 }
367 else if (strncmp (*strp, "oe", 2) == 0 || strncmp (*strp, "OE", 2) == 0)
368 {
369 *strp += 2;
370 *valuep = 2;
371 }
372 else
373 errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
374
375 if ((errmsg == NULL) && (*valuep == 3))
376 errmsg = _("invalid operand. type may have values 0,1,2 only.");
377
378 return errmsg;
379}
380
381/* -- dis.c */
382
383const char * ms1_cgen_parse_operand
47b0e7ad 384 (CGEN_CPU_DESC, int, const char **, CGEN_FIELDS *);
ac188222
DB
385
386/* Main entry point for operand parsing.
387
388 This function is basically just a big switch statement. Earlier versions
389 used tables to look up the function to use, but
390 - if the table contains both assembler and disassembler functions then
391 the disassembler contains much of the assembler and vice-versa,
392 - there's a lot of inlining possibilities as things grow,
393 - using a switch statement avoids the function call overhead.
394
395 This function could be moved into `parse_insn_normal', but keeping it
396 separate makes clear the interface between `parse_insn_normal' and each of
397 the handlers. */
398
399const char *
47b0e7ad
NC
400ms1_cgen_parse_operand (CGEN_CPU_DESC cd,
401 int opindex,
402 const char ** strp,
403 CGEN_FIELDS * fields)
ac188222
DB
404{
405 const char * errmsg = NULL;
406 /* Used by scalar operands that still need to be parsed. */
407 long junk ATTRIBUTE_UNUSED;
408
409 switch (opindex)
410 {
411 case MS1_OPERAND_A23 :
412 errmsg = cgen_parse_unsigned_integer (cd, strp, MS1_OPERAND_A23, (unsigned long *) (& fields->f_a23));
413 break;
414 case MS1_OPERAND_BALL :
415 errmsg = parse_ball (cd, strp, MS1_OPERAND_BALL, (unsigned long *) (& fields->f_ball));
416 break;
417 case MS1_OPERAND_BALL2 :
418 errmsg = parse_ball (cd, strp, MS1_OPERAND_BALL2, (unsigned long *) (& fields->f_ball2));
419 break;
420 case MS1_OPERAND_BANKADDR :
421 errmsg = cgen_parse_unsigned_integer (cd, strp, MS1_OPERAND_BANKADDR, (unsigned long *) (& fields->f_bankaddr));
422 break;
423 case MS1_OPERAND_BRC :
424 errmsg = cgen_parse_unsigned_integer (cd, strp, MS1_OPERAND_BRC, (unsigned long *) (& fields->f_brc));
425 break;
426 case MS1_OPERAND_BRC2 :
427 errmsg = cgen_parse_unsigned_integer (cd, strp, MS1_OPERAND_BRC2, (unsigned long *) (& fields->f_brc2));
428 break;
429 case MS1_OPERAND_CBRB :
430 errmsg = parse_cbrb (cd, strp, MS1_OPERAND_CBRB, (unsigned long *) (& fields->f_cbrb));
431 break;
432 case MS1_OPERAND_CBS :
433 errmsg = cgen_parse_unsigned_integer (cd, strp, MS1_OPERAND_CBS, (unsigned long *) (& fields->f_cbs));
434 break;
435 case MS1_OPERAND_CBX :
436 errmsg = cgen_parse_unsigned_integer (cd, strp, MS1_OPERAND_CBX, (unsigned long *) (& fields->f_cbx));
437 break;
438 case MS1_OPERAND_CCB :
439 errmsg = cgen_parse_unsigned_integer (cd, strp, MS1_OPERAND_CCB, (unsigned long *) (& fields->f_ccb));
440 break;
441 case MS1_OPERAND_CDB :
442 errmsg = cgen_parse_unsigned_integer (cd, strp, MS1_OPERAND_CDB, (unsigned long *) (& fields->f_cdb));
443 break;
444 case MS1_OPERAND_CELL :
445 errmsg = cgen_parse_unsigned_integer (cd, strp, MS1_OPERAND_CELL, (unsigned long *) (& fields->f_cell));
446 break;
447 case MS1_OPERAND_COLNUM :
448 errmsg = cgen_parse_unsigned_integer (cd, strp, MS1_OPERAND_COLNUM, (unsigned long *) (& fields->f_colnum));
449 break;
450 case MS1_OPERAND_CONTNUM :
451 errmsg = cgen_parse_unsigned_integer (cd, strp, MS1_OPERAND_CONTNUM, (unsigned long *) (& fields->f_contnum));
452 break;
453 case MS1_OPERAND_CR :
454 errmsg = cgen_parse_unsigned_integer (cd, strp, MS1_OPERAND_CR, (unsigned long *) (& fields->f_cr));
455 break;
456 case MS1_OPERAND_CTXDISP :
457 errmsg = cgen_parse_unsigned_integer (cd, strp, MS1_OPERAND_CTXDISP, (unsigned long *) (& fields->f_ctxdisp));
458 break;
459 case MS1_OPERAND_DUP :
460 errmsg = parse_dup (cd, strp, MS1_OPERAND_DUP, (unsigned long *) (& fields->f_dup));
461 break;
462 case MS1_OPERAND_FBDISP :
463 errmsg = cgen_parse_unsigned_integer (cd, strp, MS1_OPERAND_FBDISP, (unsigned long *) (& fields->f_fbdisp));
464 break;
465 case MS1_OPERAND_FBINCR :
466 errmsg = cgen_parse_unsigned_integer (cd, strp, MS1_OPERAND_FBINCR, (unsigned long *) (& fields->f_fbincr));
467 break;
468 case MS1_OPERAND_FRDR :
469 errmsg = cgen_parse_keyword (cd, strp, & ms1_cgen_opval_h_spr, & fields->f_dr);
470 break;
471 case MS1_OPERAND_FRDRRR :
472 errmsg = cgen_parse_keyword (cd, strp, & ms1_cgen_opval_h_spr, & fields->f_drrr);
473 break;
474 case MS1_OPERAND_FRSR1 :
475 errmsg = cgen_parse_keyword (cd, strp, & ms1_cgen_opval_h_spr, & fields->f_sr1);
476 break;
477 case MS1_OPERAND_FRSR2 :
478 errmsg = cgen_parse_keyword (cd, strp, & ms1_cgen_opval_h_spr, & fields->f_sr2);
479 break;
480 case MS1_OPERAND_ID :
481 errmsg = cgen_parse_unsigned_integer (cd, strp, MS1_OPERAND_ID, (unsigned long *) (& fields->f_id));
482 break;
483 case MS1_OPERAND_IMM16 :
484 errmsg = parse_imm16 (cd, strp, MS1_OPERAND_IMM16, (long *) (& fields->f_imm16s));
485 break;
486 case MS1_OPERAND_IMM16O :
487 errmsg = parse_imm16 (cd, strp, MS1_OPERAND_IMM16O, (unsigned long *) (& fields->f_imm16s));
488 break;
489 case MS1_OPERAND_IMM16Z :
490 errmsg = parse_imm16 (cd, strp, MS1_OPERAND_IMM16Z, (unsigned long *) (& fields->f_imm16u));
491 break;
492 case MS1_OPERAND_INCAMT :
493 errmsg = cgen_parse_unsigned_integer (cd, strp, MS1_OPERAND_INCAMT, (unsigned long *) (& fields->f_incamt));
494 break;
495 case MS1_OPERAND_INCR :
496 errmsg = cgen_parse_unsigned_integer (cd, strp, MS1_OPERAND_INCR, (unsigned long *) (& fields->f_incr));
497 break;
498 case MS1_OPERAND_LENGTH :
499 errmsg = cgen_parse_unsigned_integer (cd, strp, MS1_OPERAND_LENGTH, (unsigned long *) (& fields->f_length));
500 break;
501 case MS1_OPERAND_MASK :
502 errmsg = cgen_parse_unsigned_integer (cd, strp, MS1_OPERAND_MASK, (unsigned long *) (& fields->f_mask));
503 break;
504 case MS1_OPERAND_MASK1 :
505 errmsg = cgen_parse_unsigned_integer (cd, strp, MS1_OPERAND_MASK1, (unsigned long *) (& fields->f_mask1));
506 break;
507 case MS1_OPERAND_MODE :
508 errmsg = cgen_parse_unsigned_integer (cd, strp, MS1_OPERAND_MODE, (unsigned long *) (& fields->f_mode));
509 break;
510 case MS1_OPERAND_PERM :
511 errmsg = cgen_parse_unsigned_integer (cd, strp, MS1_OPERAND_PERM, (unsigned long *) (& fields->f_perm));
512 break;
513 case MS1_OPERAND_RBBC :
514 errmsg = parse_rbbc (cd, strp, MS1_OPERAND_RBBC, (unsigned long *) (& fields->f_rbbc));
515 break;
516 case MS1_OPERAND_RC :
517 errmsg = parse_rc (cd, strp, MS1_OPERAND_RC, (unsigned long *) (& fields->f_rc));
518 break;
519 case MS1_OPERAND_RC1 :
520 errmsg = parse_rc (cd, strp, MS1_OPERAND_RC1, (unsigned long *) (& fields->f_rc1));
521 break;
522 case MS1_OPERAND_RC2 :
523 errmsg = parse_rc (cd, strp, MS1_OPERAND_RC2, (unsigned long *) (& fields->f_rc2));
524 break;
525 case MS1_OPERAND_RCNUM :
526 errmsg = cgen_parse_unsigned_integer (cd, strp, MS1_OPERAND_RCNUM, (unsigned long *) (& fields->f_rcnum));
527 break;
528 case MS1_OPERAND_RDA :
529 errmsg = cgen_parse_unsigned_integer (cd, strp, MS1_OPERAND_RDA, (unsigned long *) (& fields->f_rda));
530 break;
531 case MS1_OPERAND_ROWNUM :
532 errmsg = cgen_parse_unsigned_integer (cd, strp, MS1_OPERAND_ROWNUM, (unsigned long *) (& fields->f_rownum));
533 break;
534 case MS1_OPERAND_ROWNUM1 :
535 errmsg = cgen_parse_unsigned_integer (cd, strp, MS1_OPERAND_ROWNUM1, (unsigned long *) (& fields->f_rownum1));
536 break;
537 case MS1_OPERAND_ROWNUM2 :
538 errmsg = cgen_parse_unsigned_integer (cd, strp, MS1_OPERAND_ROWNUM2, (unsigned long *) (& fields->f_rownum2));
539 break;
540 case MS1_OPERAND_SIZE :
541 errmsg = cgen_parse_unsigned_integer (cd, strp, MS1_OPERAND_SIZE, (unsigned long *) (& fields->f_size));
542 break;
543 case MS1_OPERAND_TYPE :
544 errmsg = parse_type (cd, strp, MS1_OPERAND_TYPE, (unsigned long *) (& fields->f_type));
545 break;
546 case MS1_OPERAND_WR :
547 errmsg = cgen_parse_unsigned_integer (cd, strp, MS1_OPERAND_WR, (unsigned long *) (& fields->f_wr));
548 break;
549 case MS1_OPERAND_XMODE :
550 errmsg = parse_xmode (cd, strp, MS1_OPERAND_XMODE, (unsigned long *) (& fields->f_xmode));
551 break;
552
553 default :
554 /* xgettext:c-format */
555 fprintf (stderr, _("Unrecognized field %d while parsing.\n"), opindex);
556 abort ();
557 }
558
559 return errmsg;
560}
561
562cgen_parse_fn * const ms1_cgen_parse_handlers[] =
563{
564 parse_insn_normal,
565};
566
567void
47b0e7ad 568ms1_cgen_init_asm (CGEN_CPU_DESC cd)
ac188222
DB
569{
570 ms1_cgen_init_opcode_table (cd);
571 ms1_cgen_init_ibld_table (cd);
572 cd->parse_handlers = & ms1_cgen_parse_handlers[0];
573 cd->parse_operand = ms1_cgen_parse_operand;
574}
575
576\f
577
578/* Regex construction routine.
579
580 This translates an opcode syntax string into a regex string,
581 by replacing any non-character syntax element (such as an
582 opcode) with the pattern '.*'
583
584 It then compiles the regex and stores it in the opcode, for
585 later use by ms1_cgen_assemble_insn
586
587 Returns NULL for success, an error message for failure. */
588
589char *
590ms1_cgen_build_insn_regex (CGEN_INSN *insn)
591{
592 CGEN_OPCODE *opc = (CGEN_OPCODE *) CGEN_INSN_OPCODE (insn);
593 const char *mnem = CGEN_INSN_MNEMONIC (insn);
594 char rxbuf[CGEN_MAX_RX_ELEMENTS];
595 char *rx = rxbuf;
596 const CGEN_SYNTAX_CHAR_TYPE *syn;
597 int reg_err;
598
599 syn = CGEN_SYNTAX_STRING (CGEN_OPCODE_SYNTAX (opc));
600
601 /* Mnemonics come first in the syntax string. */
602 if (! CGEN_SYNTAX_MNEMONIC_P (* syn))
603 return _("missing mnemonic in syntax string");
604 ++syn;
605
606 /* Generate a case sensitive regular expression that emulates case
607 insensitive matching in the "C" locale. We cannot generate a case
608 insensitive regular expression because in Turkish locales, 'i' and 'I'
609 are not equal modulo case conversion. */
610
611 /* Copy the literal mnemonic out of the insn. */
612 for (; *mnem; mnem++)
613 {
614 char c = *mnem;
615
616 if (ISALPHA (c))
617 {
618 *rx++ = '[';
619 *rx++ = TOLOWER (c);
620 *rx++ = TOUPPER (c);
621 *rx++ = ']';
622 }
623 else
624 *rx++ = c;
625 }
626
627 /* Copy any remaining literals from the syntax string into the rx. */
628 for(; * syn != 0 && rx <= rxbuf + (CGEN_MAX_RX_ELEMENTS - 7 - 4); ++syn)
629 {
630 if (CGEN_SYNTAX_CHAR_P (* syn))
631 {
632 char c = CGEN_SYNTAX_CHAR (* syn);
633
634 switch (c)
635 {
636 /* Escape any regex metacharacters in the syntax. */
637 case '.': case '[': case '\\':
638 case '*': case '^': case '$':
639
640#ifdef CGEN_ESCAPE_EXTENDED_REGEX
641 case '?': case '{': case '}':
642 case '(': case ')': case '*':
643 case '|': case '+': case ']':
644#endif
645 *rx++ = '\\';
646 *rx++ = c;
647 break;
648
649 default:
650 if (ISALPHA (c))
651 {
652 *rx++ = '[';
653 *rx++ = TOLOWER (c);
654 *rx++ = TOUPPER (c);
655 *rx++ = ']';
656 }
657 else
658 *rx++ = c;
659 break;
660 }
661 }
662 else
663 {
664 /* Replace non-syntax fields with globs. */
665 *rx++ = '.';
666 *rx++ = '*';
667 }
668 }
669
670 /* Trailing whitespace ok. */
671 * rx++ = '[';
672 * rx++ = ' ';
673 * rx++ = '\t';
674 * rx++ = ']';
675 * rx++ = '*';
676
677 /* But anchor it after that. */
678 * rx++ = '$';
679 * rx = '\0';
680
681 CGEN_INSN_RX (insn) = xmalloc (sizeof (regex_t));
682 reg_err = regcomp ((regex_t *) CGEN_INSN_RX (insn), rxbuf, REG_NOSUB);
683
684 if (reg_err == 0)
685 return NULL;
686 else
687 {
688 static char msg[80];
689
690 regerror (reg_err, (regex_t *) CGEN_INSN_RX (insn), msg, 80);
691 regfree ((regex_t *) CGEN_INSN_RX (insn));
692 free (CGEN_INSN_RX (insn));
693 (CGEN_INSN_RX (insn)) = NULL;
694 return msg;
695 }
696}
697
698\f
699/* Default insn parser.
700
701 The syntax string is scanned and operands are parsed and stored in FIELDS.
702 Relocs are queued as we go via other callbacks.
703
704 ??? Note that this is currently an all-or-nothing parser. If we fail to
705 parse the instruction, we return 0 and the caller will start over from
706 the beginning. Backtracking will be necessary in parsing subexpressions,
707 but that can be handled there. Not handling backtracking here may get
708 expensive in the case of the m68k. Deal with later.
709
710 Returns NULL for success, an error message for failure. */
711
712static const char *
713parse_insn_normal (CGEN_CPU_DESC cd,
714 const CGEN_INSN *insn,
715 const char **strp,
716 CGEN_FIELDS *fields)
717{
718 /* ??? Runtime added insns not handled yet. */
719 const CGEN_SYNTAX *syntax = CGEN_INSN_SYNTAX (insn);
720 const char *str = *strp;
721 const char *errmsg;
722 const char *p;
723 const CGEN_SYNTAX_CHAR_TYPE * syn;
724#ifdef CGEN_MNEMONIC_OPERANDS
725 /* FIXME: wip */
726 int past_opcode_p;
727#endif
728
729 /* For now we assume the mnemonic is first (there are no leading operands).
730 We can parse it without needing to set up operand parsing.
731 GAS's input scrubber will ensure mnemonics are lowercase, but we may
732 not be called from GAS. */
733 p = CGEN_INSN_MNEMONIC (insn);
734 while (*p && TOLOWER (*p) == TOLOWER (*str))
735 ++p, ++str;
736
737 if (* p)
738 return _("unrecognized instruction");
739
740#ifndef CGEN_MNEMONIC_OPERANDS
741 if (* str && ! ISSPACE (* str))
742 return _("unrecognized instruction");
743#endif
744
745 CGEN_INIT_PARSE (cd);
746 cgen_init_parse_operand (cd);
747#ifdef CGEN_MNEMONIC_OPERANDS
748 past_opcode_p = 0;
749#endif
750
751 /* We don't check for (*str != '\0') here because we want to parse
752 any trailing fake arguments in the syntax string. */
753 syn = CGEN_SYNTAX_STRING (syntax);
754
755 /* Mnemonics come first for now, ensure valid string. */
756 if (! CGEN_SYNTAX_MNEMONIC_P (* syn))
757 abort ();
758
759 ++syn;
760
761 while (* syn != 0)
762 {
763 /* Non operand chars must match exactly. */
764 if (CGEN_SYNTAX_CHAR_P (* syn))
765 {
766 /* FIXME: While we allow for non-GAS callers above, we assume the
767 first char after the mnemonic part is a space. */
768 /* FIXME: We also take inappropriate advantage of the fact that
769 GAS's input scrubber will remove extraneous blanks. */
770 if (TOLOWER (*str) == TOLOWER (CGEN_SYNTAX_CHAR (* syn)))
771 {
772#ifdef CGEN_MNEMONIC_OPERANDS
773 if (CGEN_SYNTAX_CHAR(* syn) == ' ')
774 past_opcode_p = 1;
775#endif
776 ++ syn;
777 ++ str;
778 }
779 else if (*str)
780 {
781 /* Syntax char didn't match. Can't be this insn. */
782 static char msg [80];
783
784 /* xgettext:c-format */
785 sprintf (msg, _("syntax error (expected char `%c', found `%c')"),
786 CGEN_SYNTAX_CHAR(*syn), *str);
787 return msg;
788 }
789 else
790 {
791 /* Ran out of input. */
792 static char msg [80];
793
794 /* xgettext:c-format */
795 sprintf (msg, _("syntax error (expected char `%c', found end of instruction)"),
796 CGEN_SYNTAX_CHAR(*syn));
797 return msg;
798 }
799 continue;
800 }
801
802 /* We have an operand of some sort. */
803 errmsg = cd->parse_operand (cd, CGEN_SYNTAX_FIELD (*syn),
804 &str, fields);
805 if (errmsg)
806 return errmsg;
807
808 /* Done with this operand, continue with next one. */
809 ++ syn;
810 }
811
812 /* If we're at the end of the syntax string, we're done. */
813 if (* syn == 0)
814 {
815 /* FIXME: For the moment we assume a valid `str' can only contain
816 blanks now. IE: We needn't try again with a longer version of
817 the insn and it is assumed that longer versions of insns appear
818 before shorter ones (eg: lsr r2,r3,1 vs lsr r2,r3). */
819 while (ISSPACE (* str))
820 ++ str;
821
822 if (* str != '\0')
823 return _("junk at end of line"); /* FIXME: would like to include `str' */
824
825 return NULL;
826 }
827
828 /* We couldn't parse it. */
829 return _("unrecognized instruction");
830}
831\f
832/* Main entry point.
833 This routine is called for each instruction to be assembled.
834 STR points to the insn to be assembled.
835 We assume all necessary tables have been initialized.
836 The assembled instruction, less any fixups, is stored in BUF.
837 Remember that if CGEN_INT_INSN_P then BUF is an int and thus the value
838 still needs to be converted to target byte order, otherwise BUF is an array
839 of bytes in target byte order.
840 The result is a pointer to the insn's entry in the opcode table,
841 or NULL if an error occured (an error message will have already been
842 printed).
843
844 Note that when processing (non-alias) macro-insns,
845 this function recurses.
846
847 ??? It's possible to make this cpu-independent.
848 One would have to deal with a few minor things.
849 At this point in time doing so would be more of a curiosity than useful
850 [for example this file isn't _that_ big], but keeping the possibility in
851 mind helps keep the design clean. */
852
853const CGEN_INSN *
854ms1_cgen_assemble_insn (CGEN_CPU_DESC cd,
855 const char *str,
856 CGEN_FIELDS *fields,
857 CGEN_INSN_BYTES_PTR buf,
858 char **errmsg)
859{
860 const char *start;
861 CGEN_INSN_LIST *ilist;
862 const char *parse_errmsg = NULL;
863 const char *insert_errmsg = NULL;
864 int recognized_mnemonic = 0;
865
866 /* Skip leading white space. */
867 while (ISSPACE (* str))
868 ++ str;
869
870 /* The instructions are stored in hashed lists.
871 Get the first in the list. */
872 ilist = CGEN_ASM_LOOKUP_INSN (cd, str);
873
874 /* Keep looking until we find a match. */
875 start = str;
876 for ( ; ilist != NULL ; ilist = CGEN_ASM_NEXT_INSN (ilist))
877 {
878 const CGEN_INSN *insn = ilist->insn;
879 recognized_mnemonic = 1;
880
881#ifdef CGEN_VALIDATE_INSN_SUPPORTED
882 /* Not usually needed as unsupported opcodes
883 shouldn't be in the hash lists. */
884 /* Is this insn supported by the selected cpu? */
885 if (! ms1_cgen_insn_supported (cd, insn))
886 continue;
887#endif
888 /* If the RELAXED attribute is set, this is an insn that shouldn't be
889 chosen immediately. Instead, it is used during assembler/linker
890 relaxation if possible. */
891 if (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_RELAXED) != 0)
892 continue;
893
894 str = start;
895
896 /* Skip this insn if str doesn't look right lexically. */
897 if (CGEN_INSN_RX (insn) != NULL &&
898 regexec ((regex_t *) CGEN_INSN_RX (insn), str, 0, NULL, 0) == REG_NOMATCH)
899 continue;
900
901 /* Allow parse/insert handlers to obtain length of insn. */
902 CGEN_FIELDS_BITSIZE (fields) = CGEN_INSN_BITSIZE (insn);
903
904 parse_errmsg = CGEN_PARSE_FN (cd, insn) (cd, insn, & str, fields);
905 if (parse_errmsg != NULL)
906 continue;
907
908 /* ??? 0 is passed for `pc'. */
909 insert_errmsg = CGEN_INSERT_FN (cd, insn) (cd, insn, fields, buf,
910 (bfd_vma) 0);
911 if (insert_errmsg != NULL)
912 continue;
913
914 /* It is up to the caller to actually output the insn and any
915 queued relocs. */
916 return insn;
917 }
918
919 {
920 static char errbuf[150];
921#ifdef CGEN_VERBOSE_ASSEMBLER_ERRORS
922 const char *tmp_errmsg;
923
924 /* If requesting verbose error messages, use insert_errmsg.
925 Failing that, use parse_errmsg. */
926 tmp_errmsg = (insert_errmsg ? insert_errmsg :
927 parse_errmsg ? parse_errmsg :
928 recognized_mnemonic ?
929 _("unrecognized form of instruction") :
930 _("unrecognized instruction"));
931
932 if (strlen (start) > 50)
933 /* xgettext:c-format */
934 sprintf (errbuf, "%s `%.50s...'", tmp_errmsg, start);
935 else
936 /* xgettext:c-format */
937 sprintf (errbuf, "%s `%.50s'", tmp_errmsg, start);
938#else
939 if (strlen (start) > 50)
940 /* xgettext:c-format */
941 sprintf (errbuf, _("bad instruction `%.50s...'"), start);
942 else
943 /* xgettext:c-format */
944 sprintf (errbuf, _("bad instruction `%.50s'"), start);
945#endif
946
947 *errmsg = errbuf;
948 return NULL;
949 }
950}