* acinclude.m4: Include libtool and gettext macros from the
[external/binutils.git] / opcodes / cgen-ibld.in
1 /* Instruction building/extraction support for @arch@. -*- C -*-
2
3 THIS FILE IS MACHINE GENERATED WITH CGEN: Cpu tools GENerator.
4 - the resultant file is machine generated, cgen-ibld.in isn't
5
6 Copyright (C) 1996, 1997, 1998, 1999, 2000 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 /* ??? Eventually more and more of this stuff can go to cpu-independent files.
25    Keep that in mind.  */
26
27 #include "sysdep.h"
28 #include <ctype.h>
29 #include <stdio.h>
30 #include "ansidecl.h"
31 #include "dis-asm.h"
32 #include "bfd.h"
33 #include "symcat.h"
34 #include "@prefix@-desc.h"
35 #include "@prefix@-opc.h"
36 #include "opintl.h"
37
38 #undef min
39 #define min(a,b) ((a) < (b) ? (a) : (b))
40 #undef max
41 #define max(a,b) ((a) > (b) ? (a) : (b))
42
43 /* Used by the ifield rtx function.  */
44 #define FLD(f) (fields->f)
45
46 static const char * insert_normal
47      PARAMS ((CGEN_CPU_DESC, long, unsigned int, unsigned int, unsigned int,
48               unsigned int, unsigned int, unsigned int, CGEN_INSN_BYTES_PTR));
49 static const char * insert_insn_normal
50      PARAMS ((CGEN_CPU_DESC, const CGEN_INSN *,
51               CGEN_FIELDS *, CGEN_INSN_BYTES_PTR, bfd_vma));
52
53 static int extract_normal
54      PARAMS ((CGEN_CPU_DESC, CGEN_EXTRACT_INFO *, CGEN_INSN_INT,
55               unsigned int, unsigned int, unsigned int, unsigned int,
56               unsigned int, unsigned int, bfd_vma, long *));
57 static int extract_insn_normal
58      PARAMS ((CGEN_CPU_DESC, const CGEN_INSN *, CGEN_EXTRACT_INFO *,
59               CGEN_INSN_INT, CGEN_FIELDS *, bfd_vma));
60 static void put_insn_int_value
61      PARAMS ((CGEN_CPU_DESC, CGEN_INSN_BYTES_PTR, int, int, CGEN_INSN_INT));
62
63 \f
64 /* Operand insertion.  */
65
66 #if ! CGEN_INT_INSN_P
67
68 /* Subroutine of insert_normal.  */
69
70 static CGEN_INLINE void
71 insert_1 (cd, value, start, length, word_length, bufp)
72      CGEN_CPU_DESC cd;
73      unsigned long value;
74      int start,length,word_length;
75      unsigned char *bufp;
76 {
77   unsigned long x,mask;
78   int shift;
79   int big_p = CGEN_CPU_INSN_ENDIAN (cd) == CGEN_ENDIAN_BIG;
80
81   switch (word_length)
82     {
83     case 8:
84       x = *bufp;
85       break;
86     case 16:
87       if (big_p)
88         x = bfd_getb16 (bufp);
89       else
90         x = bfd_getl16 (bufp);
91       break;
92     case 24:
93       /* ??? This may need reworking as these cases don't necessarily
94          want the first byte and the last two bytes handled like this.  */
95       if (big_p)
96         x = (bufp[0] << 16) | bfd_getb16 (bufp + 1);
97       else
98         x = bfd_getl16 (bufp) | (bufp[2] << 16);
99       break;
100     case 32:
101       if (big_p)
102         x = bfd_getb32 (bufp);
103       else
104         x = bfd_getl32 (bufp);
105       break;
106     default :
107       abort ();
108     }
109
110   /* Written this way to avoid undefined behaviour.  */
111   mask = (((1L << (length - 1)) - 1) << 1) | 1;
112   if (CGEN_INSN_LSB0_P)
113     shift = (start + 1) - length;
114   else
115     shift = (word_length - (start + length));
116   x = (x & ~(mask << shift)) | ((value & mask) << shift);
117
118   switch (word_length)
119     {
120     case 8:
121       *bufp = x;
122       break;
123     case 16:
124       if (big_p)
125         bfd_putb16 (x, bufp);
126       else
127         bfd_putl16 (x, bufp);
128       break;
129     case 24:
130       /* ??? This may need reworking as these cases don't necessarily
131          want the first byte and the last two bytes handled like this.  */
132       if (big_p)
133         {
134           bufp[0] = x >> 16;
135           bfd_putb16 (x, bufp + 1);
136         }
137       else
138         {
139           bfd_putl16 (x, bufp);
140           bufp[2] = x >> 16;
141         }
142       break;
143     case 32:
144       if (big_p)
145         bfd_putb32 (x, bufp);
146       else
147         bfd_putl32 (x, bufp);
148       break;
149     default :
150       abort ();
151     }
152 }
153
154 #endif /* ! CGEN_INT_INSN_P */
155
156 /* Default insertion routine.
157
158    ATTRS is a mask of the boolean attributes.
159    WORD_OFFSET is the offset in bits from the start of the insn of the value.
160    WORD_LENGTH is the length of the word in bits in which the value resides.
161    START is the starting bit number in the word, architecture origin.
162    LENGTH is the length of VALUE in bits.
163    TOTAL_LENGTH is the total length of the insn in bits.
164
165    The result is an error message or NULL if success.  */
166
167 /* ??? This duplicates functionality with bfd's howto table and
168    bfd_install_relocation.  */
169 /* ??? This doesn't handle bfd_vma's.  Create another function when
170    necessary.  */
171
172 static const char *
173 insert_normal (cd, value, attrs, word_offset, start, length, word_length,
174                total_length, buffer)
175      CGEN_CPU_DESC cd;
176      long value;
177      unsigned int attrs;
178      unsigned int word_offset, start, length, word_length, total_length;
179      CGEN_INSN_BYTES_PTR buffer;
180 {
181   static char errbuf[100];
182   /* Written this way to avoid undefined behaviour.  */
183   unsigned long mask = (((1L << (length - 1)) - 1) << 1) | 1;
184
185   /* If LENGTH is zero, this operand doesn't contribute to the value.  */
186   if (length == 0)
187     return NULL;
188
189 #if 0
190   if (CGEN_INT_INSN_P
191       && word_offset != 0)
192     abort ();
193 #endif
194
195   if (word_length > 32)
196     abort ();
197
198   /* For architectures with insns smaller than the base-insn-bitsize,
199      word_length may be too big.  */
200   if (cd->min_insn_bitsize < cd->base_insn_bitsize)
201     {
202       if (word_offset == 0
203           && word_length > total_length)
204         word_length = total_length;
205     }
206
207   /* Ensure VALUE will fit.  */
208   if (! CGEN_BOOL_ATTR (attrs, CGEN_IFLD_SIGNED))
209     {
210       unsigned long maxval = mask;
211       
212       if ((unsigned long) value > maxval)
213         {
214           /* xgettext:c-format */
215           sprintf (errbuf,
216                    _("operand out of range (%lu not between 0 and %lu)"),
217                    value, maxval);
218           return errbuf;
219         }
220     }
221   else
222     {
223       if (! cgen_signed_overflow_ok_p (cd))
224         {
225           long minval = - (1L << (length - 1));
226           long maxval =   (1L << (length - 1)) - 1;
227           
228           if (value < minval || value > maxval)
229             {
230               sprintf
231                 /* xgettext:c-format */
232                 (errbuf, _("operand out of range (%ld not between %ld and %ld)"),
233                  value, minval, maxval);
234               return errbuf;
235             }
236         }
237     }
238
239 #if CGEN_INT_INSN_P
240
241   {
242     int shift;
243
244     if (CGEN_INSN_LSB0_P)
245       shift = (word_offset + start + 1) - length;
246     else
247       shift = total_length - (word_offset + start + length);
248     *buffer = (*buffer & ~(mask << shift)) | ((value & mask) << shift);
249   }
250
251 #else /* ! CGEN_INT_INSN_P */
252
253   {
254     unsigned char *bufp = (unsigned char *) buffer + word_offset / 8;
255
256     insert_1 (cd, value, start, length, word_length, bufp);
257   }
258
259 #endif /* ! CGEN_INT_INSN_P */
260
261   return NULL;
262 }
263
264 /* Default insn builder (insert handler).
265    The instruction is recorded in CGEN_INT_INSN_P byte order
266    (meaning that if CGEN_INT_INSN_P BUFFER is an int * and thus the value is
267    recorded in host byte order, otherwise BUFFER is an array of bytes and the
268    value is recorded in target byte order).
269    The result is an error message or NULL if success.  */
270
271 static const char *
272 insert_insn_normal (cd, insn, fields, buffer, pc)
273      CGEN_CPU_DESC cd;
274      const CGEN_INSN * insn;
275      CGEN_FIELDS * fields;
276      CGEN_INSN_BYTES_PTR buffer;
277      bfd_vma pc;
278 {
279   const CGEN_SYNTAX *syntax = CGEN_INSN_SYNTAX (insn);
280   unsigned long value;
281   const unsigned char * syn;
282
283   CGEN_INIT_INSERT (cd);
284   value = CGEN_INSN_BASE_VALUE (insn);
285
286   /* If we're recording insns as numbers (rather than a string of bytes),
287      target byte order handling is deferred until later.  */
288
289 #if CGEN_INT_INSN_P
290
291   put_insn_int_value (cd, buffer, cd->base_insn_bitsize,
292                       CGEN_FIELDS_BITSIZE (fields), value);
293
294 #else
295
296   cgen_put_insn_value (cd, buffer, min (cd->base_insn_bitsize,
297                                         CGEN_FIELDS_BITSIZE (fields)),
298                        value);
299
300 #endif /* ! CGEN_INT_INSN_P */
301
302   /* ??? It would be better to scan the format's fields.
303      Still need to be able to insert a value based on the operand though;
304      e.g. storing a branch displacement that got resolved later.
305      Needs more thought first.  */
306
307   for (syn = CGEN_SYNTAX_STRING (syntax); * syn != '\0'; ++ syn)
308     {
309       const char *errmsg;
310
311       if (CGEN_SYNTAX_CHAR_P (* syn))
312         continue;
313
314       errmsg = (* cd->insert_operand) (cd, CGEN_SYNTAX_FIELD (*syn),
315                                        fields, buffer, pc);
316       if (errmsg)
317         return errmsg;
318     }
319
320   return NULL;
321 }
322
323 /* Cover function to store an insn value into an integral insn.  Must go here
324  because it needs <prefix>-desc.h for CGEN_INT_INSN_P.  */
325
326 static void
327 put_insn_int_value (cd, buf, length, insn_length, value)
328      CGEN_CPU_DESC cd;
329      CGEN_INSN_BYTES_PTR buf;
330      int length;
331      int insn_length;
332      CGEN_INSN_INT value;
333 {
334   /* For architectures with insns smaller than the base-insn-bitsize,
335      length may be too big.  */
336   if (length > insn_length)
337     *buf = value;
338   else
339     {
340       int shift = insn_length - length;
341       /* Written this way to avoid undefined behaviour.  */
342       CGEN_INSN_INT mask = (((1L << (length - 1)) - 1) << 1) | 1;
343       *buf = (*buf & ~(mask << shift)) | ((value & mask) << shift);
344     }
345 }
346 \f
347 /* Operand extraction.  */
348
349 #if ! CGEN_INT_INSN_P
350
351 /* Subroutine of extract_normal.
352    Ensure sufficient bytes are cached in EX_INFO.
353    OFFSET is the offset in bytes from the start of the insn of the value.
354    BYTES is the length of the needed value.
355    Returns 1 for success, 0 for failure.  */
356
357 static CGEN_INLINE int
358 fill_cache (cd, ex_info, offset, bytes, pc)
359      CGEN_CPU_DESC cd;
360      CGEN_EXTRACT_INFO *ex_info;
361      int offset, bytes;
362      bfd_vma pc;
363 {
364   /* It's doubtful that the middle part has already been fetched so
365      we don't optimize that case.  kiss.  */
366   int mask;
367   disassemble_info *info = (disassemble_info *) ex_info->dis_info;
368
369   /* First do a quick check.  */
370   mask = (1 << bytes) - 1;
371   if (((ex_info->valid >> offset) & mask) == mask)
372     return 1;
373
374   /* Search for the first byte we need to read.  */
375   for (mask = 1 << offset; bytes > 0; --bytes, ++offset, mask <<= 1)
376     if (! (mask & ex_info->valid))
377       break;
378
379   if (bytes)
380     {
381       int status;
382
383       pc += offset;
384       status = (*info->read_memory_func)
385         (pc, ex_info->insn_bytes + offset, bytes, info);
386
387       if (status != 0)
388         {
389           (*info->memory_error_func) (status, pc, info);
390           return 0;
391         }
392
393       ex_info->valid |= ((1 << bytes) - 1) << offset;
394     }
395
396   return 1;
397 }
398
399 /* Subroutine of extract_normal.  */
400
401 static CGEN_INLINE long
402 extract_1 (cd, ex_info, start, length, word_length, bufp, pc)
403      CGEN_CPU_DESC cd;
404      CGEN_EXTRACT_INFO *ex_info;
405      int start,length,word_length;
406      unsigned char *bufp;
407      bfd_vma pc;
408 {
409   unsigned long x,mask;
410   int shift;
411   int big_p = CGEN_CPU_INSN_ENDIAN (cd) == CGEN_ENDIAN_BIG;
412
413   switch (word_length)
414     {
415     case 8:
416       x = *bufp;
417       break;
418     case 16:
419       if (big_p)
420         x = bfd_getb16 (bufp);
421       else
422         x = bfd_getl16 (bufp);
423       break;
424     case 24:
425       /* ??? This may need reworking as these cases don't necessarily
426          want the first byte and the last two bytes handled like this.  */
427       if (big_p)
428         x = (bufp[0] << 16) | bfd_getb16 (bufp + 1);
429       else
430         x = bfd_getl16 (bufp) | (bufp[2] << 16);
431       break;
432     case 32:
433       if (big_p)
434         x = bfd_getb32 (bufp);
435       else
436         x = bfd_getl32 (bufp);
437       break;
438     default :
439       abort ();
440     }
441
442   /* Written this way to avoid undefined behaviour.  */
443   mask = (((1L << (length - 1)) - 1) << 1) | 1;
444   if (CGEN_INSN_LSB0_P)
445     shift = (start + 1) - length;
446   else
447     shift = (word_length - (start + length));
448   return (x >> shift) & mask;
449 }
450
451 #endif /* ! CGEN_INT_INSN_P */
452
453 /* Default extraction routine.
454
455    INSN_VALUE is the first base_insn_bitsize bits of the insn in host order,
456    or sometimes less for cases like the m32r where the base insn size is 32
457    but some insns are 16 bits.
458    ATTRS is a mask of the boolean attributes.  We only need `SIGNED',
459    but for generality we take a bitmask of all of them.
460    WORD_OFFSET is the offset in bits from the start of the insn of the value.
461    WORD_LENGTH is the length of the word in bits in which the value resides.
462    START is the starting bit number in the word, architecture origin.
463    LENGTH is the length of VALUE in bits.
464    TOTAL_LENGTH is the total length of the insn in bits.
465
466    Returns 1 for success, 0 for failure.  */
467
468 /* ??? The return code isn't properly used.  wip.  */
469
470 /* ??? This doesn't handle bfd_vma's.  Create another function when
471    necessary.  */
472
473 static int
474 extract_normal (cd, ex_info, insn_value, attrs, word_offset, start, length,
475                 word_length, total_length, pc, valuep)
476      CGEN_CPU_DESC cd;
477 #if ! CGEN_INT_INSN_P
478      CGEN_EXTRACT_INFO *ex_info;
479 #else
480      CGEN_EXTRACT_INFO *ex_info ATTRIBUTE_UNUSED;
481 #endif
482      CGEN_INSN_INT insn_value;
483      unsigned int attrs;
484      unsigned int word_offset, start, length, word_length, total_length;
485 #if ! CGEN_INT_INSN_P
486      bfd_vma pc;
487 #else
488      bfd_vma pc ATTRIBUTE_UNUSED;
489 #endif
490      long *valuep;
491 {
492   CGEN_INSN_INT value;
493
494   /* If LENGTH is zero, this operand doesn't contribute to the value
495      so give it a standard value of zero.  */
496   if (length == 0)
497     {
498       *valuep = 0;
499       return 1;
500     }
501
502 #if 0
503   if (CGEN_INT_INSN_P
504       && word_offset != 0)
505     abort ();
506 #endif
507
508   if (word_length > 32)
509     abort ();
510
511   /* For architectures with insns smaller than the insn-base-bitsize,
512      word_length may be too big.  */
513   if (cd->min_insn_bitsize < cd->base_insn_bitsize)
514     {
515       if (word_offset == 0
516           && word_length > total_length)
517         word_length = total_length;
518     }
519
520   /* Does the value reside in INSN_VALUE?  */
521
522   if (CGEN_INT_INSN_P || word_offset == 0)
523     {
524       /* Written this way to avoid undefined behaviour.  */
525       CGEN_INSN_INT mask = (((1L << (length - 1)) - 1) << 1) | 1;
526
527       if (CGEN_INSN_LSB0_P)
528         value = insn_value >> ((word_offset + start + 1) - length);
529       else
530         value = insn_value >> (total_length - ( word_offset + start + length));
531       value &= mask;
532       /* sign extend? */
533       if (CGEN_BOOL_ATTR (attrs, CGEN_IFLD_SIGNED)
534           && (value & (1L << (length - 1))))
535         value |= ~mask;
536     }
537
538 #if ! CGEN_INT_INSN_P
539
540   else
541     {
542       unsigned char *bufp = ex_info->insn_bytes + word_offset / 8;
543
544       if (word_length > 32)
545         abort ();
546
547       if (fill_cache (cd, ex_info, word_offset / 8, word_length / 8, pc) == 0)
548         return 0;
549
550       value = extract_1 (cd, ex_info, start, length, word_length, bufp, pc);
551     }
552
553 #endif /* ! CGEN_INT_INSN_P */
554
555   *valuep = value;
556
557   return 1;
558 }
559
560 /* Default insn extractor.
561
562    INSN_VALUE is the first base_insn_bitsize bits, translated to host order.
563    The extracted fields are stored in FIELDS.
564    EX_INFO is used to handle reading variable length insns.
565    Return the length of the insn in bits, or 0 if no match,
566    or -1 if an error occurs fetching data (memory_error_func will have
567    been called).  */
568
569 static int
570 extract_insn_normal (cd, insn, ex_info, insn_value, fields, pc)
571      CGEN_CPU_DESC cd;
572      const CGEN_INSN *insn;
573      CGEN_EXTRACT_INFO *ex_info;
574      CGEN_INSN_INT insn_value;
575      CGEN_FIELDS *fields;
576      bfd_vma pc;
577 {
578   const CGEN_SYNTAX *syntax = CGEN_INSN_SYNTAX (insn);
579   const unsigned char *syn;
580
581   CGEN_FIELDS_BITSIZE (fields) = CGEN_INSN_BITSIZE (insn);
582
583   CGEN_INIT_EXTRACT (cd);
584
585   for (syn = CGEN_SYNTAX_STRING (syntax); *syn; ++syn)
586     {
587       int length;
588
589       if (CGEN_SYNTAX_CHAR_P (*syn))
590         continue;
591
592       length = (* cd->extract_operand) (cd, CGEN_SYNTAX_FIELD (*syn),
593                                         ex_info, insn_value, fields, pc);
594       if (length <= 0)
595         return length;
596     }
597
598   /* We recognized and successfully extracted this insn.  */
599   return CGEN_INSN_BITSIZE (insn);
600 }
601 \f
602 /* machine generated code added here */