mirror of
https://github.com/danbulant/Cosmos
synced 2026-05-27 22:12:25 +00:00
[-] some unnecessary overloads [+] overloaded operators in order to allow defining memory operands easily [+] overloaded automatic conversions to allow operands [+] Labels support [+] code generator based on F# started
153 lines
4 KiB
C#
153 lines
4 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using System.IO;
|
|
|
|
namespace Lost.JIT.AMD64
|
|
{
|
|
[Serializable]
|
|
public class Move: ProcessorInstruction
|
|
{
|
|
public Move(InstructionOperand dest, InstructionOperand source)
|
|
{
|
|
Dest = dest;
|
|
Source = source;
|
|
}
|
|
|
|
public InstructionOperand Dest { get; set; }
|
|
public InstructionOperand Source { get; set; }
|
|
|
|
public override int? Size
|
|
{
|
|
get { throw new NotImplementedException(); }
|
|
}
|
|
|
|
public override string ToFASM()
|
|
{
|
|
if ((Dest is GeneralPurposeRegister || Dest is MemoryOperand)
|
|
&& (Source is GeneralPurposeRegister || Source is MemoryOperand || Source is ImmediateOperand)
|
|
) return string.Format("mov {0}, {1}", Dest, Source);
|
|
throw new NotImplementedException();
|
|
}
|
|
|
|
public override string OpCodeFASM
|
|
{
|
|
get { return "mov"; }
|
|
}
|
|
|
|
public override void Compile(Stream destStream)
|
|
{
|
|
GeneralPurposeRegister reg;
|
|
Rex rex = Rex.None;
|
|
|
|
#region Source is Immediate
|
|
if (Source is ImmediateOperand)
|
|
{
|
|
var source = Source as ImmediateOperand;
|
|
if (Dest is GeneralPurposeRegister)
|
|
{
|
|
reg = Dest as GeneralPurposeRegister;
|
|
int opcode = 0xB0;
|
|
opcode += reg.Register.GetIndex();
|
|
if (reg.Register.IsNew()) rex |= Rex.Reg;
|
|
switch (reg.Size)
|
|
{
|
|
case 1:
|
|
if (rex != Rex.None) destStream.WriteRex(rex);
|
|
destStream.WriteByte(opcode);
|
|
destStream.WriteByte(source.Value);
|
|
return;
|
|
case 2:
|
|
destStream.WriteByte(OperandSizeOverride);
|
|
if (rex != Rex.None) destStream.WriteRex(rex);
|
|
destStream.WriteByte(opcode + 8);
|
|
destStream.WriteShort(source.Value);
|
|
return;
|
|
case 4:
|
|
if (rex != Rex.None) destStream.WriteRex(rex);
|
|
destStream.WriteByte(opcode + 8);
|
|
destStream.WriteInt(source.Value);
|
|
return;
|
|
case 8:
|
|
rex |= Rex.Wide;
|
|
if (rex != Rex.None) destStream.WriteRex(rex);
|
|
destStream.WriteByte(opcode + 8);
|
|
destStream.WriteLong(source.Value);
|
|
return;
|
|
default:
|
|
throw new NotSupportedException();
|
|
}
|
|
}
|
|
|
|
if (Dest is MemoryOperand)
|
|
{
|
|
var mem = Dest as MemoryOperand;
|
|
throw new NotImplementedException();
|
|
}
|
|
}
|
|
#endregion Source is Immediate
|
|
|
|
int opcode_base = 0x88;
|
|
#region MOV reg, reg
|
|
if (Dest is GeneralPurposeRegister && Source is GeneralPurposeRegister)
|
|
{
|
|
var dest = Dest as GeneralPurposeRegister;
|
|
var source = Source as GeneralPurposeRegister;
|
|
if (dest.Size != source.Size) throw new NotSupportedException();
|
|
if (dest.Register.IsNew()) rex |= Rex.NewRegRM;
|
|
if (source.Register.IsNew()) rex |= Rex.Reg;
|
|
switch (dest.Size)
|
|
{
|
|
case 1:
|
|
break;
|
|
case 2:
|
|
destStream.WriteByte(OperandSizeOverride);
|
|
goto case 4;
|
|
case 4:
|
|
opcode_base++;
|
|
break;
|
|
case 8:
|
|
rex |= Rex.Wide;
|
|
goto case 4;
|
|
default:
|
|
throw new NotSupportedException();
|
|
}
|
|
if (rex != Rex.None) destStream.WriteRex(rex);
|
|
destStream.WriteByte(opcode_base);
|
|
WriteOperands(source.Register, dest.Register, destStream);
|
|
return;
|
|
}
|
|
#endregion MOV reg, reg
|
|
|
|
#region MOV reg/mem, reg (MOV reg, reg/mem)
|
|
var memory = Dest is GeneralPurposeRegister ? Source as MemoryOperand : Dest as MemoryOperand;
|
|
reg = Dest is GeneralPurposeRegister ? Dest as GeneralPurposeRegister : Source as GeneralPurposeRegister;
|
|
if (Dest is GeneralPurposeRegister) opcode_base += 2;
|
|
rex = NeedsRex(memory);
|
|
if (reg.Register.IsNew()) rex |= Rex.Reg;
|
|
|
|
switch (reg.Size)
|
|
{
|
|
case 1:
|
|
break;
|
|
case 2:
|
|
destStream.WriteByte(OperandSizeOverride);
|
|
goto case 4;
|
|
case 4:
|
|
opcode_base++;
|
|
break;
|
|
case 8:
|
|
rex |= Rex.Wide;
|
|
goto case 4;
|
|
default:
|
|
throw new NotSupportedException();
|
|
}
|
|
|
|
if (rex != Rex.None) destStream.WriteRex(rex);
|
|
destStream.WriteByte(opcode_base);
|
|
WriteOperands(reg, memory, destStream);
|
|
#endregion
|
|
}
|
|
}
|
|
}
|