1 /* Print National Semiconductor 32000 instructions. 2 Copyright (c) 1986, 88, 91, 92, 94, 95, 1998 Free Software Foundation, Inc. 3 4 This file is part of opcodes library. 5 6 This program is free software; you can redistribute it and/or modify 7 it under the terms of the GNU General Public License as published by 8 the Free Software Foundation; either version 2 of the License, or 9 (at your option) any later version. 10 11 This program is distributed in the hope that it will be useful, 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 GNU General Public License for more details. 15 16 You should have received a copy of the GNU General Public License 17 along with this program; if not, write to the Free Software 18 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ 19 20 21 #include "bfd.h" 22 #include "sysdep.h" 23 #include "dis-asm.h" 24 #if !defined(const) && !defined(__STDC__) 25 #define const 26 #endif 27 #include "opcode/ns32k.h" 28 #include "opintl.h" 29 30 static disassemble_info *dis_info; 31 32 /* 33 * Hacks to get it to compile <= READ THESE AS FIXES NEEDED 34 */ 35 #define INVALID_FLOAT(val, size) invalid_float((char *)val, size) 36 37 static int print_insn_arg 38 PARAMS ((int, int, int *, char *, bfd_vma, char *, int)); 39 static int get_displacement PARAMS ((char *, int *)); 40 static int invalid_float PARAMS ((char *, int)); 41 42 static long read_memory_integer(addr, nr) 43 unsigned char *addr; 44 int nr; 45 { 46 long val; 47 int i; 48 for (val = 0, i = nr - 1; i >= 0; i--) { 49 val = (val << 8); 50 val |= (0xff & *(addr + i)); 51 } 52 return val; 53 } 54 55 /* 32000 instructions are never longer than this. */ 56 #define MAXLEN 62 57 58 59 #include <setjmp.h> 60 61 struct private 62 { 63 /* Points to first byte not fetched. */ 64 bfd_byte *max_fetched; 65 bfd_byte the_buffer[MAXLEN]; 66 bfd_vma insn_start; 67 jmp_buf bailout; 68 }; 69 70 71 /* Make sure that bytes from INFO->PRIVATE_DATA->BUFFER (inclusive) 72 to ADDR (exclusive) are valid. Returns 1 for success, longjmps 73 on error. */ 74 #define FETCH_DATA(info, addr) \ 75 ((addr) <= ((struct private *)(info->private_data))->max_fetched \ 76 ? 1 : fetch_data ((info), (addr))) 77 78 static int 79 fetch_data (info, addr) 80 struct disassemble_info *info; 81 bfd_byte *addr; 82 { 83 int status; 84 struct private *priv = (struct private *)info->private_data; 85 bfd_vma start = priv->insn_start + (priv->max_fetched - priv->the_buffer); 86 87 status = (*info->read_memory_func) (start, 88 priv->max_fetched, 89 addr - priv->max_fetched, 90 info); 91 if (status != 0) 92 { 93 (*info->memory_error_func) (status, start, info); 94 longjmp (priv->bailout, 1); 95 } 96 else 97 priv->max_fetched = addr; 98 return 1; 99 } 100 /* Number of elements in the opcode table. */ 101 #define NOPCODES (sizeof ns32k_opcodes / sizeof ns32k_opcodes[0]) 102 103 #define NEXT_IS_ADDR '|' 104 105 106 struct ns32k_option { 107 char *pattern; /* the option itself */ 108 unsigned long value; /* binary value of the option */ 109 unsigned long match; /* these bits must match */ 110 }; 111 112 113 static const struct ns32k_option opt_u[]= /* restore, exit */ 114 { 115 { "r0", 0x80, 0x80 }, 116 { "r1", 0x40, 0x40 }, 117 { "r2", 0x20, 0x20 }, 118 { "r3", 0x10, 0x10 }, 119 { "r4", 0x08, 0x08 }, 120 { "r5", 0x04, 0x04 }, 121 { "r6", 0x02, 0x02 }, 122 { "r7", 0x01, 0x01 }, 123 { 0 , 0x00, 0x00 } 124 }; 125 126 static const struct ns32k_option opt_U[]= /* save, enter */ 127 { 128 { "r0", 0x01, 0x01 }, 129 { "r1", 0x02, 0x02 }, 130 { "r2", 0x04, 0x04 }, 131 { "r3", 0x08, 0x08 }, 132 { "r4", 0x10, 0x10 }, 133 { "r5", 0x20, 0x20 }, 134 { "r6", 0x40, 0x40 }, 135 { "r7", 0x80, 0x80 }, 136 { 0 , 0x00, 0x00 } 137 }; 138 139 static const struct ns32k_option opt_O[]= /* setcfg */ 140 { 141 { "c", 0x8, 0x8 }, 142 { "m", 0x4, 0x4 }, 143 { "f", 0x2, 0x2 }, 144 { "i", 0x1, 0x1 }, 145 { 0 , 0x0, 0x0 } 146 }; 147 148 static const struct ns32k_option opt_C[]= /* cinv */ 149 { 150 { "a", 0x4, 0x4 }, 151 { "i", 0x2, 0x2 }, 152 { "d", 0x1, 0x1 }, 153 { 0 , 0x0, 0x0 } 154 }; 155 156 static const struct ns32k_option opt_S[]= /* string inst */ 157 { 158 { "b", 0x1, 0x1 }, 159 { "u", 0x6, 0x6 }, 160 { "w", 0x2, 0x2 }, 161 { 0 , 0x0, 0x0 } 162 }; 163 164 static const struct ns32k_option list_P532[]= /* lpr spr */ 165 { 166 { "us", 0x0, 0xf }, 167 { "dcr", 0x1, 0xf }, 168 { "bpc", 0x2, 0xf }, 169 { "dsr", 0x3, 0xf }, 170 { "car", 0x4, 0xf }, 171 { "fp", 0x8, 0xf }, 172 { "sp", 0x9, 0xf }, 173 { "sb", 0xa, 0xf }, 174 { "usp", 0xb, 0xf }, 175 { "cfg", 0xc, 0xf }, 176 { "psr", 0xd, 0xf }, 177 { "intbase", 0xe, 0xf }, 178 { "mod", 0xf, 0xf }, 179 { 0 , 0x00, 0xf } 180 }; 181 182 static const struct ns32k_option list_M532[]= /* lmr smr */ 183 { 184 { "mcr", 0x9, 0xf }, 185 { "msr", 0xa, 0xf }, 186 { "tear", 0xb, 0xf }, 187 { "ptb0", 0xc, 0xf }, 188 { "ptb1", 0xd, 0xf }, 189 { "ivar0", 0xe, 0xf }, 190 { "ivar1", 0xf, 0xf }, 191 { 0 , 0x0, 0xf } 192 }; 193 194 static const struct ns32k_option list_P032[]= /* lpr spr */ 195 { 196 { "upsr", 0x0, 0xf }, 197 { "fp", 0x8, 0xf }, 198 { "sp", 0x9, 0xf }, 199 { "sb", 0xa, 0xf }, 200 { "psr", 0xb, 0xf }, 201 { "intbase", 0xe, 0xf }, 202 { "mod", 0xf, 0xf }, 203 { 0 , 0x0, 0xf } 204 }; 205 206 static const struct ns32k_option list_M032[]= /* lmr smr */ 207 { 208 { "bpr0", 0x0, 0xf }, 209 { "bpr1", 0x1, 0xf }, 210 { "pf0", 0x4, 0xf }, 211 { "pf1", 0x5, 0xf }, 212 { "sc", 0x8, 0xf }, 213 { "msr", 0xa, 0xf }, 214 { "bcnt", 0xb, 0xf }, 215 { "ptb0", 0xc, 0xf }, 216 { "ptb1", 0xd, 0xf }, 217 { "eia", 0xf, 0xf }, 218 { 0 , 0x0, 0xf } 219 }; 220 221 222 /* 223 * figure out which options are present 224 */ 225 static void 226 optlist(options, optionP, result) 227 int options; 228 const struct ns32k_option *optionP; 229 char *result; 230 { 231 if (options == 0) { 232 sprintf(result, "[]"); 233 return; 234 } 235 sprintf(result, "["); 236 237 for (; (options != 0) && optionP->pattern; optionP++) { 238 if ((options & optionP->match) == optionP->value) { 239 /* we found a match, update result and options */ 240 strcat(result, optionP->pattern); 241 options &= ~optionP->value; 242 if (options != 0) /* more options to come */ 243 strcat(result, ","); 244 } 245 } 246 if (options != 0) 247 strcat(result, "undefined"); 248 249 strcat(result, "]"); 250 } 251 252 static void 253 list_search (reg_value, optionP, result) 254 int reg_value; 255 const struct ns32k_option *optionP; 256 char *result; 257 { 258 for (; optionP->pattern; optionP++) { 259 if ((reg_value & optionP->match) == optionP->value) { 260 sprintf(result, "%s", optionP->pattern); 261 return; 262 } 263 } 264 sprintf(result, "undefined"); 265 } 266 267 /* 268 * extract "count" bits starting "offset" bits 269 * into buffer 270 */ 271 272 static int 273 bit_extract (buffer, offset, count) 274 bfd_byte *buffer; 275 int offset; 276 int count; 277 { 278 int result; 279 int bit; 280 281 buffer += offset >> 3; 282 offset &= 7; 283 bit = 1; 284 result = 0; 285 while (count--) 286 { 287 FETCH_DATA(dis_info, buffer + 1); 288 if ((*buffer & (1 << offset))) 289 result |= bit; 290 if (++offset == 8) 291 { 292 offset = 0; 293 buffer++; 294 } 295 bit <<= 1; 296 } 297 return result; 298 } 299 300 /* Like bit extract but the buffer is valid and doen't need to be 301 * fetched 302 */ 303 static int 304 bit_extract_simple (buffer, offset, count) 305 bfd_byte *buffer; 306 int offset; 307 int count; 308 { 309 int result; 310 int mask; 311 int bit; 312 313 buffer += offset >> 3; 314 offset &= 7; 315 bit = 1; 316 result = 0; 317 while (count--) 318 { 319 if ((*buffer & (1 << offset))) 320 result |= bit; 321 if (++offset == 8) 322 { 323 offset = 0; 324 buffer++; 325 } 326 bit <<= 1; 327 } 328 return result; 329 } 330 331 static void 332 bit_copy (buffer, offset, count, to) 333 char *buffer; 334 int offset; 335 int count; 336 char *to; 337 { 338 for(; count > 8; count -= 8, to++, offset += 8) 339 *to = bit_extract (buffer, offset, 8); 340 *to = bit_extract (buffer, offset, count); 341 } 342 343 344 static int 345 sign_extend (value, bits) 346 int value, bits; 347 { 348 value = value & ((1 << bits) - 1); 349 return (value & (1 << (bits-1)) 350 ? value | (~((1 << bits) - 1)) 351 : value); 352 } 353 354 static void 355 flip_bytes (ptr, count) 356 char *ptr; 357 int count; 358 { 359 char tmp; 360 361 while (count > 0) 362 { 363 tmp = ptr[0]; 364 ptr[0] = ptr[count-1]; 365 ptr[count-1] = tmp; 366 ptr++; 367 count -= 2; 368 } 369 } 370 371 /* Given a character C, does it represent a general addressing mode? */ 372 #define Is_gen(c) \ 373 ((c) == 'F' || (c) == 'L' || (c) == 'B' \ 374 || (c) == 'W' || (c) == 'D' || (c) == 'A' || (c) == 'I' || (c) == 'Z') 375 376 /* Adressing modes. */ 377 #define Adrmod_index_byte 0x1c 378 #define Adrmod_index_word 0x1d 379 #define Adrmod_index_doubleword 0x1e 380 #define Adrmod_index_quadword 0x1f 381 382 /* Is MODE an indexed addressing mode? */ 383 #define Adrmod_is_index(mode) \ 384 (mode == Adrmod_index_byte \ 385 || mode == Adrmod_index_word \ 386 || mode == Adrmod_index_doubleword \ 387 || mode == Adrmod_index_quadword) 388 389 390 /* Print the 32000 instruction at address MEMADDR in debugged memory, 391 on STREAM. Returns length of the instruction, in bytes. */ 392 393 int 394 print_insn_ns32k (memaddr, info) 395 bfd_vma memaddr; 396 disassemble_info *info; 397 { 398 register unsigned int i; 399 register char *d; 400 unsigned short first_word; 401 int ioffset; /* bits into instruction */ 402 int aoffset; /* bits into arguments */ 403 char arg_bufs[MAX_ARGS+1][ARG_LEN]; 404 int argnum; 405 int maxarg; 406 struct private priv; 407 bfd_byte *buffer = priv.the_buffer; 408 dis_info = info; 409 410 info->private_data = (PTR) &priv; 411 priv.max_fetched = priv.the_buffer; 412 priv.insn_start = memaddr; 413 if (setjmp (priv.bailout) != 0) 414 /* Error return. */ 415 return -1; 416 417 /* Look for 8bit opcodes first. Other wise, fetching two bytes could take 418 * us over the end of accessible data unnecessarilly 419 */ 420 FETCH_DATA(info, buffer + 1); 421 for (i = 0; i < NOPCODES; i++) 422 if (ns32k_opcodes[i].opcode_id_size <= 8 423 && ((buffer[0] 424 & (((unsigned long) 1 << ns32k_opcodes[i].opcode_id_size) - 1)) 425 == ns32k_opcodes[i].opcode_seed)) 426 break; 427 if (i == NOPCODES) { 428 /* Maybe it is 9 to 16 bits big */ 429 FETCH_DATA(info, buffer + 2); 430 first_word = read_memory_integer(buffer, 2); 431 432 for (i = 0; i < NOPCODES; i++) 433 if ((first_word 434 & (((unsigned long) 1 << ns32k_opcodes[i].opcode_id_size) - 1)) 435 == ns32k_opcodes[i].opcode_seed) 436 break; 437 438 /* Handle undefined instructions. */ 439 if (i == NOPCODES) 440 { 441 (*dis_info->fprintf_func)(dis_info->stream, "0%o", buffer[0]); 442 return 1; 443 } 444 } 445 446 (*dis_info->fprintf_func)(dis_info->stream, "%s", ns32k_opcodes[i].name); 447 448 ioffset = ns32k_opcodes[i].opcode_size; 449 aoffset = ns32k_opcodes[i].opcode_size; 450 d = ns32k_opcodes[i].operands; 451 452 if (*d) 453 { 454 /* Offset in bits of the first thing beyond each index byte. 455 Element 0 is for operand A and element 1 is for operand B. 456 The rest are irrelevant, but we put them here so we don't 457 index outside the array. */ 458 int index_offset[MAX_ARGS]; 459 460 /* 0 for operand A, 1 for operand B, greater for other args. */ 461 int whicharg = 0; 462 463 (*dis_info->fprintf_func)(dis_info->stream, "\t"); 464 465 maxarg = 0; 466 467 /* First we have to find and keep track of the index bytes, 468 if we are using scaled indexed addressing mode, since the index 469 bytes occur right after the basic instruction, not as part 470 of the addressing extension. */ 471 if (Is_gen(d[1])) 472 { 473 int addr_mode = bit_extract (buffer, ioffset - 5, 5); 474 475 if (Adrmod_is_index (addr_mode)) 476 { 477 aoffset += 8; 478 index_offset[0] = aoffset; 479 } 480 } 481 if (d[2] && Is_gen(d[3])) 482 { 483 int addr_mode = bit_extract (buffer, ioffset - 10, 5); 484 485 if (Adrmod_is_index (addr_mode)) 486 { 487 aoffset += 8; 488 index_offset[1] = aoffset; 489 } 490 } 491 492 while (*d) 493 { 494 argnum = *d - '1'; 495 d++; 496 if (argnum > maxarg && argnum < MAX_ARGS) 497 maxarg = argnum; 498 ioffset = print_insn_arg (*d, ioffset, &aoffset, buffer, 499 memaddr, arg_bufs[argnum], 500 index_offset[whicharg]); 501 d++; 502 whicharg++; 503 } 504 for (argnum = 0; argnum <= maxarg; argnum++) 505 { 506 bfd_vma addr; 507 char *ch; 508 for (ch = arg_bufs[argnum]; *ch;) 509 { 510 if (*ch == NEXT_IS_ADDR) 511 { 512 ++ch; 513 addr = bfd_scan_vma (ch, NULL, 16); 514 (*dis_info->print_address_func) (addr, dis_info); 515 while (*ch && *ch != NEXT_IS_ADDR) 516 ++ch; 517 if (*ch) 518 ++ch; 519 } 520 else 521 (*dis_info->fprintf_func)(dis_info->stream, "%c", *ch++); 522 } 523 if (argnum < maxarg) 524 (*dis_info->fprintf_func)(dis_info->stream, ", "); 525 } 526 } 527 return aoffset / 8; 528 } 529 530 /* Print an instruction operand of category given by d. IOFFSET is 531 the bit position below which small (<1 byte) parts of the operand can 532 be found (usually in the basic instruction, but for indexed 533 addressing it can be in the index byte). AOFFSETP is a pointer to the 534 bit position of the addressing extension. BUFFER contains the 535 instruction. ADDR is where BUFFER was read from. Put the disassembled 536 version of the operand in RESULT. INDEX_OFFSET is the bit position 537 of the index byte (it contains garbage if this operand is not a 538 general operand using scaled indexed addressing mode). */ 539 540 static int 541 print_insn_arg (d, ioffset, aoffsetp, buffer, addr, result, index_offset) 542 int d; 543 int ioffset, *aoffsetp; 544 char *buffer; 545 bfd_vma addr; 546 char *result; 547 int index_offset; 548 { 549 int addr_mode; 550 float Fvalue; 551 double Lvalue; 552 int Ivalue; 553 int disp1, disp2; 554 int index; 555 int size; 556 557 switch (d) 558 { 559 case 'f': 560 /* a "gen" operand but 5 bits from the end of instruction */ 561 ioffset -= 5; 562 case 'Z': 563 case 'F': 564 case 'L': 565 case 'I': 566 case 'B': 567 case 'W': 568 case 'D': 569 case 'A': 570 addr_mode = bit_extract (buffer, ioffset-5, 5); 571 ioffset -= 5; 572 switch (addr_mode) 573 { 574 case 0x0: case 0x1: case 0x2: case 0x3: 575 case 0x4: case 0x5: case 0x6: case 0x7: 576 /* register mode R0 -- R7 */ 577 switch (d) 578 { 579 case 'F': 580 case 'L': 581 case 'Z': 582 sprintf (result, "f%d", addr_mode); 583 break; 584 default: 585 sprintf (result, "r%d", addr_mode); 586 } 587 break; 588 case 0x8: case 0x9: case 0xa: case 0xb: 589 case 0xc: case 0xd: case 0xe: case 0xf: 590 /* Register relative disp(R0 -- R7) */ 591 disp1 = get_displacement (buffer, aoffsetp); 592 sprintf (result, "%d(r%d)", disp1, addr_mode & 7); 593 break; 594 case 0x10: 595 case 0x11: 596 case 0x12: 597 /* Memory relative disp2(disp1(FP, SP, SB)) */ 598 disp1 = get_displacement (buffer, aoffsetp); 599 disp2 = get_displacement (buffer, aoffsetp); 600 sprintf (result, "%d(%d(%s))", disp2, disp1, 601 addr_mode==0x10?"fp":addr_mode==0x11?"sp":"sb"); 602 break; 603 case 0x13: 604 /* reserved */ 605 sprintf (result, "reserved"); 606 break; 607 case 0x14: 608 /* Immediate */ 609 switch (d) 610 { 611 case 'I': case 'Z': case 'A': 612 /* I and Z are output operands and can`t be immediate 613 * A is an address and we can`t have the address of 614 * an immediate either. We don't know how much to increase 615 * aoffsetp by since whatever generated this is broken 616 * anyway! 617 */ 618 sprintf (result, _("$<undefined>")); 619 break; 620 case 'B': 621 Ivalue = bit_extract (buffer, *aoffsetp, 8); 622 Ivalue = sign_extend (Ivalue, 8); 623 *aoffsetp += 8; 624 sprintf (result, "$%d", Ivalue); 625 break; 626 case 'W': 627 Ivalue = bit_extract (buffer, *aoffsetp, 16); 628 flip_bytes (&Ivalue, 2); 629 *aoffsetp += 16; 630 Ivalue = sign_extend (Ivalue, 16); 631 sprintf (result, "$%d", Ivalue); 632 break; 633 case 'D': 634 Ivalue = bit_extract (buffer, *aoffsetp, 32); 635 flip_bytes (&Ivalue, 4); 636 *aoffsetp += 32; 637 sprintf (result, "$%d", Ivalue); 638 break; 639 case 'F': 640 bit_copy (buffer, *aoffsetp, 32, (char *) &Fvalue); 641 flip_bytes (&Fvalue, 4); 642 *aoffsetp += 32; 643 if (INVALID_FLOAT (&Fvalue, 4)) 644 sprintf (result, "<<invalid float 0x%.8x>>", *(int *) &Fvalue); 645 else /* assume host has ieee float */ 646 sprintf (result, "$%g", Fvalue); 647 break; 648 case 'L': 649 bit_copy (buffer, *aoffsetp, 64, (char *) &Lvalue); 650 flip_bytes (&Lvalue, 8); 651 *aoffsetp += 64; 652 if (INVALID_FLOAT (&Lvalue, 8)) 653 sprintf (result, "<<invalid long 0x%.8x%.8x>>", 654 *(((int *) &Lvalue) + 1), *(int *) &Lvalue); 655 else /* assume host has ieee float */ 656 sprintf (result, "$%g", Lvalue); 657 break; 658 } 659 break; 660 case 0x15: 661 /* Absolute @disp */ 662 disp1 = get_displacement (buffer, aoffsetp); 663 sprintf (result, "@|%d|", disp1); 664 break; 665 case 0x16: 666 /* External EXT(disp1) + disp2 (Mod table stuff) */ 667 disp1 = get_displacement (buffer, aoffsetp); 668 disp2 = get_displacement (buffer, aoffsetp); 669 sprintf (result, "EXT(%d) + %d", disp1, disp2); 670 break; 671 case 0x17: 672 /* Top of stack tos */ 673 sprintf (result, "tos"); 674 break; 675 case 0x18: 676 /* Memory space disp(FP) */ 677 disp1 = get_displacement (buffer, aoffsetp); 678 sprintf (result, "%d(fp)", disp1); 679 break; 680 case 0x19: 681 /* Memory space disp(SP) */ 682 disp1 = get_displacement (buffer, aoffsetp); 683 sprintf (result, "%d(sp)", disp1); 684 break; 685 case 0x1a: 686 /* Memory space disp(SB) */ 687 disp1 = get_displacement (buffer, aoffsetp); 688 sprintf (result, "%d(sb)", disp1); 689 break; 690 case 0x1b: 691 /* Memory space disp(PC) */ 692 disp1 = get_displacement (buffer, aoffsetp); 693 *result++ = NEXT_IS_ADDR; 694 sprintf_vma (result, addr + disp1); 695 result += strlen (result); 696 *result++ = NEXT_IS_ADDR; 697 *result = '\0'; 698 break; 699 case 0x1c: 700 case 0x1d: 701 case 0x1e: 702 case 0x1f: 703 /* Scaled index basemode[R0 -- R7:B,W,D,Q] */ 704 index = bit_extract (buffer, index_offset - 8, 3); 705 print_insn_arg (d, index_offset, aoffsetp, buffer, addr, 706 result, 0); 707 { 708 static const char *ind = "bwdq"; 709 char *off; 710 711 off = result + strlen (result); 712 sprintf (off, "[r%d:%c]", index, 713 ind[addr_mode & 3]); 714 } 715 break; 716 } 717 break; 718 case 'H': 719 case 'q': 720 Ivalue = bit_extract (buffer, ioffset-4, 4); 721 Ivalue = sign_extend (Ivalue, 4); 722 sprintf (result, "%d", Ivalue); 723 ioffset -= 4; 724 break; 725 case 'r': 726 Ivalue = bit_extract (buffer, ioffset-3, 3); 727 sprintf (result, "r%d", Ivalue&7); 728 ioffset -= 3; 729 break; 730 case 'd': 731 sprintf (result, "%d", get_displacement (buffer, aoffsetp)); 732 break; 733 case 'b': 734 Ivalue = get_displacement (buffer, aoffsetp); 735 /* 736 * Warning!! HACK ALERT! 737 * Operand type 'b' is only used by the cmp{b,w,d} and 738 * movm{b,w,d} instructions; we need to know whether 739 * it's a `b' or `w' or `d' instruction; and for both 740 * cmpm and movm it's stored at the same place so we 741 * just grab two bits of the opcode and look at it... 742 * 743 */ 744 size = bit_extract(buffer, ioffset-6, 2); 745 if (size == 0) /* 00 => b */ 746 size = 1; 747 else if (size == 1) /* 01 => w */ 748 size = 2; 749 else 750 size = 4; /* 11 => d */ 751 752 sprintf (result, "%d", (Ivalue / size) + 1); 753 break; 754 case 'p': 755 *result++ = NEXT_IS_ADDR; 756 sprintf_vma (result, addr + get_displacement (buffer, aoffsetp)); 757 result += strlen (result); 758 *result++ = NEXT_IS_ADDR; 759 *result = '\0'; 760 break; 761 case 'i': 762 Ivalue = bit_extract (buffer, *aoffsetp, 8); 763 *aoffsetp += 8; 764 sprintf (result, "0x%x", Ivalue); 765 break; 766 case 'u': 767 Ivalue = bit_extract (buffer, *aoffsetp, 8); 768 optlist(Ivalue, opt_u, result); 769 *aoffsetp += 8; 770 break; 771 case 'U': 772 Ivalue = bit_extract(buffer, *aoffsetp, 8); 773 optlist(Ivalue, opt_U, result); 774 *aoffsetp += 8; 775 break; 776 case 'O': 777 Ivalue = bit_extract(buffer, ioffset-9, 9); 778 optlist(Ivalue, opt_O, result); 779 ioffset -= 9; 780 break; 781 case 'C': 782 Ivalue = bit_extract(buffer, ioffset-4, 4); 783 optlist(Ivalue, opt_C, result); 784 ioffset -= 4; 785 break; 786 case 'S': 787 Ivalue = bit_extract(buffer, ioffset - 8, 8); 788 optlist(Ivalue, opt_S, result); 789 ioffset -= 8; 790 break; 791 case 'M': 792 Ivalue = bit_extract(buffer, ioffset-4, 4); 793 list_search(Ivalue, 0 ? list_M032 : list_M532, result); 794 ioffset -= 4; 795 break; 796 case 'P': 797 Ivalue = bit_extract(buffer, ioffset-4, 4); 798 list_search(Ivalue, 0 ? list_P032 : list_P532, result); 799 ioffset -= 4; 800 break; 801 case 'g': 802 Ivalue = bit_extract(buffer, *aoffsetp, 3); 803 sprintf(result, "%d", Ivalue); 804 *aoffsetp += 3; 805 break; 806 case 'G': 807 Ivalue = bit_extract(buffer, *aoffsetp, 5); 808 sprintf(result, "%d", Ivalue + 1); 809 *aoffsetp += 5; 810 break; 811 } 812 return ioffset; 813 } 814 815 static int 816 get_displacement (buffer, aoffsetp) 817 char *buffer; 818 int *aoffsetp; 819 { 820 int Ivalue; 821 short Ivalue2; 822 823 Ivalue = bit_extract (buffer, *aoffsetp, 8); 824 switch (Ivalue & 0xc0) 825 { 826 case 0x00: 827 case 0x40: 828 Ivalue = sign_extend (Ivalue, 7); 829 *aoffsetp += 8; 830 break; 831 case 0x80: 832 Ivalue2 = bit_extract (buffer, *aoffsetp, 16); 833 flip_bytes (&Ivalue2, 2); 834 Ivalue = sign_extend (Ivalue2, 14); 835 *aoffsetp += 16; 836 break; 837 case 0xc0: 838 Ivalue = bit_extract (buffer, *aoffsetp, 32); 839 flip_bytes (&Ivalue, 4); 840 Ivalue = sign_extend (Ivalue, 30); 841 *aoffsetp += 32; 842 break; 843 } 844 return Ivalue; 845 } 846 847 848 #if 1 /* a version that should work on ns32k f's&d's on any machine */ 849 static int 850 invalid_float (p, len) 851 register char *p; 852 register int len; 853 { 854 register int val; 855 856 if ( len == 4 ) 857 val = (bit_extract_simple(p, 23, 8)/*exponent*/ == 0xff 858 || (bit_extract_simple(p, 23, 8)/*exponent*/ == 0 && 859 bit_extract_simple(p, 0, 23)/*mantisa*/ != 0)); 860 else if ( len == 8 ) 861 val = (bit_extract_simple(p, 52, 11)/*exponent*/ == 0x7ff 862 || (bit_extract_simple(p, 52, 11)/*exponent*/ == 0 863 && (bit_extract_simple(p, 0, 32)/*low mantisa*/ != 0 864 || bit_extract_simple(p, 32, 20)/*high mantisa*/ != 0))); 865 else 866 val = 1; 867 return (val); 868 } 869 #else 870 871 /* assumes the bytes have been swapped to local order */ 872 typedef union { double d; 873 float f; 874 struct { unsigned m:23, e:8, :1;} sf; 875 struct { unsigned lm; unsigned m:20, e:11, :1;} sd; 876 } float_type_u; 877 878 static int 879 invalid_float (p, len) 880 register float_type_u *p; 881 register int len; 882 { 883 register int val; 884 if ( len == sizeof (float) ) 885 val = (p->sf.e == 0xff 886 || (p->sf.e == 0 && p->sf.m != 0)); 887 else if ( len == sizeof (double) ) 888 val = (p->sd.e == 0x7ff 889 || (p->sd.e == 0 && (p->sd.m != 0 || p->sd.lm != 0))); 890 else 891 val = 1; 892 return (val); 893 } 894 #endif 895