Some smaller refactorings and misc changes

This commit is contained in:
mterwoord_cp 2008-11-09 12:50:58 +00:00
parent ab7807cdb0
commit ec5eebdeed
24 changed files with 545 additions and 210 deletions

View file

@ -92,8 +92,6 @@ namespace Indy.IL2CPU.Assembler {
}
}
private Func<string, string> mGetFileNameForGroup;
private uint mDataMemberCounter = 0;
public string GetIdentifier(string aPrefix) {
@ -101,29 +99,11 @@ namespace Indy.IL2CPU.Assembler {
return aPrefix + mDataMemberCounter.ToString("X8").ToUpper();
}
public Assembler(Func<string, string> aGetFileNameForGroup) {
mGetFileNameForGroup = aGetFileNameForGroup;
public Assembler() {
CurrentInstance.Push(this);
//mInstructions.AddComplexIndexDefinition(
}
public List<KeyValuePair<string, Instruction>> GetInstructions() {
//using (mInstructionsLocker.AcquireReaderLock()) {
// if(mInstructions.ContainsKey(Thread.CurrentThread.ManagedThreadId)) {
// return mInstructions[Thread.CurrentThread.ManagedThreadId];
// }
//}
// using(mInstructionsLocker.AcquireWriterLock()) {
// // do this check again, between the two locks, the situation might have changed.
// if (mInstructions.ContainsKey(Thread.CurrentThread.ManagedThreadId))
// {
// return mInstructions[Thread.CurrentThread.ManagedThreadId];
// }
// var xResult = new
// }
throw new NotImplementedException("After multi-threaded refactorings, this hasn't been implemented again, yet");
}
public List<DataMember> DataMembers {
get { return mDataMembers; }
}
@ -294,7 +274,9 @@ namespace Indy.IL2CPU.Assembler {
}
if (mInstructions.Count > 0) {
string xMainLabel="";
foreach (Instruction x in mInstructions) {
for(int i = 0; i < mInstructions.Count;i++){
//foreach (Instruction x in mInstructions) {
var x = mInstructions[i];
string prefix = "\t\t\t";
Label xLabel = x as Label;
if (xLabel != null) {

View file

@ -19,6 +19,35 @@ namespace Indy.IL2CPU.Assembler {
}
}
private ulong? mActualAddress;
public bool Resolve(Assembler aAssembler, out ulong aAddress) {
if (mActualAddress != null) {
aAddress = mActualAddress.Value;
return true;
}
BaseAssemblerElement xElement = (from item in aAssembler.Instructions
let xLabel = item as Label
where xLabel != null && xLabel.QualifiedName.Equals(Name, StringComparison.InvariantCultureIgnoreCase)
select item).SingleOrDefault();
if (xElement == null) {
xElement = (from item in aAssembler.DataMembers
where item.Name.Equals(Name, StringComparison.InvariantCultureIgnoreCase)
select item).SingleOrDefault();
}
if (xElement != null) {
if (xElement.ActualAddress.HasValue) {
mActualAddress = xElement.ActualAddress.Value + (uint)Offset;
aAddress = mActualAddress.Value;
return true;
}
}
aAddress = 0;
return false;
}
public int Offset {
get;
set;

View file

@ -6,6 +6,6 @@ using System.IO;
namespace Indy.IL2CPU.Assembler {
public class RawAssembler : Assembler {
public RawAssembler() : base(null) { }
public RawAssembler() : base() { }
}
}

View file

@ -6,155 +6,9 @@ using System.Text;
namespace Indy.IL2CPU.Assembler.X86 {
public class Assembler : Indy.IL2CPU.Assembler.Assembler {
//TODO: COM Port info - should be in assembler? Assembler should not know about comports...
protected byte mComNumber = 0;
protected UInt16[] mComPortAddresses = { 0x3F8, 0x2F8, 0x3E8, 0x2E8 };
public Assembler(Func<string, string> aGetStreamForGroup, byte aComNumber)
: base(aGetStreamForGroup) {
mComNumber = aComNumber;
}
public Assembler(Func<string, string> aGetStreamForGroup) : base(aGetStreamForGroup) {
}
private static string GetValidGroupName(string aGroup) {
return aGroup.Replace('-','_').Replace('.', '_');
}
public override void Initialize() {
base.Initialize();
if (mComNumber > 0) {
new Define("DEBUGSTUB");
}
new Label("Kernel_Start");
new Comment("MultiBoot-compliant loader (e.g. GRUB or X.exe) provides info in registers: ");
new Comment("EBX=multiboot_info ");
new Comment("EAX=0x2BADB002 - check if it's really Multiboot loader ");
new Comment(" ;- copy mb info - some stuff for you ");
new Add { DestinationReg = Registers.EBX, SourceValue = 4 };
new Move {
DestinationReg = Registers.EAX,
SourceReg = Registers.EBX,
SourceIsIndirect = true
};
new Move { DestinationRef = new ElementReference("MultiBootInfo_Memory_Low"), DestinationIsIndirect = true, SourceReg = Registers.EAX };
new Add { DestinationReg = Registers.EBX, SourceValue = 4 };
new Move {
DestinationReg = Registers.EAX,
SourceReg = Registers.EBX,
SourceIsIndirect = true
};
new Move { DestinationRef = new ElementReference("MultiBootInfo_Memory_High"), DestinationIsIndirect = true, SourceReg = Registers.EAX };
new Move {
DestinationReg = Registers.ESP,
SourceRef = new ElementReference("Kernel_Stack")
};
new Comment("some more startups todo");
new ClrInterruptFlag();
if (mComNumber > 0) {
UInt16 xComAddr = mComPortAddresses[mComNumber - 1];
// 9600 baud, 8 databits, no parity, 1 stopbit
new Move { DestinationReg = Registers.DX, SourceValue = (uint)xComAddr + 1 };
new Move { DestinationReg = Registers.AL, SourceValue = 0 };
new Out { Size = 8 }; // disable interrupts for serial stuff
new Move { DestinationReg = Registers.DX, SourceValue = (uint)xComAddr + 3 };
new Move { DestinationReg = Registers.AL, SourceValue = 0x80 };
new Out { Size = 8 }; // Enable DLAB (set baud rate divisor)
new Move { DestinationReg = Registers.DX, SourceValue = (uint)xComAddr };
new Move { DestinationReg = Registers.AL, SourceValue = 0xC };
new Out { Size = 8 }; // Set divisor (lo byte)
new Move { DestinationReg = Registers.DX, SourceValue = (uint)xComAddr + 1 };
new Move { DestinationReg = Registers.AL, SourceValue = 0x0 };
new Out { Size = 8 }; // (hi byte)
new Move { DestinationReg = Registers.DX, SourceValue = (uint)xComAddr + 3 };
new Move { DestinationReg = Registers.AL, SourceValue = 0x3 };
new Out { Size = 8 }; // 8 bits, no parity, one stop bit
new Move { DestinationReg = Registers.DX, SourceValue = (uint)xComAddr + 2 };
new Move { DestinationReg = Registers.AL, SourceValue = 0xC7 };
new Out { Size = 8 }; // Enable FIFO, clear them, with 14-byte threshold
new Move { DestinationReg = Registers.DX, SourceValue = (uint)xComAddr + 4 };
new Move { DestinationReg = Registers.AL, SourceValue = 0x3 };
new Out { Size = 8 }; // IRQ-s enabled, RTS/DSR set
}
// SSE init
// CR4[bit 9]=1, CR4[bit 10]=1, CR0[bit 2]=0, CR0[bit 1]=1
new Move { DestinationReg = Registers.EAX, SourceReg = Registers.CR4 };
new Or { DestinationReg = Registers.EAX, SourceValue = 0x100 };
new Move { DestinationReg = Registers.CR4, SourceReg = Registers.EAX };
new Move { DestinationReg = Registers.EAX, SourceReg = Registers.CR4 };
new Or { DestinationReg = Registers.EAX, SourceValue = 0x200 };
new Move { DestinationReg = Registers.CR4, SourceReg = Registers.EAX };
new Move { DestinationReg = Registers.EAX, SourceReg = Registers.CR0 };
new And { DestinationReg = Registers.EAX, SourceValue = 0xfffffffd };
new Move { DestinationReg = Registers.CR0, SourceReg = Registers.EAX };
new Move { DestinationReg = Registers.EAX, SourceReg = Registers.CR0 };
new And { DestinationReg = Registers.EAX, SourceValue = 1 };
new Move { DestinationReg = Registers.CR0, SourceReg = Registers.EAX };
// END SSE INIT
new Call { DestinationLabel = EntryPointName };
new Label(".loop");
new ClrInterruptFlag();
new Halt();
new Jump { DestinationLabel = ".loop" };
new Label("DEBUG_STUB_");
new Return();
if (mComNumber > 0) {
var xStub = new DebugStub();
xStub.Main(mComPortAddresses[mComNumber - 1]);
}
//aOutputWriter.WriteLine("section .data");
DataMembers.Add(new DataIfNotDefined("NASM_COMPILATION"));
uint xFlags = 0x10003;
DataMembers.Add(new DataMember("MultibootSignature",
new uint[] { 0x1BADB002 }));
DataMembers.Add(new DataMember("MultibootFlags",
xFlags));
DataMembers.Add(new DataMember("MultibootChecksum",
(int)(0 - (xFlags + 0x1BADB002))));
DataMembers.Add(new DataMember("MultibootHeaderAddr", new ElementReference("MultibootSignature")));
DataMembers.Add(new DataMember("MultibootLoadAddr", new ElementReference("MultibootSignature")));
DataMembers.Add(new DataMember("MultibootLoadEndAddr", 0));
DataMembers.Add(new DataMember("MultibootBSSEndAddr", 0));
DataMembers.Add(new DataMember("MultibootEntryAddr", new ElementReference("Kernel_Start")));
DataMembers.Add(new DataEndIfDefined());
DataMembers.Add(new DataIfDefined("NASM_COMPILATION"));
xFlags = 0x00003;
DataMembers.Add(new DataMember("MultibootSignature",
new uint[] { 0x1BADB002 }));
DataMembers.Add(new DataMember("MultibootFlags",
xFlags));
DataMembers.Add(new DataMember("MultibootChecksum",
(int)(0 - (xFlags + 0x1BADB002))));
DataMembers.Add(new DataEndIfDefined());
DataMembers.Add(new DataMember("MultiBootInfo_Memory_High", 0));
DataMembers.Add(new DataMember("MultiBootInfo_Memory_Low", 0));
DataMembers.Add(new DataMember("Before_Kernel_Stack",
new byte[0x50000]));
DataMembers.Add(new DataMember("Kernel_Stack",
new byte[0]));
DebugStub.EmitDataSection();
}
protected override void OnBeforeFlush() {
base.OnBeforeFlush();
DataMembers.AddRange(new DataMember[]{
new DataMember("_end_data",
new byte[0])});
new Label("_end_code");
}
public override void FlushText(TextWriter aOutput) {
aOutput.WriteLine("use32");
//aOutput.WriteLine("%define NASM_COMPILATION 1");
//aOutput.WriteLine("global Kernel_Start");
aOutput.WriteLine("[map all main.map]");
//aOutput.WriteLine("org 0x500000");
aOutput.WriteLine("org 0x200000");
base.FlushText(aOutput);
}
}

View file

@ -0,0 +1,157 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
namespace Indy.IL2CPU.Assembler.X86 {
public class CosmosAssembler: Assembler {
//TODO: COM Port info - should be in assembler? Assembler should not know about comports...
protected byte mComNumber = 0;
protected UInt16[] mComPortAddresses = { 0x3F8, 0x2F8, 0x3E8, 0x2E8 };
public CosmosAssembler(byte aComNumber) {
mComNumber = aComNumber;
}
private static string GetValidGroupName(string aGroup) {
return aGroup.Replace('-','_').Replace('.', '_');
}
public override void Initialize() {
base.Initialize();
if (mComNumber > 0) {
new Define("DEBUGSTUB");
}
new Label("Kernel_Start");
new Comment("MultiBoot-compliant loader (e.g. GRUB or X.exe) provides info in registers: ");
new Comment("EBX=multiboot_info ");
new Comment("EAX=0x2BADB002 - check if it's really Multiboot loader ");
new Comment(" ;- copy mb info - some stuff for you ");
new Add { DestinationReg = Registers.EBX, SourceValue = 4 };
new Move {
DestinationReg = Registers.EAX,
SourceReg = Registers.EBX,
SourceIsIndirect = true
};
new Move { DestinationRef = new ElementReference("MultiBootInfo_Memory_Low"), DestinationIsIndirect = true, SourceReg = Registers.EAX };
new Add { DestinationReg = Registers.EBX, SourceValue = 4 };
new Move {
DestinationReg = Registers.EAX,
SourceReg = Registers.EBX,
SourceIsIndirect = true
};
new Move { DestinationRef = new ElementReference("MultiBootInfo_Memory_High"), DestinationIsIndirect = true, SourceReg = Registers.EAX };
new Move {
DestinationReg = Registers.ESP,
SourceRef = new ElementReference("Kernel_Stack")
};
new Comment("some more startups todo");
new ClrInterruptFlag();
if (mComNumber > 0) {
UInt16 xComAddr = mComPortAddresses[mComNumber - 1];
// 9600 baud, 8 databits, no parity, 1 stopbit
new Move { DestinationReg = Registers.DX, SourceValue = (uint)xComAddr + 1 };
new Move { DestinationReg = Registers.AL, SourceValue = 0 };
new Out { Size = 8 }; // disable interrupts for serial stuff
new Move { DestinationReg = Registers.DX, SourceValue = (uint)xComAddr + 3 };
new Move { DestinationReg = Registers.AL, SourceValue = 0x80 };
new Out { Size = 8 }; // Enable DLAB (set baud rate divisor)
new Move { DestinationReg = Registers.DX, SourceValue = (uint)xComAddr };
new Move { DestinationReg = Registers.AL, SourceValue = 0xC };
new Out { Size = 8 }; // Set divisor (lo byte)
new Move { DestinationReg = Registers.DX, SourceValue = (uint)xComAddr + 1 };
new Move { DestinationReg = Registers.AL, SourceValue = 0x0 };
new Out { Size = 8 }; // (hi byte)
new Move { DestinationReg = Registers.DX, SourceValue = (uint)xComAddr + 3 };
new Move { DestinationReg = Registers.AL, SourceValue = 0x3 };
new Out { Size = 8 }; // 8 bits, no parity, one stop bit
new Move { DestinationReg = Registers.DX, SourceValue = (uint)xComAddr + 2 };
new Move { DestinationReg = Registers.AL, SourceValue = 0xC7 };
new Out { Size = 8 }; // Enable FIFO, clear them, with 14-byte threshold
new Move { DestinationReg = Registers.DX, SourceValue = (uint)xComAddr + 4 };
new Move { DestinationReg = Registers.AL, SourceValue = 0x3 };
new Out { Size = 8 }; // IRQ-s enabled, RTS/DSR set
}
// SSE init
// CR4[bit 9]=1, CR4[bit 10]=1, CR0[bit 2]=0, CR0[bit 1]=1
new Move { DestinationReg = Registers.EAX, SourceReg = Registers.CR4 };
new Or { DestinationReg = Registers.EAX, SourceValue = 0x100 };
new Move { DestinationReg = Registers.CR4, SourceReg = Registers.EAX };
new Move { DestinationReg = Registers.EAX, SourceReg = Registers.CR4 };
new Or { DestinationReg = Registers.EAX, SourceValue = 0x200 };
new Move { DestinationReg = Registers.CR4, SourceReg = Registers.EAX };
new Move { DestinationReg = Registers.EAX, SourceReg = Registers.CR0 };
new And { DestinationReg = Registers.EAX, SourceValue = 0xfffffffd };
new Move { DestinationReg = Registers.CR0, SourceReg = Registers.EAX };
new Move { DestinationReg = Registers.EAX, SourceReg = Registers.CR0 };
new And { DestinationReg = Registers.EAX, SourceValue = 1 };
new Move { DestinationReg = Registers.CR0, SourceReg = Registers.EAX };
// END SSE INIT
new Call { DestinationLabel = EntryPointName };
new Label(".loop");
new ClrInterruptFlag();
new Halt();
new Jump { DestinationLabel = ".loop" };
new Label("DEBUG_STUB_");
new Return();
if (mComNumber > 0) {
var xStub = new DebugStub();
xStub.Main(mComPortAddresses[mComNumber - 1]);
}
//aOutputWriter.WriteLine("section .data");
DataMembers.Add(new DataIfNotDefined("NASM_COMPILATION"));
uint xFlags = 0x10003;
DataMembers.Add(new DataMember("MultibootSignature",
new uint[] { 0x1BADB002 }));
DataMembers.Add(new DataMember("MultibootFlags",
xFlags));
DataMembers.Add(new DataMember("MultibootChecksum",
(int)(0 - (xFlags + 0x1BADB002))));
DataMembers.Add(new DataMember("MultibootHeaderAddr", new ElementReference("MultibootSignature")));
DataMembers.Add(new DataMember("MultibootLoadAddr", new ElementReference("MultibootSignature")));
DataMembers.Add(new DataMember("MultibootLoadEndAddr", 0));
DataMembers.Add(new DataMember("MultibootBSSEndAddr", 0));
DataMembers.Add(new DataMember("MultibootEntryAddr", new ElementReference("Kernel_Start")));
DataMembers.Add(new DataEndIfDefined());
DataMembers.Add(new DataIfDefined("NASM_COMPILATION"));
xFlags = 0x00003;
DataMembers.Add(new DataMember("MultibootSignature",
new uint[] { 0x1BADB002 }));
DataMembers.Add(new DataMember("MultibootFlags",
xFlags));
DataMembers.Add(new DataMember("MultibootChecksum",
(int)(0 - (xFlags + 0x1BADB002))));
DataMembers.Add(new DataEndIfDefined());
DataMembers.Add(new DataMember("MultiBootInfo_Memory_High", 0));
DataMembers.Add(new DataMember("MultiBootInfo_Memory_Low", 0));
DataMembers.Add(new DataMember("Before_Kernel_Stack",
new byte[0x50000]));
DataMembers.Add(new DataMember("Kernel_Stack",
new byte[0]));
DebugStub.EmitDataSection();
}
protected override void OnBeforeFlush() {
base.OnBeforeFlush();
DataMembers.AddRange(new DataMember[]{
new DataMember("_end_data",
new byte[0])});
new Label("_end_code");
}
public override void FlushText(TextWriter aOutput) {
//aOutput.WriteLine("use32");
//aOutput.WriteLine("%define NASM_COMPILATION 1");
//aOutput.WriteLine("global Kernel_Start");
aOutput.WriteLine("[map all main.map]");
//aOutput.WriteLine("org 0x500000");
base.FlushText(aOutput);
}
}
}

View file

@ -8,7 +8,7 @@ namespace Indy.IL2CPU.Assembler.X86
{
public static void InitializeEncodingData(Instruction.InstructionData aData) {
aData.EncodingOptions.Add(new InstructionData.InstructionEncodingOption {
OpCode= new byte[0xF4]
OpCode= new byte[]{0xF4}
});
}
}

View file

@ -16,5 +16,15 @@ namespace Indy.IL2CPU.Assembler.X86 {
DestinationRef = new ElementReference(value);
}
}
public override string ToString() {
var xResult = base.ToString();
if (!xResult.StartsWith(Mnemonic + " near", StringComparison.InvariantCultureIgnoreCase)) {
if (xResult.StartsWith(Mnemonic)) {
return Mnemonic + " near " + xResult.Substring(Mnemonic.Length + 1);
}
}
return xResult;
}
}
}

View file

@ -7,14 +7,23 @@ namespace Indy.IL2CPU.Assembler.X86 {
[OpCode("mov")]
public class Move: InstructionWithDestinationAndSourceAndSize {
public static void InitializeEncodingData(Instruction.InstructionData aData){
aData.DefaultSize = false;
aData.EncodingOptions.Add(new InstructionData.InstructionEncodingOption {
OpCode = new byte[] { 0xB0 },
//NeedsModRMByte=true,
OperandSizeByte=0,
OperandSizeBitShiftLeft = 3,
DestinationReg=Guid.Empty,
DestinationRegByte=0,
SourceImmediate=true
}); // immediate to register
aData.EncodingOptions.Add(new InstructionData.InstructionEncodingOption {
OpCode = new byte[] { 0xC6 },
NeedsModRMByte=true,
OperandSizeByte=0,
DestinationReg=Guid.Empty,
DestinationRegByte=1,
SourceImmediate=true
});
//NeedsModRMByte=true,
OperandSizeByte = 0,
OperandSizeBitShiftLeft = 0,
SourceImmediate = true
}); // immediate to memory
}
}
}

View file

@ -6,5 +6,8 @@ using System.Text;
namespace Indy.IL2CPU.Assembler.X86 {
[OpCode("push")]
public class Push : InstructionWithDestinationAndSize {
public Push() {
Size = 32;
}
}
}

View file

@ -0,0 +1,35 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Indy.IL2CPU.Assembler.X86.X {
public class RegisterEBX : Register32 {
public const string Name = "EBX";
public static readonly RegisterEBX Instance = new RegisterEBX();
public override string ToString() {
return Name;
}
public static implicit operator RegisterEBX(ElementReference aReference) {
Instance.Move(aReference);
return Instance;
}
public static implicit operator RegisterEBX(MemoryAction aAction) {
Instance.Move(aAction);
return Instance;
}
public static implicit operator RegisterEBX(UInt32 aValue) {
Instance.Move(aValue);
return Instance;
}
public static implicit operator RegisterEBX(RegisterECX aValue) {
Instance.Move(aValue.GetId());
return Instance;
}
}
}

View file

@ -13,7 +13,8 @@ namespace Indy.IL2CPU.Assembler.X86.X {
//TODO: Add registers as needed, not all are here yet
public RegisterEAX EAX = RegisterEAX.Instance;
public RegisterAL AL = RegisterAL.Instance;
public RegisterEBX EBX = RegisterEBX.Instance;
public RegisterECX ECX = RegisterECX.Instance;
public RegisterEDX EDX = RegisterEDX.Instance;

View file

@ -13,7 +13,7 @@ namespace Indy.IL2CPU.Assembler.X86 {
if (aThis.DestinationReg != Guid.Empty) {
xDest = Registers.GetRegisterName(aThis.DestinationReg);
} else {
xDest = "0x" + aThis.DestinationValue.ToString("X").ToUpperInvariant();
xDest = "0x" + aThis.DestinationValue.GetValueOrDefault().ToString("X").ToUpperInvariant();
}
}
if (aThis.DestinationDisplacement != 0) {

View file

@ -15,7 +15,7 @@ namespace Indy.IL2CPU.Assembler.X86 {
set;
}
uint DestinationValue {
uint? DestinationValue {
get;
set;
}

View file

@ -15,7 +15,7 @@ namespace Indy.IL2CPU.Assembler.X86 {
set;
}
uint SourceValue {
uint? SourceValue {
get;
set;
}

View file

@ -73,6 +73,10 @@ namespace Indy.IL2CPU.Assembler.X86 {
public bool HasDestinationOperand;
public bool HasSourceOperand;
/// <summary>
/// True if by default large (32bit), false if small (16bit)
/// </summary>
public bool? DefaultSize;
public List<InstructionEncodingOption> EncodingOptions = new List<InstructionEncodingOption>();
}
@ -131,8 +135,261 @@ namespace Indy.IL2CPU.Assembler.X86 {
case 64:
return "qword";
default:
return "non-existing size!!";
throw new Exception("Invalid size: " + aSize);
}
}
}
public override bool DetermineSize(Indy.IL2CPU.Assembler.Assembler aAssembler, out ulong aSize) {
InstructionData xInstructionData = null;
using (mInstructionDatasLocker.AcquireReaderLock()) {
mInstructionDatas.TryGetValue(this.GetType(), out xInstructionData);
}
if (xInstructionData == null) {
return base.DetermineSize(aAssembler, out aSize);
}
var xWithDestAndSourceAndSize = this as InstructionWithDestinationAndSourceAndSize;
if (xWithDestAndSourceAndSize != null) {
return DetermineSize(xWithDestAndSourceAndSize, xInstructionData, out aSize);
}
var xWithDestAndSource = this as InstructionWithDestinationAndSource;
if (xWithDestAndSource != null) {
return base.DetermineSize(aAssembler, out aSize);
}
var xWithDestAndSize = this as InstructionWithDestinationAndSize;
if (xWithDestAndSize != null) {
return base.DetermineSize(aAssembler, out aSize);
}
var xWithDest = this as InstructionWithDestination;
if (xWithDest != null) {
return base.DetermineSize(aAssembler, out aSize);
}
if (xInstructionData.EncodingOptions.Count > 0) {
// todo: improve
aSize = (ulong)xInstructionData.EncodingOptions[0].OpCode.Length;
return true;
}
aSize = 0;
return false;
}
private static bool DetermineSize(InstructionWithDestinationAndSourceAndSize aInstruction, InstructionData aInstructionData, out ulong aSize) {
var xTheEncodingOption = GetInstructionEncodingOption(aInstruction, aInstructionData);
aSize = (ulong)xTheEncodingOption.OpCode.Length;
if (xTheEncodingOption.NeedsModRMByte) {
aSize += 1;
}
if (aInstruction.DestinationValue.HasValue || aInstruction.DestinationRef != null) {
aSize += 4;
}
if (aInstruction.SourceValue.HasValue || aInstruction.SourceRef != null) {
aSize += 4;
}
if (aInstructionData.DefaultSize.HasValue && aInstructionData.DefaultSize.Value) {
if (aInstruction.Size < 16) {
aSize += 1;
}
}
return true;
}
private static InstructionData.InstructionEncodingOption GetInstructionEncodingOption(InstructionWithDestinationAndSourceAndSize aInstruction, InstructionData aInstructionData) {
InstructionData.InstructionEncodingOption xTheEncodingOption = null;
for (int i = 0; i < aInstructionData.EncodingOptions.Count; i++) {
var xEncodingOption = aInstructionData.EncodingOptions[i];
if (!((xEncodingOption.DestinationReg.HasValue && aInstruction.DestinationReg != Guid.Empty) ||
(!xEncodingOption.DestinationReg.HasValue && aInstruction.DestinationReg == Guid.Empty))) {
// mismatch
continue;
}
if (!((xEncodingOption.DestinationMemory && (aInstruction.DestinationValue != null && aInstruction.DestinationIsIndirect)) ||
(!xEncodingOption.DestinationMemory && (aInstruction.DestinationValue == null && !aInstruction.DestinationIsIndirect))) && aInstruction.DestinationIsIndirect) {
continue;
}
if (!((xEncodingOption.DestinationImmediate && aInstruction.DestinationValue != null) ||
(!xEncodingOption.DestinationImmediate && aInstruction.DestinationValue == null))) {
continue;
}
if (!((xEncodingOption.SourceReg.HasValue && aInstruction.SourceReg != Guid.Empty) ||
(!xEncodingOption.SourceReg.HasValue && aInstruction.SourceReg == Guid.Empty))) {
// mismatch
continue;
}
if (!((xEncodingOption.SourceMemory && (aInstruction.SourceValue != null && aInstruction.SourceIsIndirect)) ||
(!xEncodingOption.SourceMemory && (aInstruction.SourceValue == null && !aInstruction.SourceIsIndirect))) && aInstruction.SourceIsIndirect) {
continue;
}
if (!((xEncodingOption.SourceImmediate && aInstruction.SourceValue != null) ||
(!xEncodingOption.SourceImmediate && aInstruction.SourceValue == null))) {
continue;
}
xTheEncodingOption = xEncodingOption;
break;
}
if (xTheEncodingOption == null) {
throw new Exception("No valid EncodingOption found!");
}
return xTheEncodingOption;
}
public override byte[] GetData(Indy.IL2CPU.Assembler.Assembler aAssembler) {
InstructionData xInstructionData = null;
using (mInstructionDatasLocker.AcquireReaderLock()) {
mInstructionDatas.TryGetValue(this.GetType(), out xInstructionData);
}
if (xInstructionData == null) {
return base.GetData(aAssembler);
}
var xWithDestAndSourceAndSize = this as InstructionWithDestinationAndSourceAndSize;
if (xWithDestAndSourceAndSize != null) {
return GetData(aAssembler, xWithDestAndSourceAndSize, xInstructionData);
}
var xWithDestAndSource = this as InstructionWithDestinationAndSource;
if (xWithDestAndSource != null) {
return base.GetData(aAssembler);
}
var xWithDestAndSize = this as InstructionWithDestinationAndSize;
if (xWithDestAndSize != null) {
return base.GetData(aAssembler);
}
var xWithDest = this as InstructionWithDestination;
if (xWithDest != null) {
return base.GetData(aAssembler);
}
if (xInstructionData.EncodingOptions.Count > 0) {
// todo: improve
return xInstructionData.EncodingOptions[0].OpCode;
}
return null;
}
private static byte[] GetData(Indy.IL2CPU.Assembler.Assembler aAssembler, InstructionWithDestinationAndSourceAndSize aInstruction, InstructionData aInstructionData) {
var xEncodingOption = GetInstructionEncodingOption(aInstruction, aInstructionData);
var xSize = xEncodingOption.OpCode.Length;
if (xEncodingOption.NeedsModRMByte) {
xSize += 1;
}
if (aInstruction.DestinationValue.HasValue || aInstruction.DestinationRef != null) {
xSize += 4;
}
if (aInstruction.SourceValue.HasValue || aInstruction.SourceRef != null) {
xSize += 4;
}
int xExtraOffset = 0;
if (aInstructionData.DefaultSize.HasValue && aInstructionData.DefaultSize.Value) {
if (aInstruction.Size < 16) {
xSize += 1;
xExtraOffset = 1;
}
}
var xBuffer = new byte[xSize];
Array.Copy(xEncodingOption.OpCode, 0, xBuffer, xExtraOffset, xEncodingOption.OpCode.Length);
if (xExtraOffset == 1) {
throw new Exception("OperandSize prefix needed!");
}
if (xEncodingOption.NeedsModRMByte) {
if(aInstruction.DestinationReg != Guid.Empty && !aInstruction.DestinationIsIndirect) {
xBuffer[xEncodingOption.OpCode.Length] |= 0xC0;
}
if(aInstruction.DestinationReg != Guid.Empty && aInstruction.DestinationIsIndirect) {
//
}
// todo: add more ModRM stuff
}
if (aInstruction.DestinationReg != Guid.Empty) {
xBuffer[xEncodingOption.DestinationRegByte] |= (byte)(EncodeRegister(aInstruction.DestinationReg) << xEncodingOption.DestinationRegBitShiftLeft);
}
// todo: add more options
if (aInstruction.SourceValue.HasValue) {
int xOffset = xEncodingOption.OpCode.Length + xExtraOffset;
if(xEncodingOption.NeedsModRMByte) {
xOffset++;
}
Array.Copy(BitConverter.GetBytes(aInstruction.SourceValue.Value), 0, xBuffer, xOffset, 4);
}
if(aInstructionData.DefaultSize.HasValue) {
if(!aInstructionData.DefaultSize.Value && aInstruction.Size > 16) {
xBuffer[xEncodingOption.OperandSizeByte] |= (byte)(1 << xEncodingOption.OperandSizeBitShiftLeft);
}
}
//
return xBuffer;
}
private static byte EncodeRegister(Guid aRegister) {
// todo: implement support for other registers
if (!Registers.Is32Bit(aRegister)) {
throw new Exception("Register not supported!");
}
if (aRegister == Registers.EAX) return 0x0;
if (aRegister == Registers.ECX) return 0x1;
if (aRegister == Registers.EDX) return 0x2;
if (aRegister == Registers.EBX) return 0x3;
if (aRegister == Registers.ESP) return 0x4;
if (aRegister == Registers.EBP) return 0x5;
if (aRegister == Registers.ESI) return 0x6;
if (aRegister == Registers.EDI) return 0x7;
throw new Exception("Register not supported!");
}
private ulong? mDataSize;
public override bool IsComplete(Indy.IL2CPU.Assembler.Assembler aAssembler) {
var xWithDestAndSourceAndSize = this as InstructionWithDestinationAndSourceAndSize;
if (xWithDestAndSourceAndSize != null) {
ulong xAddress;
if (xWithDestAndSourceAndSize.DestinationRef != null && !xWithDestAndSourceAndSize.DestinationRef.Resolve(aAssembler, out xAddress)) {
return false;
}
if (xWithDestAndSourceAndSize.DestinationRef != null && !xWithDestAndSourceAndSize.SourceRef.Resolve(aAssembler, out xAddress)) {
return false;
}
}
var xWithDestAndSource = this as InstructionWithDestinationAndSource;
if (xWithDestAndSource != null) {
ulong xAddress;
if (xWithDestAndSource.DestinationRef != null && !xWithDestAndSource.DestinationRef.Resolve(aAssembler, out xAddress)) {
return false;
}
if (xWithDestAndSource.DestinationRef != null && !xWithDestAndSource.SourceRef.Resolve(aAssembler, out xAddress)) {
return false;
}
}
var xWithDestAndSize = this as InstructionWithDestinationAndSize;
if (xWithDestAndSize != null) {
ulong xAddress;
if (xWithDestAndSize.DestinationRef != null && !xWithDestAndSize.DestinationRef.Resolve(aAssembler, out xAddress)) {
return false;
}
}
var xWithDest = this as InstructionWithDestination;
if (xWithDest != null) {
ulong xAddress;
if (xWithDest.DestinationRef!=null && !xWithDest.DestinationRef.Resolve(aAssembler, out xAddress)) {
return false;
}
}
return true;
}
public override ulong? ActualAddress {
get {
if (!StartAddress.HasValue) {
return null;
}
if(!mDataSize.HasValue){
return null;
}
return StartAddress.Value + mDataSize.Value;
}
}
private static bool IsLargeRegister(Guid aRegister) {
return Registers.Is32Bit(aRegister);
}
}
}

View file

@ -15,7 +15,7 @@ namespace Indy.IL2CPU.Assembler.X86 {
set;
}
public uint DestinationValue {
public uint? DestinationValue {
get;
set;
}

View file

@ -15,7 +15,7 @@ namespace Indy.IL2CPU.Assembler.X86 {
set;
}
public uint SourceValue {
public uint? SourceValue {
get;
set;
}
@ -38,7 +38,7 @@ namespace Indy.IL2CPU.Assembler.X86 {
if (SourceReg != Guid.Empty) {
xDest = Registers.GetRegisterName(SourceReg);
} else {
xDest = "0x" + SourceValue.ToString("X").ToUpperInvariant();
xDest = "0x" + SourceValue.GetValueOrDefault().ToString("X").ToUpperInvariant();
}
}
if (SourceDisplacement != 0) {

View file

@ -167,10 +167,9 @@ namespace Indy.IL2CPU {
switch (aTargetPlatform) {
case TargetPlatformEnum.X86: {
mMap = new Indy.IL2CPU.IL.X86.X86OpCodeMap();
mAssembler = new Assembler.X86.Assembler(aGetFileNameForGroup,
((aDebugMode != DebugMode.None) && (aDebugMode != DebugMode.MLUsingGDB))
? aDebugComNumber
: (byte)0);
mAssembler = new Assembler.X86.CosmosAssembler(((aDebugMode != DebugMode.None) && (aDebugMode != DebugMode.MLUsingGDB))
? aDebugComNumber
: (byte)0);
break;
}
default:

View file

@ -54,11 +54,11 @@ namespace Indy.IL2CPU.IL.X86 {
new CPUx86.Pop { DestinationReg = CPUx86.Registers.ESI};
new CPUx86.Push { DestinationReg = CPUx86.Registers.ESI };
//Assembler.StackSizes.Push(xElementCountSize);
new CPUx86.Push { DestinationValue = mElementSize };
new CPUx86.Push { Size=32,DestinationValue = mElementSize };
Assembler.StackContents.Push(new StackContent(4, typeof(uint)));
Multiply(Assembler);
// the total items size is now on the stack
new CPUx86.Push { DestinationValue = (ObjectImpl.FieldDataOffset + 4) };
new CPUx86.Push { Size=32,DestinationValue = (ObjectImpl.FieldDataOffset + 4) };
Assembler.StackContents.Push(new StackContent(4, typeof(uint)));
Add(Assembler);
// the total array size is now on the stack.

View file

@ -233,7 +233,7 @@ namespace Indy.IL2CPU.IL.X86 {
throw new Exception("Remainder size " + (aField.Size) + " not supported!");
}
if (aAddGCCode && aField.NeedsGC) {
new CPUx86.Push { DestinationReg = Registers.ESP, DestinationIsIndirect = true };
new CPUx86.Push {Size=32, DestinationReg = Registers.ESP, DestinationIsIndirect = true };
Engine.QueueMethod(GCImplementationRefs.IncRefCountRef);
new CPUx86.Call { DestinationLabel = Label.GenerateLabelName(GCImplementationRefs.IncRefCountRef) };
}

View file

@ -16,7 +16,7 @@ namespace Indy.IL2CPU.IL.X86 {
}
public override void Push(uint aValue) {
new CPUx86.Push { DestinationValue = aValue };
new CPUx86.Push {Size=32, DestinationValue = aValue };
}
private int xLabelId = 0;

View file

@ -44,7 +44,7 @@ namespace Indy.IL2CPU.IL.X86 {
foreach (var xLocal in aLocals) {
aAssembler.StackContents.Push(new StackContent(xLocal.Size, xLocal.VariableType));
for (int i = 0; i < (xLocal.Size / 4); i++) {
new CPUx86.Push{DestinationValue=0};
new CPUx86.Push{Size=32,DestinationValue=0};
}
}
if(aDebugMode&& aIsNonDebuggable) {

View file

@ -90,11 +90,13 @@
<Compile Include="Assembler\EndIfDefined.cs" />
<Compile Include="Assembler\IfDefined.cs" />
<Compile Include="Assembler\IfNotDefined.cs" />
<Compile Include="Assembler\x86\CosmosAssembler.cs" />
<Compile Include="Assembler\x86\In.cs" />
<Compile Include="Assembler\x86\JumpToSegment.cs" />
<Compile Include="Assembler\x86\MoveIfBelow.cs" />
<Compile Include="Assembler\x86\MoveIfLess.cs" />
<Compile Include="Assembler\x86\Registers_Old.cs" />
<Compile Include="Assembler\x86\X\RegisterEBX.cs" />
<Compile Include="Assembler\x86\_Infra\Extensions.cs" />
<Compile Include="Assembler\x86\_Infra\IInstructionWithDestination.cs" />
<Compile Include="Assembler\x86\_Infra\IInstructionWithSize.cs" />

View file

@ -12,7 +12,8 @@ namespace TestApp {
class Renderer : Y86 {
public void DoRender() {
Label = "Kernel_Start";
EAX = 0xB8000;
EBX = 0xB8000;
Memory[EBX, 8] = 65;
//IfDefined("DefinedSymbol");
//Memory[0xB8002, 8] = 66;
//Memory[0xB8003, 8] = 15;
@ -26,11 +27,7 @@ namespace TestApp {
}
static void Main(string[] args) {
try {
var xAsm = new Assembler(delegate(string aGroup) {
return Path.Combine(Path.Combine(Path.GetDirectoryName(Assembly.GetEntryAssembly().Location),
"Output"),
aGroup + ".out");
});
var xAsm = new Assembler();
xAsm.Initialize();
xAsm.DataMembers.Add(new Indy.IL2CPU.Assembler.DataMember("TestData", new byte[]{65, 66, 67, 68,69,70, 71, 72, 73, 74}));
xAsm.Instructions.Clear();
@ -42,17 +39,17 @@ namespace TestApp {
Directory.CreateDirectory(Path.Combine(Path.GetDirectoryName(Assembly.GetEntryAssembly().Location),
"Output"));
}
//using (Stream xOutput = new FileStream(Path.Combine(Path.Combine(Path.GetDirectoryName(Assembly.GetEntryAssembly().Location),
// "Output"),
// "TheOutput.out"), FileMode.Create)) {
// xAsm.FlushBinary(xOutput, 0x500000);
//}
using (StreamWriter xOutput = new StreamWriter(Path.Combine(Path.Combine(Path.GetDirectoryName(Assembly.GetEntryAssembly().Location),
using (Stream xOutput = new FileStream(Path.Combine(Path.Combine(Path.GetDirectoryName(Assembly.GetEntryAssembly().Location),
"Output"),
"TheOutput.out"))) {
xAsm.FlushText(xOutput);
}
"TheOutput.bin"), FileMode.Create)) {
xAsm.FlushBinary(xOutput, 0x500000);
}
//using (StreamWriter xOutput = new StreamWriter(Path.Combine(Path.Combine(Path.GetDirectoryName(Assembly.GetEntryAssembly().Location),
// "Output"),
// "TheOutput.asm"))) {
// xAsm.FlushText(xOutput);
//}
// now the file should have been written
} catch (Exception E) { Console.WriteLine(E.ToString()); }