1 /* Assembler interface for targets using CGEN. -*- C -*-
2 CGEN: Cpu tools GENerator
6 Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc.
8 This file is part of the GNU Binutils and GDB, the GNU debugger.
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 2, or (at your option)
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software Foundation, Inc.,
22 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
34 #define min(a,b) ((a) < (b) ? (a) : (b))
36 #define max(a,b) ((a) > (b) ? (a) : (b))
40 #define INLINE __inline__
45 /* Used by the ifield rtx function. */
46 #define FLD(f) (fields->f)
48 static const char * insert_normal
49 PARAMS ((CGEN_OPCODE_DESC, long, unsigned int, unsigned int, unsigned int,
50 unsigned int, unsigned int, unsigned int, CGEN_INSN_BYTES_PTR));
51 static const char * parse_insn_normal
52 PARAMS ((CGEN_OPCODE_DESC, const CGEN_INSN *,
53 const char **, CGEN_FIELDS *));
54 static const char * insert_insn_normal
55 PARAMS ((CGEN_OPCODE_DESC, const CGEN_INSN *,
56 CGEN_FIELDS *, CGEN_INSN_BYTES_PTR, bfd_vma));
58 /* -- assembler routines inserted here */
62 /* Subroutine of insert_normal. */
65 insert_1 (od, value, start, length, word_length, bufp)
68 int start,length,word_length;
73 int big_p = CGEN_OPCODE_INSN_ENDIAN (od) == CGEN_ENDIAN_BIG;
82 x = bfd_getb16 (bufp);
84 x = bfd_getl16 (bufp);
87 /* ??? This may need reworking as these cases don't necessarily
88 want the first byte and the last two bytes handled like this. */
90 x = (bufp[0] << 16) | bfd_getb16 (bufp + 1);
92 x = bfd_getl16 (bufp) | (bufp[2] << 16);
96 x = bfd_getb32 (bufp);
98 x = bfd_getl32 (bufp);
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;
109 shift = (word_length - (start + length));
110 x = (x & ~(mask << shift)) | ((value & mask) << shift);
119 bfd_putb16 (x, bufp);
121 bfd_putl16 (x, bufp);
124 /* ??? This may need reworking as these cases don't necessarily
125 want the first byte and the last two bytes handled like this. */
129 bfd_putb16 (x, bufp + 1);
133 bfd_putl16 (x, bufp);
139 bfd_putb32 (x, bufp);
141 bfd_putl32 (x, bufp);
148 #endif /* ! CGEN_INT_INSN_P */
150 /* Default insertion routine.
152 ATTRS is a mask of the boolean attributes.
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.
156 LENGTH is the length of VALUE in bits.
157 TOTAL_LENGTH is the total length of the insn in bits.
159 The result is an error message or NULL if success. */
161 /* ??? This duplicates functionality with bfd's howto table and
162 bfd_install_relocation. */
163 /* ??? This doesn't handle bfd_vma's. Create another function when
167 insert_normal (od, value, attrs, word_offset, start, length, word_length,
168 total_length, buffer)
172 unsigned int word_offset, start, length, word_length, total_length;
173 CGEN_INSN_BYTES_PTR buffer;
175 static char errbuf[100];
176 /* Written this way to avoid undefined behaviour. */
177 unsigned long mask = (((1L << (length - 1)) - 1) << 1) | 1;
179 /* If LENGTH is zero, this operand doesn't contribute to the value. */
187 if (word_length > 32)
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
194 && word_length > total_length)
195 word_length = total_length;
198 /* Ensure VALUE will fit. */
199 if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_UNSIGNED))
201 unsigned long maxval = mask;
202 if ((unsigned long) value > maxval)
204 /* xgettext:c-format */
206 _("operand out of range (%lu not between 0 and %lu)"),
213 long minval = - (1L << (length - 1));
214 long maxval = (1L << (length - 1)) - 1;
215 if (value < minval || value > maxval)
218 /* xgettext:c-format */
219 (errbuf, _("operand out of range (%ld not between %ld and %ld)"),
220 value, minval, maxval);
230 if (CGEN_INSN_LSB0_P)
231 shift = (start + 1) - length;
233 shift = word_length - (start + length);
234 *buffer = (*buffer & ~(mask << shift)) | ((value & mask) << shift);
237 #else /* ! CGEN_INT_INSN_P */
240 unsigned char *bufp = (unsigned char *) buffer + word_offset / 8;
242 insert_1 (od, value, start, length, word_length, bufp);
245 #endif /* ! CGEN_INT_INSN_P */
250 /* Default insn parser.
252 The syntax string is scanned and operands are parsed and stored in FIELDS.
253 Relocs are queued as we go via other callbacks.
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.
261 Returns NULL for success, an error message for failure.
265 parse_insn_normal (od, insn, strp, fields)
267 const CGEN_INSN * insn;
269 CGEN_FIELDS * fields;
271 const CGEN_SYNTAX * syntax = CGEN_INSN_SYNTAX (insn);
272 const char * str = *strp;
275 const unsigned char * syn;
276 #ifdef CGEN_MNEMONIC_OPERANDS
281 /* For now we assume the mnemonic is first (there are no leading operands).
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. */
285 p = CGEN_INSN_MNEMONIC (insn);
286 while (*p && tolower (*p) == tolower (*str))
289 if (* p || (* str && !isspace (* str)))
290 return _("unrecognized instruction");
292 CGEN_INIT_PARSE (od);
293 cgen_init_parse_operand (od);
294 #ifdef CGEN_MNEMONIC_OPERANDS
298 /* We don't check for (*str != '\0') here because we want to parse
299 any trailing fake arguments in the syntax string. */
300 syn = CGEN_SYNTAX_STRING (syntax);
302 /* Mnemonics come first for now, ensure valid string. */
303 if (! CGEN_SYNTAX_MNEMONIC_P (* syn))
310 /* Non operand chars must match exactly. */
311 if (CGEN_SYNTAX_CHAR_P (* syn))
313 if (*str == CGEN_SYNTAX_CHAR (* syn))
315 #ifdef CGEN_MNEMONIC_OPERANDS
324 /* Syntax char didn't match. Can't be this insn. */
325 /* FIXME: would like to return something like
326 "expected char `c'" */
327 return _("syntax error");
332 /* We have an operand of some sort. */
333 errmsg = @arch@_cgen_parse_operand (od, CGEN_SYNTAX_FIELD (*syn),
338 /* Done with this operand, continue with next one. */
342 /* If we're at the end of the syntax string, we're done. */
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). */
349 while (isspace (* str))
353 return _("junk at end of line"); /* FIXME: would like to include `str' */
358 /* We couldn't parse it. */
359 return _("unrecognized instruction");
362 /* Default insn builder (insert handler).
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).
367 The result is an error message or NULL if success. */
370 insert_insn_normal (od, insn, fields, buffer, pc)
372 const CGEN_INSN * insn;
373 CGEN_FIELDS * fields;
374 CGEN_INSN_BYTES_PTR buffer;
377 const CGEN_SYNTAX * syntax = CGEN_INSN_SYNTAX (insn);
379 const unsigned char * syn;
381 CGEN_INIT_INSERT (od);
382 value = CGEN_INSN_BASE_VALUE (insn);
384 /* If we're recording insns as numbers (rather than a string of bytes),
385 target byte order handling is deferred until later. */
393 cgen_put_insn_value (od, buffer, min (CGEN_BASE_INSN_BITSIZE,
394 CGEN_FIELDS_BITSIZE (fields)),
397 #endif /* ! CGEN_INT_INSN_P */
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. */
404 for (syn = CGEN_SYNTAX_STRING (syntax); * syn != '\0'; ++ syn)
408 if (CGEN_SYNTAX_CHAR_P (* syn))
411 errmsg = @arch@_cgen_insert_operand (od, CGEN_SYNTAX_FIELD (*syn),
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.
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.
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
432 Note that when processing (non-alias) macro-insns,
433 this function recurses. */
436 @arch@_cgen_assemble_insn (od, str, fields, buf, errmsg)
439 CGEN_FIELDS * fields;
440 CGEN_INSN_BYTES_PTR buf;
444 CGEN_INSN_LIST * ilist;
446 /* Skip leading white space. */
447 while (isspace (* str))
450 /* The instructions are stored in hashed lists.
451 Get the first in the list. */
452 ilist = CGEN_ASM_LOOKUP_INSN (od, str);
454 /* Keep looking until we find a match. */
457 for ( ; ilist != NULL ; ilist = CGEN_ASM_NEXT_INSN (ilist))
459 const CGEN_INSN *insn = ilist->insn;
461 #if 0 /* not needed as unsupported opcodes shouldn't be in the hash lists */
462 /* Is this insn supported by the selected cpu? */
463 if (! @arch@_cgen_insn_supported (od, insn))
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)
475 /* Allow parse/insert handlers to obtain length of insn. */
476 CGEN_FIELDS_BITSIZE (fields) = CGEN_INSN_BITSIZE (insn);
478 if (! CGEN_PARSE_FN (insn) (od, insn, & str, fields))
480 /* ??? 0 is passed for `pc' */
481 if (CGEN_INSERT_FN (insn) (od, insn, fields, buf, (bfd_vma) 0) != NULL)
483 /* It is up to the caller to actually output the insn and any
488 /* Try the next entry. */
491 /* FIXME: We can return a better error message than this.
492 Need to track why it failed and pick the right one. */
494 static char errbuf[100];
495 if (strlen (start) > 50)
496 /* xgettext:c-format */
497 sprintf (errbuf, _("bad instruction `%.50s...'"), start);
499 /* xgettext:c-format */
500 sprintf (errbuf, _("bad instruction `%.50s'"), start);
507 #if 0 /* This calls back to GAS which we can't do without care. */
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. */
513 /* Record each member of OPVALS in the assembler's symbol table.
514 FIXME: Not currently used. */
517 @arch@_cgen_asm_hash_keywords (od, opvals)
519 CGEN_KEYWORD * opvals;
521 CGEN_KEYWORD_SEARCH search = cgen_keyword_search_init (opvals, NULL);
522 const CGEN_KEYWORD_ENTRY * ke;
524 while ((ke = cgen_keyword_search_next (& search)) != NULL)
526 #if 0 /* Unnecessary, should be done in the search routine. */
527 if (! @arch@_cgen_opval_supported (ke))
530 cgen_asm_record_register (od, ke->name, ke->value);