ref: b5a6dc7849cbd9f1fd23183ba46f0d5deb24e81d
dir: /sys/src/cmd/aux/realemu/fmt.c/
#include <u.h> #include <libc.h> #include "dat.h" #include "fns.h" static char *opstr[] = { /* Edit s/O(.*),/[O\1]= "\1",/g */ [OBAD]= "BAD", [O0F]= "0F", [OAAA]= "AAA", [OAAD]= "AAD", [OAAM]= "AAM", [OAAS]= "AAS", [OADC]= "ADC", [OADD]= "ADD", [OAND]= "AND", [OARPL]= "ARPL", [OASIZE]= "ASIZE", [OBOUND]= "BOUND", [OBT]= "BT", [OBTC]= "BTC", [OBTR]= "BTR", [OBTS]= "BTS", [OBSF]= "BSF", [OBSR]= "BSR", [OCALL]= "CALL", [OCBW]= "CBW", [OCLC]= "CLC", [OCLD]= "CLD", [OCLI]= "CLI", [OCMC]= "CMC", [OCMOV]= "CMOV", [OCMP]= "CMP", [OCMPS]= "CMPS", [OCWD]= "CWD", [ODAA]= "DAA", [ODAS]= "DAS", [ODEC]= "DEC", [ODIV]= "DIV", [OENTER]= "ENTER", [OGP1]= "GP1", [OGP2]= "GP2", [OGP3b]= "GP3b", [OGP3v]= "GP3v", [OGP4]= "GP4", [OGP5]= "GP5", [OHLT]= "HLT", [OIDIV]= "IDIV", [OIMUL]= "IMUL", [OIN]= "IN", [OINC]= "INC", [OINS]= "INS", [OINT]= "INT", [OIRET]= "IRET", [OJUMP]= "JUMP", [OLAHF]= "LAHF", [OLFP]= "LFP", [OLEA]= "LEA", [OLEAVE]= "LEAVE", [OLOCK]= "LOCK", [OLODS]= "LODS", [OLOOP]= "LOOP", [OLOOPNZ]= "LOOPNZ", [OLOOPZ]= "LOOPZ", [OMOV]= "MOV", [OMOVS]= "MOVS", [OMOVZX]= "MOVZX", [OMOVSX]= "MOVSX", [OMUL]= "MUL", [ONEG]= "NEG", [ONOP]= "NOP", [ONOT]= "NOT", [OOR]= "OR", [OOSIZE]= "OSIZE", [OOUT]= "OUT", [OOUTS]= "OUTS", [OPOP]= "POP", [OPOPA]= "POPA", [OPOPF]= "POPF", [OPUSH]= "PUSH", [OPUSHA]= "PUSHA", [OPUSHF]= "PUSHF", [ORCL]= "RCL", [ORCR]= "RCR", [OREPE]= "REPE", [OREPNE]= "REPNE", [ORET]= "RET", [ORETF]= "RETF", [OROL]= "ROL", [OROR]= "ROR", [OSAHF]= "SAHF", [OSAR]= "SAR", [OSBB]= "SBB", [OSCAS]= "SCAS", [OSEG]= "SEG", [OSET]= "SET", [OSHL]= "SHL", [OSHLD]= "SHLD", [OSHR]= "SHR", [OSHRD]= "SHRD", [OSTC]= "STC", [OSTD]= "STD", [OSTI]= "STI", [OSTOS]= "STOS", [OSUB]= "SUB", [OTEST]= "TEST", [OWAIT]= "WAIT", [OXCHG]= "XCHG", [OXLAT]= "XLAT", [OXOR]= "XOR", }; static char *memstr16[] = { "BX+SI", "BX+DI", "BP+SI", "BP+DI", "SI", "DI", "BP", "BX", }; static char *memstr32[] = { "EAX", "ECX", "EDX", "EBX", "0", "EBP", "ESI", "EDI", }; static int argconv(char *p, Inst *i, Iarg *a) { jmp_buf jmp; char *s; s = p; switch(a->tag){ default: abort(); case TCON: return sprint(p, "%lud", a->val); case TREG: case TREG|TH: switch(a->len){ case 1: return sprint(p, "%c%c", "ACDB"[a->reg], "LH"[(a->tag & TH) != 0]); case 4: *p++ = 'E'; case 2: p += sprint(p, "%c%c", "ACDBSBSDECSDFGIF"[a->reg], "XXXXPPIISSSSSSPL"[a->reg]); return p - s; } case TMEM: break; } /* setup trap jump in case we dereference bad memory */ memmove(jmp, a->cpu->jmp, sizeof jmp); if(setjmp(a->cpu->jmp)){ p += sprint(p, "<%.4lux:%.4lux>", a->seg, a->off); goto out; } switch(a->atype){ default: abort(); case AAp: p += sprint(p, "[%.4lux:%.4lux]", a->seg, a->off); break; case AJb: case AJv: p += sprint(p, "[%.4lux]", a->off); break; case AIc: p += sprint(p, "$%.2lx", ars(a)); break; case AIb: case AIw: case AIv: p += sprint(p, "$%.*lux", (int)a->len*2, ar(a)); break; case AMp: *p++ = '*'; case AEb: case AEw: case AEv: case AM: case AMa: case AMa2: case AOb: case AOv: if(i->sreg != RDS) p += sprint(p, "%cS:", "ECSDFG"[i->sreg - RES]); if(a->atype == AOb || a->atype == AOv || (i->mod == 0 && (i->alen == 2 && i->rm == 6) || (i->alen == 4 && ((i->rm == 5) || (i->rm == 4 && i->index == 4 && i->base == 5))))){ p += sprint(p, "[%.*lux]", (int)i->alen*2, a->off); break; } *p++ = '['; if(i->alen == 2) p += sprint(p, "%s", memstr16[i->rm]); else{ if(i->rm == 4){ if(i->index != 4) p += sprint(p, "%c*%s+", "1248"[i->scale], memstr32[i->index]); if(i->base != 5) p += sprint(p, "%s", memstr32[i->base]); else{ if(i->mod == 0) p += sprint(p, "%.4lux", i->off); else p += sprint(p, "EBP"); } } else p += sprint(p, "%s", memstr32[i->rm]); } if(i->mod != 0) p += sprint(p, "%+lx", i->disp); *p++ = ']'; break; case AXb: case AXv: if(a->sreg != RDS) p += sprint(p, "%cS:", "ECSDFG"[a->sreg - RES]); p += sprint(p, "[SI]"); break; case AYb: case AYv: if(a->sreg != RDS) p += sprint(p, "%cS:", "ECSDFG"[a->sreg - RES]); p += sprint(p, "[DI]"); break; } out: memmove(a->cpu->jmp, jmp, sizeof jmp); *p = 0; return p - s; } static char *jmpstr[] = { "JO", "JNO", "JC", "JNC", "JZ", "JNZ", "JBE", "JA", "JS", "JNS", "JP", "JNP", "JL", "JGE", "JLE", "JG", }; int instfmt(Fmt *fmt) { Inst *i; char *p, buf[256]; i = va_arg(fmt->args, Inst*); p = buf; if(i->olen == 4) p += sprint(p, "O32: "); if(i->alen == 4) p += sprint(p, "A32: "); if(i->rep) p += sprint(p, "%s: ", opstr[i->rep]); if(i->op == OXLAT && i->sreg != RDS) p += sprint(p, "%cS:", "ECSDFG"[i->sreg - RES]); if(i->op == OJUMP){ switch(i->code){ case 0xE3: p += sprint(p, "%s ", "JCXZ"); break; case 0xEB: case 0xE9: case 0xEA: case 0xFF: p += sprint(p, "%s ", "JMP"); break; default: p += sprint(p, "%s ", jmpstr[i->code&0xF]); break; } } else p += sprint(p, "%s ", opstr[i->op]); for(;;){ if(i->a1 == nil) break; p += argconv(p, i, i->a1); if(i->a2 == nil) break; *p++ = ','; *p++ = ' '; p += argconv(p, i, i->a2); if(i->a3 == nil) break; *p++ = ','; *p++ = ' '; p += argconv(p, i, i->a3); break; } *p = 0; fmtstrcpy(fmt, buf); return 0; } int flagfmt(Fmt *fmt) { char buf[16]; ulong f; f = va_arg(fmt->args, ulong); sprint(buf, "%c%c%c%c%c%c%c", (f & CF) ? 'C' : 'c', (f & SF) ? 'S' : 's', (f & ZF) ? 'Z' : 'z', (f & OF) ? 'O' : 'o', (f & PF) ? 'P' : 'p', (f & DF) ? 'D' : 'd', (f & IF) ? 'I' : 'i'); fmtstrcpy(fmt, buf); return 0; } int cpufmt(Fmt *fmt) { char buf[512]; jmp_buf jmp; Cpu *cpu; Inst i; cpu = va_arg(fmt->args, Cpu*); memmove(jmp, cpu->jmp, sizeof jmp); if(setjmp(cpu->jmp) == 0) decode(amem(cpu, 1, RCS, cpu->reg[RIP]), &i); memmove(cpu->jmp, jmp, sizeof jmp); snprint(buf, sizeof(buf), "%.6lux " "%.8lux %.8lux %.8lux %.8lux %.8lux %.8lux %.8lux %.8lux " "%.4lux %.4lux %.4lux %.4lux " "%J %.4lux %.2ux %I", cpu->ic, cpu->reg[RAX], cpu->reg[RBX], cpu->reg[RCX], cpu->reg[RDX], cpu->reg[RDI], cpu->reg[RSI], cpu->reg[RBP], cpu->reg[RSP], cpu->reg[RDS], cpu->reg[RES], cpu->reg[RSS], cpu->reg[RCS], cpu->reg[RFL], cpu->reg[RIP], i.code, &i); fmtstrcpy(fmt, buf); return 0; }