ns32k-dis.c
来自「基于4个mips核的noc设计」· C语言 代码 · 共 896 行 · 第 1/2 页
C
896 行
ioffset = ns32k_opcodes[i].opcode_size; aoffset = ns32k_opcodes[i].opcode_size; d = ns32k_opcodes[i].operands; if (*d) { /* Offset in bits of the first thing beyond each index byte. Element 0 is for operand A and element 1 is for operand B. The rest are irrelevant, but we put them here so we don't index outside the array. */ int index_offset[MAX_ARGS]; /* 0 for operand A, 1 for operand B, greater for other args. */ int whicharg = 0; (*dis_info->fprintf_func)(dis_info->stream, "\t"); maxarg = 0; /* First we have to find and keep track of the index bytes, if we are using scaled indexed addressing mode, since the index bytes occur right after the basic instruction, not as part of the addressing extension. */ if (Is_gen(d[1])) { int addr_mode = bit_extract (buffer, ioffset - 5, 5); if (Adrmod_is_index (addr_mode)) { aoffset += 8; index_offset[0] = aoffset; } } if (d[2] && Is_gen(d[3])) { int addr_mode = bit_extract (buffer, ioffset - 10, 5); if (Adrmod_is_index (addr_mode)) { aoffset += 8; index_offset[1] = aoffset; } } while (*d) { argnum = *d - '1'; d++; if (argnum > maxarg && argnum < MAX_ARGS) maxarg = argnum; ioffset = print_insn_arg (*d, ioffset, &aoffset, buffer, memaddr, arg_bufs[argnum], index_offset[whicharg]); d++; whicharg++; } for (argnum = 0; argnum <= maxarg; argnum++) { bfd_vma addr; char *ch; for (ch = arg_bufs[argnum]; *ch;) { if (*ch == NEXT_IS_ADDR) { ++ch; addr = bfd_scan_vma (ch, NULL, 16); (*dis_info->print_address_func) (addr, dis_info); while (*ch && *ch != NEXT_IS_ADDR) ++ch; if (*ch) ++ch; } else (*dis_info->fprintf_func)(dis_info->stream, "%c", *ch++); } if (argnum < maxarg) (*dis_info->fprintf_func)(dis_info->stream, ", "); } } return aoffset / 8;}/* Print an instruction operand of category given by d. IOFFSET is the bit position below which small (<1 byte) parts of the operand can be found (usually in the basic instruction, but for indexed addressing it can be in the index byte). AOFFSETP is a pointer to the bit position of the addressing extension. BUFFER contains the instruction. ADDR is where BUFFER was read from. Put the disassembled version of the operand in RESULT. INDEX_OFFSET is the bit position of the index byte (it contains garbage if this operand is not a general operand using scaled indexed addressing mode). */static intprint_insn_arg (d, ioffset, aoffsetp, buffer, addr, result, index_offset) int d; int ioffset, *aoffsetp; char *buffer; bfd_vma addr; char *result; int index_offset;{ int addr_mode; float Fvalue; double Lvalue; int Ivalue; int disp1, disp2; int index; int size; switch (d) { case 'f': /* a "gen" operand but 5 bits from the end of instruction */ ioffset -= 5; case 'Z': case 'F': case 'L': case 'I': case 'B': case 'W': case 'D': case 'A': addr_mode = bit_extract (buffer, ioffset-5, 5); ioffset -= 5; switch (addr_mode) { case 0x0: case 0x1: case 0x2: case 0x3: case 0x4: case 0x5: case 0x6: case 0x7: /* register mode R0 -- R7 */ switch (d) { case 'F': case 'L': case 'Z': sprintf (result, "f%d", addr_mode); break; default: sprintf (result, "r%d", addr_mode); } break; case 0x8: case 0x9: case 0xa: case 0xb: case 0xc: case 0xd: case 0xe: case 0xf: /* Register relative disp(R0 -- R7) */ disp1 = get_displacement (buffer, aoffsetp); sprintf (result, "%d(r%d)", disp1, addr_mode & 7); break; case 0x10: case 0x11: case 0x12: /* Memory relative disp2(disp1(FP, SP, SB)) */ disp1 = get_displacement (buffer, aoffsetp); disp2 = get_displacement (buffer, aoffsetp); sprintf (result, "%d(%d(%s))", disp2, disp1, addr_mode==0x10?"fp":addr_mode==0x11?"sp":"sb"); break; case 0x13: /* reserved */ sprintf (result, "reserved"); break; case 0x14: /* Immediate */ switch (d) { case 'I': case 'Z': case 'A': /* I and Z are output operands and can`t be immediate * A is an address and we can`t have the address of * an immediate either. We don't know how much to increase * aoffsetp by since whatever generated this is broken * anyway! */ sprintf (result, _("$<undefined>")); break; case 'B': Ivalue = bit_extract (buffer, *aoffsetp, 8); Ivalue = sign_extend (Ivalue, 8); *aoffsetp += 8; sprintf (result, "$%d", Ivalue); break; case 'W': Ivalue = bit_extract (buffer, *aoffsetp, 16); flip_bytes (&Ivalue, 2); *aoffsetp += 16; Ivalue = sign_extend (Ivalue, 16); sprintf (result, "$%d", Ivalue); break; case 'D': Ivalue = bit_extract (buffer, *aoffsetp, 32); flip_bytes (&Ivalue, 4); *aoffsetp += 32; sprintf (result, "$%d", Ivalue); break; case 'F': bit_copy (buffer, *aoffsetp, 32, (char *) &Fvalue); flip_bytes (&Fvalue, 4); *aoffsetp += 32; if (INVALID_FLOAT (&Fvalue, 4)) sprintf (result, "<<invalid float 0x%.8x>>", *(int *) &Fvalue); else /* assume host has ieee float */ sprintf (result, "$%g", Fvalue); break; case 'L': bit_copy (buffer, *aoffsetp, 64, (char *) &Lvalue); flip_bytes (&Lvalue, 8); *aoffsetp += 64; if (INVALID_FLOAT (&Lvalue, 8)) sprintf (result, "<<invalid long 0x%.8x%.8x>>", *(((int *) &Lvalue) + 1), *(int *) &Lvalue); else /* assume host has ieee float */ sprintf (result, "$%g", Lvalue); break; } break; case 0x15: /* Absolute @disp */ disp1 = get_displacement (buffer, aoffsetp); sprintf (result, "@|%d|", disp1); break; case 0x16: /* External EXT(disp1) + disp2 (Mod table stuff) */ disp1 = get_displacement (buffer, aoffsetp); disp2 = get_displacement (buffer, aoffsetp); sprintf (result, "EXT(%d) + %d", disp1, disp2); break; case 0x17: /* Top of stack tos */ sprintf (result, "tos"); break; case 0x18: /* Memory space disp(FP) */ disp1 = get_displacement (buffer, aoffsetp); sprintf (result, "%d(fp)", disp1); break; case 0x19: /* Memory space disp(SP) */ disp1 = get_displacement (buffer, aoffsetp); sprintf (result, "%d(sp)", disp1); break; case 0x1a: /* Memory space disp(SB) */ disp1 = get_displacement (buffer, aoffsetp); sprintf (result, "%d(sb)", disp1); break; case 0x1b: /* Memory space disp(PC) */ disp1 = get_displacement (buffer, aoffsetp); *result++ = NEXT_IS_ADDR; sprintf_vma (result, addr + disp1); result += strlen (result); *result++ = NEXT_IS_ADDR; *result = '\0'; break; case 0x1c: case 0x1d: case 0x1e: case 0x1f: /* Scaled index basemode[R0 -- R7:B,W,D,Q] */ index = bit_extract (buffer, index_offset - 8, 3); print_insn_arg (d, index_offset, aoffsetp, buffer, addr, result, 0); { static const char *ind = "bwdq"; char *off; off = result + strlen (result); sprintf (off, "[r%d:%c]", index, ind[addr_mode & 3]); } break; } break; case 'H': case 'q': Ivalue = bit_extract (buffer, ioffset-4, 4); Ivalue = sign_extend (Ivalue, 4); sprintf (result, "%d", Ivalue); ioffset -= 4; break; case 'r': Ivalue = bit_extract (buffer, ioffset-3, 3); sprintf (result, "r%d", Ivalue&7); ioffset -= 3; break; case 'd': sprintf (result, "%d", get_displacement (buffer, aoffsetp)); break; case 'b': Ivalue = get_displacement (buffer, aoffsetp); /* * Warning!! HACK ALERT! * Operand type 'b' is only used by the cmp{b,w,d} and * movm{b,w,d} instructions; we need to know whether * it's a `b' or `w' or `d' instruction; and for both * cmpm and movm it's stored at the same place so we * just grab two bits of the opcode and look at it... * */ size = bit_extract(buffer, ioffset-6, 2); if (size == 0) /* 00 => b */ size = 1; else if (size == 1) /* 01 => w */ size = 2; else size = 4; /* 11 => d */ sprintf (result, "%d", (Ivalue / size) + 1); break; case 'p': *result++ = NEXT_IS_ADDR; sprintf_vma (result, addr + get_displacement (buffer, aoffsetp)); result += strlen (result); *result++ = NEXT_IS_ADDR; *result = '\0'; break; case 'i': Ivalue = bit_extract (buffer, *aoffsetp, 8); *aoffsetp += 8; sprintf (result, "0x%x", Ivalue); break; case 'u': Ivalue = bit_extract (buffer, *aoffsetp, 8); optlist(Ivalue, opt_u, result); *aoffsetp += 8; break; case 'U': Ivalue = bit_extract(buffer, *aoffsetp, 8); optlist(Ivalue, opt_U, result); *aoffsetp += 8; break; case 'O': Ivalue = bit_extract(buffer, ioffset-9, 9); optlist(Ivalue, opt_O, result); ioffset -= 9; break; case 'C': Ivalue = bit_extract(buffer, ioffset-4, 4); optlist(Ivalue, opt_C, result); ioffset -= 4; break; case 'S': Ivalue = bit_extract(buffer, ioffset - 8, 8); optlist(Ivalue, opt_S, result); ioffset -= 8; break; case 'M': Ivalue = bit_extract(buffer, ioffset-4, 4); list_search(Ivalue, 0 ? list_M032 : list_M532, result); ioffset -= 4; break; case 'P': Ivalue = bit_extract(buffer, ioffset-4, 4); list_search(Ivalue, 0 ? list_P032 : list_P532, result); ioffset -= 4; break; case 'g': Ivalue = bit_extract(buffer, *aoffsetp, 3); sprintf(result, "%d", Ivalue); *aoffsetp += 3; break; case 'G': Ivalue = bit_extract(buffer, *aoffsetp, 5); sprintf(result, "%d", Ivalue + 1); *aoffsetp += 5; break; } return ioffset;}static intget_displacement (buffer, aoffsetp) char *buffer; int *aoffsetp;{ int Ivalue; short Ivalue2; Ivalue = bit_extract (buffer, *aoffsetp, 8); switch (Ivalue & 0xc0) { case 0x00: case 0x40: Ivalue = sign_extend (Ivalue, 7); *aoffsetp += 8; break; case 0x80: Ivalue2 = bit_extract (buffer, *aoffsetp, 16); flip_bytes (&Ivalue2, 2); Ivalue = sign_extend (Ivalue2, 14); *aoffsetp += 16; break; case 0xc0: Ivalue = bit_extract (buffer, *aoffsetp, 32); flip_bytes (&Ivalue, 4); Ivalue = sign_extend (Ivalue, 30); *aoffsetp += 32; break; } return Ivalue;}#if 1 /* a version that should work on ns32k f's&d's on any machine */static intinvalid_float (p, len) register char *p; register int len;{ register int val; if ( len == 4 ) val = (bit_extract_simple(p, 23, 8)/*exponent*/ == 0xff || (bit_extract_simple(p, 23, 8)/*exponent*/ == 0 && bit_extract_simple(p, 0, 23)/*mantisa*/ != 0)); else if ( len == 8 ) val = (bit_extract_simple(p, 52, 11)/*exponent*/ == 0x7ff || (bit_extract_simple(p, 52, 11)/*exponent*/ == 0 && (bit_extract_simple(p, 0, 32)/*low mantisa*/ != 0 || bit_extract_simple(p, 32, 20)/*high mantisa*/ != 0))); else val = 1; return (val);}#else/* assumes the bytes have been swapped to local order */typedef union { double d; float f; struct { unsigned m:23, e:8, :1;} sf; struct { unsigned lm; unsigned m:20, e:11, :1;} sd; } float_type_u;static intinvalid_float (p, len) register float_type_u *p; register int len;{ register int val; if ( len == sizeof (float) ) val = (p->sf.e == 0xff || (p->sf.e == 0 && p->sf.m != 0)); else if ( len == sizeof (double) ) val = (p->sd.e == 0x7ff || (p->sd.e == 0 && (p->sd.m != 0 || p->sd.lm != 0))); else val = 1; return (val);}#endif
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?