mirror of
https://github.com/danbulant/Cosmos
synced 2026-06-06 16:22:40 +00:00
This commit is contained in:
parent
49bd0d1383
commit
21ec33c46d
5 changed files with 115 additions and 74 deletions
|
|
@ -8,6 +8,7 @@ using NUnit.Framework;
|
||||||
namespace Indy.IL2CPU.Tests.Assembler.X86 {
|
namespace Indy.IL2CPU.Tests.Assembler.X86 {
|
||||||
[TestFixture]
|
[TestFixture]
|
||||||
public class HaltTests: BaseTest {
|
public class HaltTests: BaseTest {
|
||||||
|
[Test]
|
||||||
public void TestIt() {
|
public void TestIt() {
|
||||||
new Halt();
|
new Halt();
|
||||||
Verify();
|
Verify();
|
||||||
|
|
|
||||||
|
|
@ -19,16 +19,21 @@ DestinationRegBitShiftLeft=0
|
||||||
AllowedSizes = InstructionSizes.DWord,
|
AllowedSizes = InstructionSizes.DWord,
|
||||||
DestinationImmediate = true
|
DestinationImmediate = true
|
||||||
}); // immediate
|
}); // immediate
|
||||||
|
aData.EncodingOptions.Add(new InstructionData.InstructionEncodingOption {
|
||||||
|
AllowedSizes = InstructionSizes.DWord,
|
||||||
|
OpCode = new byte[] { 0xFF },
|
||||||
|
NeedsModRMByte = true,
|
||||||
|
DestinationMemory = true,
|
||||||
|
DefaultSize = InstructionSize.DWord,
|
||||||
|
InitialModRMByteValue = 0x30
|
||||||
|
}); // pop to memory
|
||||||
}
|
}
|
||||||
|
|
||||||
public Push()
|
public Push() {
|
||||||
{
|
|
||||||
//Changed without size
|
//Changed without size
|
||||||
//Size = 32;
|
//Size = 32;
|
||||||
}
|
}
|
||||||
public override string ToString()
|
public override string ToString() {
|
||||||
{
|
|
||||||
return this.mMnemonic + " dword " + this.GetDestinationAsString();
|
return this.mMnemonic + " dword " + this.GetDestinationAsString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -18,14 +18,15 @@ namespace Indy.IL2CPU.Assembler.X86 {
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum InstructionSize {
|
public enum InstructionSize {
|
||||||
None,
|
None = 0,
|
||||||
Byte,
|
Byte = 8,
|
||||||
Word,
|
Word = 16,
|
||||||
DWord,
|
DWord = 32,
|
||||||
QWord,
|
QWord = 64,
|
||||||
}
|
}
|
||||||
public class InstructionData {
|
public class InstructionData {
|
||||||
public class InstructionEncodingOption {
|
public class InstructionEncodingOption {
|
||||||
|
public Action<byte[], Instruction> ModifyBytes;
|
||||||
|
|
||||||
public byte[] OpCode;
|
public byte[] OpCode;
|
||||||
|
|
||||||
|
|
@ -34,6 +35,7 @@ namespace Indy.IL2CPU.Assembler.X86 {
|
||||||
/// which refer to <see cref="OpCode"/> bytes, can assume an extra ModRM byte.
|
/// which refer to <see cref="OpCode"/> bytes, can assume an extra ModRM byte.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool NeedsModRMByte;
|
public bool NeedsModRMByte;
|
||||||
|
public byte InitialModRMByteValue;
|
||||||
|
|
||||||
public InstructionSizes AllowedSizes;
|
public InstructionSizes AllowedSizes;
|
||||||
public InstructionSize DefaultSize = InstructionSize.DWord;
|
public InstructionSize DefaultSize = InstructionSize.DWord;
|
||||||
|
|
@ -110,7 +112,6 @@ namespace Indy.IL2CPU.Assembler.X86 {
|
||||||
mInstructionDatasLocker = new ReaderWriterLocker();
|
mInstructionDatasLocker = new ReaderWriterLocker();
|
||||||
using (mInstructionDatasLocker.AcquireWriterLock()) {
|
using (mInstructionDatasLocker.AcquireWriterLock()) {
|
||||||
mInstructionDatas = new SortedList<Type, InstructionData>(new TypeComparer());
|
mInstructionDatas = new SortedList<Type, InstructionData>(new TypeComparer());
|
||||||
int xInstructionsWithEncodingOptions = 0;
|
|
||||||
foreach (Type xType in typeof(Instruction).Assembly.GetTypes()) {
|
foreach (Type xType in typeof(Instruction).Assembly.GetTypes()) {
|
||||||
if (!xType.IsSubclassOf(typeof(Instruction))) {
|
if (!xType.IsSubclassOf(typeof(Instruction))) {
|
||||||
continue;
|
continue;
|
||||||
|
|
@ -138,12 +139,8 @@ namespace Indy.IL2CPU.Assembler.X86 {
|
||||||
if (xMethod != null) {
|
if (xMethod != null) {
|
||||||
xMethod.Invoke(null, new object[] { xNewInstructionData });
|
xMethod.Invoke(null, new object[] { xNewInstructionData });
|
||||||
}
|
}
|
||||||
if (xNewInstructionData.EncodingOptions.Count > 0) {
|
|
||||||
xInstructionsWithEncodingOptions++;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Console.WriteLine("Total Instructions = {0}, Instructions with encoding data = {1}", mInstructionDatas.Count, xInstructionsWithEncodingOptions);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Instruction() {
|
protected Instruction() {
|
||||||
|
|
@ -170,15 +167,15 @@ namespace Indy.IL2CPU.Assembler.X86 {
|
||||||
}
|
}
|
||||||
if (aInstructionData == null) {
|
if (aInstructionData == null) {
|
||||||
aEncodingOption = null;
|
aEncodingOption = null;
|
||||||
aInstructionData=null;
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
aEncodingOption = null;
|
aEncodingOption = null;
|
||||||
for (int i = 0; i < aInstructionData.EncodingOptions.Count; i++) {
|
for (int i = 0; i < aInstructionData.EncodingOptions.Count; i++) {
|
||||||
|
|
||||||
var xEncodingOption = aInstructionData.EncodingOptions[i];
|
var xEncodingOption = aInstructionData.EncodingOptions[i];
|
||||||
if (aInstructionWithDestination != null) {
|
if (aInstructionWithDestination != null) {
|
||||||
if (!(((xEncodingOption.DestinationMemory || xEncodingOption.DestinationReg.HasValue) && aInstructionWithDestination.DestinationReg != Guid.Empty) ||
|
if (!(((xEncodingOption.DestinationMemory || xEncodingOption.DestinationReg.HasValue) && (aInstructionWithDestination.DestinationReg != Guid.Empty || aInstructionWithDestination.DestinationValue.HasValue)) ||
|
||||||
(!(xEncodingOption.DestinationMemory || xEncodingOption.DestinationReg.HasValue) && aInstructionWithDestination.DestinationReg == Guid.Empty))) {
|
(!(xEncodingOption.DestinationMemory || xEncodingOption.DestinationReg.HasValue) && aInstructionWithDestination.DestinationReg == Guid.Empty && aInstructionWithDestination.DestinationValue.HasValue))) {
|
||||||
// mismatch
|
// mismatch
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
@ -188,23 +185,26 @@ namespace Indy.IL2CPU.Assembler.X86 {
|
||||||
(!xEncodingOption.DestinationMemory && (aInstructionWithDestination.DestinationReg != Guid.Empty && !aInstructionWithDestination.DestinationIsIndirect)))) && aInstructionWithDestination.DestinationIsIndirect) {
|
(!xEncodingOption.DestinationMemory && (aInstructionWithDestination.DestinationReg != Guid.Empty && !aInstructionWithDestination.DestinationIsIndirect)))) && aInstructionWithDestination.DestinationIsIndirect) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (!((xEncodingOption.DestinationImmediate && aInstructionWithDestination.DestinationValue != null) ||
|
if (!((xEncodingOption.DestinationImmediate && aInstructionWithDestination.DestinationValue != null && !aInstructionWithDestination.DestinationIsIndirect) ||
|
||||||
(!xEncodingOption.DestinationImmediate && aInstructionWithDestination.DestinationValue == null))) {
|
(!xEncodingOption.DestinationImmediate && (aInstructionWithDestination.DestinationValue == null || aInstructionWithDestination.DestinationIsIndirect)))) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (aInstructionWithSource != null) {
|
if (aInstructionWithSource != null) {
|
||||||
if (!((xEncodingOption.SourceReg.HasValue && aInstructionWithSource.SourceReg != Guid.Empty) ||
|
if (!(((xEncodingOption.SourceMemory || xEncodingOption.SourceReg.HasValue) && (aInstructionWithSource.SourceReg != Guid.Empty || aInstructionWithSource.SourceValue.HasValue)) ||
|
||||||
(!xEncodingOption.SourceReg.HasValue && aInstructionWithSource.SourceReg == Guid.Empty))) {
|
(!(xEncodingOption.SourceMemory || xEncodingOption.SourceReg.HasValue) && aInstructionWithSource.SourceReg == Guid.Empty && aInstructionWithSource.SourceValue.HasValue))) {
|
||||||
// mismatch
|
// mismatch
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (!((xEncodingOption.SourceMemory && (aInstructionWithSource.SourceValue != null && aInstructionWithSource.SourceIsIndirect)) ||
|
|
||||||
(!xEncodingOption.SourceMemory && (aInstructionWithSource.SourceValue == null && !aInstructionWithSource.SourceIsIndirect))) && aInstructionWithSource.SourceIsIndirect) {
|
if ((!((xEncodingOption.SourceMemory && (aInstructionWithSource.SourceValue != null && aInstructionWithSource.SourceIsIndirect)) ||
|
||||||
|
(!xEncodingOption.SourceMemory && (aInstructionWithSource.SourceValue == null && !aInstructionWithSource.SourceIsIndirect))) &&
|
||||||
|
!((xEncodingOption.SourceMemory && (aInstructionWithSource.SourceReg != Guid.Empty && aInstructionWithSource.SourceIsIndirect)) ||
|
||||||
|
(!xEncodingOption.SourceMemory && (aInstructionWithSource.SourceReg != Guid.Empty && !aInstructionWithSource.SourceIsIndirect)))) && aInstructionWithSource.SourceIsIndirect) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (!((xEncodingOption.SourceImmediate && aInstructionWithSource.SourceValue != null) ||
|
if (!((xEncodingOption.SourceImmediate && aInstructionWithSource.SourceValue != null && !aInstructionWithSource.SourceIsIndirect) ||
|
||||||
(!xEncodingOption.SourceImmediate && aInstructionWithSource.SourceValue == null))) {
|
(!xEncodingOption.SourceImmediate && (aInstructionWithSource.SourceValue == null || aInstructionWithSource.SourceIsIndirect)))) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -227,8 +227,7 @@ namespace Indy.IL2CPU.Assembler.X86 {
|
||||||
aInstructionWithDestination.DestinationReg == Registers.ESP)) {
|
aInstructionWithDestination.DestinationReg == Registers.ESP)) {
|
||||||
aSize++;
|
aSize++;
|
||||||
xSIB = true;
|
xSIB = true;
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
if (aInstructionWithSource != null &&
|
if (aInstructionWithSource != null &&
|
||||||
((aInstructionWithSource.SourceReg == Registers.EBP && !(aInstructionWithSource.SourceReg != Guid.Empty && aInstructionWithSource.SourceIsIndirect && aInstructionWithSource.SourceDisplacement > 0)) ||
|
((aInstructionWithSource.SourceReg == Registers.EBP && !(aInstructionWithSource.SourceReg != Guid.Empty && aInstructionWithSource.SourceIsIndirect && aInstructionWithSource.SourceDisplacement > 0)) ||
|
||||||
aInstructionWithSource.SourceReg == Registers.ESP)) {
|
aInstructionWithSource.SourceReg == Registers.ESP)) {
|
||||||
|
|
@ -250,11 +249,12 @@ namespace Indy.IL2CPU.Assembler.X86 {
|
||||||
// aSize -= 1;
|
// aSize -= 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
if (aInstructionWithDestination != null && aInstructionWithSize != null) {
|
||||||
if (aInstructionWithDestination != null && aInstructionWithDestination.DestinationValue.HasValue) {
|
if (aInstructionWithDestination != null && aInstructionWithDestination.DestinationValue.HasValue) {
|
||||||
aSize += (ulong)aInstructionWithSize.Size / 8;
|
aSize += (ulong)aInstructionWithSize.Size / 8;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (aInstructionWithDestination != null && aInstructionWithDestination.DestinationRef != null) {
|
if (aInstructionWithDestination != null && aInstructionWithDestination.DestinationRef != null) {
|
||||||
aSize += 4;
|
aSize += 4;
|
||||||
}
|
}
|
||||||
|
|
@ -264,6 +264,9 @@ namespace Indy.IL2CPU.Assembler.X86 {
|
||||||
if (aInstructionWithSource != null && aInstructionWithSource.SourceRef != null) {
|
if (aInstructionWithSource != null && aInstructionWithSource.SourceRef != null) {
|
||||||
aSize += 4;
|
aSize += 4;
|
||||||
}
|
}
|
||||||
|
if (aInstructionWithDestination != null && (aInstructionWithDestination.DestinationValue.HasValue && !(aInstructionWithDestination.DestinationIsIndirect && aInstructionWithDestination.DestinationDisplacement > 0))) {
|
||||||
|
aSize += (ulong)aEncodingOption.DefaultSize / 8;
|
||||||
|
}
|
||||||
if (aEncodingOption.DefaultSize == InstructionSize.DWord && aInstructionWithSize != null && aInstructionWithSize.Size == 16) {
|
if (aEncodingOption.DefaultSize == InstructionSize.DWord && aInstructionWithSize != null && aInstructionWithSize.Size == 16) {
|
||||||
aSize += 1;
|
aSize += 1;
|
||||||
}
|
}
|
||||||
|
|
@ -329,7 +332,7 @@ namespace Indy.IL2CPU.Assembler.X86 {
|
||||||
return GetData(aAssembler, this, xInstructionWithDestination, xInstructionWithSize, xInstructionWithSource, xInstructionData, xEncodingOption);
|
return GetData(aAssembler, this, xInstructionWithDestination, xInstructionWithSize, xInstructionWithSource, xInstructionData, xEncodingOption);
|
||||||
}
|
}
|
||||||
|
|
||||||
private byte[] GetData(Indy.IL2CPU.Assembler.Assembler aAssembler, Instruction aInstruction, IInstructionWithDestination aInstructionWithDestination, IInstructionWithSize aInstructionWithSize, IInstructionWithSource aInstructionWithSource, InstructionData aInstructionData, InstructionData.InstructionEncodingOption aEncodingOption) {
|
private static byte[] GetData(Indy.IL2CPU.Assembler.Assembler aAssembler, Instruction aInstruction, IInstructionWithDestination aInstructionWithDestination, IInstructionWithSize aInstructionWithSize, IInstructionWithSource aInstructionWithSource, InstructionData aInstructionData, InstructionData.InstructionEncodingOption aEncodingOption) {
|
||||||
if (aInstruction.ToString() == "mov word [ESP], 0x47") {
|
if (aInstruction.ToString() == "mov word [ESP], 0x47") {
|
||||||
Console.Write("");
|
Console.Write("");
|
||||||
}
|
}
|
||||||
|
|
@ -366,10 +369,11 @@ namespace Indy.IL2CPU.Assembler.X86 {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (aEncodingOption.NeedsModRMByte) {
|
if (aEncodingOption.NeedsModRMByte) {
|
||||||
xBuffer[aEncodingOption.OpCode.Length + xExtraOffset] = 0;
|
xBuffer[aEncodingOption.OpCode.Length + xExtraOffset] = aEncodingOption.InitialModRMByteValue;
|
||||||
byte xModRM = 0;
|
|
||||||
if (aInstructionWithDestination != null) {
|
if (aInstructionWithDestination != null) {
|
||||||
|
if (aInstructionWithDestination.DestinationReg != Guid.Empty) {
|
||||||
xBuffer[aEncodingOption.OpCode.Length + xExtraOffset] |= EncodeRegister(aInstructionWithDestination.DestinationReg);
|
xBuffer[aEncodingOption.OpCode.Length + xExtraOffset] |= EncodeRegister(aInstructionWithDestination.DestinationReg);
|
||||||
|
}
|
||||||
byte? xSIB = null;
|
byte? xSIB = null;
|
||||||
//if (!aInstructionWithDestination.DestinationIsIndirect) {
|
//if (!aInstructionWithDestination.DestinationIsIndirect) {
|
||||||
if ((aInstructionWithDestination.DestinationReg == Registers.EBP && !(aInstructionWithDestination.DestinationIsIndirect && aInstructionWithDestination.DestinationDisplacement > 0)) ||
|
if ((aInstructionWithDestination.DestinationReg == Registers.EBP && !(aInstructionWithDestination.DestinationIsIndirect && aInstructionWithDestination.DestinationDisplacement > 0)) ||
|
||||||
|
|
@ -386,6 +390,20 @@ namespace Indy.IL2CPU.Assembler.X86 {
|
||||||
((aInstructionWithSource.SourceReg == Registers.EBP && !(aInstructionWithSource.SourceReg != Guid.Empty && aInstructionWithSource.SourceIsIndirect && aInstructionWithSource.SourceDisplacement > 0)) ||
|
((aInstructionWithSource.SourceReg == Registers.EBP && !(aInstructionWithSource.SourceReg != Guid.Empty && aInstructionWithSource.SourceIsIndirect && aInstructionWithSource.SourceDisplacement > 0)) ||
|
||||||
aInstructionWithSource.SourceReg == Registers.ESP)) {
|
aInstructionWithSource.SourceReg == Registers.ESP)) {
|
||||||
throw new NotImplementedException();
|
throw new NotImplementedException();
|
||||||
|
}else {
|
||||||
|
if(aInstructionWithDestination.DestinationReg == Guid.Empty && aInstructionWithDestination.DestinationIsIndirect) {
|
||||||
|
// todo: fix for 16bit mode, it should then be 0x36
|
||||||
|
xBuffer[aEncodingOption.OpCode.Length + xExtraOffset] |= 0x5;
|
||||||
|
ulong xAddress = 0;
|
||||||
|
if (!(aInstructionWithDestination.DestinationRef != null && aInstructionWithDestination.DestinationRef.Resolve(aAssembler, out xAddress))) {
|
||||||
|
if(aInstructionWithDestination.DestinationValue.HasValue){
|
||||||
|
xAddress = aInstructionWithDestination.DestinationValue.Value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
xAddress += (ulong)aInstructionWithDestination.DestinationDisplacement;
|
||||||
|
Array.Copy(BitConverter.GetBytes((uint)xAddress), 0, xBuffer, aEncodingOption.OpCode.Length + xExtraOffset + 1, 4);
|
||||||
|
xExtraOffset += 4;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -395,7 +413,7 @@ namespace Indy.IL2CPU.Assembler.X86 {
|
||||||
xBuffer[aEncodingOption.OpCode.Length + xExtraOffset] |= (byte)(EncodeRegister(aInstructionWithSource.SourceReg) << 3);
|
xBuffer[aEncodingOption.OpCode.Length + xExtraOffset] |= (byte)(EncodeRegister(aInstructionWithSource.SourceReg) << 3);
|
||||||
}
|
}
|
||||||
//SBArray.Resize(ref xBuffer, xBuffer.Length + 1);
|
//SBArray.Resize(ref xBuffer, xBuffer.Length + 1);
|
||||||
if (aInstructionWithDestination.DestinationIsIndirect && aInstructionWithDestination.DestinationDisplacement > 0) {
|
if (aInstructionWithDestination.DestinationReg != Guid.Empty && aInstructionWithDestination.DestinationIsIndirect && aInstructionWithDestination.DestinationDisplacement > 0) {
|
||||||
var xSIBOffset = 0;
|
var xSIBOffset = 0;
|
||||||
if (xSIB != null) {
|
if (xSIB != null) {
|
||||||
//xExtraOffset++;
|
//xExtraOffset++;
|
||||||
|
|
@ -423,7 +441,22 @@ namespace Indy.IL2CPU.Assembler.X86 {
|
||||||
//EncodeModRMByte(aInstruction.DestinationReg, aInstruction.DestinationIsIndirect, aInstruction.DestinationDisplacement > 0, aInstruction.DestinationDisplacement > 255, out xSIB);
|
//EncodeModRMByte(aInstruction.DestinationReg, aInstruction.DestinationIsIndirect, aInstruction.DestinationDisplacement > 0, aInstruction.DestinationDisplacement > 255, out xSIB);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
if (aInstructionWithDestination != null) {
|
||||||
|
if (aInstructionWithDestination.DestinationValue.HasValue && !aInstructionWithDestination.DestinationIsIndirect) {
|
||||||
|
int xOffset = aEncodingOption.OpCode.Length + xExtraOffset;
|
||||||
|
if (aEncodingOption.NeedsModRMByte) {
|
||||||
|
xOffset++;
|
||||||
|
}
|
||||||
|
var xInstrSize = 0;
|
||||||
|
if (aInstructionWithSize != null) {
|
||||||
|
xInstrSize = aInstructionWithSize.Size / 8;
|
||||||
|
} else {
|
||||||
|
// throw new NotImplementedException("size not known");
|
||||||
|
xInstrSize = (int)aEncodingOption.DefaultSize / 8;
|
||||||
|
}
|
||||||
|
Array.Copy(BitConverter.GetBytes(aInstructionWithDestination.DestinationValue.Value), 0, xBuffer, xOffset, xInstrSize);
|
||||||
|
}
|
||||||
|
}
|
||||||
// todo: add more options
|
// todo: add more options
|
||||||
if (aInstructionWithSource != null) {
|
if (aInstructionWithSource != null) {
|
||||||
if (aInstructionWithSource.SourceValue.HasValue) {
|
if (aInstructionWithSource.SourceValue.HasValue) {
|
||||||
|
|
@ -448,7 +481,9 @@ namespace Indy.IL2CPU.Assembler.X86 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(aEncodingOption.ModifyBytes != null) {
|
||||||
|
aEncodingOption.ModifyBytes(xBuffer, aInstruction);
|
||||||
|
}
|
||||||
//
|
//
|
||||||
return xBuffer;
|
return xBuffer;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ namespace TestApp {
|
||||||
class Program {
|
class Program {
|
||||||
class Renderer : Y86 {
|
class Renderer : Y86 {
|
||||||
public void DoRender() {
|
public void DoRender() {
|
||||||
new Push { DestinationValue = 300000 };
|
new Push { DestinationIsIndirect = true, DestinationValue = 65 };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
static void Main(string[] args) {
|
static void Main(string[] args) {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue