/
Assignments.cs
141 lines (126 loc) · 7.45 KB
/
Assignments.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
using Spruce.Attribs;
using Spruce.Tokens;
using XSharp.Tokens;
using XSharp.x86;
using XSharp.x86.Params;
using Reg = XSharp.Tokens.Reg;
using Reg08 = XSharp.Tokens.Reg08;
using Reg16 = XSharp.Tokens.Reg16;
using Reg32 = XSharp.Tokens.Reg32;
namespace XSharp.Emitters
{
/// <summary>
/// The class that provides assignments for different types.
/// </summary>
/// <seealso cref="XSharp.Emitters.Emitters" />
public class Assignments : Emitters
{
public Assignments(Compiler aCompiler, x86.Assemblers.Assembler aAsm) : base(aCompiler, aAsm)
{
}
// EAX = [EBX]
[Emitter(typeof(Reg), typeof(OpEquals), typeof(OpOpenBracket), typeof(Reg), typeof(OpCloseBracket))]
protected void MemoryAssignToReg(Register aRegister, string aOpEquals, string aOpOpenBracket, Register aSourceRegister, string aOpCloseBracket)
{
Asm.Emit(OpCode.Mov, aRegister, aRegister.RegSize, new Address(aSourceRegister));
}
[Emitter(typeof(Reg08), typeof(OpEquals), typeof(Reg08))] // AH = BH
[Emitter(typeof(Reg16), typeof(OpEquals), typeof(Reg16))] // AX = BX
[Emitter(typeof(Reg32), typeof(OpEquals), typeof(Reg32))] // EAX = EBX
protected void RegAssigReg(Register aDestReg, string aEquals, Register aSrcReg)
{
Asm.Emit(OpCode.Mov, aDestReg, aSrcReg);
}
// [EAX] = EAX
[Emitter(typeof(OpOpenBracket), typeof(Reg), typeof(OpCloseBracket), typeof(OpEquals), typeof(Reg))]
protected void RegAssignToMemory(string aOpOpenBracket, Register aTargetRegisterRoot, string aOpCloseBracket, string aOpEquals, Register source)
{
Asm.Emit(OpCode.Mov, source.RegSize, new Address(aTargetRegisterRoot), source);
}
// [EAX] = .varname
[Emitter(typeof(OpOpenBracket), typeof(Reg), typeof(OpCloseBracket), typeof(OpEquals), typeof(Variable))]
protected void VariableAssignToMemory(string aOpOpenBracket, Register aTargetRegisterRoot, string aOpCloseBracket, string aOpEquals, Address source)
{
Asm.Emit(OpCode.Mov, "dword", new Address(aTargetRegisterRoot), source.AddPrefix(Compiler.GetPrefixForVar));
}
// [EAX] = 0x10
[Emitter(typeof(OpOpenBracket), typeof(Reg), typeof(OpCloseBracket), typeof(OpEquals), typeof(Int32u))]
protected void IntegerAssignToMemory(string aOpOpenBracket, Register aTargetRegisterRoot, string aOpCloseBracket, string aOpEquals, object source)
{
Asm.Emit(OpCode.Mov, "dword", new Address(aTargetRegisterRoot), source);
}
// Don't use Reg. This method ensures proper data sizes.
// This could be combined with RegAssignReg by using object type for last arg, but this is a bit cleaner to separate.
[Emitter(typeof(Reg08), typeof(OpEquals), typeof(Int08u))] // AH = 0
[Emitter(typeof(Reg16), typeof(OpEquals), typeof(Int16u))] // AX = 0
[Emitter(typeof(Reg32), typeof(OpEquals), typeof(Int32u))] // EAX = 0
protected void RegAssigNum(Register aDestReg, string aEquals, object aVal)
{
Asm.Emit(OpCode.Mov, aDestReg, aVal);
}
// AX = #Test
[Emitter(typeof(Reg), typeof(OpEquals), typeof(Const))]
protected void RegAssigConst(Register aReg, string aEquals, string aVal)
{
Asm.Emit(OpCode.Mov, aReg, $"{Compiler.GetPrefixForConst}{aVal}");
}
// EAX = .Varname
[Emitter(typeof(Reg), typeof(OpEquals), typeof(Variable))]
protected void RegAssigVar(Register aReg, string aEquals, Address aVal)
{
Asm.Emit(OpCode.Mov, aReg, aReg.RegSize, aVal.AddPrefix(Compiler.GetPrefixForVar));
}
// AL = @.varname
[Emitter(typeof(Reg), typeof(OpEquals), typeof(VariableAddress))]
protected void RegAssignVarAddr(Register aReg, string aEquals, string aVal)
{
Asm.Emit(OpCode.Mov, aReg, $"{Compiler.GetPrefixForVar}{aVal}");
}
// ESI = [EBP-1] => mov ESI, dword [EBP - 1]
[Emitter(typeof(Reg), typeof(OpEquals), typeof(OpOpenBracket), typeof(Reg08), typeof(OpPlus), typeof(Int08u), typeof(OpCloseBracket))]
[Emitter(typeof(Reg), typeof(OpEquals), typeof(OpOpenBracket), typeof(Reg16), typeof(OpPlus), typeof(Int16u), typeof(OpCloseBracket))]
[Emitter(typeof(Reg), typeof(OpEquals), typeof(OpOpenBracket), typeof(Reg32), typeof(OpPlus), typeof(Int32u), typeof(OpCloseBracket))]
[Emitter(typeof(Reg), typeof(OpEquals), typeof(OpOpenBracket), typeof(Reg08), typeof(OpMinus), typeof(Int08u), typeof(OpCloseBracket))]
[Emitter(typeof(Reg), typeof(OpEquals), typeof(OpOpenBracket), typeof(Reg16), typeof(OpMinus), typeof(Int16u), typeof(OpCloseBracket))]
[Emitter(typeof(Reg), typeof(OpEquals), typeof(OpOpenBracket), typeof(Reg32), typeof(OpMinus), typeof(Int32u), typeof(OpCloseBracket))]
protected void MemoryAssignToReg(Register aDestReg, string aOpEquals, string aOpOpen, Register aSrc, string aOp, object aOffset, string aOpClose)
{
Asm.Emit(OpCode.Mov, aDestReg, aDestReg.RegSize, new Address(aSrc, aOffset, aOp == "-"));
}
// [AX + 12] = EAX => mov dword [AX + 12], EAX
[Emitter(typeof(OpOpenBracket), typeof(Reg08), typeof(OpPlus), typeof(Int08u), typeof(OpCloseBracket), typeof(OpEquals), typeof(Reg))]
[Emitter(typeof(OpOpenBracket), typeof(Reg16), typeof(OpPlus), typeof(Int16u), typeof(OpCloseBracket), typeof(OpEquals), typeof(Reg))]
[Emitter(typeof(OpOpenBracket), typeof(Reg32), typeof(OpPlus), typeof(Int32u), typeof(OpCloseBracket), typeof(OpEquals), typeof(Reg))]
[Emitter(typeof(OpOpenBracket), typeof(Reg08), typeof(OpMinus), typeof(Int08u), typeof(OpCloseBracket), typeof(OpEquals), typeof(Reg))]
[Emitter(typeof(OpOpenBracket), typeof(Reg16), typeof(OpMinus), typeof(Int16u), typeof(OpCloseBracket), typeof(OpEquals), typeof(Reg))]
[Emitter(typeof(OpOpenBracket), typeof(Reg32), typeof(OpMinus), typeof(Int32u), typeof(OpCloseBracket), typeof(OpEquals), typeof(Reg))]
protected void RegAssignToMemory(string aOpOpenBracket, Register aTargetRegisterRoot, string aOpOperator, object aOffset, string aOpCloseBracket, string aOpEquals, Register source)
{
Asm.Emit(OpCode.Mov, source.RegSize, new Address(aTargetRegisterRoot, aOffset, aOpOperator == "-"), source);
}
// .v1 = 1 => mov dword [v1], 0x1
[Emitter(typeof(Variable), typeof(OpEquals), typeof(Int32u))]
[Emitter(typeof(Variable), typeof(OpEquals), typeof(Reg))]
[Emitter(typeof(Variable), typeof(OpEquals), typeof(Const))]
protected void VariableAssignment(Address aVariableName, string aOpEquals, object aValue)
{
string size;
switch (aValue)
{
case uint _:
size = "dword";
Asm.Emit(OpCode.Mov, size, aVariableName.AddPrefix(Compiler.GetPrefixForVar), aValue);
break;
case Register aValueReg:
size = aValueReg.RegSize;
Asm.Emit(OpCode.Mov, size, aVariableName.AddPrefix(Compiler.GetPrefixForVar), aValue);
break;
case string _:
//TODO: verify this
aValue = $"{Compiler.GetPrefixForConst}{aValue}";
Asm.Emit(OpCode.Mov, aVariableName.AddPrefix(Compiler.GetPrefixForVar), aValue);
break;
}
}
}
}