Cosmos/source/Indy.IL2CPU/Assembler/x86/CosmosAssembler.cs
2008-11-09 12:50:58 +00:00

157 lines
No EOL
8.2 KiB
C#

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);
}
}
}