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