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
142
143
144
145
146
|
using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
namespace ARMeilleure.IntermediateRepresentation
{
class Operand
{
public OperandKind Kind { get; private set; }
public OperandType Type { get; private set; }
public ulong Value { get; private set; }
public bool Relocatable { get; private set; }
public int? PtcIndex { get; private set; }
public List<Node> Assignments { get; }
public List<Node> Uses { get; }
public Operand()
{
Assignments = new List<Node>();
Uses = new List<Node>();
}
public Operand(OperandKind kind, OperandType type = OperandType.None) : this()
{
Kind = kind;
Type = type;
}
public Operand With(
OperandKind kind,
OperandType type = OperandType.None,
ulong value = 0,
bool relocatable = false,
int? index = null)
{
Kind = kind;
Type = type;
Value = value;
Relocatable = relocatable;
PtcIndex = index;
Assignments.Clear();
Uses.Clear();
return this;
}
public Operand With(int value)
{
return With(OperandKind.Constant, OperandType.I32, (uint)value);
}
public Operand With(uint value)
{
return With(OperandKind.Constant, OperandType.I32, value);
}
public Operand With(long value, bool relocatable = false, int? index = null)
{
return With(OperandKind.Constant, OperandType.I64, (ulong)value, relocatable, index);
}
public Operand With(ulong value)
{
return With(OperandKind.Constant, OperandType.I64, value);
}
public Operand With(float value)
{
return With(OperandKind.Constant, OperandType.FP32, (ulong)BitConverter.SingleToInt32Bits(value));
}
public Operand With(double value)
{
return With(OperandKind.Constant, OperandType.FP64, (ulong)BitConverter.DoubleToInt64Bits(value));
}
public Operand With(int index, RegisterType regType, OperandType type)
{
return With(OperandKind.Register, type, (ulong)((int)regType << 24 | index));
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Register GetRegister()
{
return new Register((int)Value & 0xffffff, (RegisterType)(Value >> 24));
}
public byte AsByte()
{
return (byte)Value;
}
public short AsInt16()
{
return (short)Value;
}
public int AsInt32()
{
return (int)Value;
}
public long AsInt64()
{
return (long)Value;
}
public float AsFloat()
{
return BitConverter.Int32BitsToSingle((int)Value);
}
public double AsDouble()
{
return BitConverter.Int64BitsToDouble((long)Value);
}
internal void NumberLocal(int number)
{
if (Kind != OperandKind.LocalVariable)
{
throw new InvalidOperationException("The operand is not a local variable.");
}
Value = (ulong)number;
}
public override int GetHashCode()
{
if (Kind == OperandKind.LocalVariable)
{
return base.GetHashCode();
}
else
{
return (int)Value ^ ((int)Kind << 16) ^ ((int)Type << 20);
}
}
}
}
|