200 lines
8.7 KiB
C#
200 lines
8.7 KiB
C#
using System.Text;
|
|
|
|
namespace BizHawk.Emulation.CPUs.x86
|
|
{
|
|
public class DisassemblyInfo
|
|
{
|
|
public int Addr;
|
|
public string Mnemonic;
|
|
public string Args;
|
|
public string RawBytes;
|
|
public int Length;
|
|
|
|
public override string ToString()
|
|
{
|
|
return string.Format("{0:X6} {3,-12} {1,-8} {2}", Addr, Mnemonic, Args, RawBytes);
|
|
}
|
|
}
|
|
|
|
public partial class x86<CpuType> where CpuType : struct, x86CpuType
|
|
{
|
|
private ushort ReadWord(int addr)
|
|
{
|
|
return (ushort)(ReadMemory(addr++) + (ReadMemory(addr) << 8));
|
|
}
|
|
|
|
private string DisassembleRM8(ref int addr)
|
|
{
|
|
byte ModRM = ReadMemory(addr++);
|
|
int mod = (ModRM >> 6) & 3;
|
|
int r = (ModRM >> 3) & 7;
|
|
int m = ModRM & 7;
|
|
|
|
string reg;
|
|
switch (r)
|
|
{
|
|
case 0: reg = "AL"; break;
|
|
case 1: reg = "CL"; break;
|
|
case 2: reg = "DL"; break;
|
|
case 3: reg = "BL"; break;
|
|
case 4: reg = "AH"; break;
|
|
case 5: reg = "CH"; break;
|
|
case 6: reg = "DH"; break;
|
|
case 7: reg = "BH"; break;
|
|
default: reg = "UNKNOWN"; break;
|
|
}
|
|
return reg+", "+DisassembleMod(ref addr, mod, m, 1);
|
|
}
|
|
|
|
private string DisassembleMod(ref int addr, int mod, int m, int size)
|
|
{
|
|
string ret;
|
|
switch (mod)
|
|
{
|
|
case 0:
|
|
switch (m)
|
|
{
|
|
case 0: return "[BX+SI]";
|
|
case 1: return "[BX+DI]";
|
|
case 2: return "[BP+SI]";
|
|
case 3: return "[BP+DI]";
|
|
case 4: return "[SI]";
|
|
case 5: return "[DI]";
|
|
case 6: ret = string.Format("{0:X4}h", ReadWord(addr)); addr += 2; return ret;
|
|
case 7: return "[BX]";
|
|
}
|
|
break;
|
|
case 1:
|
|
switch (m)
|
|
{
|
|
case 0: return string.Format("[BX+SI] + {0:X2}h", ReadMemory(addr++));
|
|
case 1: return string.Format("[BX+DI] + {0:X2}h", ReadMemory(addr++));
|
|
case 2: return string.Format("[BP+SI] + {0:X2}h", ReadMemory(addr++));
|
|
case 3: return string.Format("[BP+DI] + {0:X2}h", ReadMemory(addr++));
|
|
case 4: return string.Format("[SI] + {0:X2}h", ReadMemory(addr++));
|
|
case 5: return string.Format("[DI] + {0:X2}h", ReadMemory(addr++));
|
|
case 6: return string.Format("[BP] + {0:X2}h", ReadMemory(addr++));
|
|
case 7: return string.Format("[BX] + {0:X2}h", ReadMemory(addr++));
|
|
}
|
|
break;
|
|
case 2:
|
|
switch (m)
|
|
{
|
|
case 0: ret = string.Format("[BX+SI] + {0:X4}h", ReadWord(addr)); addr += 2; return ret;
|
|
case 1: ret = string.Format("[BX+DI] + {0:X4}h", ReadWord(addr)); addr += 2; return ret;
|
|
case 2: ret = string.Format("[BP+SI] + {0:X4}h", ReadWord(addr)); addr += 2; return ret;
|
|
case 3: ret = string.Format("[BP+DI] + {0:X4}h", ReadWord(addr)); addr += 2; return ret;
|
|
case 4: ret = string.Format("[SI] + {0:X4}h", ReadWord(addr)); addr += 2; return ret;
|
|
case 5: ret = string.Format("[DI] + {0:X4}h", ReadWord(addr)); addr += 2; return ret;
|
|
case 6: ret = string.Format("[BP] + {0:X4}h", ReadWord(addr)); addr += 2; return ret;
|
|
case 7: ret = string.Format("[BX] + {0:X4}h", ReadWord(addr)); addr += 2; return ret;
|
|
}
|
|
break;
|
|
case 3:
|
|
switch (m)
|
|
{
|
|
case 0: return size == 1 ? "AL" : "AX";
|
|
case 1: return size == 1 ? "CL" : "CX";
|
|
case 2: return size == 1 ? "DL" : "DX";
|
|
case 3: return size == 1 ? "BL" : "BX";
|
|
case 4: return size == 1 ? "AH" : "SP";
|
|
case 5: return size == 1 ? "CH" : "BP";
|
|
case 6: return size == 1 ? "DH" : "SI";
|
|
case 7: return size == 1 ? "BH" : "DI";
|
|
}
|
|
break;
|
|
}
|
|
return "Disassembly Error";
|
|
}
|
|
|
|
public DisassemblyInfo Disassemble(int addr)
|
|
{
|
|
var info = new DisassemblyInfo { Addr = addr };
|
|
byte op1 = ReadMemory(addr++);
|
|
switch (op1)
|
|
{
|
|
case 0x02: // ADD r8,r/m8
|
|
info.Mnemonic = "ADD";
|
|
info.Args = DisassembleRM8(ref addr);
|
|
break;
|
|
case 0xB0: // MOV AL, immed
|
|
info.Mnemonic = "MOV";
|
|
info.Args = string.Format("AL, {0:X2}h", ReadMemory(addr++));
|
|
break;
|
|
case 0xB1: // MOV CL, immed
|
|
info.Mnemonic = "MOV";
|
|
info.Args = string.Format("CL, {0:X2}h", ReadMemory(addr++));
|
|
break;
|
|
case 0xB2: // MOV DL, immed
|
|
info.Mnemonic = "MOV";
|
|
info.Args = string.Format("DL, {0:X2}h", ReadMemory(addr++));
|
|
break;
|
|
case 0xB3: // MOV BL, immed
|
|
info.Mnemonic = "MOV";
|
|
info.Args = string.Format("BL, {0:X2}h", ReadMemory(addr++));
|
|
break;
|
|
case 0xB4: // MOV AH, immed
|
|
info.Mnemonic = "MOV";
|
|
info.Args = string.Format("AH, {0:X2}h", ReadMemory(addr++));
|
|
break;
|
|
case 0xB5: // MOV CH, immed
|
|
info.Mnemonic = "MOV";
|
|
info.Args = string.Format("CH, {0:X2}h", ReadMemory(addr++));
|
|
break;
|
|
case 0xB6: // MOV DH, immed
|
|
info.Mnemonic = "MOV";
|
|
info.Args = string.Format("DH, {0:X2}h", ReadMemory(addr++));
|
|
break;
|
|
case 0xB7: // MOV BH, immed
|
|
info.Mnemonic = "MOV";
|
|
info.Args = string.Format("BH, {0:X2}h", ReadMemory(addr++));
|
|
break;
|
|
case 0xB8: // MOV AX, immed
|
|
info.Mnemonic = "MOV";
|
|
info.Args = string.Format("AX, {0:X4}h", ReadWord(addr)); addr += 2;
|
|
break;
|
|
case 0xB9: // MOV CX, immed
|
|
info.Mnemonic = "MOV";
|
|
info.Args = string.Format("CX, {0:X4}h", ReadWord(addr)); addr += 2;
|
|
break;
|
|
case 0xBA: // MOV DX, immed
|
|
info.Mnemonic = "MOV";
|
|
info.Args = string.Format("DX, {0:X4}h", ReadWord(addr)); addr += 2;
|
|
break;
|
|
case 0xBB: // MOV BX, immed
|
|
info.Mnemonic = "MOV";
|
|
info.Args = string.Format("BX, {0:X4}h", ReadWord(addr)); addr += 2;
|
|
break;
|
|
case 0xBC: // MOV SP, immed
|
|
info.Mnemonic = "MOV";
|
|
info.Args = string.Format("SP, {0:X4}h", ReadWord(addr)); addr += 2;
|
|
break;
|
|
case 0xBD: // MOV BP, immed
|
|
info.Mnemonic = "MOV";
|
|
info.Args = string.Format("BP, {0:X4}h", ReadWord(addr)); addr += 2;
|
|
break;
|
|
case 0xBE: // MOV SI, immed
|
|
info.Mnemonic = "MOV";
|
|
info.Args = string.Format("SI, {0:X4}h", ReadWord(addr)); addr += 2;
|
|
break;
|
|
case 0xBF: // MOV DI, immed
|
|
info.Mnemonic = "MOV";
|
|
info.Args = string.Format("DI, {0:X4}h", ReadWord(addr)); addr += 2;
|
|
break;
|
|
default:
|
|
info.Mnemonic = "DB";
|
|
info.Args = string.Format("{0:X2}h", op1);
|
|
break;
|
|
}
|
|
|
|
info.Length = addr - info.Addr;
|
|
var sb = new StringBuilder();
|
|
for (int p = info.Addr; p < info.Addr + info.Length; p++)
|
|
sb.AppendFormat("{0:X2}", ReadMemory(p));
|
|
info.RawBytes = sb.ToString();
|
|
|
|
return info;
|
|
}
|
|
}
|
|
}
|