jehanne/sys/src/cmd/hmi/realemu/fmt.c

397 lines
6.6 KiB
C

#include <u.h>
#include <lib9.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)
{
print_func_entry();
jmp_buf jmp;
char *s;
s = p;
switch(a->tag){
default:
abort();
case TCON:
print_func_exit();
return sprint(p, "%lud", a->val);
case TREG:
case TREG|TH:
switch(a->len){
case 1:
print_func_exit();
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]);
print_func_exit();
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;
print_func_exit();
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)
{
print_func_entry();
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);
print_func_exit();
return 0;
}
int
flagfmt(Fmt *fmt)
{
print_func_entry();
char buf[16];
unsigned long f;
f = va_arg(fmt->args, unsigned long);
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);
print_func_exit();
return 0;
}
int
cpufmt(Fmt *fmt)
{
print_func_entry();
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);
print_func_exit();
return 0;
}