mirror of
https://github.com/danbulant/Cosmos
synced 2026-05-30 21:00:30 +00:00
212 lines
No EOL
6.4 KiB
C#
212 lines
No EOL
6.4 KiB
C#
using System;
|
|
using System.Linq;
|
|
using Indy.IL2CPU.Assembler;
|
|
using Indy.IL2CPU.Assembler.X86;
|
|
using Mono.Cecil;
|
|
using CPU = Indy.IL2CPU.Assembler.X86;
|
|
using Instruction = Mono.Cecil.Cil.Instruction;
|
|
|
|
namespace Indy.IL2CPU.IL.X86 {
|
|
public abstract class Op: IL.Op {
|
|
public Op(Instruction aInstruction, MethodInformation aMethodInfo)
|
|
: base(aInstruction, aMethodInfo) {
|
|
}
|
|
protected void Call(string aAddress) {
|
|
Assembler.Add(new Assembler.X86.Call(aAddress));
|
|
}
|
|
|
|
protected void Label(string aName) {
|
|
Assembler.Add(new Label(aName));
|
|
}
|
|
|
|
protected void Compare(string aAddress1, string aAddress2) {
|
|
Assembler.Add(new Compare(aAddress1, aAddress2));
|
|
}
|
|
|
|
public static void Move(Assembler.Assembler aAssembler, string aDestination, string aSource) {
|
|
aAssembler.Add(new Move(aDestination, aSource));
|
|
}
|
|
|
|
protected void Test(string aArg1, string aArg2) {
|
|
Assembler.Add(new Test(aArg1, aArg2));
|
|
}
|
|
|
|
protected void JumpIfZero(string aAddress) {
|
|
Assembler.Add(new JumpIfZero(aAddress));
|
|
}
|
|
|
|
protected void JumpIfEquals(string aAddress) {
|
|
Assembler.Add(new JumpIfEquals(aAddress));
|
|
}
|
|
|
|
protected void JumpIfGreater(string aAddress) {
|
|
Assembler.Add(new JumpIfGreater(aAddress));
|
|
}
|
|
|
|
protected void JumpIfNotZero(string aAddress) {
|
|
Assembler.Add(new JumpIfNotEquals(aAddress));
|
|
}
|
|
|
|
protected void JumpAlways(string aAddress) {
|
|
Assembler.Add(new JumpAlways(aAddress));
|
|
}
|
|
|
|
[Obsolete("Try using specialized opcodes")]
|
|
protected void Literal(string aData) {
|
|
Assembler.Add(new Literal(aData));
|
|
}
|
|
|
|
protected void Comment(string aText) {
|
|
Assembler.Add(new Comment(aText));
|
|
}
|
|
|
|
public static void Push(Assembler.Assembler aAssembler, int aSize, params string[] aArguments) {
|
|
aAssembler.Add(new Push(aArguments));
|
|
aAssembler.StackSizes.Push(aSize);
|
|
}
|
|
|
|
protected void Pushd(int aSize, params string[] aArguments) {
|
|
Assembler.Add(new Pushd(aArguments));
|
|
Assembler.StackSizes.Push(aSize);
|
|
}
|
|
|
|
protected void Xor(string aArgument1, string aArgument2) {
|
|
Assembler.Add(new Assembler.X86.Xor(aArgument1, aArgument2));
|
|
}
|
|
|
|
protected void Pop(params string[] aArguments) {
|
|
Assembler.Add(new Assembler.X86.Pop(aArguments));
|
|
}
|
|
|
|
protected void Ret() {
|
|
Assembler.Add(new Assembler.X86.Ret(""));
|
|
}
|
|
|
|
public static void Ldarg(Assembler.Assembler aAssembler, string[] aAddresses, int aSize) {
|
|
foreach (string xAddress in aAddresses) {
|
|
Move(aAssembler, "eax", "[" + xAddress + "]");
|
|
aAssembler.Add(new Push("eax"));
|
|
}
|
|
aAssembler.StackSizes.Push(aSize);
|
|
}
|
|
|
|
public static void Ldflda(Assembler.Assembler aAssembler, string aRelativeAddress) {
|
|
aAssembler.Add(new Popd("eax"));
|
|
aAssembler.Add(new CPU.Add("eax", aRelativeAddress.Trim().Substring(1)));
|
|
aAssembler.Add(new Pushd("eax"));
|
|
aAssembler.StackSizes.Push(4);
|
|
}
|
|
|
|
public static void Multiply(Assembler.Assembler aAssembler) {
|
|
aAssembler.StackSizes.Pop();
|
|
aAssembler.Add(new CPU.Pop("eax"));
|
|
aAssembler.Add(new CPU.Multiply("dword [esp]"));
|
|
aAssembler.Add(new CPU.Add("esp", "4"));
|
|
aAssembler.Add(new Pushd("eax"));
|
|
}
|
|
|
|
public static void Ldfld(Assembler.Assembler aAssembler, TypeInformation.Field aField) {
|
|
aAssembler.StackSizes.Pop();
|
|
aAssembler.Add(new CPU.Pop("ecx"));
|
|
aAssembler.Add(new CPU.Add("ecx", "0x" + (aField.Offset).ToString("X")));
|
|
if (aField.Size >= 4) {
|
|
for (int i = 0; i < (aField.Size / 4); i++) {
|
|
// Pop("eax");
|
|
// Move(Assembler, "dword [" + mDataName + " + 0x" + (i * 4).ToString("X") + "]", "eax");
|
|
aAssembler.Add(new CPU.Move("eax", "[ecx + 0x" + (i * 4).ToString("X") + "]"));
|
|
aAssembler.Add(new CPU.Pushd("eax"));
|
|
}
|
|
switch (aField.Size % 4) {
|
|
case 1: {
|
|
aAssembler.Add(new CPU.Move("eax", "0"));
|
|
aAssembler.Add(new CPU.Move("al", "[ecx + 0x" + (aField.Size - 1).ToString("X") + "]"));
|
|
aAssembler.Add(new CPU.Push("eax"));
|
|
break;
|
|
}
|
|
case 2: {
|
|
aAssembler.Add(new CPU.Move("eax", "0"));
|
|
aAssembler.Add(new CPU.Move("ax", "[ecx + 0x" + (aField.Size - 2).ToString("X") + "]"));
|
|
aAssembler.Add(new CPU.Push("eax"));
|
|
break;
|
|
}
|
|
case 0: {
|
|
break;
|
|
}
|
|
default:
|
|
throw new Exception("Remainder size " + (aField.Size % 4) + " not supported!");
|
|
}
|
|
} else {
|
|
switch (aField.Size) {
|
|
case 1: {
|
|
aAssembler.Add(new CPU.Move("eax", "0"));
|
|
aAssembler.Add(new CPU.Move("al", "[ecx]"));
|
|
aAssembler.Add(new CPU.Push("eax"));
|
|
break;
|
|
}
|
|
case 2: {
|
|
aAssembler.Add(new CPU.Move("eax", "0"));
|
|
aAssembler.Add(new CPU.Move("ax", "[ecx]"));
|
|
aAssembler.Add(new CPU.Push("eax"));
|
|
break;
|
|
}
|
|
case 0: {
|
|
break;
|
|
}
|
|
default:
|
|
throw new Exception("Remainder size " + (aField.Size) + " not supported!");
|
|
}
|
|
}
|
|
aAssembler.StackSizes.Push(aField.Size);
|
|
}
|
|
|
|
public static void Stfld(Assembler.Assembler aAssembler, TypeInformation.Field aField) {
|
|
aAssembler.StackSizes.Pop();
|
|
int xRoundedSize = aField.Size;
|
|
if(xRoundedSize % 4 != 0) {
|
|
xRoundedSize += 4 - (xRoundedSize % 4);
|
|
}
|
|
aAssembler.Add(new CPU.Move("ecx", "[esp + 0x" + xRoundedSize.ToString("X") + "]"));
|
|
aAssembler.Add(new CPU.Add("ecx", "0x" + aField.Offset.ToString("X")));
|
|
for (int i = 1; i <= (aField.Size / 4); i++) {
|
|
aAssembler.Add(new CPU.Pop("eax"));
|
|
Move(aAssembler, "dword [ecx + 0x" + (aField.Size - (i * 4)).ToString("X") + "]", "eax");
|
|
}
|
|
switch (aField.Size % 4) {
|
|
case 1: {
|
|
aAssembler.Add(new CPU.Pop("eax"));
|
|
Move(aAssembler, "byte [ecx]", "al");
|
|
break;
|
|
}
|
|
case 2: {
|
|
aAssembler.Add(new CPU.Pop("eax"));
|
|
Move(aAssembler, "word [ecx]", "ax");
|
|
break;
|
|
}
|
|
case 0: {
|
|
break;
|
|
}
|
|
default:
|
|
throw new Exception("Remainder size " + (aField.Size % 4) + " not supported!");
|
|
|
|
}
|
|
aAssembler.Add(new CPU.Add("esp", "4"));
|
|
aAssembler.StackSizes.Pop();
|
|
}
|
|
|
|
public void Multiply() {
|
|
Multiply(Assembler);
|
|
}
|
|
|
|
public static void Add(Assembler.Assembler aAssembler) {
|
|
aAssembler.StackSizes.Pop();
|
|
aAssembler.Add(new CPU.Pop("eax"));
|
|
aAssembler.Add(new CPU.Add("eax", "[esp]"));
|
|
aAssembler.Add(new CPU.Add("esp", "4"));
|
|
aAssembler.Add(new Pushd("eax"));
|
|
}
|
|
|
|
public void Add() {
|
|
Add(Assembler);
|
|
}
|
|
}
|
|
} |