Add Odin templating and Z80Disasm
This commit is contained in:
22
z80_disasm/src/Test.cs
Normal file
22
z80_disasm/src/Test.cs
Normal file
@@ -0,0 +1,22 @@
|
||||
using Z80;
|
||||
class Test {
|
||||
|
||||
// not sure what i was thinking when i wrote this
|
||||
static void Main(string[] args)
|
||||
{
|
||||
Disasm disasm = new Disasm();
|
||||
byte[] x = new byte[3000];
|
||||
for (uint i = 0; i < 3000; i++)
|
||||
{
|
||||
x[i] = (byte) (i % 256);
|
||||
}
|
||||
disasm.Bytes = x;
|
||||
var watch = System.Diagnostics.Stopwatch.StartNew();
|
||||
System.Console.WriteLine(disasm.Bytes.Length);
|
||||
System.Console.WriteLine(disasm.Disassemble());
|
||||
watch.Stop();
|
||||
var elapsedMs = watch.ElapsedMilliseconds;
|
||||
System.Console.WriteLine("Time elapsed: " + elapsedMs + "ms.");
|
||||
|
||||
}
|
||||
}
|
||||
255
z80_disasm/src/Z80Disasm.cs
Normal file
255
z80_disasm/src/Z80Disasm.cs
Normal file
@@ -0,0 +1,255 @@
|
||||
namespace Z80
|
||||
{
|
||||
public class Disasm
|
||||
{
|
||||
public byte[] Bytes
|
||||
{
|
||||
get; set;
|
||||
}
|
||||
private uint labelCounter = 0;
|
||||
private uint programCounter = 0;
|
||||
private byte currentOp = 0;
|
||||
private string currentInstrName;
|
||||
private string currentPredicate;
|
||||
|
||||
|
||||
public string Disassemble()
|
||||
{
|
||||
if (Bytes == null)
|
||||
{
|
||||
throw new System.NullReferenceException();
|
||||
}
|
||||
|
||||
string ret = "";
|
||||
for (int i = 0; i < Bytes.Length; i++)
|
||||
{
|
||||
ret += DisassembleInstruction() + "\n";
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
public string DisassembleInstruction()
|
||||
{
|
||||
int err;
|
||||
if (programCounter + 1 > Bytes.Length)
|
||||
return "EOS";
|
||||
err = DisasmInstructionName();
|
||||
if (programCounter + 1 > Bytes.Length)
|
||||
return "EOS";
|
||||
if (err == -2)
|
||||
DisasmBitInstructionNames();
|
||||
|
||||
DisasmPredicate();
|
||||
|
||||
return currentInstrName + " " + currentPredicate;
|
||||
}
|
||||
|
||||
private int DisasmInstructionName()
|
||||
{
|
||||
currentOp = Bytes[programCounter++];
|
||||
currentInstrName = "<?>";
|
||||
|
||||
switch (currentOp)
|
||||
{
|
||||
case 0:
|
||||
currentInstrName = "NOP";
|
||||
break;
|
||||
case 0xCB:
|
||||
currentInstrName = "BIT INSTRUCTIONS";
|
||||
return -2;
|
||||
case 0xDD:
|
||||
currentInstrName = "IX INSTRUCTIONS";
|
||||
return -3;
|
||||
case 0xED:
|
||||
currentInstrName = "EXTENDED INSTRUCTIONS";
|
||||
return -4;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
The load instruction
|
||||
*/
|
||||
if (currentOp == 0xF9)
|
||||
{
|
||||
currentInstrName = "LD";
|
||||
}
|
||||
|
||||
switch (currentOp & 0xF0)
|
||||
{
|
||||
case 0x40:
|
||||
case 0x50:
|
||||
case 0x60:
|
||||
case 0x70:
|
||||
if (currentOp != 0x76)
|
||||
currentInstrName = "LD";
|
||||
else
|
||||
currentInstrName = "HALT";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
switch ((currentOp) & 0x0F)
|
||||
{
|
||||
case 0x01:
|
||||
case 0x02:
|
||||
case 0x06:
|
||||
case 0x0A:
|
||||
case 0x0E:
|
||||
if (currentOp < 0x80)
|
||||
currentInstrName = "LD";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (currentOp >= 0x80 && currentOp <= 0x8F || currentOp == 0xC6)
|
||||
currentInstrName = "ADD";
|
||||
if (currentOp >= 0x90 && currentOp <= 0x9F || currentOp == 0xD6)
|
||||
currentInstrName = "SUB";
|
||||
if (currentOp >= 0xA0 && currentOp <= 0xAF || currentOp == 0xE6)
|
||||
currentInstrName = "AND";
|
||||
if (currentOp >= 0xB0 && currentOp <= 0xBF || currentOp == 0xF6)
|
||||
currentInstrName = "OR";
|
||||
|
||||
if (currentOp >= 0x88 && currentOp <= 0x8F || currentOp == 0xCE)
|
||||
currentInstrName = "ADC";
|
||||
if (currentOp >= 0x98 && currentOp <= 0x9F || currentOp == 0xDE)
|
||||
currentInstrName = "SBC";
|
||||
if (currentOp >= 0xA8 && currentOp <= 0xAF || currentOp == 0xEE)
|
||||
currentInstrName = "XOR";
|
||||
if (currentOp >= 0xB8 && currentOp <= 0xBF || currentOp == 0xFE)
|
||||
currentInstrName = "CP";
|
||||
return 0;
|
||||
}
|
||||
|
||||
private int DisasmBitInstructionNames()
|
||||
{
|
||||
byte instr = Bytes[programCounter++];
|
||||
if ((instr & 0x30) != 0)
|
||||
{
|
||||
if (instr <= 0x07)
|
||||
currentInstrName = "RLC";
|
||||
else if (instr <= 0x0F)
|
||||
currentInstrName = "RRC";
|
||||
else if (instr <= 0x17)
|
||||
currentInstrName = "RL";
|
||||
else if (instr <= 0x1F)
|
||||
currentInstrName = "RR";
|
||||
else if (instr <= 0x27)
|
||||
currentInstrName = "SLA";
|
||||
else if (instr <= 0x2F)
|
||||
currentInstrName = "SRA";
|
||||
else if (instr <= 0x37)
|
||||
currentInstrName = "SSL";
|
||||
else if (instr <= 0x3F)
|
||||
currentInstrName = "SRL";
|
||||
}
|
||||
switch (instr & 0xF0)
|
||||
{
|
||||
case 0x40:
|
||||
case 0x50:
|
||||
case 0x60:
|
||||
case 0x70:
|
||||
currentInstrName = "BIT";
|
||||
break;
|
||||
case 0x80:
|
||||
case 0x90:
|
||||
case 0xA0:
|
||||
case 0xB0:
|
||||
currentInstrName = "RES";
|
||||
break;
|
||||
case 0xC0:
|
||||
case 0xD0:
|
||||
case 0xE0:
|
||||
case 0xF0:
|
||||
currentInstrName = "SET";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
public int DisasmPredicate()
|
||||
{
|
||||
currentPredicate = "";
|
||||
if (currentOp >= 0x40 && currentOp <= 0x47)
|
||||
{
|
||||
currentPredicate = "b, ";
|
||||
}
|
||||
if (currentOp >= 0x50 && currentOp <= 0x57)
|
||||
{
|
||||
currentPredicate = "d, ";
|
||||
}
|
||||
if (currentOp >= 0x60 && currentOp <= 0x67)
|
||||
{
|
||||
currentPredicate = "h, ";
|
||||
}
|
||||
if (currentOp >= 0x70 && currentOp <= 0x77)
|
||||
{
|
||||
currentPredicate = "(hl), ";
|
||||
}
|
||||
if (currentOp >= 0x48 && currentOp <= 0x4F)
|
||||
{
|
||||
currentPredicate = "c, ";
|
||||
}
|
||||
if (currentOp >= 0x58 && currentOp <= 0x5F)
|
||||
{
|
||||
currentPredicate = "e, ";
|
||||
}
|
||||
if (currentOp >= 0x68 && currentOp <= 0x6F)
|
||||
{
|
||||
currentPredicate = "l, ";
|
||||
}
|
||||
if (currentOp >= 0x78 && currentOp <= 0x7F)
|
||||
{
|
||||
currentPredicate = "a, ";
|
||||
}
|
||||
|
||||
if (currentOp >= 0x40 && currentOp <= 0xBF)
|
||||
{
|
||||
switch (currentOp & 0x0F)
|
||||
{
|
||||
case 0x7:
|
||||
case 0xF:
|
||||
currentPredicate += "a";
|
||||
break;
|
||||
case 0x0:
|
||||
case 0x8:
|
||||
currentPredicate += "b";
|
||||
break;
|
||||
case 0x1:
|
||||
case 0x9:
|
||||
currentPredicate += "c";
|
||||
break;
|
||||
case 0x2:
|
||||
case 0xA:
|
||||
currentPredicate += "d";
|
||||
break;
|
||||
case 0x3:
|
||||
case 0xB:
|
||||
currentPredicate += "e";
|
||||
break;
|
||||
case 0x4:
|
||||
case 0xC:
|
||||
currentPredicate += "h";
|
||||
break;
|
||||
case 0x5:
|
||||
case 0xD:
|
||||
currentPredicate += "l";
|
||||
break;
|
||||
case 0x6:
|
||||
case 0xE:
|
||||
currentPredicate += "(hl)";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user