]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - opcodes/cgen-dis.in
* config/sh/tm-sh.h (BELIEVE_PCC_PROMOTION): Define, so that
[thirdparty/binutils-gdb.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 }