blob: ce39fddba8045971b85bd65725a45c28aa0dec14 (
plain) (
blame)
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
|
using ChocolArm64.State;
using System;
using System.Collections.Generic;
using static ChocolArm64.State.RegisterConsts;
namespace ChocolArm64.IntermediateRepresentation
{
class BasicBlock
{
public int Index { get; set; }
public RegisterMask RegInputs { get; private set; }
public RegisterMask RegOutputs { get; private set; }
public bool HasStateLoad { get; private set; }
private List<Operation> _operations;
public int Count => _operations.Count;
private BasicBlock _next;
private BasicBlock _branch;
public BasicBlock Next
{
get => _next;
set => _next = AddSuccessor(_next, value);
}
public BasicBlock Branch
{
get => _branch;
set => _branch = AddSuccessor(_branch, value);
}
public List<BasicBlock> Predecessors { get; }
public BasicBlock(int index = 0)
{
Index = index;
_operations = new List<Operation>();
Predecessors = new List<BasicBlock>();
}
private BasicBlock AddSuccessor(BasicBlock oldBlock, BasicBlock newBlock)
{
oldBlock?.Predecessors.Remove(this);
newBlock?.Predecessors.Add(this);
return newBlock;
}
public void Add(Operation operation)
{
if (operation.Type == OperationType.LoadLocal ||
operation.Type == OperationType.StoreLocal)
{
int index = operation.GetArg<int>(0);
if (IsRegIndex(index))
{
long intMask = 0;
long vecMask = 0;
switch (operation.GetArg<RegisterType>(1))
{
case RegisterType.Flag: intMask = (1L << RegsCount) << index; break;
case RegisterType.Int: intMask = 1L << index; break;
case RegisterType.Vector: vecMask = 1L << index; break;
}
RegisterMask mask = new RegisterMask(intMask, vecMask);
if (operation.Type == OperationType.LoadLocal)
{
RegInputs |= mask & ~RegOutputs;
}
else
{
RegOutputs |= mask;
}
}
}
else if (operation.Type == OperationType.LoadContext)
{
HasStateLoad = true;
}
operation.Parent = this;
_operations.Add(operation);
}
public static bool IsRegIndex(int index)
{
return (uint)index < RegsCount;
}
public Operation GetOperation(int index)
{
if ((uint)index >= _operations.Count)
{
throw new ArgumentOutOfRangeException(nameof(index));
}
return _operations[index];
}
public Operation GetLastOp()
{
if (Count == 0)
{
return null;
}
return _operations[Count - 1];
}
}
}
|