This commit is contained in:
kudzu_cp 2011-07-13 05:05:35 +00:00
parent beb587aea0
commit 967ca09a2c
2 changed files with 102 additions and 34 deletions

View file

@ -48,6 +48,7 @@ namespace Cosmos.IL2CPU.X86
new Comment(this, "EBX=multiboot_info ");
new Comment(this, "EAX=0x2BADB002 - check if it's really Multiboot loader ");
new Comment(this, " ;- copy mb info - some stuff for you ");
new Comment(this, "BEGIN - Multiboot Info");
//new Move { DestinationReg = Registers.ESI, SourceReg = Registers.EBX };
//new Move { DestinationReg = Registers.EDI, SourceRef = ElementReference.New("MultiBootInfo_Structure") };
//new Move { DestinationReg = Registers.ECX, SourceValue = 0x58 };
@ -56,12 +57,7 @@ namespace Cosmos.IL2CPU.X86
//new Move { DestinationReg = Registers.EBX, SourceRef = ElementReference.New("MultiBootInfo_Structure") };
new Move { DestinationRef = ElementReference.New("MultiBootInfo_Structure"), DestinationIsIndirect = true, SourceReg = Registers.EBX };
new Add { DestinationReg = Registers.EBX, SourceValue = 4 };
new Move
{
DestinationReg = Registers.EAX,
SourceReg = Registers.EBX,
SourceIsIndirect = true
};
new Move { DestinationReg = Registers.EAX, SourceReg = Registers.EBX, SourceIsIndirect = true };
new Move { DestinationRef = ElementReference.New("MultiBootInfo_Memory_Low"), DestinationIsIndirect = true, SourceReg = Registers.EAX };
new Add { DestinationReg = Registers.EBX, SourceValue = 4 };
new Move
@ -76,6 +72,8 @@ namespace Cosmos.IL2CPU.X86
DestinationReg = Registers.ESP,
SourceRef = ElementReference.New("Kernel_Stack")
};
new Comment(this, "END - Multiboot Info");
#if LFB_1024_8
new Comment("Set graphics fields");
new Move { DestinationReg = Registers.EBX, SourceRef = ElementReference.New("MultiBootInfo_Structure"), SourceIsIndirect = true };
@ -86,9 +84,8 @@ namespace Cosmos.IL2CPU.X86
new Move { DestinationReg = Registers.EAX, SourceReg = Registers.EBX, SourceIsIndirect = true, SourceDisplacement = 80 };
new Move { DestinationRef = ElementReference.New("MultibootGraphicsRuntime_VbeMode"), DestinationIsIndirect = true, SourceReg = Registers.EAX };
#endif
new Comment(this, "some more startups todo");
// SSE init
new Comment(this, "BEGIN - 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 };
@ -104,7 +101,7 @@ namespace Cosmos.IL2CPU.X86
new And { DestinationReg = Registers.EAX, SourceValue = 1 };
new Move { DestinationReg = Registers.CR0, SourceReg = Registers.EAX };
// END SSE INIT
new Comment(this, "END - SSE Init");
if (mComNumber > 0)
{
@ -118,7 +115,7 @@ namespace Cosmos.IL2CPU.X86
// Jump to Kernel entry point
new Call { DestinationLabel = EntryPointName };
// After Kernel is done, sit here and halt till next IRQ.
new Comment(this, "Kernel done - loop till next IRQ");
new Label(".loop");
new ClrInterruptFlag();
new Halt();

View file

@ -6,33 +6,104 @@ using CPUx86 = Cosmos.Compiler.Assembler.X86;
using System.Collections.Generic;
namespace Cosmos.Core.Plugs.Assemblers {
public class CreateGDT : AssemblerMethod {
public override void AssembleNew(object aAssembler, object aMethodInfo) {
var xAssembler = (Assembler)aAssembler;
xAssembler.DataMembers.Add(new CPUAll.DataMember("_NATIVE_GDT_Contents"
, new byte[]
{0,0,0,0,0,0,0,0 // Null Segment
, 0xFF, 0xFF, 0, 0, 0, 0x99, 0xCF, 0 // Code Segment
, 0xFF,0xFF,0,0,0,0x93,0xCF,0})); // Data Segment
xAssembler.DataMembers.Add(new CPUAll.DataMember("_NATIVE_GDT_Pointer", new ushort[] { 0x17, 0, 0 }));
public class CreateGDT : AssemblerMethod {
// http://wiki.osdev.org/Global_Descriptor_Table
// http://http://wiki.osdev.org/GDT_Tutorial
// http://www.osdever.net/bkerndev/Docs/gdt.htm
new CPUx86.Move { DestinationReg = CPUx86.Registers.EAX, SourceRef = CPUAll.ElementReference.New("_NATIVE_GDT_Pointer") };
new CPUx86.Move { DestinationRef = CPUAll.ElementReference.New("_NATIVE_GDT_Pointer"), DestinationIsIndirect = true, DestinationDisplacement = 2, SourceRef = CPUAll.ElementReference.New("_NATIVE_GDT_Contents") };
//TODO: Modify this to support the flags and access as individual input rather
// than requiring user to pass pre-calculated numbers.
protected byte[] Descriptor(UInt32 aBase, UInt32 aSize, bool aCode) {
// Limit is a confusing word. Is it the max physical address or size?
// In fact it is the size, and 286 docs actually refer to it as size
// rather than limit.
// It is also size - 1, else there would be no way to specify
// all of RAM, and a limit of 0 is invalid.
new CPUAll.Label(".RegisterGDT");
new CPUx86.Move { DestinationReg = CPUx86.Registers.EAX, SourceRef = CPUAll.ElementReference.New("_NATIVE_GDT_Pointer") };
new CPUx86.Lgdt { DestinationReg = CPUx86.Registers.EAX, DestinationIsIndirect = true };
var xResult = new byte[8];
// Check the limit to make sure that it can be encoded
if ((aSize > 65536) && (aSize & 0x0FFF) != 0x0FFF) {
// If larger than 16 bit, must be an even page (4kb) size
throw new Exception("Invalid size in GDT descriptor.");
}
// Flags nibble
// 7: Granularity
// 0 = bytes
// 1 = 4kb pages
// 6: 1 = 32 bit mode
// 5: 0 - Reserved
// 4: 0 - Reserved
xResult[6] = 0x40;
if (aSize > 65536) {
// Set page sizing instead of byte sizing
aSize = aSize >> 12;
xResult[6] = (byte)(xResult[6] | 0x80);
}
xResult[0] = (byte)(aSize & 0xFF);
xResult[1] = (byte)((aSize >> 8) & 0xFF);
xResult[6] = (byte)(xResult[6] | ((aSize >> 16) & 0x0F));
new CPUx86.Move { DestinationReg = CPUx86.Registers.AX, SourceValue = 0x10 };
new CPUx86.Move { DestinationReg = CPUx86.Registers.DS, SourceReg = CPUx86.Registers.AX };
new CPUx86.Move { DestinationReg = CPUx86.Registers.ES, SourceReg = CPUx86.Registers.AX };
new CPUx86.Move { DestinationReg = CPUx86.Registers.FS, SourceReg = CPUx86.Registers.AX };
new CPUx86.Move { DestinationReg = CPUx86.Registers.GS, SourceReg = CPUx86.Registers.AX };
new CPUx86.Move { DestinationReg = CPUx86.Registers.SS, SourceReg = CPUx86.Registers.AX };
xResult[2] = (byte)(aBase & 0xFF);
xResult[3] = (byte)((aBase >> 8) & 0xFF);
xResult[4] = (byte)((aBase >> 16) & 0xFF);
xResult[7] = (byte)((aBase >> 24) & 0xFF);
// Force reload of code segment
new CPUx86.JumpToSegment { Segment = 8, DestinationLabel = "flush__GDT__table" };
new CPUAll.Label("flush__GDT__table");
}
xResult[5] = (byte)(
// Bit 7: Present, must be 1
0x80 |
// Bit 6-5: Privilege, 0=kernel, 3=user
0x00 |
// Reserved, must be 1
0x10 |
// Bit 3: 1=Code, 0=Data
(aCode ? 0x08 : 0x00) |
// Bit 2: Direction/Conforming
0x00 |
// Bit 1: R/W Data (1=Writeable, 0=Read only) Code (1=Readable, 0=Not readable)
0x02 |
// Bit 0: Accessed - Set to 0. Updated by CPU later.
0x00
);
return xResult;
}
public override void AssembleNew(object aAssembler, object aMethodInfo) {
var xAsm = (Assembler)aAssembler;
var xGDT = new List<byte>();
// Null Segment - Selector 0x00
// Not used, but required by many emulators.
xGDT.AddRange(new byte[8] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 });
// Code Segment
byte xCodeSelector = (byte)xGDT.Count;
xGDT.AddRange(Descriptor(0x00000000, 0xFFFFFFFF, true));
// Data Segment - Selector 0x0B
byte xDataSelector = (byte)xGDT.Count;
xGDT.AddRange(Descriptor(0x00000000, 0xFFFFFFFF, false));
xAsm.DataMembers.Add(new CPUAll.DataMember("_NATIVE_GDT_Contents", xGDT.ToArray()));
xAsm.DataMembers.Add(new CPUAll.DataMember("_NATIVE_GDT_Pointer", new ushort[] { 0x17, 0, 0 }));
new CPUx86.Move { DestinationReg = CPUx86.Registers.EAX, SourceRef = CPUAll.ElementReference.New("_NATIVE_GDT_Pointer") };
new CPUx86.Move { DestinationRef = CPUAll.ElementReference.New("_NATIVE_GDT_Pointer"), DestinationIsIndirect = true, DestinationDisplacement = 2, SourceRef = CPUAll.ElementReference.New("_NATIVE_GDT_Contents") };
new CPUAll.Label(".RegisterGDT");
new CPUx86.Move { DestinationReg = CPUx86.Registers.EAX, SourceRef = CPUAll.ElementReference.New("_NATIVE_GDT_Pointer") };
new CPUx86.Lgdt { DestinationReg = CPUx86.Registers.EAX, DestinationIsIndirect = true };
new CPUx86.Move { DestinationReg = CPUx86.Registers.AX, SourceValue = 0x10 };
new CPUx86.Move { DestinationReg = CPUx86.Registers.DS, SourceReg = CPUx86.Registers.AX };
new CPUx86.Move { DestinationReg = CPUx86.Registers.ES, SourceReg = CPUx86.Registers.AX };
new CPUx86.Move { DestinationReg = CPUx86.Registers.FS, SourceReg = CPUx86.Registers.AX };
new CPUx86.Move { DestinationReg = CPUx86.Registers.GS, SourceReg = CPUx86.Registers.AX };
new CPUx86.Move { DestinationReg = CPUx86.Registers.SS, SourceReg = CPUx86.Registers.AX };
new CPUAll.Comment("Force reload of code segment");
new CPUx86.JumpToSegment { Segment = 0x08, DestinationLabel = "flush__GDT__table" };
new CPUAll.Label("flush__GDT__table");
}
}
}