]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - opcodes/fr30-dis.c
Mon Nov 16 19:21:48 1998 Dave Brolley <brolley@cygnus.com>
[thirdparty/binutils-gdb.git] / opcodes / fr30-dis.c
1 /* Disassembler interface for targets using CGEN. -*- C -*-
2 CGEN: Cpu tools GENerator
3
4 THIS FILE IS USED TO GENERATE fr30-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 "fr30-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 static int extract_normal
44 PARAMS ((CGEN_OPCODE_DESC, CGEN_EXTRACT_INFO *, CGEN_INSN_BYTES,
45 unsigned int, int, int, int, long *));
46 static void print_normal
47 PARAMS ((CGEN_OPCODE_DESC, PTR, long, unsigned int, bfd_vma, int));
48 static void print_address
49 PARAMS ((CGEN_OPCODE_DESC, PTR, bfd_vma, unsigned int, bfd_vma, int));
50 static void print_keyword
51 PARAMS ((CGEN_OPCODE_DESC, PTR, CGEN_KEYWORD *, long, unsigned int));
52 static int extract_insn_normal
53 PARAMS ((CGEN_OPCODE_DESC, const CGEN_INSN *, CGEN_EXTRACT_INFO *,
54 unsigned long, CGEN_FIELDS *, bfd_vma));
55 static void print_insn_normal
56 PARAMS ((CGEN_OPCODE_DESC, PTR, const CGEN_INSN *, CGEN_FIELDS *,
57 bfd_vma, int));
58 static int print_insn PARAMS ((CGEN_OPCODE_DESC, bfd_vma,
59 disassemble_info *, char *, int));
60 static int default_print_insn
61 PARAMS ((CGEN_OPCODE_DESC, bfd_vma, disassemble_info *));
62 \f
63 /* -- disassembler routines inserted here */
64
65 /* Main entry point for operand extraction.
66
67 This function is basically just a big switch statement. Earlier versions
68 used tables to look up the function to use, but
69 - if the table contains both assembler and disassembler functions then
70 the disassembler contains much of the assembler and vice-versa,
71 - there's a lot of inlining possibilities as things grow,
72 - using a switch statement avoids the function call overhead.
73
74 This function could be moved into `print_insn_normal', but keeping it
75 separate makes clear the interface between `print_insn_normal' and each of
76 the handlers.
77 */
78
79 int
80 fr30_cgen_extract_operand (od, opindex, ex_info, insn_value, fields, pc)
81 CGEN_OPCODE_DESC od;
82 int opindex;
83 CGEN_EXTRACT_INFO *ex_info;
84 CGEN_INSN_BYTES insn_value;
85 CGEN_FIELDS * fields;
86 bfd_vma pc;
87 {
88 int length;
89
90 switch (opindex)
91 {
92 case FR30_OPERAND_RI :
93 length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_UNSIGNED), 12, 4, CGEN_FIELDS_BITSIZE (fields), & fields->f_Ri);
94 break;
95 case FR30_OPERAND_RJ :
96 length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_UNSIGNED), 8, 4, CGEN_FIELDS_BITSIZE (fields), & fields->f_Rj);
97 break;
98 case FR30_OPERAND_RS1 :
99 length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_UNSIGNED), 8, 4, CGEN_FIELDS_BITSIZE (fields), & fields->f_Rs1);
100 break;
101 case FR30_OPERAND_RS2 :
102 length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_UNSIGNED), 12, 4, CGEN_FIELDS_BITSIZE (fields), & fields->f_Rs2);
103 break;
104 case FR30_OPERAND_R13 :
105 length = extract_normal (od, ex_info, insn_value, 0, 0, 0, CGEN_FIELDS_BITSIZE (fields), & fields->f_nil);
106 break;
107 case FR30_OPERAND_R14 :
108 length = extract_normal (od, ex_info, insn_value, 0, 0, 0, CGEN_FIELDS_BITSIZE (fields), & fields->f_nil);
109 break;
110 case FR30_OPERAND_R15 :
111 length = extract_normal (od, ex_info, insn_value, 0, 0, 0, CGEN_FIELDS_BITSIZE (fields), & fields->f_nil);
112 break;
113 case FR30_OPERAND_PS :
114 length = extract_normal (od, ex_info, insn_value, 0, 0, 0, CGEN_FIELDS_BITSIZE (fields), & fields->f_nil);
115 break;
116 case FR30_OPERAND_U4 :
117 length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_UNSIGNED), 8, 4, CGEN_FIELDS_BITSIZE (fields), & fields->f_u4);
118 break;
119 case FR30_OPERAND_M4 :
120 {
121 long value;
122 length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_UNSIGNED), 8, 4, CGEN_FIELDS_BITSIZE (fields), & value);
123 value = ((value) | ((! (15))));
124 fields->f_m4 = value;
125 }
126 break;
127 case FR30_OPERAND_U8 :
128 length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_UNSIGNED), 8, 8, CGEN_FIELDS_BITSIZE (fields), & fields->f_u8);
129 break;
130 case FR30_OPERAND_I8 :
131 length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_UNSIGNED), 4, 8, CGEN_FIELDS_BITSIZE (fields), & fields->f_i8);
132 break;
133 case FR30_OPERAND_UDISP6 :
134 {
135 long value;
136 length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_UNSIGNED), 8, 4, CGEN_FIELDS_BITSIZE (fields), & value);
137 value = ((value) << (2));
138 fields->f_udisp6 = value;
139 }
140 break;
141 case FR30_OPERAND_DISP8 :
142 length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_SIGNED), 4, 8, CGEN_FIELDS_BITSIZE (fields), & fields->f_disp8);
143 break;
144 case FR30_OPERAND_DISP9 :
145 {
146 long value;
147 length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_SIGNED), 4, 8, CGEN_FIELDS_BITSIZE (fields), & value);
148 value = ((value) << (1));
149 fields->f_disp9 = value;
150 }
151 break;
152 case FR30_OPERAND_DISP10 :
153 {
154 long value;
155 length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_SIGNED), 4, 8, CGEN_FIELDS_BITSIZE (fields), & value);
156 value = ((value) << (2));
157 fields->f_disp10 = value;
158 }
159 break;
160 case FR30_OPERAND_S10 :
161 {
162 long value;
163 length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_SIGNED), 8, 8, CGEN_FIELDS_BITSIZE (fields), & value);
164 value = ((value) << (2));
165 fields->f_s10 = value;
166 }
167 break;
168 case FR30_OPERAND_U10 :
169 {
170 long value;
171 length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_UNSIGNED), 8, 8, CGEN_FIELDS_BITSIZE (fields), & value);
172 value = ((value) << (2));
173 fields->f_u10 = value;
174 }
175 break;
176 case FR30_OPERAND_DIR8 :
177 length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_UNSIGNED), 8, 8, CGEN_FIELDS_BITSIZE (fields), & fields->f_dir8);
178 break;
179 case FR30_OPERAND_DIR9 :
180 {
181 long value;
182 length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_UNSIGNED), 8, 8, CGEN_FIELDS_BITSIZE (fields), & value);
183 value = ((value) << (1));
184 fields->f_dir9 = value;
185 }
186 break;
187 case FR30_OPERAND_DIR10 :
188 {
189 long value;
190 length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_UNSIGNED), 8, 8, CGEN_FIELDS_BITSIZE (fields), & value);
191 value = ((value) << (2));
192 fields->f_dir10 = value;
193 }
194 break;
195 case FR30_OPERAND_LABEL9 :
196 {
197 long value;
198 length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_SIGNED), 8, 8, CGEN_FIELDS_BITSIZE (fields), & value);
199 value = ((((value) << (1))) + (((pc) & (-2))));
200 fields->f_rel9 = value;
201 }
202 break;
203 case FR30_OPERAND_LABEL12 :
204 {
205 long value;
206 length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_SIGNED), 5, 11, CGEN_FIELDS_BITSIZE (fields), & value);
207 value = ((((value) << (1))) + (((pc) & (-2))));
208 fields->f_rel12 = value;
209 }
210 break;
211 case FR30_OPERAND_CC :
212 length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_UNSIGNED), 4, 4, CGEN_FIELDS_BITSIZE (fields), & fields->f_cc);
213 break;
214
215 default :
216 /* xgettext:c-format */
217 fprintf (stderr, _("Unrecognized field %d while decoding insn.\n"),
218 opindex);
219 abort ();
220 }
221
222 return length;
223 }
224
225 /* Main entry point for printing operands.
226
227 This function is basically just a big switch statement. Earlier versions
228 used tables to look up the function to use, but
229 - if the table contains both assembler and disassembler functions then
230 the disassembler contains much of the assembler and vice-versa,
231 - there's a lot of inlining possibilities as things grow,
232 - using a switch statement avoids the function call overhead.
233
234 This function could be moved into `print_insn_normal', but keeping it
235 separate makes clear the interface between `print_insn_normal' and each of
236 the handlers.
237 */
238
239 void
240 fr30_cgen_print_operand (od, opindex, info, fields, attrs, pc, length)
241 CGEN_OPCODE_DESC od;
242 int opindex;
243 disassemble_info * info;
244 CGEN_FIELDS * fields;
245 void const * attrs;
246 bfd_vma pc;
247 int length;
248 {
249 switch (opindex)
250 {
251 case FR30_OPERAND_RI :
252 print_keyword (od, info, & fr30_cgen_opval_h_gr, fields->f_Ri, 0|(1<<CGEN_OPERAND_UNSIGNED));
253 break;
254 case FR30_OPERAND_RJ :
255 print_keyword (od, info, & fr30_cgen_opval_h_gr, fields->f_Rj, 0|(1<<CGEN_OPERAND_UNSIGNED));
256 break;
257 case FR30_OPERAND_RS1 :
258 print_keyword (od, info, & fr30_cgen_opval_h_dr, fields->f_Rs1, 0|(1<<CGEN_OPERAND_UNSIGNED));
259 break;
260 case FR30_OPERAND_RS2 :
261 print_keyword (od, info, & fr30_cgen_opval_h_dr, fields->f_Rs2, 0|(1<<CGEN_OPERAND_UNSIGNED));
262 break;
263 case FR30_OPERAND_R13 :
264 print_keyword (od, info, & fr30_cgen_opval_h_r13, fields->f_nil, 0);
265 break;
266 case FR30_OPERAND_R14 :
267 print_keyword (od, info, & fr30_cgen_opval_h_r14, fields->f_nil, 0);
268 break;
269 case FR30_OPERAND_R15 :
270 print_keyword (od, info, & fr30_cgen_opval_h_r15, fields->f_nil, 0);
271 break;
272 case FR30_OPERAND_PS :
273 print_keyword (od, info, & fr30_cgen_opval_h_ps, fields->f_nil, 0);
274 break;
275 case FR30_OPERAND_U4 :
276 print_normal (od, info, fields->f_u4, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_UNSIGNED), pc, length);
277 break;
278 case FR30_OPERAND_M4 :
279 print_normal (od, info, fields->f_m4, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_UNSIGNED), pc, length);
280 break;
281 case FR30_OPERAND_U8 :
282 print_normal (od, info, fields->f_u8, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_UNSIGNED), pc, length);
283 break;
284 case FR30_OPERAND_I8 :
285 print_normal (od, info, fields->f_i8, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_UNSIGNED), pc, length);
286 break;
287 case FR30_OPERAND_UDISP6 :
288 print_normal (od, info, fields->f_udisp6, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_UNSIGNED), pc, length);
289 break;
290 case FR30_OPERAND_DISP8 :
291 print_normal (od, info, fields->f_disp8, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_SIGNED), pc, length);
292 break;
293 case FR30_OPERAND_DISP9 :
294 print_normal (od, info, fields->f_disp9, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_SIGNED), pc, length);
295 break;
296 case FR30_OPERAND_DISP10 :
297 print_normal (od, info, fields->f_disp10, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_SIGNED), pc, length);
298 break;
299 case FR30_OPERAND_S10 :
300 print_normal (od, info, fields->f_s10, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_SIGNED), pc, length);
301 break;
302 case FR30_OPERAND_U10 :
303 print_normal (od, info, fields->f_u10, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_UNSIGNED), pc, length);
304 break;
305 case FR30_OPERAND_DIR8 :
306 print_normal (od, info, fields->f_dir8, 0|(1<<CGEN_OPERAND_UNSIGNED), pc, length);
307 break;
308 case FR30_OPERAND_DIR9 :
309 print_normal (od, info, fields->f_dir9, 0|(1<<CGEN_OPERAND_UNSIGNED), pc, length);
310 break;
311 case FR30_OPERAND_DIR10 :
312 print_normal (od, info, fields->f_dir10, 0|(1<<CGEN_OPERAND_UNSIGNED), pc, length);
313 break;
314 case FR30_OPERAND_LABEL9 :
315 print_normal (od, info, fields->f_rel9, 0|(1<<CGEN_OPERAND_SIGNED), pc, length);
316 break;
317 case FR30_OPERAND_LABEL12 :
318 print_normal (od, info, fields->f_rel12, 0|(1<<CGEN_OPERAND_SIGNED), pc, length);
319 break;
320 case FR30_OPERAND_CC :
321 print_normal (od, info, fields->f_cc, 0|(1<<CGEN_OPERAND_UNSIGNED), pc, length);
322 break;
323
324 default :
325 /* xgettext:c-format */
326 fprintf (stderr, _("Unrecognized field %d while printing insn.\n"),
327 opindex);
328 abort ();
329 }
330 }
331
332 cgen_extract_fn * const fr30_cgen_extract_handlers[] =
333 {
334 0, /* default */
335 extract_insn_normal,
336 };
337
338 cgen_print_fn * const fr30_cgen_print_handlers[] =
339 {
340 0, /* default */
341 print_insn_normal,
342 };
343
344
345 void
346 fr30_cgen_init_dis (od)
347 CGEN_OPCODE_DESC od;
348 {
349 }
350
351 \f
352 #if ! CGEN_INT_INSN_P
353
354 /* Subroutine of extract_normal. */
355
356 static INLINE long
357 extract_1 (od, ex_info, start, length, word_length, bufp)
358 CGEN_OPCODE_DESC od;
359 CGEN_EXTRACT_INFO *info;
360 int start,length,word_length;
361 unsigned char *bufp;
362 {
363 unsigned long x,mask;
364 int shift;
365 int big_p = CGEN_OPCODE_INSN_ENDIAN (od) == CGEN_ENDIAN_BIG;
366
367 /* FIXME: Need to use ex_info to ensure bytes have been fetched. */
368
369 switch (word_length)
370 {
371 case 8:
372 x = *bufp;
373 break;
374 case 16:
375 if (big_p)
376 x = bfd_getb16 (bufp);
377 else
378 x = bfd_getl16 (bufp);
379 break;
380 case 24:
381 /* ??? This may need reworking as these cases don't necessarily
382 want the first byte and the last two bytes handled like this. */
383 if (big_p)
384 x = (bfd_getb8 (bufp) << 16) | bfd_getb16 (bufp + 1);
385 else
386 x = bfd_getl16 (bufp) | (bfd_getb8 (bufp + 2) << 16);
387 break;
388 case 32:
389 if (big_p)
390 x = bfd_getb32 (bufp);
391 else
392 x = bfd_getl32 (bufp);
393 break;
394 default :
395 abort ();
396 }
397
398 /* Written this way to avoid undefined behaviour. */
399 mask = (((1L << (length - 1)) - 1) << 1) | 1;
400 if (CGEN_INSN_LSB0_P)
401 shift = start;
402 else
403 shift = (word_length - (start + length));
404 return (x >> shift) & mask;
405 }
406
407 #endif /* ! CGEN_INT_INSN_P */
408
409 /* Default extraction routine.
410
411 ATTRS is a mask of the boolean attributes. We only need `unsigned',
412 but for generality we take a bitmask of all of them. */
413
414 /* ??? This doesn't handle bfd_vma's. Create another function when
415 necessary. */
416
417 static int
418 extract_normal (od, ex_info, insn_value, attrs, start, length, total_length, valuep)
419 CGEN_OPCODE_DESC od;
420 CGEN_EXTRACT_INFO *ex_info;
421 CGEN_INSN_BYTES insn_value;
422 unsigned int attrs;
423 int start, length, total_length;
424 long *valuep;
425 {
426 unsigned long value;
427
428 /* If LENGTH is zero, this operand doesn't contribute to the value
429 so give it a standard value of zero. */
430 if (length == 0)
431 {
432 *valuep = 0;
433 return 1;
434 }
435
436 #if CGEN_INT_INSN_P
437
438 {
439 /* Written this way to avoid undefined behaviour. */
440 unsigned long mask = (((1L << (length - 1)) - 1) << 1) | 1;
441
442 if (CGEN_INSN_LSB0_P)
443 value = insn_value >> start;
444 else
445 value = insn_value >> (total_length - (start + length));
446 value &= mask;
447 /* sign extend? */
448 if (! (attrs & CGEN_ATTR_MASK (CGEN_OPERAND_UNSIGNED))
449 && (value & (1L << (length - 1))))
450 value |= ~mask;
451 }
452
453 #else
454
455 /* The hard case is probably too slow for the normal cases.
456 It's certainly more difficult to understand than the normal case.
457 Thus this is split into two. Keep it that way. The hard case is defined
458 to be when a field straddles a (loosely defined) word boundary
459 (??? which may require target specific help to determine). */
460
461 #if 0 /*wip*/
462
463 #define HARD_CASE_P 0 /* FIXME:wip */
464
465 if (HARD_CASE_P)
466 {
467 }
468 #endif
469 else
470 {
471 unsigned char *bufp = (unsigned char *) insn_value;
472
473 if (length > 32)
474 abort ();
475
476 /* Adjust start,total_length,bufp to point to the pseudo-word that holds
477 the value. For example in a 48 bit insn where the value to insert
478 (say an immediate value) is the last 16 bits then word_length here
479 would be 16. To handle a 24 bit insn with an 18 bit immediate,
480 extract_1 handles 24 bits (using a combination of bfd_get8,16). */
481
482 if (total_length > 32)
483 {
484 int needed_width = start % 8 + length;
485 int fetch_length = (needed_width <= 8 ? 8
486 : needed_width <= 16 ? 16
487 : 32);
488
489 if (CGEN_INSN_LSB0_P)
490 {
491 if (CGEN_INSN_WORD_ENDIAN (od) == CGEN_ENDIAN_BIG)
492 {
493 abort (); /* wip */
494 }
495 else
496 {
497 int offset = start & ~7;
498
499 bufp += offset / 8;
500 start -= offset;
501 total_length -= offset;
502 }
503 }
504 else
505 {
506 if (CGEN_INSN_WORD_ENDIAN (od) == CGEN_ENDIAN_BIG)
507 {
508 int offset = start & ~7;
509
510 bufp += offset / 8;
511 start -= offset;
512 total_length -= offset;
513 }
514 else
515 {
516 abort (); /* wip */
517 }
518 }
519 }
520
521 /* FIXME: which bytes are being extracted have been lost. */
522 value = extract_1 (od, ex_info, start, length, total_length, bufp);
523 }
524
525 #endif /* ! CGEN_INT_INSN_P */
526
527 *valuep = value;
528
529 /* FIXME: for now */
530 return 1;
531 }
532
533 /* Default print handler. */
534
535 static void
536 print_normal (od, dis_info, value, attrs, pc, length)
537 CGEN_OPCODE_DESC od;
538 PTR dis_info;
539 long value;
540 unsigned int attrs;
541 bfd_vma pc;
542 int length;
543 {
544 disassemble_info *info = (disassemble_info *) dis_info;
545
546 #ifdef CGEN_PRINT_NORMAL
547 CGEN_PRINT_NORMAL (od, info, value, attrs, pc, length);
548 #endif
549
550 /* Print the operand as directed by the attributes. */
551 if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_SEM_ONLY))
552 ; /* nothing to do */
553 else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_UNSIGNED))
554 (*info->fprintf_func) (info->stream, "0x%lx", value);
555 else
556 (*info->fprintf_func) (info->stream, "%ld", value);
557 }
558
559 /* Default address handler. */
560
561 static void
562 print_address (od, dis_info, value, attrs, pc, length)
563 CGEN_OPCODE_DESC od;
564 PTR dis_info;
565 bfd_vma value;
566 unsigned int attrs;
567 bfd_vma pc;
568 int length;
569 {
570 disassemble_info *info = (disassemble_info *) dis_info;
571
572 #ifdef CGEN_PRINT_ADDRESS
573 CGEN_PRINT_ADDRESS (od, info, value, attrs, pc, length);
574 #endif
575
576 /* Print the operand as directed by the attributes. */
577 if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_SEM_ONLY))
578 ; /* nothing to do */
579 else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_PCREL_ADDR))
580 (*info->print_address_func) (value, info);
581 else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_ABS_ADDR))
582 (*info->print_address_func) (value, info);
583 else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_UNSIGNED))
584 (*info->fprintf_func) (info->stream, "0x%lx", (long) value);
585 else
586 (*info->fprintf_func) (info->stream, "%ld", (long) value);
587 }
588
589 /* Keyword print handler. */
590
591 static void
592 print_keyword (od, dis_info, keyword_table, value, attrs)
593 CGEN_OPCODE_DESC od;
594 PTR dis_info;
595 CGEN_KEYWORD *keyword_table;
596 long value;
597 unsigned int attrs;
598 {
599 disassemble_info *info = (disassemble_info *) dis_info;
600 const CGEN_KEYWORD_ENTRY *ke;
601
602 ke = cgen_keyword_lookup_value (keyword_table, value);
603 if (ke != NULL)
604 (*info->fprintf_func) (info->stream, "%s", ke->name);
605 else
606 (*info->fprintf_func) (info->stream, "???");
607 }
608 \f
609 /* Default insn extractor.
610
611 INSN_VALUE is the first CGEN_BASE_INSN_SIZE bytes, translated to host order.
612 The extracted fields are stored in FIELDS.
613 EX_INFO is used to handle reading variable length insns.
614 Return the length of the insn in bits, or 0 if no match,
615 or -1 if an error occurs fetching data (memory_error_func will have
616 been called). */
617
618 static int
619 extract_insn_normal (od, insn, ex_info, insn_value, fields, pc)
620 CGEN_OPCODE_DESC od;
621 const CGEN_INSN *insn;
622 CGEN_EXTRACT_INFO *ex_info;
623 unsigned long insn_value;
624 CGEN_FIELDS *fields;
625 bfd_vma pc;
626 {
627 const CGEN_SYNTAX *syntax = CGEN_INSN_SYNTAX (insn);
628 const unsigned char *syn;
629
630 CGEN_FIELDS_BITSIZE (fields) = CGEN_INSN_BITSIZE (insn);
631
632 CGEN_INIT_EXTRACT (od);
633
634 for (syn = CGEN_SYNTAX_STRING (syntax); *syn; ++syn)
635 {
636 int length;
637
638 if (CGEN_SYNTAX_CHAR_P (*syn))
639 continue;
640
641 length = fr30_cgen_extract_operand (od, CGEN_SYNTAX_FIELD (*syn),
642 ex_info, insn_value, fields, pc);
643 if (length <= 0)
644 return length;
645 }
646
647 /* We recognized and successfully extracted this insn. */
648 return CGEN_INSN_BITSIZE (insn);
649 }
650
651 /* Default insn printer.
652
653 DIS_INFO is defined as `PTR' so the disassembler needn't know anything
654 about disassemble_info. */
655
656 static void
657 print_insn_normal (od, dis_info, insn, fields, pc, length)
658 CGEN_OPCODE_DESC od;
659 PTR dis_info;
660 const CGEN_INSN *insn;
661 CGEN_FIELDS *fields;
662 bfd_vma pc;
663 int length;
664 {
665 const CGEN_SYNTAX *syntax = CGEN_INSN_SYNTAX (insn);
666 disassemble_info *info = (disassemble_info *) dis_info;
667 const unsigned char *syn;
668
669 CGEN_INIT_PRINT (od);
670
671 for (syn = CGEN_SYNTAX_STRING (syntax); *syn; ++syn)
672 {
673 if (CGEN_SYNTAX_MNEMONIC_P (*syn))
674 {
675 (*info->fprintf_func) (info->stream, "%s", CGEN_INSN_MNEMONIC (insn));
676 continue;
677 }
678 if (CGEN_SYNTAX_CHAR_P (*syn))
679 {
680 (*info->fprintf_func) (info->stream, "%c", CGEN_SYNTAX_CHAR (*syn));
681 continue;
682 }
683
684 /* We have an operand. */
685 fr30_cgen_print_operand (od, CGEN_SYNTAX_FIELD (*syn), info,
686 fields, CGEN_INSN_ATTRS (insn), pc, length);
687 }
688 }
689 \f
690 /* Utility to print an insn.
691 BUF is the base part of the insn, target byte order, BUFLEN bytes long.
692 The result is the size of the insn in bytes or zero for an unknown insn
693 or -1 if an error occurs fetching data (memory_error_func will have
694 been called). */
695
696 static int
697 print_insn (od, pc, info, buf, buflen)
698 CGEN_OPCODE_DESC od;
699 bfd_vma pc;
700 disassemble_info *info;
701 char *buf;
702 int buflen;
703 {
704 unsigned long insn_value;
705 const CGEN_INSN_LIST *insn_list;
706 CGEN_EXTRACT_INFO ex_info;
707
708 ex_info.dis_info = info;
709 ex_info.valid = (1 << CGEN_BASE_INSN_SIZE) - 1;
710 ex_info.bytes = buf;
711
712 switch (buflen)
713 {
714 case 1:
715 insn_value = buf[0];
716 break;
717 case 2:
718 insn_value = info->endian == BFD_ENDIAN_BIG ? bfd_getb16 (buf) : bfd_getl16 (buf);
719 break;
720 case 4:
721 insn_value = info->endian == BFD_ENDIAN_BIG ? bfd_getb32 (buf) : bfd_getl32 (buf);
722 break;
723 default:
724 abort ();
725 }
726
727 /* The instructions are stored in hash lists.
728 Pick the first one and keep trying until we find the right one. */
729
730 insn_list = CGEN_DIS_LOOKUP_INSN (od, buf, insn_value);
731 while (insn_list != NULL)
732 {
733 const CGEN_INSN *insn = insn_list->insn;
734 CGEN_FIELDS fields;
735 int length;
736
737 #if 0 /* not needed as insn shouldn't be in hash lists if not supported */
738 /* Supported by this cpu? */
739 if (! fr30_cgen_insn_supported (od, insn))
740 continue;
741 #endif
742
743 /* Basic bit mask must be correct. */
744 /* ??? May wish to allow target to defer this check until the extract
745 handler. */
746 if ((insn_value & CGEN_INSN_MASK (insn)) == CGEN_INSN_VALUE (insn))
747 {
748 /* Printing is handled in two passes. The first pass parses the
749 machine insn and extracts the fields. The second pass prints
750 them. */
751
752 length = (*CGEN_EXTRACT_FN (insn)) (od, insn, &ex_info, insn_value,
753 &fields, pc);
754 /* length < 0 -> error */
755 if (length < 0)
756 return length;
757 if (length > 0)
758 {
759 (*CGEN_PRINT_FN (insn)) (od, info, insn, &fields, pc, length);
760 /* length is in bits, result is in bytes */
761 return length / 8;
762 }
763 }
764
765 insn_list = CGEN_DIS_NEXT_INSN (insn_list);
766 }
767
768 return 0;
769 }
770
771 /* Default value for CGEN_PRINT_INSN.
772 The result is the size of the insn in bytes or zero for an unknown insn
773 or -1 if an error occured fetching bytes. */
774
775 #ifndef CGEN_PRINT_INSN
776 #define CGEN_PRINT_INSN default_print_insn
777 #endif
778
779 static int
780 default_print_insn (od, pc, info)
781 CGEN_OPCODE_DESC od;
782 bfd_vma pc;
783 disassemble_info *info;
784 {
785 char buf[CGEN_MAX_INSN_SIZE];
786 int status;
787
788 /* Read the base part of the insn. */
789
790 status = (*info->read_memory_func) (pc, buf, CGEN_BASE_INSN_SIZE, info);
791 if (status != 0)
792 {
793 (*info->memory_error_func) (status, pc, info);
794 return -1;
795 }
796
797 return print_insn (od, pc, info, buf, CGEN_BASE_INSN_SIZE);
798 }
799
800 /* Main entry point.
801 Print one instruction from PC on INFO->STREAM.
802 Return the size of the instruction (in bytes). */
803
804 int
805 print_insn_fr30 (pc, info)
806 bfd_vma pc;
807 disassemble_info *info;
808 {
809 int length;
810 static CGEN_OPCODE_DESC od = 0;
811 int mach = info->mach;
812 int big_p = info->endian == BFD_ENDIAN_BIG;
813
814 /* If we haven't initialized yet, initialize the opcode table. */
815 if (! od)
816 {
817 od = fr30_cgen_opcode_open (mach,
818 big_p ?
819 CGEN_ENDIAN_BIG
820 : CGEN_ENDIAN_LITTLE);
821 fr30_cgen_init_dis (od);
822 }
823 /* If we've switched cpu's, re-initialize. */
824 /* ??? Perhaps we should use BFD_ENDIAN. */
825 else if (mach != CGEN_OPCODE_MACH (od)
826 || (CGEN_OPCODE_ENDIAN (od)
827 != (big_p ? CGEN_ENDIAN_BIG : CGEN_ENDIAN_LITTLE)))
828 {
829 cgen_set_cpu (od, mach, big_p ? CGEN_ENDIAN_BIG : CGEN_ENDIAN_LITTLE);
830 }
831
832 /* We try to have as much common code as possible.
833 But at this point some targets need to take over. */
834 /* ??? Some targets may need a hook elsewhere. Try to avoid this,
835 but if not possible try to move this hook elsewhere rather than
836 have two hooks. */
837 length = CGEN_PRINT_INSN (od, pc, info);
838 if (length > 0)
839 return length;
840 if (length < 0)
841 return -1;
842
843 (*info->fprintf_func) (info->stream, UNKNOWN_INSN_MSG);
844 return CGEN_DEFAULT_INSN_SIZE;
845 }