]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - opcodes/cgen-dis.in
* config/sh/tm-sh.h (BELIEVE_PCC_PROMOTION): Define, so that
[thirdparty/binutils-gdb.git] / opcodes / cgen-dis.in
CommitLineData
bfc10abe
DE
1/* Disassembler interface for targets using CGEN. -*- C -*-
2 CGEN: Cpu tools GENerator
3
1c8f439e 4THIS FILE IS USED TO GENERATE @prefix@-dis.c.
bfc10abe 5
1c8f439e 6Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc.
bfc10abe
DE
7
8This file is part of the GNU Binutils and GDB, the GNU debugger.
9
10This program is free software; you can redistribute it and/or modify
11it under the terms of the GNU General Public License as published by
12the Free Software Foundation; either version 2, or (at your option)
13any later version.
14
15This program is distributed in the hope that it will be useful,
16but WITHOUT ANY WARRANTY; without even the implied warranty of
17MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18GNU General Public License for more details.
19
20You should have received a copy of the GNU General Public License
1c8f439e
DE
21along with this program; if not, write to the Free Software Foundation, Inc.,
2259 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
bfc10abe
DE
23
24#include "sysdep.h"
25#include <stdio.h>
26#include "ansidecl.h"
27#include "dis-asm.h"
28#include "bfd.h"
833d2990 29#include "symcat.h"
1c8f439e
DE
30#include "@prefix@-opc.h"
31#include "opintl.h"
bfc10abe 32
1c8f439e
DE
33#undef INLINE
34#ifdef __GNUC__
35#define INLINE __inline__
36#else
37#define INLINE
bfc10abe
DE
38#endif
39
1c8f439e
DE
40/* Default text to print if an instruction isn't recognized. */
41#define UNKNOWN_INSN_MSG _("*unknown*")
42
5730d39d
DE
43/* Used by the ifield rtx function. */
44#define FLD(f) (fields->f)
45
1c8f439e 46static int extract_normal
5730d39d
DE
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 *));
1c8f439e
DE
50static void print_normal
51 PARAMS ((CGEN_OPCODE_DESC, PTR, long, unsigned int, bfd_vma, int));
52static void print_address
53 PARAMS ((CGEN_OPCODE_DESC, PTR, bfd_vma, unsigned int, bfd_vma, int));
54static void print_keyword
55 PARAMS ((CGEN_OPCODE_DESC, PTR, CGEN_KEYWORD *, long, unsigned int));
bfc10abe 56static int extract_insn_normal
1c8f439e 57 PARAMS ((CGEN_OPCODE_DESC, const CGEN_INSN *, CGEN_EXTRACT_INFO *,
5730d39d 58 CGEN_INSN_INT, CGEN_FIELDS *, bfd_vma));
bfc10abe 59static void print_insn_normal
1c8f439e
DE
60 PARAMS ((CGEN_OPCODE_DESC, PTR, const CGEN_INSN *, CGEN_FIELDS *,
61 bfd_vma, int));
62static int print_insn PARAMS ((CGEN_OPCODE_DESC, bfd_vma,
63 disassemble_info *, char *, int));
64static int default_print_insn
65 PARAMS ((CGEN_OPCODE_DESC, bfd_vma, disassemble_info *));
66\f
67/* -- disassembler routines inserted here */
bfc10abe 68\f
1c8f439e
DE
69#if ! CGEN_INT_INSN_P
70
5730d39d
DE
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
77static INLINE int
78fill_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
1c8f439e
DE
119/* Subroutine of extract_normal. */
120
121static INLINE long
5730d39d 122extract_1 (od, ex_info, start, length, word_length, bufp, pc)
1c8f439e 123 CGEN_OPCODE_DESC od;
5730d39d 124 CGEN_EXTRACT_INFO *ex_info;
1c8f439e
DE
125 int start,length,word_length;
126 unsigned char *bufp;
5730d39d 127 bfd_vma pc;
1c8f439e
DE
128{
129 unsigned long x,mask;
130 int shift;
131 int big_p = CGEN_OPCODE_INSN_ENDIAN (od) == CGEN_ENDIAN_BIG;
132
1c8f439e
DE
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)
5730d39d 148 x = (bufp[0] << 16) | bfd_getb16 (bufp + 1);
1c8f439e 149 else
5730d39d 150 x = bfd_getl16 (bufp) | (bufp[2] << 16);
1c8f439e
DE
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)
5730d39d 165 shift = (start + 1) - length;
1c8f439e
DE
166 else
167 shift = (word_length - (start + length));
168 return (x >> shift) & mask;
169}
170
171#endif /* ! CGEN_INT_INSN_P */
172
bfc10abe
DE
173/* Default extraction routine.
174
5730d39d
DE
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. */
bfc10abe 189
1c8f439e
DE
190/* ??? This doesn't handle bfd_vma's. Create another function when
191 necessary. */
192
bfc10abe 193static int
5730d39d
DE
194extract_normal (od, ex_info, insn_value, attrs, word_offset, start, length,
195 word_length, total_length, pc, valuep)
1c8f439e
DE
196 CGEN_OPCODE_DESC od;
197 CGEN_EXTRACT_INFO *ex_info;
5730d39d 198 CGEN_INSN_INT insn_value;
bfc10abe 199 unsigned int attrs;
5730d39d
DE
200 unsigned int word_offset, start, length, word_length, total_length;
201 bfd_vma pc;
bfc10abe
DE
202 long *valuep;
203{
5730d39d 204 CGEN_INSN_INT value;
1c8f439e
DE
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
5730d39d
DE
214 if (CGEN_INT_INSN_P
215 && word_offset != 0)
216 abort ();
1c8f439e 217
5730d39d
DE
218 if (word_length > 32)
219 abort ();
1c8f439e 220
5730d39d
DE
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
bfc10abe 228
5730d39d 229 /* Does the value reside in INSN_VALUE? */
bfc10abe 230
5730d39d
DE
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;
1c8f439e 235
5730d39d
DE
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 }
1c8f439e 246
5730d39d 247#if ! CGEN_INT_INSN_P
1c8f439e 248
bfc10abe 249 else
1c8f439e 250 {
5730d39d 251 unsigned char *bufp = ex_info->insn_bytes + word_offset / 8;
1c8f439e 252
5730d39d 253 if (word_length > 32)
1c8f439e
DE
254 abort ();
255
5730d39d
DE
256 if (fill_cache (od, ex_info, word_offset / 8, word_length / 8, pc) == 0)
257 return 0;
1c8f439e 258
5730d39d 259 value = extract_1 (od, ex_info, start, length, word_length, bufp, pc);
1c8f439e
DE
260 }
261
262#endif /* ! CGEN_INT_INSN_P */
bfc10abe
DE
263
264 *valuep = value;
833d2990 265
bfc10abe
DE
266 return 1;
267}
268
269/* Default print handler. */
270
271static void
1c8f439e
DE
272print_normal (od, dis_info, value, attrs, pc, length)
273 CGEN_OPCODE_DESC od;
ab0bd049 274 PTR dis_info;
bfc10abe
DE
275 long value;
276 unsigned int attrs;
1c8f439e 277 bfd_vma pc;
bfc10abe
DE
278 int length;
279{
1c8f439e
DE
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
bfc10abe
DE
285
286 /* Print the operand as directed by the attributes. */
1c8f439e
DE
287 if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_SEM_ONLY))
288 ; /* nothing to do */
289 else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_UNSIGNED))
bfc10abe
DE
290 (*info->fprintf_func) (info->stream, "0x%lx", value);
291 else
292 (*info->fprintf_func) (info->stream, "%ld", value);
293}
294
1c8f439e
DE
295/* Default address handler. */
296
297static void
298print_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
bfc10abe
DE
325/* Keyword print handler. */
326
327static void
1c8f439e
DE
328print_keyword (od, dis_info, keyword_table, value, attrs)
329 CGEN_OPCODE_DESC od;
ab0bd049 330 PTR dis_info;
bfc10abe
DE
331 CGEN_KEYWORD *keyword_table;
332 long value;
1c8f439e 333 unsigned int attrs;
bfc10abe 334{
1c8f439e 335 disassemble_info *info = (disassemble_info *) dis_info;
bfc10abe
DE
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
bfc10abe
DE
345/* Default insn extractor.
346
1c8f439e
DE
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). */
bfc10abe
DE
353
354static int
1c8f439e
DE
355extract_insn_normal (od, insn, ex_info, insn_value, fields, pc)
356 CGEN_OPCODE_DESC od;
bfc10abe 357 const CGEN_INSN *insn;
1c8f439e 358 CGEN_EXTRACT_INFO *ex_info;
5730d39d 359 CGEN_INSN_INT insn_value;
bfc10abe 360 CGEN_FIELDS *fields;
1c8f439e 361 bfd_vma pc;
bfc10abe
DE
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
1c8f439e 368 CGEN_INIT_EXTRACT (od);
bfc10abe
DE
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
1c8f439e
DE
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;
bfc10abe
DE
381 }
382
383 /* We recognized and successfully extracted this insn. */
384 return CGEN_INSN_BITSIZE (insn);
385}
386
387/* Default insn printer.
388
ab0bd049 389 DIS_INFO is defined as `PTR' so the disassembler needn't know anything
1c8f439e 390 about disassemble_info. */
bfc10abe
DE
391
392static void
1c8f439e
DE
393print_insn_normal (od, dis_info, insn, fields, pc, length)
394 CGEN_OPCODE_DESC od;
ab0bd049 395 PTR dis_info;
bfc10abe
DE
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);
1c8f439e 402 disassemble_info *info = (disassemble_info *) dis_info;
bfc10abe
DE
403 const unsigned char *syn;
404
1c8f439e 405 CGEN_INIT_PRINT (od);
bfc10abe
DE
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. */
1c8f439e
DE
421 @arch@_cgen_print_operand (od, CGEN_SYNTAX_FIELD (*syn), info,
422 fields, CGEN_INSN_ATTRS (insn), pc, length);
bfc10abe
DE
423 }
424}
425\f
1c8f439e
DE
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). */
bfc10abe
DE
431
432static int
1c8f439e
DE
433print_insn (od, pc, info, buf, buflen)
434 CGEN_OPCODE_DESC od;
bfc10abe
DE
435 bfd_vma pc;
436 disassemble_info *info;
437 char *buf;
438 int buflen;
439{
bfc10abe
DE
440 unsigned long insn_value;
441 const CGEN_INSN_LIST *insn_list;
1c8f439e
DE
442 CGEN_EXTRACT_INFO ex_info;
443
444 ex_info.dis_info = info;
445 ex_info.valid = (1 << CGEN_BASE_INSN_SIZE) - 1;
5730d39d 446 ex_info.insn_bytes = buf;
bfc10abe
DE
447
448 switch (buflen)
449 {
1c8f439e 450 case 1:
bfc10abe
DE
451 insn_value = buf[0];
452 break;
1c8f439e 453 case 2:
bfc10abe
DE
454 insn_value = info->endian == BFD_ENDIAN_BIG ? bfd_getb16 (buf) : bfd_getl16 (buf);
455 break;
1c8f439e 456 case 4:
bfc10abe
DE
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
1c8f439e 466 insn_list = CGEN_DIS_LOOKUP_INSN (od, buf, insn_value);
bfc10abe
DE
467 while (insn_list != NULL)
468 {
469 const CGEN_INSN *insn = insn_list->insn;
bfc10abe
DE
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? */
1c8f439e 475 if (! @arch@_cgen_insn_supported (od, insn))
bfc10abe
DE
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. */
5730d39d
DE
482 if ((insn_value & CGEN_INSN_BASE_MASK (insn))
483 == CGEN_INSN_BASE_VALUE (insn))
bfc10abe
DE
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
1c8f439e
DE
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;
bfc10abe
DE
494 if (length > 0)
495 {
1c8f439e 496 (*CGEN_PRINT_FN (insn)) (od, info, insn, &fields, pc, length);
bfc10abe
DE
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
1c8f439e
DE
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
516static int
517default_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
bfc10abe
DE
537/* Main entry point.
538 Print one instruction from PC on INFO->STREAM.
539 Return the size of the instruction (in bytes). */
540
541int
542print_insn_@arch@ (pc, info)
543 bfd_vma pc;
544 disassemble_info *info;
545{
1c8f439e
DE
546 int length;
547 static CGEN_OPCODE_DESC od = 0;
bfc10abe
DE
548 int mach = info->mach;
549 int big_p = info->endian == BFD_ENDIAN_BIG;
550
1c8f439e
DE
551 /* If we haven't initialized yet, initialize the opcode table. */
552 if (! od)
bfc10abe 553 {
1c8f439e
DE
554 od = @arch@_cgen_opcode_open (mach,
555 big_p ?
556 CGEN_ENDIAN_BIG
557 : CGEN_ENDIAN_LITTLE);
558 @arch@_cgen_init_dis (od);
bfc10abe 559 }
1c8f439e
DE
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)))
bfc10abe 565 {
1c8f439e 566 cgen_set_cpu (od, mach, big_p ? CGEN_ENDIAN_BIG : CGEN_ENDIAN_LITTLE);
bfc10abe
DE
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. */
1c8f439e
DE
574 length = CGEN_PRINT_INSN (od, pc, info);
575 if (length > 0)
bfc10abe 576 return length;
1c8f439e
DE
577 if (length < 0)
578 return -1;
bfc10abe
DE
579
580 (*info->fprintf_func) (info->stream, UNKNOWN_INSN_MSG);
581 return CGEN_DEFAULT_INSN_SIZE;
582}