1 /* Disassembler interface for targets using CGEN. -*- C -*-
2 CGEN: Cpu tools GENerator
4 THIS FILE IS USED TO GENERATE @prefix@-dis.c.
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. */
30 #include "@prefix@-opc.h"
35 #define INLINE __inline__
40 /* Default text to print if an instruction isn't recognized. */
41 #define UNKNOWN_INSN_MSG _("*unknown*")
43 /* Used by the ifield rtx function. */
44 #define FLD(f) (fields->f)
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 *,
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 *));
67 /* -- disassembler routines inserted here */
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. */
78 fill_cache (od, ex_info, offset, bytes, pc)
80 CGEN_EXTRACT_INFO *ex_info;
84 /* It's doubtful that the middle part has already been fetched so
85 we don't optimize that case. kiss. */
87 disassemble_info *info = (disassemble_info *) ex_info->dis_info;
89 /* First do a quick check. */
90 mask = (1 << bytes) - 1;
91 if (((ex_info->valid >> offset) & mask) == mask)
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))
104 status = (*info->read_memory_func)
105 (pc, ex_info->insn_bytes + offset, bytes, info);
109 (*info->memory_error_func) (status, pc, info);
113 ex_info->valid |= ((1 << bytes) - 1) << offset;
119 /* Subroutine of extract_normal. */
122 extract_1 (od, ex_info, start, length, word_length, bufp, pc)
124 CGEN_EXTRACT_INFO *ex_info;
125 int start,length,word_length;
129 unsigned long x,mask;
131 int big_p = CGEN_OPCODE_INSN_ENDIAN (od) == CGEN_ENDIAN_BIG;
140 x = bfd_getb16 (bufp);
142 x = bfd_getl16 (bufp);
145 /* ??? This may need reworking as these cases don't necessarily
146 want the first byte and the last two bytes handled like this. */
148 x = (bufp[0] << 16) | bfd_getb16 (bufp + 1);
150 x = bfd_getl16 (bufp) | (bufp[2] << 16);
154 x = bfd_getb32 (bufp);
156 x = bfd_getl32 (bufp);
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;
167 shift = (word_length - (start + length));
168 return (x >> shift) & mask;
171 #endif /* ! CGEN_INT_INSN_P */
173 /* Default extraction routine.
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.
186 Returns 1 for success, 0 for failure. */
188 /* ??? The return code isn't properly used. wip. */
190 /* ??? This doesn't handle bfd_vma's. Create another function when
194 extract_normal (od, ex_info, insn_value, attrs, word_offset, start, length,
195 word_length, total_length, pc, valuep)
197 CGEN_EXTRACT_INFO *ex_info;
198 CGEN_INSN_INT insn_value;
200 unsigned int word_offset, start, length, word_length, total_length;
206 /* If LENGTH is zero, this operand doesn't contribute to the value
207 so give it a standard value of zero. */
218 if (word_length > 32)
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
225 && word_length > total_length)
226 word_length = total_length;
229 /* Does the value reside in INSN_VALUE? */
231 if (word_offset == 0)
233 /* Written this way to avoid undefined behaviour. */
234 CGEN_INSN_INT mask = (((1L << (length - 1)) - 1) << 1) | 1;
236 if (CGEN_INSN_LSB0_P)
237 value = insn_value >> ((start + 1) - length);
239 value = insn_value >> (word_length - (start + length));
242 if (! CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_UNSIGNED)
243 && (value & (1L << (length - 1))))
247 #if ! CGEN_INT_INSN_P
251 unsigned char *bufp = ex_info->insn_bytes + word_offset / 8;
253 if (word_length > 32)
256 if (fill_cache (od, ex_info, word_offset / 8, word_length / 8, pc) == 0)
259 value = extract_1 (od, ex_info, start, length, word_length, bufp, pc);
262 #endif /* ! CGEN_INT_INSN_P */
269 /* Default print handler. */
272 print_normal (od, dis_info, value, attrs, pc, length)
280 disassemble_info *info = (disassemble_info *) dis_info;
282 #ifdef CGEN_PRINT_NORMAL
283 CGEN_PRINT_NORMAL (od, info, value, attrs, pc, length);
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);
292 (*info->fprintf_func) (info->stream, "%ld", value);
295 /* Default address handler. */
298 print_address (od, dis_info, value, attrs, pc, length)
306 disassemble_info *info = (disassemble_info *) dis_info;
308 #ifdef CGEN_PRINT_ADDRESS
309 CGEN_PRINT_ADDRESS (od, info, value, attrs, pc, length);
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);
322 (*info->fprintf_func) (info->stream, "%ld", (long) value);
325 /* Keyword print handler. */
328 print_keyword (od, dis_info, keyword_table, value, attrs)
331 CGEN_KEYWORD *keyword_table;
335 disassemble_info *info = (disassemble_info *) dis_info;
336 const CGEN_KEYWORD_ENTRY *ke;
338 ke = cgen_keyword_lookup_value (keyword_table, value);
340 (*info->fprintf_func) (info->stream, "%s", ke->name);
342 (*info->fprintf_func) (info->stream, "???");
345 /* Default insn extractor.
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
355 extract_insn_normal (od, insn, ex_info, insn_value, fields, pc)
357 const CGEN_INSN *insn;
358 CGEN_EXTRACT_INFO *ex_info;
359 CGEN_INSN_INT insn_value;
363 const CGEN_SYNTAX *syntax = CGEN_INSN_SYNTAX (insn);
364 const unsigned char *syn;
366 CGEN_FIELDS_BITSIZE (fields) = CGEN_INSN_BITSIZE (insn);
368 CGEN_INIT_EXTRACT (od);
370 for (syn = CGEN_SYNTAX_STRING (syntax); *syn; ++syn)
374 if (CGEN_SYNTAX_CHAR_P (*syn))
377 length = @arch@_cgen_extract_operand (od, CGEN_SYNTAX_FIELD (*syn),
378 ex_info, insn_value, fields, pc);
383 /* We recognized and successfully extracted this insn. */
384 return CGEN_INSN_BITSIZE (insn);
387 /* Default insn printer.
389 DIS_INFO is defined as `PTR' so the disassembler needn't know anything
390 about disassemble_info. */
393 print_insn_normal (od, dis_info, insn, fields, pc, length)
396 const CGEN_INSN *insn;
401 const CGEN_SYNTAX *syntax = CGEN_INSN_SYNTAX (insn);
402 disassemble_info *info = (disassemble_info *) dis_info;
403 const unsigned char *syn;
405 CGEN_INIT_PRINT (od);
407 for (syn = CGEN_SYNTAX_STRING (syntax); *syn; ++syn)
409 if (CGEN_SYNTAX_MNEMONIC_P (*syn))
411 (*info->fprintf_func) (info->stream, "%s", CGEN_INSN_MNEMONIC (insn));
414 if (CGEN_SYNTAX_CHAR_P (*syn))
416 (*info->fprintf_func) (info->stream, "%c", CGEN_SYNTAX_CHAR (*syn));
420 /* We have an operand. */
421 @arch@_cgen_print_operand (od, CGEN_SYNTAX_FIELD (*syn), info,
422 fields, CGEN_INSN_ATTRS (insn), pc, length);
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
433 print_insn (od, pc, info, buf, buflen)
436 disassemble_info *info;
440 unsigned long insn_value;
441 const CGEN_INSN_LIST *insn_list;
442 CGEN_EXTRACT_INFO ex_info;
444 ex_info.dis_info = info;
445 ex_info.valid = (1 << CGEN_BASE_INSN_SIZE) - 1;
446 ex_info.insn_bytes = buf;
454 insn_value = info->endian == BFD_ENDIAN_BIG ? bfd_getb16 (buf) : bfd_getl16 (buf);
457 insn_value = info->endian == BFD_ENDIAN_BIG ? bfd_getb32 (buf) : bfd_getl32 (buf);
463 /* The instructions are stored in hash lists.
464 Pick the first one and keep trying until we find the right one. */
466 insn_list = CGEN_DIS_LOOKUP_INSN (od, buf, insn_value);
467 while (insn_list != NULL)
469 const CGEN_INSN *insn = insn_list->insn;
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))
479 /* Basic bit mask must be correct. */
480 /* ??? May wish to allow target to defer this check until the extract
482 if ((insn_value & CGEN_INSN_BASE_MASK (insn))
483 == CGEN_INSN_BASE_VALUE (insn))
485 /* Printing is handled in two passes. The first pass parses the
486 machine insn and extracts the fields. The second pass prints
489 length = (*CGEN_EXTRACT_FN (insn)) (od, insn, &ex_info, insn_value,
491 /* length < 0 -> error */
496 (*CGEN_PRINT_FN (insn)) (od, info, insn, &fields, pc, length);
497 /* length is in bits, result is in bytes */
502 insn_list = CGEN_DIS_NEXT_INSN (insn_list);
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. */
512 #ifndef CGEN_PRINT_INSN
513 #define CGEN_PRINT_INSN default_print_insn
517 default_print_insn (od, pc, info)
520 disassemble_info *info;
522 char buf[CGEN_MAX_INSN_SIZE];
525 /* Read the base part of the insn. */
527 status = (*info->read_memory_func) (pc, buf, CGEN_BASE_INSN_SIZE, info);
530 (*info->memory_error_func) (status, pc, info);
534 return print_insn (od, pc, info, buf, CGEN_BASE_INSN_SIZE);
538 Print one instruction from PC on INFO->STREAM.
539 Return the size of the instruction (in bytes). */
542 print_insn_@arch@ (pc, info)
544 disassemble_info *info;
547 static CGEN_OPCODE_DESC od = 0;
548 int mach = info->mach;
549 int big_p = info->endian == BFD_ENDIAN_BIG;
551 /* If we haven't initialized yet, initialize the opcode table. */
554 od = @arch@_cgen_opcode_open (mach,
557 : CGEN_ENDIAN_LITTLE);
558 @arch@_cgen_init_dis (od);
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)))
566 cgen_set_cpu (od, mach, big_p ? CGEN_ENDIAN_BIG : CGEN_ENDIAN_LITTLE);
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
574 length = CGEN_PRINT_INSN (od, pc, info);
580 (*info->fprintf_func) (info->stream, UNKNOWN_INSN_MSG);
581 return CGEN_DEFAULT_INSN_SIZE;