* cgen-opc.in: New file.
[deliverable/binutils-gdb.git] / opcodes / m32r-dis.c
1 /* Disassembler interface for targets using CGEN. -*- C -*-
2 CGEN: Cpu tools GENerator
3
4 This file is used to generate m32r-dis.c.
5
6 Copyright (C) 1996, 1997 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
22 Foundation, Inc., 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 "m32r-opc.h"
30
31 /* ??? The layout of this stuff is still work in progress.
32 For speed in assembly/disassembly, we use inline functions. That of course
33 will only work for GCC. When this stuff is finished, we can decide whether
34 to keep the inline functions (and only get the performance increase when
35 compiled with GCC), or switch to macros, or use something else.
36 */
37
38 /* Default text to print if an instruction isn't recognized. */
39 #define UNKNOWN_INSN_MSG "*unknown*"
40
41 /* FIXME: Machine generate. */
42 #ifndef CGEN_PCREL_OFFSET
43 #define CGEN_PCREL_OFFSET 0
44 #endif
45
46 static int print_insn PARAMS ((bfd_vma, disassemble_info *, char *, int));
47
48 static int extract_insn_normal
49 PARAMS ((const CGEN_INSN *, void *, cgen_insn_t, CGEN_FIELDS *));
50 static void print_insn_normal
51 PARAMS ((void *, const CGEN_INSN *, CGEN_FIELDS *, bfd_vma, int));
52 \f
53 /* Default extraction routine.
54
55 ATTRS is a mask of the boolean attributes. We only need `unsigned',
56 but for generality we take a bitmask of all of them. */
57
58 static int
59 extract_normal (buf_ctrl, insn_value, attrs, start, length, shift, total_length, valuep)
60 PTR buf_ctrl;
61 cgen_insn_t insn_value;
62 unsigned int attrs;
63 int start, length, shift, total_length;
64 long *valuep;
65 {
66 long value;
67
68 #ifdef CGEN_INT_INSN
69 #if 0
70 value = ((insn_value >> (CGEN_BASE_INSN_BITSIZE - (start + length)))
71 & ((1 << length) - 1));
72 #else
73 value = ((insn_value >> (total_length - (start + length)))
74 & ((1 << length) - 1));
75 #endif
76 if (! (attrs & CGEN_ATTR_MASK (CGEN_OPERAND_UNSIGNED))
77 && (value & (1 << (length - 1))))
78 value -= 1 << length;
79 #else
80 /* FIXME: unfinished */
81 #endif
82
83 /* This is backwards as we undo the effects of insert_normal. */
84 if (shift < 0)
85 value >>= -shift;
86 else
87 value <<= shift;
88
89 *valuep = value;
90 return 1;
91 }
92
93 /* Default print handler. */
94
95 static void
96 print_normal (dis_info, value, attrs, pc, length)
97 PTR dis_info;
98 long value;
99 unsigned int attrs;
100 unsigned long pc; /* FIXME: should be bfd_vma */
101 int length;
102 {
103 disassemble_info *info = dis_info;
104
105 /* Print the operand as directed by the attributes. */
106 if (attrs & CGEN_ATTR_MASK (CGEN_OPERAND_FAKE))
107 ; /* nothing to do (??? at least not yet) */
108 else if (attrs & CGEN_ATTR_MASK (CGEN_OPERAND_PCREL_ADDR))
109 (*info->print_address_func) (pc + CGEN_PCREL_OFFSET + value, info);
110 /* ??? Not all cases of this are currently caught. */
111 else if (attrs & CGEN_ATTR_MASK (CGEN_OPERAND_ABS_ADDR))
112 /* FIXME: Why & 0xffffffff? */
113 (*info->print_address_func) ((bfd_vma) value & 0xffffffff, info);
114 else if (attrs & CGEN_ATTR_MASK (CGEN_OPERAND_UNSIGNED))
115 (*info->fprintf_func) (info->stream, "0x%lx", value);
116 else
117 (*info->fprintf_func) (info->stream, "%ld", value);
118 }
119
120 /* Keyword print handler. */
121
122 static void
123 print_keyword (dis_info, keyword_table, value, attrs)
124 PTR dis_info;
125 CGEN_KEYWORD *keyword_table;
126 long value;
127 CGEN_ATTR *attrs;
128 {
129 disassemble_info *info = dis_info;
130 const CGEN_KEYWORD_ENTRY *ke;
131
132 ke = cgen_keyword_lookup_value (keyword_table, value);
133 if (ke != NULL)
134 (*info->fprintf_func) (info->stream, "%s", ke->name);
135 else
136 (*info->fprintf_func) (info->stream, "???");
137 }
138 \f
139 /* -- disassembler routines inserted here */
140 /* -- dis.c */
141
142 #undef CGEN_PRINT_INSN
143 #define CGEN_PRINT_INSN my_print_insn
144
145 static int
146 my_print_insn (pc, info, buf, buflen)
147 bfd_vma pc;
148 disassemble_info *info;
149 char *buf;
150 int buflen;
151 {
152 /* 32 bit insn? */
153 if ((pc & 3) == 0 && (buf[0] & 0x80) != 0)
154 return print_insn (pc, info, buf, buflen);
155
156 /* Print the first insn. */
157 if ((pc & 3) == 0)
158 {
159 if (print_insn (pc, info, buf, 16) == 0)
160 (*info->fprintf_func) (info->stream, UNKNOWN_INSN_MSG);
161 buf += 2;
162 }
163
164 if (buf[0] & 0x80)
165 {
166 /* Parallel. */
167 (*info->fprintf_func) (info->stream, " || ");
168 buf[0] &= 0x7f;
169 }
170 else
171 (*info->fprintf_func) (info->stream, " -> ");
172
173 /* The "& 3" is to ensure the branch address is computed correctly
174 [if it is a branch]. */
175 if (print_insn (pc & ~ (bfd_vma) 3, info, buf, 16) == 0)
176 (*info->fprintf_func) (info->stream, UNKNOWN_INSN_MSG);
177
178 return (pc & 3) ? 2 : 4;
179 }
180
181 /* -- */
182
183 /* Main entry point for operand extraction.
184
185 This function is basically just a big switch statement. Earlier versions
186 used tables to look up the function to use, but
187 - if the table contains both assembler and disassembler functions then
188 the disassembler contains much of the assembler and vice-versa,
189 - there's a lot of inlining possibilities as things grow,
190 - using a switch statement avoids the function call overhead.
191
192 This function could be moved into `print_insn_normal', but keeping it
193 separate makes clear the interface between `print_insn_normal' and each of
194 the handlers.
195 */
196
197 CGEN_INLINE int
198 m32r_cgen_extract_operand (opindex, buf_ctrl, insn_value, fields)
199 int opindex;
200 PTR buf_ctrl;
201 cgen_insn_t insn_value;
202 CGEN_FIELDS * fields;
203 {
204 int length;
205
206 switch (opindex)
207 {
208 case M32R_OPERAND_SR :
209 length = extract_normal (NULL /*FIXME*/, insn_value, 0|(1<<CGEN_OPERAND_UNSIGNED), 12, 4, 0, CGEN_FIELDS_BITSIZE (fields), & fields->f_r2);
210 break;
211 case M32R_OPERAND_DR :
212 length = extract_normal (NULL /*FIXME*/, insn_value, 0|(1<<CGEN_OPERAND_UNSIGNED), 4, 4, 0, CGEN_FIELDS_BITSIZE (fields), & fields->f_r1);
213 break;
214 case M32R_OPERAND_SRC1 :
215 length = extract_normal (NULL /*FIXME*/, insn_value, 0|(1<<CGEN_OPERAND_UNSIGNED), 4, 4, 0, CGEN_FIELDS_BITSIZE (fields), & fields->f_r1);
216 break;
217 case M32R_OPERAND_SRC2 :
218 length = extract_normal (NULL /*FIXME*/, insn_value, 0|(1<<CGEN_OPERAND_UNSIGNED), 12, 4, 0, CGEN_FIELDS_BITSIZE (fields), & fields->f_r2);
219 break;
220 case M32R_OPERAND_SCR :
221 length = extract_normal (NULL /*FIXME*/, insn_value, 0|(1<<CGEN_OPERAND_UNSIGNED), 12, 4, 0, CGEN_FIELDS_BITSIZE (fields), & fields->f_r2);
222 break;
223 case M32R_OPERAND_DCR :
224 length = extract_normal (NULL /*FIXME*/, insn_value, 0|(1<<CGEN_OPERAND_UNSIGNED), 4, 4, 0, CGEN_FIELDS_BITSIZE (fields), & fields->f_r1);
225 break;
226 case M32R_OPERAND_SIMM8 :
227 length = extract_normal (NULL /*FIXME*/, insn_value, 0, 8, 8, 0, CGEN_FIELDS_BITSIZE (fields), & fields->f_simm8);
228 break;
229 case M32R_OPERAND_SIMM16 :
230 length = extract_normal (NULL /*FIXME*/, insn_value, 0, 16, 16, 0, CGEN_FIELDS_BITSIZE (fields), & fields->f_simm16);
231 break;
232 case M32R_OPERAND_UIMM4 :
233 length = extract_normal (NULL /*FIXME*/, insn_value, 0|(1<<CGEN_OPERAND_UNSIGNED), 12, 4, 0, CGEN_FIELDS_BITSIZE (fields), & fields->f_uimm4);
234 break;
235 case M32R_OPERAND_UIMM5 :
236 length = extract_normal (NULL /*FIXME*/, insn_value, 0|(1<<CGEN_OPERAND_UNSIGNED), 11, 5, 0, CGEN_FIELDS_BITSIZE (fields), & fields->f_uimm5);
237 break;
238 case M32R_OPERAND_UIMM16 :
239 length = extract_normal (NULL /*FIXME*/, insn_value, 0|(1<<CGEN_OPERAND_UNSIGNED), 16, 16, 0, CGEN_FIELDS_BITSIZE (fields), & fields->f_uimm16);
240 break;
241 /* start-sanitize-m32rx */
242 case M32R_OPERAND_IMM1 :
243 length = extract_normal (NULL /*FIXME*/, insn_value, 0|(1<<CGEN_OPERAND_UNSIGNED), 15, 1, 0, CGEN_FIELDS_BITSIZE (fields), & fields->f_imm1);
244 break;
245 /* end-sanitize-m32rx */
246 /* start-sanitize-m32rx */
247 case M32R_OPERAND_ACCD :
248 length = extract_normal (NULL /*FIXME*/, insn_value, 0|(1<<CGEN_OPERAND_UNSIGNED), 4, 2, 0, CGEN_FIELDS_BITSIZE (fields), & fields->f_accd);
249 break;
250 /* end-sanitize-m32rx */
251 /* start-sanitize-m32rx */
252 case M32R_OPERAND_ACCS :
253 length = extract_normal (NULL /*FIXME*/, insn_value, 0|(1<<CGEN_OPERAND_UNSIGNED), 12, 2, 0, CGEN_FIELDS_BITSIZE (fields), & fields->f_accs);
254 break;
255 /* end-sanitize-m32rx */
256 /* start-sanitize-m32rx */
257 case M32R_OPERAND_ACC :
258 length = extract_normal (NULL /*FIXME*/, insn_value, 0|(1<<CGEN_OPERAND_UNSIGNED), 8, 1, 0, CGEN_FIELDS_BITSIZE (fields), & fields->f_acc);
259 break;
260 /* end-sanitize-m32rx */
261 case M32R_OPERAND_HI16 :
262 length = extract_normal (NULL /*FIXME*/, insn_value, 0|(1<<CGEN_OPERAND_SIGN_OPT)|(1<<CGEN_OPERAND_UNSIGNED), 16, 16, 0, CGEN_FIELDS_BITSIZE (fields), & fields->f_hi16);
263 break;
264 case M32R_OPERAND_SLO16 :
265 length = extract_normal (NULL /*FIXME*/, insn_value, 0, 16, 16, 0, CGEN_FIELDS_BITSIZE (fields), & fields->f_simm16);
266 break;
267 case M32R_OPERAND_ULO16 :
268 length = extract_normal (NULL /*FIXME*/, insn_value, 0|(1<<CGEN_OPERAND_UNSIGNED), 16, 16, 0, CGEN_FIELDS_BITSIZE (fields), & fields->f_uimm16);
269 break;
270 case M32R_OPERAND_UIMM24 :
271 length = extract_normal (NULL /*FIXME*/, insn_value, 0|(1<<CGEN_OPERAND_RELOC)|(1<<CGEN_OPERAND_ABS_ADDR)|(1<<CGEN_OPERAND_UNSIGNED), 8, 24, 0, CGEN_FIELDS_BITSIZE (fields), & fields->f_uimm24);
272 break;
273 case M32R_OPERAND_DISP8 :
274 length = extract_normal (NULL /*FIXME*/, insn_value, 0|(1<<CGEN_OPERAND_RELAX)|(1<<CGEN_OPERAND_RELOC)|(1<<CGEN_OPERAND_PCREL_ADDR), 8, 8, 2, CGEN_FIELDS_BITSIZE (fields), & fields->f_disp8);
275 break;
276 case M32R_OPERAND_DISP16 :
277 length = extract_normal (NULL /*FIXME*/, insn_value, 0|(1<<CGEN_OPERAND_RELOC)|(1<<CGEN_OPERAND_PCREL_ADDR), 16, 16, 2, CGEN_FIELDS_BITSIZE (fields), & fields->f_disp16);
278 break;
279 case M32R_OPERAND_DISP24 :
280 length = extract_normal (NULL /*FIXME*/, insn_value, 0|(1<<CGEN_OPERAND_RELAX)|(1<<CGEN_OPERAND_RELOC)|(1<<CGEN_OPERAND_PCREL_ADDR), 8, 24, 2, CGEN_FIELDS_BITSIZE (fields), & fields->f_disp24);
281 break;
282
283 default :
284 fprintf (stderr, "Unrecognized field %d while decoding insn.\n",
285 opindex);
286 abort ();
287 }
288
289 return length;
290 }
291
292 /* Main entry point for printing operands.
293
294 This function is basically just a big switch statement. Earlier versions
295 used tables to look up the function to use, but
296 - if the table contains both assembler and disassembler functions then
297 the disassembler contains much of the assembler and vice-versa,
298 - there's a lot of inlining possibilities as things grow,
299 - using a switch statement avoids the function call overhead.
300
301 This function could be moved into `print_insn_normal', but keeping it
302 separate makes clear the interface between `print_insn_normal' and each of
303 the handlers.
304 */
305
306 CGEN_INLINE void
307 m32r_cgen_print_operand (opindex, info, fields, attrs, pc, length)
308 int opindex;
309 disassemble_info * info;
310 CGEN_FIELDS * fields;
311 void const * attrs;
312 bfd_vma pc;
313 int length;
314 {
315 switch (opindex)
316 {
317 case M32R_OPERAND_SR :
318 print_keyword (info, & m32r_cgen_opval_h_gr, fields->f_r2, 0|(1<<CGEN_OPERAND_UNSIGNED));
319 break;
320 case M32R_OPERAND_DR :
321 print_keyword (info, & m32r_cgen_opval_h_gr, fields->f_r1, 0|(1<<CGEN_OPERAND_UNSIGNED));
322 break;
323 case M32R_OPERAND_SRC1 :
324 print_keyword (info, & m32r_cgen_opval_h_gr, fields->f_r1, 0|(1<<CGEN_OPERAND_UNSIGNED));
325 break;
326 case M32R_OPERAND_SRC2 :
327 print_keyword (info, & m32r_cgen_opval_h_gr, fields->f_r2, 0|(1<<CGEN_OPERAND_UNSIGNED));
328 break;
329 case M32R_OPERAND_SCR :
330 print_keyword (info, & m32r_cgen_opval_h_cr, fields->f_r2, 0|(1<<CGEN_OPERAND_UNSIGNED));
331 break;
332 case M32R_OPERAND_DCR :
333 print_keyword (info, & m32r_cgen_opval_h_cr, fields->f_r1, 0|(1<<CGEN_OPERAND_UNSIGNED));
334 break;
335 case M32R_OPERAND_SIMM8 :
336 print_normal (info, fields->f_simm8, 0, pc, length);
337 break;
338 case M32R_OPERAND_SIMM16 :
339 print_normal (info, fields->f_simm16, 0, pc, length);
340 break;
341 case M32R_OPERAND_UIMM4 :
342 print_normal (info, fields->f_uimm4, 0|(1<<CGEN_OPERAND_UNSIGNED), pc, length);
343 break;
344 case M32R_OPERAND_UIMM5 :
345 print_normal (info, fields->f_uimm5, 0|(1<<CGEN_OPERAND_UNSIGNED), pc, length);
346 break;
347 case M32R_OPERAND_UIMM16 :
348 print_normal (info, fields->f_uimm16, 0|(1<<CGEN_OPERAND_UNSIGNED), pc, length);
349 break;
350 /* start-sanitize-m32rx */
351 case M32R_OPERAND_IMM1 :
352 print_normal (info, fields->f_imm1, 0|(1<<CGEN_OPERAND_UNSIGNED), pc, length);
353 break;
354 /* end-sanitize-m32rx */
355 /* start-sanitize-m32rx */
356 case M32R_OPERAND_ACCD :
357 print_keyword (info, & m32r_cgen_opval_h_accums, fields->f_accd, 0|(1<<CGEN_OPERAND_UNSIGNED));
358 break;
359 /* end-sanitize-m32rx */
360 /* start-sanitize-m32rx */
361 case M32R_OPERAND_ACCS :
362 print_keyword (info, & m32r_cgen_opval_h_accums, fields->f_accs, 0|(1<<CGEN_OPERAND_UNSIGNED));
363 break;
364 /* end-sanitize-m32rx */
365 /* start-sanitize-m32rx */
366 case M32R_OPERAND_ACC :
367 print_keyword (info, & m32r_cgen_opval_h_accums, fields->f_acc, 0|(1<<CGEN_OPERAND_UNSIGNED));
368 break;
369 /* end-sanitize-m32rx */
370 case M32R_OPERAND_HI16 :
371 print_normal (info, fields->f_hi16, 0|(1<<CGEN_OPERAND_SIGN_OPT)|(1<<CGEN_OPERAND_UNSIGNED), pc, length);
372 break;
373 case M32R_OPERAND_SLO16 :
374 print_normal (info, fields->f_simm16, 0, pc, length);
375 break;
376 case M32R_OPERAND_ULO16 :
377 print_normal (info, fields->f_uimm16, 0|(1<<CGEN_OPERAND_UNSIGNED), pc, length);
378 break;
379 case M32R_OPERAND_UIMM24 :
380 print_normal (info, fields->f_uimm24, 0|(1<<CGEN_OPERAND_RELOC)|(1<<CGEN_OPERAND_ABS_ADDR)|(1<<CGEN_OPERAND_UNSIGNED), pc, length);
381 break;
382 case M32R_OPERAND_DISP8 :
383 print_normal (info, fields->f_disp8, 0|(1<<CGEN_OPERAND_RELAX)|(1<<CGEN_OPERAND_RELOC)|(1<<CGEN_OPERAND_PCREL_ADDR), pc, length);
384 break;
385 case M32R_OPERAND_DISP16 :
386 print_normal (info, fields->f_disp16, 0|(1<<CGEN_OPERAND_RELOC)|(1<<CGEN_OPERAND_PCREL_ADDR), pc, length);
387 break;
388 case M32R_OPERAND_DISP24 :
389 print_normal (info, fields->f_disp24, 0|(1<<CGEN_OPERAND_RELAX)|(1<<CGEN_OPERAND_RELOC)|(1<<CGEN_OPERAND_PCREL_ADDR), pc, length);
390 break;
391
392 default :
393 fprintf (stderr, "Unrecognized field %d while printing insn.\n",
394 opindex);
395 abort ();
396 }
397 }
398
399 cgen_extract_fn * m32r_cgen_extract_handlers[] =
400 {
401 0, /* default */
402 extract_insn_normal,
403 };
404
405 cgen_print_fn * m32r_cgen_print_handlers[] =
406 {
407 0, /* default */
408 print_insn_normal,
409 };
410
411
412 void
413 m32r_cgen_init_dis (mach, endian)
414 int mach;
415 enum cgen_endian endian;
416 {
417 m32r_cgen_init_tables (mach);
418 cgen_set_cpu (& m32r_cgen_opcode_data, mach, endian);
419 cgen_dis_init ();
420 }
421
422 \f
423 /* Default insn extractor.
424
425 The extracted fields are stored in DIS_FLDS.
426 BUF_CTRL is used to handle reading variable length insns (FIXME: not done).
427 Return the length of the insn in bits, or 0 if no match. */
428
429 static int
430 extract_insn_normal (insn, buf_ctrl, insn_value, fields)
431 const CGEN_INSN *insn;
432 PTR buf_ctrl;
433 cgen_insn_t insn_value;
434 CGEN_FIELDS *fields;
435 {
436 const CGEN_SYNTAX *syntax = CGEN_INSN_SYNTAX (insn);
437 const unsigned char *syn;
438
439 CGEN_FIELDS_BITSIZE (fields) = CGEN_INSN_BITSIZE (insn);
440
441 CGEN_INIT_EXTRACT ();
442
443 for (syn = CGEN_SYNTAX_STRING (syntax); *syn; ++syn)
444 {
445 int length;
446
447 if (CGEN_SYNTAX_CHAR_P (*syn))
448 continue;
449
450 length = m32r_cgen_extract_operand (CGEN_SYNTAX_FIELD (*syn),
451 buf_ctrl, insn_value, fields);
452 if (length == 0)
453 return 0;
454 }
455
456 /* We recognized and successfully extracted this insn. */
457 return CGEN_INSN_BITSIZE (insn);
458 }
459
460 /* Default insn printer.
461
462 DIS_INFO is defined as `PTR' so the disassembler needn't know anything
463 about disassemble_info.
464 */
465
466 static void
467 print_insn_normal (dis_info, insn, fields, pc, length)
468 PTR dis_info;
469 const CGEN_INSN *insn;
470 CGEN_FIELDS *fields;
471 bfd_vma pc;
472 int length;
473 {
474 const CGEN_SYNTAX *syntax = CGEN_INSN_SYNTAX (insn);
475 disassemble_info *info = dis_info;
476 const unsigned char *syn;
477
478 CGEN_INIT_PRINT ();
479
480 for (syn = CGEN_SYNTAX_STRING (syntax); *syn; ++syn)
481 {
482 if (CGEN_SYNTAX_MNEMONIC_P (*syn))
483 {
484 (*info->fprintf_func) (info->stream, "%s", CGEN_INSN_MNEMONIC (insn));
485 continue;
486 }
487 if (CGEN_SYNTAX_CHAR_P (*syn))
488 {
489 (*info->fprintf_func) (info->stream, "%c", CGEN_SYNTAX_CHAR (*syn));
490 continue;
491 }
492
493 /* We have an operand. */
494 m32r_cgen_print_operand (CGEN_SYNTAX_FIELD (*syn), info,
495 fields, CGEN_INSN_ATTRS (insn), pc, length);
496 }
497 }
498 \f
499 /* Default value for CGEN_PRINT_INSN.
500 Given BUFLEN bits (target byte order) read into BUF, look up the
501 insn in the instruction table and disassemble it.
502
503 The result is the size of the insn in bytes. */
504
505 #ifndef CGEN_PRINT_INSN
506 #define CGEN_PRINT_INSN print_insn
507 #endif
508
509 static int
510 print_insn (pc, info, buf, buflen)
511 bfd_vma pc;
512 disassemble_info *info;
513 char *buf;
514 int buflen;
515 {
516 unsigned long insn_value;
517 const CGEN_INSN_LIST *insn_list;
518
519 switch (buflen)
520 {
521 case 8:
522 insn_value = buf[0];
523 break;
524 case 16:
525 insn_value = info->endian == BFD_ENDIAN_BIG ? bfd_getb16 (buf) : bfd_getl16 (buf);
526 break;
527 case 32:
528 insn_value = info->endian == BFD_ENDIAN_BIG ? bfd_getb32 (buf) : bfd_getl32 (buf);
529 break;
530 default:
531 abort ();
532 }
533
534 /* The instructions are stored in hash lists.
535 Pick the first one and keep trying until we find the right one. */
536
537 insn_list = CGEN_DIS_LOOKUP_INSN (buf, insn_value);
538 while (insn_list != NULL)
539 {
540 const CGEN_INSN *insn = insn_list->insn;
541 CGEN_FIELDS fields;
542 int length;
543
544 #if 0 /* not needed as insn shouldn't be in hash lists if not supported */
545 /* Supported by this cpu? */
546 if (! m32r_cgen_insn_supported (insn))
547 continue;
548 #endif
549
550 /* Basic bit mask must be correct. */
551 /* ??? May wish to allow target to defer this check until the extract
552 handler. */
553 if ((insn_value & CGEN_INSN_MASK (insn)) == CGEN_INSN_VALUE (insn))
554 {
555 /* Printing is handled in two passes. The first pass parses the
556 machine insn and extracts the fields. The second pass prints
557 them. */
558
559 length = (*CGEN_EXTRACT_FN (insn)) (insn, NULL, insn_value, &fields);
560 if (length > 0)
561 {
562 (*CGEN_PRINT_FN (insn)) (info, insn, &fields, pc, length);
563 /* length is in bits, result is in bytes */
564 return length / 8;
565 }
566 }
567
568 insn_list = CGEN_DIS_NEXT_INSN (insn_list);
569 }
570
571 return 0;
572 }
573
574 /* Main entry point.
575 Print one instruction from PC on INFO->STREAM.
576 Return the size of the instruction (in bytes). */
577
578 int
579 print_insn_m32r (pc, info)
580 bfd_vma pc;
581 disassemble_info *info;
582 {
583 char buffer[CGEN_MAX_INSN_SIZE];
584 int status, length;
585 static int initialized = 0;
586 static int current_mach = 0;
587 static int current_big_p = 0;
588 int mach = info->mach;
589 int big_p = info->endian == BFD_ENDIAN_BIG;
590
591 /* If we haven't initialized yet, or if we've switched cpu's, initialize. */
592 if (!initialized || mach != current_mach || big_p != current_big_p)
593 {
594 initialized = 1;
595 current_mach = mach;
596 current_big_p = big_p;
597 m32r_cgen_init_dis (mach, big_p ? CGEN_ENDIAN_BIG : CGEN_ENDIAN_LITTLE);
598 }
599
600 /* Read enough of the insn so we can look it up in the hash lists. */
601
602 status = (*info->read_memory_func) (pc, buffer, CGEN_BASE_INSN_SIZE, info);
603 if (status != 0)
604 {
605 (*info->memory_error_func) (status, pc, info);
606 return -1;
607 }
608
609 /* We try to have as much common code as possible.
610 But at this point some targets need to take over. */
611 /* ??? Some targets may need a hook elsewhere. Try to avoid this,
612 but if not possible try to move this hook elsewhere rather than
613 have two hooks. */
614 length = CGEN_PRINT_INSN (pc, info, buffer, CGEN_BASE_INSN_BITSIZE);
615 if (length)
616 return length;
617
618 (*info->fprintf_func) (info->stream, UNKNOWN_INSN_MSG);
619 return CGEN_DEFAULT_INSN_SIZE;
620 }
This page took 0.043434 seconds and 5 git commands to generate.