* cgen-asm.in (insert_normal): Use CGEN_BOOL_ATTR.
[platform/upstream/binutils.git] / opcodes / cgen-asm.in
1 /* Assembler interface for targets using CGEN. -*- C -*-
2    CGEN: Cpu tools GENerator
3
4 THIS FILE IS USED TO GENERATE @prefix@-asm.c.
5
6 Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc.
7
8 This file is part of the GNU Binutils and GDB, the GNU debugger.
9
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)
13 any later version.
14
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.
19
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.  */
23
24 #include "sysdep.h"
25 #include <ctype.h>
26 #include <stdio.h>
27 #include "ansidecl.h"
28 #include "bfd.h"
29 #include "symcat.h"
30 #include "@prefix@-opc.h"
31 #include "opintl.h"
32
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)
47
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));
57 \f
58 /* -- assembler routines inserted here */
59 \f
60 #if ! CGEN_INT_INSN_P
61
62 /* Subroutine of insert_normal.  */
63
64 static INLINE void
65 insert_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
150 /* Default insertion routine.
151
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.
158
159    The result is an error message or NULL if success.  */
160
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
164    necessary.  */
165
166 static const char *
167 insert_normal (od, value, attrs, word_offset, start, length, word_length,
168                total_length, buffer)
169      CGEN_OPCODE_DESC od;
170      long value;
171      unsigned int attrs;
172      unsigned int word_offset, start, length, word_length, total_length;
173      CGEN_INSN_BYTES_PTR buffer;
174 {
175   static char errbuf[100];
176   /* Written this way to avoid undefined behaviour.  */
177   unsigned long mask = (((1L << (length - 1)) - 1) << 1) | 1;
178
179   /* If LENGTH is zero, this operand doesn't contribute to the value.  */
180   if (length == 0)
181     return NULL;
182
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
198   /* Ensure VALUE will fit.  */
199   if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_UNSIGNED))
200     {
201       unsigned long maxval = mask;
202       if ((unsigned long) value > maxval)
203         {
204           /* xgettext:c-format */
205           sprintf (errbuf,
206                    _("operand out of range (%lu not between 0 and %lu)"),
207                    value, maxval);
208           return errbuf;
209         }
210     }
211   else
212     {
213       long minval = - (1L << (length - 1));
214       long maxval = (1L << (length - 1)) - 1;
215       if (value < minval || value > maxval)
216         {
217           sprintf
218             /* xgettext:c-format */
219             (errbuf, _("operand out of range (%ld not between %ld and %ld)"),
220              value, minval, maxval);
221           return errbuf;
222         }
223     }
224
225 #if CGEN_INT_INSN_P
226
227   {
228     int shift;
229
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 */
246
247   return NULL;
248 }
249 \f
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
264 static const char *
265 parse_insn_normal (od, insn, strp, fields)
266      CGEN_OPCODE_DESC od;
267      const CGEN_INSN * insn;
268      const char ** strp;
269      CGEN_FIELDS * fields;
270 {
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;
276 #ifdef CGEN_MNEMONIC_OPERANDS
277   /* FIXME: wip */
278   int past_opcode_p;
279 #endif
280
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))
287     ++p, ++str;
288   
289   if (* p || (* str && !isspace (* str)))
290     return _("unrecognized instruction");
291
292   CGEN_INIT_PARSE (od);
293   cgen_init_parse_operand (od);
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.  */
300   syn = CGEN_SYNTAX_STRING (syntax);
301
302   /* Mnemonics come first for now, ensure valid string.  */
303   if (! CGEN_SYNTAX_MNEMONIC_P (* syn))
304     abort ();
305
306   ++syn;
307
308   while (* syn != 0)
309     {
310       /* Non operand chars must match exactly.  */
311       if (CGEN_SYNTAX_CHAR_P (* syn))
312         {
313           if (*str == CGEN_SYNTAX_CHAR (* syn))
314             {
315 #ifdef CGEN_MNEMONIC_OPERANDS
316               if (* syn == ' ')
317                 past_opcode_p = 1;
318 #endif
319               ++ syn;
320               ++ str;
321             }
322           else
323             {
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");
328             }
329           continue;
330         }
331
332       /* We have an operand of some sort.  */
333       errmsg = @arch@_cgen_parse_operand (od, CGEN_SYNTAX_FIELD (*syn),
334                                           &str, fields);
335       if (errmsg)
336         return errmsg;
337
338       /* Done with this operand, continue with next one.  */
339       ++ syn;
340     }
341
342   /* If we're at the end of the syntax string, we're done.  */
343   if (* syn == '\0')
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).  */
349       while (isspace (* str))
350         ++ str;
351
352       if (* str != '\0')
353         return _("junk at end of line"); /* FIXME: would like to include `str' */
354
355       return NULL;
356     }
357
358   /* We couldn't parse it.  */
359   return _("unrecognized instruction");
360 }
361
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.  */
368
369 static const char *
370 insert_insn_normal (od, insn, fields, buffer, pc)
371      CGEN_OPCODE_DESC od;
372      const CGEN_INSN * insn;
373      CGEN_FIELDS * fields;
374      CGEN_INSN_BYTES_PTR buffer;
375      bfd_vma pc;
376 {
377   const CGEN_SYNTAX * syntax = CGEN_INSN_SYNTAX (insn);
378   unsigned long value;
379   const unsigned char * syn;
380
381   CGEN_INIT_INSERT (od);
382   value = CGEN_INSN_BASE_VALUE (insn);
383
384   /* If we're recording insns as numbers (rather than a string of bytes),
385      target byte order handling is deferred until later.  */
386
387 #if CGEN_INT_INSN_P
388
389   *buffer = value;
390
391 #else
392
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.  */
403
404   for (syn = CGEN_SYNTAX_STRING (syntax); * syn != '\0'; ++ syn)
405     {
406       const char *errmsg;
407
408       if (CGEN_SYNTAX_CHAR_P (* syn))
409         continue;
410
411       errmsg = @arch@_cgen_insert_operand (od, CGEN_SYNTAX_FIELD (*syn),
412                                            fields, buffer, pc);
413       if (errmsg)
414         return errmsg;
415     }
416
417   return NULL;
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.
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
430    printed).
431
432    Note that when processing (non-alias) macro-insns,
433    this function recurses.  */
434
435 const CGEN_INSN *
436 @arch@_cgen_assemble_insn (od, str, fields, buf, errmsg)
437      CGEN_OPCODE_DESC od;
438      const char * str;
439      CGEN_FIELDS * fields;
440      CGEN_INSN_BYTES_PTR buf;
441      char ** errmsg;
442 {
443   const char * start;
444   CGEN_INSN_LIST * ilist;
445
446   /* Skip leading white space.  */
447   while (isspace (* str))
448     ++ str;
449
450   /* The instructions are stored in hashed lists.
451      Get the first in the list.  */
452   ilist = CGEN_ASM_LOOKUP_INSN (od, str);
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?  */
463       if (! @arch@_cgen_insn_supported (od, insn))
464         continue;
465 #endif
466
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;
472
473       str = start;
474
475       /* Allow parse/insert handlers to obtain length of insn.  */
476       CGEN_FIELDS_BITSIZE (fields) = CGEN_INSN_BITSIZE (insn);
477
478       if (! CGEN_PARSE_FN (insn) (od, insn, & str, fields))
479         {
480           /* ??? 0 is passed for `pc' */
481           if (CGEN_INSERT_FN (insn) (od, insn, fields, buf, (bfd_vma) 0) != NULL)
482             continue;
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];
495     if (strlen (start) > 50)
496       /* xgettext:c-format */
497       sprintf (errbuf, _("bad instruction `%.50s...'"), start);
498     else 
499       /* xgettext:c-format */
500       sprintf (errbuf, _("bad instruction `%.50s'"), start);
501       
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
516 void
517 @arch@_cgen_asm_hash_keywords (od, opvals)
518      CGEN_OPCODE_DESC od;
519      CGEN_KEYWORD * opvals;
520 {
521   CGEN_KEYWORD_SEARCH search = cgen_keyword_search_init (opvals, NULL);
522   const CGEN_KEYWORD_ENTRY * ke;
523
524   while ((ke = cgen_keyword_search_next (& search)) != NULL)
525     {
526 #if 0 /* Unnecessary, should be done in the search routine.  */
527       if (! @arch@_cgen_opval_supported (ke))
528         continue;
529 #endif
530       cgen_asm_record_register (od, ke->name, ke->value);
531     }
532 }
533
534 #endif /* 0 */