[cgen]
[deliverable/binutils-gdb.git] / opcodes / mep-dis.c
1 /* Disassembler interface for targets using CGEN. -*- C -*-
2 CGEN: Cpu tools GENerator
3
4 THIS FILE IS MACHINE GENERATED WITH CGEN.
5 - the resultant file is machine generated, cgen-dis.in isn't
6
7 Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2005, 2007,
8 2008 Free Software Foundation, Inc.
9
10 This file is part of libopcodes.
11
12 This library is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 3, or (at your option)
15 any later version.
16
17 It is distributed in the hope that it will be useful, but WITHOUT
18 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
19 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
20 License for more details.
21
22 You should have received a copy of the GNU General Public License
23 along with this program; if not, write to the Free Software Foundation, Inc.,
24 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */
25
26 /* ??? Eventually more and more of this stuff can go to cpu-independent files.
27 Keep that in mind. */
28
29 #include "sysdep.h"
30 #include <stdio.h>
31 #include "ansidecl.h"
32 #include "dis-asm.h"
33 #include "bfd.h"
34 #include "symcat.h"
35 #include "libiberty.h"
36 #include "mep-desc.h"
37 #include "mep-opc.h"
38 #include "opintl.h"
39
40 /* Default text to print if an instruction isn't recognized. */
41 #define UNKNOWN_INSN_MSG _("*unknown*")
42
43 static void print_normal
44 (CGEN_CPU_DESC, void *, long, unsigned int, bfd_vma, int);
45 static void print_address
46 (CGEN_CPU_DESC, void *, bfd_vma, unsigned int, bfd_vma, int) ATTRIBUTE_UNUSED;
47 static void print_keyword
48 (CGEN_CPU_DESC, void *, CGEN_KEYWORD *, long, unsigned int) ATTRIBUTE_UNUSED;
49 static void print_insn_normal
50 (CGEN_CPU_DESC, void *, const CGEN_INSN *, CGEN_FIELDS *, bfd_vma, int);
51 static int print_insn
52 (CGEN_CPU_DESC, bfd_vma, disassemble_info *, bfd_byte *, unsigned);
53 static int default_print_insn
54 (CGEN_CPU_DESC, bfd_vma, disassemble_info *) ATTRIBUTE_UNUSED;
55 static int read_insn
56 (CGEN_CPU_DESC, bfd_vma, disassemble_info *, bfd_byte *, int, CGEN_EXTRACT_INFO *,
57 unsigned long *);
58 \f
59 /* -- disassembler routines inserted here. */
60
61 /* -- dis.c */
62
63 #include "elf/mep.h"
64 #include "elf-bfd.h"
65
66 #define CGEN_VALIDATE_INSN_SUPPORTED
67
68 static void print_tpreg (CGEN_CPU_DESC, PTR, CGEN_KEYWORD *, long, unsigned int);
69 static void print_spreg (CGEN_CPU_DESC, PTR, CGEN_KEYWORD *, long, unsigned int);
70
71 static void
72 print_tpreg (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, PTR dis_info,
73 CGEN_KEYWORD *table ATTRIBUTE_UNUSED, long val ATTRIBUTE_UNUSED,
74 unsigned int flags ATTRIBUTE_UNUSED)
75 {
76 disassemble_info *info = (disassemble_info *) dis_info;
77
78 (*info->fprintf_func) (info->stream, "$tp");
79 }
80
81 static void
82 print_spreg (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, PTR dis_info,
83 CGEN_KEYWORD *table ATTRIBUTE_UNUSED, long val ATTRIBUTE_UNUSED,
84 unsigned int flags ATTRIBUTE_UNUSED)
85 {
86 disassemble_info *info = (disassemble_info *) dis_info;
87
88 (*info->fprintf_func) (info->stream, "$sp");
89 }
90
91 /* begin-cop-ip-print-handlers */
92 /* end-cop-ip-print-handlers */
93
94 /************************************************************\
95 *********************** Experimental *************************
96 \************************************************************/
97
98 #undef CGEN_PRINT_INSN
99 #define CGEN_PRINT_INSN mep_print_insn
100
101 static int
102 mep_print_vliw_insns (CGEN_CPU_DESC cd, bfd_vma pc, disassemble_info *info,
103 bfd_byte *buf, int corelength, int copro1length,
104 int copro2length ATTRIBUTE_UNUSED)
105 {
106 int i;
107 int status = 0;
108 /* char insnbuf[CGEN_MAX_INSN_SIZE]; */
109 bfd_byte insnbuf[64];
110
111 /* If corelength > 0 then there is a core insn present. It
112 will be at the beginning of the buffer. After printing
113 the core insn, we need to print the + on the next line. */
114 if (corelength > 0)
115 {
116 int my_status = 0;
117
118 for (i = 0; i < corelength; i++ )
119 insnbuf[i] = buf[i];
120 cd->isas = & MEP_CORE_ISA;
121
122 my_status = print_insn (cd, pc, info, insnbuf, corelength);
123 if (my_status != corelength)
124 {
125 (*info->fprintf_func) (info->stream, UNKNOWN_INSN_MSG);
126 my_status = corelength;
127 }
128 status += my_status;
129
130 /* Print the + to indicate that the following copro insn is */
131 /* part of a vliw group. */
132 if (copro1length > 0)
133 (*info->fprintf_func) (info->stream, " + ");
134 }
135
136 /* Now all that is left to be processed is the coprocessor insns
137 In vliw mode, there will always be one. Its positioning will
138 be from byte corelength to byte corelength+copro1length -1.
139 No need to check for existence. Also, the first vliw insn,
140 will, as spec'd, always be at least as long as the core insn
141 so we don't need to flush the buffer. */
142 if (copro1length > 0)
143 {
144 int my_status = 0;
145
146 for (i = corelength; i < corelength + copro1length; i++ )
147 insnbuf[i - corelength] = buf[i];
148
149 switch (copro1length)
150 {
151 case 0:
152 break;
153 case 2:
154 cd->isas = & MEP_COP16_ISA;
155 break;
156 case 4:
157 cd->isas = & MEP_COP32_ISA;
158 break;
159 case 6:
160 cd->isas = & MEP_COP48_ISA;
161 break;
162 case 8:
163 cd->isas = & MEP_COP64_ISA;
164 break;
165 default:
166 /* Shouldn't be anything but 16,32,48,64. */
167 break;
168 }
169
170 my_status = print_insn (cd, pc, info, insnbuf, copro1length);
171
172 if (my_status != copro1length)
173 {
174 (*info->fprintf_func) (info->stream, UNKNOWN_INSN_MSG);
175 my_status = copro1length;
176 }
177 status += my_status;
178 }
179
180 #if 0
181 /* Now we need to process the second copro insn if it exists. We
182 have no guarantee that the second copro insn will be longer
183 than the first, so we have to flush the buffer if we are have
184 a second copro insn to process. If present, this insn will
185 be in the position from byte corelength+copro1length to byte
186 corelength+copro1length+copro2length-1 (which better equal 8
187 or else we're in big trouble. */
188 if (copro2length > 0)
189 {
190 int my_status = 0;
191
192 for (i = 0; i < 64 ; i++)
193 insnbuf[i] = 0;
194
195 for (i = corelength + copro1length; i < 64; i++)
196 insnbuf[i - (corelength + copro1length)] = buf[i];
197
198 switch (copro2length)
199 {
200 case 2:
201 cd->isas = 1 << ISA_EXT_COP1_16;
202 break;
203 case 4:
204 cd->isas = 1 << ISA_EXT_COP1_32;
205 break;
206 case 6:
207 cd->isas = 1 << ISA_EXT_COP1_48;
208 break;
209 case 8:
210 cd->isas = 1 << ISA_EXT_COP1_64;
211 break;
212 default:
213 /* Shouldn't be anything but 16,32,48,64. */
214 break;
215 }
216
217 my_status = print_insn (cd, pc, info, insnbuf, copro2length);
218
219 if (my_status != copro2length)
220 {
221 (*info->fprintf_func) (info->stream, UNKNOWN_INSN_MSG);
222 my_status = copro2length;
223 }
224
225 status += my_status;
226 }
227 #endif
228
229 /* Status should now be the number of bytes that were printed
230 which should be 4 for VLIW32 mode and 64 for VLIW64 mode. */
231
232 if ((!MEP_VLIW64 && (status != 4)) || (MEP_VLIW64 && (status != 8)))
233 return -1;
234 else
235 return status;
236 }
237
238 /* The two functions mep_examine_vliw[32,64]_insns are used find out
239 which vliw combinaion (16 bit core with 48 bit copro, 32 bit core
240 with 32 bit copro, etc.) is present. Later on, when internally
241 parallel coprocessors are handled, only these functions should
242 need to be changed.
243
244 At this time only the following combinations are supported:
245
246 VLIW32 Mode:
247 16 bit core insn (core) and 16 bit coprocessor insn (cop1)
248 32 bit core insn (core)
249 32 bit coprocessor insn (cop1)
250 Note: As of this time, I do not believe we have enough information
251 to distinguish a 32 bit core insn from a 32 bit cop insn. Also,
252 no 16 bit coprocessor insns have been specified.
253
254 VLIW64 Mode:
255 16 bit core insn (core) and 48 bit coprocessor insn (cop1)
256 32 bit core insn (core) and 32 bit coprocessor insn (cop1)
257 64 bit coprocessor insn (cop1)
258
259 The framework for an internally parallel coprocessor is also
260 present (2nd coprocessor insn is cop2), but at this time it
261 is not used. This only appears to be valid in VLIW64 mode. */
262
263 static int
264 mep_examine_vliw32_insns (CGEN_CPU_DESC cd, bfd_vma pc, disassemble_info *info)
265 {
266 int status;
267 int buflength;
268 int corebuflength;
269 int cop1buflength;
270 int cop2buflength;
271 bfd_byte buf[CGEN_MAX_INSN_SIZE];
272 char indicator16[1];
273 char indicatorcop32[2];
274
275 /* At this time we're not supporting internally parallel coprocessors,
276 so cop2buflength will always be 0. */
277 cop2buflength = 0;
278
279 /* Read in 32 bits. */
280 buflength = 4; /* VLIW insn spans 4 bytes. */
281 status = (*info->read_memory_func) (pc, buf, buflength, info);
282
283 if (status != 0)
284 {
285 (*info->memory_error_func) (status, pc, info);
286 return -1;
287 }
288
289 /* Put the big endian representation of the bytes to be examined
290 in the temporary buffers for examination. */
291
292 if (info->endian == BFD_ENDIAN_BIG)
293 {
294 indicator16[0] = buf[0];
295 indicatorcop32[0] = buf[0];
296 indicatorcop32[1] = buf[1];
297 }
298 else
299 {
300 indicator16[0] = buf[1];
301 indicatorcop32[0] = buf[1];
302 indicatorcop32[1] = buf[0];
303 }
304
305 /* If the two high order bits are 00, 01 or 10, we have a 16 bit
306 core insn and a 48 bit copro insn. */
307
308 if ((indicator16[0] & 0x80) && (indicator16[0] & 0x40))
309 {
310 if ((indicatorcop32[0] & 0xf0) == 0xf0 && (indicatorcop32[1] & 0x07) == 0x07)
311 {
312 /* We have a 32 bit copro insn. */
313 corebuflength = 0;
314 /* All 4 4ytes are one copro insn. */
315 cop1buflength = 4;
316 }
317 else
318 {
319 /* We have a 32 bit core. */
320 corebuflength = 4;
321 cop1buflength = 0;
322 }
323 }
324 else
325 {
326 /* We have a 16 bit core insn and a 16 bit copro insn. */
327 corebuflength = 2;
328 cop1buflength = 2;
329 }
330
331 /* Now we have the distrubution set. Print them out. */
332 status = mep_print_vliw_insns (cd, pc, info, buf, corebuflength,
333 cop1buflength, cop2buflength);
334
335 return status;
336 }
337
338 static int
339 mep_examine_vliw64_insns (CGEN_CPU_DESC cd, bfd_vma pc, disassemble_info *info)
340 {
341 int status;
342 int buflength;
343 int corebuflength;
344 int cop1buflength;
345 int cop2buflength;
346 bfd_byte buf[CGEN_MAX_INSN_SIZE];
347 char indicator16[1];
348 char indicator64[4];
349
350 /* At this time we're not supporting internally parallel
351 coprocessors, so cop2buflength will always be 0. */
352 cop2buflength = 0;
353
354 /* Read in 64 bits. */
355 buflength = 8; /* VLIW insn spans 8 bytes. */
356 status = (*info->read_memory_func) (pc, buf, buflength, info);
357
358 if (status != 0)
359 {
360 (*info->memory_error_func) (status, pc, info);
361 return -1;
362 }
363
364 /* We have all 64 bits in the buffer now. We have to figure out
365 what combination of instruction sizes are present. The two
366 high order bits will indicate whether or not we have a 16 bit
367 core insn or not. If not, then we have to look at the 7,8th
368 bytes to tell whether we have 64 bit copro insn or a 32 bit
369 core insn with a 32 bit copro insn. Endianness will make a
370 difference here. */
371
372 /* Put the big endian representation of the bytes to be examined
373 in the temporary buffers for examination. */
374
375 /* indicator16[0] = buf[0]; */
376 if (info->endian == BFD_ENDIAN_BIG)
377 {
378 indicator16[0] = buf[0];
379 indicator64[0] = buf[0];
380 indicator64[1] = buf[1];
381 indicator64[2] = buf[2];
382 indicator64[3] = buf[3];
383 }
384 else
385 {
386 indicator16[0] = buf[1];
387 indicator64[0] = buf[1];
388 indicator64[1] = buf[0];
389 indicator64[2] = buf[3];
390 indicator64[3] = buf[2];
391 }
392
393 /* If the two high order bits are 00, 01 or 10, we have a 16 bit
394 core insn and a 48 bit copro insn. */
395
396 if ((indicator16[0] & 0x80) && (indicator16[0] & 0x40))
397 {
398 if ((indicator64[0] & 0xf0) == 0xf0 && (indicator64[1] & 0x07) == 0x07
399 && ((indicator64[2] & 0xfe) != 0xf0 || (indicator64[3] & 0xf4) != 0))
400 {
401 /* We have a 64 bit copro insn. */
402 corebuflength = 0;
403 /* All 8 bytes are one copro insn. */
404 cop1buflength = 8;
405 }
406 else
407 {
408 /* We have a 32 bit core insn and a 32 bit copro insn. */
409 corebuflength = 4;
410 cop1buflength = 4;
411 }
412 }
413 else
414 {
415 /* We have a 16 bit core insn and a 48 bit copro insn. */
416 corebuflength = 2;
417 cop1buflength = 6;
418 }
419
420 /* Now we have the distrubution set. Print them out. */
421 status = mep_print_vliw_insns (cd, pc, info, buf, corebuflength,
422 cop1buflength, cop2buflength);
423
424 return status;
425 }
426
427 static int
428 mep_print_insn (CGEN_CPU_DESC cd, bfd_vma pc, disassemble_info *info)
429 {
430 int status;
431
432 /* Extract and adapt to configuration number, if available. */
433 if (info->section && info->section->owner)
434 {
435 bfd *abfd = info->section->owner;
436 mep_config_index = abfd->tdata.elf_obj_data->elf_header->e_flags & EF_MEP_INDEX_MASK;
437 /* This instantly redefines MEP_CONFIG, MEP_OMASK, .... MEP_VLIW64 */
438 }
439
440 /* Picking the right ISA bitmask for the current context is tricky. */
441 if (info->section)
442 {
443 if (info->section->flags & SEC_MEP_VLIW)
444 {
445 /* Are we in 32 or 64 bit vliw mode? */
446 if (MEP_VLIW64)
447 status = mep_examine_vliw64_insns (cd, pc, info);
448 else
449 status = mep_examine_vliw32_insns (cd, pc, info);
450 /* Both the above branches set their own isa bitmasks. */
451 }
452 else
453 {
454 cd->isas = & MEP_CORE_ISA;
455 status = default_print_insn (cd, pc, info);
456 }
457 }
458 else /* sid or gdb */
459 {
460 status = default_print_insn (cd, pc, info);
461 }
462
463 return status;
464 }
465
466
467 /* -- opc.c */
468
469 void mep_cgen_print_operand
470 (CGEN_CPU_DESC, int, PTR, CGEN_FIELDS *, void const *, bfd_vma, int);
471
472 /* Main entry point for printing operands.
473 XINFO is a `void *' and not a `disassemble_info *' to not put a requirement
474 of dis-asm.h on cgen.h.
475
476 This function is basically just a big switch statement. Earlier versions
477 used tables to look up the function to use, but
478 - if the table contains both assembler and disassembler functions then
479 the disassembler contains much of the assembler and vice-versa,
480 - there's a lot of inlining possibilities as things grow,
481 - using a switch statement avoids the function call overhead.
482
483 This function could be moved into `print_insn_normal', but keeping it
484 separate makes clear the interface between `print_insn_normal' and each of
485 the handlers. */
486
487 void
488 mep_cgen_print_operand (CGEN_CPU_DESC cd,
489 int opindex,
490 void * xinfo,
491 CGEN_FIELDS *fields,
492 void const *attrs ATTRIBUTE_UNUSED,
493 bfd_vma pc,
494 int length)
495 {
496 disassemble_info *info = (disassemble_info *) xinfo;
497
498 switch (opindex)
499 {
500 case MEP_OPERAND_ADDR24A4 :
501 print_normal (cd, info, fields->f_24u8a4n, 0|(1<<CGEN_OPERAND_VIRTUAL), pc, length);
502 break;
503 case MEP_OPERAND_C5RMUIMM20 :
504 print_normal (cd, info, fields->f_c5_rmuimm20, 0|(1<<CGEN_OPERAND_VIRTUAL), pc, length);
505 break;
506 case MEP_OPERAND_C5RNMUIMM24 :
507 print_normal (cd, info, fields->f_c5_rnmuimm24, 0|(1<<CGEN_OPERAND_VIRTUAL), pc, length);
508 break;
509 case MEP_OPERAND_CALLNUM :
510 print_normal (cd, info, fields->f_callnum, 0|(1<<CGEN_OPERAND_VIRTUAL), pc, length);
511 break;
512 case MEP_OPERAND_CCCC :
513 print_normal (cd, info, fields->f_rm, 0, pc, length);
514 break;
515 case MEP_OPERAND_CCRN :
516 print_keyword (cd, info, & mep_cgen_opval_h_ccr, fields->f_ccrn, 0|(1<<CGEN_OPERAND_VIRTUAL));
517 break;
518 case MEP_OPERAND_CDISP10 :
519 print_normal (cd, info, fields->f_cdisp10, 0|(1<<CGEN_OPERAND_SIGNED), pc, length);
520 break;
521 case MEP_OPERAND_CDISP10A2 :
522 print_normal (cd, info, fields->f_cdisp10, 0|(1<<CGEN_OPERAND_SIGNED), pc, length);
523 break;
524 case MEP_OPERAND_CDISP10A4 :
525 print_normal (cd, info, fields->f_cdisp10, 0|(1<<CGEN_OPERAND_SIGNED), pc, length);
526 break;
527 case MEP_OPERAND_CDISP10A8 :
528 print_normal (cd, info, fields->f_cdisp10, 0|(1<<CGEN_OPERAND_SIGNED), pc, length);
529 break;
530 case MEP_OPERAND_CDISP12 :
531 print_normal (cd, info, fields->f_12s20, 0|(1<<CGEN_OPERAND_SIGNED), pc, length);
532 break;
533 case MEP_OPERAND_CIMM4 :
534 print_normal (cd, info, fields->f_rn, 0, pc, length);
535 break;
536 case MEP_OPERAND_CIMM5 :
537 print_normal (cd, info, fields->f_5u24, 0, pc, length);
538 break;
539 case MEP_OPERAND_CODE16 :
540 print_normal (cd, info, fields->f_16u16, 0, pc, length);
541 break;
542 case MEP_OPERAND_CODE24 :
543 print_normal (cd, info, fields->f_24u4n, 0|(1<<CGEN_OPERAND_VIRTUAL), pc, length);
544 break;
545 case MEP_OPERAND_CP_FLAG :
546 print_keyword (cd, info, & mep_cgen_opval_h_ccr, 0, 0);
547 break;
548 case MEP_OPERAND_CRN :
549 print_keyword (cd, info, & mep_cgen_opval_h_cr, fields->f_crn, 0);
550 break;
551 case MEP_OPERAND_CRN64 :
552 print_keyword (cd, info, & mep_cgen_opval_h_cr64, fields->f_crn, 0);
553 break;
554 case MEP_OPERAND_CRNX :
555 print_keyword (cd, info, & mep_cgen_opval_h_cr, fields->f_crnx, 0|(1<<CGEN_OPERAND_VIRTUAL));
556 break;
557 case MEP_OPERAND_CRNX64 :
558 print_keyword (cd, info, & mep_cgen_opval_h_cr64, fields->f_crnx, 0|(1<<CGEN_OPERAND_VIRTUAL));
559 break;
560 case MEP_OPERAND_CSRN :
561 print_keyword (cd, info, & mep_cgen_opval_h_csr, fields->f_csrn, 0|(1<<CGEN_OPERAND_VIRTUAL));
562 break;
563 case MEP_OPERAND_CSRN_IDX :
564 print_normal (cd, info, fields->f_csrn, 0|(1<<CGEN_OPERAND_VIRTUAL), pc, length);
565 break;
566 case MEP_OPERAND_DBG :
567 print_keyword (cd, info, & mep_cgen_opval_h_csr, 0, 0);
568 break;
569 case MEP_OPERAND_DEPC :
570 print_keyword (cd, info, & mep_cgen_opval_h_csr, 0, 0);
571 break;
572 case MEP_OPERAND_EPC :
573 print_keyword (cd, info, & mep_cgen_opval_h_csr, 0, 0);
574 break;
575 case MEP_OPERAND_EXC :
576 print_keyword (cd, info, & mep_cgen_opval_h_csr, 0, 0);
577 break;
578 case MEP_OPERAND_HI :
579 print_keyword (cd, info, & mep_cgen_opval_h_csr, 0, 0);
580 break;
581 case MEP_OPERAND_LO :
582 print_keyword (cd, info, & mep_cgen_opval_h_csr, 0, 0);
583 break;
584 case MEP_OPERAND_LP :
585 print_keyword (cd, info, & mep_cgen_opval_h_csr, 0, 0);
586 break;
587 case MEP_OPERAND_MB0 :
588 print_keyword (cd, info, & mep_cgen_opval_h_csr, 0, 0);
589 break;
590 case MEP_OPERAND_MB1 :
591 print_keyword (cd, info, & mep_cgen_opval_h_csr, 0, 0);
592 break;
593 case MEP_OPERAND_ME0 :
594 print_keyword (cd, info, & mep_cgen_opval_h_csr, 0, 0);
595 break;
596 case MEP_OPERAND_ME1 :
597 print_keyword (cd, info, & mep_cgen_opval_h_csr, 0, 0);
598 break;
599 case MEP_OPERAND_NPC :
600 print_keyword (cd, info, & mep_cgen_opval_h_csr, 0, 0);
601 break;
602 case MEP_OPERAND_OPT :
603 print_keyword (cd, info, & mep_cgen_opval_h_csr, 0, 0);
604 break;
605 case MEP_OPERAND_PCABS24A2 :
606 print_address (cd, info, fields->f_24u5a2n, 0|(1<<CGEN_OPERAND_ABS_ADDR)|(1<<CGEN_OPERAND_VIRTUAL), pc, length);
607 break;
608 case MEP_OPERAND_PCREL12A2 :
609 print_address (cd, info, fields->f_12s4a2, 0|(1<<CGEN_OPERAND_SIGNED)|(1<<CGEN_OPERAND_RELAX)|(1<<CGEN_OPERAND_PCREL_ADDR), pc, length);
610 break;
611 case MEP_OPERAND_PCREL17A2 :
612 print_address (cd, info, fields->f_17s16a2, 0|(1<<CGEN_OPERAND_SIGNED)|(1<<CGEN_OPERAND_RELAX)|(1<<CGEN_OPERAND_PCREL_ADDR), pc, length);
613 break;
614 case MEP_OPERAND_PCREL24A2 :
615 print_address (cd, info, fields->f_24s5a2n, 0|(1<<CGEN_OPERAND_SIGNED)|(1<<CGEN_OPERAND_PCREL_ADDR)|(1<<CGEN_OPERAND_VIRTUAL), pc, length);
616 break;
617 case MEP_OPERAND_PCREL8A2 :
618 print_address (cd, info, fields->f_8s8a2, 0|(1<<CGEN_OPERAND_SIGNED)|(1<<CGEN_OPERAND_RELAX)|(1<<CGEN_OPERAND_PCREL_ADDR), pc, length);
619 break;
620 case MEP_OPERAND_PSW :
621 print_keyword (cd, info, & mep_cgen_opval_h_csr, 0, 0);
622 break;
623 case MEP_OPERAND_R0 :
624 print_keyword (cd, info, & mep_cgen_opval_h_gpr, 0, 0);
625 break;
626 case MEP_OPERAND_R1 :
627 print_keyword (cd, info, & mep_cgen_opval_h_gpr, 0, 0);
628 break;
629 case MEP_OPERAND_RL :
630 print_keyword (cd, info, & mep_cgen_opval_h_gpr, fields->f_rl, 0);
631 break;
632 case MEP_OPERAND_RL5 :
633 print_keyword (cd, info, & mep_cgen_opval_h_gpr, fields->f_rl5, 0);
634 break;
635 case MEP_OPERAND_RM :
636 print_keyword (cd, info, & mep_cgen_opval_h_gpr, fields->f_rm, 0);
637 break;
638 case MEP_OPERAND_RMA :
639 print_keyword (cd, info, & mep_cgen_opval_h_gpr, fields->f_rm, 0);
640 break;
641 case MEP_OPERAND_RN :
642 print_keyword (cd, info, & mep_cgen_opval_h_gpr, fields->f_rn, 0);
643 break;
644 case MEP_OPERAND_RN3 :
645 print_keyword (cd, info, & mep_cgen_opval_h_gpr, fields->f_rn3, 0);
646 break;
647 case MEP_OPERAND_RN3C :
648 print_keyword (cd, info, & mep_cgen_opval_h_gpr, fields->f_rn3, 0);
649 break;
650 case MEP_OPERAND_RN3L :
651 print_keyword (cd, info, & mep_cgen_opval_h_gpr, fields->f_rn3, 0);
652 break;
653 case MEP_OPERAND_RN3S :
654 print_keyword (cd, info, & mep_cgen_opval_h_gpr, fields->f_rn3, 0);
655 break;
656 case MEP_OPERAND_RN3UC :
657 print_keyword (cd, info, & mep_cgen_opval_h_gpr, fields->f_rn3, 0);
658 break;
659 case MEP_OPERAND_RN3UL :
660 print_keyword (cd, info, & mep_cgen_opval_h_gpr, fields->f_rn3, 0);
661 break;
662 case MEP_OPERAND_RN3US :
663 print_keyword (cd, info, & mep_cgen_opval_h_gpr, fields->f_rn3, 0);
664 break;
665 case MEP_OPERAND_RNC :
666 print_keyword (cd, info, & mep_cgen_opval_h_gpr, fields->f_rn, 0);
667 break;
668 case MEP_OPERAND_RNL :
669 print_keyword (cd, info, & mep_cgen_opval_h_gpr, fields->f_rn, 0);
670 break;
671 case MEP_OPERAND_RNS :
672 print_keyword (cd, info, & mep_cgen_opval_h_gpr, fields->f_rn, 0);
673 break;
674 case MEP_OPERAND_RNUC :
675 print_keyword (cd, info, & mep_cgen_opval_h_gpr, fields->f_rn, 0);
676 break;
677 case MEP_OPERAND_RNUL :
678 print_keyword (cd, info, & mep_cgen_opval_h_gpr, fields->f_rn, 0);
679 break;
680 case MEP_OPERAND_RNUS :
681 print_keyword (cd, info, & mep_cgen_opval_h_gpr, fields->f_rn, 0);
682 break;
683 case MEP_OPERAND_SAR :
684 print_keyword (cd, info, & mep_cgen_opval_h_csr, 0, 0);
685 break;
686 case MEP_OPERAND_SDISP16 :
687 print_normal (cd, info, fields->f_16s16, 0|(1<<CGEN_OPERAND_SIGNED), pc, length);
688 break;
689 case MEP_OPERAND_SIMM16 :
690 print_normal (cd, info, fields->f_16s16, 0|(1<<CGEN_OPERAND_SIGNED), pc, length);
691 break;
692 case MEP_OPERAND_SIMM6 :
693 print_normal (cd, info, fields->f_6s8, 0|(1<<CGEN_OPERAND_SIGNED), pc, length);
694 break;
695 case MEP_OPERAND_SIMM8 :
696 print_normal (cd, info, fields->f_8s8, 0|(1<<CGEN_OPERAND_SIGNED)|(1<<CGEN_OPERAND_RELOC_IMPLIES_OVERFLOW), pc, length);
697 break;
698 case MEP_OPERAND_SP :
699 print_keyword (cd, info, & mep_cgen_opval_h_gpr, 0, 0);
700 break;
701 case MEP_OPERAND_SPR :
702 print_spreg (cd, info, & mep_cgen_opval_h_gpr, 0, 0);
703 break;
704 case MEP_OPERAND_TP :
705 print_keyword (cd, info, & mep_cgen_opval_h_gpr, 0, 0);
706 break;
707 case MEP_OPERAND_TPR :
708 print_tpreg (cd, info, & mep_cgen_opval_h_gpr, 0, 0);
709 break;
710 case MEP_OPERAND_UDISP2 :
711 print_normal (cd, info, fields->f_2u6, 0|(1<<CGEN_OPERAND_SIGNED), pc, length);
712 break;
713 case MEP_OPERAND_UDISP7 :
714 print_normal (cd, info, fields->f_7u9, 0, pc, length);
715 break;
716 case MEP_OPERAND_UDISP7A2 :
717 print_normal (cd, info, fields->f_7u9a2, 0, pc, length);
718 break;
719 case MEP_OPERAND_UDISP7A4 :
720 print_normal (cd, info, fields->f_7u9a4, 0, pc, length);
721 break;
722 case MEP_OPERAND_UIMM16 :
723 print_normal (cd, info, fields->f_16u16, 0, pc, length);
724 break;
725 case MEP_OPERAND_UIMM2 :
726 print_normal (cd, info, fields->f_2u10, 0, pc, length);
727 break;
728 case MEP_OPERAND_UIMM24 :
729 print_normal (cd, info, fields->f_24u8n, 0|(1<<CGEN_OPERAND_VIRTUAL), pc, length);
730 break;
731 case MEP_OPERAND_UIMM3 :
732 print_normal (cd, info, fields->f_3u5, 0, pc, length);
733 break;
734 case MEP_OPERAND_UIMM4 :
735 print_normal (cd, info, fields->f_4u8, 0, pc, length);
736 break;
737 case MEP_OPERAND_UIMM5 :
738 print_normal (cd, info, fields->f_5u8, 0, pc, length);
739 break;
740 case MEP_OPERAND_UIMM7A4 :
741 print_normal (cd, info, fields->f_7u9a4, 0, pc, length);
742 break;
743 case MEP_OPERAND_ZERO :
744 print_normal (cd, info, 0, 0|(1<<CGEN_OPERAND_SIGNED), pc, length);
745 break;
746
747 default :
748 /* xgettext:c-format */
749 fprintf (stderr, _("Unrecognized field %d while printing insn.\n"),
750 opindex);
751 abort ();
752 }
753 }
754
755 cgen_print_fn * const mep_cgen_print_handlers[] =
756 {
757 print_insn_normal,
758 };
759
760
761 void
762 mep_cgen_init_dis (CGEN_CPU_DESC cd)
763 {
764 mep_cgen_init_opcode_table (cd);
765 mep_cgen_init_ibld_table (cd);
766 cd->print_handlers = & mep_cgen_print_handlers[0];
767 cd->print_operand = mep_cgen_print_operand;
768 }
769
770 \f
771 /* Default print handler. */
772
773 static void
774 print_normal (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
775 void *dis_info,
776 long value,
777 unsigned int attrs,
778 bfd_vma pc ATTRIBUTE_UNUSED,
779 int length ATTRIBUTE_UNUSED)
780 {
781 disassemble_info *info = (disassemble_info *) dis_info;
782
783 #ifdef CGEN_PRINT_NORMAL
784 CGEN_PRINT_NORMAL (cd, info, value, attrs, pc, length);
785 #endif
786
787 /* Print the operand as directed by the attributes. */
788 if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_SEM_ONLY))
789 ; /* nothing to do */
790 else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_SIGNED))
791 (*info->fprintf_func) (info->stream, "%ld", value);
792 else
793 (*info->fprintf_func) (info->stream, "0x%lx", value);
794 }
795
796 /* Default address handler. */
797
798 static void
799 print_address (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
800 void *dis_info,
801 bfd_vma value,
802 unsigned int attrs,
803 bfd_vma pc ATTRIBUTE_UNUSED,
804 int length ATTRIBUTE_UNUSED)
805 {
806 disassemble_info *info = (disassemble_info *) dis_info;
807
808 #ifdef CGEN_PRINT_ADDRESS
809 CGEN_PRINT_ADDRESS (cd, info, value, attrs, pc, length);
810 #endif
811
812 /* Print the operand as directed by the attributes. */
813 if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_SEM_ONLY))
814 ; /* Nothing to do. */
815 else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_PCREL_ADDR))
816 (*info->print_address_func) (value, info);
817 else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_ABS_ADDR))
818 (*info->print_address_func) (value, info);
819 else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_SIGNED))
820 (*info->fprintf_func) (info->stream, "%ld", (long) value);
821 else
822 (*info->fprintf_func) (info->stream, "0x%lx", (long) value);
823 }
824
825 /* Keyword print handler. */
826
827 static void
828 print_keyword (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
829 void *dis_info,
830 CGEN_KEYWORD *keyword_table,
831 long value,
832 unsigned int attrs ATTRIBUTE_UNUSED)
833 {
834 disassemble_info *info = (disassemble_info *) dis_info;
835 const CGEN_KEYWORD_ENTRY *ke;
836
837 ke = cgen_keyword_lookup_value (keyword_table, value);
838 if (ke != NULL)
839 (*info->fprintf_func) (info->stream, "%s", ke->name);
840 else
841 (*info->fprintf_func) (info->stream, "???");
842 }
843 \f
844 /* Default insn printer.
845
846 DIS_INFO is defined as `void *' so the disassembler needn't know anything
847 about disassemble_info. */
848
849 static void
850 print_insn_normal (CGEN_CPU_DESC cd,
851 void *dis_info,
852 const CGEN_INSN *insn,
853 CGEN_FIELDS *fields,
854 bfd_vma pc,
855 int length)
856 {
857 const CGEN_SYNTAX *syntax = CGEN_INSN_SYNTAX (insn);
858 disassemble_info *info = (disassemble_info *) dis_info;
859 const CGEN_SYNTAX_CHAR_TYPE *syn;
860
861 CGEN_INIT_PRINT (cd);
862
863 for (syn = CGEN_SYNTAX_STRING (syntax); *syn; ++syn)
864 {
865 if (CGEN_SYNTAX_MNEMONIC_P (*syn))
866 {
867 (*info->fprintf_func) (info->stream, "%s", CGEN_INSN_MNEMONIC (insn));
868 continue;
869 }
870 if (CGEN_SYNTAX_CHAR_P (*syn))
871 {
872 (*info->fprintf_func) (info->stream, "%c", CGEN_SYNTAX_CHAR (*syn));
873 continue;
874 }
875
876 /* We have an operand. */
877 mep_cgen_print_operand (cd, CGEN_SYNTAX_FIELD (*syn), info,
878 fields, CGEN_INSN_ATTRS (insn), pc, length);
879 }
880 }
881 \f
882 /* Subroutine of print_insn. Reads an insn into the given buffers and updates
883 the extract info.
884 Returns 0 if all is well, non-zero otherwise. */
885
886 static int
887 read_insn (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
888 bfd_vma pc,
889 disassemble_info *info,
890 bfd_byte *buf,
891 int buflen,
892 CGEN_EXTRACT_INFO *ex_info,
893 unsigned long *insn_value)
894 {
895 int status = (*info->read_memory_func) (pc, buf, buflen, info);
896
897 if (status != 0)
898 {
899 (*info->memory_error_func) (status, pc, info);
900 return -1;
901 }
902
903 ex_info->dis_info = info;
904 ex_info->valid = (1 << buflen) - 1;
905 ex_info->insn_bytes = buf;
906
907 *insn_value = bfd_get_bits (buf, buflen * 8, info->endian == BFD_ENDIAN_BIG);
908 return 0;
909 }
910
911 /* Utility to print an insn.
912 BUF is the base part of the insn, target byte order, BUFLEN bytes long.
913 The result is the size of the insn in bytes or zero for an unknown insn
914 or -1 if an error occurs fetching data (memory_error_func will have
915 been called). */
916
917 static int
918 print_insn (CGEN_CPU_DESC cd,
919 bfd_vma pc,
920 disassemble_info *info,
921 bfd_byte *buf,
922 unsigned int buflen)
923 {
924 CGEN_INSN_INT insn_value;
925 const CGEN_INSN_LIST *insn_list;
926 CGEN_EXTRACT_INFO ex_info;
927 int basesize;
928
929 /* Extract base part of instruction, just in case CGEN_DIS_* uses it. */
930 basesize = cd->base_insn_bitsize < buflen * 8 ?
931 cd->base_insn_bitsize : buflen * 8;
932 insn_value = cgen_get_insn_value (cd, buf, basesize);
933
934
935 /* Fill in ex_info fields like read_insn would. Don't actually call
936 read_insn, since the incoming buffer is already read (and possibly
937 modified a la m32r). */
938 ex_info.valid = (1 << buflen) - 1;
939 ex_info.dis_info = info;
940 ex_info.insn_bytes = buf;
941
942 /* The instructions are stored in hash lists.
943 Pick the first one and keep trying until we find the right one. */
944
945 insn_list = CGEN_DIS_LOOKUP_INSN (cd, (char *) buf, insn_value);
946 while (insn_list != NULL)
947 {
948 const CGEN_INSN *insn = insn_list->insn;
949 CGEN_FIELDS fields;
950 int length;
951 unsigned long insn_value_cropped;
952
953 #ifdef CGEN_VALIDATE_INSN_SUPPORTED
954 /* Not needed as insn shouldn't be in hash lists if not supported. */
955 /* Supported by this cpu? */
956 if (! mep_cgen_insn_supported (cd, insn))
957 {
958 insn_list = CGEN_DIS_NEXT_INSN (insn_list);
959 continue;
960 }
961 #endif
962
963 /* Basic bit mask must be correct. */
964 /* ??? May wish to allow target to defer this check until the extract
965 handler. */
966
967 /* Base size may exceed this instruction's size. Extract the
968 relevant part from the buffer. */
969 if ((unsigned) (CGEN_INSN_BITSIZE (insn) / 8) < buflen &&
970 (unsigned) (CGEN_INSN_BITSIZE (insn) / 8) <= sizeof (unsigned long))
971 insn_value_cropped = bfd_get_bits (buf, CGEN_INSN_BITSIZE (insn),
972 info->endian == BFD_ENDIAN_BIG);
973 else
974 insn_value_cropped = insn_value;
975
976 if ((insn_value_cropped & CGEN_INSN_BASE_MASK (insn))
977 == CGEN_INSN_BASE_VALUE (insn))
978 {
979 /* Printing is handled in two passes. The first pass parses the
980 machine insn and extracts the fields. The second pass prints
981 them. */
982
983 /* Make sure the entire insn is loaded into insn_value, if it
984 can fit. */
985 if (((unsigned) CGEN_INSN_BITSIZE (insn) > cd->base_insn_bitsize) &&
986 (unsigned) (CGEN_INSN_BITSIZE (insn) / 8) <= sizeof (unsigned long))
987 {
988 unsigned long full_insn_value;
989 int rc = read_insn (cd, pc, info, buf,
990 CGEN_INSN_BITSIZE (insn) / 8,
991 & ex_info, & full_insn_value);
992 if (rc != 0)
993 return rc;
994 length = CGEN_EXTRACT_FN (cd, insn)
995 (cd, insn, &ex_info, full_insn_value, &fields, pc);
996 }
997 else
998 length = CGEN_EXTRACT_FN (cd, insn)
999 (cd, insn, &ex_info, insn_value_cropped, &fields, pc);
1000
1001 /* Length < 0 -> error. */
1002 if (length < 0)
1003 return length;
1004 if (length > 0)
1005 {
1006 CGEN_PRINT_FN (cd, insn) (cd, info, insn, &fields, pc, length);
1007 /* Length is in bits, result is in bytes. */
1008 return length / 8;
1009 }
1010 }
1011
1012 insn_list = CGEN_DIS_NEXT_INSN (insn_list);
1013 }
1014
1015 return 0;
1016 }
1017
1018 /* Default value for CGEN_PRINT_INSN.
1019 The result is the size of the insn in bytes or zero for an unknown insn
1020 or -1 if an error occured fetching bytes. */
1021
1022 #ifndef CGEN_PRINT_INSN
1023 #define CGEN_PRINT_INSN default_print_insn
1024 #endif
1025
1026 static int
1027 default_print_insn (CGEN_CPU_DESC cd, bfd_vma pc, disassemble_info *info)
1028 {
1029 bfd_byte buf[CGEN_MAX_INSN_SIZE];
1030 int buflen;
1031 int status;
1032
1033 /* Attempt to read the base part of the insn. */
1034 buflen = cd->base_insn_bitsize / 8;
1035 status = (*info->read_memory_func) (pc, buf, buflen, info);
1036
1037 /* Try again with the minimum part, if min < base. */
1038 if (status != 0 && (cd->min_insn_bitsize < cd->base_insn_bitsize))
1039 {
1040 buflen = cd->min_insn_bitsize / 8;
1041 status = (*info->read_memory_func) (pc, buf, buflen, info);
1042 }
1043
1044 if (status != 0)
1045 {
1046 (*info->memory_error_func) (status, pc, info);
1047 return -1;
1048 }
1049
1050 return print_insn (cd, pc, info, buf, buflen);
1051 }
1052
1053 /* Main entry point.
1054 Print one instruction from PC on INFO->STREAM.
1055 Return the size of the instruction (in bytes). */
1056
1057 typedef struct cpu_desc_list
1058 {
1059 struct cpu_desc_list *next;
1060 CGEN_BITSET *isa;
1061 int mach;
1062 int endian;
1063 CGEN_CPU_DESC cd;
1064 } cpu_desc_list;
1065
1066 int
1067 print_insn_mep (bfd_vma pc, disassemble_info *info)
1068 {
1069 static cpu_desc_list *cd_list = 0;
1070 cpu_desc_list *cl = 0;
1071 static CGEN_CPU_DESC cd = 0;
1072 static CGEN_BITSET *prev_isa;
1073 static int prev_mach;
1074 static int prev_endian;
1075 int length;
1076 CGEN_BITSET *isa;
1077 int mach;
1078 int endian = (info->endian == BFD_ENDIAN_BIG
1079 ? CGEN_ENDIAN_BIG
1080 : CGEN_ENDIAN_LITTLE);
1081 enum bfd_architecture arch;
1082
1083 /* ??? gdb will set mach but leave the architecture as "unknown" */
1084 #ifndef CGEN_BFD_ARCH
1085 #define CGEN_BFD_ARCH bfd_arch_mep
1086 #endif
1087 arch = info->arch;
1088 if (arch == bfd_arch_unknown)
1089 arch = CGEN_BFD_ARCH;
1090
1091 /* There's no standard way to compute the machine or isa number
1092 so we leave it to the target. */
1093 #ifdef CGEN_COMPUTE_MACH
1094 mach = CGEN_COMPUTE_MACH (info);
1095 #else
1096 mach = info->mach;
1097 #endif
1098
1099 #ifdef CGEN_COMPUTE_ISA
1100 {
1101 static CGEN_BITSET *permanent_isa;
1102
1103 if (!permanent_isa)
1104 permanent_isa = cgen_bitset_create (MAX_ISAS);
1105 isa = permanent_isa;
1106 cgen_bitset_clear (isa);
1107 cgen_bitset_add (isa, CGEN_COMPUTE_ISA (info));
1108 }
1109 #else
1110 isa = info->insn_sets;
1111 #endif
1112
1113 /* If we've switched cpu's, try to find a handle we've used before */
1114 if (cd
1115 && (cgen_bitset_compare (isa, prev_isa) != 0
1116 || mach != prev_mach
1117 || endian != prev_endian))
1118 {
1119 cd = 0;
1120 for (cl = cd_list; cl; cl = cl->next)
1121 {
1122 if (cgen_bitset_compare (cl->isa, isa) == 0 &&
1123 cl->mach == mach &&
1124 cl->endian == endian)
1125 {
1126 cd = cl->cd;
1127 prev_isa = cd->isas;
1128 break;
1129 }
1130 }
1131 }
1132
1133 /* If we haven't initialized yet, initialize the opcode table. */
1134 if (! cd)
1135 {
1136 const bfd_arch_info_type *arch_type = bfd_lookup_arch (arch, mach);
1137 const char *mach_name;
1138
1139 if (!arch_type)
1140 abort ();
1141 mach_name = arch_type->printable_name;
1142
1143 prev_isa = cgen_bitset_copy (isa);
1144 prev_mach = mach;
1145 prev_endian = endian;
1146 cd = mep_cgen_cpu_open (CGEN_CPU_OPEN_ISAS, prev_isa,
1147 CGEN_CPU_OPEN_BFDMACH, mach_name,
1148 CGEN_CPU_OPEN_ENDIAN, prev_endian,
1149 CGEN_CPU_OPEN_END);
1150 if (!cd)
1151 abort ();
1152
1153 /* Save this away for future reference. */
1154 cl = xmalloc (sizeof (struct cpu_desc_list));
1155 cl->cd = cd;
1156 cl->isa = prev_isa;
1157 cl->mach = mach;
1158 cl->endian = endian;
1159 cl->next = cd_list;
1160 cd_list = cl;
1161
1162 mep_cgen_init_dis (cd);
1163 }
1164
1165 /* We try to have as much common code as possible.
1166 But at this point some targets need to take over. */
1167 /* ??? Some targets may need a hook elsewhere. Try to avoid this,
1168 but if not possible try to move this hook elsewhere rather than
1169 have two hooks. */
1170 length = CGEN_PRINT_INSN (cd, pc, info);
1171 if (length > 0)
1172 return length;
1173 if (length < 0)
1174 return -1;
1175
1176 (*info->fprintf_func) (info->stream, UNKNOWN_INSN_MSG);
1177 return cd->default_insn_bitsize / 8;
1178 }
This page took 0.054949 seconds and 5 git commands to generate.