This commit is contained in:
kudzu_cp 2008-04-27 06:31:13 +00:00
parent f95db75e67
commit 788b6cdb5d
16 changed files with 308 additions and 149 deletions

View file

@ -5,10 +5,115 @@ using System.Linq;
using System.Text;
namespace Indy.IL2CPU.Assembler.X86 {
public class Assembler: Indy.IL2CPU.Assembler.Assembler {
public class Assembler : Indy.IL2CPU.Assembler.Assembler {
protected class Y86 : X.Y86 {
public void DebugStub(TextWriter aOutputWriter, UInt16 aComAddr) {
UInt16 xComStatusAddr = (UInt16)(aComAddr + 5);
Label = "WriteByteToComPort";
Label = "WriteByteToComPort_Wait";
DX = xComStatusAddr;
AL = Port(DX);
AL.Test(0x20);
JumpIfEqual("WriteByteToComPort_Wait");
DX = aComAddr;
new Move(Registers.AL, "[esp + 4]");
new Out(Registers.DX, Registers.AL);
new Ret(4);
new Label("DebugWriteEIP");
new Move(Registers.AL, "[ebp + 3]");
new Push(Registers.EAX);
new Call("WriteByteToComPort");
new Move(Registers.AL, "[ebp + 2]");
new Push(Registers.EAX);
new Call("WriteByteToComPort");
new Move(Registers.AL, "[ebp + 1]");
new Push(Registers.EAX);
new Call("WriteByteToComPort");
new Move(Registers.AL, "[ebp]");
new Push(Registers.EAX);
new Call("WriteByteToComPort");
new Ret();
new Label("DebugPoint_WaitCmd");
DX = xComStatusAddr;
new InByte(Registers.AL, Registers.DX);
new Test(Registers.AL, 1);
new JumpIfZero("DebugPoint_WaitCmd");
new Jump("DebugPoint_ProcessCmd");
new Label("DebugPoint__");
new Pushad();
new Move(Registers.EBP, Registers.ESP);
new Add(Registers.EBP, 32);
// Check TraceMode
new Move(Registers.EAX, "[TraceMode]");
new Compare(Registers.AX, 1);
new JumpIfEqual("DebugPoint_NoTrace");
//
new Call("DebugWriteEIP");
//
new Move(Registers.EAX, "[TraceMode]");
new Compare(Registers.AL, 4);
new JumpIfEqual("DebugPoint_WaitCmd");
new Label("DebugPoint_NoTrace");
// Is there a new incoming command?
new Label("DebugPoint_CheckCmd");
DX = xComStatusAddr;
new InByte(Registers.AL, Registers.DX);
new Test(Registers.AL, 1);
new JumpIfZero("DebugPoint_AfterCmd");
new Label("DebugPoint_ProcessCmd");
DX = aComAddr;
new InByte(Registers.AL, Registers.DX);
new Compare(Registers.AL, 1);
new JumpIfNotEqual("DebugPoint_Cmd02");
new Move("dword", "[TraceMode]", 1);
new Jump("DebugPoint_CheckCmd");
//
new Label("DebugPoint_Cmd02");
new Compare(Registers.AL, 2);
new JumpIfNotEqual("DebugPoint_Cmd03");
new Move("dword", "[TraceMode]", 2);
new Jump("DebugPoint_CheckCmd");
//
new Label("DebugPoint_Cmd03");
new Compare(Registers.AL, 3);
new JumpIfNotEqual("DebugPoint_Cmd04");
new Move("dword", "[TraceMode]", 4);
new Jump("DebugPoint_AfterCmd");
//
new Label("DebugPoint_Cmd04");
new Compare(Registers.AL, 4);
new JumpIfNotEqual("DebugPoint_Cmd05");
new Move("dword", "[TraceMode]", 4);
new Jump("DebugPoint_WaitCmd");
//
new Label("DebugPoint_Cmd05");
// -Evaluate variables
// -Step to next debug call
// Break points
// Immediate break
new Label("DebugPoint_AfterCmd");
// TraceMode
// 1 - No tracing
// 2 - Tracing
// 3 -
// 4 - Break and wait
new Popad();
new Ret();
}
}
public const string BreakMethodName = "_CODE_REQUESTED_BREAK_";
protected byte mComNumber = 0;
protected UInt32[] mComPortAddresses = { 0x3F8, 0x2F8, 0x3E8, 0x2E8 };
protected UInt16[] mComPortAddresses = { 0x3F8, 0x2F8, 0x3E8, 0x2E8 };
public Assembler(Func<string, string> aGetStreamForGroup, bool aInMetalMode, byte aComNumber)
: base(aGetStreamForGroup, aInMetalMode) {
@ -24,7 +129,7 @@ namespace Indy.IL2CPU.Assembler.X86 {
protected override void EmitCodeSectionHeader(string aGroup, TextWriter aOutputWriter) {
base.EmitCodeSectionHeader(aGroup, aOutputWriter);
using (var xAsm = new DumbAssembler()) {
using (var xAsm = new RawAssembler()) {
aOutputWriter.WriteLine("section .text");
if (aGroup == MainGroup) {
aOutputWriter.WriteLine("global Kernel_Start");
@ -48,8 +153,8 @@ namespace Indy.IL2CPU.Assembler.X86 {
aOutputWriter.WriteLine("; some more startups todo");
aOutputWriter.WriteLine(" cli");
//aOutputWriter.WriteLine(" push ebx");
if (mComNumber != null) {
UInt32 xComAddr = mComPortAddresses[mComNumber - 1];
if (mComNumber > 0) {
UInt16 xComAddr = mComPortAddresses[mComNumber - 1];
aOutputWriter.WriteLine("mov dx, 0x{0}", (xComAddr + 1).ToString("X"));
aOutputWriter.WriteLine("mov al, 0x00");
aOutputWriter.WriteLine("out DX, AL"); // disable all interrupts
@ -82,106 +187,8 @@ namespace Indy.IL2CPU.Assembler.X86 {
aOutputWriter.WriteLine(" ret");
aOutputWriter.WriteLine(" ");
if (mComNumber > 0) {
UInt32 xComAddr = mComPortAddresses[mComNumber - 1];
new Label("WriteByteToComPort");
new Label("WriteByteToComPort_Wait");
new Move(Registers.DX, xComAddr + 5);
new InByte(Registers.AL, Registers.DX);
new Test(Registers.AL, 0x20);
new JumpIfEqual("WriteByteToComPort_Wait");
new Move(Registers.DX, xComAddr);
new Move(Registers.EAX, "[esp + 4]");
new Out(Registers.DX, Registers.AL);
new Ret(4);
new Label("DebugWriteEIP");
new Move(Registers.AL, "[ebp + 3]");
new Push(Registers.EAX);
new Call("WriteByteToComPort");
new Move(Registers.AL, "[ebp + 2]");
new Push(Registers.EAX);
new Call("WriteByteToComPort");
new Move(Registers.AL, "[ebp + 1]");
new Push(Registers.EAX);
new Call("WriteByteToComPort");
new Move(Registers.AL, "[ebp]");
new Push(Registers.EAX);
new Call("WriteByteToComPort");
new Ret();
new Label("DebugPoint_WaitCmd");
new Move(Registers.DX, xComAddr + 5);
new InByte(Registers.AL, Registers.DX);
new Test(Registers.AL, 1);
new JumpIfZero("DebugPoint_WaitCmd");
new Jump("DebugPoint_ProcessCmd");
new Label("DebugPoint__");
new Pushad();
new Move(Registers.EBP, Registers.ESP);
new Add(Registers.EBP, 32);
// Check TraceMode
new Move(Registers.EAX, "[TraceMode]");
new Compare(Registers.AX, 1);
new JumpIfEqual("DebugPoint_NoTrace");
//
new Call("DebugWriteEIP");
//
new Move(Registers.EAX, "[TraceMode]");
new Compare(Registers.AL, 4);
new JumpIfEqual("DebugPoint_WaitCmd");
new Label("DebugPoint_NoTrace");
// Is there a new incoming command?
new Label("DebugPoint_CheckCmd");
new Move(Registers.DX, xComAddr + 5);
new InByte(Registers.AL, Registers.DX);
new Test(Registers.AL, 1);
new JumpIfZero("DebugPoint_AfterCmd");
new Label("DebugPoint_ProcessCmd");
new Move(Registers.DX, xComAddr);
new InByte(Registers.AL, Registers.DX);
new Compare(Registers.AL, 1);
new JumpIfNotEqual("DebugPoint_Cmd02");
new Move("dword", "[TraceMode]", 1);
new Jump("DebugPoint_CheckCmd");
//
new Label("DebugPoint_Cmd02");
new Compare(Registers.AL, 2);
new JumpIfNotEqual("DebugPoint_Cmd03");
new Move("dword", "[TraceMode]", 2);
new Jump("DebugPoint_CheckCmd");
//
new Label("DebugPoint_Cmd03");
new Compare(Registers.AL, 3);
new JumpIfNotEqual("DebugPoint_Cmd04");
new Move("dword", "[TraceMode]", 4);
new Jump("DebugPoint_AfterCmd");
//
new Label("DebugPoint_Cmd04");
new Compare(Registers.AL, 4);
new JumpIfNotEqual("DebugPoint_Cmd05");
new Move("dword", "[TraceMode]", 4);
new Jump("DebugPoint_WaitCmd");
//
new Label("DebugPoint_Cmd05");
// -Evaluate variables
// -Step to next debug call
// Break points
// Immediate break
new Label("DebugPoint_AfterCmd");
// TraceMode
// 1 - No tracing
// 2 - Tracing
// 3 -
// 4 - Break and wait
new Popad();
new Ret();
var y = new Y86();
y.DebugStub(aOutputWriter, mComPortAddresses[mComNumber - 1]);
}
}
aOutputWriter.WriteLine(xAsm.GetContents());
@ -263,10 +270,5 @@ namespace Indy.IL2CPU.Assembler.X86 {
aOutputWriter.WriteLine("%endif");
}
protected override void EmitImportMembers(string aGroup, TextWriter aOutputWriter) {
if (ImportMembers.Count > 0) {
throw new Exception("You can't use P/Invoke in OS kernels");
}
}
}
}

View file

@ -123,6 +123,15 @@
<Compile Include="SubWithCarry.cs" />
<Compile Include="Test.cs" />
<Compile Include="Xor.cs" />
<Compile Include="X\PortSource.cs" />
<Compile Include="X\Register.cs" />
<Compile Include="X\Register08.cs" />
<Compile Include="X\Register16.cs" />
<Compile Include="X\Register32.cs" />
<Compile Include="X\RegisterAL.cs" />
<Compile Include="X\RegisterDX.cs" />
<Compile Include="X\RegisterEAX.cs" />
<Compile Include="X\Y86.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Indy.IL2CPU.Assembler\Indy.IL2CPU.Assembler.csproj">

View file

@ -11,12 +11,5 @@ namespace Indy.IL2CPU.Assembler.X86 {
// Yet overriden later if necessary as some instructions have seperate mnemonics on some platforms for simple variations,
// and other platforms have one mnemonic and opcode changes based on params.
}
// If there are params, descendants should override this and return Mnemonic + params
// This is virtual and not abstract so that opcodes like Noop dont need to override it
// since they do not have any params.
public virtual void EmitParams(BinaryWriter aWriter) {
}
}
}

View file

@ -0,0 +1,19 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Indy.IL2CPU.Assembler.X86.X {
public class PortSource {
string mPort;
public PortSource(string aPort) {
mPort = aPort;
}
public override string ToString() {
return mPort;
}
}
}

View file

@ -0,0 +1,18 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using X86 = Indy.IL2CPU.Assembler.X86;
namespace Indy.IL2CPU.Assembler.X86.X {
public abstract class Register {
// Not abstract so 8,16,32 dont have to override it
protected virtual string GetName() {
throw new NotImplementedException();
}
protected void Move(string aValue) {
new X86.Move(GetName(), aValue);
}
}
}

View file

@ -0,0 +1,13 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using X86 = Indy.IL2CPU.Assembler.X86;
namespace Indy.IL2CPU.Assembler.X86.X {
public class Register08 : Register {
public void Test(byte aValue) {
new X86.Test(GetName(), aValue);
}
}
}

View file

@ -0,0 +1,9 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Indy.IL2CPU.Assembler.X86.X {
public class Register16 : Register {
}
}

View file

@ -0,0 +1,9 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Indy.IL2CPU.Assembler.X86.X {
public class Register32 : Register {
}
}

View file

@ -0,0 +1,26 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using X86 = Indy.IL2CPU.Assembler.X86;
namespace Indy.IL2CPU.Assembler.X86.X {
public class RegisterAL : Register08 {
public static readonly RegisterAL Instance = new RegisterAL();
protected override string GetName() {
return "AL";
}
public static implicit operator RegisterAL(byte aValue) {
Instance.Move(aValue.ToString());
return Instance;
}
public static implicit operator RegisterAL(PortSource aValue) {
new X86.InByte(Instance.GetName(), aValue.ToString());
return Instance;
}
}
}

View file

@ -0,0 +1,19 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Indy.IL2CPU.Assembler.X86.X {
public class RegisterDX : Register16 {
public static readonly RegisterDX Instance = new RegisterDX();
protected override string GetName() {
return "DX";
}
public static implicit operator RegisterDX(UInt16 aValue) {
Instance.Move(aValue.ToString());
return Instance;
}
}
}

View file

@ -0,0 +1,19 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Indy.IL2CPU.Assembler.X86.X {
public class RegisterEAX : Register32 {
public static readonly RegisterEAX Instance = new RegisterEAX();
protected override string GetName() {
return "EAX";
}
public static implicit operator RegisterEAX(UInt32 aValue) {
Instance.Move(aValue.ToString());
return Instance;
}
}
}

View file

@ -0,0 +1,29 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using X86 = Indy.IL2CPU.Assembler.X86;
namespace Indy.IL2CPU.Assembler.X86.X {
public class Y86 {
public RegisterEAX EAX = RegisterEAX.Instance;
public RegisterAL AL = RegisterAL.Instance;
public RegisterDX DX = RegisterDX.Instance;
public PortSource Port(RegisterDX aDX) {
return new PortSource("DX");
}
public string Label {
set {
new Indy.IL2CPU.Assembler.Label(value);
}
}
public void JumpIfEqual(string aLabel) {
new X86.JumpIfEqual(aLabel);
}
}
}

View file

@ -201,7 +201,6 @@ namespace Indy.IL2CPU.Assembler {
}
if (mImportMembers.Count > 0) {
EmitIDataSectionHeader(xGroup, xOutputWriter);
EmitImportMembers(xGroup, xOutputWriter);
EmitIDataSectionFooter(xGroup, xOutputWriter);
}
EmitFooter(xGroup, xOutputWriter);
@ -245,8 +244,6 @@ namespace Indy.IL2CPU.Assembler {
protected virtual void EmitIncludes(string aGroup, TextWriter aOutputWriter) {
}
protected abstract void EmitImportMembers(string aGroup, TextWriter aOutputWriter);
protected virtual void EmitIDataSectionHeader(string aGroup, TextWriter aOutputWriter) {
}

View file

@ -1,28 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
namespace Indy.IL2CPU.Assembler {
public class DumbAssembler: Assembler {
public DumbAssembler() : base(null, false) {
}
public string GetContents() {
using (StringWriter sw = new StringWriter()) {
var xLabels = new List<string>();
foreach (var xGroup in (from item in Instructions
select item.Key).Distinct()) {
EmitCodeSection(xGroup, sw, xLabels);
}
return sw.ToString();
}
}
protected override void EmitHeader(string aGroup, TextWriter aOutputWriter) {
}
protected override void EmitImportMembers(string aGroup, TextWriter aOutputWriter) {
}
}
}

View file

@ -54,7 +54,7 @@
<Compile Include="Assembler.cs" />
<Compile Include="Comment.cs" />
<Compile Include="DataMember.cs" />
<Compile Include="DumbAssembler.cs" />
<Compile Include="RawAssembler.cs" />
<Compile Include="ImportMember.cs" />
<Compile Include="ImportMethodMember.cs" />
<Compile Include="Instruction.cs" />

View file

@ -0,0 +1,25 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
namespace Indy.IL2CPU.Assembler {
public class RawAssembler : Assembler {
public RawAssembler() : base(null, false) { }
public string GetContents() {
using (var sw = new StringWriter()) {
var xLabels = new List<string>();
foreach (var xGroup in
(from item in Instructions select item.Key).Distinct()) {
EmitCodeSection(xGroup, sw, xLabels);
}
return sw.ToString();
}
}
protected override void EmitHeader(string aGroup, TextWriter aOutputWriter) { }
}
}