mirror of
https://github.com/danbulant/Cosmos
synced 2026-05-27 05:52:11 +00:00
Some smaller refactorings and misc changes
This commit is contained in:
parent
ab7807cdb0
commit
ec5eebdeed
24 changed files with 545 additions and 210 deletions
|
|
@ -92,8 +92,6 @@ namespace Indy.IL2CPU.Assembler {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Func<string, string> mGetFileNameForGroup;
|
|
||||||
|
|
||||||
private uint mDataMemberCounter = 0;
|
private uint mDataMemberCounter = 0;
|
||||||
|
|
||||||
public string GetIdentifier(string aPrefix) {
|
public string GetIdentifier(string aPrefix) {
|
||||||
|
|
@ -101,29 +99,11 @@ namespace Indy.IL2CPU.Assembler {
|
||||||
return aPrefix + mDataMemberCounter.ToString("X8").ToUpper();
|
return aPrefix + mDataMemberCounter.ToString("X8").ToUpper();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Assembler(Func<string, string> aGetFileNameForGroup) {
|
public Assembler() {
|
||||||
mGetFileNameForGroup = aGetFileNameForGroup;
|
|
||||||
CurrentInstance.Push(this);
|
CurrentInstance.Push(this);
|
||||||
//mInstructions.AddComplexIndexDefinition(
|
//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 {
|
public List<DataMember> DataMembers {
|
||||||
get { return mDataMembers; }
|
get { return mDataMembers; }
|
||||||
}
|
}
|
||||||
|
|
@ -294,7 +274,9 @@ namespace Indy.IL2CPU.Assembler {
|
||||||
}
|
}
|
||||||
if (mInstructions.Count > 0) {
|
if (mInstructions.Count > 0) {
|
||||||
string xMainLabel="";
|
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";
|
string prefix = "\t\t\t";
|
||||||
Label xLabel = x as Label;
|
Label xLabel = x as Label;
|
||||||
if (xLabel != null) {
|
if (xLabel != null) {
|
||||||
|
|
|
||||||
|
|
@ -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 {
|
public int Offset {
|
||||||
get;
|
get;
|
||||||
set;
|
set;
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,6 @@ using System.IO;
|
||||||
|
|
||||||
namespace Indy.IL2CPU.Assembler {
|
namespace Indy.IL2CPU.Assembler {
|
||||||
public class RawAssembler : Assembler {
|
public class RawAssembler : Assembler {
|
||||||
public RawAssembler() : base(null) { }
|
public RawAssembler() : base() { }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,155 +6,9 @@ using System.Text;
|
||||||
|
|
||||||
namespace Indy.IL2CPU.Assembler.X86 {
|
namespace Indy.IL2CPU.Assembler.X86 {
|
||||||
public class Assembler : Indy.IL2CPU.Assembler.Assembler {
|
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) {
|
public override void FlushText(TextWriter aOutput) {
|
||||||
aOutput.WriteLine("use32");
|
aOutput.WriteLine("use32");
|
||||||
//aOutput.WriteLine("%define NASM_COMPILATION 1");
|
aOutput.WriteLine("org 0x200000");
|
||||||
//aOutput.WriteLine("global Kernel_Start");
|
|
||||||
aOutput.WriteLine("[map all main.map]");
|
|
||||||
//aOutput.WriteLine("org 0x500000");
|
|
||||||
base.FlushText(aOutput);
|
base.FlushText(aOutput);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
157
source/Indy.IL2CPU/Assembler/x86/CosmosAssembler.cs
Normal file
157
source/Indy.IL2CPU/Assembler/x86/CosmosAssembler.cs
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -8,7 +8,7 @@ namespace Indy.IL2CPU.Assembler.X86
|
||||||
{
|
{
|
||||||
public static void InitializeEncodingData(Instruction.InstructionData aData) {
|
public static void InitializeEncodingData(Instruction.InstructionData aData) {
|
||||||
aData.EncodingOptions.Add(new InstructionData.InstructionEncodingOption {
|
aData.EncodingOptions.Add(new InstructionData.InstructionEncodingOption {
|
||||||
OpCode= new byte[0xF4]
|
OpCode= new byte[]{0xF4}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -16,5 +16,15 @@ namespace Indy.IL2CPU.Assembler.X86 {
|
||||||
DestinationRef = new ElementReference(value);
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -7,14 +7,23 @@ namespace Indy.IL2CPU.Assembler.X86 {
|
||||||
[OpCode("mov")]
|
[OpCode("mov")]
|
||||||
public class Move: InstructionWithDestinationAndSourceAndSize {
|
public class Move: InstructionWithDestinationAndSourceAndSize {
|
||||||
public static void InitializeEncodingData(Instruction.InstructionData aData){
|
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 {
|
aData.EncodingOptions.Add(new InstructionData.InstructionEncodingOption {
|
||||||
OpCode = new byte[] { 0xC6 },
|
OpCode = new byte[] { 0xC6 },
|
||||||
NeedsModRMByte=true,
|
//NeedsModRMByte=true,
|
||||||
OperandSizeByte=0,
|
OperandSizeByte = 0,
|
||||||
DestinationReg=Guid.Empty,
|
OperandSizeBitShiftLeft = 0,
|
||||||
DestinationRegByte=1,
|
SourceImmediate = true
|
||||||
SourceImmediate=true
|
}); // immediate to memory
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,5 +6,8 @@ using System.Text;
|
||||||
namespace Indy.IL2CPU.Assembler.X86 {
|
namespace Indy.IL2CPU.Assembler.X86 {
|
||||||
[OpCode("push")]
|
[OpCode("push")]
|
||||||
public class Push : InstructionWithDestinationAndSize {
|
public class Push : InstructionWithDestinationAndSize {
|
||||||
|
public Push() {
|
||||||
|
Size = 32;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
35
source/Indy.IL2CPU/Assembler/x86/X/RegisterEBX.cs
Normal file
35
source/Indy.IL2CPU/Assembler/x86/X/RegisterEBX.cs
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -14,6 +14,7 @@ namespace Indy.IL2CPU.Assembler.X86.X {
|
||||||
public RegisterEAX EAX = RegisterEAX.Instance;
|
public RegisterEAX EAX = RegisterEAX.Instance;
|
||||||
public RegisterAL AL = RegisterAL.Instance;
|
public RegisterAL AL = RegisterAL.Instance;
|
||||||
|
|
||||||
|
public RegisterEBX EBX = RegisterEBX.Instance;
|
||||||
public RegisterECX ECX = RegisterECX.Instance;
|
public RegisterECX ECX = RegisterECX.Instance;
|
||||||
|
|
||||||
public RegisterEDX EDX = RegisterEDX.Instance;
|
public RegisterEDX EDX = RegisterEDX.Instance;
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ namespace Indy.IL2CPU.Assembler.X86 {
|
||||||
if (aThis.DestinationReg != Guid.Empty) {
|
if (aThis.DestinationReg != Guid.Empty) {
|
||||||
xDest = Registers.GetRegisterName(aThis.DestinationReg);
|
xDest = Registers.GetRegisterName(aThis.DestinationReg);
|
||||||
} else {
|
} else {
|
||||||
xDest = "0x" + aThis.DestinationValue.ToString("X").ToUpperInvariant();
|
xDest = "0x" + aThis.DestinationValue.GetValueOrDefault().ToString("X").ToUpperInvariant();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (aThis.DestinationDisplacement != 0) {
|
if (aThis.DestinationDisplacement != 0) {
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ namespace Indy.IL2CPU.Assembler.X86 {
|
||||||
set;
|
set;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint DestinationValue {
|
uint? DestinationValue {
|
||||||
get;
|
get;
|
||||||
set;
|
set;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ namespace Indy.IL2CPU.Assembler.X86 {
|
||||||
set;
|
set;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint SourceValue {
|
uint? SourceValue {
|
||||||
get;
|
get;
|
||||||
set;
|
set;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -73,6 +73,10 @@ namespace Indy.IL2CPU.Assembler.X86 {
|
||||||
public bool HasDestinationOperand;
|
public bool HasDestinationOperand;
|
||||||
public bool HasSourceOperand;
|
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>();
|
public List<InstructionEncodingOption> EncodingOptions = new List<InstructionEncodingOption>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -131,8 +135,261 @@ namespace Indy.IL2CPU.Assembler.X86 {
|
||||||
case 64:
|
case 64:
|
||||||
return "qword";
|
return "qword";
|
||||||
default:
|
default:
|
||||||
|
return "non-existing size!!";
|
||||||
throw new Exception("Invalid size: " + aSize);
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ namespace Indy.IL2CPU.Assembler.X86 {
|
||||||
set;
|
set;
|
||||||
}
|
}
|
||||||
|
|
||||||
public uint DestinationValue {
|
public uint? DestinationValue {
|
||||||
get;
|
get;
|
||||||
set;
|
set;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ namespace Indy.IL2CPU.Assembler.X86 {
|
||||||
set;
|
set;
|
||||||
}
|
}
|
||||||
|
|
||||||
public uint SourceValue {
|
public uint? SourceValue {
|
||||||
get;
|
get;
|
||||||
set;
|
set;
|
||||||
}
|
}
|
||||||
|
|
@ -38,7 +38,7 @@ namespace Indy.IL2CPU.Assembler.X86 {
|
||||||
if (SourceReg != Guid.Empty) {
|
if (SourceReg != Guid.Empty) {
|
||||||
xDest = Registers.GetRegisterName(SourceReg);
|
xDest = Registers.GetRegisterName(SourceReg);
|
||||||
} else {
|
} else {
|
||||||
xDest = "0x" + SourceValue.ToString("X").ToUpperInvariant();
|
xDest = "0x" + SourceValue.GetValueOrDefault().ToString("X").ToUpperInvariant();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (SourceDisplacement != 0) {
|
if (SourceDisplacement != 0) {
|
||||||
|
|
|
||||||
|
|
@ -167,10 +167,9 @@ namespace Indy.IL2CPU {
|
||||||
switch (aTargetPlatform) {
|
switch (aTargetPlatform) {
|
||||||
case TargetPlatformEnum.X86: {
|
case TargetPlatformEnum.X86: {
|
||||||
mMap = new Indy.IL2CPU.IL.X86.X86OpCodeMap();
|
mMap = new Indy.IL2CPU.IL.X86.X86OpCodeMap();
|
||||||
mAssembler = new Assembler.X86.Assembler(aGetFileNameForGroup,
|
mAssembler = new Assembler.X86.CosmosAssembler(((aDebugMode != DebugMode.None) && (aDebugMode != DebugMode.MLUsingGDB))
|
||||||
((aDebugMode != DebugMode.None) && (aDebugMode != DebugMode.MLUsingGDB))
|
? aDebugComNumber
|
||||||
? aDebugComNumber
|
: (byte)0);
|
||||||
: (byte)0);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
|
|
|
||||||
|
|
@ -54,11 +54,11 @@ namespace Indy.IL2CPU.IL.X86 {
|
||||||
new CPUx86.Pop { DestinationReg = CPUx86.Registers.ESI};
|
new CPUx86.Pop { DestinationReg = CPUx86.Registers.ESI};
|
||||||
new CPUx86.Push { DestinationReg = CPUx86.Registers.ESI };
|
new CPUx86.Push { DestinationReg = CPUx86.Registers.ESI };
|
||||||
//Assembler.StackSizes.Push(xElementCountSize);
|
//Assembler.StackSizes.Push(xElementCountSize);
|
||||||
new CPUx86.Push { DestinationValue = mElementSize };
|
new CPUx86.Push { Size=32,DestinationValue = mElementSize };
|
||||||
Assembler.StackContents.Push(new StackContent(4, typeof(uint)));
|
Assembler.StackContents.Push(new StackContent(4, typeof(uint)));
|
||||||
Multiply(Assembler);
|
Multiply(Assembler);
|
||||||
// the total items size is now on the stack
|
// 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)));
|
Assembler.StackContents.Push(new StackContent(4, typeof(uint)));
|
||||||
Add(Assembler);
|
Add(Assembler);
|
||||||
// the total array size is now on the stack.
|
// the total array size is now on the stack.
|
||||||
|
|
|
||||||
|
|
@ -233,7 +233,7 @@ namespace Indy.IL2CPU.IL.X86 {
|
||||||
throw new Exception("Remainder size " + (aField.Size) + " not supported!");
|
throw new Exception("Remainder size " + (aField.Size) + " not supported!");
|
||||||
}
|
}
|
||||||
if (aAddGCCode && aField.NeedsGC) {
|
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);
|
Engine.QueueMethod(GCImplementationRefs.IncRefCountRef);
|
||||||
new CPUx86.Call { DestinationLabel = Label.GenerateLabelName(GCImplementationRefs.IncRefCountRef) };
|
new CPUx86.Call { DestinationLabel = Label.GenerateLabelName(GCImplementationRefs.IncRefCountRef) };
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@ namespace Indy.IL2CPU.IL.X86 {
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Push(uint aValue) {
|
public override void Push(uint aValue) {
|
||||||
new CPUx86.Push { DestinationValue = aValue };
|
new CPUx86.Push {Size=32, DestinationValue = aValue };
|
||||||
}
|
}
|
||||||
|
|
||||||
private int xLabelId = 0;
|
private int xLabelId = 0;
|
||||||
|
|
|
||||||
|
|
@ -44,7 +44,7 @@ namespace Indy.IL2CPU.IL.X86 {
|
||||||
foreach (var xLocal in aLocals) {
|
foreach (var xLocal in aLocals) {
|
||||||
aAssembler.StackContents.Push(new StackContent(xLocal.Size, xLocal.VariableType));
|
aAssembler.StackContents.Push(new StackContent(xLocal.Size, xLocal.VariableType));
|
||||||
for (int i = 0; i < (xLocal.Size / 4); i++) {
|
for (int i = 0; i < (xLocal.Size / 4); i++) {
|
||||||
new CPUx86.Push{DestinationValue=0};
|
new CPUx86.Push{Size=32,DestinationValue=0};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(aDebugMode&& aIsNonDebuggable) {
|
if(aDebugMode&& aIsNonDebuggable) {
|
||||||
|
|
|
||||||
|
|
@ -90,11 +90,13 @@
|
||||||
<Compile Include="Assembler\EndIfDefined.cs" />
|
<Compile Include="Assembler\EndIfDefined.cs" />
|
||||||
<Compile Include="Assembler\IfDefined.cs" />
|
<Compile Include="Assembler\IfDefined.cs" />
|
||||||
<Compile Include="Assembler\IfNotDefined.cs" />
|
<Compile Include="Assembler\IfNotDefined.cs" />
|
||||||
|
<Compile Include="Assembler\x86\CosmosAssembler.cs" />
|
||||||
<Compile Include="Assembler\x86\In.cs" />
|
<Compile Include="Assembler\x86\In.cs" />
|
||||||
<Compile Include="Assembler\x86\JumpToSegment.cs" />
|
<Compile Include="Assembler\x86\JumpToSegment.cs" />
|
||||||
<Compile Include="Assembler\x86\MoveIfBelow.cs" />
|
<Compile Include="Assembler\x86\MoveIfBelow.cs" />
|
||||||
<Compile Include="Assembler\x86\MoveIfLess.cs" />
|
<Compile Include="Assembler\x86\MoveIfLess.cs" />
|
||||||
<Compile Include="Assembler\x86\Registers_Old.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\Extensions.cs" />
|
||||||
<Compile Include="Assembler\x86\_Infra\IInstructionWithDestination.cs" />
|
<Compile Include="Assembler\x86\_Infra\IInstructionWithDestination.cs" />
|
||||||
<Compile Include="Assembler\x86\_Infra\IInstructionWithSize.cs" />
|
<Compile Include="Assembler\x86\_Infra\IInstructionWithSize.cs" />
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,8 @@ namespace TestApp {
|
||||||
class Renderer : Y86 {
|
class Renderer : Y86 {
|
||||||
public void DoRender() {
|
public void DoRender() {
|
||||||
Label = "Kernel_Start";
|
Label = "Kernel_Start";
|
||||||
EAX = 0xB8000;
|
EBX = 0xB8000;
|
||||||
|
Memory[EBX, 8] = 65;
|
||||||
//IfDefined("DefinedSymbol");
|
//IfDefined("DefinedSymbol");
|
||||||
//Memory[0xB8002, 8] = 66;
|
//Memory[0xB8002, 8] = 66;
|
||||||
//Memory[0xB8003, 8] = 15;
|
//Memory[0xB8003, 8] = 15;
|
||||||
|
|
@ -26,11 +27,7 @@ namespace TestApp {
|
||||||
}
|
}
|
||||||
static void Main(string[] args) {
|
static void Main(string[] args) {
|
||||||
try {
|
try {
|
||||||
var xAsm = new Assembler(delegate(string aGroup) {
|
var xAsm = new Assembler();
|
||||||
return Path.Combine(Path.Combine(Path.GetDirectoryName(Assembly.GetEntryAssembly().Location),
|
|
||||||
"Output"),
|
|
||||||
aGroup + ".out");
|
|
||||||
});
|
|
||||||
xAsm.Initialize();
|
xAsm.Initialize();
|
||||||
xAsm.DataMembers.Add(new Indy.IL2CPU.Assembler.DataMember("TestData", new byte[]{65, 66, 67, 68,69,70, 71, 72, 73, 74}));
|
xAsm.DataMembers.Add(new Indy.IL2CPU.Assembler.DataMember("TestData", new byte[]{65, 66, 67, 68,69,70, 71, 72, 73, 74}));
|
||||||
xAsm.Instructions.Clear();
|
xAsm.Instructions.Clear();
|
||||||
|
|
@ -42,18 +39,18 @@ namespace TestApp {
|
||||||
Directory.CreateDirectory(Path.Combine(Path.GetDirectoryName(Assembly.GetEntryAssembly().Location),
|
Directory.CreateDirectory(Path.Combine(Path.GetDirectoryName(Assembly.GetEntryAssembly().Location),
|
||||||
"Output"));
|
"Output"));
|
||||||
}
|
}
|
||||||
//using (Stream xOutput = new FileStream(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"), FileMode.Create)) {
|
|
||||||
// xAsm.FlushBinary(xOutput, 0x500000);
|
|
||||||
//}
|
|
||||||
|
|
||||||
using (StreamWriter xOutput = new StreamWriter(Path.Combine(Path.Combine(Path.GetDirectoryName(Assembly.GetEntryAssembly().Location),
|
|
||||||
"Output"),
|
"Output"),
|
||||||
"TheOutput.out"))) {
|
"TheOutput.bin"), FileMode.Create)) {
|
||||||
xAsm.FlushText(xOutput);
|
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
|
// now the file should have been written
|
||||||
} catch (Exception E) { Console.WriteLine(E.ToString()); }
|
} catch (Exception E) { Console.WriteLine(E.ToString()); }
|
||||||
finally {
|
finally {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue