* cgen-asm.in (insert_normal): Use CGEN_BOOL_ATTR.
[platform/upstream/binutils.git] / opcodes / cgen-dis.in
1 /* Disassembler interface for targets using CGEN. -*- C -*-
2    CGEN: Cpu tools GENerator
3
4 THIS FILE IS USED TO GENERATE @prefix@-dis.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 <stdio.h>
26 #include "ansidecl.h"
27 #include "dis-asm.h"
28 #include "bfd.h"
29 #include "symcat.h"
30 #include "@prefix@-opc.h"
31 #include "opintl.h"
32
33 #undef INLINE
34 #ifdef __GNUC__
35 #define INLINE __inline__
36 #else
37 #define INLINE
38 #endif
39
40 /* Default text to print if an instruction isn't recognized.  */
41 #define UNKNOWN_INSN_MSG _("*unknown*")
42
43 /* Used by the ifield rtx function.  */
44 #define FLD(f) (fields->f)
45
46 static int extract_normal
47      PARAMS ((CGEN_OPCODE_DESC, CGEN_EXTRACT_INFO *, CGEN_INSN_INT,
48               unsigned int, unsigned int, unsigned int, unsigned int,
49               unsigned int, unsigned int, bfd_vma, long *));
50 static void print_normal
51      PARAMS ((CGEN_OPCODE_DESC, PTR, long, unsigned int, bfd_vma, int));
52 static void print_address
53      PARAMS ((CGEN_OPCODE_DESC, PTR, bfd_vma, unsigned int, bfd_vma, int));
54 static void print_keyword
55      PARAMS ((CGEN_OPCODE_DESC, PTR, CGEN_KEYWORD *, long, unsigned int));
56 static int extract_insn_normal
57      PARAMS ((CGEN_OPCODE_DESC, const CGEN_INSN *, CGEN_EXTRACT_INFO *,
58               CGEN_INSN_INT, CGEN_FIELDS *, bfd_vma));
59 static void print_insn_normal
60      PARAMS ((CGEN_OPCODE_DESC, PTR, const CGEN_INSN *, CGEN_FIELDS *,
61               bfd_vma, int));
62 static int print_insn PARAMS ((CGEN_OPCODE_DESC, bfd_vma,
63                                disassemble_info *, char *, int));
64 static int default_print_insn
65      PARAMS ((CGEN_OPCODE_DESC, bfd_vma, disassemble_info *));
66 \f
67 /* -- disassembler routines inserted here */
68 \f
69 #if ! CGEN_INT_INSN_P
70
71 /* Subroutine of extract_normal.
72    Ensure sufficient bytes are cached in EX_INFO.
73    OFFSET is the offset in bytes from the start of the insn of the value.
74    BYTES is the length of the needed value.
75    Returns 1 for success, 0 for failure.  */
76
77 static INLINE int
78 fill_cache (od, ex_info, offset, bytes, pc)
79      CGEN_OPCODE_DESC od;
80      CGEN_EXTRACT_INFO *ex_info;
81      int offset, bytes;
82      bfd_vma pc;
83 {
84   /* It's doubtful that the middle part has already been fetched so
85      we don't optimize that case.  kiss.  */
86   int mask;
87   disassemble_info *info = (disassemble_info *) ex_info->dis_info;
88
89   /* First do a quick check.  */
90   mask = (1 << bytes) - 1;
91   if (((ex_info->valid >> offset) & mask) == mask)
92     return 1;
93
94   /* Search for the first byte we need to read.  */
95   for (mask = 1 << offset; bytes > 0; --bytes, ++offset, mask <<= 1)
96     if (! (mask & ex_info->valid))
97       break;
98
99   if (bytes)
100     {
101       int status;
102
103       pc += offset;
104       status = (*info->read_memory_func)
105         (pc, ex_info->insn_bytes + offset, bytes, info);
106
107       if (status != 0)
108         {
109           (*info->memory_error_func) (status, pc, info);
110           return 0;
111         }
112
113       ex_info->valid |= ((1 << bytes) - 1) << offset;
114     }
115
116   return 1;
117 }
118
119 /* Subroutine of extract_normal.  */
120
121 static INLINE long
122 extract_1 (od, ex_info, start, length, word_length, bufp, pc)
123      CGEN_OPCODE_DESC od;
124      CGEN_EXTRACT_INFO *ex_info;
125      int start,length,word_length;
126      unsigned char *bufp;
127      bfd_vma pc;
128 {
129   unsigned long x,mask;
130   int shift;
131   int big_p = CGEN_OPCODE_INSN_ENDIAN (od) == CGEN_ENDIAN_BIG;
132
133   switch (word_length)
134     {
135     case 8:
136       x = *bufp;
137       break;
138     case 16:
139       if (big_p)
140         x = bfd_getb16 (bufp);
141       else
142         x = bfd_getl16 (bufp);
143       break;
144     case 24:
145       /* ??? This may need reworking as these cases don't necessarily
146          want the first byte and the last two bytes handled like this.  */
147       if (big_p)
148         x = (bufp[0] << 16) | bfd_getb16 (bufp + 1);
149       else
150         x = bfd_getl16 (bufp) | (bufp[2] << 16);
151       break;
152     case 32:
153       if (big_p)
154         x = bfd_getb32 (bufp);
155       else
156         x = bfd_getl32 (bufp);
157       break;
158     default :
159       abort ();
160     }
161
162   /* Written this way to avoid undefined behaviour.  */
163   mask = (((1L << (length - 1)) - 1) << 1) | 1;
164   if (CGEN_INSN_LSB0_P)
165     shift = (start + 1) - length;
166   else
167     shift = (word_length - (start + length));
168   return (x >> shift) & mask;
169 }
170
171 #endif /* ! CGEN_INT_INSN_P */
172
173 /* Default extraction routine.
174
175    INSN_VALUE is the first CGEN_BASE_INSN_SIZE bits of the insn in host order,
176    or sometimes less for cases like the m32r where the base insn size is 32
177    but some insns are 16 bits.
178    ATTRS is a mask of the boolean attributes.  We only need `UNSIGNED',
179    but for generality we take a bitmask of all of them.
180    WORD_OFFSET is the offset in bits from the start of the insn of the value.
181    WORD_LENGTH is the length of the word in bits in which the value resides.
182    START is the starting bit number in the word, architecture origin.
183    LENGTH is the length of VALUE in bits.
184    TOTAL_LENGTH is the total length of the insn in bits.
185
186    Returns 1 for success, 0 for failure.  */
187
188 /* ??? The return code isn't properly used.  wip.  */
189
190 /* ??? This doesn't handle bfd_vma's.  Create another function when
191    necessary.  */
192
193 static int
194 extract_normal (od, ex_info, insn_value, attrs, word_offset, start, length,
195                 word_length, total_length, pc, valuep)
196      CGEN_OPCODE_DESC od;
197      CGEN_EXTRACT_INFO *ex_info;
198      CGEN_INSN_INT insn_value;
199      unsigned int attrs;
200      unsigned int word_offset, start, length, word_length, total_length;
201      bfd_vma pc;
202      long *valuep;
203 {
204   CGEN_INSN_INT value;
205
206   /* If LENGTH is zero, this operand doesn't contribute to the value
207      so give it a standard value of zero.  */
208   if (length == 0)
209     {
210       *valuep = 0;
211       return 1;
212     }
213
214   if (CGEN_INT_INSN_P
215       && word_offset != 0)
216     abort ();
217
218   if (word_length > 32)
219     abort ();
220
221   /* For architectures with insns smaller than the insn-base-bitsize,
222      word_length may be too big.  */
223 #if CGEN_MIN_INSN_BITSIZE < CGEN_BASE_INSN_BITSIZE
224   if (word_offset == 0
225       && word_length > total_length)
226     word_length = total_length;
227 #endif
228
229   /* Does the value reside in INSN_VALUE?  */
230
231   if (word_offset == 0)
232     {
233       /* Written this way to avoid undefined behaviour.  */
234       CGEN_INSN_INT mask = (((1L << (length - 1)) - 1) << 1) | 1;
235
236       if (CGEN_INSN_LSB0_P)
237         value = insn_value >> ((start + 1) - length);
238       else
239         value = insn_value >> (word_length - (start + length));
240       value &= mask;
241       /* sign extend? */
242       if (! CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_UNSIGNED)
243           && (value & (1L << (length - 1))))
244         value |= ~mask;
245     }
246
247 #if ! CGEN_INT_INSN_P
248
249   else
250     {
251       unsigned char *bufp = ex_info->insn_bytes + word_offset / 8;
252
253       if (word_length > 32)
254         abort ();
255
256       if (fill_cache (od, ex_info, word_offset / 8, word_length / 8, pc) == 0)
257         return 0;
258
259       value = extract_1 (od, ex_info, start, length, word_length, bufp, pc);
260     }
261
262 #endif /* ! CGEN_INT_INSN_P */
263
264   *valuep = value;
265
266   return 1;
267 }
268
269 /* Default print handler.  */
270
271 static void
272 print_normal (od, dis_info, value, attrs, pc, length)
273      CGEN_OPCODE_DESC od;
274      PTR dis_info;
275      long value;
276      unsigned int attrs;
277      bfd_vma pc;
278      int length;
279 {
280   disassemble_info *info = (disassemble_info *) dis_info;
281
282 #ifdef CGEN_PRINT_NORMAL
283   CGEN_PRINT_NORMAL (od, info, value, attrs, pc, length);
284 #endif
285
286   /* Print the operand as directed by the attributes.  */
287   if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_SEM_ONLY))
288     ; /* nothing to do */
289   else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_UNSIGNED))
290     (*info->fprintf_func) (info->stream, "0x%lx", value);
291   else
292     (*info->fprintf_func) (info->stream, "%ld", value);
293 }
294
295 /* Default address handler.  */
296
297 static void
298 print_address (od, dis_info, value, attrs, pc, length)
299      CGEN_OPCODE_DESC od;
300      PTR dis_info;
301      bfd_vma value;
302      unsigned int attrs;
303      bfd_vma pc;
304      int length;
305 {
306   disassemble_info *info = (disassemble_info *) dis_info;
307
308 #ifdef CGEN_PRINT_ADDRESS
309   CGEN_PRINT_ADDRESS (od, info, value, attrs, pc, length);
310 #endif
311
312   /* Print the operand as directed by the attributes.  */
313   if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_SEM_ONLY))
314     ; /* nothing to do */
315   else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_PCREL_ADDR))
316     (*info->print_address_func) (value, info);
317   else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_ABS_ADDR))
318     (*info->print_address_func) (value, info);
319   else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_UNSIGNED))
320     (*info->fprintf_func) (info->stream, "0x%lx", (long) value);
321   else
322     (*info->fprintf_func) (info->stream, "%ld", (long) value);
323 }
324
325 /* Keyword print handler.  */
326
327 static void
328 print_keyword (od, dis_info, keyword_table, value, attrs)
329      CGEN_OPCODE_DESC od;
330      PTR dis_info;
331      CGEN_KEYWORD *keyword_table;
332      long value;
333      unsigned int attrs;
334 {
335   disassemble_info *info = (disassemble_info *) dis_info;
336   const CGEN_KEYWORD_ENTRY *ke;
337
338   ke = cgen_keyword_lookup_value (keyword_table, value);
339   if (ke != NULL)
340     (*info->fprintf_func) (info->stream, "%s", ke->name);
341   else
342     (*info->fprintf_func) (info->stream, "???");
343 }
344 \f
345 /* Default insn extractor.
346
347    INSN_VALUE is the first CGEN_BASE_INSN_SIZE bytes, translated to host order.
348    The extracted fields are stored in FIELDS.
349    EX_INFO is used to handle reading variable length insns.
350    Return the length of the insn in bits, or 0 if no match,
351    or -1 if an error occurs fetching data (memory_error_func will have
352    been called).  */
353
354 static int
355 extract_insn_normal (od, insn, ex_info, insn_value, fields, pc)
356      CGEN_OPCODE_DESC od;
357      const CGEN_INSN *insn;
358      CGEN_EXTRACT_INFO *ex_info;
359      CGEN_INSN_INT insn_value;
360      CGEN_FIELDS *fields;
361      bfd_vma pc;
362 {
363   const CGEN_SYNTAX *syntax = CGEN_INSN_SYNTAX (insn);
364   const unsigned char *syn;
365
366   CGEN_FIELDS_BITSIZE (fields) = CGEN_INSN_BITSIZE (insn);
367
368   CGEN_INIT_EXTRACT (od);
369
370   for (syn = CGEN_SYNTAX_STRING (syntax); *syn; ++syn)
371     {
372       int length;
373
374       if (CGEN_SYNTAX_CHAR_P (*syn))
375         continue;
376
377       length = @arch@_cgen_extract_operand (od, CGEN_SYNTAX_FIELD (*syn),
378                                             ex_info, insn_value, fields, pc);
379       if (length <= 0)
380         return length;
381     }
382
383   /* We recognized and successfully extracted this insn.  */
384   return CGEN_INSN_BITSIZE (insn);
385 }
386
387 /* Default insn printer.
388
389    DIS_INFO is defined as `PTR' so the disassembler needn't know anything
390    about disassemble_info.  */
391
392 static void
393 print_insn_normal (od, dis_info, insn, fields, pc, length)
394      CGEN_OPCODE_DESC od;
395      PTR dis_info;
396      const CGEN_INSN *insn;
397      CGEN_FIELDS *fields;
398      bfd_vma pc;
399      int length;
400 {
401   const CGEN_SYNTAX *syntax = CGEN_INSN_SYNTAX (insn);
402   disassemble_info *info = (disassemble_info *) dis_info;
403   const unsigned char *syn;
404
405   CGEN_INIT_PRINT (od);
406
407   for (syn = CGEN_SYNTAX_STRING (syntax); *syn; ++syn)
408     {
409       if (CGEN_SYNTAX_MNEMONIC_P (*syn))
410         {
411           (*info->fprintf_func) (info->stream, "%s", CGEN_INSN_MNEMONIC (insn));
412           continue;
413         }
414       if (CGEN_SYNTAX_CHAR_P (*syn))
415         {
416           (*info->fprintf_func) (info->stream, "%c", CGEN_SYNTAX_CHAR (*syn));
417           continue;
418         }
419
420       /* We have an operand.  */
421       @arch@_cgen_print_operand (od, CGEN_SYNTAX_FIELD (*syn), info,
422                                  fields, CGEN_INSN_ATTRS (insn), pc, length);
423     }
424 }
425 \f
426 /* Utility to print an insn.
427    BUF is the base part of the insn, target byte order, BUFLEN bytes long.
428    The result is the size of the insn in bytes or zero for an unknown insn
429    or -1 if an error occurs fetching data (memory_error_func will have
430    been called).  */
431
432 static int
433 print_insn (od, pc, info, buf, buflen)
434      CGEN_OPCODE_DESC od;
435      bfd_vma pc;
436      disassemble_info *info;
437      char *buf;
438      int buflen;
439 {
440   unsigned long insn_value;
441   const CGEN_INSN_LIST *insn_list;
442   CGEN_EXTRACT_INFO ex_info;
443
444   ex_info.dis_info = info;
445   ex_info.valid = (1 << CGEN_BASE_INSN_SIZE) - 1;
446   ex_info.insn_bytes = buf;
447
448   switch (buflen)
449     {
450     case 1:
451       insn_value = buf[0];
452       break;
453     case 2:
454       insn_value = info->endian == BFD_ENDIAN_BIG ? bfd_getb16 (buf) : bfd_getl16 (buf);
455       break;
456     case 4:
457       insn_value = info->endian == BFD_ENDIAN_BIG ? bfd_getb32 (buf) : bfd_getl32 (buf);
458       break;
459     default:
460       abort ();
461     }
462
463   /* The instructions are stored in hash lists.
464      Pick the first one and keep trying until we find the right one.  */
465
466   insn_list = CGEN_DIS_LOOKUP_INSN (od, buf, insn_value);
467   while (insn_list != NULL)
468     {
469       const CGEN_INSN *insn = insn_list->insn;
470       CGEN_FIELDS fields;
471       int length;
472
473 #if 0 /* not needed as insn shouldn't be in hash lists if not supported */
474       /* Supported by this cpu?  */
475       if (! @arch@_cgen_insn_supported (od, insn))
476         continue;
477 #endif
478
479       /* Basic bit mask must be correct.  */
480       /* ??? May wish to allow target to defer this check until the extract
481          handler.  */
482       if ((insn_value & CGEN_INSN_BASE_MASK (insn))
483           == CGEN_INSN_BASE_VALUE (insn))
484         {
485           /* Printing is handled in two passes.  The first pass parses the
486              machine insn and extracts the fields.  The second pass prints
487              them.  */
488
489           length = (*CGEN_EXTRACT_FN (insn)) (od, insn, &ex_info, insn_value,
490                                               &fields, pc);
491           /* length < 0 -> error */
492           if (length < 0)
493             return length;
494           if (length > 0)
495             {
496               (*CGEN_PRINT_FN (insn)) (od, info, insn, &fields, pc, length);
497               /* length is in bits, result is in bytes */
498               return length / 8;
499             }
500         }
501
502       insn_list = CGEN_DIS_NEXT_INSN (insn_list);
503     }
504
505   return 0;
506 }
507
508 /* Default value for CGEN_PRINT_INSN.
509    The result is the size of the insn in bytes or zero for an unknown insn
510    or -1 if an error occured fetching bytes.  */
511
512 #ifndef CGEN_PRINT_INSN
513 #define CGEN_PRINT_INSN default_print_insn
514 #endif
515
516 static int
517 default_print_insn (od, pc, info)
518      CGEN_OPCODE_DESC od;
519      bfd_vma pc;
520      disassemble_info *info;
521 {
522   char buf[CGEN_MAX_INSN_SIZE];
523   int status;
524
525   /* Read the base part of the insn.  */
526
527   status = (*info->read_memory_func) (pc, buf, CGEN_BASE_INSN_SIZE, info);
528   if (status != 0)
529     {
530       (*info->memory_error_func) (status, pc, info);
531       return -1;
532     }
533
534   return print_insn (od, pc, info, buf, CGEN_BASE_INSN_SIZE);
535 }
536
537 /* Main entry point.
538    Print one instruction from PC on INFO->STREAM.
539    Return the size of the instruction (in bytes).  */
540
541 int
542 print_insn_@arch@ (pc, info)
543      bfd_vma pc;
544      disassemble_info *info;
545 {
546   int length;
547   static CGEN_OPCODE_DESC od = 0;
548   int mach = info->mach;
549   int big_p = info->endian == BFD_ENDIAN_BIG;
550
551   /* If we haven't initialized yet, initialize the opcode table.  */
552   if (! od)
553     {
554       od = @arch@_cgen_opcode_open (mach,
555                                     big_p ?
556                                     CGEN_ENDIAN_BIG
557                                     : CGEN_ENDIAN_LITTLE);
558       @arch@_cgen_init_dis (od);
559     }
560   /* If we've switched cpu's, re-initialize.  */
561   /* ??? Perhaps we should use BFD_ENDIAN.  */
562   else if (mach != CGEN_OPCODE_MACH (od)
563            || (CGEN_OPCODE_ENDIAN (od)
564                != (big_p ? CGEN_ENDIAN_BIG : CGEN_ENDIAN_LITTLE)))
565     {
566       cgen_set_cpu (od, mach, big_p ? CGEN_ENDIAN_BIG : CGEN_ENDIAN_LITTLE);
567     }
568
569   /* We try to have as much common code as possible.
570      But at this point some targets need to take over.  */
571   /* ??? Some targets may need a hook elsewhere.  Try to avoid this,
572      but if not possible try to move this hook elsewhere rather than
573      have two hooks.  */
574   length = CGEN_PRINT_INSN (od, pc, info);
575   if (length > 0)
576     return length;
577   if (length < 0)
578     return -1;
579
580   (*info->fprintf_func) (info->stream, UNKNOWN_INSN_MSG);
581   return CGEN_DEFAULT_INSN_SIZE;
582 }