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