1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
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 "fr30-desc.h"
37: #include "fr30-opc.h"
38: #include "opintl.h"
39:
40:
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: ^L
59:
60:
61:
62: static void
63: print_register_list (void * dis_info,
64: long value,
65: long offset,
66: int load_store)
67: {
68: disassemble_info *info = dis_info;
69: int mask;
70: int index = 0;
71: char * comma = "";
72:
73: if (load_store)
74: mask = 0x80;
75: else
76: mask = 1;
77:
78: if (value & mask)
79: {
80: (*info->fprintf_func) (info->stream, "r%li", index + offset);
81: comma = ",";
82: }
83:
84: for (index = 1; index <= 7; ++index)
85: {
86: if (load_store)
87: mask >>= 1;
88: else
89: mask <<= 1;
90:
91: if (value & mask)
92: {
93: (*info->fprintf_func) (info->stream, "%sr%li", comma, index + offset);
94: comma = ",";
95: }
96: }
97: }
98:
99: static void
100: print_hi_register_list_ld (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
101: void * dis_info,
102: long value,
103: unsigned int attrs ATTRIBUTE_UNUSED,
104: bfd_vma pc ATTRIBUTE_UNUSED,
105: int length ATTRIBUTE_UNUSED)
106: {
107: print_register_list (dis_info, value, 8, 0 );
108: }
109:
110: static void
111: print_low_register_list_ld (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
112: void * dis_info,
113: long value,
114: unsigned int attrs ATTRIBUTE_UNUSED,
115: bfd_vma pc ATTRIBUTE_UNUSED,
116: int length ATTRIBUTE_UNUSED)
117: {
118: print_register_list (dis_info, value, 0, 0 );
119: }
120:
121: static void
122: print_hi_register_list_st (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
123: void * dis_info,
124: long value,
125: unsigned int attrs ATTRIBUTE_UNUSED,
126: bfd_vma pc ATTRIBUTE_UNUSED,
127: int length ATTRIBUTE_UNUSED)
128: {
129: print_register_list (dis_info, value, 8, 1 );
130: }
131:
132: static void
133: print_low_register_list_st (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
134: void * dis_info,
135: long value,
136: unsigned int attrs ATTRIBUTE_UNUSED,
137: bfd_vma pc ATTRIBUTE_UNUSED,
138: int length ATTRIBUTE_UNUSED)
139: {
140: print_register_list (dis_info, value, 0, 1 );
141: }
142:
143: static void
144: print_m4 (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
145: void * dis_info,
146: long value,
147: unsigned int attrs ATTRIBUTE_UNUSED,
148: bfd_vma pc ATTRIBUTE_UNUSED,
149: int length ATTRIBUTE_UNUSED)
150: {
151: disassemble_info *info = (disassemble_info *) dis_info;
152:
153: (*info->fprintf_func) (info->stream, "%ld", value);
154: }
155:
156:
157: void fr30_cgen_print_operand
158: (CGEN_CPU_DESC, int, PTR, CGEN_FIELDS *, void const *, bfd_vma, int);
159:
160:
161:
162:
163:
164:
165:
166:
167:
168:
169:
170:
171:
172:
173:
174:
175: void
176: fr30_cgen_print_operand (CGEN_CPU_DESC cd,
177: int opindex,
178: void * xinfo,
179: CGEN_FIELDS *fields,
180: void const *attrs ATTRIBUTE_UNUSED,
181: bfd_vma pc,
182: int length)
183: {
184: disassemble_info *info = (disassemble_info *) xinfo;
185:
186: switch (opindex)
187: {
188: case FR30_OPERAND_CRI :
189: print_keyword (cd, info, & fr30_cgen_opval_cr_names, fields->f_CRi, 0);
190: break;
191: case FR30_OPERAND_CRJ :
192: print_keyword (cd, info, & fr30_cgen_opval_cr_names, fields->f_CRj, 0);
193: break;
194: case FR30_OPERAND_R13 :
195: print_keyword (cd, info, & fr30_cgen_opval_h_r13, 0, 0);
196: break;
197: case FR30_OPERAND_R14 :
198: print_keyword (cd, info, & fr30_cgen_opval_h_r14, 0, 0);
199: break;
200: case FR30_OPERAND_R15 :
201: print_keyword (cd, info, & fr30_cgen_opval_h_r15, 0, 0);
202: break;
203: case FR30_OPERAND_RI :
204: print_keyword (cd, info, & fr30_cgen_opval_gr_names, fields->f_Ri, 0);
205: break;
206: case FR30_OPERAND_RIC :
207: print_keyword (cd, info, & fr30_cgen_opval_gr_names, fields->f_Ric, 0);
208: break;
209: case FR30_OPERAND_RJ :
210: print_keyword (cd, info, & fr30_cgen_opval_gr_names, fields->f_Rj, 0);
211: break;
212: case FR30_OPERAND_RJC :
213: print_keyword (cd, info, & fr30_cgen_opval_gr_names, fields->f_Rjc, 0);
214: break;
215: case FR30_OPERAND_RS1 :
216: print_keyword (cd, info, & fr30_cgen_opval_dr_names, fields->f_Rs1, 0);
217: break;
218: case FR30_OPERAND_RS2 :
219: print_keyword (cd, info, & fr30_cgen_opval_dr_names, fields->f_Rs2, 0);
220: break;
221: case FR30_OPERAND_CC :
222: print_normal (cd, info, fields->f_cc, 0, pc, length);
223: break;
224: case FR30_OPERAND_CCC :
225: print_normal (cd, info, fields->f_ccc, 0|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
226: break;
227: case FR30_OPERAND_DIR10 :
228: print_normal (cd, info, fields->f_dir10, 0, pc, length);
229: break;
230: case FR30_OPERAND_DIR8 :
231: print_normal (cd, info, fields->f_dir8, 0, pc, length);
232: break;
233: case FR30_OPERAND_DIR9 :
234: print_normal (cd, info, fields->f_dir9, 0, pc, length);
235: break;
236: case FR30_OPERAND_DISP10 :
237: print_normal (cd, info, fields->f_disp10, 0|(1<<CGEN_OPERAND_SIGNED)|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
238: break;
239: case FR30_OPERAND_DISP8 :
240: print_normal (cd, info, fields->f_disp8, 0|(1<<CGEN_OPERAND_SIGNED)|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
241: break;
242: case FR30_OPERAND_DISP9 :
243: print_normal (cd, info, fields->f_disp9, 0|(1<<CGEN_OPERAND_SIGNED)|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
244: break;
245: case FR30_OPERAND_I20 :
246: print_normal (cd, info, fields->f_i20, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_VIRTUAL), pc, length);
247: break;
248: case FR30_OPERAND_I32 :
249: print_normal (cd, info, fields->f_i32, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_SIGN_OPT), pc, length);
250: break;
251: case FR30_OPERAND_I8 :
252: print_normal (cd, info, fields->f_i8, 0|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
253: break;
254: case FR30_OPERAND_LABEL12 :
255: print_address (cd, info, fields->f_rel12, 0|(1<<CGEN_OPERAND_PCREL_ADDR), pc, length);
256: break;
257: case FR30_OPERAND_LABEL9 :
258: print_address (cd, info, fields->f_rel9, 0|(1<<CGEN_OPERAND_PCREL_ADDR), pc, length);
259: break;
260: case FR30_OPERAND_M4 :
261: print_m4 (cd, info, fields->f_m4, 0|(1<<CGEN_OPERAND_SIGNED)|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
262: break;
263: case FR30_OPERAND_PS :
264: print_keyword (cd, info, & fr30_cgen_opval_h_ps, 0, 0);
265: break;
266: case FR30_OPERAND_REGLIST_HI_LD :
267: print_hi_register_list_ld (cd, info, fields->f_reglist_hi_ld, 0, pc, length);
268: break;
269: case FR30_OPERAND_REGLIST_HI_ST :
270: print_hi_register_list_st (cd, info, fields->f_reglist_hi_st, 0, pc, length);
271: break;
272: case FR30_OPERAND_REGLIST_LOW_LD :
273: print_low_register_list_ld (cd, info, fields->f_reglist_low_ld, 0, pc, length);
274: break;
275: case FR30_OPERAND_REGLIST_LOW_ST :
276: print_low_register_list_st (cd, info, fields->f_reglist_low_st, 0, pc, length);
277: break;
278: case FR30_OPERAND_S10 :
279: print_normal (cd, info, fields->f_s10, 0|(1<<CGEN_OPERAND_SIGNED)|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
280: break;
281: case FR30_OPERAND_U10 :
282: print_normal (cd, info, fields->f_u10, 0|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
283: break;
284: case FR30_OPERAND_U4 :
285: print_normal (cd, info, fields->f_u4, 0|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
286: break;
287: case FR30_OPERAND_U4C :
288: print_normal (cd, info, fields->f_u4c, 0|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
289: break;
290: case FR30_OPERAND_U8 :
291: print_normal (cd, info, fields->f_u8, 0|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
292: break;
293: case FR30_OPERAND_UDISP6 :
294: print_normal (cd, info, fields->f_udisp6, 0|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
295: break;
296:
297: default :
298:
299: fprintf (stderr, _("Unrecognized field %d while printing insn.\n"),
300: opindex);
301: abort ();
302: }
303: }
304:
305: cgen_print_fn * const fr30_cgen_print_handlers[] =
306: {
307: print_insn_normal,
308: };
309:
310:
311: void
312: fr30_cgen_init_dis (CGEN_CPU_DESC cd)
313: {
314: fr30_cgen_init_opcode_table (cd);
315: fr30_cgen_init_ibld_table (cd);
316: cd->print_handlers = & fr30_cgen_print_handlers[0];
317: cd->print_operand = fr30_cgen_print_operand;
318: }
319:
320: ^L
321:
322:
323: static void
324: print_normal (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
325: void *dis_info,
326: long value,
327: unsigned int attrs,
328: bfd_vma pc ATTRIBUTE_UNUSED,
329: int length ATTRIBUTE_UNUSED)
330: {
331: disassemble_info *info = (disassemble_info *) dis_info;
332:
333: #ifdef CGEN_PRINT_NORMAL
334: CGEN_PRINT_NORMAL (cd, info, value, attrs, pc, length);
335: #endif
336:
337:
338: if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_SEM_ONLY))
339: ;
340: else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_SIGNED))
341: (*info->fprintf_func) (info->stream, "%ld", value);
342: else
343: (*info->fprintf_func) (info->stream, "0x%lx", value);
344: }
345:
346:
347:
348: static void
349: print_address (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
350: void *dis_info,
351: bfd_vma value,
352: unsigned int attrs,
353: bfd_vma pc ATTRIBUTE_UNUSED,
354: int length ATTRIBUTE_UNUSED)
355: {
356: disassemble_info *info = (disassemble_info *) dis_info;
357:
358: #ifdef CGEN_PRINT_ADDRESS
359: CGEN_PRINT_ADDRESS (cd, info, value, attrs, pc, length);
360: #endif
361:
362:
363: if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_SEM_ONLY))
364: ;
365: else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_PCREL_ADDR))
366: (*info->print_address_func) (value, info);
367: else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_ABS_ADDR))
368: (*info->print_address_func) (value, info);
369: else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_SIGNED))
370: (*info->fprintf_func) (info->stream, "%ld", (long) value);
371: else
372: (*info->fprintf_func) (info->stream, "0x%lx", (long) value);
373: }
374:
375:
376:
377: static void
378: print_keyword (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
379: void *dis_info,
380: CGEN_KEYWORD *keyword_table,
381: long value,
382: unsigned int attrs ATTRIBUTE_UNUSED)
383: {
384: disassemble_info *info = (disassemble_info *) dis_info;
385: const CGEN_KEYWORD_ENTRY *ke;
386:
387: ke = cgen_keyword_lookup_value (keyword_table, value);
388: if (ke != NULL)
389: (*info->fprintf_func) (info->stream, "%s", ke->name);
390: else
391: (*info->fprintf_func) (info->stream, "???");
392: }
393: ^L
394:
395:
396:
397:
398:
399: static void
400: print_insn_normal (CGEN_CPU_DESC cd,
401: void *dis_info,
402: const CGEN_INSN *insn,
403: CGEN_FIELDS *fields,
404: bfd_vma pc,
405: int length)
406: {
407: const CGEN_SYNTAX *syntax = CGEN_INSN_SYNTAX (insn);
408: disassemble_info *info = (disassemble_info *) dis_info;
409: const CGEN_SYNTAX_CHAR_TYPE *syn;
410:
411: CGEN_INIT_PRINT (cd);
412:
413: for (syn = CGEN_SYNTAX_STRING (syntax); *syn; ++syn)
414: {
415: if (CGEN_SYNTAX_MNEMONIC_P (*syn))
416: {
417: (*info->fprintf_func) (info->stream, "%s", CGEN_INSN_MNEMONIC (insn));
418: continue;
419: }
420: if (CGEN_SYNTAX_CHAR_P (*syn))
421: {
422: (*info->fprintf_func) (info->stream, "%c", CGEN_SYNTAX_CHAR (*syn));
423: continue;
424: }
425:
426:
427: fr30_cgen_print_operand (cd, CGEN_SYNTAX_FIELD (*syn), info,
428: fields, CGEN_INSN_ATTRS (insn), pc, length);
429: }
430: }
431: ^L
432:
433:
434:
435:
436: static int
437: read_insn (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
438: bfd_vma pc,
439: disassemble_info *info,
440: bfd_byte *buf,
441: int buflen,
442: CGEN_EXTRACT_INFO *ex_info,
443: unsigned long *insn_value)
444: {
445: int status = (*info->read_memory_func) (pc, buf, buflen, info);
446:
447: if (status != 0)
448: {
449: (*info->memory_error_func) (status, pc, info);
450: return -1;
451: }
452:
453: ex_info->dis_info = info;
454: ex_info->valid = (1 << buflen) - 1;
455: ex_info->insn_bytes = buf;
456:
457: *insn_value = bfd_get_bits (buf, buflen * 8, info->endian == BFD_ENDIAN_BIG);
458: return 0;
459: }
460:
461:
462:
463:
464:
465:
466:
467: static int
468: print_insn (CGEN_CPU_DESC cd,
469: bfd_vma pc,
470: disassemble_info *info,
471: bfd_byte *buf,
472: unsigned int buflen)
473: {
474: CGEN_INSN_INT insn_value;
475: const CGEN_INSN_LIST *insn_list;
476: CGEN_EXTRACT_INFO ex_info;
477: int basesize;
478:
479:
480: basesize = cd->base_insn_bitsize < buflen * 8 ?
481: cd->base_insn_bitsize : buflen * 8;
482: insn_value = cgen_get_insn_value (cd, buf, basesize);
483:
484:
485:
486:
487:
488: ex_info.valid = (1 << buflen) - 1;
489: ex_info.dis_info = info;
490: ex_info.insn_bytes = buf;
491:
492:
493:
494:
495: insn_list = CGEN_DIS_LOOKUP_INSN (cd, (char *) buf, insn_value);
496: while (insn_list != NULL)
497: {
498: const CGEN_INSN *insn = insn_list->insn;
499: CGEN_FIELDS fields;
500: int length;
501: unsigned long insn_value_cropped;
502:
503: #ifdef CGEN_VALIDATE_INSN_SUPPORTED
504:
505:
506: if (! fr30_cgen_insn_supported (cd, insn))
507: {
508: insn_list = CGEN_DIS_NEXT_INSN (insn_list);
509: continue;
510: }
511: #endif
512:
513:
514:
515:
516:
517:
518:
519: if ((unsigned) (CGEN_INSN_BITSIZE (insn) / 8) < buflen &&
520: (unsigned) (CGEN_INSN_BITSIZE (insn) / 8) <= sizeof (unsigned long))
521: insn_value_cropped = bfd_get_bits (buf, CGEN_INSN_BITSIZE (insn),
522: info->endian == BFD_ENDIAN_BIG);
523: else
524: insn_value_cropped = insn_value;
525:
526: if ((insn_value_cropped & CGEN_INSN_BASE_MASK (insn))
527: == CGEN_INSN_BASE_VALUE (insn))
528: {
529:
530:
531:
532:
533:
534:
535: if (((unsigned) CGEN_INSN_BITSIZE (insn) > cd->base_insn_bitsize) &&
536: (unsigned) (CGEN_INSN_BITSIZE (insn) / 8) <= sizeof (unsigned long))
537: {
538: