00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035 #include "sysdep.h"
00036 #include <stdio.h>
00037 #include "ansidecl.h"
00038 #include "dis-asm.h"
00039 #include "bfd.h"
00040 #include "symcat.h"
00041 #include "libiberty.h"
00042 #include "xstormy16-desc.h"
00043 #include "xstormy16-opc.h"
00044 #include "opintl.h"
00045
00046
00047 #define UNKNOWN_INSN_MSG _("*unknown*")
00048
00049 static void print_normal
00050 (CGEN_CPU_DESC, void *, long, unsigned int, bfd_vma, int);
00051 static void print_address
00052 (CGEN_CPU_DESC, void *, bfd_vma, unsigned int, bfd_vma, int) ATTRIBUTE_UNUSED;
00053 static void print_keyword
00054 (CGEN_CPU_DESC, void *, CGEN_KEYWORD *, long, unsigned int) ATTRIBUTE_UNUSED;
00055 static void print_insn_normal
00056 (CGEN_CPU_DESC, void *, const CGEN_INSN *, CGEN_FIELDS *, bfd_vma, int);
00057 static int print_insn
00058 (CGEN_CPU_DESC, bfd_vma, disassemble_info *, bfd_byte *, unsigned);
00059 static int default_print_insn
00060 (CGEN_CPU_DESC, bfd_vma, disassemble_info *) ATTRIBUTE_UNUSED;
00061 static int read_insn
00062 (CGEN_CPU_DESC, bfd_vma, disassemble_info *, bfd_byte *, int, CGEN_EXTRACT_INFO *,
00063 unsigned long *);
00064
00065
00066
00067
00068 void xstormy16_cgen_print_operand
00069 PARAMS ((CGEN_CPU_DESC, int, PTR, CGEN_FIELDS *,
00070 void const *, bfd_vma, int));
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087 void
00088 xstormy16_cgen_print_operand (cd, opindex, xinfo, fields, attrs, pc, length)
00089 CGEN_CPU_DESC cd;
00090 int opindex;
00091 PTR xinfo;
00092 CGEN_FIELDS *fields;
00093 void const *attrs ATTRIBUTE_UNUSED;
00094 bfd_vma pc;
00095 int length;
00096 {
00097 disassemble_info *info = (disassemble_info *) xinfo;
00098
00099 switch (opindex)
00100 {
00101 case XSTORMY16_OPERAND_RB :
00102 print_keyword (cd, info, & xstormy16_cgen_opval_gr_Rb_names, fields->f_Rb, 0);
00103 break;
00104 case XSTORMY16_OPERAND_RBJ :
00105 print_keyword (cd, info, & xstormy16_cgen_opval_gr_Rb_names, fields->f_Rbj, 0);
00106 break;
00107 case XSTORMY16_OPERAND_RD :
00108 print_keyword (cd, info, & xstormy16_cgen_opval_gr_names, fields->f_Rd, 0);
00109 break;
00110 case XSTORMY16_OPERAND_RDM :
00111 print_keyword (cd, info, & xstormy16_cgen_opval_gr_names, fields->f_Rdm, 0);
00112 break;
00113 case XSTORMY16_OPERAND_RM :
00114 print_keyword (cd, info, & xstormy16_cgen_opval_gr_names, fields->f_Rm, 0);
00115 break;
00116 case XSTORMY16_OPERAND_RS :
00117 print_keyword (cd, info, & xstormy16_cgen_opval_gr_names, fields->f_Rs, 0);
00118 break;
00119 case XSTORMY16_OPERAND_ABS24 :
00120 print_normal (cd, info, fields->f_abs24, 0|(1<<CGEN_OPERAND_ABS_ADDR)|(1<<CGEN_OPERAND_VIRTUAL), pc, length);
00121 break;
00122 case XSTORMY16_OPERAND_BCOND2 :
00123 print_keyword (cd, info, & xstormy16_cgen_opval_h_branchcond, fields->f_op2, 0);
00124 break;
00125 case XSTORMY16_OPERAND_BCOND5 :
00126 print_keyword (cd, info, & xstormy16_cgen_opval_h_branchcond, fields->f_op5, 0);
00127 break;
00128 case XSTORMY16_OPERAND_HMEM8 :
00129 print_normal (cd, info, fields->f_hmem8, 0|(1<<CGEN_OPERAND_ABS_ADDR), pc, length);
00130 break;
00131 case XSTORMY16_OPERAND_IMM12 :
00132 print_normal (cd, info, fields->f_imm12, 0|(1<<CGEN_OPERAND_SIGNED), pc, length);
00133 break;
00134 case XSTORMY16_OPERAND_IMM16 :
00135 print_normal (cd, info, fields->f_imm16, 0|(1<<CGEN_OPERAND_SIGN_OPT), pc, length);
00136 break;
00137 case XSTORMY16_OPERAND_IMM2 :
00138 print_normal (cd, info, fields->f_imm2, 0, pc, length);
00139 break;
00140 case XSTORMY16_OPERAND_IMM3 :
00141 print_normal (cd, info, fields->f_imm3, 0, pc, length);
00142 break;
00143 case XSTORMY16_OPERAND_IMM3B :
00144 print_normal (cd, info, fields->f_imm3b, 0, pc, length);
00145 break;
00146 case XSTORMY16_OPERAND_IMM4 :
00147 print_normal (cd, info, fields->f_imm4, 0, pc, length);
00148 break;
00149 case XSTORMY16_OPERAND_IMM8 :
00150 print_normal (cd, info, fields->f_imm8, 0, pc, length);
00151 break;
00152 case XSTORMY16_OPERAND_IMM8SMALL :
00153 print_normal (cd, info, fields->f_imm8, 0, pc, length);
00154 break;
00155 case XSTORMY16_OPERAND_LMEM8 :
00156 print_normal (cd, info, fields->f_lmem8, 0|(1<<CGEN_OPERAND_ABS_ADDR), pc, length);
00157 break;
00158 case XSTORMY16_OPERAND_REL12 :
00159 print_normal (cd, info, fields->f_rel12, 0|(1<<CGEN_OPERAND_PCREL_ADDR), pc, length);
00160 break;
00161 case XSTORMY16_OPERAND_REL12A :
00162 print_normal (cd, info, fields->f_rel12a, 0|(1<<CGEN_OPERAND_PCREL_ADDR), pc, length);
00163 break;
00164 case XSTORMY16_OPERAND_REL8_2 :
00165 print_normal (cd, info, fields->f_rel8_2, 0|(1<<CGEN_OPERAND_PCREL_ADDR), pc, length);
00166 break;
00167 case XSTORMY16_OPERAND_REL8_4 :
00168 print_normal (cd, info, fields->f_rel8_4, 0|(1<<CGEN_OPERAND_PCREL_ADDR), pc, length);
00169 break;
00170 case XSTORMY16_OPERAND_WS2 :
00171 print_keyword (cd, info, & xstormy16_cgen_opval_h_wordsize, fields->f_op2m, 0);
00172 break;
00173
00174 default :
00175
00176 fprintf (stderr, _("Unrecognized field %d while printing insn.\n"),
00177 opindex);
00178 abort ();
00179 }
00180 }
00181
00182 cgen_print_fn * const xstormy16_cgen_print_handlers[] =
00183 {
00184 print_insn_normal,
00185 };
00186
00187
00188 void
00189 xstormy16_cgen_init_dis (cd)
00190 CGEN_CPU_DESC cd;
00191 {
00192 xstormy16_cgen_init_opcode_table (cd);
00193 xstormy16_cgen_init_ibld_table (cd);
00194 cd->print_handlers = & xstormy16_cgen_print_handlers[0];
00195 cd->print_operand = xstormy16_cgen_print_operand;
00196 }
00197
00198
00199
00200
00201 static void
00202 print_normal (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
00203 void *dis_info,
00204 long value,
00205 unsigned int attrs,
00206 bfd_vma pc ATTRIBUTE_UNUSED,
00207 int length ATTRIBUTE_UNUSED)
00208 {
00209 disassemble_info *info = (disassemble_info *) dis_info;
00210
00211 #ifdef CGEN_PRINT_NORMAL
00212 CGEN_PRINT_NORMAL (cd, info, value, attrs, pc, length);
00213 #endif
00214
00215
00216 if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_SEM_ONLY))
00217 ;
00218 else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_SIGNED))
00219 (*info->fprintf_func) (info->stream, "%ld", value);
00220 else
00221 (*info->fprintf_func) (info->stream, "0x%lx", value);
00222 }
00223
00224
00225
00226 static void
00227 print_address (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
00228 void *dis_info,
00229 bfd_vma value,
00230 unsigned int attrs,
00231 bfd_vma pc ATTRIBUTE_UNUSED,
00232 int length ATTRIBUTE_UNUSED)
00233 {
00234 disassemble_info *info = (disassemble_info *) dis_info;
00235
00236 #ifdef CGEN_PRINT_ADDRESS
00237 CGEN_PRINT_ADDRESS (cd, info, value, attrs, pc, length);
00238 #endif
00239
00240
00241 if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_SEM_ONLY))
00242 ;
00243 else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_PCREL_ADDR))
00244 (*info->print_address_func) (value, info);
00245 else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_ABS_ADDR))
00246 (*info->print_address_func) (value, info);
00247 else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_SIGNED))
00248 (*info->fprintf_func) (info->stream, "%ld", (long) value);
00249 else
00250 (*info->fprintf_func) (info->stream, "0x%lx", (long) value);
00251 }
00252
00253
00254
00255 static void
00256 print_keyword (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
00257 void *dis_info,
00258 CGEN_KEYWORD *keyword_table,
00259 long value,
00260 unsigned int attrs ATTRIBUTE_UNUSED)
00261 {
00262 disassemble_info *info = (disassemble_info *) dis_info;
00263 const CGEN_KEYWORD_ENTRY *ke;
00264
00265 ke = cgen_keyword_lookup_value (keyword_table, value);
00266 if (ke != NULL)
00267 (*info->fprintf_func) (info->stream, "%s", ke->name);
00268 else
00269 (*info->fprintf_func) (info->stream, "???");
00270 }
00271
00272
00273
00274
00275
00276
00277 static void
00278 print_insn_normal (CGEN_CPU_DESC cd,
00279 void *dis_info,
00280 const CGEN_INSN *insn,
00281 CGEN_FIELDS *fields,
00282 bfd_vma pc,
00283 int length)
00284 {
00285 const CGEN_SYNTAX *syntax = CGEN_INSN_SYNTAX (insn);
00286 disassemble_info *info = (disassemble_info *) dis_info;
00287 const CGEN_SYNTAX_CHAR_TYPE *syn;
00288
00289 CGEN_INIT_PRINT (cd);
00290
00291 for (syn = CGEN_SYNTAX_STRING (syntax); *syn; ++syn)
00292 {
00293 if (CGEN_SYNTAX_MNEMONIC_P (*syn))
00294 {
00295 (*info->fprintf_func) (info->stream, "%s", CGEN_INSN_MNEMONIC (insn));
00296 continue;
00297 }
00298 if (CGEN_SYNTAX_CHAR_P (*syn))
00299 {
00300 (*info->fprintf_func) (info->stream, "%c", CGEN_SYNTAX_CHAR (*syn));
00301 continue;
00302 }
00303
00304
00305 xstormy16_cgen_print_operand (cd, CGEN_SYNTAX_FIELD (*syn), info,
00306 fields, CGEN_INSN_ATTRS (insn), pc, length);
00307 }
00308 }
00309
00310
00311
00312
00313
00314 static int
00315 read_insn (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
00316 bfd_vma pc,
00317 disassemble_info *info,
00318 bfd_byte *buf,
00319 int buflen,
00320 CGEN_EXTRACT_INFO *ex_info,
00321 unsigned long *insn_value)
00322 {
00323 int status = (*info->read_memory_func) (pc, buf, buflen, info);
00324 if (status != 0)
00325 {
00326 (*info->memory_error_func) (status, pc, info);
00327 return -1;
00328 }
00329
00330 ex_info->dis_info = info;
00331 ex_info->valid = (1 << buflen) - 1;
00332 ex_info->insn_bytes = buf;
00333
00334 *insn_value = bfd_get_bits (buf, buflen * 8, info->endian == BFD_ENDIAN_BIG);
00335 return 0;
00336 }
00337
00338
00339
00340
00341
00342
00343
00344 static int
00345 print_insn (CGEN_CPU_DESC cd,
00346 bfd_vma pc,
00347 disassemble_info *info,
00348 bfd_byte *buf,
00349 unsigned int buflen)
00350 {
00351 CGEN_INSN_INT insn_value;
00352 const CGEN_INSN_LIST *insn_list;
00353 CGEN_EXTRACT_INFO ex_info;
00354 int basesize;
00355
00356
00357 basesize = cd->base_insn_bitsize < buflen * 8 ?
00358 cd->base_insn_bitsize : buflen * 8;
00359 insn_value = cgen_get_insn_value (cd, buf, basesize);
00360
00361
00362
00363
00364
00365 ex_info.valid = (1 << buflen) - 1;
00366 ex_info.dis_info = info;
00367 ex_info.insn_bytes = buf;
00368
00369
00370
00371
00372 insn_list = CGEN_DIS_LOOKUP_INSN (cd, (char *) buf, insn_value);
00373 while (insn_list != NULL)
00374 {
00375 const CGEN_INSN *insn = insn_list->insn;
00376 CGEN_FIELDS fields;
00377 int length;
00378 unsigned long insn_value_cropped;
00379
00380 #ifdef CGEN_VALIDATE_INSN_SUPPORTED
00381
00382
00383 if (! xstormy16_cgen_insn_supported (cd, insn))
00384 {
00385 insn_list = CGEN_DIS_NEXT_INSN (insn_list);
00386 continue;
00387 }
00388 #endif
00389
00390
00391
00392
00393
00394
00395
00396 if ((unsigned) (CGEN_INSN_BITSIZE (insn) / 8) < buflen &&
00397 (unsigned) (CGEN_INSN_BITSIZE (insn) / 8) <= sizeof (unsigned long))
00398 insn_value_cropped = bfd_get_bits (buf, CGEN_INSN_BITSIZE (insn),
00399 info->endian == BFD_ENDIAN_BIG);
00400 else
00401 insn_value_cropped = insn_value;
00402
00403 if ((insn_value_cropped & CGEN_INSN_BASE_MASK (insn))
00404 == CGEN_INSN_BASE_VALUE (insn))
00405 {
00406
00407
00408
00409
00410
00411
00412 if (((unsigned) CGEN_INSN_BITSIZE (insn) > cd->base_insn_bitsize) &&
00413 (unsigned) (CGEN_INSN_BITSIZE (insn) / 8) <= sizeof (unsigned long))
00414 {
00415 unsigned long full_insn_value;
00416 int rc = read_insn (cd, pc, info, buf,
00417 CGEN_INSN_BITSIZE (insn) / 8,
00418 & ex_info, & full_insn_value);
00419 if (rc != 0)
00420 return rc;
00421 length = CGEN_EXTRACT_FN (cd, insn)
00422 (cd, insn, &ex_info, full_insn_value, &fields, pc);
00423 }
00424 else
00425 length = CGEN_EXTRACT_FN (cd, insn)
00426 (cd, insn, &ex_info, insn_value_cropped, &fields, pc);
00427
00428
00429 if (length < 0)
00430 return length;
00431 if (length > 0)
00432 {
00433 CGEN_PRINT_FN (cd, insn) (cd, info, insn, &fields, pc, length);
00434
00435 return length / 8;
00436 }
00437 }
00438
00439 insn_list = CGEN_DIS_NEXT_INSN (insn_list);
00440 }
00441
00442 return 0;
00443 }
00444
00445
00446
00447
00448
00449 #ifndef CGEN_PRINT_INSN
00450 #define CGEN_PRINT_INSN default_print_insn
00451 #endif
00452
00453 static int
00454 default_print_insn (CGEN_CPU_DESC cd, bfd_vma pc, disassemble_info *info)
00455 {
00456 bfd_byte buf[CGEN_MAX_INSN_SIZE];
00457 int buflen;
00458 int status;
00459
00460
00461 buflen = cd->base_insn_bitsize / 8;
00462 status = (*info->read_memory_func) (pc, buf, buflen, info);
00463
00464
00465 if (status != 0 && (cd->min_insn_bitsize < cd->base_insn_bitsize))
00466 {
00467 buflen = cd->min_insn_bitsize / 8;
00468 status = (*info->read_memory_func) (pc, buf, buflen, info);
00469 }
00470
00471 if (status != 0)
00472 {
00473 (*info->memory_error_func) (status, pc, info);
00474 return -1;
00475 }
00476
00477 return print_insn (cd, pc, info, buf, buflen);
00478 }
00479
00480
00481
00482
00483
00484 typedef struct cpu_desc_list {
00485 struct cpu_desc_list *next;
00486 int isa;
00487 int mach;
00488 int endian;
00489 CGEN_CPU_DESC cd;
00490 } cpu_desc_list;
00491
00492 int
00493 print_insn_xstormy16 (bfd_vma pc, disassemble_info *info)
00494 {
00495 static cpu_desc_list *cd_list = 0;
00496 cpu_desc_list *cl = 0;
00497 static CGEN_CPU_DESC cd = 0;
00498 static int prev_isa;
00499 static int prev_mach;
00500 static int prev_endian;
00501 int length;
00502 int isa,mach;
00503 int endian = (info->endian == BFD_ENDIAN_BIG
00504 ? CGEN_ENDIAN_BIG
00505 : CGEN_ENDIAN_LITTLE);
00506 enum bfd_architecture arch;
00507
00508
00509 #ifndef CGEN_BFD_ARCH
00510 #define CGEN_BFD_ARCH bfd_arch_xstormy16
00511 #endif
00512 arch = info->arch;
00513 if (arch == bfd_arch_unknown)
00514 arch = CGEN_BFD_ARCH;
00515
00516
00517
00518 #ifdef CGEN_COMPUTE_MACH
00519 mach = CGEN_COMPUTE_MACH (info);
00520 #else
00521 mach = info->mach;
00522 #endif
00523
00524 #ifdef CGEN_COMPUTE_ISA
00525 isa = CGEN_COMPUTE_ISA (info);
00526 #else
00527 isa = info->insn_sets;
00528 #endif
00529
00530
00531 if (cd
00532 && (isa != prev_isa
00533 || mach != prev_mach
00534 || endian != prev_endian))
00535 {
00536 cd = 0;
00537 for (cl = cd_list; cl; cl = cl->next)
00538 {
00539 if (cl->isa == isa &&
00540 cl->mach == mach &&
00541 cl->endian == endian)
00542 {
00543 cd = cl->cd;
00544 break;
00545 }
00546 }
00547 }
00548
00549
00550 if (! cd)
00551 {
00552 const bfd_arch_info_type *arch_type = bfd_lookup_arch (arch, mach);
00553 const char *mach_name;
00554
00555 if (!arch_type)
00556 abort ();
00557 mach_name = arch_type->printable_name;
00558
00559 prev_isa = isa;
00560 prev_mach = mach;
00561 prev_endian = endian;
00562 cd = xstormy16_cgen_cpu_open (CGEN_CPU_OPEN_ISAS, prev_isa,
00563 CGEN_CPU_OPEN_BFDMACH, mach_name,
00564 CGEN_CPU_OPEN_ENDIAN, prev_endian,
00565 CGEN_CPU_OPEN_END);
00566 if (!cd)
00567 abort ();
00568
00569
00570 cl = xmalloc (sizeof (struct cpu_desc_list));
00571 cl->cd = cd;
00572 cl->isa = isa;
00573 cl->mach = mach;
00574 cl->endian = endian;
00575 cl->next = cd_list;
00576 cd_list = cl;
00577
00578 xstormy16_cgen_init_dis (cd);
00579 }
00580
00581
00582
00583
00584
00585
00586 length = CGEN_PRINT_INSN (cd, pc, info);
00587 if (length > 0)
00588 return length;
00589 if (length < 0)
00590 return -1;
00591
00592 (*info->fprintf_func) (info->stream, UNKNOWN_INSN_MSG);
00593 return cd->default_insn_bitsize / 8;
00594 }