104 lines
4.2 KiB
C#
104 lines
4.2 KiB
C#
namespace StoicGoose.Core.CPU
|
|
{
|
|
public sealed partial class V30MZ
|
|
{
|
|
ModRM modRm;
|
|
|
|
private void ReadModRM()
|
|
{
|
|
if (modRm.IsSet) return;
|
|
|
|
modRm.Set(ReadMemory8(cs, ip++));
|
|
switch (modRm.Mod)
|
|
{
|
|
case ModRM.Modes.NoDisplacement:
|
|
switch (modRm.Mem)
|
|
{
|
|
case 0b000: modRm.Segment = GetSegmentViaOverride(SegmentNumber.DS); modRm.Offset = (ushort)(bx.Word + si); break;
|
|
case 0b001: modRm.Segment = GetSegmentViaOverride(SegmentNumber.DS); modRm.Offset = (ushort)(bx.Word + di); break;
|
|
case 0b010: modRm.Segment = GetSegmentViaOverride(SegmentNumber.SS); modRm.Offset = (ushort)(bp + si); break;
|
|
case 0b011: modRm.Segment = GetSegmentViaOverride(SegmentNumber.SS); modRm.Offset = (ushort)(bp + di); break;
|
|
case 0b100: modRm.Segment = GetSegmentViaOverride(SegmentNumber.DS); modRm.Offset = si; break;
|
|
case 0b101: modRm.Segment = GetSegmentViaOverride(SegmentNumber.DS); modRm.Offset = di; break;
|
|
case 0b110: modRm.Segment = GetSegmentViaOverride(SegmentNumber.DS); modRm.Offset = ReadMemory16(cs, ip); ip += 2; break;
|
|
case 0b111: modRm.Segment = GetSegmentViaOverride(SegmentNumber.DS); modRm.Offset = bx.Word; break;
|
|
}
|
|
break;
|
|
|
|
case ModRM.Modes.OneByteDisplacement:
|
|
{
|
|
var displacement = (sbyte)ReadMemory8(cs, ip);
|
|
ip++;
|
|
switch (modRm.Mem)
|
|
{
|
|
case 0b000: modRm.Segment = GetSegmentViaOverride(SegmentNumber.DS); modRm.Offset = (ushort)(bx.Word + si + displacement); break;
|
|
case 0b001: modRm.Segment = GetSegmentViaOverride(SegmentNumber.DS); modRm.Offset = (ushort)(bx.Word + di + displacement); break;
|
|
case 0b010: modRm.Segment = GetSegmentViaOverride(SegmentNumber.SS); modRm.Offset = (ushort)(bp + si + displacement); break;
|
|
case 0b011: modRm.Segment = GetSegmentViaOverride(SegmentNumber.SS); modRm.Offset = (ushort)(bp + di + displacement); break;
|
|
case 0b100: modRm.Segment = GetSegmentViaOverride(SegmentNumber.DS); modRm.Offset = (ushort)(si + displacement); break;
|
|
case 0b101: modRm.Segment = GetSegmentViaOverride(SegmentNumber.DS); modRm.Offset = (ushort)(di + displacement); break;
|
|
case 0b110: modRm.Segment = GetSegmentViaOverride(SegmentNumber.SS); modRm.Offset = (ushort)(bp + displacement); break;
|
|
case 0b111: modRm.Segment = GetSegmentViaOverride(SegmentNumber.DS); modRm.Offset = (ushort)(bx.Word + displacement); break;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case ModRM.Modes.TwoByteDisplacement:
|
|
{
|
|
var displacement = (short)ReadMemory16(cs, ip);
|
|
ip += 2;
|
|
switch (modRm.Mem)
|
|
{
|
|
case 0b000: modRm.Segment = GetSegmentViaOverride(SegmentNumber.DS); modRm.Offset = (ushort)(bx.Word + si + displacement); break;
|
|
case 0b001: modRm.Segment = GetSegmentViaOverride(SegmentNumber.DS); modRm.Offset = (ushort)(bx.Word + di + displacement); break;
|
|
case 0b010: modRm.Segment = GetSegmentViaOverride(SegmentNumber.SS); modRm.Offset = (ushort)(bp + si + displacement); break;
|
|
case 0b011: modRm.Segment = GetSegmentViaOverride(SegmentNumber.SS); modRm.Offset = (ushort)(bp + di + displacement); break;
|
|
case 0b100: modRm.Segment = GetSegmentViaOverride(SegmentNumber.DS); modRm.Offset = (ushort)(si + displacement); break;
|
|
case 0b101: modRm.Segment = GetSegmentViaOverride(SegmentNumber.DS); modRm.Offset = (ushort)(di + displacement); break;
|
|
case 0b110: modRm.Segment = GetSegmentViaOverride(SegmentNumber.SS); modRm.Offset = (ushort)(bp + displacement); break;
|
|
case 0b111: modRm.Segment = GetSegmentViaOverride(SegmentNumber.DS); modRm.Offset = (ushort)(bx.Word + displacement); break;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
struct ModRM
|
|
{
|
|
public enum Modes : byte
|
|
{
|
|
NoDisplacement = 0b00,
|
|
OneByteDisplacement = 0b01,
|
|
TwoByteDisplacement = 0b10,
|
|
Register = 0b11
|
|
}
|
|
|
|
byte data;
|
|
|
|
public Modes Mod => (Modes)((data >> 6) & 0b11);
|
|
public byte Reg => (byte)((data >> 3) & 0b111);
|
|
public byte Mem => (byte)((data >> 0) & 0b111);
|
|
|
|
public ushort Segment, Offset;
|
|
|
|
public bool IsSet;
|
|
|
|
public void Set(byte value)
|
|
{
|
|
data = value;
|
|
|
|
IsSet = true;
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
data = 0;
|
|
Segment = 0;
|
|
Offset = 0;
|
|
|
|
IsSet = false;
|
|
}
|
|
}
|
|
}
|
|
}
|