1 /* Disassembler interface for targets using CGEN. -*- C -*-
2 CGEN: Cpu tools GENerator
4 THIS FILE IS USED TO GENERATE i960c-dis.c.
6 Copyright (C) 1996, 1997, 1998, 1999 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 "i960c-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 */
69 /* Main entry point for operand extraction.
71 This function is basically just a big switch statement. Earlier versions
72 used tables to look up the function to use, but
73 - if the table contains both assembler and disassembler functions then
74 the disassembler contains much of the assembler and vice-versa,
75 - there's a lot of inlining possibilities as things grow,
76 - using a switch statement avoids the function call overhead.
78 This function could be moved into `print_insn_normal', but keeping it
79 separate makes clear the interface between `print_insn_normal' and each of
84 i960_cgen_extract_operand (od
, opindex
, ex_info
, insn_value
, fields
, pc
)
87 CGEN_EXTRACT_INFO
*ex_info
;
88 CGEN_INSN_INT insn_value
;
93 unsigned int total_length
= CGEN_FIELDS_BITSIZE (fields
);
97 case I960_OPERAND_SRC1
:
98 length
= extract_normal (od
, ex_info
, insn_value
, 0|(1<<CGEN_OPERAND_UNSIGNED
), 0, 27, 5, 32, total_length
, pc
, & fields
->f_src1
);
100 case I960_OPERAND_SRC2
:
101 length
= extract_normal (od
, ex_info
, insn_value
, 0|(1<<CGEN_OPERAND_UNSIGNED
), 0, 13, 5, 32, total_length
, pc
, & fields
->f_src2
);
103 case I960_OPERAND_DST
:
104 length
= extract_normal (od
, ex_info
, insn_value
, 0|(1<<CGEN_OPERAND_UNSIGNED
), 0, 8, 5, 32, total_length
, pc
, & fields
->f_srcdst
);
106 case I960_OPERAND_LIT1
:
107 length
= extract_normal (od
, ex_info
, insn_value
, 0|(1<<CGEN_OPERAND_UNSIGNED
), 0, 27, 5, 32, total_length
, pc
, & fields
->f_src1
);
109 case I960_OPERAND_LIT2
:
110 length
= extract_normal (od
, ex_info
, insn_value
, 0|(1<<CGEN_OPERAND_UNSIGNED
), 0, 13, 5, 32, total_length
, pc
, & fields
->f_src2
);
112 case I960_OPERAND_ST_SRC
:
113 length
= extract_normal (od
, ex_info
, insn_value
, 0|(1<<CGEN_OPERAND_UNSIGNED
), 0, 8, 5, 32, total_length
, pc
, & fields
->f_srcdst
);
115 case I960_OPERAND_ABASE
:
116 length
= extract_normal (od
, ex_info
, insn_value
, 0|(1<<CGEN_OPERAND_UNSIGNED
), 0, 13, 5, 32, total_length
, pc
, & fields
->f_abase
);
118 case I960_OPERAND_OFFSET
:
119 length
= extract_normal (od
, ex_info
, insn_value
, 0|(1<<CGEN_OPERAND_UNSIGNED
), 0, 20, 12, 32, total_length
, pc
, & fields
->f_offset
);
121 case I960_OPERAND_SCALE
:
122 length
= extract_normal (od
, ex_info
, insn_value
, 0|(1<<CGEN_OPERAND_UNSIGNED
), 0, 22, 3, 32, total_length
, pc
, & fields
->f_scale
);
124 case I960_OPERAND_INDEX
:
125 length
= extract_normal (od
, ex_info
, insn_value
, 0|(1<<CGEN_OPERAND_UNSIGNED
), 0, 27, 5, 32, total_length
, pc
, & fields
->f_index
);
127 case I960_OPERAND_OPTDISP
:
128 length
= extract_normal (od
, ex_info
, insn_value
, 0|(1<<CGEN_OPERAND_UNSIGNED
), 32, 0, 32, 32, total_length
, pc
, & fields
->f_optdisp
);
130 case I960_OPERAND_BR_SRC1
:
131 length
= extract_normal (od
, ex_info
, insn_value
, 0|(1<<CGEN_OPERAND_UNSIGNED
), 0, 8, 5, 32, total_length
, pc
, & fields
->f_br_src1
);
133 case I960_OPERAND_BR_SRC2
:
134 length
= extract_normal (od
, ex_info
, insn_value
, 0|(1<<CGEN_OPERAND_UNSIGNED
), 0, 13, 5, 32, total_length
, pc
, & fields
->f_br_src2
);
136 case I960_OPERAND_BR_DISP
:
139 length
= extract_normal (od
, ex_info
, insn_value
, 0|(1<<CGEN_OPERAND_PCREL_ADDR
), 0, 19, 11, 32, total_length
, pc
, & value
);
140 value
= ((((value
) << (2))) + (pc
));
141 fields
->f_br_disp
= value
;
144 case I960_OPERAND_BR_LIT1
:
145 length
= extract_normal (od
, ex_info
, insn_value
, 0|(1<<CGEN_OPERAND_UNSIGNED
), 0, 8, 5, 32, total_length
, pc
, & fields
->f_br_src1
);
147 case I960_OPERAND_CTRL_DISP
:
150 length
= extract_normal (od
, ex_info
, insn_value
, 0|(1<<CGEN_OPERAND_PCREL_ADDR
), 0, 8, 22, 32, total_length
, pc
, & value
);
151 value
= ((((value
) << (2))) + (pc
));
152 fields
->f_ctrl_disp
= value
;
157 /* xgettext:c-format */
158 fprintf (stderr
, _("Unrecognized field %d while decoding insn.\n"),
166 /* Main entry point for printing operands.
168 This function is basically just a big switch statement. Earlier versions
169 used tables to look up the function to use, but
170 - if the table contains both assembler and disassembler functions then
171 the disassembler contains much of the assembler and vice-versa,
172 - there's a lot of inlining possibilities as things grow,
173 - using a switch statement avoids the function call overhead.
175 This function could be moved into `print_insn_normal', but keeping it
176 separate makes clear the interface between `print_insn_normal' and each of
181 i960_cgen_print_operand (od
, opindex
, info
, fields
, attrs
, pc
, length
)
184 disassemble_info
* info
;
185 CGEN_FIELDS
* fields
;
192 case I960_OPERAND_SRC1
:
193 print_keyword (od
, info
, & i960_cgen_opval_h_gr
, fields
->f_src1
, 0|(1<<CGEN_OPERAND_UNSIGNED
));
195 case I960_OPERAND_SRC2
:
196 print_keyword (od
, info
, & i960_cgen_opval_h_gr
, fields
->f_src2
, 0|(1<<CGEN_OPERAND_UNSIGNED
));
198 case I960_OPERAND_DST
:
199 print_keyword (od
, info
, & i960_cgen_opval_h_gr
, fields
->f_srcdst
, 0|(1<<CGEN_OPERAND_UNSIGNED
));
201 case I960_OPERAND_LIT1
:
202 print_normal (od
, info
, fields
->f_src1
, 0|(1<<CGEN_OPERAND_UNSIGNED
), pc
, length
);
204 case I960_OPERAND_LIT2
:
205 print_normal (od
, info
, fields
->f_src2
, 0|(1<<CGEN_OPERAND_UNSIGNED
), pc
, length
);
207 case I960_OPERAND_ST_SRC
:
208 print_keyword (od
, info
, & i960_cgen_opval_h_gr
, fields
->f_srcdst
, 0|(1<<CGEN_OPERAND_UNSIGNED
));
210 case I960_OPERAND_ABASE
:
211 print_keyword (od
, info
, & i960_cgen_opval_h_gr
, fields
->f_abase
, 0|(1<<CGEN_OPERAND_UNSIGNED
));
213 case I960_OPERAND_OFFSET
:
214 print_normal (od
, info
, fields
->f_offset
, 0|(1<<CGEN_OPERAND_UNSIGNED
), pc
, length
);
216 case I960_OPERAND_SCALE
:
217 print_normal (od
, info
, fields
->f_scale
, 0|(1<<CGEN_OPERAND_UNSIGNED
), pc
, length
);
219 case I960_OPERAND_INDEX
:
220 print_keyword (od
, info
, & i960_cgen_opval_h_gr
, fields
->f_index
, 0|(1<<CGEN_OPERAND_UNSIGNED
));
222 case I960_OPERAND_OPTDISP
:
223 print_normal (od
, info
, fields
->f_optdisp
, 0|(1<<CGEN_OPERAND_UNSIGNED
), pc
, length
);
225 case I960_OPERAND_BR_SRC1
:
226 print_keyword (od
, info
, & i960_cgen_opval_h_gr
, fields
->f_br_src1
, 0|(1<<CGEN_OPERAND_UNSIGNED
));
228 case I960_OPERAND_BR_SRC2
:
229 print_keyword (od
, info
, & i960_cgen_opval_h_gr
, fields
->f_br_src2
, 0|(1<<CGEN_OPERAND_UNSIGNED
));
231 case I960_OPERAND_BR_DISP
:
232 print_address (od
, info
, fields
->f_br_disp
, 0|(1<<CGEN_OPERAND_PCREL_ADDR
), pc
, length
);
234 case I960_OPERAND_BR_LIT1
:
235 print_normal (od
, info
, fields
->f_br_src1
, 0|(1<<CGEN_OPERAND_UNSIGNED
), pc
, length
);
237 case I960_OPERAND_CTRL_DISP
:
238 print_address (od
, info
, fields
->f_ctrl_disp
, 0|(1<<CGEN_OPERAND_PCREL_ADDR
), pc
, length
);
242 /* xgettext:c-format */
243 fprintf (stderr
, _("Unrecognized field %d while printing insn.\n"),
249 cgen_extract_fn
* const i960_cgen_extract_handlers
[] =
255 cgen_print_fn
* const i960_cgen_print_handlers
[] =
263 i960_cgen_init_dis (od
)
269 #if ! CGEN_INT_INSN_P
271 /* Subroutine of extract_normal.
272 Ensure sufficient bytes are cached in EX_INFO.
273 OFFSET is the offset in bytes from the start of the insn of the value.
274 BYTES is the length of the needed value.
275 Returns 1 for success, 0 for failure. */
278 fill_cache (od
, ex_info
, offset
, bytes
, pc
)
280 CGEN_EXTRACT_INFO
*ex_info
;
284 /* It's doubtful that the middle part has already been fetched so
285 we don't optimize that case. kiss. */
287 disassemble_info
*info
= (disassemble_info
*) ex_info
->dis_info
;
289 /* First do a quick check. */
290 mask
= (1 << bytes
) - 1;
291 if (((ex_info
->valid
>> offset
) & mask
) == mask
)
294 /* Search for the first byte we need to read. */
295 for (mask
= 1 << offset
; bytes
> 0; --bytes
, ++offset
, mask
<<= 1)
296 if (! (mask
& ex_info
->valid
))
304 status
= (*info
->read_memory_func
)
305 (pc
, ex_info
->insn_bytes
+ offset
, bytes
, info
);
309 (*info
->memory_error_func
) (status
, pc
, info
);
313 ex_info
->valid
|= ((1 << bytes
) - 1) << offset
;
319 /* Subroutine of extract_normal. */
322 extract_1 (od
, ex_info
, start
, length
, word_length
, bufp
, pc
)
324 CGEN_EXTRACT_INFO
*ex_info
;
325 int start
,length
,word_length
;
329 unsigned long x
,mask
;
331 int big_p
= CGEN_OPCODE_INSN_ENDIAN (od
) == CGEN_ENDIAN_BIG
;
340 x
= bfd_getb16 (bufp
);
342 x
= bfd_getl16 (bufp
);
345 /* ??? This may need reworking as these cases don't necessarily
346 want the first byte and the last two bytes handled like this. */
348 x
= (bufp
[0] << 16) | bfd_getb16 (bufp
+ 1);
350 x
= bfd_getl16 (bufp
) | (bufp
[2] << 16);
354 x
= bfd_getb32 (bufp
);
356 x
= bfd_getl32 (bufp
);
362 /* Written this way to avoid undefined behaviour. */
363 mask
= (((1L << (length
- 1)) - 1) << 1) | 1;
364 if (CGEN_INSN_LSB0_P
)
365 shift
= (start
+ 1) - length
;
367 shift
= (word_length
- (start
+ length
));
368 return (x
>> shift
) & mask
;
371 #endif /* ! CGEN_INT_INSN_P */
373 /* Default extraction routine.
375 INSN_VALUE is the first CGEN_BASE_INSN_SIZE bits of the insn in host order,
376 or sometimes less for cases like the m32r where the base insn size is 32
377 but some insns are 16 bits.
378 ATTRS is a mask of the boolean attributes. We only need `UNSIGNED',
379 but for generality we take a bitmask of all of them.
380 WORD_OFFSET is the offset in bits from the start of the insn of the value.
381 WORD_LENGTH is the length of the word in bits in which the value resides.
382 START is the starting bit number in the word, architecture origin.
383 LENGTH is the length of VALUE in bits.
384 TOTAL_LENGTH is the total length of the insn in bits.
386 Returns 1 for success, 0 for failure. */
388 /* ??? The return code isn't properly used. wip. */
390 /* ??? This doesn't handle bfd_vma's. Create another function when
394 extract_normal (od
, ex_info
, insn_value
, attrs
, word_offset
, start
, length
,
395 word_length
, total_length
, pc
, valuep
)
397 CGEN_EXTRACT_INFO
*ex_info
;
398 CGEN_INSN_INT insn_value
;
400 unsigned int word_offset
, start
, length
, word_length
, total_length
;
406 /* If LENGTH is zero, this operand doesn't contribute to the value
407 so give it a standard value of zero. */
418 if (word_length
> 32)
421 /* For architectures with insns smaller than the insn-base-bitsize,
422 word_length may be too big. */
423 #if CGEN_MIN_INSN_BITSIZE < CGEN_BASE_INSN_BITSIZE
425 && word_length
> total_length
)
426 word_length
= total_length
;
429 /* Does the value reside in INSN_VALUE? */
431 if (word_offset
== 0)
433 /* Written this way to avoid undefined behaviour. */
434 CGEN_INSN_INT mask
= (((1L << (length
- 1)) - 1) << 1) | 1;
436 if (CGEN_INSN_LSB0_P
)
437 value
= insn_value
>> ((start
+ 1) - length
);
439 value
= insn_value
>> (word_length
- (start
+ length
));
442 if (! CGEN_BOOL_ATTR (attrs
, CGEN_OPERAND_UNSIGNED
)
443 && (value
& (1L << (length
- 1))))
447 #if ! CGEN_INT_INSN_P
451 unsigned char *bufp
= ex_info
->insn_bytes
+ word_offset
/ 8;
453 if (word_length
> 32)
456 if (fill_cache (od
, ex_info
, word_offset
/ 8, word_length
/ 8, pc
) == 0)
459 value
= extract_1 (od
, ex_info
, start
, length
, word_length
, bufp
, pc
);
462 #endif /* ! CGEN_INT_INSN_P */
469 /* Default print handler. */
472 print_normal (od
, dis_info
, value
, attrs
, pc
, length
)
480 disassemble_info
*info
= (disassemble_info
*) dis_info
;
482 #ifdef CGEN_PRINT_NORMAL
483 CGEN_PRINT_NORMAL (od
, info
, value
, attrs
, pc
, length
);
486 /* Print the operand as directed by the attributes. */
487 if (CGEN_BOOL_ATTR (attrs
, CGEN_OPERAND_SEM_ONLY
))
488 ; /* nothing to do */
489 else if (CGEN_BOOL_ATTR (attrs
, CGEN_OPERAND_UNSIGNED
))
490 (*info
->fprintf_func
) (info
->stream
, "0x%lx", value
);
492 (*info
->fprintf_func
) (info
->stream
, "%ld", value
);
495 /* Default address handler. */
498 print_address (od
, dis_info
, value
, attrs
, pc
, length
)
506 disassemble_info
*info
= (disassemble_info
*) dis_info
;
508 #ifdef CGEN_PRINT_ADDRESS
509 CGEN_PRINT_ADDRESS (od
, info
, value
, attrs
, pc
, length
);
512 /* Print the operand as directed by the attributes. */
513 if (CGEN_BOOL_ATTR (attrs
, CGEN_OPERAND_SEM_ONLY
))
514 ; /* nothing to do */
515 else if (CGEN_BOOL_ATTR (attrs
, CGEN_OPERAND_PCREL_ADDR
))
516 (*info
->print_address_func
) (value
, info
);
517 else if (CGEN_BOOL_ATTR (attrs
, CGEN_OPERAND_ABS_ADDR
))
518 (*info
->print_address_func
) (value
, info
);
519 else if (CGEN_BOOL_ATTR (attrs
, CGEN_OPERAND_UNSIGNED
))
520 (*info
->fprintf_func
) (info
->stream
, "0x%lx", (long) value
);
522 (*info
->fprintf_func
) (info
->stream
, "%ld", (long) value
);
525 /* Keyword print handler. */
528 print_keyword (od
, dis_info
, keyword_table
, value
, attrs
)
531 CGEN_KEYWORD
*keyword_table
;
535 disassemble_info
*info
= (disassemble_info
*) dis_info
;
536 const CGEN_KEYWORD_ENTRY
*ke
;
538 ke
= cgen_keyword_lookup_value (keyword_table
, value
);
540 (*info
->fprintf_func
) (info
->stream
, "%s", ke
->name
);
542 (*info
->fprintf_func
) (info
->stream
, "???");
545 /* Default insn extractor.
547 INSN_VALUE is the first CGEN_BASE_INSN_SIZE bytes, translated to host order.
548 The extracted fields are stored in FIELDS.
549 EX_INFO is used to handle reading variable length insns.
550 Return the length of the insn in bits, or 0 if no match,
551 or -1 if an error occurs fetching data (memory_error_func will have
555 extract_insn_normal (od
, insn
, ex_info
, insn_value
, fields
, pc
)
557 const CGEN_INSN
*insn
;
558 CGEN_EXTRACT_INFO
*ex_info
;
559 CGEN_INSN_INT insn_value
;
563 const CGEN_SYNTAX
*syntax
= CGEN_INSN_SYNTAX (insn
);
564 const unsigned char *syn
;
566 CGEN_FIELDS_BITSIZE (fields
) = CGEN_INSN_BITSIZE (insn
);
568 CGEN_INIT_EXTRACT (od
);
570 for (syn
= CGEN_SYNTAX_STRING (syntax
); *syn
; ++syn
)
574 if (CGEN_SYNTAX_CHAR_P (*syn
))
577 length
= i960_cgen_extract_operand (od
, CGEN_SYNTAX_FIELD (*syn
),
578 ex_info
, insn_value
, fields
, pc
);
583 /* We recognized and successfully extracted this insn. */
584 return CGEN_INSN_BITSIZE (insn
);
587 /* Default insn printer.
589 DIS_INFO is defined as `PTR' so the disassembler needn't know anything
590 about disassemble_info. */
593 print_insn_normal (od
, dis_info
, insn
, fields
, pc
, length
)
596 const CGEN_INSN
*insn
;
601 const CGEN_SYNTAX
*syntax
= CGEN_INSN_SYNTAX (insn
);
602 disassemble_info
*info
= (disassemble_info
*) dis_info
;
603 const unsigned char *syn
;
605 CGEN_INIT_PRINT (od
);
607 for (syn
= CGEN_SYNTAX_STRING (syntax
); *syn
; ++syn
)
609 if (CGEN_SYNTAX_MNEMONIC_P (*syn
))
611 (*info
->fprintf_func
) (info
->stream
, "%s", CGEN_INSN_MNEMONIC (insn
));
614 if (CGEN_SYNTAX_CHAR_P (*syn
))
616 (*info
->fprintf_func
) (info
->stream
, "%c", CGEN_SYNTAX_CHAR (*syn
));
620 /* We have an operand. */
621 i960_cgen_print_operand (od
, CGEN_SYNTAX_FIELD (*syn
), info
,
622 fields
, CGEN_INSN_ATTRS (insn
), pc
, length
);
626 /* Utility to print an insn.
627 BUF is the base part of the insn, target byte order, BUFLEN bytes long.
628 The result is the size of the insn in bytes or zero for an unknown insn
629 or -1 if an error occurs fetching data (memory_error_func will have
633 print_insn (od
, pc
, info
, buf
, buflen
)
636 disassemble_info
*info
;
640 unsigned long insn_value
;
641 const CGEN_INSN_LIST
*insn_list
;
642 CGEN_EXTRACT_INFO ex_info
;
644 ex_info
.dis_info
= info
;
645 ex_info
.valid
= (1 << CGEN_BASE_INSN_SIZE
) - 1;
646 ex_info
.insn_bytes
= buf
;
654 insn_value
= info
->endian
== BFD_ENDIAN_BIG
? bfd_getb16 (buf
) : bfd_getl16 (buf
);
657 insn_value
= info
->endian
== BFD_ENDIAN_BIG
? bfd_getb32 (buf
) : bfd_getl32 (buf
);
663 /* The instructions are stored in hash lists.
664 Pick the first one and keep trying until we find the right one. */
666 insn_list
= CGEN_DIS_LOOKUP_INSN (od
, buf
, insn_value
);
667 while (insn_list
!= NULL
)
669 const CGEN_INSN
*insn
= insn_list
->insn
;
673 #if 0 /* not needed as insn shouldn't be in hash lists if not supported */
674 /* Supported by this cpu? */
675 if (! i960_cgen_insn_supported (od
, insn
))
679 /* Basic bit mask must be correct. */
680 /* ??? May wish to allow target to defer this check until the extract
682 if ((insn_value
& CGEN_INSN_BASE_MASK (insn
))
683 == CGEN_INSN_BASE_VALUE (insn
))
685 /* Printing is handled in two passes. The first pass parses the
686 machine insn and extracts the fields. The second pass prints
689 length
= (*CGEN_EXTRACT_FN (insn
)) (od
, insn
, &ex_info
, insn_value
,
691 /* length < 0 -> error */
696 (*CGEN_PRINT_FN (insn
)) (od
, info
, insn
, &fields
, pc
, length
);
697 /* length is in bits, result is in bytes */
702 insn_list
= CGEN_DIS_NEXT_INSN (insn_list
);
708 /* Default value for CGEN_PRINT_INSN.
709 The result is the size of the insn in bytes or zero for an unknown insn
710 or -1 if an error occured fetching bytes. */
712 #ifndef CGEN_PRINT_INSN
713 #define CGEN_PRINT_INSN default_print_insn
717 default_print_insn (od
, pc
, info
)
720 disassemble_info
*info
;
722 char buf
[CGEN_MAX_INSN_SIZE
];
725 /* Read the base part of the insn. */
727 status
= (*info
->read_memory_func
) (pc
, buf
, CGEN_BASE_INSN_SIZE
, info
);
730 (*info
->memory_error_func
) (status
, pc
, info
);
734 return print_insn (od
, pc
, info
, buf
, CGEN_BASE_INSN_SIZE
);
738 Print one instruction from PC on INFO->STREAM.
739 Return the size of the instruction (in bytes). */
742 print_insn_i960 (pc
, info
)
744 disassemble_info
*info
;
747 static CGEN_OPCODE_DESC od
= 0;
748 int mach
= info
->mach
;
749 int big_p
= info
->endian
== BFD_ENDIAN_BIG
;
751 /* If we haven't initialized yet, initialize the opcode table. */
754 od
= i960_cgen_opcode_open (mach
,
757 : CGEN_ENDIAN_LITTLE
);
758 i960_cgen_init_dis (od
);
760 /* If we've switched cpu's, re-initialize. */
761 /* ??? Perhaps we should use BFD_ENDIAN. */
762 else if (mach
!= CGEN_OPCODE_MACH (od
)
763 || (CGEN_OPCODE_ENDIAN (od
)
764 != (big_p
? CGEN_ENDIAN_BIG
: CGEN_ENDIAN_LITTLE
)))
766 cgen_set_cpu (od
, mach
, big_p
? CGEN_ENDIAN_BIG
: CGEN_ENDIAN_LITTLE
);
769 /* We try to have as much common code as possible.
770 But at this point some targets need to take over. */
771 /* ??? Some targets may need a hook elsewhere. Try to avoid this,
772 but if not possible try to move this hook elsewhere rather than
774 length
= CGEN_PRINT_INSN (od
, pc
, info
);
780 (*info
->fprintf_func
) (info
->stream
, UNKNOWN_INSN_MSG
);
781 return CGEN_DEFAULT_INSN_SIZE
;