]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - opcodes/cgen-asm.in
* config/sh/tm-sh.h (BELIEVE_PCC_PROMOTION): Define, so that
[thirdparty/binutils-gdb.git] / opcodes / cgen-asm.in
CommitLineData
bfc10abe
DE
1/* Assembler interface for targets using CGEN. -*- C -*-
2 CGEN: Cpu tools GENerator
3
fbc8134d 4THIS FILE IS USED TO GENERATE @prefix@-asm.c.
bfc10abe 5
833d2990 6Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc.
bfc10abe
DE
7
8This file is part of the GNU Binutils and GDB, the GNU debugger.
9
10This program is free software; you can redistribute it and/or modify
11it under the terms of the GNU General Public License as published by
12the Free Software Foundation; either version 2, or (at your option)
13any later version.
14
15This program is distributed in the hope that it will be useful,
16but WITHOUT ANY WARRANTY; without even the implied warranty of
17MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18GNU General Public License for more details.
19
20You should have received a copy of the GNU General Public License
fbc8134d
DE
21along with this program; if not, write to the Free Software Foundation, Inc.,
2259 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
bfc10abe
DE
23
24#include "sysdep.h"
25#include <ctype.h>
26#include <stdio.h>
27#include "ansidecl.h"
28#include "bfd.h"
833d2990 29#include "symcat.h"
fbc8134d 30#include "@prefix@-opc.h"
240f5c9f 31#include "opintl.h"
bfc10abe 32
5730d39d
DE
33#undef min
34#define min(a,b) ((a) < (b) ? (a) : (b))
35#undef max
36#define max(a,b) ((a) > (b) ? (a) : (b))
37
38#undef INLINE
39#ifdef __GNUC__
40#define INLINE __inline__
41#else
42#define INLINE
43#endif
44
45/* Used by the ifield rtx function. */
46#define FLD(f) (fields->f)
bfc10abe 47
041d7e18 48static const char * insert_normal
5730d39d
DE
49 PARAMS ((CGEN_OPCODE_DESC, long, unsigned int, unsigned int, unsigned int,
50 unsigned int, unsigned int, unsigned int, CGEN_INSN_BYTES_PTR));
833d2990 51static const char * parse_insn_normal
5730d39d
DE
52 PARAMS ((CGEN_OPCODE_DESC, const CGEN_INSN *,
53 const char **, CGEN_FIELDS *));
833d2990 54static const char * insert_insn_normal
5730d39d
DE
55 PARAMS ((CGEN_OPCODE_DESC, const CGEN_INSN *,
56 CGEN_FIELDS *, CGEN_INSN_BYTES_PTR, bfd_vma));
bfc10abe 57\f
041d7e18
DE
58/* -- assembler routines inserted here */
59\f
5730d39d
DE
60#if ! CGEN_INT_INSN_P
61
62/* Subroutine of insert_normal. */
63
64static INLINE void
65insert_1 (od, value, start, length, word_length, bufp)
66 CGEN_OPCODE_DESC od;
67 unsigned long value;
68 int start,length,word_length;
69 unsigned char *bufp;
70{
71 unsigned long x,mask;
72 int shift;
73 int big_p = CGEN_OPCODE_INSN_ENDIAN (od) == CGEN_ENDIAN_BIG;
74
75 switch (word_length)
76 {
77 case 8:
78 x = *bufp;
79 break;
80 case 16:
81 if (big_p)
82 x = bfd_getb16 (bufp);
83 else
84 x = bfd_getl16 (bufp);
85 break;
86 case 24:
87 /* ??? This may need reworking as these cases don't necessarily
88 want the first byte and the last two bytes handled like this. */
89 if (big_p)
90 x = (bufp[0] << 16) | bfd_getb16 (bufp + 1);
91 else
92 x = bfd_getl16 (bufp) | (bufp[2] << 16);
93 break;
94 case 32:
95 if (big_p)
96 x = bfd_getb32 (bufp);
97 else
98 x = bfd_getl32 (bufp);
99 break;
100 default :
101 abort ();
102 }
103
104 /* Written this way to avoid undefined behaviour. */
105 mask = (((1L << (length - 1)) - 1) << 1) | 1;
106 if (CGEN_INSN_LSB0_P)
107 shift = (start + 1) - length;
108 else
109 shift = (word_length - (start + length));
110 x = (x & ~(mask << shift)) | ((value & mask) << shift);
111
112 switch (word_length)
113 {
114 case 8:
115 *bufp = x;
116 break;
117 case 16:
118 if (big_p)
119 bfd_putb16 (x, bufp);
120 else
121 bfd_putl16 (x, bufp);
122 break;
123 case 24:
124 /* ??? This may need reworking as these cases don't necessarily
125 want the first byte and the last two bytes handled like this. */
126 if (big_p)
127 {
128 bufp[0] = x >> 16;
129 bfd_putb16 (x, bufp + 1);
130 }
131 else
132 {
133 bfd_putl16 (x, bufp);
134 bufp[2] = x >> 16;
135 }
136 break;
137 case 32:
138 if (big_p)
139 bfd_putb32 (x, bufp);
140 else
141 bfd_putl32 (x, bufp);
142 break;
143 default :
144 abort ();
145 }
146}
147
148#endif /* ! CGEN_INT_INSN_P */
149
bfc10abe
DE
150/* Default insertion routine.
151
833d2990 152 ATTRS is a mask of the boolean attributes.
5730d39d
DE
153 WORD_OFFSET is the offset in bits from the start of the insn of the value.
154 WORD_LENGTH is the length of the word in bits in which the value resides.
155 START is the starting bit number in the word, architecture origin.
833d2990 156 LENGTH is the length of VALUE in bits.
5730d39d 157 TOTAL_LENGTH is the total length of the insn in bits.
bfc10abe 158
833d2990 159 The result is an error message or NULL if success. */
bfc10abe 160
833d2990 161/* ??? This duplicates functionality with bfd's howto table and
bfc10abe 162 bfd_install_relocation. */
5730d39d
DE
163/* ??? This doesn't handle bfd_vma's. Create another function when
164 necessary. */
bfc10abe 165
833d2990 166static const char *
5730d39d
DE
167insert_normal (od, value, attrs, word_offset, start, length, word_length,
168 total_length, buffer)
169 CGEN_OPCODE_DESC od;
bfc10abe
DE
170 long value;
171 unsigned int attrs;
5730d39d
DE
172 unsigned int word_offset, start, length, word_length, total_length;
173 CGEN_INSN_BYTES_PTR buffer;
bfc10abe 174{
5730d39d
DE
175 static char errbuf[100];
176 /* Written this way to avoid undefined behaviour. */
177 unsigned long mask = (((1L << (length - 1)) - 1) << 1) | 1;
fbc8134d
DE
178
179 /* If LENGTH is zero, this operand doesn't contribute to the value. */
180 if (length == 0)
181 return NULL;
833d2990 182
5730d39d
DE
183 if (CGEN_INT_INSN_P
184 && word_offset != 0)
185 abort ();
186
187 if (word_length > 32)
188 abort ();
189
190 /* For architectures with insns smaller than the insn-base-bitsize,
191 word_length may be too big. */
192#if CGEN_MIN_INSN_BITSIZE < CGEN_BASE_INSN_BITSIZE
193 if (word_offset == 0
194 && word_length > total_length)
195 word_length = total_length;
196#endif
197
833d2990 198 /* Ensure VALUE will fit. */
5730d39d 199 if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_UNSIGNED))
833d2990 200 {
5730d39d
DE
201 unsigned long maxval = mask;
202 if ((unsigned long) value > maxval)
833d2990 203 {
fbc8134d 204 /* xgettext:c-format */
5730d39d
DE
205 sprintf (errbuf,
206 _("operand out of range (%lu not between 0 and %lu)"),
207 value, maxval);
208 return errbuf;
833d2990
DE
209 }
210 }
211 else
212 {
5730d39d
DE
213 long minval = - (1L << (length - 1));
214 long maxval = (1L << (length - 1)) - 1;
215 if (value < minval || value > maxval)
fbc8134d
DE
216 {
217 sprintf
218 /* xgettext:c-format */
5730d39d
DE
219 (errbuf, _("operand out of range (%ld not between %ld and %ld)"),
220 value, minval, maxval);
221 return errbuf;
fbc8134d 222 }
833d2990 223 }
bfc10abe 224
5730d39d 225#if CGEN_INT_INSN_P
bfc10abe 226
5730d39d
DE
227 {
228 int shift;
bfc10abe 229
5730d39d
DE
230 if (CGEN_INSN_LSB0_P)
231 shift = (start + 1) - length;
232 else
233 shift = word_length - (start + length);
234 *buffer = (*buffer & ~(mask << shift)) | ((value & mask) << shift);
235 }
236
237#else /* ! CGEN_INT_INSN_P */
238
239 {
240 unsigned char *bufp = (unsigned char *) buffer + word_offset / 8;
241
242 insert_1 (od, value, start, length, word_length, bufp);
243 }
244
245#endif /* ! CGEN_INT_INSN_P */
833d2990
DE
246
247 return NULL;
bfc10abe
DE
248}
249\f
bfc10abe
DE
250/* Default insn parser.
251
252 The syntax string is scanned and operands are parsed and stored in FIELDS.
253 Relocs are queued as we go via other callbacks.
254
255 ??? Note that this is currently an all-or-nothing parser. If we fail to
256 parse the instruction, we return 0 and the caller will start over from
257 the beginning. Backtracking will be necessary in parsing subexpressions,
258 but that can be handled there. Not handling backtracking here may get
259 expensive in the case of the m68k. Deal with later.
260
261 Returns NULL for success, an error message for failure.
262*/
263
264static const char *
5730d39d
DE
265parse_insn_normal (od, insn, strp, fields)
266 CGEN_OPCODE_DESC od;
833d2990
DE
267 const CGEN_INSN * insn;
268 const char ** strp;
269 CGEN_FIELDS * fields;
bfc10abe 270{
833d2990
DE
271 const CGEN_SYNTAX * syntax = CGEN_INSN_SYNTAX (insn);
272 const char * str = *strp;
273 const char * errmsg;
274 const char * p;
275 const unsigned char * syn;
bfc10abe 276#ifdef CGEN_MNEMONIC_OPERANDS
fbc8134d 277 /* FIXME: wip */
bfc10abe
DE
278 int past_opcode_p;
279#endif
280
281 /* For now we assume the mnemonic is first (there are no leading operands).
5730d39d
DE
282 We can parse it without needing to set up operand parsing.
283 GAS's input scrubber will ensure mnemonics are lowercase, but we may
284 not be called from GAS. */
bfc10abe 285 p = CGEN_INSN_MNEMONIC (insn);
5730d39d
DE
286 while (*p && tolower (*p) == tolower (*str))
287 ++p, ++str;
240f5c9f 288
833d2990 289 if (* p || (* str && !isspace (* str)))
240f5c9f 290 return _("unrecognized instruction");
bfc10abe 291
5730d39d
DE
292 CGEN_INIT_PARSE (od);
293 cgen_init_parse_operand (od);
bfc10abe
DE
294#ifdef CGEN_MNEMONIC_OPERANDS
295 past_opcode_p = 0;
296#endif
297
298 /* We don't check for (*str != '\0') here because we want to parse
299 any trailing fake arguments in the syntax string. */
5730d39d 300 syn = CGEN_SYNTAX_STRING (syntax);
833d2990 301
bfc10abe 302 /* Mnemonics come first for now, ensure valid string. */
833d2990 303 if (! CGEN_SYNTAX_MNEMONIC_P (* syn))
bfc10abe 304 abort ();
833d2990 305
bfc10abe 306 ++syn;
833d2990
DE
307
308 while (* syn != 0)
bfc10abe
DE
309 {
310 /* Non operand chars must match exactly. */
833d2990 311 if (CGEN_SYNTAX_CHAR_P (* syn))
bfc10abe 312 {
833d2990 313 if (*str == CGEN_SYNTAX_CHAR (* syn))
bfc10abe
DE
314 {
315#ifdef CGEN_MNEMONIC_OPERANDS
833d2990 316 if (* syn == ' ')
bfc10abe
DE
317 past_opcode_p = 1;
318#endif
833d2990
DE
319 ++ syn;
320 ++ str;
bfc10abe
DE
321 }
322 else
323 {
324 /* Syntax char didn't match. Can't be this insn. */
833d2990
DE
325 /* FIXME: would like to return something like
326 "expected char `c'" */
240f5c9f 327 return _("syntax error");
bfc10abe
DE
328 }
329 continue;
330 }
331
332 /* We have an operand of some sort. */
5730d39d
DE
333 errmsg = @arch@_cgen_parse_operand (od, CGEN_SYNTAX_FIELD (*syn),
334 &str, fields);
bfc10abe
DE
335 if (errmsg)
336 return errmsg;
337
338 /* Done with this operand, continue with next one. */
833d2990 339 ++ syn;
bfc10abe
DE
340 }
341
342 /* If we're at the end of the syntax string, we're done. */
833d2990 343 if (* syn == '\0')
bfc10abe
DE
344 {
345 /* FIXME: For the moment we assume a valid `str' can only contain
346 blanks now. IE: We needn't try again with a longer version of
347 the insn and it is assumed that longer versions of insns appear
348 before shorter ones (eg: lsr r2,r3,1 vs lsr r2,r3). */
833d2990
DE
349 while (isspace (* str))
350 ++ str;
bfc10abe 351
833d2990 352 if (* str != '\0')
240f5c9f 353 return _("junk at end of line"); /* FIXME: would like to include `str' */
bfc10abe
DE
354
355 return NULL;
356 }
357
358 /* We couldn't parse it. */
5730d39d 359 return _("unrecognized instruction");
bfc10abe
DE
360}
361
362/* Default insn builder (insert handler).
5730d39d
DE
363 The instruction is recorded in CGEN_INT_INSN_P byte order
364 (meaning that if CGEN_INT_INSN_P BUFFER is an int * and thus the value is
365 recorded in host byte order, otherwise BUFFER is an array of bytes and the
366 value is recorded in target byte order).
833d2990 367 The result is an error message or NULL if success. */
bfc10abe 368
833d2990 369static const char *
5730d39d
DE
370insert_insn_normal (od, insn, fields, buffer, pc)
371 CGEN_OPCODE_DESC od;
833d2990
DE
372 const CGEN_INSN * insn;
373 CGEN_FIELDS * fields;
5730d39d 374 CGEN_INSN_BYTES_PTR buffer;
fbc8134d 375 bfd_vma pc;
bfc10abe 376{
833d2990 377 const CGEN_SYNTAX * syntax = CGEN_INSN_SYNTAX (insn);
5730d39d 378 unsigned long value;
833d2990 379 const unsigned char * syn;
bfc10abe 380
5730d39d
DE
381 CGEN_INIT_INSERT (od);
382 value = CGEN_INSN_BASE_VALUE (insn);
bfc10abe
DE
383
384 /* If we're recording insns as numbers (rather than a string of bytes),
385 target byte order handling is deferred until later. */
5730d39d
DE
386
387#if CGEN_INT_INSN_P
388
bfc10abe 389 *buffer = value;
5730d39d 390
bfc10abe 391#else
bfc10abe 392
5730d39d
DE
393 cgen_put_insn_value (od, buffer, min (CGEN_BASE_INSN_BITSIZE,
394 CGEN_FIELDS_BITSIZE (fields)),
395 value);
396
397#endif /* ! CGEN_INT_INSN_P */
398
399 /* ??? It would be better to scan the format's fields.
400 Still need to be able to insert a value based on the operand though;
401 e.g. storing a branch displacement that got resolved later.
402 Needs more thought first. */
bfc10abe 403
833d2990 404 for (syn = CGEN_SYNTAX_STRING (syntax); * syn != '\0'; ++ syn)
bfc10abe 405 {
833d2990
DE
406 const char *errmsg;
407
408 if (CGEN_SYNTAX_CHAR_P (* syn))
bfc10abe
DE
409 continue;
410
5730d39d
DE
411 errmsg = @arch@_cgen_insert_operand (od, CGEN_SYNTAX_FIELD (*syn),
412 fields, buffer, pc);
833d2990
DE
413 if (errmsg)
414 return errmsg;
bfc10abe 415 }
833d2990
DE
416
417 return NULL;
bfc10abe
DE
418}
419\f
420/* Main entry point.
421 This routine is called for each instruction to be assembled.
422 STR points to the insn to be assembled.
423 We assume all necessary tables have been initialized.
5730d39d
DE
424 The assembled instruction, less any fixups, is stored in BUF.
425 Remember that if CGEN_INT_INSN_P then BUF is an int and thus the value
426 still needs to be converted to target byte order, otherwise BUF is an array
427 of bytes in target byte order.
bfc10abe
DE
428 The result is a pointer to the insn's entry in the opcode table,
429 or NULL if an error occured (an error message will have already been
041d7e18
DE
430 printed).
431
432 Note that when processing (non-alias) macro-insns,
433 this function recurses. */
bfc10abe
DE
434
435const CGEN_INSN *
5730d39d
DE
436@arch@_cgen_assemble_insn (od, str, fields, buf, errmsg)
437 CGEN_OPCODE_DESC od;
833d2990
DE
438 const char * str;
439 CGEN_FIELDS * fields;
5730d39d 440 CGEN_INSN_BYTES_PTR buf;
833d2990 441 char ** errmsg;
bfc10abe 442{
833d2990
DE
443 const char * start;
444 CGEN_INSN_LIST * ilist;
bfc10abe
DE
445
446 /* Skip leading white space. */
833d2990
DE
447 while (isspace (* str))
448 ++ str;
bfc10abe
DE
449
450 /* The instructions are stored in hashed lists.
451 Get the first in the list. */
5730d39d 452 ilist = CGEN_ASM_LOOKUP_INSN (od, str);
bfc10abe
DE
453
454 /* Keep looking until we find a match. */
455
456 start = str;
457 for ( ; ilist != NULL ; ilist = CGEN_ASM_NEXT_INSN (ilist))
458 {
459 const CGEN_INSN *insn = ilist->insn;
460
461#if 0 /* not needed as unsupported opcodes shouldn't be in the hash lists */
462 /* Is this insn supported by the selected cpu? */
5730d39d 463 if (! @arch@_cgen_insn_supported (od, insn))
bfc10abe
DE
464 continue;
465#endif
466
bfc10abe
DE
467 /* If the RELAX attribute is set, this is an insn that shouldn't be
468 chosen immediately. Instead, it is used during assembler/linker
469 relaxation if possible. */
470 if (CGEN_INSN_ATTR (insn, CGEN_INSN_RELAX) != 0)
471 continue;
bfc10abe
DE
472
473 str = start;
474
5730d39d 475 /* Allow parse/insert handlers to obtain length of insn. */
bfc10abe
DE
476 CGEN_FIELDS_BITSIZE (fields) = CGEN_INSN_BITSIZE (insn);
477
5730d39d 478 if (! CGEN_PARSE_FN (insn) (od, insn, & str, fields))
bfc10abe 479 {
fbc8134d 480 /* ??? 0 is passed for `pc' */
5730d39d 481 if (CGEN_INSERT_FN (insn) (od, insn, fields, buf, (bfd_vma) 0) != NULL)
833d2990 482 continue;
bfc10abe
DE
483 /* It is up to the caller to actually output the insn and any
484 queued relocs. */
485 return insn;
486 }
487
488 /* Try the next entry. */
489 }
490
491 /* FIXME: We can return a better error message than this.
492 Need to track why it failed and pick the right one. */
493 {
494 static char errbuf[100];
240f5c9f 495 if (strlen (start) > 50)
fbc8134d 496 /* xgettext:c-format */
240f5c9f 497 sprintf (errbuf, _("bad instruction `%.50s...'"), start);
fbc8134d
DE
498 else
499 /* xgettext:c-format */
240f5c9f
NC
500 sprintf (errbuf, _("bad instruction `%.50s'"), start);
501
bfc10abe
DE
502 *errmsg = errbuf;
503 return NULL;
504 }
505}
506\f
507#if 0 /* This calls back to GAS which we can't do without care. */
508
509/* Record each member of OPVALS in the assembler's symbol table.
510 This lets GAS parse registers for us.
511 ??? Interesting idea but not currently used. */
512
513/* Record each member of OPVALS in the assembler's symbol table.
514 FIXME: Not currently used. */
515
516void
5730d39d
DE
517@arch@_cgen_asm_hash_keywords (od, opvals)
518 CGEN_OPCODE_DESC od;
833d2990 519 CGEN_KEYWORD * opvals;
bfc10abe
DE
520{
521 CGEN_KEYWORD_SEARCH search = cgen_keyword_search_init (opvals, NULL);
833d2990 522 const CGEN_KEYWORD_ENTRY * ke;
bfc10abe 523
833d2990 524 while ((ke = cgen_keyword_search_next (& search)) != NULL)
bfc10abe
DE
525 {
526#if 0 /* Unnecessary, should be done in the search routine. */
527 if (! @arch@_cgen_opval_supported (ke))
528 continue;
529#endif
5730d39d 530 cgen_asm_record_register (od, ke->name, ke->value);
bfc10abe
DE
531 }
532}
533
534#endif /* 0 */