static int dis_tcc(uint32_t *pc, uint32_t inst) { char *tcc[0x10] = { "tn", "te", "tle", "tl", "tleu", "tcs", "tneg", "tvs", "ta", "tne", "tg", "tge", "tgu", "tcc", "tpos", "tvc" }; (void)printf("%p:\t%s%s\t%s, ", (void *)pc, HT(inst) ? "h" : "", tcc[COND(inst)], TCC(inst) ? "%xcc" : "%icc"); if (IMM(inst)) (void)printf("0x%x\n", SWTRAP(inst)); else (void)printf("%s\n", sregs[RS2(inst)]); return OK; }
static int dis_wrpr(uint32_t *pc, uint32_t inst) { char *prs[] = { "%tpc", "%tnpc", "%tstate", "%tt", "%tick", "%tba", "%pstate", "%tl", "%pil", "%cwp", "%cansave", "%canrestore", "%cleanwin", "%otherwin", "%wstate", "%fq", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-" }; if (RD(inst) >= 15) { ILLEGAL; } (void)printf("%p:\twrpr\t%s,%s, ", (void *)pc, prs[RD(inst)], sregs[RS1(inst)]); if (IMM(inst)) (void)printf("%ld, ", SIMM13(inst)); else (void)printf("%s, ", sregs[RS2(inst)]); (void)printf("%s\n", sregs[RD(inst)]); return OK; }
static int dis_class3(uint32_t *pc, uint32_t inst) { int op3 = OP3(inst); char *opc[0x40] = { "lduw", "ldub", "lduh", "ldd", "stw", "stb", "sth", "std", "ldsw", "ldsb", "ldsh", "ldx", "-", "ldstub", "stx", "swap", "lduwa", "lduba", "lduha", "ldda", "stwa", "stba", "stha", "stda", "ldswa", "ldsba", "ldsha", "ldxa", "-", "ldstuba", "stxa", "swapa", "ldf", "ldfsr", "ldqf", "lddf" "stf", "stfsr", "stqf", "stdf", "-", "-", "-", "-", "-", "prefetch", "-", "-", "ldfa", "-", "ldqfa", "lddfa", "stfa", "-", "stqfa", "stdfa", "-", "-", "-", "-", "casa", "prefetcha", "casxa", "-" }; switch(op3) { case 0x0c: case 0x1c: case 0x28: case 0x29: case 0x2a: case 0x2b: case 0x2c: case 0x2e: case 0x31: case 0x35: case 0x38: case 0x39: case 0x3a: case 0x3b: case 0x3f: ILLEGAL; case 0x00: /* LDUW */ case 0x01: /* LDUB */ case 0x02: /* LDUH */ case 0x03: /* LDD */ case 0x08: /* LDSW */ case 0x09: /* LDSB */ case 0x0a: /* LDSH */ case 0x0b: /* LDX */ case 0x0d: /* LDSTUB */ case 0x1f: /* SWAP */ (void)printf("%p:\t%s\t[%s + ", (void *)pc, opc[op3], sregs[RS1(inst)]); if (IMM(inst)) (void)printf("%ld], ", SIMM13(inst)); else (void)printf("%s], ", sregs[RS2(inst)]); (void)printf("%s\n", sregs[RD(inst)]); return OK; case 0x04: /* STW */ case 0x05: /* STB */ case 0x06: /* STH */ case 0x07: /* STD */ case 0x0e: /* STX */ (void)printf("%p:\t%s\t%s, ", (void *)pc, opc[op3], sregs[RD(inst)]); (void)printf("[%s + ", sregs[RS1(inst)]); if (IMM(inst)) (void)printf("%ld]\n", SIMM13(inst)); else (void)printf("%s]\n", sregs[RS2(inst)]); return OK; case 0x10: /* LDUWA */ case 0x11: /* LDUBA */ case 0x12: /* LDUHA */ case 0x13: /* LDDA */ case 0x18: /* LDSWA */ case 0x19: /* LDSBA */ case 0x1a: /* LDSHA */ case 0x1b: /* LDXA */ case 0x1d: /* LDSTUBA */ case 0x2f: /* SWAPA */ case 0x3c: /* CASA */ case 0x3e: /* CASXA */ (void)printf("%p:\t%s\t[%s + ", (void *)pc, opc[op3], sregs[RS1(inst)]); if (IMM(inst)) (void)printf("%ld] %%asi, ", SIMM13(inst)); else (void)printf("%s] 0x%x, ", sregs[RS2(inst)], IMMASI(inst)); (void)printf("%s\n", sregs[RD(inst)]); return OK; case 0x14: /* STWA */ case 0x15: /* STBA */ case 0x16: /* STHA */ case 0x17: /* STDA */ case 0x1e: /* STXA */ (void)printf("%p:\t%s\t%s, ", (void *)pc, opc[op3], sregs[RD(inst)]); (void)printf("[%s + ", sregs[RS1(inst)]); if (IMM(inst)) (void)printf("%ld] %%asi\n", SIMM13(inst)); else (void)printf("%s] 0x%x\n", sregs[RS2(inst)], IMMASI(inst)); return OK; case 0x2d: /* PREFETCH */ if ((RD(inst) >=5) && (RD(inst) <= 15)) { ILLEGAL; } (void)printf("%p:\t%s\t[%s + ", (void *)pc, opc[op3], sregs[RS1(inst)]); if (IMM(inst)) (void)printf("%ld], ", SIMM13(inst)); else (void)printf("%s], ", sregs[RS2(inst)]); (void)printf("%d\n", RD(inst)); return OK; case 0x3d: /* PREFETCHA */ if ((RD(inst) >=5) && (RD(inst) <= 15)) { ILLEGAL; } (void)printf("%p:\t%s\t[%s + ", (void *)pc, opc[op3], sregs[RS1(inst)]); if (IMM(inst)) (void)printf("%ld] %%asi, ", SIMM13(inst)); else (void)printf("%s] 0x%x, ", sregs[RS2(inst)], IMMASI(inst)); (void)printf("%d\n", RD(inst)); return OK; case 0x20: case 0x21: case 0x22: case 0x23: case 0x30: case 0x32: case 0x33: (void)printf("XXXX %p:\tLDF XXX op3=%x\n", (void *)pc, OP3(inst)); return ERR; case 0x24: case 0x25: case 0x26: case 0x27: case 0x34: case 0x36: case 0x37: (void)printf("XXXX %p:\tSTF XXX op3=%x\n", (void *)pc, OP3(inst)); return ERR; default: (void)printf("XXXX dis_class3 op3=%x\n", OP3(inst)); return ERR; } }
static int dis_wrasr(uint32_t *pc, uint32_t inst) { char *asrs[] = { "wry", "-", "wrccr", "wrasi", "wrtick", "-", "wrfprs", "-", "-", "-", "-", "-", "-", "-", "-", "sir", }; if ((RD(inst) == 0xf) && (RS1(inst) != 0) && (IMM(inst) == 0)) { ILLEGAL; } switch(RD(inst)) { case 0x01: ILLEGAL; case 0x0f: /* SIR */ case 0x00: /* WRY */ case 0x02: /* WRCCR */ case 0x03: /* WRASI */ case 0x06: /* WRFPRS */ (void)printf("%p:\t%s\t%s,", (void *)pc, asrs[RD(inst)], sregs[RS1(inst)]); if (IMM(inst)) (void)printf("%ld, ", SIMM13(inst)); else (void)printf("%s, ", sregs[RS2(inst)]); (void)printf("\n"); return OK; case 0x04: case 0x05: case 0x07: case 0x08: case 0x09: case 0x0a: case 0x0b: case 0x0c: case 0x0d: case 0x0e: ILLEGAL; case 0x10: case 0x11: case 0x12: case 0x13: case 0x14: case 0x15: case 0x16: case 0x17: case 0x18: case 0x19: case 0x1a: case 0x1b: case 0x1c: case 0x1d: case 0x1e: case 0x1f: (void)printf("%p:\twr\t%s, ", (void *)pc, sregs[RS1(inst)]); if (IMM(inst)) (void)printf("%ld, ", SIMM13(inst)); else (void)printf("%s, ", sregs[RS2(inst)]); (void)printf("%%asr%d\n", RD(inst)); return ERR; default: (void)printf("XXXX wrasr %d\n", RD(inst)); return ERR; } }
static int dis_class2(uint32_t *pc, uint32_t inst) { int op3 = OP3(inst); char *opc[] = { "add", "and", "or", "xor", "sub", "andn", "orn", "xnor", "addc", "mulx", "umul", "smul", "subc", "udivx", "udiv", "sdiv", "addcc", "andcc", "orcc", "xorcc", "subcc", "andncc", "orncc", "xnorcc", "addccc", "-", "umulcc", "smulcc", "subccc", "-", "udivcc", "sdivcc", "taddcc", "tsubcc", "taddcctv", "tsubcctv", "mulscc", "sll", "srl", "sra", "rdy", "-", "rdpr", "flushw", "movcc", "sdivx", "popc", "movr", "wry", "saved", "wrpr", "-", "fpop1", "fpop2", "impldep1", "impldep2", "jmpl", "return", "tcc", "flush", "save", "restore", "done", "-" }; switch(op3) { case 0x00: /* ADD */ case 0x01: /* AND */ case 0x02: /* OR */ case 0x03: /* XOR */ case 0x04: /* SUB */ case 0x05: /* ANDN */ case 0x06: /* ORN */ case 0x07: /* XNOR */ case 0x08: /* ADDC */ case 0x09: /* MULX */ case 0x0a: /* UMUL */ case 0x0b: /* SMUL */ case 0x0c: /* SUBC */ case 0x0d: /* UDIVX */ case 0x0e: /* UDIV */ case 0x0f: /* SDIV */ case 0x10: /* ADDcc */ case 0x11: /* ANDcc */ case 0x12: /* ORcc */ case 0x13: /* XORcc */ case 0x14: /* SUBcc */ case 0x15: /* ANDNcc */ case 0x16: /* ORNcc */ case 0x17: /* XNORcc */ case 0x18: /* ANDCcc */ case 0x1a: /* UMULcc */ case 0x1b: /* SMULcc */ case 0x1c: /* SUBCcc */ case 0x1e: /* UDIVcc */ case 0x1f: /* SDIVcc */ case 0x20: /* TADDcc */ case 0x21: /* TSUBcc */ case 0x22: /* TADDccTV */ case 0x23: /* TSUBccTV */ case 0x24: /* MULScc */ case 0x2c: /* MOVcc */ case 0x2d: /* SDIVX */ case 0x2f: /* MOVr */ case 0x38: /* JMPL */ case 0x3c: /* SAVE */ case 0x3d: /* RESTORE */ (void)printf("%p:\t%s\t%s, ", (void *)pc, opc[op3], sregs[RS1(inst)]); if (IMM(inst)) (void)printf("%ld, ", SIMM13(inst)); else (void)printf("%s, ", sregs[RS2(inst)]); (void)printf("%s\n", sregs[RD(inst)]); return (op3 == 0x38) ? DELAY : OK; case 0x2b: /* FLUSHW */ if ((RD(inst) == 0) && (RS1(inst) == 0) && (IMM(inst) == 0) && (SIMM13(inst) == 0)) { (void)printf("%p:\t%s\n", (void *)pc, opc[op3]); return OK; } ILLEGAL; case 0x39: /* RETURN */ case 0x3b: /* FLUSH */ if (RD(inst)) { ILLEGAL; } (void)printf("%p:\t%s\t%s + ", (void *)pc, opc[op3], sregs[RS1(inst)]); if (IMM(inst)) (void)printf("%ld\n", SIMM13(inst)); else (void)printf("%s\n", sregs[RS2(inst)]); return OK; case 0x19: case 0x1d: case 0x29: case 0x33: case 0x3f: ILLEGAL; case 0x25: /* SLL/SLLX */ case 0x26: /* SRL/SRLX */ case 0x27: /* SRA/SRAX */ (void)printf("%p:\t%s%s\t%s, ", (void *)pc, opc[op3], X(inst) ? "x" : "", sregs[RS1(inst)]); if (IMM(inst)) (void)printf("%d, ", X(inst) ? SHIFT64(inst) : SHIFT32(inst)); else (void)printf("%s, ", sregs[RS2(inst)]); (void)printf("%s\n", sregs[RD(inst)]); return OK; case 0x28: /* RDASR */ return dis_rdasr(pc, inst); case 0x2a: /* RDPR */ return dis_rdpr(pc, inst); case 0x30: /* WRASR */ return dis_wrasr(pc, inst); case 0x31: /* SAVED/RESTORED */ if(FCN(inst) == 0) { (void)printf("%p:\tsaved\n", (void *)pc); return OK; } if(FCN(inst) == 1) { (void)printf("%p:\trestored\n", (void *)pc); return OK; } ILLEGAL; case 0x32: /* WRPR */ return dis_wrpr(pc, inst); case 0x3a: /* Tcc */ return dis_tcc(pc, inst); case 0x3e: /* DONE/RETRY */ if(FCN(inst) == 0) { (void)printf("%p:\tdone\n", (void *)pc); return OK; } if(FCN(inst) == 1) { (void)printf("%p:\tretry\n", (void *)pc); return OK; } ILLEGAL; case 0x36: /* IMPDEP1 */ (void)printf("XXXX %p:\timpldep1\n", (void *)pc ); return ERR; case 0x37: /* IMPLDEP2 */ (void)printf("XXXX %p:\timpldep2\n", (void *)pc); return ERR; default: (void)printf("XXXX dis_class2 op3=%x\n", op3); return ERR; } }
void findcalls(nltype *parentp, pctype p_lowpc, pctype p_highpc) { unsigned long instructp; sztype length; nltype *childp; pctype destpc; if (textspace == 0) { return; } if (p_lowpc > s_highpc) return; if (p_highpc < s_lowpc) return; if (p_lowpc < s_lowpc) p_lowpc = s_lowpc; if (p_highpc > s_highpc) p_highpc = s_highpc; #ifdef DEBUG if (debug & CALLSDEBUG) { printf("[findcalls] %s: 0x%llx to 0x%llx\n", parentp->name, p_lowpc, p_highpc); } #endif /* DEBUG */ length = 4; for (instructp = (uintptr_t)textspace + p_lowpc - TORIGIN; instructp < (uintptr_t)textspace + p_highpc - TORIGIN; instructp += length) { switch (OP(instructp)) { case CALL: /* * May be a call, better check it out. */ #ifdef DEBUG if (debug & CALLSDEBUG) { printf("[findcalls]\t0x%x:call\n", PC_VAL(instructp)); } #endif /* DEBUG */ destpc = (DISP30(instructp) << 2) + PC_VAL(instructp); break; case FMT3_0x10: if (OP3(instructp) != JMPL) continue; #ifdef DEBUG if (debug & CALLSDEBUG) printf("[findcalls]\t0x%x:jmpl", PC_VAL(instructp)); #endif /* DEBUG */ if (RD(instructp) == R_G0) { #ifdef DEBUG if (debug & CALLSDEBUG) { switch (RS1(instructp)) { case R_O7: printf("\tprobably a RETL\n"); break; case R_I7: printf("\tprobably a RET\n"); break; default: printf(", but not a call: " "linked to g0\n"); } } #endif /* DEBUG */ continue; } #ifdef DEBUG if (debug & CALLSDEBUG) { printf("\toperands are DST = R%d,\tSRC = R%d", RD(instructp), RS1(instructp)); } #endif /* DEBUG */ if (IMMED(instructp)) { #ifdef DEBUG if (debug & CALLSDEBUG) { if (SIMM13(instructp) < 0) { printf(" - 0x%x\n", -(SIMM13(instructp))); } else { printf(" + 0x%x\n", SIMM13(instructp)); } } #endif /* DEBUG */ switch (RS1(instructp)) { case R_G0: /* * absolute address, simm 13 */ destpc = SIMM13(instructp); break; default: /* * indirect call */ addarc(parentp, &indirectchild, 0); continue; } } else { /* * two register sources, all cases are indirect */ #ifdef DEBUG if (debug & CALLSDEBUG) { printf(" + R%d\n", RS2(instructp)); } #endif /* DEBUG */ addarc(parentp, &indirectchild, 0); continue; } break; default: continue; } /* * Check that the destination is the address of * a function; this allows us to differentiate * real calls from someone trying to get the PC, * e.g. position independent switches. */ if (destpc >= s_lowpc && destpc <= s_highpc) { childp = nllookup(&modules, destpc, NULL); #ifdef DEBUG if (debug & CALLSDEBUG) { printf("[findcalls]\tdestpc 0x%llx", destpc); printf(" childp->name %s", childp->name); printf(" childp->value 0x%llx\n", childp->value); } #endif /* DEBUG */ if (childp->value == destpc) { /* * a hit */ addarc(parentp, childp, 0); continue; } } /* * else: * it looked like a call, * but it wasn't to anywhere. */ #ifdef DEBUG if (debug & CALLSDEBUG) { printf("[findcalls]\tbut it's a switch or a botch\n"); } #endif /* DEBUG */ continue; } }
{ "st", F3(3, 0x35, 1), F3(~3, ~0x35, ~1), "C,[i+1]", 0, v6 }, { "st", F3(3, 0x35, 1), F3(~3, ~0x35, ~1)|RS1_G0, "C,[i]", 0, v6 }, { "st", F3(3, 0x35, 1), F3(~3, ~0x35, ~1)|SIMM13(~0), "C,[1]", 0, v6 }, /* st d,[rs1+0] */ { "st", F3(3, 0x25, 0), F3(~3, ~0x25, ~0)|RD_G0|ASI(~0), "F,[1+2]", 0, v6 }, { "st", F3(3, 0x25, 0), F3(~3, ~0x25, ~0)|RD_G0|ASI_RS2(~0), "F,[1]", 0, v6 }, /* st d,[rs1+%g0] */ { "st", F3(3, 0x25, 1), F3(~3, ~0x25, ~1)|RD_G0, "F,[1+i]", 0, v6 }, { "st", F3(3, 0x25, 1), F3(~3, ~0x25, ~1)|RD_G0, "F,[i+1]", 0, v6 }, { "st", F3(3, 0x25, 1), F3(~3, ~0x25, ~1)|RD_G0|RS1_G0, "F,[i]", 0, v6 }, { "st", F3(3, 0x25, 1), F3(~3, ~0x25, ~1)|RD_G0|SIMM13(~0), "F,[1]", 0, v6 }, /* st d,[rs1+0] */ { "sta", F3(3, 0x14, 0), F3(~3, ~0x14, ~0), "d,[1+2]A", 0, v6 }, { "sta", F3(3, 0x14, 0), F3(~3, ~0x14, ~0)|RS2(~0), "d,[1]A", 0, v6 }, /* sta d,[rs1+%g0] */ { "stb", F3(3, 0x05, 0), F3(~3, ~0x05, ~0)|ASI(~0), "d,[1+2]", 0, v6 }, { "stb", F3(3, 0x05, 0), F3(~3, ~0x05, ~0)|ASI_RS2(~0), "d,[1]", 0, v6 }, /* stb d,[rs1+%g0] */ { "stb", F3(3, 0x05, 1), F3(~3, ~0x05, ~1), "d,[1+i]", 0, v6 }, { "stb", F3(3, 0x05, 1), F3(~3, ~0x05, ~1), "d,[i+1]", 0, v6 }, { "stb", F3(3, 0x05, 1), F3(~3, ~0x05, ~1)|RS1_G0, "d,[i]", 0, v6 }, { "stb", F3(3, 0x05, 1), F3(~3, ~0x05, ~1)|SIMM13(~0), "d,[1]", 0, v6 }, /* stb d,[rs1+0] */ { "stba", F3(3, 0x15, 0), F3(~3, ~0x15, ~0), "d,[1+2]A", 0, v6 },