Cosmos/source/Tests/MathTest/Lost/LostTest.cs
2008-04-11 15:51:46 +00:00

274 lines
7.7 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Lost.JIT.AMD64;
using System.IO;
using System.Diagnostics;
//using Cosmos.Build.Windows;
namespace Lost
{
class LostTest
{
[STAThread]
static void Main(string[] args)
{
//using (var source = new StreamReader(args[0]))
//{
// string srcLine;
// while ((srcLine = source.ReadLine()) != null)
// {
// var op = ProcessorInstruction.Parse(srcLine);
// Console.WriteLine(op);
// }
//}
CompilationTest();
if (File.Exists(tempFile)) File.Delete(tempFile);
Console.ReadKey();
}
static string RunFasm(string filename, string dest)
{
//C:\Programs\Devel\asm\fasmw16726\
const string fasm = @"fasm.exe";
var par = new ProcessStartInfo(fasm, string.Format("\"{0}\" \"{1}\"", filename, dest));
par.CreateNoWindow = true;
par.RedirectStandardOutput = true;
par.RedirectStandardError = true;
par.UseShellExecute = false;
string result;
using (var process = Process.Start(par))
using(var output = process.StandardOutput)
using(var errorStream =process.StandardError)
{
result = output.ReadToEnd();
var error = errorStream.ReadToEnd().Trim();
process.WaitForExit();
if (!string.IsNullOrEmpty(error))
throw new InvalidProgramException(error);
}
return result;
}
static readonly string tempFile = Path.GetTempFileName();
static void CompilationTest()
{
#region ALU
#region ADC
Test("adc al, 1", new AddWithCarry(GeneralPurposeRegister.AL, (byte)1));
Test("adc rcx, 1", new AddWithCarry(GeneralPurposeRegister.RCX, (byte)1));
Test("adc rcx, 0xFFF", new AddWithCarry(GeneralPurposeRegister.RCX, 0xFFF));
Test("adc [rip + 1], rax",
new AddWithCarry(new MemoryOperand()
{
RipBased = true,
Displacement = 1,
}, GeneralPurposeRegister.RAX));
Test("adc [rax], rax", new AddWithCarry(new MemoryOperand() {
Base = GeneralPurposeRegister.RAX,
}, GeneralPurposeRegister.RAX));
Test("adc [rax + 3], r11",
new AddWithCarry(new MemoryOperand() {
Displacement = 3,
Base = GeneralPurposeRegister.RAX,
}, GeneralPurposeRegister.R11));
Test("adc [rsp + 0xFFF], eax",
new AddWithCarry(new MemoryOperand() {
Displacement = 0xFFF,
Base = GeneralPurposeRegister.RSP,
}, GeneralPurposeRegister.EAX));
Test("adc al, [rax*2 + r11]",
new AddWithCarry(GeneralPurposeRegister.AL,
new MemoryOperand() {
Base = GeneralPurposeRegister.R11,
Index = GeneralPurposeRegister.RAX,
Scale = 2,
}));
Test(new AddWithCarry(GeneralPurposeRegister.RAX, GeneralPurposeRegister.RBP));
Test(new AddWithCarry(GeneralPurposeRegister.RBP, GeneralPurposeRegister.RSP));
#endregion
#region AND
Test("and al, 1", new And(GeneralPurposeRegister.AL, (byte)1));
Test("and rcx, 1", new And(GeneralPurposeRegister.RCX, (byte)1));
Test("and rcx, 0xFFF", new And(GeneralPurposeRegister.RCX, 0xFFF));
Test("and [rip + 1], rax",
new And(new MemoryOperand() {
RipBased = true,
Displacement = 1,
}, GeneralPurposeRegister.RAX));
Test("and [rax], rax", new And(new MemoryOperand() {
Base = GeneralPurposeRegister.RAX,
}, GeneralPurposeRegister.RAX));
Test("and [rax + 3], r11",
new And(new MemoryOperand() {
Displacement = 3,
Base = GeneralPurposeRegister.RAX,
}, GeneralPurposeRegister.R11));
Test("and [rsp + 0xFFF], eax",
new And(new MemoryOperand() {
Displacement = 0xFFF,
Base = GeneralPurposeRegister.RSP,
}, GeneralPurposeRegister.EAX));
Test("and al, [rax*2 + r11]",
new And(GeneralPurposeRegister.AL,
new MemoryOperand() {
Base = GeneralPurposeRegister.R11,
Index = GeneralPurposeRegister.RAX,
Scale = 2,
}));
#endregion
#region CMP
Test(new Compare(GeneralPurposeRegister.AL, (byte)1));
Test(new Compare(GeneralPurposeRegister.RCX, (byte)1));
Test(new Compare(GeneralPurposeRegister.R10, 0xFFF));
Test(new Compare(new MemoryOperand(){
Base = GeneralPurposeRegister.RAX,
Index = GeneralPurposeRegister.RAX,
Scale = 8,
}, GeneralPurposeRegister.R12));
#endregion
#endregion
#region Stack
#region POP
Test("pop rax", new Pop(GeneralPurposeRegister.RAX));
Test("pop r12", new Pop(GeneralPurposeRegister.R12));
Test("pop qword [rax]", new Pop(new MemoryOperand() {
Base = GeneralPurposeRegister.RAX,
}));
Test("pop qword [rip + 1]", new Pop(new MemoryOperand() {
Displacement = 1,
RipBased = true,
}));
Test("pop qword [rax*2 + r11]",
new Pop(
new MemoryOperand() {
Base = GeneralPurposeRegister.R11,
Index = GeneralPurposeRegister.RAX,
Scale = 2,
}));
Test("pop qword [rsp + 0xFFF]",
new Pop(
new MemoryOperand() {
Displacement = 0xFFF,
Base = GeneralPurposeRegister.RSP,
}));
Test("pop qword [r12*8 + r11]",
new Pop(
new MemoryOperand() {
Base = GeneralPurposeRegister.R11,
Index = GeneralPurposeRegister.R12,
Scale = 8,
}));
#endregion
#region PUSH
Test("push 1", new Push(1));
Test("push qword [r12*8 + r11]",
new Push(
new MemoryOperand() {
Base = GeneralPurposeRegister.R11,
Index = GeneralPurposeRegister.R12,
Scale = 8,
}));
#endregion
#endregion
#region Control Transfers
#region Unconditional Jumps
Test("jmp 7", new Jump(5));
Test("jmp 0xFFF", new Jump(0xFFA));
Test("call rax", new Call(GeneralPurposeRegister.RAX));
Test("call qword [r12*8 + r11]", new Call(new MemoryOperand() {
Base = GeneralPurposeRegister.R11,
Index = GeneralPurposeRegister.R12,
Scale = 8,
}));
Test(new Return());
Test(new Return(64));
#endregion
#region Conditional Jumps
Test("je 7", new JumpIfEqual(5));
Test("je 0x1005", new JumpIfEqual(0xFFF));
#warning FASM's immediates in Jumps are counted from current instruction IP
#endregion
#endregion
#region MOV
Test(new Move(GeneralPurposeRegister.R10, GeneralPurposeRegister.RSI));
Test(new Move(GeneralPurposeRegister.R10, new MemoryOperand() {
Base = GeneralPurposeRegister.RAX,
Index = GeneralPurposeRegister.RBP,
Scale = 4,
}));
//Test(new Move(new MemoryOperand() {
// Base = GeneralPurposeRegister.R11,
// Index = GeneralPurposeRegister.RSP,
// Scale = 2,
//}, GeneralPurposeRegister.R11));
//Invalid Address
#endregion MOV
}
static void Test(ProcessorInstruction my_code)
{
Test(null, my_code);
}
static void Test(
string xxx,
ProcessorInstruction my_code)
{
string fasm_code = my_code.ToFASM();
using (var writer = new StreamWriter(tempFile))
{
writer.WriteLine("use64");
writer.WriteLine(fasm_code);
writer.Close();
}
var asm_out = RunFasm(tempFile, "fasm.out");
byte[] fasm_out;
using (var stream = new FileStream("fasm.out", FileMode.Open, FileAccess.Read, FileShare.Read))
{
fasm_out = new byte[stream.Length];
stream.Read(fasm_out, 0, fasm_out.Length);
}
byte[] my_out;
using (var stream = new MemoryStream())
{
my_code.Compile(stream);
my_out = stream.ToArray();
}
if (fasm_out.Length != my_out.Length) throw new InvalidProgramException();
for (int i = 0; i < fasm_out.Length; i++)
if (fasm_out[i] != my_out[i]) throw new InvalidProgramException(i.ToString());
Console.WriteLine("{0}: passed", fasm_code);
}
}
}